Web端调用微信sdk扫一扫功能

Web端调用微信sdk扫一扫功能

常见问题

  1. 没有调用成功摄像头?
/*
* 我们使用的是wxsdk,那自然是只有在微信中才能打开喽。你要是在浏览器上打开那怎么调用摄像头(很蠢,自己一开始是在浏览器上测试的)
* 另外看一下自己是否成功的鉴权了。如果密钥没错的话那就没问题
* 另外注意参数的大小写问题哦
*/

准备工作

  1. 微信公众号订阅号即可 绑定自己的域名(JS接口安全域名),添加IP白名单、获取AppSecret
  2. 在Java后端写一些Utils去向微信发送请求,以达到鉴权获取 ticket

后端代码

public static final String TOKEN_URL = "https://api.weixin.qq.com/cgi-bin/token";// 获取access_token
public static final String TICKET_URL = " https://api.weixin.qq.com/cgi-bin/ticket/getticket";// 拿到token以后获取ticket

获取签名的接口

package com.ruoyi.system.service.impl;

import com.ruoyi.common.core.redis.RedisCache;
import com.ruoyi.common.utils.Constants;
import com.ruoyi.common.utils.SendToWxUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional;

import java.io.UnsupportedEncodingException;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.*;
import java.util.concurrent.TimeUnit;

@Component("JsApiService")
@Transactional
public class JsApiService {

    @Autowired
    private RedisCache redisCache;

    /**
     * 获取签名
     *
     * @param url
     * @return
     */
    public Map<String, String> sign(String url) {
        Map<String, String> resultMap = new HashMap<>(16);

        //这里的jsapi_ticket是获取的jsapi_ticket。
        //String ticket = this.getJsApiTicket();
        String ticket = null;
        Object object = redisCache.getCacheObject("ticket");
        if (object != null) {
            ticket = object.toString();
        } else {
            HashMap<String, String> resMap = SendToWxUtils.getTicket();
            ticket = resMap.get("ticket");
            redisCache.setCacheObject("ticket", ticket);
            redisCache.expire("ticket", 2, TimeUnit.HOURS);
        }



        System.err.println("###########读取ticket:" + ticket);
        //这里签名中的nonceStr要与前端页面config中的nonceStr保持一致,所以这里获取并生成签名之后,还要将其原值传到前端
        String nonceStr = createNonceStr();
        //nonceStr
        String timestamp = createTimestamp();
        String string1;
        String signature = "";

        //注意这里参数名必须全部小写,且必须有序
        string1 = "jsapi_ticket=" + ticket +
                "&noncestr=" + nonceStr +
                "&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();
        }

        resultMap.put("url", url);
        resultMap.put("jsapi_ticket", ticket);
        resultMap.put("nonceStr", nonceStr);
        resultMap.put("timestamp", timestamp);
        resultMap.put("signature", signature);
        resultMap.put("appId", Constants.APPID);
        System.err.println("###########打印resultMap:" + resultMap.get("jsapi_ticket") + "," + resultMap.get("url"));
        return resultMap;
    }

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

    private static String createTimestamp() {
        return Long.toString(System.currentTimeMillis() / 1000);
    }
}

后端向微信发送请求获取Token、等参数的Utils

package com.ruoyi.common.utils;

import com.alibaba.fastjson2.JSONObject;
import com.ruoyi.common.core.redis.RedisCache;

import javax.annotation.Resource;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.ConnectException;
import java.net.SocketTimeoutException;
import java.net.URL;
import java.net.URLConnection;
import java.util.HashMap;

public class SendToWxUtils {
    @Resource
    RedisCache redisCache;

    public static String getAccessToken() {
        String param = String.format("appid=%s&secret=%s&grant_type=%s", Constants.APPID, Constants.SECRET, Constants.GRANT_TYPE);
        String res = sendGet(Constants.TOKEN_URL, param);
        JSONObject obj = JSONObject.parseObject(res);
        String accessToken = obj.getString("access_token");
        System.err.println("accessToken-->" + accessToken);
        return obj.getString("access_token");
    }

    public static HashMap<String, String> getTicket() {
        String accessToken = getAccessToken();
        String param = String.format("access_token=%s&type=jsapi", accessToken);
        String res = sendGet(Constants.TICKET_URL, param);
        JSONObject parsed = JSONObject.parseObject(res);
        String ticket = parsed.getString("ticket");
        HashMap<String, String> resMap = new HashMap<>();
        resMap.put("ticket", ticket);
        return resMap;
    }

