前言
企業微信第三方應用登錄有兩種方式網頁授權登錄和掃碼授權登錄:
官網文檔詳解
登錄操作,需要與前端進行合作開發,我這邊只有寫了后端的開發流程及代碼
一、掃碼授權登錄
1、掃碼授權登錄需要進入服務商后台->應用管理->登錄授權配置我們發起授權的域名(參考企業微信第三方應用(一)配置)
2、需要用到的參數

3、用戶進入登錄授權頁后,需要確認並同意將自己的企業微信和登錄賬號信息授權給企業或服務商,完成授權流程
4、授權后回調URI,得到授權碼和過期時間,授權流程完成后,會進入回調URI,並在URL參數中返回授權碼,跳轉地址
5、獲取登錄用戶信息
二、網頁授權登錄
1、構造網頁授權鏈接
2、所需要用到的參數

3、獲取訪問用戶身份
掃碼授權登錄和網頁授權登錄之后,獲取訪問用戶的身份需用用到一個入參code,這個入參code需要前端給出(點擊登錄按鈕,訪問OAuth2網頁授權鏈接獲取微信授權code【前端處理】)
三、開始開發
控制層:WeChatThirdController
package com.wechat.controller;
import com.wechat.entity.wechat.WeChatLoginUrl;
import com.wechat.entity.wechat.WeChatUserinfo3rd;
import com.wechat.entity.wechat.WechatUserInfo;
import com.wechat.service.IWeChatService;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
/**
* 第三方應用操作
*
* @author: wx
* @date: 2022/4/1
*/
@Slf4j
@RestController
@RequestMapping(value = "wechat")
public class WeChatThirdController {
@Autowired
private IWeChatService weChatService;
/**
* 獲取掃碼登錄地址
*/
@ApiOperation(value = "獲取掃碼登錄地址")
@PostMapping(value = "login")
public WeChatLoginUrl login(){
//獲取掃碼登錄地址
return weChatService.thirdLoginUrl();
}
/**
* 企業微信內登錄地址
*/
@ApiOperation(value = "企業微信內登錄")
@PostMapping(value = "wechatLogin")
public WeChatLoginUrl wechatLogin(){
//獲取企業微信內登錄地址
return weChatService.wechatLoginUrl();
}
/**
* 前端回調->掃碼授權登錄-獲取訪問用戶身份
*/
@ApiOperation(value = "獲取訪問用戶身份")
@PostMapping(value = "getUserInfo")
public WechatUserInfo getUserInfo(String code){
//獲取訪問用戶身份
return weChatService.getUserInfo(code);
}
/**
* 前端回調->網頁授權登錄-獲取訪問用戶身份
*/
@ApiOperation(value = "獲取訪問用戶身份")
@PostMapping(value = "getUserinfo3rd")
public WeChatUserinfo3rd getUserinfo3rd(String code){
//獲取訪問用戶身份
return weChatService.getUserinfo3rd(code);
}
}
服務層:IWeChatService
package com.wechat.service;
import com.wechat.entity.wechat.WeChatLoginUrl;
import com.wechat.entity.wechat.WeChatUserinfo3rd;
import com.wechat.entity.wechat.WechatUserInfo;
/**
* 第三方應用服務層
*/
public interface IWeChatService {
/**
* 獲取企業永久碼
*/
void getPermanentCode(String authCode);
/**
* 掃碼登錄-獲取用戶信息
*/
WechatUserInfo getUserInfo(String code);
/**
* 網頁授權登錄-獲取用戶信息
*/
WeChatUserinfo3rd getUserinfo3rd(String code);
/**
* 獲取掃碼登錄地址
*/
WeChatLoginUrl thirdLoginUrl();
/**
* 獲取企業微信內登錄地址
*/
WeChatLoginUrl wechatLoginUrl();
}
服務實現層impl:WeChatServiceImpl
package com.wechat.service.impl;
import cn.hutool.http.ContentType;
import cn.hutool.http.HttpRequest;
import cn.hutool.json.JSONUtil;
import com.wechat.common.WeChatConstants;
import com.wechat.common.WeChatUtils;
import com.wechat.common.cache.CacheData;
import com.wechat.entity.wechat.WeChatLoginUrl;
import com.wechat.entity.wechat.WeChatPermanentCodeReturn;
import com.wechat.entity.wechat.WeChatUserinfo3rd;
import com.wechat.entity.wechat.WechatUserInfo;
import com.wechat.service.IWeChatService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import java.util.HashMap;
import java.util.Map;
/**
* 第三方應用服務層
*/
@Slf4j
@Service
public class WeChatServiceImpl implements IWeChatService {
/**
* 構造掃碼登錄鏈接
*/
@Override
public WeChatLoginUrl thirdLoginUrl() {
WeChatLoginUrl login = new WeChatLoginUrl();
// 企業微信的CorpID
String corpId = WeChatConstants.CORP_ID;
// 重定向url
String redirectUrl = WeChatConstants.REDIRECT_URL;
log.debug("登錄地址url:"+redirectUrl+"企業微信corpId->"+corpId);
// 重定向地址
String redirectUri = "";
try {
redirectUri = URLEncoder.encode((redirectUrl), "UTF-8");
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
throw new RuntimeException(e.getMessage());
}
// 獲取掃碼登錄鏈接
String getWechatLogin = WeChatUtils.THIRD_BUS_WECHAT_LOGIN;
// 轉換成登錄地址
String loginUrl = getWechatLogin.replace(WeChatConstants.CORP_ID, corpId).replace(WeChatConstants.REDIRECT_URI,redirectUri);
login.setLoginUrl(loginUrl);
log.debug("重定向后登錄地址url:"+login);
return login;
}
/**
* 構造企業微信內登錄鏈接
*/
@Override
public WeChatLoginUrl wechatLoginUrl() {
log.debug("wechatLogin->start");
WeChatLoginUrl login = new WeChatLoginUrl();
// 第三方應用id(即ww或wx開頭的suite_id)。
String suiteId = WeChatConstants.SUITE_ID;
// 重定向地址
String redirectUrl = WeChatConstants.REDIRECT_URL;
log.debug("suiteId:"+suiteId+"==redirectUrl:"+redirectUrl);
// 重定向地址
try {
redirectUrl = URLEncoder.encode(redirectUrl, "UTF-8");
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
throw new RuntimeException(e.getMessage());
}
//第三方 構造網頁授權鏈接
String getWechatLogin = WeChatUtils.THIRD_BUS_WECHAT_AUTHORIZE_URL;
// 轉換成登錄地址
String loginUrl = getWechatLogin.replace(WeChatConstants.APP_ID, suiteId).replace(WeChatConstants.REDIRECT_URI,redirectUrl);
login.setLoginUrl(loginUrl);
log.debug("企業微信內登錄重定向url:"+loginUrl);
return login;
}
/**
* 獲取企業永久碼
*/
@Override
public void getPermanentCode(String authCode) {
// 永久授權碼
log.debug("獲取企業永久授權碼->getPermanentCode->start");
// 第三方應用access_token
String suiteToken = (String)CacheData.get("SUITE_TOKEN");
// 獲取企業永久授權碼url
String accessTokenUrl = WeChatUtils.THIRD_BUS_WECHAT_ACCESS_TOKEN;
// 替換值
accessTokenUrl = accessTokenUrl.replace("SUITE_ACCESS_TOKEN", suiteToken);
try {
Map<String, Object> map = new HashMap<>();
map.put("auth_code", authCode);
log.debug("獲取企業永久授權碼accessTokenUrl:"+accessTokenUrl+"->auth_code:"+authCode);
String body = HttpRequest.post(accessTokenUrl).body(JSONUtil.toJsonStr(map), ContentType.JSON.getValue()).execute().body();
WeChatPermanentCodeReturn weChat = JSONUtil.toBean(body, WeChatPermanentCodeReturn.class);
log.debug("獲取企業永久授權碼轉換成bean->weChat:"+weChat);
//授權方(企業)access_token
String accessToken = weChat.getAccess_token();
//授權方企業微信id
String corpId = weChat.getAuth_corp_info().getCorpid();
//授權方企業微信名稱
String corpName = weChat.getAuth_corp_info().getCorp_name();
//授權方應用id
Long agentId = weChat.getAuth_info().getAgent().get(0).getAgentid();
//用戶id
String userId = weChat.getAuth_user_info().getUserid();
//企業永久授權碼
String permanentCode = weChat.getPermanent_code();
//存放到cache中
CacheData.put(WeChatConstants.ACCESS_TOKEN, accessToken);
//授權方企業微信id
CacheData.put(WeChatConstants.AUTH_CORPID, corpId);
//授權方企業微信名稱
CacheData.put(WeChatConstants.CORP_NAME, corpName);
//授權方應用id
CacheData.put(WeChatConstants.AGENT_ID, agentId);
//用戶id
CacheData.put(WeChatConstants.USER_ID, userId);
//獲取企業永久授權碼
CacheData.put(WeChatConstants.PERMANENT_CODE, permanentCode);
log.debug("獲取企業永久授權碼->PERMANENT_CODE:"+permanentCode);
} catch (Exception e) {
log.debug("獲取accessToken失敗errcode");
throw new RuntimeException();
}
log.debug("獲取企業永久授權碼->getPermanentCode->end");
}
/**
* 獲取用戶信息
*/
@Override
public WechatUserInfo getUserInfo(String code) {
// 授權登錄服務商的網站時,使用應用提供商的provider_access_toke
String providerSccessToken = (String) CacheData.get(WeChatConstants. PROVIDER_ACCESS_TOKEN);
// 獲取掃碼登錄鏈接url
String getUserInfo = WeChatUtils.THIRD_BUS_WECHAT_GET_LOGIN_INFO;
// 獲取登錄用戶信息
String getUserInfoUrl = getUserInfo.replace(WeChatConstants.PROVIDER_ACCESS_TOKEN, providerSccessToken);
log.debug("getUserInfo->獲取登錄用戶信息Url->"+getUserInfoUrl);
// 使用http請求調用
Map<String, Object> mapCode = new HashMap<>();
mapCode.put("auth_code", code);
String body = HttpRequest.post(getUserInfoUrl).body(JSONUtil.toJsonStr(mapCode), ContentType.JSON.getValue()).execute().body();
WechatUserInfo userInfo = null;
String userId = "";
try {
// 獲取用戶信息
userInfo = JSONUtil.toBean(body, WechatUserInfo.class);
log.debug("getUserInfo->獲取用戶信息轉換成bean:"+JSONUtil.toJsonStr(userInfo));
if(userInfo.getErrcode() == null || userInfo.getErrcode() == 0){
// 用戶id
userId = userInfo.getUser_info().getUserid();
userInfo.setUserId(userId);
} else{
throw new RuntimeException(userInfo.getErrmsg());
}
log.debug("獲取訪問用戶身份成功");
} catch (Exception e) {
log.debug("獲取訪問用戶身份失敗");
throw new RuntimeException(userInfo.getErrmsg());
}
log.debug("getUserInfo->end->userInfo:"+JSONUtil.toJsonStr(userInfo));
return userInfo;
}
/**
* 網頁授權登錄-獲取用戶信息
*/
@Override
public WeChatUserinfo3rd getUserinfo3rd(String code) {
//授權登錄服務商的網站時,第三方應用access_token
String suiteToken = (String) CacheData.get(WeChatConstants.SUITE_TOKEN);
// 獲取掃碼登錄鏈接url
String getUserinfo3rdUrl = WeChatUtils.THIRD_BUS_WECHAT_GET_USER_INFO;
// 替換
getUserinfo3rdUrl = getUserinfo3rdUrl.replace(WeChatConstants.SUITE_TOKEN, suiteToken).replace(WeChatConstants.CODE, code);
log.debug("獲取訪問用戶身份url:"+getUserinfo3rdUrl);
// 使用http請求調用
String body = HttpRequest.get(getUserinfo3rdUrl).execute().body();
WeChatUserinfo3rd userInfo = null;
String userId = "";
try {
// 取部門列表信息
userInfo = JSONUtil.toBean(body, WeChatUserinfo3rd.class);
log.debug("獲取訪問用戶身份userInfo轉換成bean:"+JSONUtil.toJsonStr(userInfo));
if(userInfo.getErrcode() == null || userInfo.getErrcode() == 0){
// 用戶id
userId = userInfo.getUserId();
userInfo.setUserId(userId);
} else{
throw new RuntimeException(userInfo.getErrmsg());
}
String success = String.format("獲取訪問用戶身份成功", userId ,userInfo.getErrcode());
log.debug(success);
} catch (Exception e) {
String error = String.format("獲取訪問用戶身份失敗", userInfo.getErrcode() ,userInfo.getErrmsg());
log.debug(error);
throw new RuntimeException(userInfo.getErrmsg());
}
log.debug("getUserinfo3rd->end:"+JSONUtil.toJsonStr(userInfo));
return userInfo;
}
}
實體類:WechatUserInfo
package com.wechat.entity.wechat;
import lombok.Data;
import lombok.NoArgsConstructor;
/**
* 獲取訪問用戶身份返回值
*
* @author: wx
* @date: 2021/12/31
*/
@NoArgsConstructor
@Data
public class WechatUserInfo {
private Integer errcode;
private String errmsg;
private String userId;
private UserInfo user_info;
private CorpInfo corp_info;
private Integer status;
public static class UserInfo{
private String userid;
private String open_userid;
private String name;
public String getUserid() {
return userid;
}
public void setUserid(String userid) {
this.userid = userid;
}
public String getOpen_userid() {
return open_userid;
}
public void setOpen_userid(String open_userid) {
this.open_userid = open_userid;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
public static class CorpInfo{
private String corpid;
public String getCorpid() {
return corpid;
}
public void setCorpid(String corpid) {
this.corpid = corpid;
}
}
}
實體類:WeChatUserinfo3rd
package com.wechat.entity.wechat;
import lombok.Data;
import lombok.NoArgsConstructor;
/**
* 獲取訪問用戶身份
* 網頁登錄
*
* @author: wx
* @date: 2022/2/23
*/
@NoArgsConstructor
@Data
public class WeChatUserinfo3rd {
private Integer errcode;
private String errmsg;
private String CorpId;
private String UserId;
private String DeviceId;
private String user_ticket;
private String open_userid;
private Integer status;
}
實體類:WeChatLoginUrl
package com.wechat.entity.wechat;
import lombok.Data;
import lombok.NoArgsConstructor;
/**
* 登錄url地址
*
* @author: wx
* @date: 2022/2/21
*/
@NoArgsConstructor
@Data
public class WeChatLoginUrl {
private String loginUrl;
}
驗證:
1、掃碼方式


用企業微信掃碼登錄成功后,會回調用戶信息接口,如下圖:

2、網頁方式


總結
以上就是實現登錄和獲取用戶信息的功能!
1、企業微信第三方應用如何配置
2、api接口如何調用
3、如何獲取三種token
4、實現兩種登錄方式
5、獲取用戶信息
上面五個內容完成了基礎的企業微信第三方應用的開發,后面可以根據實際業務去調用企業微信第三方應用的api,方式同上面類似。
GitHub源碼地址:https://github.com/18606199546/third-wechat/
Gitee源碼地址:https://gitee.com/allenxiao/third-wechat
