用java實現“釘釘微應用,免登進入某H5系統首頁“功能”


一、前言

哈哈,這是我的第一篇博客。

先說一下這個小功能的具體場景:

用戶登錄釘釘app,點擊微應用,獲取當前用戶的信息,與H5系統的數據庫的用戶信息對比,如果存在該用戶,則點擊后直接進入H5系統的首頁,否則顯示“您無權限”。

補充:又加了一個小需求,就是免登成功,會給該用戶發條消息

我是參考釘釘開發文檔實現的這個小功能,文檔地址:https://ding-doc.dingtalk.com/doc#/serverapi2/clotub

二、准備工作

 需要創建一個微應用:https://open-dev.dingtalk.com

 

1.是在企業內部開發中創建H5微應用,不是第三方企業應用中

企業內部開發:企業內部開發是指“開發企業內部應用”供企業內部的人員使用。企業可以選擇由企業內部的開發者進行開發,或者由企業授權定制服務商進行開發。

第三方企業應用:第三方企業應用開發,是指開發者以釘釘、企業之外的第三方身份,基於釘釘的開放能力開發應用,並提供給釘釘上的其他組織使用。(哈哈,這個區別我是直接copy文檔中的)

2.H5工程中,創建的一個前端頁面ddNoLogin.html(哈哈,這個起名有點中文式英語,因為我沒有找到合適的英文單詞):

該頁面是用來獲取免登授權碼,然后把該code傳遞給后台接口的。

3.填寫公司服務器的公網IP

可以敲命令查看該ip:curl ifconfig.me

 4.微應用創建好,會生成三個參數,

agentId、appKey、appSecret

外加一個corpId(釘釘開發者平台的首頁中有顯示),這四個參數值是固定的,后續開發需用

5.接口權限

高級權限-企業通訊錄中的接口都需要給開通

6.最后發布應用

三、功能開發

哈哈,要開始敲代碼了

1.獲取免登授權碼code

這里調用的是釘釘JS-API中的方法,本功能調用的方法是不需要鑒權的,如果需要鑒權,則還需先dd.config。

關於功能方法是否需要鑒權,可以去查看JSAPI總覽

ddNoLogin.html:

<!DOCTYPE html>
<html>
<head>
    <title>微應用登陸</title>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width,initial-scale=1 user-scalable=0" />
    <script src="https://cdn.bootcss.com/jquery/3.3.1/jquery.min.js"></script>
    <script type="text/javascript" src="http://g.alicdn.com/dingding/open-develop/1.9.0/dingtalk.js"></script>
</head>
<body>
<div id="ddNoLogin"></div>
<script type="text/javascript">
        dd.ready(function() {
        //1.獲取免登授權碼code
        dd.runtime.permission.requestAuthCode({
            corpId : corpId ,  //企業id
            onSuccess : function(result) {
                var code = result.code;
                getUserInfo(code);   //通過該code可以獲取用戶身份
            },
            onFail : function(err) {
                alert('出錯了, ' + err);
            }
        });
    });
        function getUserInfo(code) {
        $.ajax({
            type : "GET",
            url : "/xxx/noLogin?code=" + code,
            async : false,
            dataType : 'json',
            contentType : "application/json;charset=utf-8",
            success : (function(res) {
                if(res.code == "0000"){                                        
                       window.location.href = '/#/xxxxx';
                                }else{
                                   $('#ddNoLogin').html(res.msg);
                                }
            }),
        });
    }
</script>
</body>
</html>

獲取code的實現是需要用前端JS去寫的

2.獲取access_token

釘釘提供了開放的api后台接口,這里通過appkey和appsecret獲取token,請求路徑:https://oapi.dingtalk.com/gettoken?appkey=key&appsecret=secret

該token有效期是2個小時,有效期內重復獲取,會返回相同結果,並自動續期,

故這里我的實現是:定時刷新token,每隔1小時50分鍾去獲取釘釘的token,並緩存到redis中(我把釘釘的相關配置都放入到application.yml中了)

DdTokenTask.java:

/**
 * 定時獲取釘釘的token
 */
@Component
@EnableScheduling
public class DdTokenTask {

    @Autowired
    private JedisClient jedisClient;

    public static final long cacheTime = 1000 * 60 * 55 * 2;//1小時50分鍾
    @Value("${dtalk.tokenUrl}")
    private String tokenUrl;
    @Value("${dtalk.app.key}")
    private String appKey;
    @Value("${dtalk.app.secret}")
    private String appSecret;
    @Value("${dtalk.redisTokenKey}")
    private String tokenKey;
    @Value("${dtalk.taskRun}")
    private String taskRun;


    /**
     * 每隔1小時50分鍾獲取釘釘的access_token
     */
    @Scheduled(fixedRate = cacheTime)
    @Async
    public void getDdTokenTask(){
        if("true".equals(taskRun)){
            //刷新
            System.out.println("--->>>>>-------------獲取釘釘token的定時任務開始了:"+ DateUtil.formatDateToString(new Date(), "HH:mm:ss"));

            String accessTokenUrl = tokenUrl + "?appkey=" + appKey + "&appsecret=" + appSecret;
            //訪問獲取access_token   有效期是2小時
            String accessToken = JsonUtil.getJsonNode(HttpUtil.doGet(accessTokenUrl)).get("access_token").asText();
            //放入到redis中
            jedisClient.set(tokenKey, accessToken);

            System.out.println("--->>>>>-------------獲取釘釘token的定時任務結束了,token:"+accessToken);
        }
    }