    public static String sendGet(String url, String param) {
        StringBuilder result = new StringBuilder();
        BufferedReader in = null;
        try {
            String urlNameString = url + "?" + param;
            URL realUrl = new URL(urlNameString);
            URLConnection connection = realUrl.openConnection();
            connection.setRequestProperty("accept", "*/*");
            connection.setRequestProperty("connection", "Keep-Alive");
            connection.setRequestProperty("user-agent", "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1;SV1)");
            connection.connect();
            in = new BufferedReader(new InputStreamReader(connection.getInputStream(), "UTF-8"));
            String line;
            while ((line = in.readLine()) != null) {
                result.append(line);
            }
        } catch (ConnectException e) {
            System.err.println("调用HttpUtils.sendGet ConnectException, url=" + url + ",param=" + param + e);
        } catch (SocketTimeoutException e) {
            System.err.println("调用HttpUtils.sendGet SocketTimeoutException, url=" + url + ",param=" + param + e);
        } catch (IOException e) {
            System.err.println("调用HttpUtils.sendGet IOException, url=" + url + ",param=" + param + e);
        } catch (Exception e) {
            System.err.println("调用HttpsUtil.sendGet Exception, url=" + url + ",param=" + param + e);
        } finally {
            try {
                if (in != null) {
                    in.close();
                }
            } catch (Exception ex) {
                System.err.println("调用in.close Exception, url=" + url + ",param=" + param + ex);
            }
        }
        return result.toString();
    }

    public static void main(String[] args) {
        String param = String.format("appid=%s&secret=%s&grant_type=%s", Constants.APPID, Constants.SECRET, Constants.GRANT_TYPE);
        String res = sendGet(Constants.TOKEN_URL, param);
        JSONObject obj = JSONObject.parseObject(res);
        String accessToken = obj.getString("access_token");

        String param2 = String.format("access_token=%s&type=jsapi", accessToken);
        String res2 = sendGet(Constants.TICKET_URL, param2);
        JSONObject parsed = JSONObject.parseObject(res2);
        String ticket = parsed.getString("ticket");
        System.err.println(accessToken);
        System.err.println(ticket);
    }
}

一些静态常量

package com.ruoyi.common.utils;

public class Constants {
    public static final String GRANT_TYPE = "client_credential";
    public static final String APPID = "你自己的APPID ";
    public static final String SECRET = "你自己的SECRET ";

    public static final String TOKEN_URL = "https://api.weixin.qq.com/cgi-bin/token";
    public static final String TICKET_URL = " https://api.weixin.qq.com/cgi-bin/ticket/getticket";
}

前端调用接口

    @PostMapping("/getSign")
    public AjaxResult getSign(@RequestBody String url) {
        Map<String, String> sign = jsApiService.sign(url);
        return AjaxResult.success(sign);
    }

前端代码

这里我使用的是Vue,先安装 weixin-js-sdk,pip install即可。

考虑到Android和IOS适配我们需要写一个Config.js

/*
 * 判断是否IOS环境
 * */
//自己封装的请求方法
import wx from "weixin-js-sdk";
import { getSign } from '@/api/system/tab'
export function isIOS() {
  let isIphone = navigator.userAgent.includes("iPhone");
  let isIpad = navigator.userAgent.includes("iPad");
  return isIphone || isIpad;
}
/*
* 获取微信签名,注入权限验证配置
* 这里我用到的是微信扫一扫功能。所以jsApiList: ['checkJsApi', 'scanQRCode']就写了这么多
* 具体用到的什么功能向里边添加即可
* 可以参考Weixin官网提供的一些接口 https://developers.weixin.qq.com/doc/offiaccount/OA_Web_Apps/JS-SDK.html
*/
export function requestWxStr() {
  getSign({ url: window.location.href.split('#')[0] }).then(res => {
    console.log('获取签名信息成功', res)
    wx.config({
      debug: false,
      appId: res.data.appId,
      timestamp: res.data.timestamp,
      nonceStr: res.data.nonceStr,
      signature: res.data.signature,
      jsApiList: ['checkJsApi', 'scanQRCode']
    })
  }).catch(error => {
    console.log('获取签名信息失败', error)
  })
  wx.ready(() => {
    wx.checkJsApi({
      jsApiList: ['scanQRCode'], // 需要检测的JS接口列表,所有JS接口列表见附录2,
      success: function(res) {
        alert("扫一扫准备就绪")
      }
    })
  })
}

在Vue组件中使用,这里我用到的是微信扫一扫功能

import wx from 'weixin-js-sdk'
  methods: {
    init() {
      if (!isIOS()) {
        requestWxStr()
      }
    },
    scanBarCode(row, col) {
      var that = this
      this.scanData.rowNumber = row
      this.scanData.columnNumber = col
      wx.scanQRCode({
          needResult: 1, // 默认为0,扫描结果由微信处理,1则直接返回扫描结果,
          scanType: ['barCode'], // 可以指定扫二维码还是一维码,默认二者都有
          success: function(res) {
            const parts = res.resultStr.split(',')
            // 提取条形码值
            that.scanData.content = parts[1]
            that.isOpen = true
          },
          error: function(res) {
            alert('识别error')
          }
        }
      )
    },

然后就没有然后了,就搞定了。注意需要发布到线上才能测试,可以打印一些log测试。alert(xxx);

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值