vue调用企业微信扫码接口

准备工作 -企业微信授权

见企业微信官方网站:https://developer.work.weixin.qq.com/document/path/90513

前端 test01.vue

1. 引入js

// 引用企业微信sdk
<script src="//res.wx.qq.com/open/js/jweixin-1.2.0.js"></script>
或vue命令行
npm install  weixin-js-sdk
import 'wx' from 'weixin-js-sdk'

// axios
或vue命令行:npm i axios vue-axios
import _axios from 'axios'

2. 代码

<template>
  <div class="hello">
    <button @click="toScan()">toScan</button>
  </div>
</template>

<script>
/* eslint-disable */
// eslint-disable-next-line
import wx from "weixin-js-sdk"
import _axios from 'axios'

export default {
  name: 'HelloWorld',
  data () {
    return {
      msg: 'Welcome',
      data:{
        appId:'',
        timestamp:'',
        nonceStr:'',
        signature:'',
      }
    }
  },
  methods:{
    async getParams(){
      let that = this;
      _axios.get("http://ip:8080/wx/getToken")
        .then(
          function (response) {
            that.data = response.data.data;
            that.scanCode();
          }
        )
        .catch(function (error) { // 请求失败处理
          console.log(error);
        });
    },
    async toScan(){
      let that = this;
      await that.getParams();
    },
    async scanCode(){
      let that = this;
      try{
        //动态获取当前页面的url地址
        //将url作为参数传入接口,将接口数据解构出来用data对象接受
        if(that.data.appId.length === 0) return;
        //可以将接口中数据打印出来看
        wx.config({
          beta: true,// 必须这么写,否则wx.invoke调用形式的jsapi会有问题
          debug: true, // 在测试没问题之后,关闭debug模式,防止弹窗
          appId: that.data.appId, // 必填,企业微信的corpID
          timestamp: that.data.timestamp, // 必填,生成签名的时间戳
          nonceStr: that.data.nonceStr, // 必填,生成签名的随机串
          signature: that.data.signature,// 必填,签名,见 附录-JS-SDK使用权限签名算法
          jsApiList: ["scanQRCode"] // 必填,需要使用的JS接口列表,凡是要调用的接口都需要传进来
        })
      }catch(error){
        console.log(error)
      }
      wx.ready(function () {
        /*alert('ready');*/
        // 调用企业微信扫一扫接口
        wx.scanQRCode({
          desc: "scanQRCode desc",
          needResult: 1, // 默认为0,扫描结果由企业微信处理,1则直接返回扫描结果,
          scanType: ["qrCode", "barCode"], // 可以指定扫二维码还是条形码(一维码),默认二者都有
          success: function(res) {
            // 回调
            const resultIsbn = res.resultStr;//当needResult为1时返回处理结果
            that.$router.push({ path: '/book-info', query: { isbn: resultIsbn } })//带扫码结果跳转到自己的页面
          },
          error: function(res) {
            if (res.errMsg.indexOf('function_not_exist') > 0) {
              alert('版本过低请升级')
            }
          }
        })
      })
      wx.error(function(res){
        //config信息验证失败会执行error函数,如签名过期导致验证失败,具体错误信息可以打开config的debug模式查看,也可以在返回的res参数中查看,对于SPA可以在这里更新签名。
        let result = res.resultStr// eslint-disable-line no-unused-vars
        console.log("ready失败!")
      })
    }
  }
}
</script>

后台代码

  1. WxController.java
import com.alibaba.fastjson.JSONObject;
import com.MyCache;
import com.common.ServerResponse;
import com.HttpClientHelper;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Controller;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;

import java.security.MessageDigest;
import java.util.HashMap;
import java.util.Map;

@Controller
@RequestMapping("/wx")
@Slf4j
public class WxController {

    private static String CORPID = "********";
    private static String CORPSECRET = "********";
    private static String GET_TOKEN_URL = "https://qyapi.weixin.qq.com/cgi-bin/gettoken";
    private static String NONCESTR = "********";
    private static String CURR_URL = "********";

