使用微信测试号 实现微信扫一扫功能时 出现的问题
1. 环境: springboot + js +微信测试号 + 花生壳穿透
2. 问题
ios系统 调用微信扫一扫时候出现 realauthurl:xxx errmsg config:invalid signature 错误
经过比对 生成和传递的signature 值是相同的,排除签名问题
微信 JS 接口签名校验:https://mp.weixin.qq.com/debug/cgi-bin/sandbox?t=jsapisign
错误提示中有url 猜测是url 问题 , 一直没有搞懂这里的url到底是什么的url 。 此时的url应该是当前网页的url http://xxxx/xx.html
如果url是正确的会提示 errMsg: config:invalid url domain
3. 解决
url中从#号前边的都要有 通过js 获取当前网页的url
<script>
window.onload = function() {
var wx_invite_url = location.href.split('#')[0]; //获取当前网页的url !!!!
console.log("url",wx_invite_url);
$.get("jsapi/getSign",{url:wx_invite_url},function(data){
wx.config({
debug: true, // 开启调试模式,调用的所有api的返回值会在客户端alert出来,若要查看传入的参数,可以在pc端打开,参数信息会通过log打出,仅在pc端时才会打印。
appId: data.appId, // 必填,公众号的唯一标识
timestamp: data.timestamp, // 必填,生成签名的时间戳
nonceStr: data.nonceStr, // 必填,生成签名的随机串
signature: data.signature,// 必填,签名
jsApiList: ['scanQRCode'] // 必填,需要使用的JS接口列表
});
wx.error(function(res){
alert(res);
// config信息验证失败会执行error函数,如签名过期导致验证失败,具体错误信息可以打开config的debug模式查看,也可以在返回的res参数中查看,对于SPA可以在这里更新签名。
});
});
}
function scaneMethod() {
var ua = navigator.userAgent.toLowerCase()
var isWeixin = ua.indexOf('micromessenger') !== -1
if (!isWeixin) {
alert('请用微信打开连接,才可使用扫一扫')
}
window.wx.scanQRCode({
needResult: 1, // 默认为0,扫描结果由微信处理,1则直接返回扫描结果,
scanType: ['qrCode', 'barCode'], // 可以指定扫二维码还是一维码,默认二者都有
success: function (res) {
// 扫码成功,跳转到二维码指定页面(res.resultStr为扫码返回的结果)
var scan = res.resultStr
alert(scan)
}
})}
</script>
完整的代码:
- 获取签名的接口:
@RequestMapping(value = "/getSign")
@ResponseBody
public Map tiaoma( HttpServletRequest request,String url) throws Exception {
String Url=request.getRequestURL().toString();
log.info("请求的url={}",Url);
Map resMap = new HashMap();
resMap = JsUtils.sign(url);
log.info("=======map参数:{}",resMap);
return resMap;
}
- 签名的工具类 加密 获取token ticket … 直接修改appid appsecret 就可用
public class JsUtils {
public static String accessToken = null;
public static String ticket = null;
private static final String appid=null;
private static final String appsecret=null;
public static Map sign(String url) {
if(accessToken==null){
String sendUrl = "https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid="+appid+"&secret="+appsecret;
String result = getHttpResult(sendUrl);
JSONObject tokenJson = JSONObject.parseObject(result);
accessToken= tokenJson.get("access_token").toString();
log.info("toke={}",accessToken);
}
if(ticket==null){
String signUrl = "https://api.weixin.qq.com/cgi-bin/ticket/getticket?access_token=" + accessToken + "&type=jsapi";
String resultSign = getHttpResult(signUrl);
JSONObject tokenJson = JSONObject.parseObject(resultSign);
ticket= tokenJson.get("ticket").toString();
}
Map<String, Object> ret = new HashMap();
String nonce_str = create_nonce_str();
String timestamp = create_timestamp();
String string1;
String signature = "";
//注意这里参数名必须全部小写,且必须有序
string1 = "jsapi_ticket=" + ticket +
"&noncestr=" + nonce_str +
"×tamp=" + timestamp +
"&url=" + url;
try {
MessageDigest crypt = MessageDigest.getInstance("SHA-1");
crypt.reset();
crypt.update(string1.getBytes("UTF-8"));
signature = byteToHex(crypt.digest());
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
}
ret.put("url", url);
ret.put("nonceStr", nonce_str);
ret.put("timestamp", Integer.parseInt(timestamp));
ret.put("signature", signature);
ret.put("jsapi_ticket", ticket);
ret.put("appId", appid);
return ret;
}
/**
* 随机加密
*
* @param hash
* @return
*/
private static String byteToHex(final byte[] hash) {
Formatter formatter = new Formatter();
for (byte b : hash) {
formatter.format("%02x", b);
}
String result = formatter.toString();
formatter.close();
return result;
}
/*
* 获取访问地址链接返回值
*/
private static String getHttpResult(String url) {
String result = "";
HttpGet httpRequest = new HttpGet(url);
try {
HttpResponse httpResponse = HttpClients.createDefault().execute(httpRequest);
if (httpResponse.getStatusLine().getStatusCode() == 200) {
result = EntityUtils.toString(httpResponse.getEntity());
}
} catch (ClientProtocolException e) {
e.printStackTrace();
result = e.getMessage().toString();
} catch (IOException e) {
e.printStackTrace();
result = e.getMessage().toString();
}
return result;
}
/**
* 产生随机串--由程序自己随机产生
*
* @return
*/
private static String create_nonce_str() {
return UUID.randomUUID().toString();
}
/**
* 由程序自己获取当前时间
*
* @return
*/
private static String create_timestamp() {
return Long.toString(System.currentTimeMillis() / 1000);
}
}
微信测试号地址:https://mp.weixin.qq.com/debug/cgi-bin/sandboxinfo?action=showinfo&t=sandbox/index
微信js sdk 文档地址:https://developers.weixin.qq.com/doc/offiaccount/OA_Web_Apps/JS-SDK.html