1、页面展示钉钉二维码,根据配置信息来获取。
开发文档中的第二种实现方式,将钉钉登陆二维码嵌入自有项目的页面中
@RequestMapping("getAppId")
@ResponseBody
public WebResponse getAppId() throws Exception {
try {
Map res = new HashMap();
//应用标识(自定义)
res.put("appFlag", WebConfig.DTALK_SCAN_APP_FLAG);
//回调地址(自定义,配置路径:钉钉开放平台开发者后台-我的应用详情-应用配置-网页配置)
res.put("redirectUrl",WebConfig.DTALK_SCAN_APP_REDIRECT_URL);
//登录域名
res.put("domainUrl",WebConfig.DTALK_SCAN_APP_DOMAIN_URL);
return WebResponse.resSuccess("获取成功", res);
} catch (Exception e) {
return WebResponse.resFail("获取失败", null);
}
}
配置信息①:应用标识
配置信息②:回调地址
配置扫码后获取用户信息进行下一步业务操作的接口(完整地址,不用加参数,且注意不同环境配置不同地址)
配置信息③:登录域名(构造登录页面)
选择Saas环境的配置参数
2、获取钉钉用户信息
@RequestMapping(value = "getUserData")
@ResponseBody
public String getUserData(String code){
try {
//应用access_token
String accessToken = redisValueTemplate.hGetAll(WebConfig.DTALK_SCAN_REDIS_TOKEN_KEY).get(WebConfig.DTALK_SCAN_REDIS_TOKEN_KEY);
logger.info("access token:" + accessToken);
ExecutableClient executableClient = ExecutableClient.getInstance();
//应用的唯一标识key(即App Key)
executableClient.setAccessKey(WebConfig.DTALK_SCAN_APP_ID);
//应用的密钥(即App Secret)
executableClient.setSecretKey(WebConfig.DTALK_SCAN_CORP_SECRET);
//开放平台域名
executableClient.setDomainName(WebConfig.DINGDOMAIN);
executableClient.setProtocal("https");
executableClient.init();
String api ="/rpc/oauth2/getuserinfo_bycode.json";
PostClient postClient = executableClient.newPostClient(api);
//设置参数
postClient.addParameter("access_token", accessToken);
postClient.addParameter("code", code);
//调用API
String apiResult = postClient.post();
logger.info("浙政钉2.0 获取 扫码用户信息返回json:" + apiResult);
JSONObject json = JSON.parseObject(apiResult);
JSONObject content = JSON.parseObject(json.getJSONObject("content").toString());
String accountId = content.getJSONObject("data").getString("accountId");
String lastName = content.getJSONObject("data").getString("lastName");
Map res = new HashMap();
res.put("name",lastName);
res.put("userId",accountId);
return FastJsonUtil.toJSONString(res);
}catch (Exception e){
logger.error("错误 ",e);
return null;
}
}
配置信息④:应用 access_token
这边就是开发人员自定义的一个配置项而已,用来存取accessToken的一个key名称,与钉钉平台对接的关系不大,只是需要去定时获取这个accessToken
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.dao.DataAccessException;
import org.springframework.data.redis.connection.RedisConnection;
import org.springframework.data.redis.core.RedisCallback;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Component;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;
@Component
public class RedisValueTemplate {
private static int dbIdx = 1;
@Autowired
private RedisTemplate<String, String> redisTemplate;
public void hMset(String key, final Map<String, String> map) {
redisTemplate.execute(new RedisCallback<Object>() {
@Override
public Object doInRedis(RedisConnection connection) throws DataAccessException {
connection.select(dbIdx);
connection.hMSet(key.getBytes(), fromStringToByte(map));
return null;
}
});
}
public Map<String, String> hGetAll(final String key) {
return (Map<String, String>) redisTemplate.execute(new RedisCallback<Object>() {
@Override
public Map<String, String> doInRedis(RedisConnection connection)
throws DataAccessException {
connection.select(dbIdx);
Map<String, String> map = fromByteToString(connection.hGetAll(key.getBytes()));
return map;
}
});
}
public void selectDb(final int dbId) {
dbIdx = dbId;
}
private Map<byte[], byte[]> fromStringToByte(Map<String, String> map) {
Map<byte[], byte[]> resultMap = new HashMap<byte[], byte[]>();
Set<String> keySet = map.keySet();
for (String key : keySet) {
String value = map.get(key);
resultMap.put(key.getBytes(), value.getBytes());
}
return resultMap;
}
private Map<String, String> fromByteToString(Map<byte[], byte[]> map) {
Map<String, String> resultMap = new HashMap<String, String>();
Set<byte[]> keySet = map.keySet();
for (byte[] key : keySet) {
String value = new String(map.get(key));
String keyStr = new String(key);
resultMap.put(keyStr, value);
}
return resultMap;
}
}
注意这边需要查看一下pom文件
另外还需要注意定时任务需要设置随项目启动就开启(解决方式:在项目启动的Application类文件上加@EnableScheduling注解),这两个问题都有可能会导致获取access_token失败
相关异常信息为:java.lang.UnsupportedOperationException: Selecting a new database not supported due to shared connection. Use separate ConnectionFactorys to work with multiple databases
<!-- redis 依赖 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
<exclusions>
<exclusion>
<groupId>io.lettuce</groupId>
<artifactId>lettuce-core</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>redis.clients</groupId>
<artifactId>jedis</artifactId>
<version>2.9.0</version>
</dependency>
配置信息⑤:应用凭证
应用的唯一标识key(即App Key) 和 应用的密钥(即App Secret)
配置信息⑥:开放平台域名(调接口使用)
仍选择Saas环境的配置参数
至此顺利的话,就可以成功拿到钉钉的用户信息了。本次对接的版本为浙政钉,非普通钉钉版本。普通钉钉版本基本开发过程与文章内描述相仿,少数地方稍有不同,具体遵循钉钉开发文档。