IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> JavaScript知识库 -> vue 实现企业微信内部H5应用获取授权 -> 正文阅读

[JavaScript知识库]vue 实现企业微信内部H5应用获取授权

一、调用流程

官方文档:企业微信
在这里插入图片描述

二、流程参考

企业微信H5_身份验证,H5应用网页授权登录获取身份

三、准备过程

1. 申请企业微信

个人也是可以申请的,只是没有企业认证
在这里插入图片描述

2. 创建内部应用

在这里插入图片描述

3. 设置应用路径

在这里插入图片描述

4. 设置可信域名

这边结合腾讯服务器和宝塔
在这里插入图片描述
在这里插入图片描述

然后前往企业微信刚刚创建的应用里面设置可信域名,填好域名,下载文件,上传到宝塔站点根目录再点确定
在这里插入图片描述
把验证文件放到站点根目录下
在这里插入图片描述
然后企业微信中点击确定即可。

5. 本地调试

通过win+R唤起运行框输入: C:\Windows\System32\drivers\etc
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

四、代码展示

1. 前端代码
1.1 调用的方法js:src\api\wcLogin.js
import request from '@/utils/request'

export function oauthUrl(query) {
  return request({
    url: '/wecom/oauthUrl',
    method: 'get',
    params: query
  })
}

export function oauthUser(query) {
  return request({
    url: '/wecom/oauthUser',
    method: 'get',
    params: query
  })
}


export function queryString(name) {
  var reg = new RegExp('(^|&)' + name + '=([^&]*)(&|$)', 'i');
  var r = window.location.search.substr(1).match(reg);
  if (r != null) {
    return unescape(r[2]);
  }
  return null;
}

1.2 应用访问入口页面:src\views\login\index.vue
<template>
  <div id="loader-wrapper">
    <div id="loader"></div>
    <div class="loader-section section-left"></div>
    <div class="loader-section section-right"></div>
    <div class="load_title">正在加载系统资源,请耐心等待</div>
  </div>
</template>

 <script>
import { oauthUrl } from "@/api/wecom/wcLogin";
import { getToken } from "@/utils/auth";

export default {
  data() {
    return {
      url: window.location.href,
    };
  },
  created() {
    this.getOauthUrl();
  },
  computed: {},
  methods: {
    getOauthUrl() {
      // 判断是否登录
      if (getToken()) {
        // 已登录的直接跳转到目的地
        window.location.href =
          window.location.protocol +
          "//" +
          window.location.host +
          "/index";
      } else {
        // window.location 对象用于获得当前页面的地址 (URL),并把浏览器重定向到新的页面
        let oauthCallback =
          window.location.protocol +
          "//" +
          window.location.host +
          "/wecom/callback/index";
        // agentId:企业微信 应用ID
        let params = {
          oauthCallback: oauthCallback,
          agentId: 1000002,
        };
        oauthUrl(params).then((res) => {
          // alert(res.data);
          window.location.href = res.data;
        });
      }
    },
  },
};
</script>
1.3 微信授权回调页面:src\views\callback\index.vue
<template>
  <div id="loader-wrapper">
    <div id="loader"></div>
    <div class="loader-section section-left"></div>
    <div class="loader-section section-right"></div>
    <div class="load_title">正在加载系统资源,请耐心等待</div>
  </div>
</template>

 <script>
import { oauthUser, queryString } from "@/api/wcLogin";

export default {
  created() {
    this.getOauthUser();
  },
  computed: {
    url() {
      return window.location.href;
    },
  },
  methods: {
    getOauthUser() {
      // agentId:企业微信 应用ID
      let params = {
        code: queryString("code"),
        agentId: 1000002,
        baseUrl: window.location.protocol + "//" + window.location.host,
      };

      oauthUser(params).then((res) => {
        // console.log(res.data);
        window.location.href = res.data;
      });
    },
  },
};
</script>
2. 后端代码
2.1 引用第三方企业微信SDK

第三方企业微信SDK文档:binarywang/WxJava

        <!--第三方企业微信SDK-->
        <dependency>
            <groupId>com.github.binarywang</groupId>
            <artifactId>weixin-java-cp</artifactId>
            <version>4.3.0</version>
        </dependency>
        <!--读取配置-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-configuration-processor</artifactId>
            <optional>true</optional>
        </dependency>
        <!--lombok-->
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
        </dependency>
2.2 配置文件
wechat:
  cp:
    # 测试企业
    corpId: ww8917f1xxxx7e3xxx
    appConfigs:
      - agentId: 1000002
        secret: xYxxxxxyxnxxxxxgQxxxxxIxxwVxxxxxixxxx5xxxxx
        // 没有配置可以默认xxx
        token: xxx
        aesKey: xxx

logging:
  level:
    com.github.binarywang.demo.wx.cp: DEBUG
    me.chanjar.weixin: DEBUG
