企业应用(阿里商旅)集成 钉钉 与 微信 实现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# 投递钉钉信息等公司10个岗位
投递钉钉信息等公司10个岗位
