背景介绍:
因开发需要实现公众号网页扫码功能,参考了官方API ,写完总是出现 config:invalid signature,检查了appId,和appSecret 都没问题,但就是报错。官方对于签名中描述的很模糊,这里分享下出现的原因,和解决办法。基本都是签名出了问题,官方中说当前网页的URL 会让人误解,特此强调。
第一个坑:一定是调用微信JS-SDK 页面的url。不是域名,也不是首页URL。
第二个坑:签名签完了要转成小写。大写也是有问题的。
基本就这两点最容易忽略,其他的坑官方都有列举,这里就不一一举例了。
前台页面
var ul = location.href;
//后台签证请求,此次为获取当前页面的url或者说调用JSAPI页面的url,哪个页面调用,就传哪个页面的url
app.callAjaxPost({ url: "WxOAuth/Signature", param: { url: ul } }, function (result2) {
if (result2.state == "error") {
mui.alert(result2.message);
}
if (result2.state == "success") {
var config = result2.data;
console.log(JSON.stringify(config));
//mui.toast('配置api权限中');
wx.config({
debug: false,// 开启调试模式,调用的所有api的返回值会在客户端alert出来,若要查看传入的参数,可以在pc端打开,参数信息会通过log打出,仅在pc端时才会打印。
appId: config.appid,// 必填,公众号的唯一标识
timestamp: config.timestamp,// 必填,生成签名的时间戳
nonceStr: config.noncestr,// 必填,生成签名的随机串
signature: config.signature,// 必填,签名
jsApiList: [
'checkJsApi',
'scanQRCode'
]
});
}
});
//WxERROR
wx.error(function (res) {
mui.alert("出错了:" + res.errMsg);//这个地方的好处就是wx.config配置错误,会弹出窗口哪里错误,然后根据微信文档查询即可。
});
//WXREADY
wx.ready(function () {
//是否支持js接口
wx.checkJsApi({
jsApiList: [
'scanQRCode',
'onMenuShareTimeline',
'onMenuShareAppMessage',
'onMenuShareQQ',
'onMenuShareWeibo'
],
success: function (res) {
if (res.checkResult.scanQRCode) {
}
}
});
});
前台扫码事件
//扫码按钮事件
function ewm() {
wx.scanQRCode({
needResult: 1, // 默认为0,扫描结果由微信处理,1则直接返回扫描结果,
scanType: ["qrCode", "barCode"], // 可以指定扫二维码还是一维码,默认二者都有
success: function (data) {
var res = data.resultStr; // 当needResult 为 1 时,扫码返回的结果
app.callAjaxPost({ url: "../User/SignIn", param: { code: res } }, function (result) {
if (result.state == "error") {
mui.alert(result.message);
}
if (result.state == "success") {
mui.toast(result.message);
}
});
}
});
}
后台页面
public ActionResult Signature(string url)
{
string appid = AppConfig.AppId;
string secet = AppConfig.AppSecret;
object accessToken = SessionHelper.GetSession("access_token");
if (accessToken == null)
{
string accessTokenRequest = WxApi.GetAccessToken(appid, secet);
AccessTokenResult result = accessTokenRequest.ToObject();
accessToken = result.access_token;
SessionHelper.AddSession("access_token", result.access_token, 7200); //缓存access_Token
}
#region JSAPI权签
string timestamp = TimeHelper.ConvertToTimeStamp(DateTime.Now).ToString(); //生成签名的时间戳
string nonceStr = RandomHelper.GetRandCode(16); //生成签名的随机串
//string baseUrl = Configs.GetValue("DefultUrl"); //当前的地址
object jsapiticket = SessionHelper.GetSession("jsapi_ticket");
string ticketStr = string.Empty;
//ticket 缓存7200秒
if (jsapiticket == null)
{
ticketStr = WxApi.GetJsapiTicket(accessToken.ToString());
WxAccessToken token = ticketStr.ToObject();
if (token.errcode == 40001)
{
LogUtil.WriteInfoLog("获取JsApi权签失败");
return ErrorMsg("获取JsApi权签失败");
}
jsapiticket = token.ticket;
SessionHelper.AddSession("jsapi_ticket", token.ticket, 7200);
}
else
{
jsapiticket = SessionHelper.GetSession("jsapi_ticket").ToString();
}
try
{
string signature = WxApi.ToSignature(jsapiticket.ToString(), timestamp, nonceStr, url);
var data = new
{
appid = AppConfig.AppId,
timestamp = timestamp,
noncestr = nonceStr,
signature = signature.ToLower(),
jsapi_ticket = jsapiticket
};
LogUtil.WriteInfoLog(data.ToJson());
return SuccessMsg("获取JsApi权签成功", data);
}
catch (Exception e)
{
LogUtil.WriteInfoLog(e);
}
return ErrorMsg("系统报错");
#endregion
}