DBMNG数据库管理与应用

才能是来自独创性。独创性是思维、观察、理解和判断的一种独特的方式。
当前位置:首页 > 移动应用 > 微信开发

最新微信JS-SDK签名验证方法的java实现

doc: http://mp.weixin.qq.com/wiki/7/aaa137b55fb2e0456bf8dd9148dd613f.html
demo:http://demo.open.weixin.qq.com/jssdk/
sandbox:http://mp.weixin.qq.com/debug/cgi-bin/sandbox?t=jsapisign

生成签名之前必须先了解一下jsapi_ticket,jsapi_ticket是公众号用于调用微信JS接口的临时票据。正常情况下,jsapi_ticket的有效期为7200秒,通过access_token来获取。由于获取jsapi_ticket的api调用次数非常有限,频繁刷新jsapi_ticket会导致api调用受限,影响自身业务,开发者必须在自己的服务全局缓存jsapi_ticket 。
参考以下文档获取access_token(有效期7200秒,开发者必须在自己的服务全局缓存access_token):
用第一步拿到的access_token 采用http GET方式请求获得jsapi_ticket(有效期7200秒,开发者必须在自己的服务全局缓存jsapi_ticket):

https://api.weixin.qq.com/cgi-bin/ticket/getticket?access_token=ACCESS_TOKEN&type=jsapi

注意事项

1.设置JS接口安全域名
2.签名用的noncestr和timestamp必须与wx.config中的nonceStr和timestamp相同。
3.签名用的url必须是调用JS接口页面的完整URL。
4.出于安全考虑,开发者必须在服务器端实现签名的逻辑。

JAVA实现

