首先需求是:将微信扫一扫的分享功能 回形针图片 描述 标题 换成自定义的

大概是从上往下的这个效果。
好了需求已经很明确了,接下来说一下实现过程。先贴两个很有用的帖子可以借鉴参考:
http://www.jjyc.org/a/d/182281
https://www.jianshu.com/p/922b0986d1b0
除了这两篇帖子外的需要做的还有一个全局缓存,因为jsapi_ticket有个7200的失效时间,而微信对这个调用微信JS接口的临时票据有调用限制。因此redis最好缓存一下,能增大对外的用户使用次数(后面会把做法详细说)。

我这边静态页面是写在后端,用调接口渲染出的静态页面,谁知道后面加了需求要对接jssdk,只能一点点append。。。真是太惨了。。大致是下面这样:
仔细看过流程的人就会发现:
上面的接口是从ajax请求返回的结果里取出来的。这三个参数作为请求wx官方的参数,是很重要的,时间戳、随机字符串都很好获取,最主要的是signature这个签名。下面来说怎么获取。
说之前提一下为什么多了这步:

其实没有这步,直接在后端获取再把值赋上去,而不用用ajax返回的对象data一个个去拿值,也能达到效果,但是只能转发一个用户,当这个用户用自己的链接再转发给其他人时就失效了,因为微信转发时会自动拼接一串字符,这些是未知的,所以请求的页面url不是固定的(一个素材id转发不是只有一个用户转发),这时只能用js的var url = location.href.split(’#’)[0];方法即时获取当前地址,不同用户不同的。【当前url是post请求求参数,返回jssdk的请求参数】后端代码如下:

@ApiOperation("获取推广微信JS-SDK请求参数")
@GetMapping("/pub/html/wxJSSdk")
@ResponseBody
public WxShareSignParam getWXjsSdkResult(@RequestParam("url") String url) {try {return wxShareSupport.getSignParam(url);} catch (Exception e) {e.printStackTrace();}return null;
}

顺便把拼接的前端代码放一下,虽然丑陋。。。

 /*** @param accountId  用户id标识* @param title      推广文章标题* @param updateTime 推广页面展示:更新时间* @param content    推广页面展示:内容* @param QRUrl      推广页面展示:注册入口二维码* @param imgUrl     缩略图地址* @param link       跳转链接* @return*/public String buildHtml(Long accountId, String title, String updateTime, String content, String QRUrl, String imgUrl, String link, String descLimit) {String url = spreadRegHtmlUrl + "/#/register?id=" + accountId;StringBuffer builder = new StringBuffer();builder.append("<html>");builder.append("<head>");builder.append("<meta charset=\"utf-8\">");builder.append("<meta http-equiv=\"X-UA-Compatible\" content=\"IE=edge\">");builder.append("<meta name=\"viewport\" content=\"width=device-width,initial-scale=1.0\">");builder.append("<link rel=\"stylesheet\" type=\"text/css\" href=\"" + publicCssFileUrl + "\" />");builder.append("<title>" + title + "</title>");builder.append("<style>");builder.append("*{\n" +"        margin: 0;padding:0;\n" +"      }" +"      .title{\n" +"        margin: 0;font-size: 24px;font-family: PingFang SC;font-weight:bold;color:rgba(0,0,0,1);margin-bottom: 20px !important;\n" +"      }\n" +"      .avater{\n" +"        width: 36px !important;display: inline-block;vertical-align: middle;margin-bottom: 17px;margin-right: 10px;\n" +"      }\n" +"      .avater-right{\n" +"        display: inline-block;vertical-align: middle;margin-bottom: 17px;\n" +"      }\n" +"      .avater-name{\n" +"        margin: 0;font-size:16px;font-family:PingFang SC;font-weight:bold;color:rgba(0,0,0,1);\n" +"      }\n" +"      .time{\n" +"        margin: 0;font-size:12px;font-family:PingFang SC;font-weight:400;color:rgba(0,0,0,1);\n" +"      }\n" +"      .fix-bot{\n" +"        width:100px;\n" +"        position: fixed;\n" +"        bottom: 70px;\n" +"        right: 0;\n" +"      }");builder.append("</style>");builder.append("</head>");builder.append("<body>");builder.append("<div class=\"ql-container ql-snow\">");builder.append("<div class=\"ql-editor\">");builder.append("<p class=\"title\">" + title + "</p>");builder.append("<img class=\"avater\" src=" + spreadHtmlTitleUrl + " />");builder.append("<div class=\"avater-right\">");builder.append("<p class=\"avater-name\">" + spreadHtmlAuthor + "</p>");builder.append("<p class=\"time\">" + updateTime + "</p>");builder.append("</div>");builder.append(content);builder.append("<img data-v-569dfcf0 src=\"" + QRUrl + "\"/>");builder.append("</div>");builder.append("</div>");builder.append("<img onclick='window.location.href=\"" + url + "\"' class=\"fix-bot\" src=\"" + regBtnUrl + "\" />");builder.append("<script src = \"http://res.wx.qq.com/open/js/jweixin-1.2.0.js\"></script>");builder.append("<script src=\"https://apps.bdimg.com/libs/jquery/2.1.4/jquery.min.js\"></script>");builder.append("<script>");builder.append("    $(function () {\n" +"        var url = location.href.split('#')[0];\n" +"        $.ajax({\n" +"            url: \"http://qiandun-spread-test.rrgs2.cn" + "/spread/pub/html/wxJSSdk\"" + ",\n" +"            data: {\n" +"                \"url\": url\n" +"            },\n" +"            dataType: \"json\",\n" +"            timeout: 5000,\n" +"            error: function (XMLHttpRequest, textStatus, errorThrown) {\n" +"                if (textStatus == \"timeout\") {\n" +"                } else {\n" +"                }\n" +"            },\n" +"            success: function (data, textStatus) {\n" +"                if (textStatus == \"success\") {\n" +"                    wx.config({\n" +"                        debug: true,\n" +"                        appId: 'wx3fa8908cb1f9409b',\n" +"                        timestamp: data.timestamp,\n" +"                        nonceStr: data.nonceStr,\n" +"                        signature: data.signature,\n" +"                        jsApiList: ['checkJsApi', 'onMenuShareTimeline', 'onMenuShareAppMessage', 'onMenuShareQQ', 'onMenuShareWeibo']\n" +"                    });\n" +"                    wx.ready(function () {\n" +"                        wx.onMenuShareTimeline({\n" +"                            imgUrl:'" + imgUrl + "',\n" +"                            title:'" + title + "',\n" +"                            desc: '" + descLimit + "',\n" +"                            link:'" + link + "',\n" +"                        });\n" +"                        wx.onMenuShareAppMessage({\n" +"                            imgUrl:'" + imgUrl + "',\n" +"                            title:'" + title + "',\n" +"                            desc: '" + descLimit + "',\n" +"                            link:'" + link + "',\n" +"                        });\n" +"                    });\n" +"                }\n" +"            }\n" +"        });\n" +"    });");builder.append("</script>");builder.append("</body>");builder.append("</html>");return builder.toString();}

这些写在前端就会清楚很多,只不过跟我们公司的需求有关,原本只是简单拼接一个html,标题内容时间这些内容。谁知道后面加需求了,只能在原来的代码上加。。加上负责这块的同事刚离职,,真是雪上加霜。。。
前端就差不多了,后面主要讲签名怎么获取。前端这里还有一个注意事项:
config里的配置
参数名是固定的(严格区分大小写,千万别写错了),后面jsapilist是指定分享的程序,比如发给朋友,朋友圈,微博,qq等。
下面是获取签名的代码:

public WxShareSignParam getSignParam(String url) {try {//随机字符串String nonceStr = getNonceStr();//时间戳String timeStamp = getTimeStampSecond();//获取加密签名String signature = SHA1("jsapi_ticket=" + getTicketWithCache() + "&noncestr=" + nonceStr + "&timestamp=" + timeStamp + "&url=" + url);return new WxShareSignParam(timeStamp, nonceStr, signature);} catch (Exception e) {logger.info("获取微信分享 WxShareSignParam 异常 url:{}", url, e);}return null;
}
/*** 获取随机字符串,16位** @return*/
private static String getNonceStr() {return UUID.randomUUID().toString().replace("-", "").substring(0, 16);
}/*** 获取时间戳,秒** @return*/
private static String getTimeStampSecond() {return String.valueOf(System.currentTimeMillis() / 1000);//时间戳
}


将参数拼成字符串,其中jsapi_ticket处理成缓存,url是ajaxs请求来的当前随机地址

/*** 同步关键字防止并发问题* 分布式环境仍然可能出现问题,但是概率小且无影响,暂不处理* @return*/
private synchronized String getTicketWithCache() {String ticket = getTicket();if (StringUtils.isNotBlank(ticket)) {return ticket;}String accessToken = getAccessToken();ticket = getTicket(accessToken);return ticket;
}private String getTicket(){try {//private StringRedisTemplate stringRedisTemplate;return stringRedisTemplate.boundValueOps(WX_SHARE_TICKET_CACHE_KEY).get();}catch (Exception e){logger.error("redis error");}return "";
}private void setTicket(String ticket, long expireTime){if(expireTime < 0){return ;}try {stringRedisTemplate.boundValueOps(WX_SHARE_TICKET_CACHE_KEY).set(ticket,expireTime, TimeUnit.SECONDS);}catch (Exception e){logger.error("redis error");}
}//缓存里没有的话 则重新请求/*** 每次获取accessToken都会导致上一个失效* 目前只有这里用到,所以不做缓存,每次都重新获取* @return*/
public static String getAccessToken() {String url = "https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential" + "&appid=" + APP_ID + "&secret=" + SECRET;try {JSONObject demoJson = HttpClientUtils.httpGet(url);logger.info("获取微信分享 key 结果:{}", demoJson);String accessToken = demoJson.getString("access_token");if (StringUtils.isBlank(accessToken)) {throw new SpreadRuntimeException(SpreadErrorCode.SPREAD_WX_JsSDK_ACCESS_TOKEN_ERROR2);}return accessToken;} catch (Exception e) {logger.error("获取微信分享 key 异常", e);throw new SpreadRuntimeException(SpreadErrorCode.SPREAD_WX_JsSDK_ACCESS_TOKEN_ERROR1);}
}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 StringStringBuffer 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) {throw new SpreadRuntimeException(SpreadErrorCode.SPREAD_WX_JsSDK_SHA1_ERROR);}
}

微信js-sdk分享链接自定义图片描述标题相关推荐

  1. 微信js sdk 分享 失败 有时候好 有时候坏

    微信js sdk 分享 失败  有时候好 有时候坏 用了一个www开头的域名 和一个xx.com的域名 两个在解析上有问题. 实践是www.xx.com的比较 稳定 转载于:https://www.c ...

  2. php转发朋友圈缩略图片,解释最全的,手把手教的微信JS sdk分享设置教程-微信分享插件PHP源码JS-SDK接口,分享到朋友圈 转发好友带缩略图...

    亲们,此文是我上传的有关微信分享插件PHP源码JS-SDK接口的.rar和.zip的说明使用文件 许多朋友都面临自己编写的网站通过微信转发时,无论是分享微信好友或是微信朋友圈时,出现无缩略图显示的问题 ...

  3. 公众号 H5页面分享链接携带图片与标题(自定义卡片式分享链接)

    第一步:引入微信sdk(npm install weixin-js-sdk --save) 第二步:创建wechat.js import wx from "../node_modules/w ...

  4. 微信公众号分享链接自定义hash值的处理

    微信公众号默认的分享样式是直接分享一条链接的,样式丑陋.但是微信jsdk暴露了分享的API可以自定义分享样式. 一.分享鉴权及分享接口冲定义 这一块的文档很全面,不做细述.关键代码如下: functi ...

  5. 微信分享网页链接自定义图片和文字描述

    今天开发需要微信分享网页链接自定义图片和文字描述,于是网上各种查找资料和各种看手册,遇到了好多坑,不过啃了半天以后终于把问题解决了,以防以后忘记,今天记录一下; 首先,由于微信已经发布了想要分享链接必 ...

  6. 微信朋友圈分享链接的【图片】设置

    微信朋友圈分享链接的[图片]设置 我们在制作好一些网页以后,希望通过微信朋友圈分享给大家.但是发现这样分享到微信朋友圈是没有小图标的.如何在链接前增加吸引人的图片呢?请看下面的制作方法. 在网页的头部 ...

  7. 微信JS接口 分享到朋友圈 分享给朋友 分享到QQ 拍照或从手机相册中选图 识别音频并返回识别结果 使用微信内置地图查看位置

    微信JS接口 微信JS接口 分享到朋友圈 分享给朋友 分享到QQ 拍照或从手机相册中选图 识别音频并返回识别结果 使用微信内置地图查看位置 来源:http://www.cnblogs.com/txw1 ...

  8. android微信源生SDK分享问题

    android微信源生SDK分享问题 老生常谈了,不过还是记录一下这些坑比较合适!今天测试忽然发现,微信分享出去的条目,自身机子可以看到图片,而别人的手机上却发现缩略图没了,成为另一个链接黑图.这种问 ...

  9. 微信js sdk 授权上传头像下载代码片段和注意事项

    /*  * 描述:当前页授权  * @param url   例:index.html / 如果有参数,需加密index.html?id=1     */ 1.对需要运用js sdk的页面授权 get ...

最新文章

  1. 【pwnable】asm之write up
  2. Android开发系列(三)
  3. Fckeditor插入视频或视频文件
  4. boost::mp11::mp_bind_front_q相关用法的测试程序
  5. 查看未提交事务或sleep session最后执行的sql语句
  6. MongoDB、ElasticSearch、Redis、HBase比较
  7. win7您需要来自计算机管理员的权限,win7需要提供管理员权限才能打开文件怎么解决...
  8. 关于计算机用途的大学英语作文,学习使用电脑Student Use of Computers
  9. C#数学计算包 Math.NET
  10. 关于软件测试学习的心得
  11. servlet+jsp项目改成springboot+jsp+maven
  12. VBScript入门篇
  13. 华为手机刷机后显示无服务器,华为手机刷机后,无法开机怎么办?
  14. ADNI数据_PET——官方预处理
  15. 部分js文件在360浏览器极速模式下不加载,不执行的原因
  16. mysql联合主键的坑
  17. Android性能优化系列-监听View inflate周期并动态替换
  18. 北京市金融工作局:大数据重塑未来金融监管方式
  19. palette gef_GEF走向3D
  20. 穹顶之下——大数据下生活

热门文章

  1. Java六大线程池和四大拒绝策略
  2. ISP算法:gamma矫正
  3. Python尝试给扫描件添加自然阴影
  4. 数电出题??自启动问题
  5. 我的互联网创业公司的第一笔收入磨难记
  6. 这几个方法让你学会PDF尺寸大小怎么调整
  7. ThinkPHPdayo01学习笔记(体系化,系统化笔记)
  8. 用文字,把这支笔卖给我
  9. HTML的背景颜色和背景图片
  10. 论文的主要观点怎么写?