/dingding-demo-vue

dingding钉钉小程序h5微应用使用vue实现例子

Primary LanguageJavaScript

概述

钉钉在企业应用已经是一件很普遍的事情了,我这讲讲钉钉应用小程序中的h5微应用的开发。本文借鉴了lnexin的文章。主要从两个demo来阐述,第一个是通过依照钉钉官网的描述,html+java实现;第二个是使用vue+java实现。

实现逻辑

开发钉钉企业应用,针对企业内部应用。钉钉应用有一个非常好的特性:当我们配置的首页地址是局域网地址,手机连接在局域网,钉钉是能够访问应用的。

  • 1.获得相应企业管理员权限
  • 2.登陆钉钉开发后台,根据钉钉图文创建应用,创建成功后,可以获取到appkey和appSecret,同时在后台首页还可以获取到corpId 在这里插入图片描述- 3.在创建应用的时候需要填入首页地址,这个首页地址填入我们的页面地址,这个页面中必须包含钉钉的回调函数,用于获取code.

h5微应用-html+java demo

  • 1.首页 index.html 页面如下,加入了钉钉的回调函数,主要用于获取钉钉传过来的code,然后传递给后台。
<!DOCTYPE html>
<meta charset="UTF-8">
<html>

<head>
    <title>H5微应用开发demo</title>
    <!-- 这个必须引入的啊,钉钉的前端js SDK, 使用框架的请自行参照开发文档 -->
    <script src="https://g.alicdn.com/dingding/dingtalk-jsapi/2.7.13/dingtalk.open.js"></script>
    <!-- 这个jquery 想不想引入自己决定,没什么影响 -->
    <script src="https://cdn.staticfile.org/jquery/1.10.2/jquery.min.js"></script>
</head>

<body>
<hr>
<h1>H5微应用免登demo</h1>
<p>当前页面的url:</p>
<p id="url"></p>
<br>
<p>解析url,获取的corpID:</p>
<p id="corpId"></p>
<br>
<p>SDK初始化获取的code:</p>
<p id="code"></p>
<br>
<p>请求我们服务端,登录返回的结果:</p>
<p id="result"></p>
</body>
<script type="text/javascript">
    $(function () {
        //钉钉sdk 初始化
        // dd.ready参数为回调函数,在环境准备就绪时触发,jsapi的调用需要保证在该回调函数触发后调用,否则无效。
        dd.ready(function () {
            //获取当前网页的url
            //http://ding-web.lnexin.cn/?corpid=ding46a9582af5b7541b35c2f4657eb6378f
            var currentUrl = document.location.toString()
            $("#url").append(currentUrl)

            // 解析url中包含的corpId
            var corpId = '??';
            // var corpId = currentUrl.split("corpid=")[1];
            $("#corpId").append(corpId)

            //使用SDK 获取免登授权码
            dd.runtime.permission.requestAuthCode({
                corpId: corpId,
                onSuccess: function (result) {
                    var code = result.code;
                    $("#code").append(code)
                    //请求我们服务端的登陆地址
                    $.get("http://10.4.94.250:9000/ding/login?code=" + code + "&corpId=" + corpId, function (response) {
                        // 我们服务器返回的信息
                        // 下面代码主要是将返回结果显示出来,可以根据自己的数据结构随便写
                        for (item in response) {
                            $("#result").append("<li>" + item + ":" + response[item] + "</li>")
                        }
                        if (response.user) {
                            for (item in response.user) {
                                $("#result").append("<li>\t[user 属性] " + item + " : " + response.user[item] + "</li>")
                            }
                        }
                    });
                }
            });
        });
    })

</script>

</html>
  • 2.后台 后台使用springboot框架,后台关键代码如下:
package com.demo.ading.demo.service.impl;

import com.demo.ading.demo.constant.DingCodeEnum;
import com.demo.ading.demo.constant.DingProperties;
import com.demo.ading.demo.dto.DingAccessTokenDTO;
import com.demo.ading.demo.service.DingAuthService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpHeaders;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Service;
import org.springframework.web.client.RestTemplate;

import java.util.HashMap;
import java.util.Map;

@Slf4j
@Service
public class DingAuthServiceImpl implements DingAuthService {

    @Autowired
    private RestTemplate restTemplate;

    @Autowired
    private DingProperties dingProperties;

    public DingAccessTokenDTO accessToken(){
        long starTime = System.nanoTime();
        DingAccessTokenDTO dingAccessToken = null;
        String url = dingProperties.getDingAccessToken();
        HttpHeaders headers = new HttpHeaders();
        headers.setContentType(MediaType.APPLICATION_JSON);
        Map map = new HashMap();
        map.put("appkey", dingProperties.getAppKey());
        map.put("appsecret", dingProperties.getAppSecret());
        ResponseEntity<DingAccessTokenDTO> response = restTemplate.getForEntity(url, DingAccessTokenDTO.class,map);
        if(response.getStatusCode().is2xxSuccessful()){
            if(response.getBody()!=null && response.getBody().getErrcode().equals(DingCodeEnum.success.getCode())){
                dingAccessToken = response.getBody();
            }
        }
        if(dingAccessToken == null){
            log.warn("[1.1.1]获取钉钉token失败,地址:{},参数:{}",url,map);
        }

        log.info("[1.1.2]获取钉钉token结束,耗时:{}ms",(System.nanoTime()-starTime)/1000);
        return dingAccessToken;

    }

}

package com.demo.ading.demo.service.impl;

