django对接钉钉登录系统

1,382 阅读1分钟

小知识,大挑战!本文正在参与「程序员必备小知识」创作活动

本文同时参与 「掘力星计划」   ,赢取创作大礼包,挑战创作激励金

需求:

业务需要,当前H5应用需要嵌入钉钉中进行使用

基础配置

  • 创建钉钉H5微应用(地址:钉钉开发平台->应用开发->企业内部开发->创建应用)

image.png

  • 获取应用基础信息

image.png

  • 权限开通

image.png

  • 配置IP出口以及链接

image.png

开发 (这里只给出主要封装代码)

服务端代码:

  • 获取token
@retry(reraise=True, stop=(stop_after_delay(10) | stop_after_attempt(3)), wait=wait_random(min=1, max=3),
       retry=retry_if_exception_type())
def get_token(self, *args, **kwargs) -> dict:
    '''
    :result  获取access_token
    '''
    path = 'gettoken'
    params = {
        "appkey": self.__appkey,
        "appsecret": self.__appsecret
    }
    response = self.conn.get(
        path=path,
        params=params,
        timeout=5
    )
    data = response.json()
    errcode = data.get('errcode', -1)
    if str(errcode) == "0":
        result = data.get('access_token', {})
        result = result if isinstance(result, str) else ""
        return result
    return {}
  • 通过code获取人员信息
def getuserinfo(self, code: str, *args, **kwargs):
    path = "/user/getuserinfo"
    params = {
        "access_token": self.get_token(),
        "code": code
    }
    response = self.conn.get(
        path=path,
        params=params,
        timeout=5
    )
    data = response.json()
    errcode = data.get('errcode', -1)
    if str(errcode) == '0':
        result = data
        result = result if isinstance(result, dict) else {}
        user_id = result.get('userid')
        response = self._get_user_detail(user_id)
        return response
    return {}

  • 获取人员详情
def _get_user_detail(self, user_id: str, *args, **kwargs):
    key = str(user_id) + "_get_user_detail"
    info = redisClient.authcache('get', key)
    if info:
        return info
    path = '/topapi/v2/user/get?access_token={}'.format(self.get_token())
    params = {
        "language": "zh_CN",
        "userid": user_id
    }
    response = self.conn.post(
        path=path,
        params=params,
        timeout=5
    )
    data = response.json()
    errcode = data.get('errcode', -1)
    if str(errcode) == '0':
        result = data.get('result', {})
        result = result if isinstance(result, dict) else {}
        redisClient.authcache('set', key, result)
        return result
    return {}

前端代码

  • PC端代码
<script src="https://g.alicdn.com/dingding/dingtalk-jsapi/2.10.3/dingtalk.open.js"></script>
<p>Opening with system default browser(Google Chrome Recommened) ... ...</p>
<script>
   dd.ready(function () {
       dd.runtime.permission.requestAuthCode({
           corpId: "{{ corpId }}", // 企业id
           onSuccess: function (result) {
               dd.biz.util.openLink({
                   url: window.location.protocol + "//" + window.location.host + "{{ uri }}&code=" + result.code,//要打开链接的地址
                   onSuccess: function (result) {
                       /**/
                   },
                   onFail: function (err) {
                   }
               });
           },
           onFail: function (error) {
               alert(`钉钉认证失败! ${JSON.stringify(error)}`);
           }
       });
   });
</script>
  • mob端代码
<script src="https://g.alicdn.com/dingding/dingtalk-jsapi/2.10.3/dingtalk.open.js"></script>
<script>
   dd.ready(function () {
       dd.runtime.permission.requestAuthCode({
           corpId: "{{ corpId }}", // 企业id
           onSuccess: function (result) {
               dd.biz.navigation.replace({
                   url: window.location.protocol + "//" + window.location.host + "{{ uri }}&code=" + result.code,//要打开链接的地址
                   onSuccess: function (result) {
                       /**/
                   },
                   onFail: function (err) {
                   }
               });
           },
           onFail: function (error) {
               alert(`钉钉认证失败! ${JSON.stringify(error)}`);
           }
       });
   });
</script>
  • 登录完成跳转访问主页(这里进行session的处理)
<script>
    setTimeout(function () {
        document.location.resession_dict
        document.location.replace("{{ uri }}");
    }, 0)
</script>

扫码登录页面实现

<p align="value" style="text-align:center">{{ title }}</p>
<div id="login_container" style="text-align:center"></div>

<script src="https://g.alicdn.com/dingding/dinglogin/0.0.5/ddLogin.js"></script>

<script>
    var url = encodeURIComponent('users/login/');
    var goto = encodeURIComponent('https://oapi.dingtalk.com/connect/oauth2/sns_authorize?appid={{ appid }}&response_type=code&scope=snsapi_login&state=test&redirect_uri=' + window.location.protocol + "//" + window.location.host + url)

    var obj = DDLogin({
        id: "login_container",//这里需要你在自己的页面定义一个HTML标签并设置id,例如<div id="login_container"></div>或<span id="login_container"></span>
        goto: goto,
        style: "border:none;background-color:#FFFFFF;",
        width: "300",
        height: "400"
    });

    var hanndleMessage = function (event) {
        var origin = event.origin;
        console.log("origin", event.origin);
        if (origin == "https://login.dingtalk.com") { //判断是否来自ddLogin扫码事件。
            var loginTmpCode = event.data; //拿到loginTmpCode后就可以在这里构造跳转链接进行跳转了
            console.log("loginTmpCode", loginTmpCode);
            var url2 = "https://oapi.dingtalk.com/connect/oauth2/sns_authorize?appid={{appid}}&response_type=code&scope=snsapi_login&state=NvSxTQh&redirect_uri=" + window.location.protocol + "//" + window.location.host + url + "&loginTmpCode=" + loginTmpCode;
            console.log("url2", url2)
            window.location.href = url2;
        }
    };

    if (typeof window.addEventListener != 'undefined') {
        window.addEventListener('message', hanndleMessage, false);
    } else if (typeof window.attachEvent != 'undefined') {
        window.attachEvent('onmessage', hanndleMessage);
    }

</script>