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();
}
}