java 钉钉-第三方企业应用-免登

java 钉钉-第三方企业应用-免登

在这里插入图片描述
https://open.dingtalk.com/document/isvapp/sso-overview#title-lki-b8q-ar2
在这里插入图片描述
前端传输对象:

@Data
public class DingReq {
    private String corpId;
    private String authCode;
    private String dingUserId;
    private boolean isAdmin;
    private List<String> userIdList;
    private List<Long> deptIdList;
    private String name;
    private String projectName;
    private String time;
    private String templateId;
    private String teacher;
}

钉钉-获取accessToken

 /**
     * ISV获取企业访问凭证
     *
     * @param corpId 授权企业的corpId
     */
    @Override
    public String getCorpToken(String corpId, String suiteTicket) {
        if (StringUtils.isEmpty(corpId)) {
            return null;
        }
        if (null != jedisClient.get(corpId)) {
            return (String) jedisClient.get(corpId);
        }
        long timestamp = System.currentTimeMillis();
        //正式应用应该由钉钉通过开发者的回调地址动态获取到
        String signature = DingTalkSignatureUtil.computeSignature(Constant.SUITE_SECRET,
                DingTalkSignatureUtil.getCanonicalStringForIsv(timestamp, suiteTicket));
        Map<String, String> params = new LinkedHashMap<String, String>();
        params.put("timestamp", String.valueOf(timestamp));
        params.put("suiteTicket", suiteTicket);
        params.put("accessKey", Constant.SUITE_KEY);
        params.put("signature", signature);
        String queryString = DingTalkSignatureUtil.paramToQueryString(params, "utf-8");
        DingTalkClient client = new DefaultDingTalkClient(ApiUrlConstant.URL_GET_CORP_TOKEN + "?" + queryString);
        OapiServiceGetCorpTokenRequest request = new OapiServiceGetCorpTokenRequest();
        request.setAuthCorpid(corpId);
        OapiServiceGetCorpTokenResponse response;
        try {
            response = client.execute(request);
            if (null == response || StringUtils.isEmpty(response.getAccessToken())) {
                log.error("获取token失败,response:{}", JSONUtil.toJsonStr(response));
                return null;
            }
            log.info("获取企业acccessToken,serviceGetCorpTokenResponse:{}", JSONUtil.toJsonStr(response));
            //设置过期时间,1小时50分钟
            jedisClient.setStringExpire(corpId, response.getAccessToken(), 110 * 60);
        } catch (ApiException e) {
            log.error("获取token失败:", e, e);
            return null;
        }
        if (response == null || !response.isSuccess()) {
            log.error("获取token失败");
            return null;
        }
        return response.getAccessToken();
    }

钉钉-获取用户信息

 /**
     * 通过钉钉服务端API获取用户在当前企业的userId
     *
     * @param accessToken 企业访问凭证Token
     * @param code        免登code
     * @
     */
    @Override
    public OapiUserGetuserinfoResponse getOapiUserGetuserinfo(String accessToken, String code) {
        DingTalkClient client = new DefaultDingTalkClient(ApiUrlConstant.URL_GET_USER_INFO);
        OapiUserGetuserinfoRequest request = new OapiUserGetuserinfoRequest();
        request.setCode(code);
        request.setHttpMethod("GET");
        OapiUserGetuserinfoResponse response;
        try {
            response = client.execute(request, accessToken);
        } catch (ApiException e) {
            e.printStackTrace();
            return null;
        }
        log.info("通过钉钉服务端API获取用户在当前企业的userId:{}", JSONUtil.toJsonStr(response));
        if (response == null || !response.isSuccess()) {
            return null;
        }
        return response;

钉钉获取用户个人信息

/**
     * 获取用户个人信息
     *
     * @param
     * @return
     * @throws Exception
     */
    public GetUserTokenResponse getUserinfo(String code) throws Exception {
        com.aliyun.dingtalkoauth2_1_0.Client client = createClient();
        GetUserTokenResponse userToken = null;
        GetUserTokenRequest getUserTokenRequest = new GetUserTokenRequest()
                .setClientId(Constant.SUITE_KEY)
                .setClientSecret(Constant.SUITE_SECRET)
                .setCode(code)
                .setGrantType("authorization_code");
        //如果使用授权码换token,传authorization_code。
        //如果使用刷新token换用户token,传refresh_token。
        try {
            userToken = client.getUserToken(getUserTokenRequest);
        } catch (TeaException err) {
            if (!com.aliyun.teautil.Common.empty(err.code) && !com.aliyun.teautil.Common.empty(err.message)) {
                // err 中含有 code 和 message 属性,可帮助开发定位问题
            }

        } 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 属性,可帮助开发定位问题
            }

        }
        return userToken;
    }

钉钉-获取用户详细信息(获取用户手机号)

