企业应用(阿里商旅)集成 钉钉 与 微信 实现SSO单点登陆
1.钉钉准备工作
(1) 创建应用
https://open-dev.dingtalk.com/fe/app#/corp/app

(2)获取应用凭证
记录 AgentId AppKey AppSecret

(3)开通权限
开通需要的权限,并指定范围

(4)设置应用首页
构建单点登陆连接可参考 https://open.dingtalk.com/document/orgapp-server/logon-free-third-party-websites

(5)发布应用

2.微信准备工作
(1)添加应用

(2)获取应用凭证

并在我的企业中记录企业的CorpIDID

(3)设置可信域名

(4)设置工作台应用主页
此处设置的即为跳转的连接,将会携带当前授权的用户code

3.代码
(1)项目依赖
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.example</groupId>
<artifactId>Alibtrip_Sso</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>Alibtrip_Sso</name>
<description>Alibtrip_Sso</description>
<properties>
<java.version>1.8</java.version>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
<spring-boot.version>2.3.7.RELEASE</spring-boot.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-boot-starter</artifactId>
<version>3.4.2</version>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
<exclusions>
<exclusion>
<groupId>org.junit.vintage</groupId>
<artifactId>junit-vintage-engine</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>com.aliyun</groupId>
<artifactId>btripopen20220520</artifactId>
<version>1.0.13</version>
</dependency>
<dependency>
<groupId>com.aliyun</groupId>
<artifactId>dingtalk</artifactId>
<version>1.4.43</version>
</dependency>
<dependency>
<groupId>com.aliyun</groupId>
<artifactId>alibaba-dingtalk-service-sdk</artifactId>
<version>2.0.0</version>
</dependency>
<dependency>
<groupId>com.github.ben-manes.caffeine</groupId>
<artifactId>caffeine</artifactId>
<version>2.9.3</version>
</dependency>
<dependency>
<groupId>commons-httpclient</groupId>
<artifactId>commons-httpclient</artifactId>
<version>3.1</version>
</dependency>
<dependency>
<groupId>org.apache.httpcomponents</groupId>
<artifactId>httpclient</artifactId>
<version>4.5.13</version>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
<version>2.0.13</version>
</dependency>
</dependencies>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-dependencies</artifactId>
<version>${spring-boot.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
</project> (2)application.properties 配置文件
# 应用名称 spring.application.name=alibtrip_sso spring.profiles.active=dev logging.level.root=INFO logging.level.org.springframework=WARN logging.level.org.spring.springboot.dao=DEBUG logging.level.com.accenture.fssc.hdl.mapper=DEBUG logging.config=classpath:logback-dev.xml logging.path=./log/alitrip # 应用服务 WEB 访问端口 server.port=9712 #阿里商旅配置 alibtrip.appKey= alibtrip.appSecret= #类型,0-自营 1-分销 alibtrip.corpTokenType= #企业代理id,值可以在开放平台中的关联企业查看企业代理id。 alibtrip.corpTokenCorpId= #钉钉配置 dingding.url= #应用id dingding.app.agentid= #应用key dingding.app.key= #应用秘钥 dingding.app.secret= #微信配置 wechat.corpid= wechat.corpsecret= wechat.getTokenUri= wechat.getUserIdUri= wechat.readUserUri=
(3)Controller 层
AlibtripController
@Slf4j
@RequestMapping("/alibtrip")
@Controller
public class AlibtripController {
private static final String URL_GET_USERINFO_BY_CODE = "https://oapi.dingtalk.com/sns/getuserinfo_bycode";
@RequestMapping("/dingding2TripCode")
public void dingding2TripCode(@RequestParam("code")String code,HttpServletResponse response) {
try {
AlibTripService dingdingAlibTrip = (AlibTripService) SpringBeanUtils.getBean("dingdingAlibTrip");
String redirectUrl = dingdingAlibTrip.invokeAddressGet(code);
response.sendRedirect(redirectUrl);
} catch (Exception e) {
log.error("dingding 重定向 trip出错 {}", e);
}
}
@RequestMapping("/dingding2TripWX")
public void dingding2TripWX(@RequestParam("code")String code,HttpServletResponse response) {
try {
AlibTripService wxAlibTrip = (AlibTripService) SpringBeanUtils.getBean("wxAlibTrip");
String redirectUrl = wxAlibTrip.invokeAddressGet(code);
response.sendRedirect(redirectUrl);
} catch (Exception e) {
log.error("WX 重定向 trip出错 {}", e);
}
}
} (4)Service层
AbstractDingDing
public abstract class AbstractDingDing {
public abstract String getAccessToken(String code);
public abstract String getUserId(String token, String code);
} AlibTripService
public interface AlibTripService {
String invokeAddressGet(String param);
} AlibTripServiceAbstract
@Slf4j @Component public abstract class AlibTripServiceAbstract implements AlibTripService{ @Autowired private ClientUtils clientUtils; @Autowired private CorpTokenUtils corpTokenUtils; public abstract String getUserId(String param); @Override public String invokeAddressGet(String param) { String empId = getUserId(param); String addressGetUrl = null; Client client = clientUtils.getClient(); String cropToken = corpTokenUtils.getToken(); AddressGetHeaders addressGetHeaders = new AddressGetHeaders(); addressGetHeaders.setXAcsBtripSoCorpToken(cropToken); AddressGetRequest addressGetRequest = new AddressGetRequest(); addressGetRequest.setUserId(empId); addressGetRequest.setActionType(4); try { AddressGetResponse addressGetResponse = client.addressGetWithOptions(addressGetRequest, addressGetHeaders, new RuntimeOptions()); AddressGetResponseBody body = addressGetResponse.body; //success的场景 addressGetUrl = body.module.getUrl(); } catch ( TeaException e) { String code = e.getCode(); String msg = e.getMessage(); Map<String, Object> data = e.getData(); //failed的场景 } catch (Exception e) { //其他异常处理 log.error("invokeAddressGet 出错 {}",e); } return addressGetUrl; } }
AlibTripServiceImpl
@Slf4j
@Service
public class AlibTripServiceImpl implements AlibTripService {
@Autowired
private ClientUtils clientUtils;
@Autowired
private CorpTokenUtils corpTokenUtils;
@Autowired
private WeChatUtil weChatUtil;
@Autowired
@Qualifier("oldDingDing")
private AbstractDingDing abstractDingDing;
public String dingding2Trip(String code) {
String accessToken = abstractDingDing.getAccessToken(code);
String userId = abstractDingDing.getUserId(accessToken, code);
String addressGet = invokeAddressGet(userId);
return addressGet;
}
public String dingding2TripWX(String code) {
String accessToekn = weChatUtil.getAccessToekn();
String userId = weChatUtil.getUserId(accessToekn, code);
String empId = weChatUtil.getEmpId(accessToekn, userId);
String addressGet = invokeAddressGet(empId);
return addressGet;
}
@Override
public String invokeAddressGet(String empId) {
String addressGetUrl = null;
Client client = clientUtils.getClient();
String cropToken = corpTokenUtils.getToken();
AddressGetHeaders addressGetHeaders = new AddressGetHeaders();
addressGetHeaders.setXAcsBtripSoCorpToken(cropToken);
AddressGetRequest addressGetRequest = new AddressGetRequest();
addressGetRequest.setUserId(empId);
addressGetRequest.setActionType(4);
try {
AddressGetResponse addressGetResponse = client.addressGetWithOptions(addressGetRequest, addressGetHeaders, new RuntimeOptions());
AddressGetResponseBody body = addressGetResponse.body;
//success的场景
addressGetUrl = body.module.getUrl();
} catch (
TeaException e) {
String code = e.getCode();
String msg = e.getMessage();
Map<String, Object> data = e.getData();
//failed的场景
} catch (Exception e) {
//其他异常处理
log.error("invokeAddressGet 出错 {}",e);
}
return addressGetUrl;
}
} DingDingAlibTripService
@Service("dingdingAlibTrip")
public class DingDingAlibTripService extends AlibTripServiceAbstract {
@Autowired
@Qualifier("oldDingDing")
private AbstractDingDing abstractDingDing;
@Override
public String getUserId(String code) {
String accessToken = abstractDingDing.getAccessToken(code);
String userId = abstractDingDing.getUserId(accessToken, code);
return userId;
}
} WXAlibTripSevice
@Service("wxAlibTrip")
public class WXAlibTripSevice extends AlibTripServiceAbstract {
@Autowired
private WeChatUtil weChatUtil;
@Override
public String getUserId(String code) {
String accessToekn = weChatUtil.getAccessToekn();
String userId = weChatUtil.getUserId(accessToekn, code);
String empId = weChatUtil.getEmpId(accessToekn, userId);
return empId;
}
} (5)工具类
AccessTokenUtils
@Slf4j @Component public class AccessTokenUtils { @Value("${alibtrip.appKey}") private String appKey; @Value("${alibtrip.appSecret}") private String appSecret; @Autowired private ClientUtils clientUtils; private AccessTokenUtils() { } ; private final String key = CacheKeyEnum.ACCESS_TOKEN_KEY.key; public String getToken() { Object ifPresent = accessTokenCache.getIfPresent(key); if (ifPresent == null) { synchronized (AccessTokenUtils.class) { if (ifPresent == null) { String accessToken = initAccessToken(); accessTokenCache.put(key, accessToken); return accessToken; } } } return (String) ifPresent; } private Cache<Object, Object> accessTokenCache = Caffeine.newBuilder().refreshAfterWrite( 7000000, TimeUnit.MILLISECONDS ).build(new CacheLoader<Object, Object>() { @Override public @Nullable Object reload(@NonNull Object key, @NonNull Object oldValue) throws Exception { String corpToken = initAccessToken(); if (corpToken == null) { return accessTokenCache.get(key, null); } return corpToken; } @Override public @Nullable Object load(Object key) throws Exception { String corpToken = initAccessToken(); if (corpToken == null) { return accessTokenCache.get(key, null); } return corpToken; } }); private String initAccessToken() { Client client = clientUtils.getClient(); try { AccessTokenRequest accessTokenCache = new AccessTokenRequest(); accessTokenCache.setAppKey(appKey); accessTokenCache.setAppSecret(appSecret); AccessTokenResponse accessTokenResponse = client.accessToken(accessTokenCache); AccessTokenResponseBody body = accessTokenResponse.body; String token = body.getData().token; return token; } catch ( TeaException e) { String code = e.getCode(); String msg = e.getMessage(); Map<String, Object> data = e.getData(); //failed的场景 StringBuffer sb = new StringBuffer(); sb.append(" code : ") .append(code) .append(" msg : ") .append(msg) .append(" data : ") .append(data); log.error(sb.toString(), e); } catch (Exception e) { //其他异常处理 log.error(LocalDateTime.now() + " initCorpToken ", e); } return null; } }
ClientUtils
@Component @Slf4j public class ClientUtils { public Client client; @Value("${alibtrip.appKey}") private String appKey; @Value("${alibtrip.appSecret}") private String appSecret; private ClientUtils() { } private void instanceClient() { Config config = new Config(); config.setAccessKeyId(appKey); config.setAccessKeySecret(appSecret); config.setProtocol("https"); config.setEndpoint("btripopen.aliyuncs.com"); try { client = new Client(config); } catch (Exception e) { e.printStackTrace(); log.error(LocalDateTime.now() + " initCorpToken ", e); } //设置签名算法 client._signatureAlgorithm = "ACS3-HMAC-SHA256"; } public Client getClient() { if (client==null){ synchronized (Object.class){ if (client==null){ instanceClient(); } } } return client; } }
CorpTokenUtils
@Slf4j @Component public class CorpTokenUtils { @Value("${alibtrip.corpTokenType}") private Integer corpTokenType; @Value("${alibtrip.corpTokenCorpId}") private String corpTokenCorpId; @Autowired private ClientUtils clientUtils; @Autowired private AccessTokenUtils accessTokenUtils; private CorpTokenUtils() { } private final String key = CacheKeyEnum.CROP_TOKEN_KEY.key; public String getToken() { Object ifPresent = corpTokenCache.getIfPresent(key); if (ifPresent == null) { synchronized (CorpTokenUtils.class) { if (ifPresent == null) { String corpToken = initCorpToken(); corpTokenCache.put(key, corpToken); return corpToken; } } } return (String) ifPresent; } private Cache<Object, Object> corpTokenCache = Caffeine.newBuilder().refreshAfterWrite( 7000000, TimeUnit.MILLISECONDS ).build(new CacheLoader<Object, Object>() { @Override public @Nullable Object reload(@NonNull Object key, @NonNull Object oldValue) throws Exception { String corpToken = initCorpToken(); if (corpToken == null) { return corpTokenCache.get(key, null); } return corpToken; } @Override public @Nullable Object load(Object key) throws Exception { String corpToken = initCorpToken(); if (corpToken == null) { return corpTokenCache.get(key, null); } return corpToken; } }); private String initCorpToken() { Client client = clientUtils.getClient(); try { CorpTokenHeaders corpTokenHeaders = new CorpTokenHeaders(); String accessTokenUtilsToken = accessTokenUtils.getToken(); corpTokenHeaders.setXAcsBtripAccessToken(accessTokenUtilsToken); CorpTokenRequest corpTokenRequest = new CorpTokenRequest(); corpTokenRequest.setType(corpTokenType); corpTokenRequest.setCorpId(corpTokenCorpId); CorpTokenResponse corpTokenResponse = client.corpTokenWithOptions(corpTokenRequest, corpTokenHeaders, new RuntimeOptions()); CorpTokenResponseBody body = corpTokenResponse.body; String token = body.getData().token; return token; } catch ( TeaException e) { String code = e.getCode(); String msg = e.getMessage(); Map<String, Object> data = e.getData(); //failed的场景 StringBuffer sb = new StringBuffer(); sb.append(" code : ") .append(code) .append(" msg : ") .append(msg) .append(" data : ") .append(data); log.error(sb.toString(), e); } catch (Exception e) { //其他异常处理 log.error(LocalDateTime.now() + " initCorpToken ", e); } return ""; } }
DingDingUtils
@Slf4j
@Component("newDingDing")
public class DingDingUtils extends AbstractDingDing {
@Value("${dingding.url}")
private String DING_URL ;
@Value("${dingding.app.agentid}")
private String AGENT_ID;
@Value("${dingding.app.key}")
private String APP_KEY; // 应用的Key
@Value("${dingding.app.secret}")
private String APP_SECRET ; // 应用的密码
com.aliyun.dingtalkcontact_1_0.Client client1 = null;
com.aliyun.dingtalkoauth2_1_0.Client client2 = null;
public static com.aliyun.dingtalkcontact_1_0.Client createClient1() throws Exception {
Config config = new Config();
config.protocol = "https";
config.regionId = "oapi.dingtalk.com";
return new com.aliyun.dingtalkcontact_1_0.Client(config);
}
public static com.aliyun.dingtalkoauth2_1_0.Client createClient2() throws Exception {
Config config = new Config();
config.protocol = "https";
config.regionId = "oapi.dingtalk.com";
return new com.aliyun.dingtalkoauth2_1_0.Client(config);
}
@Override
public String getAccessToken(String code) {
if (client2==null){
try {
client2 = DingDingUtils.createClient2();
} catch (Exception e) {
log.error("getAccessToken {}",e);
}
}
GetUserTokenRequest getUserTokenRequest = new GetUserTokenRequest()
.setClientId(APP_KEY)
.setClientSecret(APP_SECRET)
.setCode(code)
.setRefreshToken(code)
.setGrantType("authorization_code");
try {
GetUserTokenResponse userToken = client2.getUserToken(getUserTokenRequest);
return userToken.getBody().getAccessToken();
} catch (TeaException err) {
if (!com.aliyun.teautil.Common.empty(err.code) && !com.aliyun.teautil.Common.empty(err.message)) {
// err 中含有 code 和 message 属性,可帮助开发定位问题
log.error("getAccessToken {}",err);
}
} catch (Exception _err) {
TeaException err = new TeaException(_err.getMessage(), _err);
if (!com.aliyun.teautil.Common.empty(err.code) && !com.aliyun.teautil.Common.empty(err.message)) {
// err 中含有 code 和 message 属性,可帮助开发定位问题
log.error("getAccessToken {}",err);
}
}
return "";
}
@Override
public String getUserId(String accessToken, String code) {
if (client1==null){
try {
client1 = DingDingUtils.createClient1();
} catch (Exception e) {
log.error("getAccessToken {}",e);
}
}
try {
GetUserHeaders headers = new GetUserHeaders();
headers.setXAcsDingtalkAccessToken(accessToken);
GetUserResponse userWithOptions = client1.getUserWithOptions("me", headers, new RuntimeOptions());
GetUserResponseBody userWithOptionsBody = userWithOptions.getBody();
String unionId = userWithOptions.body.unionId;
} catch (TeaException err) {
if (!Common.empty(err.code) && !Common.empty(err.message)) {
// err 中含有 code 和 message 属性,可帮助开发定位问题
log.error("getAccessToken {}",err);
}
} catch (Exception _err) {
TeaException err = new TeaException(_err.getMessage(), _err);
if (!Common.empty(err.code) && !Common.empty(err.message)) {
// err 中含有 code 和 message 属性,可帮助开发定位问题
log.error("getAccessToken {}",err);
}
}
return "";
}
} HttpClientUtil
@Component @Slf4j public class HttpClientUtil { CloseableHttpClient httpclient = null; CloseableHttpResponse response = null; HttpRequestRetryHandler requestRetryHandler=new HttpRequestRetryHandler() { @Override public boolean retryRequest(IOException exception, int executionCount, HttpContext context) { if (executionCount > 3) //超过重试次数,就放弃 return false; if (exception instanceof NoHttpResponseException) {//没有响应,重试 return true; }else if (exception instanceof ConnectTimeoutException) {//连接超时,重试 return true; } else if (exception instanceof SocketTimeoutException) {//连接或读取超时,重试 return true; }else if (exception instanceof SSLHandshakeException) {//本地证书异常 return false; } else if (exception instanceof InterruptedIOException) {//被中断 return false; } else if (exception instanceof UnknownHostException) {//找不到服务器 return false; } else if (exception instanceof SSLException) {//SSL异常 return false; } else { log.info("出现异常"); } HttpClientContext clientContext = HttpClientContext.adapt(context); HttpRequest request = clientContext.getRequest(); // 如果请求是幂等的,则重试 if (!(request instanceof HttpEntityEnclosingRequest)) return true; return false; } }; public String doGet(String url, Map<String, String> map) { String returnJson = ""; try { RequestConfig globalConfig = RequestConfig.custom() .setSocketTimeout(10000) .setConnectTimeout(10000) .setCookieSpec(CookieSpecs.IGNORE_COOKIES).build(); httpclient = HttpClients.custom() .setRetryHandler(requestRetryHandler) .setDefaultRequestConfig(globalConfig).build(); HttpGet httpGet = new HttpGet(url); // httpGet.setProtocolVersion(HttpVersion.HTTP_1_0); // httpGet.addHeader(HTTP.CONN_DIRECTIVE, HTTP.CONN_CLOSE); // httpGet.addHeader(HTTP.CONTENT_TYPE, // "application/x-www-form-urlencoded;charset=UTF-8"); for (String key : map.keySet()) { httpGet.addHeader(key, map.get(key)); } response = httpclient.execute(httpGet); HttpEntity entity = response.getEntity(); if (entity != null) { returnJson = "" + EntityUtils.toString(entity, "UTF-8"); } log.info(returnJson); } catch (Exception e) { log.error("连接超时",e); throw new RuntimeException(e); } finally { closeHttp(); } return returnJson; } public String doPost(String url, String data, Map<String, String> headermap, Map<String, String> bodymap) { String returnJson = ""; try { RequestConfig globalConfig = RequestConfig.custom() .setSocketTimeout(10000) .setConnectTimeout(10000) .setCookieSpec(CookieSpecs.IGNORE_COOKIES).build(); //客户端请求 httpclient = HttpClients.custom() .setRetryHandler(requestRetryHandler) .setDefaultRequestConfig(globalConfig).build(); HttpPost httpPost = new HttpPost(url); // 设置header if (bodymap != null) { for (String key : headermap.keySet()) { httpPost.addHeader(key, headermap.get(key)); } } // 设置body if (bodymap != null) { List<NameValuePair> pairs = new ArrayList<NameValuePair>(); for (Map.Entry<String, String> entry : bodymap.entrySet()) { pairs.add(new BasicNameValuePair(entry.getKey(), entry .getValue())); } httpPost.setEntity(new UrlEncodedFormEntity(pairs, "UTF-8")); } // 参数动态传入 // StringEntity se = new StringEntity("data=" + json, "UTF-8"); if (data != null && !data.equals("")) { StringEntity se = new StringEntity(data, "UTF-8"); se.setContentEncoding("UTF-8"); se.setContentType("application/json");// 发送json需要设置contentType httpPost.setEntity(se); } response = httpclient.execute(httpPost); // 解析返结果 HttpEntity entity = response.getEntity(); if (entity != null) { returnJson = "" + EntityUtils.toString(entity, "UTF-8"); } } catch (Exception e) { log.error("连接超时",e); throw new RuntimeException(e); } finally { closeHttp(); } return returnJson; } public void closeHttp() { try { if (httpclient != null) { httpclient.close(); } if (response != null) { response.close(); } } catch (Exception e) { e.printStackTrace(); } } }
OldDingDingUtis
@Slf4j
@Component("oldDingDing")
public class OldDingDingUtis extends AbstractDingDing {
@Value("${dingding.url}")
private String DING_URL ;
@Value("${dingding.app.agentid}")
private String AGENT_ID;
@Value("${dingding.app.key}")
private String APP_KEY; // 应用的Key
@Value("${dingding.app.secret}")
private String APP_SECRET ; // 应用的密码
// 获取钉钉token
public String getAccessToken() {
String result = null;
DefaultDingTalkClient client = new DefaultDingTalkClient(DING_URL + "/gettoken");
OapiGettokenRequest request = new OapiGettokenRequest();
request.setAppkey(APP_KEY);
request.setAppsecret(APP_SECRET);
request.setHttpMethod("GET");
try {
OapiGettokenResponse response = client.execute(request);
result = response.isSuccess() ? response.getAccessToken() : null;
} catch (ApiException e) {
log.error("获取钉钉AccessToken错误 {}" , e);
}
return result;
}
@Override
public String getAccessToken(String code) {
return getAccessToken();
}
@Override
public String getUserId(String token, String code)
{
OapiV2UserGetResponse rspGetResponse = null;
try {
// 通过临时授权码获取授权用户的个人信息
DefaultDingTalkClient client2 = new DefaultDingTalkClient("https://oapi.dingtalk.com/sns/getuserinfo_bycode");
OapiSnsGetuserinfoBycodeRequest reqBycodeRequest = new OapiSnsGetuserinfoBycodeRequest();
reqBycodeRequest.setTmpAuthCode(code);
OapiSnsGetuserinfoBycodeResponse bycodeResponse = client2.execute(reqBycodeRequest, APP_KEY, APP_SECRET);
// 根据unionid获取userid
String unionid = bycodeResponse.getUserInfo().getUnionid();
DingTalkClient clientDingTalkClient = new DefaultDingTalkClient("https://oapi.dingtalk.com/topapi/user/getbyunionid");
OapiUserGetbyunionidRequest reqGetbyunionidRequest = new OapiUserGetbyunionidRequest();
reqGetbyunionidRequest.setUnionid(unionid);
OapiUserGetbyunionidResponse oapiUserGetbyunionidResponse = clientDingTalkClient.execute(reqGetbyunionidRequest, token);
// 根据userId获取用户信息
String userid = oapiUserGetbyunionidResponse.getResult().getUserid();
DingTalkClient clientDingTalkClient2 = new DefaultDingTalkClient(
"https://oapi.dingtalk.com/topapi/v2/user/get");
OapiV2UserGetRequest reqGetRequest = new OapiV2UserGetRequest();
reqGetRequest.setUserid(userid);
reqGetRequest.setLanguage("zh_CN");
rspGetResponse = clientDingTalkClient2.execute(reqGetRequest, token);
return rspGetResponse.getResult().getJobNumber();
} catch (ApiException e) {
e.printStackTrace();
}
return "";
}
} SpringBeanUtils
@Component public class SpringBeanUtils implements ApplicationContextAware { private static ApplicationContext app; @Override public void setApplicationContext(ApplicationContext applicationContext) throws BeansException { if (app == null) { app = applicationContext; } } // 获得applicationContext public static ApplicationContext getApplicationContext() throws Exception { return app; } // 通过class获取Bean public static <T> T getBean(Class<T> clazz) throws Exception { return getApplicationContext().getBean(clazz); } // 通过name获取 Bean public static Object getBean(String name) throws Exception { return getApplicationContext().getBean(name); } }
WeChatUtil
@Slf4j @Component public class WeChatUtil { @Autowired private HttpClientUtil httpClientUtil; @Value("${wechat.corpid}") private String corpid; @Value("${wechat.corpsecret}") private String corpsecret; @Value("${wechat.getTokenUri}") private String wxgetTokenUri; @Value("${wechat.getUserIdUri}") private String wxgetUserIdUri; @Value("${wechat.readUserUri}") private String wxreadUserUri; private static Long tokenTime = 0L; //2小时过期 private final Integer invalidTime = 2; private String accesstToken; //获取登陆凭证 public String getAccessToekn() { if (System.currentTimeMillis() - tokenTime > invalidTime * 1000 * 60) { tokenTime = System.currentTimeMillis(); String url = wxgetTokenUri + "?corpid=" + corpid + "&corpsecret=" + corpsecret; String doGet = httpClientUtil.doGet(url, new HashMap<>()); HashMap map = JSON.parseObject(doGet, HashMap.class); if ("ok".equals(map.get("errmsg"))) { accesstToken = (String) map.get("access_token"); return accesstToken; } else { log.error("getAccessToekn 出错 {}",map.get("errmsg")); return ""; } } else { return accesstToken; } } //获取访问用户ID public String getUserId(String accessToken, String code) { String url = wxgetUserIdUri + "?access_token=" + accessToken + "&code=" + code; String doGet = httpClientUtil.doGet(url, new HashMap<>()); HashMap map = JSON.parseObject(doGet, HashMap.class); if ("ok".equals(map.get("errmsg"))) { return (String) map.get("UserId"); } else { throw new RuntimeException(map.get("errcode")+" "+(String) map.get("errmsg")); } } public String getEmpId(String accessToken,String userId){ String url = wxreadUserUri + "?access_token=" + accessToken + "&userid=" + userId; String doGet = httpClientUtil.doGet(url, new HashMap<>()); HashMap map = JSON.parseObject(doGet, HashMap.class); JSONObject jsonDoget = (JSONObject) JSONObject.parseObject(JSON.parseObject(doGet).getString("extattr")).getJSONArray("attrs").get(0); String empId = (String) jsonDoget.get("value"); if ("ok".equals(map.get("errmsg"))) { return empId; } else { throw new RuntimeException(map.get("errcode")+" "+(String) map.get("errmsg")); } } }
(6) 枚举类
CacheKeyEnum
public enum CacheKeyEnum {
ACCESS_TOKEN_KEY("accessToken"),
CROP_TOKEN_KEY("corpToken")
;
public String key;
CacheKeyEnum(String key) {
this.key = key;
}
public String getkey() {
return key;
}
public void setkey(String key) {
this.key = key;
}
@Override
public String toString() {
return super.toString();
}
} #java#