当前位置:   article > 正文

微信内分享网页自定义标题,图片,描述_微信转发给朋友的标题描述图片分别取什么字段

微信转发给朋友的标题描述图片分别取什么字段

背景描述:

公司有个需求,将一个微网站链接,网页,外部网站在微信中打开,然后分享给其他人,但是在分享过程中发现分享完微信中显示的是这样子,

      

标题有了,但是简介显示网址,图片没有,而我想要的是上面另一种样式。标题,简介和图片都可自定义的。由此产生了这篇文章。

必备要求:

  1. 有公众号,公众号必须认证过,如果不确定认证没认证过,就看下图,在微信公众平台https://mp.weixin.qq.com最下面接口权限中看分享接口后面状态是已获得还是未获得,已获得才可以用,未获得说明没有认证过,就不用往下看了。

2.必须要有已备案的域名和服务器。实现这个功能需要调用后台接口,而且接口的域名和分享网站,网页的域名是一样的。

这里要注意:在二次分享时候如果分享地址是http的话安卓手机正常,苹果手机不正常,如果是用https的话苹果手机也正常了。

参考资料:

  1. 简书网页分享到微信https://www.jianshu.com/p/bf743d52c6d3
  2. 微信公众平台https://mp.weixin.qq.com
  3. 微信JS-SDK说明文档

实现过程:

上面准备工作做完以后开始实现。

  1. 首先可以先阅读以下微信的JS-SDK的说明文档
    微信JS-SDK说明文档
  2. 绑定域名,登录微信公众平台,进入“公众号设置”的功能设置里面填写js接口安全域名,这个是要填写的是你微信浏览器要打开的域名地址。不能添加IP地址。

    设置时候点击设置里面有说明,如下图

    画红圈的要注意,下载完的那个文件放进去一定要在浏览器能访问才能进行下一步。我是把这个文件放到tomcat下面的ROOT文件夹中,可以直接域名后面加文件名访问。

    网页访问的效果:
  3. 将你服务器的ip地址添加白名单。
    在开发-基本配置里面设置ip白名单,不然调用接口获取不到token.
  4. 在需要调用js接口的页面接入JS文件 http://res.wx.qq.com/open/js/jweixin-1.4.0.js  ,1.4.0是目前最新版本。网上有些地方用的是1.2.0.js,那个已经弃用了。
  5. 通过config接口注入权限并验证配置
    1. wx.config({
    2. debug: true, // 开启调试模式,调用的所有api的返回值会在客户端alert出来,若要查看传入的参数,可以在pc端打开,参数信息会通过log打出,仅在pc端时才会打印。
    3. appId: '', // 必填,公众号的唯一标识
    4. timestamp: , // 必填,生成签名的时间戳
    5. nonceStr: '', // 必填,生成签名的随机串
    6. signature: '',// 必填,签名
    7. jsApiList: [] // 必填,需要使用的JS接口列表
    8. });

     

  6. 这一步算是整个步骤中最关键的一步,必须正确的配置信息才可以进行调用JS-SDK。

获取配置

 获取签名实际是需要四步

1. 根据appId和appsecret获取access_token;

2. 使用access_token获取jsapi_ticket;

3. 使用时间戳,随机数,jsapi_ticket和要访问的url按照签名算法拼接字符串;

4. 对第三步的字符串进行SHA1加密,得到签名;
这步是在服务器后台写的一个工具类里面实现的,测试时候可以先后台获取,前台页面将参数写死,实际用的时候最好动态获取这些数据。如果参数写死的话会二次分享会出问题,在微信中第二次分享,微信会自己加一个参数上去,这样点开在分享的时候签名和url会匹配不上。

第一步,获取access_token

appId和appsecret可以在微信公众平台--开发-基本配置中查找

  1. /**
  2. * 第一步,获取access_token
  3. * appId和appsecret可以在微信公众平台--开发-基本配置中查找
  4. */
  5. public static String getAccess_token(String appId, String appSecret){
  6. String url = "https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=" + appId + "&secret=" + appSecret;
  7. String accessToken = null;
  8. try
  9. {
  10. URL urlGet = new URL(url);
  11. HttpURLConnection http = (HttpURLConnection) urlGet.openConnection();
  12. http.setRequestMethod("GET"); // 必须是get方式请求
  13. http.setRequestProperty("Content-Type", "application/x-www-form-urlencoded");
  14. http.setDoOutput(true);
  15. http.setDoInput(true);
  16. System.setProperty("sun.net.client.defaultConnectTimeout", "30000");// 连接超时30秒
  17. System.setProperty("sun.net.client.defaultReadTimeout", "30000"); // 读取超时30秒
  18. http.connect();
  19. InputStream is = http.getInputStream();
  20. int size = is.available();
  21. byte[] jsonBytes = new byte[size];
  22. is.read(jsonBytes);
  23. String message = new String(jsonBytes, "UTF-8");
  24. JSONObject jsonObj = JSONObject.fromObject(message);
  25. accessToken = jsonObj.getString("access_token");
  26. }
  27. catch (Exception e)
  28. {
  29. e.printStackTrace();
  30. }
  31. return accessToken;
  32. }

第二步 获取jsapi_ticket

  1. /**
  2. * 第二步:获得ACCESS_TICKET
  3. *
  4. * @Title: ACCESS_TICKET
  5. * @Description: 获得ACCESS_TICKET
  6. * @param @return 设定文件
  7. * @return String 返回类型
  8. * @throws
  9. */
  10. public static String getAccess_ticket(String access_token) {
  11. String ticket = null;
  12. String url = "https://api.weixin.qq.com/cgi-bin/ticket/getticket?access_token="+ access_token +"&type=jsapi";//这个url链接和参数不能变
  13. try {
  14. URL urlGet = new URL(url);
  15. HttpURLConnection http = (HttpURLConnection) urlGet.openConnection();
  16. http.setRequestMethod("GET"); // 必须是get方式请求
  17. http.setRequestProperty("Content-Type","application/x-www-form-urlencoded");
  18. http.setDoOutput(true);
  19. http.setDoInput(true);
  20. System.setProperty("sun.net.client.defaultConnectTimeout", "30000");// 连接超时30秒
  21. System.setProperty("sun.net.client.defaultReadTimeout", "30000"); // 读取超时30秒
  22. http.connect();
  23. InputStream is = http.getInputStream();
  24. int size = is.available();
  25. byte[] jsonBytes = new byte[size];
  26. is.read(jsonBytes);
  27. String message = new String(jsonBytes, "UTF-8");
  28. JSONObject demoJson = JSONObject.fromObject(message);
  29. System.out.println("JSON字符串:"+demoJson);
  30. ticket = demoJson.getString("ticket");
  31. is.close();
  32. } catch (Exception e) {
  33. e.printStackTrace();
  34. }
  35. return ticket;
  36. }

这里拿到对应的jsapi_ticket之后就可以进行参数排序和拼接字符串并加密

第三步:SHA1加密

  1. /**
  2. * 第三步:SHA1加密
  3. */
  4. public static String SHA1(String decript) {
  5. try {
  6. MessageDigest digest = java.security.MessageDigest.getInstance("SHA-1");
  7. digest.update(decript.getBytes());
  8. byte messageDigest[] = digest.digest();
  9. // Create Hex String
  10. StringBuffer hexString = new StringBuffer();
  11. // 字节数组转换为 十六进制 数
  12. for (int i = 0; i < messageDigest.length; i++) {
  13. String shaHex = Integer.toHexString(messageDigest[i] & 0xFF);
  14. if (shaHex.length() < 2) {
  15. hexString.append(0);
  16. }
  17. hexString.append(shaHex);
  18. }
  19. return hexString.toString();
  20. } catch (NoSuchAlgorithmException e) {
  21. e.printStackTrace();
  22. }
  23. return "";
  24. }

加密算法转载自:http://www.open-open.com/lib/view/open1392185662160.html

第四步: 获取签名

  1. /**
  2. * 第4步获取签名
  3. * 公众号
  4. * String appId="wx86b6597*****";
  5. * String appSecret="aeb428ffb9a8a071fc4******";
  6. */
  7. public static void main(String[] args) {
  8. String appId="wx118d752d*****"; //这里写自己的appId
  9. String appSecret="947cce9d2808bca0976788d4*****";
  10. //1、获取AccessToken
  11. String accessToken = getAccess_token(appId, appSecret);
  12. //2、获取Ticket
  13. String jsapi_ticket = getAccess_ticket(accessToken);
  14. //3、时间戳和随机字符串
  15. String noncestr = UUID.randomUUID().toString().replace("-", "").substring(0, 16);//随机字符串
  16. String timestamp = String.valueOf(System.currentTimeMillis() / 1000);//时间戳
  17. System.out.println("accessToken:"+accessToken+"\njsapi_ticket:"+jsapi_ticket+"\n时间戳:"+timestamp+"\n随机字符串:"+noncestr);
  18. //4、获取url
  19. String url="http://api.groupusonline.com/txrtWeb/test.html";
  20. /*根据JSSDK上面的规则进行计算,这里比较简单,我就手动写啦
  21. String[] ArrTmp = {"jsapi_ticket","timestamp","nonce","url"};
  22. Arrays.sort(ArrTmp);
  23. StringBuffer sf = new StringBuffer();
  24. for(int i=0;i<ArrTmp.length;i++){
  25. sf.append(ArrTmp[i]);
  26. }
  27. */
  28. //5、将参数排序并拼接字符串
  29. String str = "jsapi_ticket="+jsapi_ticket+"&noncestr="+noncestr+"&timestamp="+timestamp+"&url="+url;
  30. //6、将字符串进行sha1加密
  31. String signature =SHA1(str);
  32. System.out.println("参数:"+str+"\n签名:"+signature);
  33. }