/**
     * 获取用户详细信息
     *
     * @param accessToken
     * @return
     * @throws Exception
     */
    @Override
    public GetUserResponse getUseInfoDetail(String accessToken) throws Exception {
        com.aliyun.dingtalkcontact_1_0.Client client = createClient_1_0();
        com.aliyun.dingtalkcontact_1_0.models.GetUserHeaders getUserHeaders = new com.aliyun.dingtalkcontact_1_0.models.GetUserHeaders();
        getUserHeaders.xAcsDingtalkAccessToken = accessToken;
        GetUserResponse userWithOptions = null;
        try {
            userWithOptions = client.getUserWithOptions("me", getUserHeaders, new RuntimeOptions());
            log.info("钉钉-获取用户详细信息,userWithOptions:{}", JSONUtil.toJsonStr(userWithOptions));
        } catch (TeaException err) {
            if (!com.aliyun.teautil.Common.empty(err.code) && !com.aliyun.teautil.Common.empty(err.message)) {
                // err 中含有 code 和 message 属性,可帮助开发定位问题
                log.error("获取用户详细信息异常,err:{}", 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("获取用户详细信息异常,err:{}", err);
            }

        }
        return userWithOptions;
    }

1、钉钉是否弹出授权框接口

●主要用来判断钉钉是否弹出授权框
●1、获取企业accessToken,通过前端传递的corpId,查询数据库中企业表对应的企业,找出suiteTicket,通过SuiteTicket和corpId得到企业accessToken
钉钉相关接口(https://oapi.dingtalk.com/service/get_corp_token)
●2、获取用户信息,通过企业accessToken和前端传递的authCode
钉钉相关接口(https://oapi.dingtalk.com/user/getuserinfo)
●3、查询得到钉钉当前用户的dingUserId,判断企业用户表是否存在该用户,用户为空,返回弹出授权标识
用户不为空,但是账号冻结,返回冻结标识
用户不为空但是username为空(说明没有手机号,获取手机号),返回弹出授权标识
有用户,返回用户信息。

    public Result authLogin(@RequestBody DingReq ding) {
        if (StringUtils.isEmpty(ding.getCorpId())) {
            log.error("登录失败,缺少corpId");
            return Result.succeed(false);
        }
        if (StringUtils.isEmpty(ding.getAuthCode())) {
            log.error("缺少authCode");
            return Result.succeed(false);
        }
        DingAuthVO dingAuthVO = new DingAuthVO();
        dingAuthVO.setTag("no");
        Tenant tenant = tenantMapper.findTenantInfo(ding.getCorpId());
        SuiteTicket suiteTicket = suiteTicketMapper.findSuiteTicket();
        if (null == suiteTicket) {
            log.error("suiteTicket,为空");
            return Result.succeed(false);
        }
        if (StringUtils.isEmpty(suiteTicket.getSuiteTicket())) {
            log.error("登录失败,企业SuiteTicket为空");
            return Result.succeed(false);
        }
        //获取accessToken,注意正是代码要有异常流处理
        String accessToken = dingService.getCorpToken(ding.getCorpId(), suiteTicket.getSuiteTicket());
        if (null == accessToken) {
            log.error("登录失败,获取企业token失败");
            return Result.succeed(false);
        }
        //获取用户信息
        OapiUserGetuserinfoResponse oapiUserGetuserinfoResponse = dingService.getOapiUserGetuserinfo(accessToken, ding.getAuthCode());
        if (null == oapiUserGetuserinfoResponse) {
            log.error("登录失败,获取用户id失败");
            return Result.succeed(false);
        }
        //3.查询得到当前用户的userId
        // 获得到userId之后应用应该处理应用自身的登录会话管理(session),避免后续的业务交互(前端到应用服务端)每次都要重新获取用户身份,提升用户体验
        String dingUserId = oapiUserGetuserinfoResponse.getUserid();
        Boolean isAdmin = oapiUserGetuserinfoResponse.getIsSys();
        dingAuthVO.setDingUserId(dingUserId);
        dingAuthVO.setAdmin(isAdmin);
        SysEntUser user = null;
        if(null != tenant){
            user  = sysUserMapper.getUserInfo(tenant.getId(), null, dingUserId);
        }

        try {
            if (null == user) {
                //用户为空,返回弹出授权标识
                log.info("用户为空,返回弹出授权标识");
                dingAuthVO.setTag("userEmpty");
                return Result.succeed(dingAuthVO);
            } else {
                if (!user.getEnabled()) {
                    dingAuthVO.setTag("frozen");
                    log.info("用户为被冻结");
                    return Result.succeed(dingAuthVO);
                }
                String username = user.getUsername();
                if (StringUtils.isEmpty(username)) {
                    //账号为空,返回弹出授权标识
                    log.info("用户为空,返回弹出授权标识");
                    return Result.succeed(dingAuthVO);
                }
                String corpId = user.getCorpId();
                if (StringUtils.isNotEmpty(corpId) && !corpId.equals(ding.getCorpId())) {
                    log.info("corpId和数据库不一样,进行更新");
                    sysUserMapper.updateDingSysUser(user.getId(), null, ding.getCorpId());
                }
                //返回用户信息
                log.info("有用户,返回用户信息");
                dingAuthVO.setTag("yes");
                dingAuthVO.setUserId(user.getId());
                dingAuthVO.setCropId(ding.getCorpId());
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        return Result.succeed(dingAuthVO);
    }

2、钉钉登录接口

●钉钉登录,查库,有数据生成token,没数据新增用户
●1、获取用户token,授权之后,前端传递authCode获取用户的accessToken
钉钉相关接口(/v1.0/oauth2/userAccessToken)
●2、获取用户详情,拿手机号
钉钉相关接口(/v1.0/contact/users/{unionId})
●3、根据前端传递的dingUserId,查询企业库用户表是否存在用户
如果无,新增管理员,判断是否为钉钉管理员,如果是就绑定管理员角色,
如果有,更新手机号和企业corpId
●4、钉钉-给第一个用户初始化直属部门
●5、返回用户信息

    @Transactional(rollbackFor = Exception.class)
    public Result dingLogin(@RequestBody DingReq ding) {
        DingAuthVO dingAuthVO = new DingAuthVO();
        try {
            boolean isAdmin = ding.isAdmin();
            if (StringUtils.isEmpty(ding.getCorpId())) {
                log.error("登录失败,缺少corpId");
                return Result.succeed(false);
            }
            if (StringUtils.isEmpty(ding.getAuthCode())) {
                log.error("缺少authCode");
                return Result.succeed(false);
            }
            if (StringUtils.isEmpty(ding.getDingUserId())) {
                log.error("缺少dingUserId");
                return Result.succeed(false);
            }
            Tenant tenant = tenantMapper.findTenantInfo(ding.getCorpId());
            if (null == tenant) {
                log.error("登录失败,企业还未初始化");
                return Result.succeed(false);
            }
            //获取用户token
            GetUserTokenResponse userinfo = dingService.getUserinfo(ding.getAuthCode());
            if (null == userinfo) {
                log.error("获取用户token失败");
                return Result.succeed(false);
            }
            String token = userinfo.getBody().getAccessToken();
            //获取用户详情,拿手机号
            GetUserResponse useInfo = dingService.getUseInfoDetail(token);
            if (null == useInfo) {
                log.error("获取用户详情失败");
                return Result.succeed(false);
            }
            String mobile = useInfo.getBody().getMobile();
            if (StringUtils.isEmpty(mobile)) {
                log.error("获取用户电话失败");
                return Result.succeed(false);
            }
            String avatarUrl = useInfo.getBody().getAvatarUrl();
            String email = useInfo.getBody().getEmail();
            String nick = useInfo.getBody().getNick();
            SysEntUser sysUser = sysUserMapper.getUserInfo(tenant.getId(), null, ding.getDingUserId());
            if (null == sysUser) {
                //新增用户
                log.info("钉钉-新增管理员");
                sysUser = new SysEntUser();
                。。。。
                if (isAdmin) {
                    //是管理员才会给管理员设置角色
                    log.info("钉钉-给管理员设置角色");
                    sysUserMapper.addSysUser(sysUser);
                    List<SysRole> sysRoles = sysRoleMapper.selectSysRole(tenant.getId());
                    if (CollectionUtils.isNotEmpty(sysRoles)) {
                        //找到管理员角色
                        SysRole admin = sysRoles.stream().filter(v -> v.getCode().equals("ADMIN")).collect(Collectors.toList()).get(0);
                        if (null != admin) {
                            sysUserRoleMapper.addUserRole(sysUser.getId(), admin.getId(), tenant.getId());
                        }
                    }
                }
            } else {
                log.info("更新手机号和企业corpId");
                sysUserMapper.updateDingSysUser(sysUser.getId(), mobile, ding.getCorpId());
            }
            DepartmentVO departmentVO = departmentMapper.findInfo(tenant.getId(), 1);
            if (null != departmentVO) {
                log.info("钉钉-给第一个用户初始化直属部门");
                DepartUser departUser = new DepartUser();
             。。。
                departUserMapper.saveDepartUser(departUser);
            }
            log.info("用户信息:{}", JSONUtil.toJsonStr(sysUser));
            dingAuthVO.setUserId(sysUser.getId());
            dingAuthVO.setCropId(ding.getCorpId());
        } catch (Exception e) {
            e.printStackTrace();
        }
        return Result.succeed(dingAuthVO);
    }
  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值