    @RequestMapping("/getToken")
    @ResponseBody
    public ServerResponse getTokenInfo(){
        try{
            String tokenStr = getToken();
            log.info(tokenStr);
            String ticket = getTickets(tokenStr);
            String timeStamp = String.valueOf(System.currentTimeMillis()/1000);
            String signature = getSignature(NONCESTR,ticket,timeStamp,CURR_URL);
            Map<String,String> data = new HashMap<>();
            data.put("appId",CORPID);
            data.put("timestamp",timeStamp);
            data.put("nonceStr",NONCESTR);
            data.put("signature",signature);
            return ServerResponse.createBySuccess(data);
        }catch (Exception e){
            log.error(e.toString());
            return ServerResponse.createByErrorMessage(e.toString());
        }
    }

    // 获取秘钥
    private String getSignature(String noncestr, String ticket, String timeStamp, String currUrl) {
        StringBuilder stringBuilder = new StringBuilder();
        stringBuilder.append("jsapi_ticket=").append(ticket)
                .append("&noncestr=").append(noncestr)
                .append("×tamp=").append(timeStamp)
                .append("&url=").append(currUrl);
        return getSha1(stringBuilder.toString());
    }

    // 获取token
    public String getToken(){
        String tokenCache = MyCache.get("wxToken",String.class);
        if(!StringUtils.isEmpty(tokenCache)){
            return tokenCache;
        }
        JSONObject param = new JSONObject();
        param.put("corpid",CORPID);
        param.put("corpsecret",CORPSECRET);
        String resultStr = HttpClientHelper.httpGet(GET_TOKEN_URL,param);
        System.out.println(resultStr);
        JSONObject result = JSONObject.parseObject(resultStr);
        String errcode = result.getString("errcode");
        String token = "";
        if("0".equals(errcode)){
            token = result.getString("access_token");
            MyCache.put("wxToken",token,7200*1000L);
        }
        return token;
    }

    // 根据token 获取tickets
    public String getTickets(String token){
        String ticketCache = MyCache.get("apiTicket",String.class);
        if(!StringUtils.isEmpty(ticketCache)){
            return ticketCache;
        }
        JSONObject param = new JSONObject();
        param.put("access_token",token);
        String resultStr = HttpClientHelper.httpGet("https://qyapi.weixin.qq.com/cgi-bin/get_jsapi_ticket",param);
        System.out.println(resultStr);
        JSONObject result = JSONObject.parseObject(resultStr);
        String errcode = result.getString("errcode");
        String ticket = "";
        if("0".equals(errcode)){
            ticket = result.getString("ticket");
            MyCache.put("apiTicket",ticket,7200*1000L);
        }
        return ticket;
    }


    // sha1加密
    public static String getSha1(String str) {
        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) {
            return null;
        }
    }
}
  1. HttpClientHelper 请求帮助类
import com.alibaba.druid.util.StringUtils;
import com.alibaba.fastjson.JSONObject;
import com.google.common.collect.Lists;
import org.apache.http.Consts;
import org.apache.http.Header;
import org.apache.http.HttpEntity;
import org.apache.http.client.config.RequestConfig;
import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.entity.ContentType;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClientBuilder;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.message.BasicNameValuePair;
import org.apache.http.util.EntityUtils;

import java.io.IOException;
import java.util.List;

/**
 * HTTP工具类,参数统一用JSONObject对象进行传递
 * 需要注意的是,如果参数对顺序有要求,如有签名校验时
 * 在构建JSONObject对象时需要指定ordered = true
 * 创建为LinkedHashMap
 */
@SuppressWarnings("all")
public class HttpClientHelper {
    public static String httpGet(String url) {
        return httpGet(url, null, null);
    }

    public static String httpGet(String url, JSONObject params) {
        return httpGet(url, params, null);
    }