import com.demo.ading.demo.constant.DingCodeEnum;
import com.demo.ading.demo.constant.DingProperties;
import com.demo.ading.demo.dto.DingUserDTO;
import com.demo.ading.demo.dto.DingUserIdDTO;
import com.demo.ading.demo.service.DingUserService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpHeaders;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Service;
import org.springframework.web.client.RestTemplate;

import java.util.HashMap;
import java.util.Map;

@Service
@Slf4j
public class DingUserServiceImpl implements DingUserService {
    @Autowired
    private RestTemplate restTemplate;
    @Autowired
    private DingProperties dingProperties;

    public DingUserIdDTO getUserId(String access_token, String code){
        long starTime = System.nanoTime();
        DingUserIdDTO res = null;
        String url = dingProperties.getDingGetUserId();
        HttpHeaders headers = new HttpHeaders();
        headers.setContentType(MediaType.APPLICATION_JSON);
        Map map = new HashMap();
        map.put("access_token", access_token);
        map.put("code", code);
        ResponseEntity<DingUserIdDTO> response = restTemplate.getForEntity(url, DingUserIdDTO.class,map);
        if(response.getStatusCode().is2xxSuccessful()){
            if(response.getBody()!=null && response.getBody().getErrcode().equals(DingCodeEnum.success.getCode())){
                res = response.getBody();
            }
        }
        if(res == null){
            log.warn("[2.1.1]获取钉钉userid失败,地址:{},参数:{}",url,map);
        }

        log.info("[2.1.2]获取钉钉userid结束,耗时:{}ms",(System.nanoTime()-starTime)/1000);
        return res;

    }

    public DingUserDTO getUserInfo(String access_token, String userid){
        long starTime = System.nanoTime();
        DingUserDTO res = null;
        String url = dingProperties.getDingGetUser();
        HttpHeaders headers = new HttpHeaders();
        headers.setContentType(MediaType.APPLICATION_JSON);
        Map map = new HashMap();
        map.put("access_token", access_token);
        map.put("userid", userid);
        ResponseEntity<DingUserDTO> response = restTemplate.getForEntity(url, DingUserDTO.class,map);
        if(response.getStatusCode().is2xxSuccessful()){
            if(response.getBody()!=null && response.getBody().getErrcode().equals(DingCodeEnum.success.getCode())){
                res = response.getBody();
            }
        }
        if(res == null){
            log.warn("[2.2.1]获取钉钉user失败,地址:{},参数:{}",url,map);
        }

        log.info("[2.2.2]获取钉钉user结束,耗时:{}ms",(System.nanoTime()-starTime)/1000);
        return res;

    }
}

package com.demo.ading.demo.controller;

import com.demo.ading.demo.dto.DingAccessTokenDTO;
import com.demo.ading.demo.dto.DingUserDTO;
import com.demo.ading.demo.dto.DingUserIdDTO;
import com.demo.ading.demo.service.DingAuthService;
import com.demo.ading.demo.service.DingUserService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

import java.util.LinkedHashMap;
import java.util.Map;

@Slf4j
@RestController
@RequestMapping(value = "/ding")
public class UserController {

    @Autowired
    private DingAuthService dingAuthService;

    @Autowired
    private DingUserService dingUserService;

    /**
     * 根据前台初始化后获取的免登授权码获取用户信息
     *
     * @param code   免登授权码
     * @param corpId 企业应用corpId
     * @return
     */
    @GetMapping("/login")
    public Map<String,Object> authCodeLogin(@RequestParam("code") String code,
                                            @RequestParam("corpId") String corpId) {
        DingAccessTokenDTO accessTokenDTO = dingAuthService.accessToken();
        DingUserIdDTO userIdDTO = dingUserService.getUserId(accessTokenDTO.getAccess_token(), code);
        DingUserDTO userInfo = dingUserService.getUserInfo(accessTokenDTO.getAccess_token(), userIdDTO.getUserid());


        Map<String, Object> result = new LinkedHashMap<>();
        result.put("code", code);
        result.put("token", accessTokenDTO.getAccess_token());

        result.put("user", userInfo);
        result.put("corpId", corpId);

        log.debug("[钉钉] 用户免登, 根据免登授权码code, corpId获取用户信息, code: {}, corpId:{}, result:{}", code, corpId, result);

        return result;
    }
}

vue+java demo

  • 1.vue可以直接引用jsapi或者通过npm安装jsapi,本例子中遵循vue最佳时间,使用npm install dingtalk-jsapi --save 安装依赖库。
  • 2.创建dingding.js,主要是用获取钉钉回调过来的code,存入session中或者直接传递给后台。
import * as dd from 'dingtalk-jsapi';
dd.ready(function () {
    
    var corpId = '??';
    //使用SDK 获取免登授权码
    dd.runtime.permission.requestAuthCode({
        corpId: corpId,
        onSuccess: function (result) {
            var code = result.code;
            sessionStorage.setItem('code',code)
            alert(code);
        }
    });
});

export default {
    dd
}
    1. main.js中增加引入代码
import Vue from 'vue'
import App from './App.vue'
import router from './router'
import store from './store'
import ElementUI from 'element-ui';
import 'element-ui/lib/theme-chalk/index.css';
import dd from '@/components/util/dingding.js'
Vue.use(ElementUI);
Vue.config.productionTip = false
Vue.prototype.dd = dd

new Vue({
  router,
  store,
  render: h => h(App)
}).$mount('#app')

  • 4.后台使用第一个例子中的后台,vue完成demo地址:

https://github.com/Dylandelon/dingding-demo-vue.git

vuefirst

Project setup

npm install

Compiles and hot-reloads for development

npm run serve

Compiles and minifies for production

npm run build

Lints and fixes files

npm run lint

Customize configuration

See Configuration Reference.