记一次钉钉H5微应用免登接入流程

2023年 9月 28日 83.5k 0

准备工作

1.1 创建应用

要开发钉钉H5微应用,首先需要进入钉钉开发平台。点击“创建应用”按钮,进入创建应用的页面。在该页面中,可以选择创建H5微应用,并填写应用的相关信息。需要注意的是,应用的名称需要遵循钉钉的命名规范,且应用名称需要唯一。在填写完应用信息后,需要保存应用的appKey和appSecret,这些信息将用于后续的开发和部署。

image.png

image.png
image.png

保存应用的appKey和appSecret

image.png

1.2 配置应用地址

为了使H5微应用能够正常使用,需要将应用地址配置到首页地址上,并添加相应的参数。具体而言,需要在首页地址中添加&corpId=CORPIDCORPIDCORPID参数(获取组织id用)。

image.png

1.3 分配权限

为了确保H5微应用能够正常使用,需要在权限管理中对其进行相应的分配。具体而言,需要对应用中需要访问的数据进行权限控制,并确保只有具有相应权限的用户才能够访问相应的数据。此外,还需要确保应用的代码和数据在运行时得到充分的保护,以避免数据泄露和安全漏洞。

1.3.1 个人权限

个人权限需要申请:个人手机号信息、通讯录个人信息读权限

image.png

1.3.2 通讯录管理权限

通讯录管理要申请:企业员工手机号信息、邮箱等个人信息、成员信息读权限

image.png

1.4 发布

当H5微应用的开发和部署工作完成后,需要将其发布到钉钉上供用户使用。为此,需要在发布页面中填写相应的信息,并确保应用的功能和界面能够满足用户的需求。发布成功后,用户即可通过钉钉进行交互和使用H5微应用。

image.png

然后我们就能在钉钉的工作台看到我们的微应用了。

image.png

开始接入

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)

相关文章

JavaScript2024新功能:Object.groupBy、正则表达式v标志
PHP trim 函数对多字节字符的使用和限制
新函数 json_validate() 、randomizer 类扩展…20 个PHP 8.3 新特性全面解析
使用HTMX为WordPress增效:如何在不使用复杂框架的情况下增强平台功能
为React 19做准备:WordPress 6.6用户指南
如何删除WordPress中的所有评论

发布评论