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_ssospring.profiles.active=devlogging.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{@Autowiredprivate ClientUtils clientUtils;@Autowiredprivate CorpTokenUtils corpTokenUtils;public abstract String getUserId(String param);@Overridepublic 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 {@Autowiredprivate ClientUtils clientUtils;@Autowiredprivate CorpTokenUtils corpTokenUtils;@Autowiredprivate 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;}@Overridepublic 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;@Overridepublic 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 {@Autowiredprivate WeChatUtil weChatUtil;@Overridepublic 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;@Autowiredprivate 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>() {@Overridepublic @Nullable Object reload(@NonNull Object key, @NonNull Object oldValue) throws Exception {String corpToken = initAccessToken();if (corpToken == null) {return accessTokenCache.get(key, null);}return corpToken;}@Overridepublic @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;@Autowiredprivate ClientUtils clientUtils;@Autowiredprivate 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>() {@Overridepublic @Nullable Object reload(@NonNull Object key, @NonNull Object oldValue) throws Exception {String corpToken = initCorpToken();if (corpToken == null) {return corpTokenCache.get(key, null);}return corpToken;}@Overridepublic @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);}@Overridepublic  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 "";}@Overridepublic 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() {@Overridepublic 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);// 设置headerif (bodymap != null) {for (String key : headermap.keySet()) {httpPost.addHeader(key, headermap.get(key));}}// 设置bodyif (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需要设置contentTypehttpPost.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 ; // 应用的密码// 获取钉钉tokenpublic 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;}@Overridepublic String getAccessToken(String code) {return getAccessToken();}@Overridepublic 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获取useridString 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;@Overridepublic void setApplicationContext(ApplicationContext applicationContext) throws BeansException {if (app == null) {app = applicationContext;}}// 获得applicationContextpublic static ApplicationContext getApplicationContext() throws Exception {return app;}// 通过class获取Beanpublic static <T> T getBean(Class<T> clazz) throws Exception {return getApplicationContext().getBean(clazz);}// 通过name获取 Beanpublic static Object getBean(String name) throws Exception {return getApplicationContext().getBean(name);}}

WeChatUtil

@Slf4j
@Component
public class WeChatUtil {@Autowiredprivate 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;}}//获取访问用户IDpublic 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;}@Overridepublic String toString() {return super.toString();}
}

企业内部应用(阿里商旅)集成 钉钉 与 微信 实现SSO单点登陆相关推荐

  1. 钉钉企业内部机器人python开发(公网部署版本)

    钉钉企业内部机器人开发(公网部署版本) 钉钉给出的开发文档地址如下: https://open.dingtalk.com/document/group/enterprise-created-chatb ...

  2. 【钉钉-场景化能力包】e签宝提供的电子签名能力

    客户痛点 一般中大型企业,都有自己的数据系统,合同拟定都希望在本地系统中完成,但大多数公司都采用实体印章,所以生成的合同都需要手动打印出来,再进行盖章,盖章完成的文件还需要再次上传,由于系统缺少合同& ...

  3. 40079 钉钉_钉钉获取免登陆授权码CODE,返回:不存在的临时授权码40078

    [官方正版]给孩子看的编程少儿读物 55.2元 (需用券) 去购买 > 最近在踩基于钉钉开放平台进行开发的坑,然后在进行身份认证时遇到了"钉钉获取免登陆授权码CODE,返回:不存在的临 ...

  4. 钉钉开放平台-小程序开发实战(钉钉小程序客户端)

    文章目录 钉钉小程序客户端 关于钉钉开放平台 一.小程序基础 1. 基本概念 2. 小程序页面基础 页面运行机制 页面生命周期 页面栈 页面跳转 怎么使用小程序的data-*属性? 3. 小程序常用布 ...

  5. 钉钉JSAPI前端鉴权

    钉钉二次开发分为如下表所示三种类型的开发,只有企业内部应用才需要对JSAPI鉴权. 类型 开发方式 JSAPI鉴权 应用场景 第三方企业应用 E应用开发 不需要 用于发布到钉钉应用市场,供广大用户下载 ...

  6. 钉钉一键登录第三方网站

    钉钉一键登录第三方网站 序 钉钉开发者后台 H5微应用 应用代码开发 登录页面login.html 登录实现LoginController.java pom.xml增加 一键登录效果展示 序 企业内部 ...

  7. 用sip服务器实现msn企业内部交流

    用sip服务器实现msn企业内部交流 作者:梅劲松 winxp里面的windows messager可以登陆企业自己的sip服务器,实现企业内部交流. 你可以在这里下载berkeke OnDO SIP ...

  8. 大企业内部创业到底多难?从华为员工内网热议阿里钉钉谈起

    近日,在华为内部论坛上,一则关于<为什么阿里出现了"钉钉",我们没有?>的帖子引起热议. 围绕该主题,一大批的华为员工在论坛上探讨了华为产品设计.创新氛围,以及大企业内 ...

  9. 企业内部应用与钉钉的集成

    前言:废话不多说,上手就干 1.这里使用的是钉钉的h5微应用,pc端应用,至于在钉钉内怎么创建h5微应用,这里就不在一一述说了,百度也行,看钉钉官方文档也行,主要是我不想截屏了,太麻烦了,哈哈: 2. ...

最新文章

  1. linux shell sed 在一个文件中插入另一个文件
  2. JDK7 AIO介绍
  3. CBOX直播故障:正在连接
  4. 通过示例休眠–第1部分(删除孤儿)
  5. CI项目设计Redis队列
  6. C#基础|面向对象之多态
  7. 朴素贝叶斯分类器的python实现
  8. canvas学习之柱状图
  9. 李洪强iOS之集成极光推送二iOS 证书 设置指南
  10. 大数据面试题——如何从大量数据中找出高频词
  11. Wi-Fi 真的安全吗?一行代码就可让周边无线网络全部瘫痪!| 原力计划
  12. asc怎么用 linux zip_asc文件扩展名,asc文件怎么打开?
  13. 南阳oj 括号配对问题
  14. 鼠标中键控制音量大小
  15. DeepLearning论文阅读笔记(一):Cyclical Learning Rates for Training Neural Networks(CLR)
  16. 灵巧好用的手机便签软件
  17. 也来说说电影《少年班》中周知庸问王大法的问题
  18. mips-mti-gnu-linux,【歪门邪道】利用WSL搭建MIPS32构建环境
  19. 帝国塔防2 empire defence 2的攻略
  20. 有感而发20210216

热门文章

  1. xposed模块开发步骤总结
  2. 基于java毕业设计的汽车销售进销存
  3. 计算机网络c类网络划分子网介绍,IP地址的子网划分详解
  4. linux的gromacs模拟分子运动,动力学模拟gromacs(绝对详细).ppt
  5. Win10Pcap驱动部分学习
  6. Datawhale打卡活动 Kaggle Spaceship Titanic Day3
  7. multism中ui和uo应该怎么表示_Multisim在模拟与数字电子技术中的应用(最终版)最新版...
  8. python导入文件方法大全
  9. 驾驭云端之风1——Spring Cloud微服务架构实践指南
  10. 《软件测试》第二章 软件开发的过程