H5实现 js-sdk 微信扫一扫

H5实现 js-sdk 微信扫一扫

配置和绑定域名

先登录微信公众平台进入"公众号设置"的"功能设置"里填写"JS接口安全域名"。

微信公众平台

arduino 复制代码
https://mp.weixin.qq.com/

手机扫码登录

如图所示,进行配置(将第四步文件下载,上传到指定位置),如:

1、springboot项目,放在项目中resources文件夹下,保证 域名+项目名+该文件名 能访问到

域名填写为 域名+项目名

2、直接放在服务器的目录中,可通过nginx转发达到可以访问即可

域名填写为域名

备注:登录后可在"开发者中心"查看对应的接口权限。

引入JS文件

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

如需进一步提升服务稳定性,当上述资源不可访问时,可改访问:res2.wx.qq.com/open/js/jwe... (支持https)。

加入如下资源即可

xml 复制代码
    <link rel="stylesheet" href="https://res.wx.qq.com/open/libs/weui/2.0.0/weui.min.css">
    <script src="http://res.wx.qq.com/open/js/jweixin-1.4.0.js"></script>
    <script src="https://res.wx.qq.com/open/libs/weuijs/1.1.4/weui.min.js"></script>

备注:支持使用 AMD/CMD 标准模块加载方法加载

前端代码

php 复制代码
var jsApiList = [
        'checkJsApi',
        'scanQRCode'
    ];
​
    function init() {
        // console.log("url = " + location.href.split("#")[0])
        //获取签名
        $.ajax({
            url:"你的后台地址",
            method:"post",
            data:{url:location.href.split("#")[0]},
            dataType: "json",
            success:function (data) {
                console.info("data = " , data);
                var appId = data['appId'];
                var timestamp = data['timestamp'];
                var nonceStr = data['nonceStr'];
                var signature = data['signature'];
​
​
                //1 通过config接口注入权限验证配置
                wx.config({
                    debug: false, ///  // true是开启调试模式,调用的所有api的返回值会在客户端alert出来,若要查看传入的参数,可以在pc端打开,参数信息会通过log打出,仅在pc端时才会打印。
                    appId: appId,
                    timestamp: timestamp,
                    nonceStr: nonceStr,
                    signature: signature,
                    jsApiList: jsApiList
                });
​
                //2 通过ready接口处理成功验证
                wx.ready(function () {
                    //check client vserion wether support JS API
                    wx.checkJsApi({
                        jsApiList: ['scanQRCode'],
                        success: function (res) {
                            // weui.alert(res.errMsg);
​
                            wx.scanQRCode({
                                needResult: 1, // 默认为0,扫描结果由微信处理,1则直接返回扫描结果,
                                scanType: ["qrCode", "barCode"], // 可以指定扫二维码还是一维码,默认二者都有
                                success: function (res) {
                                    console.log(res)
                                    
                                }
                            });
​
                        }
                    });
                });
​
                //3 通过error接口处理失败验证
                //wrong error msg
                wx.error(function (res) {
                    weui.alert("出错了请稍后再试!" + res.errMsg);
                });
            },
            error:function (data) {
                weui.alert("网络异常,请稍后再试。");
            }
        });
    }
​
    //scanning Qr code
    function scanQRCodeFun() {
        // 初始化,成功后,会调用微信扫一扫
        init();
​
    };

后端代码

获取 Access token

仅是示例,可根据自己情况修改

WX_APPIDWX_APPSECRET替换成自己的

ini 复制代码
public String getWxAccessToken() throws IOException {
        String getUrl = "https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid="+WX_APPID+"&secret="+WX_APPSECRET;
        String res = "";
        // 创建一个URL对象
        URL url = new URL(getUrl);
        // 打开一个连接
        HttpURLConnection connection = (HttpURLConnection) url.openConnection();
        // 设置请求方式为GET
        connection.setRequestMethod("GET");
        // 设置连接超时时间
        connection.setConnectTimeout(5000);
        // 设置读取超时时间
        connection.setReadTimeout(5000);
        // 发送请求
        connection.connect();
        // 获取响应码
        int responseCode = connection.getResponseCode();
        if (responseCode == 200) {
            // 获取响应内容
            BufferedReader reader = new BufferedReader(new InputStreamReader(connection.getInputStream()));
            StringBuffer sb = new StringBuffer();
            String line;
            while ((line = reader.readLine()) != null) {
                sb.append(line);
            }
            reader.close();
            // 解析响应内容
            System.out.println(sb.toString());
            res = sb.toString();
        } else {
            System.out.println("响应码:" + responseCode);
        }
        // 关闭连接
        connection.disconnect();
        return res;
    }
