准备工作
1.1 创建应用
要开发钉钉H5微应用,首先需要进入钉钉开发平台。点击“创建应用”按钮,进入创建应用的页面。在该页面中,可以选择创建H5微应用,并填写应用的相关信息。需要注意的是,应用的名称需要遵循钉钉的命名规范,且应用名称需要唯一。在填写完应用信息后,需要保存应用的appKey和appSecret,这些信息将用于后续的开发和部署。
保存应用的appKey和appSecret
1.2 配置应用地址
为了使H5微应用能够正常使用,需要将应用地址配置到首页地址上,并添加相应的参数。具体而言,需要在首页地址中添加&corpId=CORPIDCORPIDCORPID参数(获取组织id用)。
1.3 分配权限
为了确保H5微应用能够正常使用,需要在权限管理中对其进行相应的分配。具体而言,需要对应用中需要访问的数据进行权限控制,并确保只有具有相应权限的用户才能够访问相应的数据。此外,还需要确保应用的代码和数据在运行时得到充分的保护,以避免数据泄露和安全漏洞。
1.3.1 个人权限
个人权限需要申请:个人手机号信息、通讯录个人信息读权限
1.3.2 通讯录管理权限
通讯录管理要申请:企业员工手机号信息、邮箱等个人信息、成员信息读权限
1.4 发布
当H5微应用的开发和部署工作完成后,需要将其发布到钉钉上供用户使用。为此,需要在发布页面中填写相应的信息,并确保应用的功能和界面能够满足用户的需求。发布成功后,用户即可通过钉钉进行交互和使用H5微应用。
然后我们就能在钉钉的工作台看到我们的微应用了。
开始接入
1. 前端
我们这边选择获取微应用免登授权码 的方式接入
1.1 引入钉钉js
方式一:使用npm引入(推荐)
使用npm安装。
npm install dingtalk-jsapi --save
方式二 使用cdn引入(不推荐)
浏览器引入,在浏览器中使用 script 和 link 标签直接引入文件,并使用全局变量 dd。
1.2 调用
调用runtime.permission.requestAuthCode获取微应用免登授权码。
dd.runtime.permission.requestAuthCode({
corpId: "corpid",
onSuccess: function(result) {
/*{
code: 'hYLK98jkf0m' //string authCode
}*/
},
onFail : function(err) {}
})
2.后端
2.1 引入maven
com.aliyun
dingtalk
2.0.35
2.2 编写代码
2.2.1 调用钉钉接口
包含获取accessToken,获取用户id,获取用户信息的方法。
/**
* 初始化请求客户端
* @return
* @throws Exception
*/
private Client initClient() throws Exception {
Config config = new Config();
config.protocol = "https";
config.regionId = "central";
return new Client(config);
}
/**
* 获取企业内部应用accessToken
* @param appKey
* @param appSecret
* @return
*/
public String getAccessToken(String appKey,String appSecret){
String accessToken = redisUtils.get(DINGTALK_ACCESSTOKEN_PREFIX + appKey);
if (StrUtil.isNotBlank(accessToken)){
return accessToken;
}else{
try {
Client client = initClient();
GetAccessTokenRequest getAccessTokenRequest = new GetAccessTokenRequest()
.setAppKey(appKey)
.setAppSecret(appSecret);
GetAccessTokenResponse getAccessTokenResponse = client.getAccessToken(getAccessTokenRequest);
if (ResultCode.SUCCESS == getAccessTokenResponse.getStatusCode()){
redisUtils.set(DINGTALK_ACCESSTOKEN_PREFIX +appKey,getAccessTokenResponse.getBody().getAccessToken(),getAccessTokenResponse.getBody().getExpireIn());
accessToken = getAccessTokenResponse.getBody().getAccessToken();
}else {
throw new RRException("获取accessToken失败!状态码:{}",getAccessTokenResponse.getStatusCode());
}
} catch (TeaException err) {
if (!com.aliyun.teautil.Common.empty(err.code) && !com.aliyun.teautil.Common.empty(err.message)) {
// err 中含有 code 和 message 属性,可帮助开发定位问题
log.error("调用钉钉开发平台API报错!报错码:{};报错信息:{}",err.getCode(),err.getMessage());
}
} 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("调用钉钉开发平台API报错!报错码:{};报错信息:{}",err.getCode(),err.getMessage());
}
}
}
return accessToken;
}
/**
* 获取用户信息
* @param accessToken accessToken
* @param code 免登码 前端获取
*/
public OapiV2UserGetuserinfoResponse.UserGetByCodeResponse getUserInfo(String accessToken,String code) throws ApiException {
DingTalkClient client = new DefaultDingTalkClient("https://oapi.dingtalk.com/topapi/v2/user/getuserinfo");
OapiV2UserGetuserinfoRequest req = new OapiV2UserGetuserinfoRequest();
req.setCode(code);
OapiV2UserGetuserinfoResponse rsp = client.execute(req, accessToken);
return rsp.getResult();
}
/**
* 获取用户详细信息
* @param accessToken accessToken
* @param userId userId
*/
public OapiV2UserGetResponse.UserGetResponse getUserDetail(String accessToken, String userId) throws ApiException {
DingTalkClient client = new DefaultDingTalkClient("https://oapi.dingtalk.com/topapi/v2/user/get");
OapiV2UserGetRequest req = new OapiV2UserGetRequest();
req.setUserid(userId);
OapiV2UserGetResponse rsp = client.execute(req, accessToken);
return rsp.getResult();
}
2.2.2 DingDingH5AuthService
@Slf4j
@RefreshScope
@Service("dingDingH5AuthService")
public class DingDingH5AuthService {
@Autowired
private DingTalkService dingTalkService;
@Autowired
private MallSiteService mallSiteService;
public OapiV2UserGetResponse.UserGetResponse getDingTalkUserInfo(String code,Long siteId){
MallSite mallSite = mallSiteService.getMallSite(siteId);
try{
//获取access_token
String accessToken = dingTalkService.getAccessToken(mallSite.getDingTalkAppKey(), mallSite.getDingTalkAppSecret());
//获取用户id
OapiV2UserGetuserinfoResponse.UserGetByCodeResponse userInfo = dingTalkService.getUserInfo(accessToken, code);
//获取用户信息
return dingTalkService.getUserDetail(accessToken, userInfo.getUserid());
}catch (Exception e){
log.error("调用钉钉授权服务失败!",e);
return null;
}
}
}
获取token
前面我们已经通过对接获取到了用户在钉钉里面的信息,现在只需要关联我们自己系统的用户,实现登录就可以了
由于每个系统中登录逻辑不一样,只贴上伪代码逻辑
// 获取用户钉钉信息
OapiV2UserGetResponse.UserGetResponse dingTalkUserInfo = dingDingH5AuthService.getDingTalkUserInfo(code, siteId);
log.info("通过code获取用户信息dingtalkUserInfo{}",JSON.toJSONString(dingTalkUserInfo));
if (dingTalkUserInfo == null){
return R.error("用户信息获取失败");
}
String unionid = dingTalkUserInfo.getUnionid();
String mobile = dingTalkUserInfo.getMobile();
//todo 通过手机号在自己系统查询用户
// 存在,调用登录逻辑,获取token
// 不存在,注册并登陆,获取token
参考
H5微应用JSAPI总览 - 钉钉开放平台 (dingtalk.com)
第三方企业应用免登 - 钉钉开放平台 (dingtalk.com)