2.3 配置类
package com.leo.wecom.config;

import com.google.common.collect.Maps;
import lombok.val;
import me.chanjar.weixin.cp.api.WxCpService;
import me.chanjar.weixin.cp.api.impl.WxCpServiceImpl;
import me.chanjar.weixin.cp.config.impl.WxCpDefaultConfigImpl;
import me.chanjar.weixin.cp.message.WxCpMessageRouter;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.Configuration;

import javax.annotation.PostConstruct;
import java.util.Map;
import java.util.stream.Collectors;

/**
 *
 * @author leo
 * @date 2022/6/16 14:15
 */
@Configuration
@EnableConfigurationProperties(WxCpProperties.class)
public class WxCpConfiguration {

    private final WxCpProperties properties;

    private static Map<Integer, WxCpMessageRouter> routers = Maps.newHashMap();
    private static Map<Integer, WxCpService> cpServices = Maps.newHashMap();

    @Autowired
    public WxCpConfiguration(WxCpProperties properties) {
        this.properties = properties;
    }

    public static WxCpService getCpService(Integer agentId) {
        return cpServices.get(agentId);
    }

    @PostConstruct
    public void initServices() {
        cpServices = this.properties.getAppConfigs().stream().map(a -> {
            val configStorage = new WxCpDefaultConfigImpl();
            configStorage.setCorpId(this.properties.getCorpId());
            configStorage.setAgentId(a.getAgentId());
            configStorage.setCorpSecret(a.getSecret());
            configStorage.setToken(a.getToken());
            configStorage.setAesKey(a.getAesKey());
            val service = new WxCpServiceImpl();
            service.setWxCpConfigStorage(configStorage);
            routers.put(a.getAgentId(), this.newRouter(service));
            return service;
        }).collect(Collectors.toMap(service -> service.getWxCpConfigStorage().getAgentId(), a -> a));
    }

    /**
     * 可以配置对应的监听事件
     * @param wxCpService
     * @return
     */
    private WxCpMessageRouter newRouter(WxCpService wxCpService) {
        final val newRouter = new WxCpMessageRouter(wxCpService);

//        // 记录所有事件的日志 (异步执行)
//        newRouter.rule().handler(this.logHandler).next();

        return newRouter;
    }
}

package com.leo.wecom.config;


import com.leo.wecom.utils.JsonUtils;
import lombok.Getter;
import lombok.Setter;
import org.springframework.boot.context.properties.ConfigurationProperties;

import java.util.List;

/**
 * @author leo
 * @date 2022/6/16 14:05
 */
@Getter
@Setter
@ConfigurationProperties(prefix = "wechat.cp")
public class WxCpProperties {
    /**
     * 设置企业微信的corpId
     */
    private String corpId;

    private List<AppConfig> appConfigs;

    @Getter
    @Setter
    public static class AppConfig {
        /**
         * 设置企业微信应用的AgentId
         */
        private Integer agentId;

        /**
         * 设置企业微信应用的Secret
         */
        private String secret;

        /**
         * 设置企业微信应用的token
         */
        private String token;

        /**
         * 设置企业微信应用的EncodingAESKey
         */
        private String aesKey;

    }

    @Override
    public String toString() {
        return JsonUtils.toJson(this);
    }
}

package com.leo.wecom.utils;

import com.fasterxml.jackson.annotation.JsonInclude.Include;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.SerializationFeature;

/**
 *  @author leo
 */
public class JsonUtils {
  private static final ObjectMapper JSON = new ObjectMapper();

  static {
    JSON.setSerializationInclusion(Include.NON_NULL);
    JSON.configure(SerializationFeature.INDENT_OUTPUT, Boolean.TRUE);
  }

  public static String toJson(Object obj) {
    try {
      return JSON.writeValueAsString(obj);
    } catch (JsonProcessingException e) {
      e.printStackTrace();
    }

    return null;
  }
}

2.4 controller
package com.leo.wecom.controller;

import com.alibaba.fastjson.JSONObject;
import com.leo.wecom.config.WxCpConfiguration;
import com.leo.wecom.exception.ServiceException;
import com.leo.wecom.utils.Md5Util;
import com.leo.wecom.domain.AjaxResult;
import me.chanjar.weixin.common.error.WxErrorException;
import me.chanjar.weixin.cp.api.WxCpService;
import me.chanjar.weixin.cp.bean.WxCpOauth2UserInfo;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.client.RestTemplate;

import java.text.SimpleDateFormat;
import java.util.Date;

/**
 * @author leo
 * @date 2022/6/16 14:59
 */
@RestController
@RequestMapping("/wecom")
public class GarSevWeComController {

    /**
     * 生成静默授权链接
     * @param agentId 应用ID
     * @param oauthCallback 待跳转链接
     * @return 链接Url
     */
    @CrossOrigin
    @ResponseBody
    @GetMapping("/oauthUrl")
    public AjaxResult oauthUrl(@RequestParam("agentId") Integer agentId, @RequestParam("oauthCallback") String oauthCallback) {
        WxCpService wxCpService = WxCpConfiguration.getCpService(agentId);
        // snsapi_base:静默授权,可获取成员的基础信息(UserId与DeviceId);
        String authorizationUrl = wxCpService.getOauth2Service().buildAuthorizationUrl(oauthCallback, null, "snsapi_base");
        if (!"".equals(authorizationUrl)) {
            return AjaxResult.success("操作成功",authorizationUrl);
        }
        return AjaxResult.error();
    }

    /**
     * 通过core获取员工信息
     * @param agentId 应用ID
     * @param code 微信授权core
     * @return 员工userId = 员工工号
     * @throws Exception 捕捉异常
     */
    @CrossOrigin
    @ResponseBody
    @GetMapping("/oauthUser")
    public AjaxResult oauthUser(@RequestParam("agentId") Integer agentId, @RequestParam("code") String code, @RequestParam("baseUrl") String baseUrl) throws Exception {
        WxCpService wxCpService = WxCpConfiguration.getCpService(agentId);
        WxCpOauth2UserInfo res =  wxCpService.getOauth2Service().getUserInfo(code);
        String userId = res.getUserId();
        if ("".equals(userId)) {
            return AjaxResult.error();
        }
        String ssoUrl = getSsoUrl(baseUrl, userId);
        if (!"".equals(ssoUrl)) {
            return AjaxResult.success("操作成功",ssoUrl);
        }
        return AjaxResult.error();
    }

    public String getToken(String userName){

        SimpleDateFormat sdf= new SimpleDateFormat("yyyyMMddHH");
        String now = sdf.format(new Date());
        String key = "leo_cloud_2022";
        Md5Util md5Util = new Md5Util();
        String sign = md5Util.md5(userName + "|" + key + "|" + now);
   
        String tokenUrl = "http://127.0.0.1:8080/leo/getSsoToken?userName="
                + userName + "&sign=" + sign;

        RestTemplate client = new RestTemplate();
        String response = client.getForObject(tokenUrl, String.class);
        JSONObject jsonObject = JSONObject.parseObject(response);

        if("200".equals(jsonObject.getString("code"))){
            String data = jsonObject.getString("data");
            jsonObject = JSONObject.parseObject(data);
            return jsonObject.getString("access_token");
        }else{
            System.out.println("获取token错误: "+response);
            throw new ServiceException(response);
        }
    }

    public String getSsoUrl(String baseUrl, String userName){

        if("admin".equals(userName)){
            throw new ServiceException("admin管理员不允许单点登录");
        }
        
        //不足6位前面补零
        try{
            StringBuilder userNameBuilder = new StringBuilder(userName);
            while(userNameBuilder.length()<6){
                userNameBuilder.insert(0, "0");
            }
            userName = userNameBuilder.toString();
        }catch(Exception e){
            e.printStackTrace();
        }
        String token = this.getToken(userName);
        String url = baseUrl + "/login?userName=" + userName + "&ssoToken=" + token + "&gotoUrl=/index";
        return url;
    }

}

package com.leo.wecom.utils;

import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;

public class Md5Util {

	public static void main(String[] args){
		String str = new Md5Util().md5("admin");
		System.out.println(str);
	}
	/**利用MD5进行加密
	 * @param str  待加密的字符串
	* @return  加密后的字符串
	*/
	public String md5(String str){
		try {  
            MessageDigest md = MessageDigest.getInstance("MD5");  
            md.update(str.getBytes());  
            byte b[] = md.digest();  
            int i;
            StringBuffer buf = new StringBuffer("");  
            for (int offset = 0; offset < b.length; offset++) {  
                i = b[offset];  
                if (i < 0)  
                    i += 256;  
                if (i < 16)  
                    buf.append("0");  
                buf.append(Integer.toHexString(i));  
            }  
            //32位加密  
            return buf.toString();  
            // 16位的加密  
            //return buf.toString().substring(8, 24);  
        } catch (NoSuchAlgorithmException e) {  
            e.printStackTrace();  
            return null;  
        }  
	}
}

  JavaScript知识库 最新文章
ES6的相关知识点
react 函数式组件 & react其他一些总结
Vue基础超详细
前端JS也可以连点成线(Vue中运用 AntVG6)
Vue事件处理的基本使用
Vue后台项目的记录 (一)
前后端分离vue跨域,devServer配置proxy代理
TypeScript
初识vuex
vue项目安装包指令收集
上一篇文章      下一篇文章      查看所有文章
加:2022-06-23 00:51:34  更:2022-06-23 00:52:13 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/23 16:53:23-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码