企业微信小程序_授权登录接口获取用户userid

在这里插入图片描述

文章目录

          • 一、前置知识
            • 1. 阅读 企业微信小程序开发文档
            • 2. 企业微信小程序登录流程
            • 3. 微信小程序区别
          • 二、前端部分
            • 2.1. 调用登录接口
            • 2.2. 请求后端接口
            • 2.3. 项目源码
          • 三、后端部分
            • 3.1. yml配置
            • 3.2. 获取用户信息接口
            • 3.3. 获取token
            • 3.4. 工具类
            • 3.5. vo对象
          • 四、调试部分
            • 4.1. 模式切换
            • 4.2. api执行流程
            • 4.3. 报文赏评

一、前置知识

获取小程序userid就要先将小程序提交审核->发布小程序->企微后台在自建应用中绑定小程序

1. 阅读 企业微信小程序开发文档

https://developer.work.weixin.qq.com/document/path/92426

2. 企业微信小程序登录流程

企业微信小程序获取access_token文档

在这里插入图片描述

3. 微信小程序区别

区分企业微信小程序登录流程和微信小程序登录流程不同点。

不同点:
1.企业微信小程序登录流程和微信小程序登录流程不一样,获取的用户信息也不一样。
2.企业微信小程序登录流程需要将企业微信小程序先发布上传吗,审核通过后,将企业微信小程序与企业应用进行绑定后,获取该应用的agentSecret和corpId去获取AccessToken,然后,通过AccessToken和code获取用户信息,最后通过获取的userid在调用通讯录接口获取该用户的详细信息。
3.开发阶段:可以使用企业微信提供的测试应用的agentSecret和corpId

二、前端部分
2.1. 调用登录接口

执行流程会从前端到后端:
前端调用腾讯企业微信登录接口api
登录api开发文档:https://developer.work.weixin.qq.com/document/path/91506
uniapp项目小程序项目写法:

           // 企业微信下程序登录的方法login() {wx.qy.login({success: function(res) {// 调用成功,会返回codeconsole.log("res", res)}})},

返回的报文:

{code: "VFUfreDIauQszKQy5mZgRC3aaMijd7DM-xnOcZW3LVE", errMsg: "qy__login:ok"}

小程序项目写法:

//app.js
App({onLaunch: function() {wx.qy.login({success: function(res) {if (res.code) {//发起网络请求wx.request({url: 'https://test.com/onLogin',data: {code: res.code}})} else {console.log('登录失败!' + res.errMsg)}}});}
})
2.2. 请求后端接口

携带code调用后端接口
这里使用封装好的axios和user接口api,直接使用即可
utils/request.js,这个js主要封装了axios,对请求统一管理,请求url以及数据拼接以及响应处理(这个工具类需要和后端的返回对象JsonData.java对上,下面会贴出来代码)。

const BASE_URL = 'http://api.ant-qywx.com:9900';
function request({ url, data, method }) {return new Promise((resolve, reject) => {// 发起网络请求uni.request({url: BASE_URL + url,data,method,success: ({ data }) => {console.log("data",data)// 响应成功,获取数据,解析数据if (data.success) {resolve(data);} else {// 响应失败,给用户提示uni.showToast({title: data.message,icon: 'none',mask: true,duration: 3000,});reject(data.message);}},fail: (error) => {reject(error);},complete: () => {// 关闭加载uni.hideLoading();},});});
}export default request;

引入api

<script>// 引用用户接口api 调用后端登录接口import {loginAuth} from '../../api/user.js';
</script>

编写登录方法调用企业微信登录接口

methods: {
// 企业微信下程序登录的方法login() {wx.qy.login({success: function(res) {console.log("res", res)loginAuth(res).then((response) => {console.log("response", response)});}})}
}

api/user.js这里js,作用是管理用户相关接口api

import request from '../utils/request';/*** 微信用户授权登录,携带appid和code参数,调用后端接口获取Openid*/
export function loginAuth(data) {return request({url: '/mini/login',data: {code: data.code,},});
}
2.3. 项目源码

https://gitee.com/gblfy/qywx-inner-java-api

三、后端部分
3.1. yml配置

application.yml

server:port: 9900qywx:mini:agentSecret: i5t-rh8bXeNCgihcYPrG9ZPpWkivzPJ69sv570osk6IcorpId: ww17f8d10783494584
3.2. 获取用户信息接口

Controller

package com.gblfy.qywxin.controller;import com.gblfy.qywxin.service.QywxInnerMiniService;
import com.gblfy.qywxin.utils.JWTUtils;
import com.gblfy.qywxin.vo.JsonData;
import com.gblfy.qywxin.vo.QywxInnerUser;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;import java.util.Map;@RestController
@RequestMapping("/mini")
public class QywxMiniController {private static final Logger logger = LoggerFactory.getLogger(QywxMiniController.class);@Value("${qywx.mini.corpId}")private String corpId;@Autowiredprivate QywxInnerMiniService qywxInnerMiniService;@GetMapping("/login")public JsonData login(@RequestParam(value = "code", required = false) String code) {logger.info("accept code->{}", code);Map result = qywxInnerMiniService.getOauthUser(corpId, code);logger.info("accept result->{}", result);//本案例仅从企业微信接口获取未从数据表中获取QywxInnerUser user = new QywxInnerUser();user.setCorpId(corpId);user.setUserId((String) result.get("userId"));String token = JWTUtils.geneJsonWebToken(user);result.put("token", token);return JsonData.buildSuccess(result);}
}
3.3. 获取token

service

package com.gblfy.qywxin.service;import com.gblfy.qywxin.config.QywxInnerConfig;
import com.gblfy.qywxin.utils.RestUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;import java.util.Map;@Service
public class QywxInnerMiniService {private static final Logger logger = LoggerFactory.getLogger(QywxInnerMiniService.class);@Value("${qywx.mini.agentSecret}")private String AGENT_SECRET;public Map getOauthUser(String corpId, String code) {// 1.通过corpId获取AccessTokenString accessToken = getAccessToken(corpId);String getOauthUrl = String.format(QywxInnerConfig.MINI_OAUTH_USER_URL, accessToken, code);Map response = RestUtils.get(getOauthUrl);if (response.containsKey("errcode") && (Integer) response.get("errcode") != 0) {logger.error(response.toString());return response;}System.out.println("response->" + response);//  目前已经获取到userid了// return response;//根据用户UserId->获取通讯录用户详情getString userId = (String) response.get("userid");String url = String.format(QywxInnerConfig.USER_DETAIL_URL, accessToken, userId);Map detaiResponse = RestUtils.get(url);//获取错误日志if (detaiResponse.containsKey("errcode") && (Integer) detaiResponse.get("errcode") != 0) {logger.error(detaiResponse.toString());}return detaiResponse;}/*** 通过corpId获取AccessToken** @param corpId 企业ID* @return*/public String getAccessToken(String corpId) {String result = "";String accessTokenUrl = String.format(QywxInnerConfig.MINI_ACCESS_TOKEN_URL, corpId, AGENT_SECRET);Map response = RestUtils.get(accessTokenUrl);//获取错误日志if (response.containsKey("errcode") && (Integer) response.get("errcode") != 0) {logger.error(response.toString());} else {result = (String) response.get("access_token");}return result;}
}
3.4. 工具类

RestUtils

package com.gblfy.qywxin.utils;import com.alibaba.fastjson.JSONObject;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.*;
import org.springframework.util.MultiValueMap;
import org.springframework.web.client.RestTemplate;
import org.springframework.web.util.UriComponentsBuilder;import java.io.IOException;
import java.net.URI;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.util.Map;
import java.util.Objects;@Configuration
public class RestUtils {private static final RestTemplate restTemplate = new RestTemplate();public static JSONObject get(String url, Map<String,String> urlParams){return get(urlToUri(url,urlParams));}//在处理企业微信某些参数时有问题public static JSONObject get(String url){return get(URI.create(url));}private static JSONObject get(URI uri){ResponseEntity<JSONObject> responseEntity =restTemplate.getForEntity(uri,JSONObject.class);serverIsRight(responseEntity);   //判断服务器返回状态码return responseEntity.getBody();}public static JSONObject post(String url,Map<String,String> urlParams,JSONObject json){//组装urlreturn post(urlToUri(url,urlParams),json);}public static JSONObject post(String url,JSONObject json){//组装urLreturn post(URI.create(url),json);}private static JSONObject post(URI uri,JSONObject json){//组装url//设置提交json格式数据HttpHeaders headers = new HttpHeaders();headers.setContentType(MediaType.APPLICATION_JSON);HttpEntity<JSONObject> request = new HttpEntity(json, headers);ResponseEntity<JSONObject> responseEntity = restTemplate.postForEntity(uri,request,JSONObject.class);serverIsRight(responseEntity);  //判断服务器返回状态码return responseEntity.getBody();}private static URI urlToUri(String url,Map<String,String> urlParams){//设置提交json格式数据UriComponentsBuilder uriBuilder = UriComponentsBuilder.fromHttpUrl(url);for(Map.Entry<String,String> entry : urlParams.entrySet())  {uriBuilder.queryParam((String)entry.getKey(),  (String) entry.getValue()) ;}return  uriBuilder.build(true).toUri();}public static JSONObject upload(String url,MultiValueMap formParams){//设置表单提交HttpHeaders headers = new HttpHeaders();headers.setContentType(MediaType.MULTIPART_FORM_DATA);HttpEntity<MultiValueMap<String, String>> request = new HttpEntity<>(formParams, headers);ResponseEntity<JSONObject> responseEntity = restTemplate.postForEntity(url,request,JSONObject.class);serverIsRight(responseEntity);  //判断服务器返回状态码return responseEntity.getBody();}public static String download(String url,String targetPath) throws IOException {ResponseEntity<byte[]> rsp = restTemplate.getForEntity(url, byte[].class);if(rsp.getStatusCode() != HttpStatus.OK){System.out.println("文件下载请求结果状态码:" + rsp.getStatusCode());}// 将下载下来的文件内容保存到本地Files.write(Paths.get(targetPath), Objects.requireNonNull(rsp.getBody()));return targetPath;}public static byte[] dowload(String url){ResponseEntity<byte[]> rsp = restTemplate.getForEntity(url, byte[].class);return rsp.getBody();}private static void serverIsRight(ResponseEntity responseEntity){if(responseEntity.getStatusCodeValue()==200){
//            System.out.println("服务器请求成功:{}"+responseEntity.getStatusCodeValue());}else {System.out.println("服务器请求异常:{}"+responseEntity.getStatusCodeValue());}}}

JWTUtils

package com.gblfy.qywxin.utils;import com.gblfy.qywxin.vo.QywxInnerUser;
import io.jsonwebtoken.Claims;
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.SignatureAlgorithm;import java.util.Date;public class JWTUtils {private static final long EXPIRE = 60000 * 60 * 24 * 7;private static final String SECRET = "tobdev.com";private static final String TOKEN_PREFIX = "tobdev";private static final String SUBJECT = "tobdev";/*** 生成jwt token** @param user* @return*/public static String geneJsonWebToken(QywxInnerUser user) {String token = Jwts.builder().setSubject(SUBJECT).claim("corp_id", user.getCorpId()).claim("user_id", user.getUserId()).claim("user_name", user.getName()).claim("mobile", user.getMobile()).claim("qr_code", user.getQrCode()).claim("user_type", user.getUserType()).setIssuedAt(new Date()).setExpiration(new Date(System.currentTimeMillis() + EXPIRE)).signWith(SignatureAlgorithm.HS256, SECRET).compact();token = TOKEN_PREFIX + token;return token;}/*** 校验token是否合法** @param token* @return*/public static Claims checkJWT(String token) {try {final Claims claims = Jwts.parser().setSigningKey(SECRET).parseClaimsJws(token.replace(TOKEN_PREFIX, "")).getBody();return claims;} catch (Exception e) {return null;}}
}
3.5. vo对象
package com.gblfy.qywxin.vo;/*** 返回封装对象** @author gblfy* @date 2022-01-12*/
public class JsonData {/*** 业务上的成功或失败*/private boolean success = true;private Integer code;private String msg;private Object data;public JsonData() {}public JsonData(Integer code, Object data, String msg,boolean success) {this.code = code;this.data = data;this.msg = msg;this.success = success;}public static JsonData buildSuccess() {return new JsonData(0, null, null,true);}public static JsonData buildSuccess(Object data) {return new JsonData(0, data, null,true);}public static JsonData buildError(String msg) {return new JsonData(-1, null, msg,false);}public static JsonData buildError(Integer code, String msg) {return new JsonData(code, null, msg,false);}public Integer getCode() {return code;}public void setCode(Integer code) {this.code = code;}public String getMsg() {return msg;}public void setMsg(String msg) {this.msg = msg;}public Object getData() {return data;}public void setData(Object data) {this.data = data;}public boolean getSuccess() {return success;}public void setSuccess(boolean success) {this.success = success;}
}

其他相关类,小伙伴们看源码吧,见2.3小节

四、调试部分
4.1. 模式切换

在这里插入图片描述

4.2. api执行流程

在这里插入图片描述

4.3. 报文赏评

调用login的api返回报文

{"code": "uXGXKHjUcNLbtO0sBNylDpOHmpgmXTnNkDLVMYWu7MQ"
}

调用后端获取用户信息接口返回的报文

{"success": true,"code": 0,"msg": null,"data": {"corpid": "wwea98220fdcd8a38d","deviceid": "","errcode": 0,"errmsg": "ok","session_key": "qz2VF4V3RTagW+awOAZdpA==","token": "tobdeveyJhbGciOiJIUzI1NiJ9.eyJzdWIiOiJ0b2JkZXYiLCJjb3JwX2lkIjoid3cxN2Y4ZDEwNzgzNDk0NTg0IiwiaWF0IjoxNjQyNDI3ODUyLCJleHAiOjE2NDMwMzI2NTJ9.965kwCYUt6h-BeCA-WUaf20LrHpMvzX8WYigNlkJJIQ","userid": "ZeXin"}
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/516129.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

我输给了一个 25 岁的男人

未来的你&#xff1a;小伙计你好&#xff0c;我是 10 年后的你&#xff0c;刚穿越回来&#xff0c;还是热乎的。现在的你&#xff1a;Are you sure?大哥&#xff0c;从你那憔悴的神色里可以看出日夜颠倒的作息和毫无爱情发酵的灵魂&#xff0c;随便喊个人来看看&#xff0c;咱…

阿里云公共DNS安全传输服务介绍(DoH/DoT)

概述 阿里公共DNS致力于为广大的互联网用户提供快速、稳定和安全的DNS解析。然而传统的DNS查询和应答采用UDP和TCP明文传输&#xff0c;存在网络监听、DNS劫持、中间设备干扰的风险&#xff1a; 网络监听风险&#xff1a;即便用户采用HTTPs加密的方式访问站点&#xff0c;DNS…

Excel VBA - 文件及目录操作

目录 一. 文件处理1.1 Name 语句1.2 FileCopy 语句1.3 Kill 语句1.4 GetAttr 函数1.5 SetAttr 语句1.6 FileLen 函数1.7 FileDateTime 函数二. 目录处理2.1 CurDir 函数2.1 ChDir 语句2.3 ChDrive 语句2.4 Dir 函数2.5 MkDir 语句2.6 RmDir 语句三. 文件读写3.1 Open 语句3.2 C…

企业微信小程序_集成微信小程序插件_地图选点插件

官网文档&#xff1a; https://lbs.qq.com/miniProgram/plugin/pluginGuide/locationPicker 具体操作参考官网文档即可&#xff0c;讲的很详细

一文教你如何在生产环境中在Kubernetes上部署Jaeger

作者 | Dotan Horovit翻译 | 火火酱~责编 | 晋兆雨出品 | CSDN云计算日志、指标和跟踪是“可观察性”领域的三大支柱。最近几个月&#xff0c;随着OpenTelemetry标准化以及Jaeger开源项目从CNCF孵化项目中顺利毕业&#xff0c;分布式跟踪领域出现了很多创新。根据DevOps Pulse…

一篇讲透如何理解数据库并发控制

01数据库并发控制的作用 1.1 事务的概念 在介绍并发控制前&#xff0c;首先需要了解事务。数据库提供了增删改查等几种基础操作&#xff0c;用户可以灵活地组合这几种操作&#xff0c;实现复杂的语义。在很多场景下&#xff0c;用户希望一组操作可以做为一个整体一起生效&…

工作簿长时间空闲时自动关闭

目录 1. 对关闭时间和关闭工作薄进行设置2. 利用 OnTime 方法对执行程序进行设置3. 对工作薄的变化进行设置1. 对关闭时间和关闭工作薄进行设置 在新建模块中声明一个时间作为全局的变量,该变量将是每次工作薄发生改变后延续的时间,另外再设置一个工作薄关闭的过程。 代码如…

打钱!我的数据库被黑客勒索了!

来源 | 小白学黑客责编 | 晋兆雨头图 | 付费下载于视觉中国数据库失陷昨天晚上&#xff0c;读者群里一位小伙伴发消息说自己的数据库被黑了&#xff0c;搞安全的我自然是立刻来了兴趣&#xff0c;加班加点开始分析起来&#xff0c;不知道的还以为我要熬夜等剁手节呢。这位小伙伴…

uni-app集成uview

文章目录一、uni_modules方式1. 创建uni-app项目2. 安装uview3. 安装SCSS插件二、配置步骤2.1. 引入uView主JS库2.2. 引入主题文件2.3. 引入uView基础样式2.4. 配置easycom组件模式2.5. 实战三、zip方式3.1. 创建uni-app项目3.2. 下载uview3.3. 解压重命名3.4. 拷贝UI3.5. 安装…

阿里云飞天洛神2.0:高性能网络软硬一体化技术实践

云网络架构 云计算从9年前被质疑为新瓶装旧酒&#xff0c;到经过多年的高速发展&#xff0c;正在成为水电煤一样的基础设施。云网络构建在物理网络之上&#xff0c;为云计算提供灵动、智能的网络连接。云网络的性能和稳定性是云计算的基石。 VPC是云网络的基础&#xff0c;VP…

作为后端开发如何设计数据库系列文章 设计SaaS系统表结构

在公司做了一年的SaaS内核系统&#xff0c;但是有些东西不知道能不能透露出来。我尽量在不透露一些敏感东西的情况下&#xff08;这个度我无法把控&#xff0c;只能是笼统了&#xff09;&#xff0c;将某些关于数据库方面的精髓传递出来。如果表达不畅&#xff0c;请谅解。 前…

重学 VBA - 基础与实战篇(含正则表达式)

目录 前置内容1. 单元格对象属性与方法1.1 查找最后的行、列1.1.1 End 属性1.1.2 SpecialCells 和 UsedRange1.1.3 Find 方法1.1.4 四种方法属性效果比较1.2 多重循环(案例)1.2.1 实现数据之间的匹配(不同列)1.2.2 实现数据之间的匹配(同列)1.2.3 排序 - 简单选择排序法1…

js 时间比较大小

const startTime parseInt(this.timeValue.replace(:, ));const endTime parseInt(this.timeValue2.replace(:, ));//进行比较if (startTime > endTime) {//添加校验提示console.log("startTime>endTime")} else {console.log("startTime<endTime&qu…

新一轮支付革命,利楚扫呗的数据库优化之路

中国移动支付市场崛起过程中&#xff0c;第三方、第四方等非银行支付机构在2017年至2019年之间&#xff0c;把移动支付交易量从300多亿笔拉升至近1800亿笔&#xff0c;充分彰显以扫码支付为代表的移动支付革命引领一时风潮。 利楚扫呗作为华中地区领先的金融收单企业也是其中一…

IM、RTC技术两生花,看融云如何打造“IM+RTC+Push”一站式通信云服务

11月9日&#xff0c;融云宣布完成数亿元人民币的D轮融资。从李佳琦和明星扎堆的电商直播&#xff0c;到疫情期间在线教育的全面普及&#xff0c;再到5G技术进入商用&#xff0c;实时音视频技术&#xff08;Real-Time Communication&#xff0c;以下简称RTC&#xff09;迎来了全…

Nginx实现通过不同的url前缀访问不同的前后端项目

&#xff0c;所以目前就可以通过给网页访问链接增加不同的url前缀&#xff0c;来让Nginx去实现同一端口下访问不同的前后端项目。具体配置如下&#xff1a; &#xff08;我这里是前端两个项目各自对应后端的两个服务&#xff09; server {#这里默认监听80端口&#xff0c;可根…

阿里云助力浙江大学信息化建设,以实时数据驱动校园智能管理

随着网络信息化技术的不断进步&#xff0c;就我国高校而言&#xff0c;传统的学习和生活模式已无法满足学生的需求&#xff1b;老机房堆硬件的建设&#xff0c;给信息化深度建设的管理和运维工作人员造成了巨大的麻烦。这些因素促使各所高校对校园智能管理的需求日益剧增。 20…

1 元秒杀 1000+ 册爆款电子书,错过再等一年!

wow代码人们让钱包瑟瑟发抖的双十一已经来啦与此同时码不停蹄地向你奔赴而来的还有 CSDN 为你准备的???? 1 元秒杀 ????价值 3.5 万元的爆款电子书限时特惠&#xff0c;仅需 1 元你&#xff0c;准备好了吗仅限 1000 人速领????????????错过悔10年系列好书

vue 单独页面定时器 离开页面销毁定时器

data: {return {timer: null} }, created() {this.timer setInterval(....); }, beforeDestroy() {if(this.timer) { //如果定时器还在运行 或者直接关闭&#xff0c;不用判断clearInterval(this.timer); //关闭} }

谊品生鲜:放弃传统数据库架构,全站上阿里云

疫情之下&#xff0c;生鲜电商的订单突然暴涨。 社区生鲜龙头企业谊品生鲜就是一个典型代表。它的在线交易量激增&#xff0c;日订单量超过10万单。 对电商企业而言&#xff0c;这对业务是个巨大的好消息&#xff1b;但对于IT、对于谊品生鲜的核心业务系统则是一个巨大的挑战…