Java微信网页调用扫一扫

这章主要记录下调用微信JS-SDK中的扫一扫踩到的坑


一、引入JS文件

  • 首先我们先引入js文件,地址为 http://res.wx.qq.com/open/js/jweixin-1.0.0.js,当然你也可以下载到本地,使用本地路径进行引入
  • 如果是前后端分离的项目,可以用npm来安装相关依赖,具体命令为 npm install weixin-js-sdk,然后在相应页面引入即可,具体命令为 import wx from ‘weixin-js-sdk’

二、往服务端传入当前页面url

  • 这里需要往服务端传入当前页面的url,包括’http(s)://’部分,以及’?’后面的GET参数部分,但不包括’#’hash后面的部分,此外该url需要经过 encodeURIComponent 处理,由于我只在一个页面调用了扫一扫的功能,所以我的页面url直接写死了,但如果你需要调用分享等功能,则页面的url需要通过 location.href.split(‘#’)[0] 动态获取,具体的见官方文档
  • 我的页面url参数为 var url = encodeURIComponent(‘https://www.baidu.com/‘),注意,这里我碰到一个很坑的事,后期在页面上调用扫一扫时,该url和扫一扫所在页面的url必须保持一致,我都填对了,可还是报错,最后才查出来,扫一扫所在的页面url末尾多了一个/,所以在往服务端传的url后面也加上一个/,就没问题了

三、在微信公众平台设置JS接口安全域名

  • 该域名必须与第二步中url的域名相同
    这里写图片描述
  • 还需要下载 MP_verify_xyPkykStkhZUf7ya.txt 文件,并将其上传至项目的根目录下,也就是说通过 域名 + /MP_verify_xyPkykStkhZUf7ya.txt 的形式能直接访问到该文件

四、获取jsapi_ticket

用于调用微信JS接口的临时票据,有效期为7200s,由于调用次数十分有限,所有我们需要全局缓存jsapi_ticket,可以通过 redis 来缓存,在获取 jsapi_ticket 时需要先获取 access_token,不清楚怎么获取的小伙伴可以点击看我以前的博客

    public static String getWXJsapiTicket(String accessToken) {
        // 此处accessToken为请求微信接口获取到的access_token
        String jsapiTicketUrl = "https://api.weixin.qq.com/cgi-bin/ticket/getticket?" +
                "access_token=" + accessToken +
                "&type=jsapi";
        JSONObject jsonObject = HttpUtils.httpsRequest(jsapiTicketUrl, "GET", null);
        return (String) jsonObject.get("ticket");
    }

五、服务端生成签名

  • 生成签名需要四个参数,分别为 noncestr,jsapi_ticket,timestamp,url
    • noncestr
      随机字符串
    • jsapi_ticket
      用于调用微信JS接口的临时票据,即第三步获取到的jsapi_ticket
    • timestamp
      当前时间戳,单位为秒
    • url
      当前页面url,即第二步由页面传递给服务端的url参数

WXPayUtils

    public static String generateNonceStr() {
        return UUID.randomUUID().toString().replaceAll("-", "");
    }
    public static long getCurrentTimestamp() {
        return System.currentTimeMillis()/1000;
    }
  • 用SHA1加密生成签名
    @RequestMapping("xxxxxxxxxxxxx")
    @ResponseBody
    public Map<String, Object> getSignature(HttpServletRequest request) {
        String nonceStr = WXPayUtils.generateNonceStr();
        String timestamp = WXPayUtils.getCurrentTimestamp() + "";
        // returnMap为返回给页面的数据
        Map<String, Object> returnMap = new HashMap<>();
        // 此处填写你自己公众号的appid
        map.put("appId", WXConstants.APPID);
        map.put("timestamp", timestamp);
        map.put("nonceStr", nonceStr);
        // map为用于生成签名的数据
        Map<String, Object> map = new HashMap<>();
        map.put("timestamp", timestamp);
        map.put("noncestr", nonceStr);
        map.put("jsapi_ticket", jsapiTicket);
        map.put("url", request.getParameter("url"));
        String signature = SHA1.getJsSHA1(map);
        if (null != signature) {
            returnMap.put("signature", signature);
        }
        return returnMap;
    }

SHA1

    /**
     * 用SHA1算法生成安全签名
     * @param map
     * @return 安全签名
     * @throws AesException
     */
    public static String getJsSHA1(Map<String, Object> map) {
        try {
            String[] array = new String[] { "noncestr", "jsapi_ticket", "timestamp", "url" };
            Arrays.sort(array);
            StringBuffer sb = new StringBuffer();
            // 字符串排序
            for (int i = 0; i < array.length; i++) {
                if (i < array.length-1) {
                    sb.append(array[i]).append("=").append(map.get(array[i])).append("&");
                } else {
                    sb.append(array[i]).append("=").append(map.get(array[i]));
                }
            }
            String str = sb.toString();
            // SHA1签名生成
            MessageDigest md = MessageDigest.getInstance("SHA-1");
            md.update(str.getBytes());
            byte[] digest = md.digest();

            StringBuffer hexstr = new StringBuffer();
            String shaHex = "";
            for (int i = 0; i < digest.length; i++) {
                shaHex = Integer.toHexString(digest[i] & 0xFF);
                if (shaHex.length() < 2) {
                    hexstr.append(0);
                }
                hexstr.append(shaHex);
            }
            return hexstr.toString();
        } catch (Exception e) {
            e.printStackTrace();
            return null;
        }
    }

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

  • 先执行wx.config方法,注入权限验证配置
    // 页面一加载时执行该方法
    getWXJsapiTicket() {
        // 此处需要将url用ajax传递给服务器,并接收返回来的参数
        // .........
        wx.config({
          // 开启调试模式,调用的所有api的返回值会在客户端alert出来
          // 若要查看传入的参数,可以在pc端打开,参数信息会通过log打出,仅在pc端时才会打印
          debug: false,
          // 此处填写服务端返回的appId
          appId: appId,
          // 此处填写服务端返回的时间戳
          timestamp: timestamp,
          // 此处填写服务端返回的随机字符串
          nonceStr: nonceStr,
          // 此处填写服务端返回的签名
          signature: signature,
          // 需要使用的JS接口列表,我只用到了扫一扫,所以只填写了scanQRCode
          // 如果需要其他JS接口,可以参考官方文档
          jsApiList: ['scanQRCode']
        });
    }
  • 执行完wx.config方法后,执行某一点击事件,然后执行wx.scanQRCode方法,调用微信扫一扫
    // 此为一点击事件
    scanCode() {
      wx.scanQRCode({
        // 默认为0,扫描结果由微信处理,1则直接返回扫描结果
        needResult: 0,
        // 可以指定扫二维码还是一维码,默认二者都有
        scanType: ["qrCode","barCode"],
        success: function (res) {
          // 当needResult 为 1 时,扫码返回的结果
          let result = res.resultStr;
        }
      });
    }

不出意外的话,就可以在页面里正常地调用微信扫一扫了

猜你喜欢

转载自blog.csdn.net/Goodbye_Youth/article/details/80910195