文章目录

  • 一、前置知识
    • 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. 报文赏评
一、前置知识
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"}
}

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

  1. 微信小程序之授权登录

    微信小程序之授权登录 之前微信授权登录时是直接可以通过getUserInfo接口 弹出授权弹窗.由于微信官方修改了 getUserInfo 接口,所以现在无法实现一进入微信小程序就弹出授权窗口,只能通 ...

  2. 微信登录 后台 java_Java 后端 (Spring boot)+微信小程序的授权登录

    微信小程序的授权登录 第一.Java后端代码如下 登录的接口的参数是微信小程序前端必须要传的参数微信小程序登录.授权的用户基本信息 wx.getUserInfo 特别注意 appid 和secret. ...

  3. 微信小程序之授权登录(附完整源码)

    个人博客上已经同步更新了文章,有目录索引,阅读起来比较方便,欢迎大家移步个人博客上读阅~ 个人博客地址:http://zwd596257180.gitee.io/blog/2019/04/15/wec ...

  4. 微信小程序开发——点击按钮获取用户授权没反应或反应很慢的解决方法

    微信小程序开发--点击按钮获取用户授权没反应或反应很慢的解决方法 参考文章: (1)微信小程序开发--点击按钮获取用户授权没反应或反应很慢的解决方法 (2)https://www.cnblogs.co ...

  5. 企业微信小程序_小程序开发工具及真机调试_host配置及代理

    文章目录 一.开发前准备 1. 开发文档 2. 工具安装 3. 安装插件 4. 调整编译模式 5. 选择企业 6. PC 调试前端 7. PC 调试后端 二.甄姬调试前端 2.1. 预览小程序 2.2 ...

  6. 企业微信小程序_获取准确定位的方法及解决定位不准确的问题

    文章目录 一.经验分享 1. 微信api现状 2. 解决方案 3. 适用场景 二.小程序集成腾讯定位服务 2.1. 注册腾讯开发者 2.2. 创建应用 2.3. 添加key 2.4. 下载sdk 2. ...

  7. 微信小程序之授权登录--项目需要

    1.由于项目需要,需要实现自己的微信小程序 用微信授权登录. 2.参考此项目https://blog.csdn.net/weidong_y/article/details/79636386 3.其中的 ...

  8. 微信小程序手机号授权登录

    文章目录 小程序端 服务端 注意事项 微信小程序,手机号授权登录需求. 大体流程是这样的: 小程序端使用 getPhoneNumber 向微信平台获取授权 通过微信授权后,小程序端接收微信授权后的回调 ...

  9. 【Springboot】整合wxjava实现 微信小程序:授权登录

    文章目录 一.wxjava是什么 二.使用步骤 1.引入依赖 2.配置yml 3.小程序的配置 4.后端的业务逻辑代码 controller service impl dto 5.前端的业务逻辑代码 ...

最新文章

  1. AC日记——中位数 洛谷 P1168
  2. MySQL—【加餐1】高效查询方法
  3. Split in Java
  4. optee中TA的堆的分配
  5. TCP滑动窗口和拥塞控制机制
  6. Github Pages建立个人博客
  7. scrapyd远程连接配置
  8. BZOJ 1013 球形空间产生器
  9. java jdbc 参数_java_jdbc_可变参数_MetaData
  10. 工具:帆软FineBI使用指南
  11. 人工智能、机器学习、神经网络和深度学习的发展历程(上)
  12. 携程帐号变更函(对私)
  13. Excel PivotTable 使用心得手顺分享(二)
  14. python列表获取最后一个元素的方法_Python中如何获取 list/OrderedDict 的 第一个/最后一个 元素...
  15. FCPX视频剪辑Final Cut Pro X v10.5.4中文版 Macbook支持Silicon M1 附详细安装教程
  16. JavaScript - 简介
  17. 冷笑话 企鹅与北极熊
  18. NC 前端修改数据库的方法
  19. 成功的背后(给所有IT人)—从高考落榜到IT奇才
  20. 二叉树的镜像——《剑指offer》

热门文章

  1. “数学物理反问题”:专门研究“关系”,常跟工程师打交道
  2. blockly自定义中文出问题_[BlocklyNukkit入门]#5自定义物品
  3. 6大设计原则之接口隔离原则
  4. Mybatis介绍、jdbc操作数据库原始写法以及Mybatis架构
  5. socket网络编程多线程
  6. spark 提交至yarn异常超时 Client cannot authenticate via:[TOKEN, KERBEROS]
  7. IT人的年夜饭,也太香了吧
  8. E百科 | 第2期 扒一扒能加速互联网的QUIC协议
  9. 后疫情时代,银行从数字化转型到智能化“迁徙”
  10. ServiceMesh最火项目:Istio架构解析