上面是工具类里面的内容,接下来在控制类里面写调用接口。上面的这些内容就可以算出来签名和一些配置需要的东西,测试时候可以直接算出来在html页面里面将参数写死。

第五步:调用接口

  1. /**
  2. * 微信分享相关
  3. * Created by yf on 2019/6/20.
  4. */
  5. @Controller
  6. @ResponseBody
  7. @RequestMapping("wx")
  8. public class WeChatHander {
  9. private Logger log = LoggerFactory.getLogger(WeChatHander.class);
  10. //公众号信息
  11. private static final String appId = "wx118d****12221";
  12. private static final String appSecret="947cce9***88d4b898db3e";
  13. //微信自动义分享
  14. @RequestMapping("share")
  15. public Object share(HttpSession session,String URL){
  16. String url="";
  17. //需要转换解码url
  18. try {
  19. url = java.net.URLDecoder.decode(URL,"UTF-8");
  20. } catch (UnsupportedEncodingException e) {
  21. e.printStackTrace();
  22. }
  23. //获取access_token,这里要从存到session,生成这个参数的wx调用接口有调用次数限制。这部分存session,下面的下载文件里面没有更新,自己添加进去吧,不然接口次数很快就用完了。
  24. String aeecss_token=(String) session.getAttribute("aeecss_token");
  25. if(aeecss_token==null){
  26. aeecss_token = WeChatUtil.getAccess_token(appId, appSecret);
  27. session.setAttribute("aeecss_token", aeecss_token);
  28. }
  29. //获取access_ticket
  30. String aeecss_ticket=(String) session.getAttribute("aeecss_ticket");
  31. if(aeecss_ticket==null){
  32. aeecss_ticket = WeChatUtil.getAccess_ticket(aeecss_token);
  33. session.setAttribute("aeecss_ticket", aeecss_ticket);
  34. }
  35. //String aeecss_ticket = WeChatUtil.getAccess_ticket(aeecss_token);
  36. //3、时间戳和随机字符串
  37. String nonceStr = UUID.randomUUID().toString().replace("-", "").substring(0, 16);//随机字符串
  38. String timestamp = String.valueOf(System.currentTimeMillis() / 1000);//时间戳
  39. System.out.println("accessToken:"+aeecss_token+"\njsapi_ticket:"+aeecss_ticket+"\n时间戳:"+timestamp+"\n随机字符串:"+nonceStr);
  40. //4、获取url
  41. //5、将参数排序并拼接字符串
  42. String str = "jsapi_ticket="+aeecss_ticket+"&noncestr="+nonceStr+"&timestamp="+timestamp+"&url="+url;
  43. //6、将字符串进行sha1加密
  44. String signature =WeChatUtil.SHA1(str);
  45. System.out.println("参数:"+str+"\n签名:"+signature);
  46. Map<String,String> map=new HashMap();
  47. map.put("appId",appId);
  48. map.put("timestamp",timestamp);
  49. map.put("accessToken",aeecss_token);
  50. map.put("ticket",aeecss_ticket);
  51. map.put("nonceStr",nonceStr);
  52. map.put("signature",signature);
  53. return map;
  54. }
  55. }

这样通过这个接口获取签名后把所有的信息都返回json格式了。概要的都有了,这是就可以配置config了,此时html页面中应该是:这是参数写死的时候测试用。

  1. <script type="text/javascript">
  2. wx.config({
  3. debug: true, // 开启调试模式,调用的所有api的返回值会在客户端alert出来,若要查看传入的参数,可以在pc端打开,参数信息会通过log打出,仅在pc端时才会打印。
  4. appId: 'wx118d75***212221', // 必填,公众号的唯一标识
  5. timestamp:'1560929330' , // 必填,生成签名的时间戳
  6. nonceStr: 'ab1ef978a35f4d4f', // 必填,生成签名的随机串
  7. signature: '13159896a4f8f461e0f****9df4029818e6e',// 必填,签名
  8. jsApiList: [// 必填,需要使用的JS接口列表
  9. 'updateAppMessageShareData',
  10. 'updateTimelineShareData'
  11. ], // 需要检测的JS接口列表,所有JS接口列表见附录2,
  12. });
  13. //ready
  14. wx.ready(function () { //需在用户可能点击分享按钮前就先调用
  15. shareData = {
  16. title: "测试标题", // 分享标题
  17. desc: "测试描述", // 分享描述
  18. link: "http://****.com/txrtWeb/test.html", // 分享链接
  19. imgUrl: "http://****.com/images/logo.png", // 分享图标
  20. success: function() {
  21. // 设置成功
  22. }
  23. };
  24. // 1.4.0 新接口 (只调用这个接口在安卓下是无效的)
  25. wx.updateAppMessageShareData(shareData);
  26. wx.updateTimelineShareData(shareData);
  27. });
  28. </script>