获取 jsapi_ticket

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

  1. 参考以下文档获取access_token(有效期7200秒,开发者必须在自己的服务全局缓存access_token):developers.weixin.qq.com/doc/offiacc...
  2. 用第一步拿到的access_token 采用http GET方式请求获得jsapi_ticket(有效期7200秒,开发者必须在自己的服务全局缓存jsapi_ticket):api.weixin.qq.com/cgi-bin/tic...

成功返回如下JSON:

json 复制代码
{
  "errcode":0,
  "errmsg":"ok",
  "ticket":"bxLdikRXVbTPdHSM05e5u5sUoXNKd8-41ZO3MhKoyN5OfkWITDGgnr2fwJ0m9E8NYzWKVZvdVtaUgWvsdshFKA",
  "expires_in":7200
}

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

仅是示例,可根据自己情况修改

wxAccessToken就是上面获取到的

ini 复制代码
public String getWxJsapiTicket(String wxAccessToken) throws IOException {
        String getUrl = "https://api.weixin.qq.com/cgi-bin/ticket/getticket?access_token="+wxAccessToken+"&type=jsapi";
        String res = "";
        // 创建一个URL对象
        URL url = new URL(getUrl);
        // 打开一个连接
        HttpURLConnection connection = (HttpURLConnection) url.openConnection();
        // 设置请求方式为GET
        connection.setRequestMethod("GET");
        // 设置连接超时时间
        connection.setConnectTimeout(5000);
        // 设置读取超时时间
        connection.setReadTimeout(5000);
        // 发送请求
        connection.connect();
        // 获取响应码
        int responseCode = connection.getResponseCode();
        if (responseCode == 200) {
            // 获取响应内容
            BufferedReader reader = new BufferedReader(new InputStreamReader(connection.getInputStream()));
            StringBuffer sb = new StringBuffer();
            String line;
            while ((line = reader.readLine()) != null) {
                sb.append(line);
            }
            reader.close();
            // 解析响应内容
            System.out.println(sb.toString());
            res = sb.toString();
        } else {
            System.out.println("响应码:" + responseCode);
        }
        // 关闭连接
        connection.disconnect();
        return res;
    }
权限签名

WX_APPID替换成自己的

typescript 复制代码
// 签名用的url必须是调用JS接口页面的完整URL
    public 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("appId",WX_APPID);
        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);
    }

然后在控制层将结果返回到前端

注意

相关推荐
程序员南飞38 分钟前
ps aux | grep smart_webrtc这条指令代表什么意思
java·linux·ubuntu·webrtc
弥琉撒到我42 分钟前
微服务swagger解析部署使用全流程
java·微服务·架构·swagger
一颗花生米。2 小时前
深入理解JavaScript 的原型继承
java·开发语言·javascript·原型模式
问道飞鱼2 小时前
Java基础-单例模式的实现
java·开发语言·单例模式
学习使我快乐012 小时前
JS进阶 3——深入面向对象、原型
开发语言·前端·javascript
bobostudio19952 小时前
TypeScript 设计模式之【策略模式】
前端·javascript·设计模式·typescript·策略模式
黄尚圈圈3 小时前
Vue 中引入 ECharts 的详细步骤与示例
前端·vue.js·echarts
浮华似水4 小时前
简洁之道 - React Hook Form
前端
ok!ko5 小时前
设计模式之原型模式(通俗易懂--代码辅助理解【Java版】)
java·设计模式·原型模式
正小安6 小时前
如何在微信小程序中实现分包加载和预下载
前端·微信小程序·小程序