Hi,很高兴认识你~
世界很大,巧妙的是我们在这里相遇。
欢迎关注天宇文创意乐派,一个职场人的聚集地。
一.官方教程
官方文档:https://developers.weixin.qq.com/doc/offiaccount/OA_Web_Apps/JS-SDK.html
官方文档——常见的错误及解决方法:https://developers.weixin.qq.com/doc/offiaccount/OA_Web_Apps/JS-SDK.html ——> 见页面底端的 附录5-常见错误及解决方法
官方问题反馈:https://developers.weixin.qq.com/community/develop/doc/0000e2f5d0cdc02c0a391aedd58c00
官方校验签名工具:http://mp.weixin.qq.com/debug/cgi-bin/sandbox?t=jsapisign
官方demo:https://www.weixinsxy.com/jssdk/
二.常见问题以及需要注意的地方
1. invalid signature签名错误。建议按如下顺序检查:
1. 确认签名算法正确,可用http://mp.weixin.qq.com/debug/cgi-bin/sandbox?t=jsapisign 页面工具进行校验。
2. 确认config中nonceStr(js中驼峰标准大写S), timestamp与用以签名中的对应noncestr, timestamp一致。
3. 确认url是页面完整的url(请在当前页面alert(location.href.split('#')[0])确认),包括'http(s)://'部分,以及'?'后面的GET参数部分,但不包括'#'hash后面的部分。
4. 确认 config 中的 appid 与用来获取 jsapi_ticket 的 appid 一致。
5. 确保一定缓存access_token和jsapi_ticket。
6. 确保你获取用来签名的url是动态获取的,动态页面可参见实例代码中php的实现方式。如果是html的静态页面在前端通过ajax将url传到后台签名,前端需要用js获取当前页面除去'#'hash部分的链接(可用location.href.split('#')[0]获取,而且需要encodeURIComponent,后端接收url时且必须用例如:Java URLDecoder.decode解码),因为页面一旦分享,微信客户端会在你的链接末尾加入其它参数,如果不是动态获取当前链接,将导致分享后的页面签名失败。
2.invalid domain?
配置的url与公众号JS接口安全域名不匹配
三.绑定JS接口安全域名
域名格式:如果你的项目域名是http://test.domain.com,那么JS接口安全域名为test.domain.com。切记!
四.引入JSSDK
第一种引入方式:
npm install jweixin-module --save
第二种引入方式:
在需要调用JS接口的页面引入如下JS文件,(支持https):http://res.wx.qq.com/open/js/jweixin-1.6.0.js
如需进一步提升服务稳定性,当上述资源不可访问时,可改访问:http://res2.wx.qq.com/open/js/jweixin-1.6.0.js (支持https)
<script type="text/javascript" src="http://res.wx.qq.com/open/js/jweixin-1.6.0.js"></script>
代码实现:
前端
import wx from 'weixin-js-sdk';
async _goWxchat(){
let url = encodeURIComponent(location.href.split('#')[0]);
let data={
url
}
alert(url)
const res = await reqConfigSignature(data);
if (res.code === RESULT_SUCCESS_CODE) {
//拿到后端给的这些数据
let appId = res.data.appId;
let timestamp = res.data.timestamp;
let nonceStr = res.data.nonceStr;
let signature = res.data.signature;
wx.config({
debug: true,// 开启调试模式,调用的所有api的返回值会在客户端alert出来,若要查看传入的参数,可以在pc端打开,参数信息会通过log打出,仅在pc端时才会打印。
appId, // 必填,公众号的唯一标识,填自己的!(开发者账号)
timestamp, // 必填,生成签名的时间戳,刚才接口拿到的数据
nonceStr, // 必填,生成签名的随机串
signature, // 必填,签名,见附录1
jsApiList: [
'onMenuShareTimeline',
'onMenuShareAppMessage'
]
})
wx.ready(function () {
//分享到朋友圈
wx.onMenuShareTimeline({
title: '小婊子', // 分享时的标题
link: url + '?redirectUrl=http://auth.motopa.cn/logo.png', // 分享时的链接 如果项目域名与JS接口安全域名不一致 可以采用此方式
imgUrl: '', // 分享时的图标
success: function () {
console.log("分享成功");
},
cancel: function () {
console.log("取消分享");
}
});
//分享给朋友
wx.onMenuShareAppMessage({
title: tit,
desc: '这件商品终于优惠了,每件只需元',
link: url + '?redirectUrl=http://auth.motopa.cn/logo.png',
imgUrl: '',
type: '',
dataUrl: '',
success: function () {
console.log("分享成功");
},
cancel: function () {
console.log("取消分享");
}
});
})
wx.error(function(res){
})
}
},
后端
package com.auth.sdk.controller;
import com.alibaba.fastjson.JSONObject;
import com.auth.sdk.common.ResultData;
import com.auth.sdk.db.redisson.dao.base.StringRedisBaseDao;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.codec.digest.DigestUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.client.RestTemplate;
import java.net.URLDecoder;
import java.util.Arrays;
import java.util.Random;
"/wx") (
public class WxShareController {
private static final String appId = "wxea6631d168a33e95";
private static final String appSecret= "3eae75d6a79a9af781391c9c1460026f";
private static final long expireTime = 120l;
RestTemplate restTemplate;
//redis 可以替换成自己环境的redis
StringRedisBaseDao stringRedisBaseDao;
/**
* 获取最终签名的restful方法
* @param reqJson
* @return
*/
"/WeixinAction_getWXConfigSignature") (
public ResultData getWXConfigSignature( JSONObject reqJson) {
String url = URLDecoder.decode(reqJson.getString("url"));
log.info("原始URL: " + url);
String timestamp = Long.toString(System.currentTimeMillis() / 1000);
String nonceStr = getRandomStr(8);
log.info("随机串:"+nonceStr+", 获取签名URL: " + url);
JSONObject respJson = new JSONObject();
String[] signArr = new String[]{"url=" + url, "jsapi_ticket=" + getWXJsapiTicket(), "noncestr=" + nonceStr, "timestamp=" + timestamp};
Arrays.sort(signArr);
String signStr = StringUtils.join(signArr, "&");
String resSign = DigestUtils.sha1Hex(signStr);
log.info("返回的签名:" + resSign);
respJson.put("appId", appId);
respJson.put("timestamp", timestamp);
respJson.put("nonceStr", nonceStr);
respJson.put("signature", resSign);
log.info(respJson.toJSONString());
return ResultData.success(respJson);
}
/**
* 获取jsapi_ticket方法
* @return
*/
private String getWXJsapiTicket() {
String ticket = stringRedisBaseDao.getItem(appId);
if (StringUtils.isBlank(ticket)) {
String url = "https://api.weixin.qq.com/cgi-bin/ticket/getticket?access_token=" + getWXaccessToken() + "&type=jsapi";
String resp = restTemplate.getForObject(url, String.class);
JSONObject resJson = JSONObject.parseObject(resp);
log.info("获取到ticket:" + resJson.getString("ticket"));
stringRedisBaseDao.addItem(appId, resJson.getString("ticket"), expireTime);
return resJson.getString("ticket");
}
return ticket;
}
/**
* 获取access_token
* @return
*/
private String getWXaccessToken() {
String url = "https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid="+appId+"&secret="+appSecret;
String resp = restTemplate.getForObject(url, String.class);
JSONObject resJson = JSONObject.parseObject(resp);
log.info("获取到access_token:" + resp);
return resJson.getString("access_token");
}
/**
* 随机字符串
* @param length
* @return
*/
public static String getRandomStr(int length) {
String base = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
int randomNum;
char randomChar;
Random random = new Random();
// StringBuffer类型的可以append增加字符
StringBuffer str = new StringBuffer();
for (int i = 0; i < length; i++) {
// 可生成[0,n)之间的整数,获得随机位置
randomNum = random.nextInt(base.length());
// 获得随机位置对应的字符
randomChar = base.charAt(randomNum);
// 组成一个随机字符串
str.append(randomChar);
}
return str.toString();
}
}
微信分享步骤测试 建议在wechat开发工具中测试
配置 switchhost 将本机指向JS接口安全域名
本文使用 文章同步助手 同步