微信JS-SDK签名验证

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实现

public class WxSign {
    @SuppressWarnings({ "unchecked", "unchecked" })
    public static void main(String[] args) throws Exception {
        /*
        String  access_token= WeChat.getAccessToken();
        String jsapi_ticket = WeChat.getJsApiTicket(access_token);
        */
        //System.out.println("access_token : "+access_token+ " jsapi_ticket: " +jsapi_ticket);
        String jsapi_ticket="jsapi_ticket";
        String url = "http://cmsplus.com.cn";
        Map<String, String> ret = sign(jsapi_ticket, url);
        for (Map.Entry entry : ret.entrySet()) {
            //System.out.println(entry.getKey() + "======== " + entry.getValue());
        }
        System.out.println("signature:  "+ret.get("signature") +  ": timestamp " +ret.get("timestamp"));
        System.out.println(createLinkString(ret));
    };

    //对所有待签名参数按照字段名的ASCII 码从小到大排序(字典序)后
     /**
     * 把数组所有元素排序,并按照“参数=参数值”的模式用“&”字符拼接成字符串
     * @param params 需要排序并参与字符拼接的参数组
     * @return 拼接后字符串
     */
    public static String createLinkString(Map<String, String> params) {
        List<String> keys = new ArrayList<String>(params.keySet());
        Collections.sort(keys);
        String prestr = "";
        for (int i = 0; i < keys.size(); i++) {
            String key = keys.get(i);
            String value = params.get(key);
            if (i == keys.size() - 1) {//拼接时,不包括最后一个&字符
                prestr = prestr + key + "=" + value;
            } else {
                prestr = prestr + key + "=" + value + "&";
            }
        }
        return prestr;
    }

    public static Map<String, String> sign(String jsapi_ticket, String url) {
        Map<String, String> ret = new HashMap<String, String>();
        String nonce_str = create_nonce_str();
        String timestamp = create_timestamp();
        String string1;
        String signature = "";
        // 注意这里参数名必须全部小写,且必须有序
        string1 = "jsapi_ticket=" + jsapi_ticket + "&noncestr=" + nonce_str + "&timestamp=" + timestamp + "&url=" + url;
        //System.out.println(string1);
        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("jsapi_ticket", jsapi_ticket);
        ret.put("nonceStr", nonce_str);
        ret.put("timestamp", timestamp);
        ret.put("signature", signature);
        return ret;
    }

    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 create_nonce_str() {
        return UUID.randomUUID().toString();
    }

    private static String create_timestamp() {
        return Long.toString(System.currentTimeMillis() / 1000);
    }
}
public class WeChat {
    private static final String ACCESSTOKEN_URL = "https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential";
    private static final String PAYFEEDBACK_URL = "https://api.weixin.qq.com/payfeedback/update";
    /**
     * 获取access_token
     *
     * @return
     * @throws Exception
     */
    public static String getAccessToken() throws Exception {
        String appid = ConfKit.get("AppId");
        String secret = ConfKit.get("AppSecret");
        String jsonStr = HttpKit.get(ACCESSTOKEN_URL.concat("&appid=") + appid + "&secret=" + secret);
        Map<String, Object> map = JSONObject.parseObject(jsonStr);
        return map.get("access_token").toString();
    }

    /**
     * 获取jsapi_ticket
     *
     * @return
     * @throws Exception
     */
    public static String getJsApiTicket(String accessToken) throws Exception {
        String jsonStr = HttpKit.get("https://api.weixin.qq.com/cgi-bin/ticket/getticket?access_token="+accessToken+"&type=jsapi");
        Map<String, Object> map = JSONObject.parseObject(jsonStr);
        return map.get("ticket").toString();
    }

    /**
     * 获取access_token
     *
     * @return
     * @throws Exception
     */
    public static String getAccessToken(String appid, String secret) throws Exception {
        String jsonStr = HttpKit.get(ACCESSTOKEN_URL.concat("&appid=") + appid + "&secret=" + secret);
        Map<String, Object> map = JSONObject.parseObject(jsonStr);
        return map.get("access_token").toString();
    }

    /**
     * 支付反馈
     *
     * @param openid
     * @param feedbackid
     * @return
     * @throws Exception
     */
    public static boolean payfeedback(String openid, String feedbackid) throws Exception {
        Map<String, String> map = new HashMap<String, String>();
        String accessToken = getAccessToken();
        map.put("access_token", accessToken);
        map.put("openid", openid);
        map.put("feedbackid", feedbackid);
        String jsonStr = HttpKit.get(PAYFEEDBACK_URL, map);
        Map<String, Object> jsonMap = JSONObject.parseObject(jsonStr);
        return "0".equals(jsonMap.get("errcode").toString());
    }