参数从接口获取的时候如下:

  1. <!-- Meta for OpenGraph -->
  2. <meta name="title" content="测试页面标题从meta获取">
  3. <meta name="description" content="描述">
  4. <!-- End -->
  5. <script src="include/jquery-1.7.1.min.js" language="JavaScript"></script>
  6. <script src="http://res2.wx.qq.com/open/js/jweixin-1.4.0.js"language="JavaScript"></script> <!-- 微信js -->
  7. <!--微信分享相关js -->
  8. <script type="text/javascript">
  9. var title=document.querySelector('meta[name="title"]').getAttribute('content'); //网页标题
  10. var desc=document.querySelector('meta[name="description"]').getAttribute('content'); //网页描述
  11. $.ajax({
  12. async : true, //这里参数true和false在微信中打开会有不同效果,实际用的时候用false,用true时候测试会有提示性内容。
  13. url : 'http://****.com/**/wx/share',
  14. //url : 'http://localhost:8081/txrt_api/wx/share',
  15. type : "POST",
  16. dataType : "json", // 返回的数据类型,设置为JSONP方式
  17. data : {
  18. URL : encodeURIComponent(window.location.href.split("#")[0])
  19. },
  20. success: function(response, status, xhr){
  21. //console.log('状态为:' + status + ',状态是:' + xhr.statusText);
  22. // alert("进来了");
  23. wx.config({
  24. debug: false, //调试阶段建议开启,关闭就不弹提示了
  25. appId: response.appId,//APPID
  26. timestamp: response.timestamp,//上面main方法中拿到的时间戳timestamp
  27. nonceStr: response.nonceStr,//上面main方法中拿到的随机数nonceStr
  28. signature: response.signature,//上面main方法中拿到的签名signature
  29. //需要调用的方法接口
  30. jsApiList: [
  31. 'updateAppMessageShareData','updateTimelineShareData']
  32. });
  33. //ready
  34. wx.ready(function () { //需在用户可能点击分享按钮前就先调用
  35. shareData = {
  36. title: title, // 分享标题
  37. desc: desc, // 分享描述
  38. link: window.location.href, // 分享链接,该链接域名或路径必须与当前页面对应的公众号JS安全域名一致
  39. imgUrl: "http://****.com/txrtWeb/images/zfshlogo.png", // 分享图标
  40. success: function() {
  41. //alert("设置成功分享");
  42. // 设置成功
  43. }
  44. };
  45. // 1.4.0 新接口 (只调用这个接口在安卓下是无效的)
  46. wx.updateAppMessageShareData(shareData);
  47. wx.updateTimelineShareData(shareData);
  48. });
  49. }
  50. });
  51. </script>

注意

  1. url一定要是完整的url(当前网页的URL,不包含#及其后面部分)最好是使用window.location.href.split("#")获取得到,如果传入固定的好像会报invalid signature错误,所以为了安全起见还是直接传入当前的url
  2. 这个签名的有效时间为7200秒,也就是2个小时,因此当超过两个小时候,再访问也会报invalid signature错误。但是这个我还没有遇见,并不知道这么解决,其他说是需要缓存access_token和access_ticket
  3. 另外还有一个错误:invalid url domain
    这个跟生成签名时用的url有关系,官网的说法是:
    invalid url domain当前页面所在域名与使用的appid没有绑定,请确认正确填写绑定的域名,如果使用了端口号,则配置的绑定域名也要加上端口号(一个appid可以绑定三个有效域名)
    这个url必须是:“公众号设置---功能设置----JS接口安全域名”中绑定的三个域名之一
  4. 如果以上配置都是正确,而且debug也设置为true了,在微信中访问连接会出现config:ok的界面,就说明配置成功了
  5. 有时也可以把ajax请求放在setTimeout中进行请求。

验证工具:
微信公众平台接口调试工具
微信 JS 接口签名校验工具

参考:
解决微信JS-SDK扫一扫功能接入以及出现签名无效 invalid signature
微信JS-SDK获取signature签名以及config配置

相关代码文件下载:https://download.csdn.net/download/qq_37698433/11253616

 


 

 

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/weixin_40725706/article/detail/268061
推荐阅读
相关标签
  

闽ICP备14008679号