900字范文,内容丰富有趣,生活中的好帮手!
900字范文 > 微信js-sdk分享链接自定义图片描述标题

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

时间:2022-11-17 05:36:32

相关推荐

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

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

大概是从上往下的这个效果。

好了需求已经很明确了,接下来说一下实现过程。先贴两个很有用的帖子可以借鉴参考:

/a/d/182281

/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")@ResponseBodypublic 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./open/js/jweixin-1.2.0.js\"></script>");builder.append("<script src=\"/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-" + "/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./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);}}

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。