zoukankan      html  css  js  c++  java
  • 微信jssdk 返回的 config invalid signature

       这几天一直在调试wxjssdk,按照api的需求,http://mp.weixin.qq.com/wiki/7/aaa137b55fb2e0456bf8dd9148dd613f.html ,先是根据appid和秘钥获取access_token并存入缓存:注意的是 此处的appid 和 秘钥 是 微信公众平台的appid(区别于微信开放平台,开放平台无法设置域名)。

    public final String sharing(String url, HttpServletResponse response) {
            StringBuilder stringBuilder = new StringBuilder();
            Map<String,String> resMap = new HashMap<String, String>();
            //返回给app端
            net.sf.json.JSONObject jb = new net.sf.json.JSONObject();
            net.sf.json.JSONObject data = new net.sf.json.JSONObject();
            try {
                if (url.contains("#")){
                    url = url.substring(0,url.indexOf("#")); //不需要获取后面的#的内容
                }
                Map<String,String> ecPaymentMap = myPayService.findPaymentTypeListInfo(PAYMENT_TYPE_ID);
                String accessToken = cacheUtil.readCache("access_token"); //获取token
                if (StringUtil.isEmpty(accessToken)){
                    Map<String,String> getTokenMap = new HashMap<String, String>();
                    getTokenMap.put("grant_type","client_credential"); //获取access_token填写client_credential
                    getTokenMap.put("appid", ecPaymentMap.get("appId")); //第三方用户唯一凭证
                    getTokenMap.put("secret",ecPaymentMap.get("appKey")); //第三方用户唯一凭证密钥,
                    String resTokenData = HttpClientTools.doGet(WXURLConstant.ACCESSTOKENURL, getTokenMap);
                    if (StringUtil.isEmpty(resTokenData)){
                        logger.error("WXJs Token is null");
                        throw new RuntimeException();
                    }
                    JSONObject jsonObject = JSONObject.parseObject(resTokenData);
                    logger.info("WXJs resData" + jsonObject);
    
                    if (jsonObject.get("access_token") !=null){
                        cacheUtil.setCache("access_token",jsonObject.get("access_token").toString(),Integer.valueOf(jsonObject.get("expires_in").toString()));
                    }else {
                        logger.error("get WXJs token error,errorCode: " + jsonObject.get("errcode"));
                    }
                    accessToken=cacheUtil.readCache("access_token");
                }
                String jsapiTicket = cacheUtil.readCache("jsapiTicket"); //获取jsapiTicket
                if (StringUtil.isEmpty(jsapiTicket)){
                    Map<String,String> map = new HashMap<String, String>(); //请求获取JS-SDK使用权限签名算法
                    map.put("access_token",accessToken); //请求参数access_token
                    map.put("type","jsapi"); //请求参数type 固定
                   String ticketResData = HttpClientTools.doGet(WXURLConstant.JSAPITICKET, map);
                    if (StringUtil.isEmpty(ticketResData)){
                        logger.error("requestData is null");
                        return null;
                    }
                    JSONObject jsonObject = JSONObject.parseObject(ticketResData);
    
                    if (!"0".equals(jsonObject.get("errcode").toString())){
                        logger.error("WX get jsapiTicket error" + jsonObject.toString());
                        jb.element("status", 002);
                        jb.element("msg", "jsapi error");
                        data.element("data",jsonObject);
                        jb.put("data",data);
                        stringBuilder.append(jb);
                        response.resetBuffer();
                        response.setContentType("text/html;charset=UTF-8");
                        response.getWriter().print(stringBuilder);
                        response.getWriter().flush();
                        response.getWriter().close();
                        response.flushBuffer();
                        return stringBuilder.toString();
                    }
                    cacheUtil.setCache("jsapiTicket",jsonObject.get("ticket").toString(),WXJSSDKConstant.EXPIRETIME); //缓存2个小时 其实有自动任务一个小时会执行一次 防止过期
                    jsapiTicket = jsonObject.get("ticket").toString();
                }
                String timestamp = String.valueOf(System.currentTimeMillis()/1000);
                String nonceStr = TenpayUtil.getNonceStr();
                Map<String,String> requestSignMap = new HashMap<String, String>(); //后去signature
                requestSignMap.put("noncestr", nonceStr);
                requestSignMap.put("jsapi_ticket",jsapiTicket);
                requestSignMap.put("timestamp",timestamp);
                requestSignMap.put("url",url);
                String signature = "";
                try {
                    signature = WXUtil.sha1Sign(requestSignMap);
                } catch (JDOMException e) {
                    e.printStackTrace();
                }
    
                //增加签名
                jb.element("status", 0);
                jb.element("msg", "OK");
                resMap.put("appId", ecPaymentMap.get("appId"));
                resMap.put("timestamp", timestamp);
                resMap.put("nonceStr", nonceStr);
                resMap.put("signature", signature);
                data.element("data",resMap);
                jb.element("data", data);
                stringBuilder.append(jb.toString());
                response.resetBuffer();
                response.setContentType("text/html;charset=UTF-8");
                response.getWriter().print(stringBuilder.toString());
                response.getWriter().flush();
                response.getWriter().close();
                response.flushBuffer();
    
            } catch (IOException e) {
                e.printStackTrace();
            }
            return stringBuilder.toString();
        }

    第二步 是根据acces_token获取jsapi_ticket并存入缓存,注意此处的参数type要是jsapi,还有一个获取卡卷的接口,此处容易出错 

    第三部 就是根据jsapiticket 来获取signature,参数主要是16位随机数,ticket  时间串(注意此处的格式是秒) url (注意路径:传递的时候需要转码,后台后去的时候需要解码,这个一定要注意了,好多人在这上面被坑的。。。)

    noncestr
    jsapi_ticket
    timestamp
    url
    第四步 把获得的结果传到前台即可



    遇到的问题,主要是 报这个 config invalid signature

      用jsskd自带的签名工具验签 发现没有问题,但是无论如何就是报签名错误。然后google了好多,最后发现原来是url的问题: 前端需要转码 需要转码 需要转码 ,后台需要解码 需要解码 需要解码。

      前端:url在JavaScript中千万别忘记“encodeURIComponent”!

            url在JavaScript中千万别忘记“encodeURIComponent”!

            url在JavaScript中千万别忘记“encodeURIComponent”!

    后台:

    public String sharing(HttpServletRequest request, HttpServletResponse response){
            String url = request.getParameter("url"); //分享链接url
            try {
                logger.info("beforeDecode:" + url);
                url = URLDecoder.decode(url,"utf-8");
                logger.info("afterEncode:" + url);
            } catch (UnsupportedEncodingException e) {
                e.printStackTrace();
            }
            return wXSharingService.sharing(url,response);
        }
    

      

    
    
  • 相关阅读:
    刷题总结——宠物收养所(bzoj1208)
    算法复习——trie树(poj2001)
    刷题总结——bzoj2243染色
    算法复习——虚树(消耗战bzoj2286)
    设置SSH自动登陆(免密码,用户名)
    自旋锁Spin lock与互斥锁Mutex的区别
    如何去除Linux文件的^M字符
    重构
    比赛日程安排
    基于libzip的简易压缩(zip)/解压缩(unzip)程序
  • 原文地址:https://www.cnblogs.com/thinkingandworkinghard/p/6590957.html
Copyright © 2011-2022 走看看