    public static String httpGet(String url, JSONObject params, Header header) {
        String result = "";
        if (StringUtils.isEmpty(url)) return result;
        if (params != null && !params.isEmpty()) url = convertGetParams(url, params);
        HttpGet httpGet = new HttpGet(url);
        CloseableHttpClient httpClient = HttpClientBuilder.create().build();
        httpGet.setConfig(getHttpConfig());
        httpGet.setHeader(header);
        try {
            try (CloseableHttpResponse response = httpClient.execute(httpGet)) {
                HttpEntity entity = response.getEntity();
                if (entity != null) {
                    result = EntityUtils.toString(entity, Consts.UTF_8);
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            // 关闭连接,释放资源
            try {
                httpClient.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        return result;
    }

    private static String convertGetParams(String url, JSONObject params) {
        StringBuffer sb = url.contains("?") ? new StringBuffer(url) : new StringBuffer(url + "?");
        params.forEach((k, v) -> sb.append(k).append("=").append(v).append("&"));
        return sb.substring(0, sb.length() - 1);
    }

    public static String httpPost(String url, JSONObject params) {
        return httpPost(url, params, null, ContentType.APPLICATION_JSON);
    }

    public static String httpPost(String url, JSONObject params, Header header) {
        return httpPost(url, params, header, ContentType.APPLICATION_JSON);
    }

    public static String httpPost(String url, JSONObject params, Header header, ContentType contentType) {
        String result = "";
        if (StringUtils.isEmpty(url)) return result;
        //创建默认的httpClient实例
        CloseableHttpClient httpClient = HttpClients.createDefault();
        //创建httpPost
        HttpPost httpPost = new HttpPost(url);
        httpPost.addHeader(header);
        httpPost.setConfig(getHttpConfig());
        StringEntity request;
        try {
            if (ContentType.APPLICATION_FORM_URLENCODED == contentType) {
                List<BasicNameValuePair> pairs = Lists.newArrayList();
                params.forEach((key, value) -> pairs.add(new BasicNameValuePair(key, String.valueOf(value))));
                request = new UrlEncodedFormEntity(pairs, Consts.UTF_8);
            } else {
                request = new StringEntity(String.valueOf(params), ContentType.APPLICATION_JSON);
            }
            httpPost.setEntity(request);
            try (CloseableHttpResponse response = httpClient.execute(httpPost)) {
                HttpEntity entity = response.getEntity();
                if (entity != null) {
                    result = EntityUtils.toString(entity, Consts.UTF_8);
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            //关闭连接,释放资源
            try {
                httpClient.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        return result;
    }

    private static RequestConfig getHttpConfig() {
        return RequestConfig.custom()
                .setConnectTimeout(10000)//一、连接超时:connectionTimeout-->指的是连接一个url的连接等待时间
                .setSocketTimeout(10000)// 二、读取数据超时:SocketTimeout-->指的是连接上一个url,获取response的返回等待时间
                .setConnectionRequestTimeout(10000)
                .build();
    }
}

  1. MyCache.java
import org.springframework.util.StringUtils;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.ScheduledThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicInteger;

/**
 * Description: 缓存工具类
 * 1.部分方法未验证,如有问题请自行修改
 * 2.其他方法请自行添加
 */
public class MyCache {

    /**
     * 屏蔽工具类的无参构造 避免工具类被实例化
     */
    private MyCache(){}

    /**
     * 缓存留存期 30min 1H 24H
     */
    public static final long CACHE_HOLD_TIME_30M = 30 * 60 * 1000L;
    public static final long CACHE_HOLD_TIME_1H = 2 * CACHE_HOLD_TIME_30M;
    public static final long CACHE_HOLD_TIME_24H = 24 * CACHE_HOLD_TIME_1H;
    public static final long CACHE_HOLD_TIME_FOREVER = -1L;

    /**
     * 缓存容量、最少使用容量
     */
    private static final int CACHE_MAX_CAP = 1000;
    private static final int CLEAN_LRU_CAP = 800;

    /**
     * 缓存当前大小
     */
    private static AtomicInteger CACHE_CURRENT_SIZE = new AtomicInteger(0);

    /**
     * 缓存对象
     */
    private static final Map<String,Node> CACHE_MAP = new ConcurrentHashMap<>(CACHE_MAX_CAP);

    /**
     * 最少使用记录
     */
    private static final List<String> LRU_LIST = new LinkedList<>();

    /**
     * 自动清理标志位
     */
    private static volatile boolean CLEAN_RUN_FLAG = false;

    /**
     * 默认30MIN
     * @param key
     * @param val
     */
    public static void put(String key,Object val){
        put(key,val,CACHE_HOLD_TIME_30M);
    }

    /**
     * 添加永久缓存
     * @param key
     * @param val
     */
    public static void putForever(String key,Object val){
        put(key,val,CACHE_HOLD_TIME_FOREVER);
    }

    /**
     * 添加缓存
     * @param key
     * @param val
     * @param ttlTime
     */
    public static void put(String key,Object val,long ttlTime){
        if (!StringUtils.hasLength(key) || null == val){
            return;
        }
        checkSize();
        updateCacheLru(key);
        CACHE_MAP.put(key,new Node(val,ttlTime));
    }

    /**
     * 获取缓存信息
     * @param key
     * @param clazz
     * @param 
     * @return
     */
    public static <T> T get(String key,Class<T> clazz){
        if (!StringUtils.hasLength(key) || !CACHE_MAP.containsKey(key)){
            return null;
        }
        updateCacheLru(key);
        return (T) CACHE_MAP.get(key).getVal();
    }

    /**
     * 更新最近使用位置
     * @param key
     */
    private static void updateCacheLru(String key){
        synchronized (LRU_LIST){
            LRU_LIST.remove(key);
            LRU_LIST.add(0,key);
        }
    }

    /**
     * 删除,成功则容量-1
     * @param key
     */
    private static boolean remove(String key){
        Node node = CACHE_MAP.remove(key);
        if (null!=node){
            CACHE_CURRENT_SIZE.getAndDecrement();
            return true;
        }
        return false;
    }

    /**
     * 检查是否超过容量,先清理过期,在清理最少使用
     */
    private static void checkSize(){
        if (CACHE_CURRENT_SIZE.intValue() > CACHE_MAX_CAP){
            deleteTimeOut();
        }
        if (CACHE_CURRENT_SIZE.intValue() > CLEAN_LRU_CAP){
            deleteLru();
        }
    }

    /**
     * 删除最久未使用,尾部删除
     * 永久缓存不会被清除
     */
    private static void deleteLru(){
        synchronized (LRU_LIST){
            while (LRU_LIST.size() > CLEAN_LRU_CAP){
                int lastIndex = LRU_LIST.size() - 1;
                String key = LRU_LIST.get(lastIndex);
                if (!CACHE_MAP.get(key).isForever() && remove(key)){
                    LRU_LIST.remove(lastIndex);
                }
            }
        }
    }

    /**
     * 删除过期
     */
    private static void deleteTimeOut(){
        List<String> del = new LinkedList<>();
        for (Map.Entry<String,Node> entry:CACHE_MAP.entrySet()){
            if (entry.getValue().isExpired()){
                del.add(entry.getKey());
            }
        }
        for (String k:del){
            remove(k);
        }
    }

    /**
     * 缓存是否已存在,过期则删除返回False
     * @param key
     * @return
     */
    public static boolean contains(String key){
        if (CACHE_MAP.containsKey(key)){
            if (!CACHE_MAP.get(key).isExpired()){
                return true;
            }
            if (remove(key)){
                return false;
            }
            return true;
        }
        return false;
    }

    /**
     * 清空缓存
     */
    public static void clear(){
        CACHE_MAP.clear();
        CACHE_CURRENT_SIZE.set(0);
        LRU_LIST.clear();
    }

    /**
     * 重置自动清理标志
     * @param flag
     */
    public static void setCleanRunFlag(boolean flag){
        CLEAN_RUN_FLAG = flag;
    }

    /**
     * 自动清理过期缓存
     */
    private static void startAutoClean(){

        if (!CLEAN_RUN_FLAG){
            setCleanRunFlag(true);
            ScheduledExecutorService scheduledExecutor = new ScheduledThreadPoolExecutor(1);
            scheduledExecutor.scheduleAtFixedRate(()->{
                try {
                    MyCache.setCleanRunFlag(true);
                    while (CLEAN_RUN_FLAG){
                        MyCache.deleteTimeOut();
                    }
                } catch (Exception e) {
                    e.printStackTrace();
                }
            },10,MyCache.CACHE_HOLD_TIME_1H, TimeUnit.SECONDS);
        }
    }

    /**
     * 缓存对象类
     */
    public static class Node{
        /**
         * 缓存值
         */
        private Object val;
        /**
         * 过期时间
         */
        private long ttlTime;

        public Node(Object val,long ttlTime){
            this.val = val;
            if (ttlTime<0){
                this.ttlTime = ttlTime;
            }else{
                this.ttlTime = System.currentTimeMillis() + ttlTime;
            }
        }

        public Object getVal(){
            return this.val;
        }

        public boolean isExpired(){
            if (this.ttlTime<0){
                return false;
            }
            return System.currentTimeMillis() > this.ttlTime;
        }

        public boolean isForever(){
            if (this.ttlTime<0){
                return true;
            }
            return false;
        }

    }
}
  1. 返回值封装
import java.io.Serializable;
public class ServerResponse<T> implements Serializable
{
    private int status;
    private String msg;
    private T data;
    
    private ServerResponse(final int status) {
        this.status = status;
    }
    
    private ServerResponse(final int status, final T data) {
        this.status = status;
        this.data = data;
    }
    
    private ServerResponse(final int status, final String msg, final T data) {
        this.status = status;
        this.msg = msg;
        this.data = data;
    }
    
    private ServerResponse(final int status, final String msg) {
        this.status = status;
        this.msg = msg;
    }
    
    public boolean isSuccess() {
        return this.status == ResponseCode.SUCCESS.getCode();
    }
    
    public int getStatus() {
        return this.status;
    }
    
    public T getData() {
        return this.data;
    }
    
    public String getMsg() {
        return this.msg;
    }
    
    public static <T> ServerResponse<T> createBySuccess() {
        return new ServerResponse<T>(ResponseCode.SUCCESS.getCode());
    }
    
    public static <T> ServerResponse<T> createBySuccessMessage(final String msg) {
        return new ServerResponse<T>(ResponseCode.SUCCESS.getCode(), msg);
    }
    
    public static <T> ServerResponse<T> createBySuccess(final T data) {
        return new ServerResponse<T>(ResponseCode.SUCCESS.getCode(), data);
    }
    
    public static <T> ServerResponse<T> createBySuccess(final String msg, final T data) {
        return new ServerResponse<T>(ResponseCode.SUCCESS.getCode(), msg, data);
    }
    
    public static <T> ServerResponse<T> createByError() {
        return new ServerResponse<T>(ResponseCode.ERROR.getCode(), ResponseCode.ERROR.getDesc());
    }
    
    public static <T> ServerResponse<T> createByErrorMessage(final String errorMessage) {
        return new ServerResponse<T>(ResponseCode.ERROR.getCode(), errorMessage);
    }
    
    public static <T> ServerResponse<T> createByErrorCodeMessage(final int errorCode, final String errorMessage) {
        return new ServerResponse<T>(errorCode, errorMessage);
    }
}


public enum ResponseCode {
	SUCCESS(0, "SUCCESS"), 
    ERROR(1, "ERROR"), 
    NEED_LOGIN(10, "NEED_LOGIN"), 
    ILLEGAL_ARGUMENT(2, "ILLEGAL_ARGUMENT");
    
    private final int code;
    private final String desc;
    
    private ResponseCode(final int code, final String desc) {
        this.code = code;
        this.desc = desc;
    }
    
    public int getCode() {
        return this.code;
    }
    
    public String getDesc() {
        return this.desc;
    }
}

你可能感兴趣的:(sha1,企业微信,vue,微信,vue.js,前端,java)