微信开发 扫一扫接口返回值_微信 调起微信扫一扫接口 - CSDN
  • 微信开放实战--扫一扫功能(详细)

    万次阅读 2017-12-14 23:44:27
    大概流程: 1.根据appId和app...进入微信公众平台码登录测试号公众号:https://mp.weixin.qq.com/debug/cgi-bin/sandbox?t=sandbox/login public static JSONObject getTokenTool(String appId,String appSecr
    大概流程:
    1.根据appId和appSecret获取access_token(使用凭证)
    进入微信公众平台扫码登录测试号公众号:https://mp.weixin.qq.com/debug/cgi-bin/sandbox?t=sandbox/login

    public static JSONObject getTokenTool(String appId,String appSecret){
    String url="https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid="+appId+"&secret="+appSecret;
    System.out.println(HttpRequestUtil.httpRequest(url, "GET", ""));
    return HttpRequestUtil.httpRequest(url, "GET", "");
    }

    这是测试号获取access_token的接口,普通公众号接口地址请查看微信官方文档。



    2.根据access_token获取jsapi_ticket
    public static JSONObject getTicketTool(String access_token){
    String url="https://api.weixin.qq.com/cgi-bin/ticket/getticket?access_token="+access_token+"&type=jsapi";
    System.out.println(HttpRequestUtil.httpRequest(url, "GET", ""));
    return HttpRequestUtil.httpRequest(url, "GET", "");
    }





    3.在微信获取签名算法(具体如下)
    public static Map<String, String> sign(String url) {
    String appId="wxcc42f613dbf7299f";
    String appSecret="e59e10c74c70b1c042b5ecaf454052ac";
    String access_token=getTokenTool(appId, appSecret).getString("access_token");
    JSONObject ticketJson=getTicketTool(access_token);
    System.out.println(ticketJson.toString());
    String jsapi_ticket = ticketJson.getString("ticket");
    Map<String, String> ret = new HashMap<String, String>();
    //这里的jsapi_ticket是获取的jsapi_ticket。
    String nonce_str = create_nonce_str();
    String timestamp = create_timestamp();
    String string1;
    String signature = "";
    System.out.println(2);

    //注意这里参数名必须全部小写,且必须有序
    string1 = "jsapi_ticket=" + jsapi_ticket +
    "&noncestr=" + nonce_str +
    "&timestamp=" + timestamp +
    "&url=" + url;

    try
    {
    MessageDigest crypt = MessageDigest.getInstance("SHA-1");
    crypt.reset();
    crypt.update(string1.getBytes("UTF-8"));
    signature = byteToHex(crypt.digest());
    System.out.println("crypt="+crypt.toString());
    System.out.println("string1="+string1);
    System.out.println("signature="+signature);
    }
    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);
    }

    4.获取一个js安全域名接口(如:gstz.imwork.net
    一般使用花生壳进行内网穿透,使内网地址映射到一个花生壳提供的公网的地址,适合用来测试,花生壳内网穿透如何使用可到花生壳官网查看。





    5.把域名和action的地址拼接起来成url,放入签名方法中


    @Controller
    @SuppressWarnings("serial")
    public class WeixinAction{
    /**
    * 获取签名算法
    */
    @RequestMapping("getSign")
    @ResponseBody
    public JSONObject getSign(){
    JSONObject jsonObject=new JSONObject();
    String url="http://17j62137x0.imwork.net/ssm_d1/index.jsp";
    Map<String, String> ret =WxJSUtil.sign(url);
    System.out.println("map="+ret.toString());
    jsonObject.put("weixin", ret);
    System.out.println("json="+jsonObject.toString());
    return jsonObject;
    }
    }
    6.在JSP页面初始化时异步获取签名action传来3个参数,JSP内容如下




    <%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
    <!DOCTYPE>
    <html>
    <head>
    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
    <title>微信扫一扫</title>
    <script src="http://res.wx.qq.com/open/js/jweixin-1.0.0.js"></script>
    <script type="text/javascript" src="js/jquery-3.2.1.min.js"></script>
    <script type="text/javascript" src="js/weixin.js"></script>
    </head>
    <body>
    <input id="timestamp" type="hidden" value="${timestamp}" />
    <input id="noncestr" type="hidden" value="${nonceStr}" />
    <input id="signature" type="hidden" value="${signature}" />
    <input id="id_securityCode_input">
    <button id="scanQRCode" οnclick="getWeixinResult()">扫码</button>
    </body>
    <script type="text/javascript">
    </script>
    </html>
    7.通过签名算法获取wx.config的4个重要参数:jsapi_ticket、noncestr、timestamp、url
    wx.config({ debug: true,// 开启调试模式,调用的所有api的返回值会在客户端alert出来,若要查看传入的参数,可以在pc端打开,参数信息会通过log打出,仅在pc端时才会打印。 appId:'',// 必填,公众号的唯一标识 timestamp: ,// 必填,生成签名的时间戳 nonceStr:'',// 必填,生成签名的随机串 signature:'',// 必填,签名,见附录1 jsApiList: []// 必填,需要使用的JS接口列表,所有JS接口列表见附录2});



    8.告诉微信选择调用的接口名称



    9.把获取的结果result进行处理getWeixinResultCallBack(param)


    10.给按钮添加 getWeixinResult事件,就可以通过按钮调用扫一扫功能。(记得用微信浏览器点开)


    这是DEMO的下载地址(博主本想免费分享这个资源的,无奈CSDN最少也要2点资源分才能下载):下载DEMO
    展开全文
  • 微信开发 --- 调用微信接口

    千次阅读 2018-11-17 15:31:02
    调用微信扫接口 步骤:绑定域名 微信公众号绑定域名 步骤二:引入JS文件 在需要调用JS接口的页面引入如下JS文件,(支持https):http://res.wx.qq.com/open/js/jweixin-1.0.0.js 请注意,如果你的页面启用...

    调用微信扫码接口

    步骤一:绑定域名

    微信公众号绑定域名

    步骤二:引入JS文件

    在需要调用JS接口的页面引入如下JS文件,(支持https):http://res.wx.qq.com/open/js/jweixin-1.0.0.js

    请注意,如果你的页面启用了https,务必引入 https://res.wx.qq.com/open/js/jweixin-1.0.0.js ,否则将无法在iOS9.0以上系统中成功使用JSSDK

    步骤三:通过config接口注入权限验证配置

    这个是调用微信的重要凭证,你想要掉用微信的接口 必须先得把签名通过,这个方法直接放到javascript里

    wx.config({
        debug: true, // 开启调试模式,调用的所有api的返回值会在客户端alert出来,若要查看传入的参数,可以在pc端打开,参数信息会通过log打出,仅在pc端时才会打印。
        appId: '', // 必填,公众号的唯一标识
        timestamp: , // 必填,生成签名的时间戳
        nonceStr: '', // 必填,生成签名的随机串
        signature: '',// 必填,签名,见附录1
        jsApiList: [] // 必填,需要使用的JS接口列表,所有JS接口列表见附录2
    });
    

    步骤四:通过error接口处理失败验证

    wx.error(function(res){
    
        // config信息验证失败会执行error函数,如签名过期导致验证失败,具体错误信息可以打开config的debug模式查看,也可以在返回的res参数中查看,对于SPA可以在这里更新签名。
    
    });
    

    步骤五:通过ready接口处理成功验证

    wx.ready(function(){
    
        // config信息验证后会执行ready方法,所有接口调用都必须在config接口获得结果之后,config是一个客户端的异步操作,所以如果需要在页面加载时就调用相关接口,则须把相关接口放在ready函数中调用来确保正确执行。对于用户触发时才调用的接口,则可以直接调用,不需要放在ready函数中。
    }); 
    

    基础接口
    判断当前客户端版本是否支持指定JS接口

    wx.checkJsApi({
        jsApiList: ['chooseImage'], // 需要检测的JS接口列表,所有JS接口列表见附录2,
        success: function(res) {
            // 以键值对的形式返回,可用的api值true,不可用为false
            // 如:{"checkResult":{"chooseImage":true},"errMsg":"checkJsApi:ok"}
        }
    });
    

    微信扫一扫
    调起微信扫一扫接口

    wx.scanQRCode({
        needResult: 0, // 默认为0,扫描结果由微信处理,1则直接返回扫描结果,
        scanType: ["qrCode","barCode"], // 可以指定扫二维码还是一维码,默认二者都有
        success: function (res) {
        var result = res.resultStr; // 当needResult 为 1 时,扫码返回的结果
    }
    });
    

    上边就是调用微信扫一扫接口的必要条件了
    下边就要放干货了

    js

    <script  type="text/javascript">
      
    	 $.ajax({
             type : "post",
             url : "weixinList/sys.do",
             data : {
                 "url" : location.href.split('#')[0]
             },
             dataType : "json",
             success : function(data) {
                 wx.config({
                     debug: false, // 开启调试模式   
                     appId:data.data.appId,
                     timestamp:data.data.timestamp,
                     nonceStr:data.data.nonceStr,
                     signature:data.data.signature,
                     jsApiList: [
                                   'checkJsApi',
                                   'scanQRCode'// 微信扫一扫接口
                                ] // 必填,需要使用的JS接口列表,所有JS接口列表见附录2 
                 }); 
                 //wx.config 调不通 执行的方法
                  wx.error(function(res) {
                     alert("出错了:" + res.errMsg);//这个地方的好处就是wx.config配置错误,会弹出窗口哪里错误,然后根据微信文档查询即可。
                 });
                //wx.config 调通 执行的方法
                 wx.ready(function() {
                     wx.checkJsApi({
                          jsApiList : ['scanQRCode'],
                          success : function(res) {
    
                          }
                     });
                 });
                 //点击按钮扫描二维码
                 $("#scanQRCode").click(function(){
                     wx.scanQRCode({
                         needResult : 0, // 默认为0,扫描结果由微信处理,1则直接返回扫描结果,
                         scanType : [ "qrCode", "barCode"], // 可以指定扫二维码还是一维码,默认二者都有
                         success : function(res) {
                        	 var result = res.resultStr; // 当needResult 为 1 时,扫码返回的结果
                         },
                     });
                 });
    
                 
             }
         });
    
    </script>
    

    页面加载时 执行ajax方法 获取到wx.config 需要的参数

    jsp

    <button  id="scanQRCode" >点我 ! 扫描二维码</button>
    

    utils

    package xxx.utils;
     
    /**
     * 官方给的使用js的验证工具
     * @author Administrator
     *
     */
     //url很重要 一定要从前台获取  要不然 生成片名不一致
    public class JsSignUtil {
    	    public static Map<String, String> sign(String url) throws IOException {
    	    //通过AccessToken获取到ticket   AccessToken怎么获取就不粘了
    	        JSONObject jsapiTicketObject = AuthUtil.doGetJson("https://api.weixin.qq.com/cgi-bin/ticket/getticket?access_token=" + WeiXinUtils.getAccessToken() + "&type=jsapi");
    	        String jsapiTicket = (String) jsapiTicketObject.get("ticket");
           
           //下边的就不用看了  直接粘就行
    
    	        System.out.println("微信返回jsapiTicketObject"+jsapiTicketObject);
    	        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=" + jsapiTicket +
    	                "&noncestr=" + nonce_str +
    	                "&timestamp=" + timestamp +
    	                "&url=" + url;
    	        System.out.println("string1="+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", jsapiTicket);
    	        ret.put("nonceStr", nonce_str);
    	        ret.put("timestamp", timestamp);
    	        ret.put("signature", signature);
    	        ret.put("appId", "wxca42d473ba246dd9");
    	 
    	        System.out.println("url="+ret.get("url"));
    	        System.out.println("jsapi_ticket="+ret.get("jsapi_ticket"));
    	        System.out.println("nonceStr="+ret.get("nonceStr"));
    	        System.out.println("signature="+ret.get("signature"));
    	        System.out.println("timestamp="+ret.get("timestamp"));
    	 
    	        return ret;
    	    }
    	 
    	 
    	    /**
    	     * 随机加密
    	     * @param hash
    	     * @return
    	     */
    	    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;
    	    }
    	 
    	    /**
    	     * 产生随机串--由程序自己随机产生
    	     * @return
    	     */
    	    private static String create_nonce_str() {
    	        return UUID.randomUUID().toString();
    	    }
    	 
    	    /**
    	     * 由程序自己获取当前时间
    	     * @return
    	     */
    	    private static String create_timestamp() {
    	        return Long.toString(System.currentTimeMillis() / 1000);
    	    }
    	}
    

    Controller

    @ResponseBody
    @RequestMapping(value="sys")
    	public JsonBean sys(String url) throws IOException {
    		Map<String, String> ret = JsSignUtil.sign(url);
    		return new JsonBean(0,ret,"");
    	}
    

    到现在如果你们运气好的话,点一下按钮应该就行了
    但是
    肯定会遇到这样那样的问题
    比如:invalid signature invalid url domain 这些
    https://mp.weixin.qq.com/wiki?t=resource/res_main&id=mp1421141115
    毕竟我也是找了两天三夜

    老天保佑你 阿门!!!

    展开全文
  • 参考微信JS-SDK说明文档 尽管作用不是很大1.首先在JSP页面引入http://res.wx.qq.com/open/js/jweixin-1.1.0.js2.通过config接口注入权限验证配置

    参考微信JS-SDK说明文档 看到网上很多都说微信的说明文档很坑,在我看来,仔细阅读的话,介绍还是很全的。

    1.首先在JSP页面引入http://res.wx.qq.com/open/js/jweixin-1.1.0.js

    2.通过config接口注入权限验证配置

    wx.config({
        debug: true, // 开启调试模式,调用的所有api的返回值会在客户端alert出来,若要查看传入的参数,可以在pc端打开,参数信息会通过log打出,仅在pc端时才会打印。
        appId: '', // 必填,企业号的唯一标识,此处填写企业号corpid
        timestamp: , // 必填,生成签名的时间戳
        nonceStr: '', // 必填,生成签名的随机串
        signature: '',// 必填,签名,见附录1
        jsApiList: [] // 必填,需要使用的JS接口列表,所有JS接口列表见附录2
    });

    3.通过ready接口处理成功验证

    wx.ready(function(){
        // config信息验证后会执行ready方法,所有接口调用都必须在config接口获得结果之后,config是一个客户端的异步操作,所以如果需要在页面加载时就调用相关接口,则须把相关接口放在ready函数中调用来确保正确执行。对于用户触发时才调用的接口,则可以直接调用,不需要放在ready函数中。
    });

    4.通过error接口处理失败验证

    wx.error(function(res){
        // config信息验证失败会执行error函数,如签名过期导致验证失败,具体错误信息可以打开config的debug模式查看,也可以在返回的res参数中查看,对于SPA可以在这里更新签名。
    });

    5.调起微信扫一扫

    wx.scanQRCode({
        desc: 'scanQRCode desc',
        needResult: 0, // 默认为0,扫描结果由微信处理,1则直接返回扫描结果,
        scanType: ["qrCode","barCode"], // 可以指定扫二维码还是一维码,默认二者都有
        success: function (res) {
           // 回调
        }
        error: function(res){
              if(res.errMsg.indexOf('function_not_exist') > 0){
                   alert('版本过低请升级')
                }
         }
    });

    具体代码实现如下:

    scanBarcode.jsp

    <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
    <html lang="zh-CN">
    <meta charset="utf-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=320.1,initial-scale=1,minimum-scale=1,maximum-scale=1,user-scalable=no">
    <head>
        <link rel="stylesheet" href="http://203.195.235.76/jssdk/css/style.css"/>
        <script src="http://res.wx.qq.com/open/js/jweixin-1.1.0.js"></script>
        <script src="http://libs.baidu.com/jquery/2.0.0/jquery.js"></script>
        <link rel="stylesheet" href="../../../resources/css/example.css"/>
        <link rel="stylesheet" href="../../../resources/css/weui.min.css"/>
        <link rel="stylesheet" href="../../../resources/css/borrowScan.css"/>
    </head>
    <body>
    <div class="container" style="text-align: center;">
        <div class="body_bd body_fd">
            <a class="weui-btn weui-btn-primary weui-btn-zdy" id="scanQRCode1">
                <p>扫描条码</p>
            </a>
        </div>
    </div>
    <script type="text/javascript">
        $.ajax({
            url: "${pageContext.request.contextPath}/wechat/jsapisign",
            type: "post",
            data: {
                url: location.href.split('#')[0]
            },
            contentType: 'application/x-www-form-urlencoded;charset=utf-8',
            async: true,
            success: function (data) {
                wx.config({
                    debug: false, // 开启调试模式,调用的所有api的返回值会在客户端alert出来,若要查看传入的参数,可以在pc端打开,参数信息会通过log打出,仅在pc端时才会打印。
                    appId: data.appid, // 必填,公众号的唯一标识
                    timestamp: data.timestamp, // 必填,生成签名的时间戳
                    nonceStr: data.nonceStr, // 必填,生成签名的随机串
                    signature: data.signature,// 必填,签名,见附录1
                    jsApiList: ["scanQRCode"] // 必填,需要使用的JS接口列表,所有JS接口列表见附录2
                });
            }
        });
    
        wx.ready(function () {
            // 9.1.2 扫描二维码并返回结果
            document.querySelector('#scanQRCode1').onclick = function () {
                wx.scanQRCode({
                    needResult: 1,
                    desc: 'scanQRCode desc',
                    success: function (res) {
                        //扫码后获取结果参数赋值给Input
                        var url = res.resultStr;
                        //商品条形码,取","后面的
                        if (url.indexOf(",") >= 0) {
                            var tempArray = url.split(',');
                            var barCode = tempArray[1];
                            window.location.href = "https://open.weixin.qq.com/connect/oauth2/authorize?appid=${appId}&redirect_uri=${basePath}/wechat/toBookDetail?barCode=" + barCode + "&response_type=code&scope=snsapi_base&state=BINDFACE#wechat_redirect";
                        } else {
                            alert("请对准条形码扫码!");
                        }
                    }
                });
            };
        });
    
        //初始化jsapi接口 状态
        wx.error(function (res) {
            alert("调用微信jsapi返回的状态:" + res.errMsg);
        });
    </script>
    </body>
    </html>

    微信验签代码 WxController.java

      /**
         * 微信验签
         * @param url
         * @return
         */
        @RequestMapping(value = "/jsapisign", method = {RequestMethod.GET, RequestMethod.POST}, produces = MEDIATYPE_CHARSET_JSON_UTF8)
        @ResponseBody
        public String jsApiSign(String url) {
            //添加微信js签名信息
            Map<String, String> signMap = WXJsapiticket.jsApiSign(url);
            return JSON.toJSONString(signMap);
        }

    用到的方法类

    WXJsapiticket.java

    public class WXJsapiticket {
        private static Logger logger = LoggerFactory.getLogger(WxController.class);
        /**
         * 微信jsapi验签
         * @param url
         * @return
         */
        public static Map<String, String> jsApiSign(String url) {
            Map<String, String> ret = new HashMap<String, String>();
            String nonce_str = CheckUtil.create_nonce_str();
            String timestamp = CheckUtil.create_timestamp();
            String jsapi_ticket = getJsApiTicket();
            String string1 = CheckUtil.getString1(nonce_str,timestamp,jsapi_ticket,url);
            String signature = CheckUtil.getSha1(string1);
            ret.put("appid", WXConstants.APPID);//取你自己的公众号appid
            ret.put("url", url);
            ret.put("jsapi_ticket", jsapi_ticket);
            ret.put("nonceStr", nonce_str);
            ret.put("timestamp", timestamp);
            ret.put("signature", signature);
            logger.info("jsApiSign------url=" + url + "-----jsapi_ticket=" + jsapi_ticket + "--------nonceStr=" + nonce_str + "--------timestamp=" + timestamp + "-------signature=" + signature);
            return ret;
        }
        public static String getJsApiTicket(){
            Map<String,Object> map = JsApiTicketCache.getInstance().getJsApiTicketAndExpiresIn();
            return (String) map.get("jsapi_ticket");
        }
    }

    CheckUtil.java

    public class CheckUtil {
        public static final String  token = "xiaodou"; //开发者自行定义Token
        /**
         * 对所有待签名参数按照字段名的ASCII 码从小到大排序(字典序)后,使用URL键值对的格式 (即 key1=value1&key2=value2…)拼接成字符串string1
         * @param nonce_str
         * @param timestamp
         * @param jsapi_ticket
         * @param url
         * @return
         */
        public static String getString1(String nonce_str,String timestamp,String jsapi_ticket,String url){
            //1.定义数组存放nonce_str,timestamp,jsapi_ticket,url
            String[] arr = {"noncestr="+nonce_str,"timestamp="+timestamp,"jsapi_ticket="+jsapi_ticket,"url="+url};
            //2.对数组进行排序
            Arrays.sort(arr);
            //3.生成字符串
            StringBuffer sb = new StringBuffer();
            for(String s : arr){
                sb.append(s);
                sb.append("&");
            }
            sb.deleteCharAt(sb.length()-1);
            return sb.toString();
        }
        public static String getSha1(String str){
            if(str==null||str.length()==0){
                return null;
            }
            char hexDigits[] = {'0','1','2','3','4','5','6','7','8','9',
                    'a','b','c','d','e','f'};
            try {
                MessageDigest mdTemp = MessageDigest.getInstance("SHA1");
                mdTemp.update(str.getBytes("UTF-8"));
                byte[] md = mdTemp.digest();
                int j = md.length;
                char buf[] = new char[j*2];
                int k = 0;
                for (int i = 0; i < j; i++) {
                    byte byte0 = md[i];
                    buf[k++] = hexDigits[byte0 >>> 4 & 0xf];
                    buf[k++] = hexDigits[byte0 & 0xf];
                }
                return new String(buf);
            } catch (Exception e) {
                // TODO: handle exception
                return null;
            }
        }
        public static String create_nonce_str() {
            return UUID.randomUUID().toString();
        }
        public static String create_timestamp() {
            return Long.toString(System.currentTimeMillis() / 1000);
        }
    }

    JsApiTicketCatch.java(对jsapi_ticket的缓存可自行设置,redis或者存到数据库都是可行的)

    /**
     * 缓存ticket
     */
    public class JsApiTicketCache {
        //缓存jsapi_ticket的Map,map中包含jsapiTicket,expiresIn和缓存的时间戳time
        private Map<String, String> map = new HashMap<String,String>();
        private static JsApiTicketCache jsApiTicketCache = null;
        private JsApiTicketCache() { }
        // 静态工厂方法
        public static JsApiTicketCache getInstance() {
            if (jsApiTicketCache == null) {
                jsApiTicketCache = new JsApiTicketCache();
            }
            return jsApiTicketCache;
        }
        public Map<String, String> getMap() {
            return map;
        }
        public void setMap(Map<String, String> map) {
            this.map = map;
        }
        /**
         * 获取 jsapi_ticket expires_in
         * @return
         */
        public Map<String,Object> getJsApiTicketAndExpiresIn() {
            Map<String,Object> result = new HashMap<String,Object>();
            JsApiTicketCache jsApiTicketCache = JsApiTicketCache.getInstance();
            Map<String, String> map = jsApiTicketCache.getMap();
            String time = map.get("time");
            String jsapiTicket = map.get("jsapi_ticket");
            String expiresIn = map.get("expires_in");
            Long nowDate = new Date().getTime();
            if (jsapiTicket != null && time != null && expiresIn!=null) {
                //这里设置过期时间为微信规定的过期时间减去5分钟
                int outTime = (Integer.parseInt(expiresIn)-300) * 1000;
                if (nowDate - Long.parseLong(time) < outTime) {
                    System.out.println("-----从缓存读取jsapi_ticket:" + jsapiTicket);
                    //从缓存中拿数据为返回结果赋值
                    result.put("jsapi_ticket", jsapiTicket);
                    result.put("expires_in", expiresIn);
                }
            } else {
                JsapiTicket info = WeiXinUtil.getjsapiTicket();//实际中这里要改为你自己调用微信接口去获取jsapi_ticket和expires_in
                System.out.println("-----通过调用微信接口获取jsapi_ticket:" + info.getJsapiTicket());
                //将信息放置缓存中
                map.put("time", nowDate + "");
                map.put("jsapi_ticket", info.getJsapiTicket());
                map.put("expires_in", info.getExpiresIn()+"");
                //为返回结果赋值
                result.put("jsapi_ticket", info.getJsapiTicket());
                result.put("expires_in", info.getExpiresIn());
            }
            return result;
        }
    
    }

    WeiXinUtil.java

    jsapi_ticket_url="https://api.weixin.qq.com/cgi-bin/ticket/getticket?access_token=ACCESS_TOKEN&type=jsapi";//GET方式请求获得jsapi_ticket
     /**
         * 获取jsapi_ticket
         * @return
         */
        public static JsapiTicket getjsapiTicket() {
            JsapiTicket jsapiTicket = null ;
            String accessToken = (String) AccessTokenCache.getInstance().getAcessTokenAndExpiresIn().get("access_token");
            String requestUrl = WXConstants.jsapi_ticket_url.replace("ACCESS_TOKEN", accessToken);
            JSONObject jsonObject = httpRequest(requestUrl, "GET", null);
            // 如果请求成功
            if (null != jsonObject) {
                try {
                    jsapiTicket = new JsapiTicket();
                    jsapiTicket.setJsapiTicket(jsonObject.getString("ticket"));
                    jsapiTicket.setExpiresIn(jsonObject.getInt("expires_in"));
                } catch (JSONException e) {
                    jsapiTicket = null;
                    // 获取token失败
                    log.error("获取ticket失败 errcode:{} errmsg:{}", jsonObject.getInt("errcode"), jsonObject.getString("errmsg"));
                }
            }
            return jsapiTicket;
        }

    accessToken的获取参照微信公众号开发之获取access_token,也可根据自己的定义获取。

    JsapiTicket.java

    public class JsapiTicket {
        private String id;
        private String jsapiTicket;
        private int expiresIn;
    
        public String getJsapiTicket() {
            return jsapiTicket;
        }
    
        public void setJsapiTicket(String jsapiTicket) {
            this.jsapiTicket = jsapiTicket;
        }
    
        public int getExpiresIn() {
            return expiresIn;
        }
    
        public void setExpiresIn(int expiresIn) {
            this.expiresIn = expiresIn;
        }
    
        public String getId() {
            return id;
        }
    
        public void setId(String id) {
            this.id = id;
        }
    }

    在这里总结一下开发中需要注意的地方(我遇到的坑):

    1.确认url是页面完整的url(请在当前页面alert(location.href.split('#')[0])确认),包括'http(s)://'部分,以及'?'后面的GET参数部分,但不包括'#'hash后面的部分。

    2.在生成string1时,拼接的参数均为小写,特别注意noncestr,而在jsp页面中为nonceStr(所有的参数一定要根据微信接口中的定义,否则会导致验签失败)。

    3.验证签名是否正确,可在 http://mp.weixin.qq.com/debug/cgi-bin/sandbox?t=jsapisign页面工具进行校验。

    展开全文
  • 微信公众号开发--微信JS-SDK扫一扫功能

    万次阅读 多人点赞 2016-03-02 08:55:10
    首先请阅读微信JS-SDK说明文档,了解微信JS的相关说明。 根据官方的使用步骤,关键的有以下几步 绑定域名(很关键) 引入JS文件(很简单) 通过config接口注入权限验证配置(很重要) 通过ready接口处理成功验证...

    首先请阅读微信JS-SDK说明文档,了解微信JS的相关说明。
    根据官方的使用步骤,关键的有以下几步

    1. 绑定域名(很关键
    2. 引入JS文件(很简单)
    3. 通过config接口注入权限验证配置(很重要
    4. 通过ready接口处理成功验证(还没用到)
    5. 通过error接口处理失败验证(还没用到)

    绑定域名

    绑定域名
    如果域名绑定有误,会出现如下错误提示
    错误的域名配置示例:

    `http://gwchsk.imwork.net/wechat/order/test.html`
    

    域名配置错误的提示信息:
    {“errMsg”:”config:invalid url domain”}

    这里写图片描述

    所以,域名配置的时候一定要注意
    1. 域名不要以http:开头
    2. 域名不要配置到具体的页面
    配置成功的提示如下

    这里写图片描述

    引入JS文件

    一行代码就可以了

    <script src="http://res.wx.qq.com/open/js/jweixin-1.0.0.js"></script>

    通过config接口注入权限验证配置

    这一步非常重要,也是最关键的一步,这一部分
    先看官方的示例

    wx.config({
        debug: true, // 开启调试模式,调用的所有api的返回值会在客户端alert出来,若要查看传入的参数,可以在pc端打开,参数信息会通过log打出,仅在pc端时才会打印。
        appId: '', // 必填,公众号的唯一标识
        timestamp: , // 必填,生成签名的时间戳
        nonceStr: '', // 必填,生成签名的随机串
        signature: '',// 必填,签名,见附录1
        jsApiList: [] // 必填,需要使用的JS接口列表,所有JS接口列表见附录2
    });

    这里需要从服务器端网页面传递的参数有timestamp、nonceStr和signature而appId和jsApiList都是固定的,这里直接写在页面中。

    首先,编写服务器端代码,生成timestampnonceStrsignature
    在生成timestamp、nonceStr和signature的时候有两个参数需要获取
    一个是access_token,另一个是jsapi_ticket

    access_token的获取需要AppIdAppSecret,获取地址如下,发送GET请求

    https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=APPID&secret=APPSECRET

    通过HttpClient发送http请求就可以获取到access_token

    得到access_token之后,采用http GET方式请求获得jsapi_ticket

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

    注意,access_token和jsapi_ticket得有效期为7200秒,开发者必须在自己的服务全局缓存

    获得jsapi_ticket之后,就可以生成JS-SDK权限验证的签名了。

    签名算法

    签名生成规则如下:参与签名的字段包括noncestr(随机字符串), 有效的jsapi_ticket, timestamp(时间戳), url(当前网页的URL,不包含#及其后面部分) 。对所有待签名参数按照字段名的ASCII 码从小到大排序(字典序)后,使用URL键值对的格式(即key1=value1&key2=value2…)拼接成字符串string1。这里需要注意的是所有参数名均为小写字符。对string1作sha1加密,字段名和字段值都采用原始值,不进行URL 转义。

    签名算法的实现

    最难的就是签名算法的实现部分,幸好微信给了demo,网上好多人都在找,这里我把签名算法的实现贴出来,代码来自微信demo
    这里写图片描述
    下载地址
    java代码如下,做了一点点修改

    package com.gwc.wechat.utils.wechat;
    
    import java.io.UnsupportedEncodingException;
    import java.security.MessageDigest;
    import java.security.NoSuchAlgorithmException;
    import java.util.Formatter;
    import java.util.HashMap;
    import java.util.Map;
    import java.util.UUID;
    
    public class WxJSUtil {
        public static void main(String[] args) {
    
            // 注意 URL 一定要动态获取,不能 hardcode
            String url = "http://gwchsk.imwork.net/wechat/order/test.html";
            Map<String, String> ret = sign(url);
            for (Map.Entry entry : ret.entrySet()) {
                System.out.println(entry.getKey() + "=" + entry.getValue());
            }
        };
    
        public static Map<String, String> sign(String url) {
            Map<String, String> ret = new HashMap<String, String>();
            //这里的jsapi_ticket是获取的jsapi_ticket。
            String jsapi_ticket = JSAPITicketTool.getTicket();
            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);
        }
    }
    

    Controller的代码

    @Controller
    @RequestMapping(value = "/order")
    public class OrderController {
    @RequestMapping(value = "/test.html", method = RequestMethod.GET)
        public String testPage(Model model) {
    
            String url = Constant.AppURL + "/order/test.html";
            Map<String, String> ret = WxJSUtil.sign(url);
             for (Map.Entry entry : ret.entrySet()) {
                    System.out.println(entry.getKey() + "=" + entry.getValue());
                    model.addAttribute(entry.getKey().toString(), entry.getValue());
                }
            return "jqueryMobile";
        }
    }

    在Controller中将如下参数写进了jsp页面

        timestamp=1449132293
        nonceStr=fb4eaa58-6d53-40a8-a8fa-7033e9768a8a
        signature=7ad32da3f82cb36492de935a60727d3053d33f4b

    其次编写jsp页面的代码
    在jsp页面中需要将wx.config重的参数进行配置

    wx.config({
        debug: true, // 开启调试模式,调用的所有api的返回值会在客户端alert出来,若要查看传入的参数,可以在pc端打开,参数信息会通过log打出,仅在pc端时才会打印。
        appId: '', // 必填,公众号的唯一标识
        timestamp: , // 必填,生成签名的时间戳
        nonceStr: '', // 必填,生成签名的随机串
        signature: '',// 必填,签名,见附录1
        jsApiList: [] // 必填,需要使用的JS接口列表,所有JS接口列表见附录2
    });

    在页面中读值

        <input id="timestamp" type="hidden" value="${timestamp}" />
        <input id="noncestr" type="hidden" value="${nonceStr}" />
        <input id="signature" type="hidden" value="${signature}" />

    然后赋值

        <script type="text/javascript">
            $(function() {
                var timestamp = $("#timestamp").val();//时间戳
                var nonceStr = $("#noncestr").val();//随机串
                var signature = $("#signature").val();//签名
                wx.config({
                    debug : true, // 开启调试模式,调用的所有api的返回值会在客户端alert出来,若要查看传入的参数,可以在pc端打开,参数信息会通过log打出,仅在pc端时才会打印。
                    appId : 'wx622ca8545e5c354b', // 必填,公众号的唯一标识
                    timestamp : timestamp, // 必填,生成签名的时间戳
                    nonceStr : nonceStr, // 必填,生成签名的随机串
                    signature : signature,// 必填,签名,见附录1
                    jsApiList : [ 'scanQRCode' ]
                // 必填,需要使用的JS接口列表,所有JS接口列表见附录2
                });
            });
        </script>

    写一个按钮和输入框,将扫描的结果放进输入框

    <input id="id_securityCode_input">
    <button id="scanQRCode">扫码</button>

    给按钮绑定事件,并执行微信扫码

    $("#scanQRCode").click(function() {
                wx.scanQRCode({
                    // 默认为0,扫描结果由微信处理,1则直接返回扫描结果
                    needResult : 1,
                    desc : 'scanQRCode desc',
                    success : function(res) {
                        //扫码后获取结果参数赋值给Input
                        var url = res.resultStr;
                        //商品条形码,取","后面的
                        if(url.indexOf(",")>=0){
                            var tempArray = url.split(',');
                            var tempNum = tempArray[1];
                            $("#id_securityCode_input").val(tempNum);
                        }else{
                            $("#id_securityCode_input").val(url);
                        }
                    }
                });
            });

    运行结果如图
    扫一包抽纸

    抽纸

    扫描结果

    放进input

    扫网址

    这里写图片描述

    这里写图片描述

    微信JS-SDK中的扫一扫就基本实现了。

    参考文献

    微信JS-SDK说明文档
    一篇博客

    展开全文
  • 微信扫一扫功能在我们日常生活中很常见,...调起微信扫一扫接口 wx.scanQRCode({  needResult: 0, // 默认为0,扫描结果由微信处理,1则直接返回扫描结果,  scanType: ["qrCode","barC
  • 功能需求:微信公众号里网页需要调用扫一扫功能 实现工具:微信JS-SDK接口 接口官方文档:微信JS-SDK说明文档 微信JS-SDK介绍: 微信JS-SDK是微信公众平台 面向网页开发者提供的基于微信内的网页开发工具包。 ...
  • 微信公众号开发微信扫一扫

    千次阅读 2019-05-27 22:32:59
    最近开发一个食堂项目,项目中用到使用微信扫一扫实现项目中的扫一扫的功能。 1、添加点击扫一扫的触发事件的按钮 <span id="scanQRCode">扫一扫</span> 2、添加微信扫一扫的js引用 <script ...
  • 根据微信api,整理了一下调用微信扫一扫功能。如有问题请指正: 以下是具体步骤: 1、绑定域名(很关键)2、引入JS文件(很简单) script src="http://res.wx.qq.com/open/js/jweixin-1.1.0.js">script>3、通过...
  • c# 调取微信扫一扫接口

    千次阅读 2018-07-02 14:32:18
    这里所有的内容都是从微信接口页面里面参考过来的,加上自己的实践,我在此总结一下步骤和过程,如果下面的内容,有问题,请联系 QQ: 519483246 1.微信接口网址:...
  • 正好微信JS-SDK提供了调用微信扫一扫的功能接口,下面让我们来看看是如何实现的吧。 第一步、微信JS-SDK的使用步骤,配置信息的生成获取讲解:  关于JS-SDK的使用步骤和timestamp(时间戳),nonceStr(随机串),...
  • 微信公众号扫一扫接口开发 因为个人兴趣,研究了一下微信扫码支付接口 实战 1、 首先搭建一个springboot+mybatis+maven项目,创建html页面和js文件、确保直接访问html能够正常运行、html页面引入jweixin-1.0.0.js和...
  • 步:首先配置加载官方JSSDK类,并绑定域名 <?php require_once "./js/jssdk.php"; require_once "./Application/Common/Conf/config.php"; $jssdk = new JSSDK(C('wx_appID'), C('wx_appsecret')); //改为...
  • 最近微信公众号网页开发项目遇到一个问题:在吊起扫一扫功能的时候,Android端正常,iOS端总是提示config:fail 或者签名失败(sigxxxxxx)Vue的项目,前几个类似的项目没遇到这种问题。这次微信配置和吊起的代码也...
  • 由于需要调用微信扫一扫功能,所以要先配置一下微信需要的信息 1.官方接口文档:微信JS-SDK说明文档 2.配置js安全域名:登录公众号 -》公众号设置 -》功能设置 -》JS接口安全域名 开发步骤: 1.引入js文件 CDN引入...
  • .微信准备功能 1.准备备案域名以及80端口服务器 本人准备是花生壳6元测试版 注册花生壳流程本人博客介绍花生壳IP配置流程 2.申请个公众号 本人申请为个人订阅号(搜索公众号即可注册) 3.公众号配置appId...
  • 难点:如何调起企业微信扫一扫功能 实现步骤如下 1:注册企业微信,成为管理员,得到CORPID(企业ID,每个企业微信都有一个,企业下的所有应用都是同一个)和CORPSECRET(应用Secret,每个应用都有,各不相同) 企业...
  • 就是一个商品条码,我用微信扫一扫扫描后能得到信息,但是我在公众平台申请扫一扫功能的时候,同样的条码号就不能识别了,这是为什么呢?请大家帮忙解答下,thx!
  • JAVA调用微信扫一扫

    千次阅读 2016-09-26 16:19:27
    java开发,调用微信扫一扫功能。
  • 微信企业号或微信公众号调用扫一扫功能JS-SDK安全域名配置配置设置好之后下面就上代码java代码 JS-SDK安全域名配置 企业微信号 —— 安全域名配置需要通过验证(如下图) 微信公众 ——— 安全域名配置 设置 ——&...
  • 微信JSSDK实现微信自定义分享,微信扫一扫 前言: 由于微信使用的越来越多,也让大多数平台或者APP与微信建立了比较深的合作关系,我们公司自主研发的产品也是比较依赖于微信,最近也写了几篇关于微信的博客,本文...
1 2 3 4 5 ... 20
收藏数 1,527
精华内容 610
关键字:

微信开发 扫一扫接口返回值