赞
踩
公司有个需求,将一个微网站链接,网页,外部网站在微信中打开,然后分享给其他人,但是在分享过程中发现分享完微信中显示的是这样子,
标题有了,但是简介显示网址,图片没有,而我想要的是上面另一种样式。标题,简介和图片都可自定义的。由此产生了这篇文章。
2.必须要有已备案的域名和服务器。实现这个功能需要调用后台接口,而且接口的域名和分享网站,网页的域名是一样的。
这里要注意:在二次分享时候如果分享地址是http的话安卓手机正常,苹果手机不正常,如果是用https的话苹果手机也正常了。
上面准备工作做完以后开始实现。
- wx.config({
- debug: true, // 开启调试模式,调用的所有api的返回值会在客户端alert出来,若要查看传入的参数,可以在pc端打开,参数信息会通过log打出,仅在pc端时才会打印。
- appId: '', // 必填,公众号的唯一标识
- timestamp: , // 必填,生成签名的时间戳
- nonceStr: '', // 必填,生成签名的随机串
- signature: '',// 必填,签名
- jsApiList: [] // 必填,需要使用的JS接口列表
- });
获取签名实际是需要四步
1. 根据appId和appsecret获取access_token;
2. 使用access_token获取jsapi_ticket;
3. 使用时间戳,随机数,jsapi_ticket和要访问的url按照签名算法拼接字符串;
4. 对第三步的字符串进行SHA1加密,得到签名;
这步是在服务器后台写的一个工具类里面实现的,测试时候可以先后台获取,前台页面将参数写死,实际用的时候最好动态获取这些数据。如果参数写死的话会二次分享会出问题,在微信中第二次分享,微信会自己加一个参数上去,这样点开在分享的时候签名和url会匹配不上。
第一步,获取access_token
appId和appsecret可以在微信公众平台--开发-基本配置中查找
- /**
- * 第一步,获取access_token
- * appId和appsecret可以在微信公众平台--开发-基本配置中查找
- */
- public static String getAccess_token(String appId, String appSecret){
-
- String url = "https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=" + appId + "&secret=" + appSecret;
- String accessToken = null;
- try
- {
- URL urlGet = new URL(url);
- HttpURLConnection http = (HttpURLConnection) urlGet.openConnection();
- http.setRequestMethod("GET"); // 必须是get方式请求
- http.setRequestProperty("Content-Type", "application/x-www-form-urlencoded");
- http.setDoOutput(true);
- http.setDoInput(true);
- System.setProperty("sun.net.client.defaultConnectTimeout", "30000");// 连接超时30秒
- System.setProperty("sun.net.client.defaultReadTimeout", "30000"); // 读取超时30秒
- http.connect();
- InputStream is = http.getInputStream();
- int size = is.available();
- byte[] jsonBytes = new byte[size];
- is.read(jsonBytes);
- String message = new String(jsonBytes, "UTF-8");
- JSONObject jsonObj = JSONObject.fromObject(message);
- accessToken = jsonObj.getString("access_token");
- }
- catch (Exception e)
- {
- e.printStackTrace();
- }
- return accessToken;
- }
第二步 获取jsapi_ticket
- /**
- * 第二步:获得ACCESS_TICKET
- *
- * @Title: ACCESS_TICKET
- * @Description: 获得ACCESS_TICKET
- * @param @return 设定文件
- * @return String 返回类型
- * @throws
- */
- public static String getAccess_ticket(String access_token) {
- String ticket = null;
- String url = "https://api.weixin.qq.com/cgi-bin/ticket/getticket?access_token="+ access_token +"&type=jsapi";//这个url链接和参数不能变
- try {
- URL urlGet = new URL(url);
- HttpURLConnection http = (HttpURLConnection) urlGet.openConnection();
- http.setRequestMethod("GET"); // 必须是get方式请求
- http.setRequestProperty("Content-Type","application/x-www-form-urlencoded");
- http.setDoOutput(true);
- http.setDoInput(true);
- System.setProperty("sun.net.client.defaultConnectTimeout", "30000");// 连接超时30秒
- System.setProperty("sun.net.client.defaultReadTimeout", "30000"); // 读取超时30秒
- http.connect();
- InputStream is = http.getInputStream();
- int size = is.available();
- byte[] jsonBytes = new byte[size];
- is.read(jsonBytes);
- String message = new String(jsonBytes, "UTF-8");
- JSONObject demoJson = JSONObject.fromObject(message);
- System.out.println("JSON字符串:"+demoJson);
- ticket = demoJson.getString("ticket");
- is.close();
- } catch (Exception e) {
- e.printStackTrace();
- }
- return ticket;
- }
这里拿到对应的jsapi_ticket之后就可以进行参数排序和拼接字符串并加密
第三步:SHA1加密
- /**
- * 第三步:SHA1加密
- */
- public static String SHA1(String decript) {
- try {
- MessageDigest digest = java.security.MessageDigest.getInstance("SHA-1");
- digest.update(decript.getBytes());
- byte messageDigest[] = digest.digest();
- // Create Hex String
- StringBuffer hexString = new StringBuffer();
- // 字节数组转换为 十六进制 数
- for (int i = 0; i < messageDigest.length; i++) {
- String shaHex = Integer.toHexString(messageDigest[i] & 0xFF);
- if (shaHex.length() < 2) {
- hexString.append(0);
- }
- hexString.append(shaHex);
- }
- return hexString.toString();
-
- } catch (NoSuchAlgorithmException e) {
- e.printStackTrace();
- }
- return "";
- }
加密算法转载自:http://www.open-open.com/lib/view/open1392185662160.html
第四步: 获取签名
- /**
- * 第4步获取签名
- * 公众号
- * String appId="wx86b6597*****";
- * String appSecret="aeb428ffb9a8a071fc4******";
- */
- public static void main(String[] args) {
- String appId="wx118d752d*****"; //这里写自己的appId
- String appSecret="947cce9d2808bca0976788d4*****";
- //1、获取AccessToken
- String accessToken = getAccess_token(appId, appSecret);
-
- //2、获取Ticket
- String jsapi_ticket = getAccess_ticket(accessToken);
-
- //3、时间戳和随机字符串
- String noncestr = UUID.randomUUID().toString().replace("-", "").substring(0, 16);//随机字符串
- String timestamp = String.valueOf(System.currentTimeMillis() / 1000);//时间戳
-
- System.out.println("accessToken:"+accessToken+"\njsapi_ticket:"+jsapi_ticket+"\n时间戳:"+timestamp+"\n随机字符串:"+noncestr);
-
- //4、获取url
- String url="http://api.groupusonline.com/txrtWeb/test.html";
- /*根据JSSDK上面的规则进行计算,这里比较简单,我就手动写啦
- String[] ArrTmp = {"jsapi_ticket","timestamp","nonce","url"};
- Arrays.sort(ArrTmp);
- StringBuffer sf = new StringBuffer();
- for(int i=0;i<ArrTmp.length;i++){
- sf.append(ArrTmp[i]);
- }
- */
-
- //5、将参数排序并拼接字符串
- String str = "jsapi_ticket="+jsapi_ticket+"&noncestr="+noncestr+"×tamp="+timestamp+"&url="+url;
-
- //6、将字符串进行sha1加密
- String signature =SHA1(str);
- System.out.println("参数:"+str+"\n签名:"+signature);
- }
上面是工具类里面的内容,接下来在控制类里面写调用接口。上面的这些内容就可以算出来签名和一些配置需要的东西,测试时候可以直接算出来在html页面里面将参数写死。
第五步:调用接口
- /**
- * 微信分享相关
- * Created by yf on 2019/6/20.
- */
- @Controller
- @ResponseBody
- @RequestMapping("wx")
- public class WeChatHander {
-
- private Logger log = LoggerFactory.getLogger(WeChatHander.class);
- //公众号信息
- private static final String appId = "wx118d****12221";
- private static final String appSecret="947cce9***88d4b898db3e";
- //微信自动义分享
- @RequestMapping("share")
- public Object share(HttpSession session,String URL){
- String url="";
- //需要转换解码url
- try {
- url = java.net.URLDecoder.decode(URL,"UTF-8");
- } catch (UnsupportedEncodingException e) {
- e.printStackTrace();
- }
- //获取access_token,这里要从存到session,生成这个参数的wx调用接口有调用次数限制。这部分存session,下面的下载文件里面没有更新,自己添加进去吧,不然接口次数很快就用完了。
- String aeecss_token=(String) session.getAttribute("aeecss_token");
- if(aeecss_token==null){
- aeecss_token = WeChatUtil.getAccess_token(appId, appSecret);
- session.setAttribute("aeecss_token", aeecss_token);
- }
- //获取access_ticket
- String aeecss_ticket=(String) session.getAttribute("aeecss_ticket");
- if(aeecss_ticket==null){
- aeecss_ticket = WeChatUtil.getAccess_ticket(aeecss_token);
- session.setAttribute("aeecss_ticket", aeecss_ticket);
- }
- //String aeecss_ticket = WeChatUtil.getAccess_ticket(aeecss_token);
- //3、时间戳和随机字符串
- String nonceStr = UUID.randomUUID().toString().replace("-", "").substring(0, 16);//随机字符串
- String timestamp = String.valueOf(System.currentTimeMillis() / 1000);//时间戳
- System.out.println("accessToken:"+aeecss_token+"\njsapi_ticket:"+aeecss_ticket+"\n时间戳:"+timestamp+"\n随机字符串:"+nonceStr);
- //4、获取url
- //5、将参数排序并拼接字符串
- String str = "jsapi_ticket="+aeecss_ticket+"&noncestr="+nonceStr+"×tamp="+timestamp+"&url="+url;
- //6、将字符串进行sha1加密
- String signature =WeChatUtil.SHA1(str);
- System.out.println("参数:"+str+"\n签名:"+signature);
-
-
- Map<String,String> map=new HashMap();
- map.put("appId",appId);
- map.put("timestamp",timestamp);
- map.put("accessToken",aeecss_token);
- map.put("ticket",aeecss_ticket);
- map.put("nonceStr",nonceStr);
- map.put("signature",signature);
- return map;
- }
- }
这样通过这个接口获取签名后把所有的信息都返回json格式了。概要的都有了,这是就可以配置config了,此时html页面中应该是:这是参数写死的时候测试用。
-
-
- <script type="text/javascript">
-
- wx.config({
- debug: true, // 开启调试模式,调用的所有api的返回值会在客户端alert出来,若要查看传入的参数,可以在pc端打开,参数信息会通过log打出,仅在pc端时才会打印。
- appId: 'wx118d75***212221', // 必填,公众号的唯一标识
- timestamp:'1560929330' , // 必填,生成签名的时间戳
- nonceStr: 'ab1ef978a35f4d4f', // 必填,生成签名的随机串
- signature: '13159896a4f8f461e0f****9df4029818e6e',// 必填,签名
- jsApiList: [// 必填,需要使用的JS接口列表
- 'updateAppMessageShareData',
- 'updateTimelineShareData'
-
- ], // 需要检测的JS接口列表,所有JS接口列表见附录2,
- });
- //ready
- wx.ready(function () { //需在用户可能点击分享按钮前就先调用
- shareData = {
- title: "测试标题", // 分享标题
- desc: "测试描述", // 分享描述
- link: "http://****.com/txrtWeb/test.html", // 分享链接
- imgUrl: "http://****.com/images/logo.png", // 分享图标
- success: function() {
- // 设置成功
- }
- };
- // 1.4.0 新接口 (只调用这个接口在安卓下是无效的)
- wx.updateAppMessageShareData(shareData);
- wx.updateTimelineShareData(shareData);
- });
- </script>
参数从接口获取的时候如下:
- <!-- Meta for OpenGraph -->
- <meta name="title" content="测试页面标题从meta获取">
- <meta name="description" content="描述">
- <!-- End -->
- <script src="include/jquery-1.7.1.min.js" language="JavaScript"></script>
- <script src="http://res2.wx.qq.com/open/js/jweixin-1.4.0.js"language="JavaScript"></script> <!-- 微信js -->
-
- <!--微信分享相关js -->
- <script type="text/javascript">
- var title=document.querySelector('meta[name="title"]').getAttribute('content'); //网页标题
- var desc=document.querySelector('meta[name="description"]').getAttribute('content'); //网页描述
- $.ajax({
- async : true, //这里参数true和false在微信中打开会有不同效果,实际用的时候用false,用true时候测试会有提示性内容。
- url : 'http://****.com/**/wx/share',
- //url : 'http://localhost:8081/txrt_api/wx/share',
- type : "POST",
- dataType : "json", // 返回的数据类型,设置为JSONP方式
- data : {
- URL : encodeURIComponent(window.location.href.split("#")[0])
- },
- success: function(response, status, xhr){
- //console.log('状态为:' + status + ',状态是:' + xhr.statusText);
- // alert("进来了");
- wx.config({
- debug: false, //调试阶段建议开启,关闭就不弹提示了
- appId: response.appId,//APPID
- timestamp: response.timestamp,//上面main方法中拿到的时间戳timestamp
- nonceStr: response.nonceStr,//上面main方法中拿到的随机数nonceStr
- signature: response.signature,//上面main方法中拿到的签名signature
- //需要调用的方法接口
- jsApiList: [
- 'updateAppMessageShareData','updateTimelineShareData']
- });
- //ready
- wx.ready(function () { //需在用户可能点击分享按钮前就先调用
- shareData = {
- title: title, // 分享标题
- desc: desc, // 分享描述
- link: window.location.href, // 分享链接,该链接域名或路径必须与当前页面对应的公众号JS安全域名一致
- imgUrl: "http://****.com/txrtWeb/images/zfshlogo.png", // 分享图标
- success: function() {
- //alert("设置成功分享");
- // 设置成功
- }
- };
- // 1.4.0 新接口 (只调用这个接口在安卓下是无效的)
- wx.updateAppMessageShareData(shareData);
- wx.updateTimelineShareData(shareData);
- });
- }
- });
-
- </script>
注意:
验证工具:
微信公众平台接口调试工具
微信 JS 接口签名校验工具
参考:
解决微信JS-SDK扫一扫功能接入以及出现签名无效 invalid signature
微信JS-SDK获取signature签名以及config配置
相关代码文件下载:https://download.csdn.net/download/qq_37698433/11253616
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。