    /*private String getAccessToken(){
        //需引入SDK,公司私服沒有
        DefaultDingTalkClient client = new 
        DefaultDingTalkClient("https://oapi.dingtalk.com/gettoken");
        OapiGettokenRequest request = new OapiGettokenRequest();
        request.setAppkey("appkey");
        request.setAppsecret("appsecret");
        request.setHttpMethod("GET");
        OapiGettokenResponse response = client.execute(request);
        return "";
    }*/

}

(哈哈,其實文檔中提供了釘釘SDK的java寫法,不過公司私服沒有該SDK,所以我就直接用htttp請求了)

 3.獲取用戶userid

 通過免登授權碼和access_token獲取用戶的userid,請求路徑:https://oapi.dingtalk.com/user/getuserinfo?access_token=access_token&code=code

 4.獲取用戶詳情

請求路徑:https://oapi.dingtalk.com/user/get?access_token=ACCESS_TOKEN&userid=shaocui

會返回用戶的姓名、手機號等所有信息

DdLoginController.java:

@RestController
@RequestMapping("/ddUser")
@Api(value = "/ddUser", description = "釘釘H5微應用登錄", tags = {"DdLoginController"})
public class DdLoginController {

    @Autowired
    private JedisClient jedisClient;

    @Value("${dtalk.userUrl}")
    private String userUrl;
    @Value("${dtalk.userDetailUrl}")
    private String userDetailUrl;
    @Value("${dtalk.redisTokenKey}")
    private String tokenKey;
    @Value("${dtalk.agentId}")
    private Integer agentId;


    @GetMapping("/noLogin")
    @ApiOperation( "釘釘免登")
    @ApiImplicitParam(paramType = "query", name = "code", value = "免登授權碼", dataType = "String")
    public WebResponse noLogin(@RequestParam("code") String code, HttpServletResponse response){
        //2.獲取access_token
        String accessToken = jedisClient.get(tokenKey);

        //3.獲取用戶userid
        String userIdUrl =userUrl + "?access_token=" + accessToken + "&code=" + code;
        //訪問獲取userid
        JsonNode user = JsonUtil.getJsonNode(HttpUtil.doGet(userIdUrl));
        if(user.get("errcode").asInt() != 0){
            //有些公司的公網ip不固定,導致微應用中設置的不對,這里就會報錯
            return WebResponse.resFail(user.get("errmsg").asText());
        }
        String userId = user.get("userid").asText();

        //4.獲取用戶詳情  手機號
        String userInfoUrl = userDetailUrl + "?access_token=" + accessToken + "&userid=" + userId;
        //訪問獲取mobile
        JsonNode userInfo = JsonUtil.getJsonNode(HttpUtil.doGet(userInfoUrl));
        String mobile = userInfo.get("mobile").asText();

        System.out.println("釘釘用戶的手機號:"+mobile);

        //通過手機號獲取該用戶
        SysUser sysUser = 。。。。。;
        if(sysUser == null){
            //不存在該用戶
            return WebResponse.resFail("您無權限訪問", null);
        }

        。。。。。。

        //釘釘發送免登成功消息給用戶
        sendMessage(accessToken, userId, userInfo.get("name").asText());

        return WebResponse.resSuccess("免登成功", loginUserInfo);
    }

    //釘釘發送消息給用戶
    private void sendMessage(String token, String userId, String userName){
        String messageUrl = "https://oapi.dingtalk.com/topapi/message/corpconversation/asyncsend_v2?access_token="+token;
        Map<String, Object> map = new HashMap<>();
        map.put("agent_id", agentId.longValue());
        map.put("userid_list", userId);
        map.put("to_all_user", false);
        String content = "用戶"+userName+"在"+ DateUtil.formatDateToString(new Date(), "yyyy-MM-dd HH:mm:ss")+"時成功登錄xxH5端,並進入到xxx頁面";
        String msg = "{\"msgtype\":\"text\",\"text\":{\"content\":"+"\""+content+"\""+"}}";
        JSONObject jsonObj = JSONObject.parseObject(msg);
        map.put("msg",jsonObj);

        HttpUtil.doPost(messageUrl, map, "UTF-8", 20000, null);
    }
}

(哈哈,那個。。。。。處的代碼是實現系統認證成功后的具體操作,故這里省略)

到此釘釘免登就實現了,然后免登成功后給用戶發送消息

5.工作通知消息

POST請求,請求路徑:https://oapi.dingtalk.com/topapi/message/corpconversation/asyncsend_v2?access_token=ACCESS_TOKEN

請求體{agent_id、userid_list、dept_id_list、to_all_user、msg}

注意:

給同一個用戶發送相同的內容,一天只能發一次;發送不同的內容,一天可以500次,

故這里我在發送的消息中添加了當前時間。

(哈哈,一些細節的東西我都寫在代碼的注釋里了,最后發現這個小功能好像就一點點代碼量)


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM