微信公众号 JS SDK config 签名错误,求助

shiziwen
  • 334

发现之前的分享JS已经失效,查了一下资料,说是需要使用微信JS-SDK才能自定义分享。
在使用JS-SDK的时候,通过config接口注入权限验证配置一直报invalid signature签名错误。

微信官方提供的验证签名算法的链接如下:
http://mp.weixin.qq.com/debug/cgi-bin/sandbox?t=jsapisign
对比了一下结果,相同的参数,得到的sign值是一样的。

我是使用ajax调用服务端接口实现加密和配置的,服务端直接返回config结构:

javascriptfunction GetWeiXinJsapiConfig() {
    var url = encodeURIComponent(location.href.split('#')[0]);
    alert('url is ' + url);
    $.ajax({
        type: "POST",
        url: "/XXX/GetWeiXinJsapiConfig",
        data: "{'curUrl': '" + url +
            "'}",
        contentType: "application/json; charset=utf-8",
        dataType: "json",
        success: function(data) {
            console.log(data.d);
            var configData = $.parseJSON(data.d);
            console.log('sig is ' + configData.signature);
            wx.config({
                debug: true, // 开启调试模式,调用的所有api的返回值会在客户端alert出来,若要查看传入的参数,可以在pc端打开,参数信息会通过log打出,仅在pc端时才会打印。
                appId: configData.appid, // 必填,公众号的唯一标识
                timestamp: configData.timestamp, // 必填,生成签名的时间戳
                nonceStr: configData.noncestr, // 必填,生成签名的随机串
                signature: configData.signature, // 必填,签名,见附录1
                jsApiList: ['onMenuShareTimeline', 'onMenuShareAppMessage'] // 必填,需要使用的JS接口列表,所有JS接口列表见附录2
            });
            wx.ready(function(){
                alert('OK---');
                wx.onMenuShareAppMessage({
                    title: shareTitle, // 分享标题
                    desc: descContent, // 分享描述
                    link: lineLink, // 分享链接
                    imgUrl: imgUrl, // 分享图标
                    success: function () { 
                        // 用户确认分享后执行的回调函数
                    },
                    cancel: function () { 
                       // 用户取消分享后执行的回调函数
                    }
                });

            });
            wx.error(function(res){
                // alert("err" + res);
            });
        },
        error: function(data) {
            var is_json;
            var json;
            try {
                var json = $.parseJSON(data.responseText);
                is_json = true;
            } catch (e) {
                is_json = false;
            }

            if (is_json) {
                // add_json_error(data, json);
                console.log(json.Message);
            } else {
                // Show the response text as plaintext.
                var status = data.status;
                var statusText = data.statusText;

                // If we've hit a 400 (Bad Request), show the responseText.
                if (status === 400) {
                    statusText += ": " + data.responseText;
                }
                console.log(status + " " + statusText);
            }
        },
        complete: function() {

        }
    });
}

这是服务端返回的json:

javascript{
"appid":"wxab33b5f4670fdb6e",
"timestamp": "1430853479",
"noncestr": "WecWkTYHZw4WRR0f",
"signature":"b61dec1347cea32e029283209df618709a6c9b0a"
}

已经调试了一天了,还是没有进展,求助。
不知道大家有没有遇到类似的问题,多谢。

下面是调试时的一些记录:
noncestr: "Nr1KncfjMAULdy2v"
jsapi_ticket: "sM4AOVdWfPE4DxkXGEs8VAM6b3b2DY72qJymJD2HDauxX1-fxTB1E-eWx3o1ZfI6kFZjMBHQP6NDrRTBlLeZbw"
timestamp:"1430851580"
url: "http%3A%2F%2Fm.yanchuyi.com%2Fwx%2Fpiao%2Fticket_841_test.html"

sign: "72bff8854ffda1d20999c054663a746f26a7613a"

回复
阅读 22.7k
5 个回答
imhui
  • 82
✓ 已被采纳

服务端签名的时候有没有对参数'curUrl'做urldecode?

黒之染
  • 3.1k

appid对应的公众号的JS接口安全域名填对了没,我第一次也是,代码对比过很多次了,过了两天才发现,我填的appid是服务号的,却在订阅号里设置这个安全域名。改过来就成功了

   /**
   *@author iMouseWu
   *未考虑线程安全
   **/
    public class WeiXinController  {

private static final String appid = "";

private static final String secret = "";

private static final String noncestr = "Wm3WZYTPz0wzccnW";

private static final String TOKENGET_URL = "https://api.weixin.qq.com/cgi-bin/token";

private static final String TICKET_URL = "https://api.weixin.qq.com/cgi-bin/ticket/getticket";

private static Info tokenCache;

private static final long TICKET_EXPIRES_IN = 7200;

private static Info ticketCache;

private static final Logger logger = LoggerFactory
        .getLogger(ItemCenterController.class);

public Map<String, String> gainSign(
        @RequestParam(value = "url", required = true) String url) {
    Map<String, String> result = null;
    try {
        if (null == ticketCache || ticketCache.isExpire()) {
            logger.info("refreshTicket at" + new Date());
            refreshTicketAndPutInCache();
        }

        String ticket = ticketCache.getInfo();
        long timestamp = System.currentTimeMillis();

        String sign = createSign(ticket, url, timestamp);
        result = creatResult(timestamp, sign);

    } catch (Exception e) {
        logger.error("error when call #WeiXinController# gainSign", e);
        creatResult(0, "");
    }
    return result;
}

private void refreshTicketAndPutInCache() throws IOException {
    String token = gainTokenAndPutInCache();

    String response = gainTicketResponse(token);
    JSONObject json = JSON.parseObject(response);
    String ticket = json.getString("ticket");
    if (null == ticket) {
        throw new RuntimeException("ticket is null the response is "
                + response);
    }
    ticketCache = new Info(ticket, TICKET_EXPIRES_IN);
}

private String gainTicketResponse(String token) throws IOException {
    Map<String, String> params = new HashMap<String, String>();
    params.put("access_token", token);
    params.put("type", "jsapi");
    return WebUtils.doGet(TICKET_URL, params);
}

private String gainTokenAndPutInCache() throws IOException {
    if (null != tokenCache && !tokenCache.isExpire()) {
        return tokenCache.getInfo();
    }
    logger.info("gainToken at" + new Date());
    String response = gainTokenResponse();
    JSONObject json = JSON.parseObject(response);
    String token = json.getString("access_token");
    if (null == token) {
        throw new RuntimeException("token is null the response is "
                + response);
    }
    Long expiresIn = json.getLong("expires_in");
    if (null == expiresIn) {
        expiresIn = 0L;
    }
    tokenCache = new Info(token, expiresIn);
    return token;
}

private String gainTokenResponse() throws IOException {
    Map<String, String> params1 = new HashMap<String, String>();
    params1.put("grant_type", "client_credential");
    params1.put("appid", appid);
    params1.put("secret", secret);
    return WebUtils.doGet(TOKENGET_URL, params1);
}

private String createSign(String ticket, String url, long timestamp) {
    String temp = "jsapi_ticket=" + ticket + "&noncestr=" + noncestr
            + "&timestamp=" + timestamp + "&url=" + url;
    return EncryptionUtil.encode(temp);
}

private Map<String, String> creatResult(long timestamp, String sign) {
    Map<String, String> result = new HashMap<String, String>();
    result.put("appid", appid);
    result.put("timestamp", timestamp + "");
    result.put("nonceStr", noncestr);
    result.put("signature", sign);
    return result;
}

/**
 * 承载信息的类
 * 
 * @author iMouseWu
 *
 */
private class Info {

    private String info;

    private long expireTime;

    public Info(String info, long expiresIn) {
        this.info = info;
        this.expireTime = System.currentTimeMillis() + expiresIn * 1000
                - 100 * 1000;
    }

    public String getInfo() {
        return info;
    }

    public boolean isExpire() {
        return System.currentTimeMillis() > expireTime;
    }
}

}

这是我前几天写的。不知道对你有没有帮助

疯狂的蜗牛
  • 4
新手上路,请多包涵

签名和官方的一样、 URL也是通过location.href.split('#')[0]获取的。。 也是一直提示 config:invalid signature 公众号的JS接口安全域名也是配置OK,就是不行。。 求大神帮助、
测试地址:http://weixin.zhjckx.com/ApiWeiXin/JsSdk

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
宣传栏