    /**
     * 判断是否来自微信, 5.0 之后的支持微信支付
     *
     * @param request
     * @return
     */
    public static boolean isWeiXin(HttpServletRequest request) {
        String userAgent = request.getHeader("User-Agent");
        if (StringUtils.isNotBlank(userAgent)) {
            Pattern p = Pattern.compile("MicroMessenger/(\\d+).+");
            Matcher m = p.matcher(userAgent);
            String version = null;
            if (m.find()) {
                version = m.group(1);
            }
            return (null != version && NumberUtils.toInt(version) >= 5);
        }
        return false;
    }

javascript

wx.config({
        debug: false,
        appId: ‘${appId}‘,
        timestamp: ‘${timestamp}‘,
        nonceStr: ‘${nonceStr}‘,
        signature: ‘${signature}‘,
        jsApiList: [
        ‘checkJsApi‘,
        ‘onMenuShareTimeline‘,
        ‘onMenuShareAppMessage‘,
        ‘onMenuShareQQ‘,
        ‘onMenuShareWeibo‘,
        ‘hideMenuItems‘,
        ‘showMenuItems‘,
        ‘hideAllNonBaseMenuItem‘,
        ‘showAllNonBaseMenuItem‘,
        ‘translateVoice‘,
        ‘startRecord‘,
        ‘stopRecord‘,
        ‘onRecordEnd‘,
        ‘playVoice‘,
        ‘pauseVoice‘,
        ‘stopVoice‘,
        ‘uploadVoice‘,
        ‘downloadVoice‘,
        ‘chooseImage‘,
        ‘previewImage‘,
        ‘uploadImage‘,
        ‘downloadImage‘,
        ‘getNetworkType‘,
        ‘openLocation‘,
        ‘getLocation‘,
        ‘hideOptionMenu‘,
        ‘showOptionMenu‘,
        ‘closeWindow‘,
        ‘scanQRCode‘,
        ‘chooseWXPay‘,
        ‘openProductSpecificView‘,
        ‘addCard‘,
        ‘chooseCard‘,
        ‘openCard‘
        ]
        });
        wx.ready(function () {
            var shareData = {
                title: ‘这是活动的介绍页‘,
                desc: ‘这里是发送给好友的时候的简介‘,
                link: ‘http://mp.weixin.qq.com/wiki/7/aaa137b55fb2e0456bf8dd9148dd613f.html‘,
                imgUrl: ‘http://demo.open.weixin.qq.com/jssdk/images/p2166127561.jpg‘,
            };
             //wx.onMenuShareAppMessage(shareData);
             wx.onMenuShareAppMessage({
                  title: ‘互联网之子‘,
                  desc: ‘在长大的过程中,我才慢慢发现,我身边的所有事,别人跟我说的所有事,那些所谓本来如此,注定如此的事,它们其实没有非得如此,事情是可以改变的。更重要的是,有些事既然错了,那就该做出改变。‘,
                  link: ‘http://movie.douban.com/subject/25785114/‘,
                  imgUrl: ‘http://demo.open.weixin.qq.com/jssdk/images/p2166127561.jpg‘,
                  trigger: function (res) {
                    // 不要尝试在trigger中使用ajax异步请求修改本次分享的内容,因为客户端分享操作是一个同步操作,这时候使用ajax的回包会还没有返回
                    alert(‘用户点击发送给朋友‘);
                  },
                  success: function (res) {
                    alert(‘已分享‘);
                  },
                  cancel: function (res) {
                    alert(‘已取消‘);
                  },
                  fail: function (res) {
                    alert(JSON.stringify(res));
                  }
                });
            wx.onMenuShareTimeline(shareData);
            // 要隐藏的菜单项,只能隐藏“传播类”和“保护类”按钮,所有menu项见附录3
            wx.hideMenuItems({
                menuList: [
                           ‘menuItem:copyUrl‘
                          ]
            });
            //hide
            //wx.hideAllNonBaseMenuItem();
            //wx.hideOptionMenu();
        });
        wx.error(function (res) {
            alert("error: "+ res.errMsg);
        });

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

其他语言实现

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://my.oschina.net/u/2308739/blog/371414

时间: 2024-10-11 06:46:16

微信JS-SDK签名验证的相关文章

实战微信JS SDK开发:贺卡制作与播放(1)

前段时间忙于CanTK 2.0的开发,所以博客一直没有更新.CanTK 2.0主要增强了游戏和富媒体的开发,现在编码和测试基本完成了,等文档完成了再正式发布,里面有不少激动人心的功能,等发布时再一一细说吧. 最近同事用CanTK开发了一个基于微信的贺卡制作APP,我虽然没有参与开发,但是提供CanTK和GameBuilder的技术支持,觉得有些东西比较有意思,写几篇博客和大家分享吧.这个贺卡APP完全开源,有需要的朋友可以随意修改和发布. CanTK(Canvas ToolKit)是一个开源的游

微信js sdk上传多张图片

微信js sdk上传多张图片,微信上传多张图片 该案例已tp3.2商城为例 直接上代码: php代码: public function ind(){ $appid="11111111111111111111"; $secret="11111111111111111111"; $token = S('access_token'); if (!$token) { $res = file_get_contents("https://api.weixin.qq.c

微信JS SDK开发 共享问题小结

首先,我要吐槽一下这个SDK,看了第一遍,完全不知所云,一会获取这个,一会获取那个,也没确切的告诉怎么获取. 和腾讯客服(拿钱不干事的好工作)讨教,人家不懂技术,不知道怎么解决,也没有相关技术人员对应这一块.总共费时 将近一周的时间才把这块弄懂.期间遇到的部分问题以及如何解决分享给大家,欢迎大家一起讨论并指正. 问题1:JS接口安全域名,你所有想要使用的微信接口,要在这个域名内部进行,不能在本地进行相关调试. 问题2:公众账号要求:必须是已经认证的. 问题3:配置config(PS:开启debu

微信js sdk分享开发摘记java版

绑定域名和引入js的就不说了 废话不说直接上代码 1 public void share(HttpServletRequest request) throws Exception { 2 3 StringBuffer homeUrl = request.getRequestURL(); 4 String queryString =request.getQueryString(); 5 if(StringUtils.isNotBlank(queryString)){ 6 homeUrl.appen

微信JS SDK配置授权,实现分享接口

微信开放的JS-SDK面向网页开发者提供了基于微信内的网页开发工具包,最直接的好处就是我们可以使用微信分享.扫一扫.卡券.支付等微信特有的能力.7月份的时候,因为这个分享的证书获取问题深深的栽了一坑,后面看到"config:ok"的时候真的算是石头落地,瞬间感觉世界很美好.. 这篇文章是微信开发的很多前置条件,包括了服务端基于JAVA的获取和缓存全局的access_token,获取和缓存全局的jsapi_ticket,以及前端配置授权组件封装,调用分享组件封装. 配置授权思路:首先根据

微信JS SDK使用权限签名算法

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

微信JS SDK Demo

微信JS-SDK 分享到朋友圈 分享给朋友 分享到QQ 拍照或从手机相册中选图 识别音频并返回识别结果 使用微信内置地图查看位置原文:http://www.cnblogs.com/txw1958/p/weixin-js-sdk-demo.html 一.JS部分 wx.ready(function () { // 1 判断当前版本是否支持指定 JS 接口,支持批量判断 document.querySelector('#checkJsApi').onclick = function () { wx.

微信JS SDK PHP Demo

一.JSSDK类定义 <?php class JSSDK { private $appId; private $appSecret; public function __construct($appId, $appSecret) { $this->appId = $appId; $this->appSecret = $appSecret; } public function getSignPackage() { $jsapiTicket = $this->getJsApiTicke

微信 js sdk C# 版 invalid signature 问题解决

采用Senparc.Weixin SDK 服务器端代码: using System; using System.Collections.Generic; using System.Linq; using System.Web; using System.Web.UI; using System.Web.UI.WebControls; using Senparc.Weixin.MP.CommonAPIs; using Senparc.Weixin.MP.Helpers; using Senparc

微信JS SDK Demo 官方案例

转自:http://my.oschina.net/superkangning/blog/367484 微信JS-SDK是微信公众平台面向网页开发者提供的基于微信内的网页开发工具包. 通过使用微信JS-SDK,网页开发者可借助微信高效地使用拍照.选图.语音.位置等手机系统的能力,同时可以直接使用微信分享.扫一扫.卡券.支付等微信特有的能力,为微信用户提供更优质的网页体验. 此文档面向网页开发者介绍微信JS-SDK如何使用及相关注意事项. 一:html代码部分 ? 1 2 3 4 5 6 7 8 9