001public class WxSign {
002    @SuppressWarnings({ "unchecked", "unchecked" })
003    public static void main(String[] args) throws Exception {
004        /*
005        String  access_token= WeChat.getAccessToken();
006        String jsapi_ticket = WeChat.getJsApiTicket(access_token);
007        */
008        //System.out.println("access_token : "+access_token+ " jsapi_ticket: " +jsapi_ticket);
009        String jsapi_ticket="jsapi_ticket";
010        String url = "http://cmsplus.com.cn";
011        Map<String, String> ret = sign(jsapi_ticket, url);
012        for (Map.Entry entry : ret.entrySet()) {
013            //System.out.println(entry.getKey() + "======== " + entry.getValue());
014        }
015        System.out.println("signature:  "+ret.get("signature") +  ": timestamp " +ret.get("timestamp"));
016        System.out.println(createLinkString(ret));
017    };
018 
019    //对所有待签名参数按照字段名的ASCII 码从小到大排序(字典序)后
020     /**
021     * 把数组所有元素排序,并按照“参数=参数值”的模式用“&”字符拼接成字符串
022     * @param params 需要排序并参与字符拼接的参数组
023     * @return 拼接后字符串
024     */
025    public static String createLinkString(Map<String, String> params) {
026        List<String> keys = new ArrayList<String>(params.keySet());
027        Collections.sort(keys);
028        String prestr = "";
029        for (int i = 0; i < keys.size(); i++) {
030            String key = keys.get(i);
031            String value = params.get(key);
032            if (i == keys.size() - 1) {//拼接时,不包括最后一个&字符
033                prestr = prestr + key + "=" + value;
034            } else {
035                prestr = prestr + key + "=" + value + "&";
036            }
037        }
038        return prestr;
039    }
040     
041    public static Map<String, String> sign(String jsapi_ticket, String url) {
042        Map<String, String> ret = new HashMap<String, String>();
043        String nonce_str = create_nonce_str();
044        String timestamp = create_timestamp();
045        String string1;
046        String signature = "";
047        // 注意这里参数名必须全部小写,且必须有序
048        string1 = "jsapi_ticket=" + jsapi_ticket + "&noncestr=" + nonce_str + "&timestamp=" + timestamp + "&url=" + url;
049        //System.out.println(string1);
050        try {
051            MessageDigest crypt = MessageDigest.getInstance("SHA-1");
052            crypt.reset();
053            crypt.update(string1.getBytes("UTF-8"));
054            signature = byteToHex(crypt.digest());
055        } catch (NoSuchAlgorithmException e) {
056            e.printStackTrace();
057        } catch (UnsupportedEncodingException e) {
058            e.printStackTrace();
059        }
060        ret.put("url", url);
061        ret.put("jsapi_ticket", jsapi_ticket);
062        ret.put("nonceStr", nonce_str);
063        ret.put("timestamp", timestamp);
064        ret.put("signature", signature);
065        return ret;
066    }
067 
068    private static String byteToHex(final byte[] hash) {
069        Formatter formatter = new Formatter();
070        for (byte b : hash) {
071            formatter.format("%02x", b);
072        }
073        String result = formatter.toString();
074        formatter.close();
075        return result;
076    }
077 
078    private static String create_nonce_str() {
079        return UUID.randomUUID().toString();
080    }
081 
082    private static String create_timestamp() {
083        return Long.toString(System.currentTimeMillis() / 1000);
084    }
085}
086public class WeChat {
087    private static final String ACCESSTOKEN_URL = "https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential";
088    private static final String PAYFEEDBACK_URL = "https://api.weixin.qq.com/payfeedback/update";
089    /**
090     * 获取access_token
091     *
092     * @return
093     * @throws Exception
094     */
095    public static String getAccessToken() throws Exception {
096        String appid = ConfKit.get("AppId");
097        String secret = ConfKit.get("AppSecret");
098        String jsonStr = HttpKit.get(ACCESSTOKEN_URL.concat("&appid=") + appid + "&secret=" + secret);
099        Map<String, Object> map = JSONObject.parseObject(jsonStr);
100        return map.get("access_token").toString();
101    }
102     
103    /**
104     * 获取jsapi_ticket
105     *
106     * @return
107     * @throws Exception
108     */
109    public static String getJsApiTicket(String accessToken) throws Exception {
110        String jsonStr = HttpKit.get("https://api.weixin.qq.com/cgi-bin/ticket/getticket?access_token="+accessToken+"&type=jsapi");
111        Map<String, Object> map = JSONObject.parseObject(jsonStr);
112        return map.get("ticket").toString();
113    }
114 
115    /**
116     * 获取access_token
117     *
118     * @return
119     * @throws Exception
120     */
121    public static String getAccessToken(String appid, String secret) throws Exception {
122        String jsonStr = HttpKit.get(ACCESSTOKEN_URL.concat("&appid=") + appid + "&secret=" + secret);
123        Map<String, Object> map = JSONObject.parseObject(jsonStr);
124        return map.get("access_token").toString();
125    }
126 
127    /**
128     * 支付反馈
129     *
130     * @param openid
131     * @param feedbackid
132     * @return
133     * @throws Exception
134     */
135    public static boolean payfeedback(String openid, String feedbackid) throws Exception {
136        Map<String, String> map = new HashMap<String, String>();
137        String accessToken = getAccessToken();
138        map.put("access_token", accessToken);
139        map.put("openid", openid);
140        map.put("feedbackid", feedbackid);
141        String jsonStr = HttpKit.get(PAYFEEDBACK_URL, map);
142        Map<String, Object> jsonMap = JSONObject.parseObject(jsonStr);
143        return "0".equals(jsonMap.get("errcode").toString());
144    }
145 
146    /**
147     * 判断是否来自微信, 5.0 之后的支持微信支付
148     *
149     * @param request
150     * @return
151     */
152    public static boolean isWeiXin(HttpServletRequest request) {
153        String userAgent = request.getHeader("User-Agent");
154        if (StringUtils.isNotBlank(userAgent)) {
155            Pattern p = Pattern.compile("MicroMessenger/(\\d+).+");
156            Matcher m = p.matcher(userAgent);
157            String version = null;
158            if (m.find()) {
159                version = m.group(1);
160            }
161            return (null != version && NumberUtils.toInt(version) >= 5);
162        }
163        return false;
164    }



javascript


01wx.config({
02        debug: false,
03        appId: '${appId}',
04        timestamp: '${timestamp}',
05        nonceStr: '${nonceStr}',
06        signature: '${signature}',
07        jsApiList: [
08        'checkJsApi',
09        'onMenuShareTimeline',
10        'onMenuShareAppMessage',
11        'onMenuShareQQ',
12        'onMenuShareWeibo',
13        'hideMenuItems',
14        'showMenuItems',
15        'hideAllNonBaseMenuItem',
16        'showAllNonBaseMenuItem',
17        'translateVoice',
18        'startRecord',
19        'stopRecord',
20        'onRecordEnd',
21        'playVoice',
22        'pauseVoice',
23        'stopVoice',
24        'uploadVoice',
25        'downloadVoice',
26        'chooseImage',
27        'previewImage',
28        'uploadImage',
29        'downloadImage',
30        'getNetworkType',
31        'openLocation',
32        'getLocation',
33        'hideOptionMenu',
34        'showOptionMenu',
35        'closeWindow',
36        'scanQRCode',
37        'chooseWXPay',
38        'openProductSpecificView',
39        'addCard',
40        'chooseCard',
41        'openCard'
42        ]
43        });
44        wx.ready(function () {
45            var shareData = {
46                title: '这是活动的介绍页',
47                desc: '这里是发送给好友的时候的简介',
49                imgUrl: 'http://demo.open.weixin.qq.com/jssdk/images/p2166127561.jpg',
50            };
51             //wx.onMenuShareAppMessage(shareData);
52             wx.onMenuShareAppMessage({
53                  title: '互联网之子',
54                  desc: '在长大的过程中,我才慢慢发现,我身边的所有事,别人跟我说的所有事,那些所谓本来如此,注定如此的事,它们其实没有非得如此,事情是可以改变的。更重要的是,有些事既然错了,那就该做出改变。',
55                  link: 'http://movie.douban.com/subject/25785114/',
56                  imgUrl: 'http://demo.open.weixin.qq.com/jssdk/images/p2166127561.jpg',
57                  trigger: function (res) {
58                    // 不要尝试在trigger中使用ajax异步请求修改本次分享的内容,因为客户端分享操作是一个同步操作,这时候使用ajax的回包会还没有返回
59                    alert('用户点击发送给朋友');
60                  },
61                  success: function (res) {
62                    alert('已分享');
63                  },
64                  cancel: function (res) {
65                    alert('已取消');
66                  },
67                  fail: function (res) {
68                    alert(JSON.stringify(res));
69                  }
70                });
71            wx.onMenuShareTimeline(shareData);
72            // 要隐藏的菜单项,只能隐藏“传播类”和“保护类”按钮,所有menu项见附录3
73            wx.hideMenuItems({
74                menuList: [
75                           'menuItem:copyUrl'
76                          ]
77            });
78            //hide
79            //wx.hideAllNonBaseMenuItem();
80            //wx.hideOptionMenu();
81        });
82        wx.error(function (res) {
83            alert("error: "+ res.errMsg);
84        });

实现隐藏复制链接,分享的时候改变分析的地址与内容等,其他接口按照文档来吧,没什么复杂滴。

其他语言实现

Nodejs实现:http://www.57kan.com/show/index/id/15907
https://github.com/willian12345/wechat-JS-SDK-demo
PHP实现:https://github.com/wjfz/weixin-jssdk


Refer:  微信js sdk invalid signature签名错误 问题解决:http://www.2cto.com/weixin/201503/380936.html

本站文章内容,部分来自于互联网,若侵犯了您的权益,请致邮件chuanghui423#sohu.com(请将#换为@)联系,我们会尽快核实后删除。
Copyright © 2006-2025 DBMNG.COM All Rights Reserved. Powered by DEVSOARTECH            豫ICP备11002312号-2

豫公网安备 41010502002439号