专注七星彩网站开发,建设银行哈尔滨分行网站,华中农业大学基因编辑在线设计网站,wordpress d8文章目录 说明技术路线注意操作步骤思路图 一、创建钉钉应用二、创建java项目三、创建vue项目#xff08;或uniapp项目#xff09;#xff0c;npm引入sdk的依赖四、拥有公网域名端口。开发环境可以使用#xff08;贝锐花生壳等工具#xff09;五、打开钉钉开发者平台… 文章目录 说明技术路线注意操作步骤思路图 一、创建钉钉应用二、创建java项目三、创建vue项目或uniapp项目npm引入sdk的依赖四、拥有公网域名端口。开发环境可以使用贝锐花生壳等工具五、打开钉钉开发者平台配置钉钉应用的h5公网地址六、打开手机钉钉即可看到开发的页面 说明
由于钉钉开发文档的内容特别多虽然介绍已经非常仔细了当对于那些第一次看这个文档的时候会有些疑惑。为了避免少走很多弯路故写下该文章进行技术分享
本文主要功能1、钉钉免登录获取用户信息 2、钉钉获取当前的定位
简单来说就是在钉钉里面展示我们编写的手机格式大小的网页页面
技术路线
VUE作为前端开发框架后端为Springboot项目
可以直接通过npm运行项目或者nginx运行项目 为了方便只需要部署一个项目我把vue打包成为静态文件放置到Springboot的 static 文件中。
注意
1、钉钉开发文档有时候叫 开发H5微应用有时候叫 开发网页应用注意分辨
2、开发过程中有时候会用到小程序开发者工具注意看说明书。jsapi接口有时候这个工具用不了得实际放到钉钉dingtalk才有用
3、目前该分享只是涉及到网页应用不涉及小程序应用。要注意分辨操作步骤
1、获取钉钉的应用corpId/agentId/appKey/appSecret。开发环境可以自己注册企业自己创建钉钉应用注意配置免密的权限
2、创建java项目pom引入钉钉的sdk
3、创建vue项目或uniapp项目npm引入sdk的依赖
4、拥有公网域名端口。开发环境可以使用贝锐花生壳等工具
5、打开钉钉开发者平台配置钉钉应用的h5公网地址
6、打开手机钉钉即可看到开发的页面思路图
获取免登录 jsapi鉴权获取定位坐标只有安卓端 或 苹果端有用
一、创建钉钉应用
注册钉钉企业打开钉钉开发者平台
https://open-dev.dingtalk.com/
记录下 corpId 创建应用 记录下 agentId、appKey、appSecret 二、创建java项目
POM引入依赖因为钉钉的接口分为新的接口和旧的接口目前最新的版本新接口和旧接口都是可以使用的。所以两个接口的依赖同时引入
参考我上传到 gitee的后端代码
https://gitee.com/chencanzhan/cancan-java-share/tree/master/dingtalk-demo
核心pom文件 !-- 新的接口 --dependencygroupIdcom.aliyun/groupIdartifactIddingtalk/artifactIdversion2.1.21/version/dependency!-- 旧的接口 --dependencygroupIdcom.aliyun/groupIdartifactIdalibaba-dingtalk-service-sdk/artifactIdversion2.0.0/version/dependency核心代码
Service
public class DingH5Service {Value(${dingtalk.appKey})private String appKey;Value(${dingtalk.appSecret})private String accessKeySecret;public DingUserInfo getUserByCode(String code) {DingTalkClient client new DefaultDingTalkClient(https://oapi.dingtalk.com/topapi/v2/user/getuserinfo);OapiV2UserGetuserinfoRequest req new OapiV2UserGetuserinfoRequest();req.setCode(code);OapiV2UserGetuserinfoResponse rsp null;try {rsp client.execute(req, getAccessToken());} catch (Exception e) {throw new RuntimeException(e);}cn.hutool.json.JSONObject entries JSONUtil.parseObj(rsp.getBody());Integer errcode entries.getInt(errcode);if(errcode 0){cn.hutool.json.JSONObject result entries.getJSONObject(result);DingUserInfo dingUserInfo new DingUserInfo();dingUserInfo.setAssociatedUnionid(result.getStr(associated_unionid));String unionid result.getStr(unionid);dingUserInfo.setUnionid(unionid);String deviceId result.getStr(device_id);dingUserInfo.setDeviceId(deviceId);dingUserInfo.setSysLevel(result.getInt(sys_level));String name result.getStr(name);dingUserInfo.setName(name);dingUserInfo.setSys(result.getBool(sys));String userid result.getStr(userid);dingUserInfo.setUserid(userid);return dingUserInfo;}return null;}public String getJsapiTicket() {com.aliyun.dingtalkoauth2_1_0.Client client null;try {client createClient();} catch (Exception e) {throw new RuntimeException(e);}try {com.aliyun.dingtalkoauth2_1_0.models.CreateJsapiTicketHeaders createJsapiTicketHeaders new com.aliyun.dingtalkoauth2_1_0.models.CreateJsapiTicketHeaders();createJsapiTicketHeaders.xAcsDingtalkAccessToken getAccessToken();CreateJsapiTicketResponse jsapiTicketWithOptions client.createJsapiTicketWithOptions(createJsapiTicketHeaders, new RuntimeOptions());CreateJsapiTicketResponseBody body jsapiTicketWithOptions.getBody();return body.getJsapiTicket();} 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 null;}/*** 创建钉钉客户端* return* throws Exception*/public static com.aliyun.dingtalkoauth2_1_0.Client createClient() throws Exception {com.aliyun.teaopenapi.models.Config config new com.aliyun.teaopenapi.models.Config();config.protocol https;config.regionId central;return new com.aliyun.dingtalkoauth2_1_0.Client(config);}public String getAccessToken() throws Exception {com.aliyun.teaopenapi.models.Config config new com.aliyun.teaopenapi.models.Config();config.protocol https;config.regionId central;com.aliyun.dingtalkoauth2_1_0.Client client new com.aliyun.dingtalkoauth2_1_0.Client(config);com.aliyun.dingtalkoauth2_1_0.models.GetAccessTokenRequest getAccessTokenRequest new com.aliyun.dingtalkoauth2_1_0.models.GetAccessTokenRequest().setAppKey(appKey).setAppSecret(accessKeySecret);try {return client.getAccessToken(getAccessTokenRequest).getBody().getAccessToken();} 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 null;}}RestController
RequestMapping(/ding-h5)
public class DingH5Controller {Value(${dingtalk.agentId})private String agentId;Value(${dingtalk.corpId})private String corpId;Value(${dingtalk.appKey})private String appKey;Value(${dingtalk.urlPath})private String urlPath;Autowiredprivate DingH5Service dingH5Service;/*** 获取签名* param dingConfigSignVo* param request* return*/PostMapping(/signAll)public ResponseEntityObject signAll(RequestBody DingConfigSignVo dingConfigSignVo, HttpServletRequest request){String sign null;String signedUrl urlPath;String jticket dingH5Service.getJsapiTicket();dingConfigSignVo.setJsticket(jticket);MapString, Object jMap new HashMap();try {sign DdConfigSign.sign(dingConfigSignVo.getJsticket(),dingConfigSignVo.getNonceStr(),dingConfigSignVo.getTimeStamp(),signedUrl);} catch (Exception e) {throw new RuntimeException(e);}jMap.put(agentId,agentId);jMap.put(corpId,corpId);jMap.put(appKey,appKey);jMap.put(sign,sign);return new ResponseEntity(jMap, HttpStatus.OK);}/*** 根据code获取用户信息* param code* return*/GetMapping(/getUserByCode)public ResponseEntityObject getUserByCode(String code){DingUserInfo userByCode dingH5Service.getUserByCode(code);return new ResponseEntity(userByCode, HttpStatus.OK);}}/*** 计算dd.config的签名参数**/
public class DdConfigSign {/*** 计算dd.config的签名参数** param jsticket 通过微应用appKey获取的jsticket* param nonceStr 自定义固定字符串* param timeStamp 当前时间戳* param url 调用dd.config的当前页面URL* return* throws Exception*/public static String sign(String jsticket, String nonceStr, long timeStamp, String url) throws Exception {String plain jsapi_ticket jsticket noncestr nonceStr timestamp String.valueOf(timeStamp) url decodeUrl(url);try {MessageDigest sha1 MessageDigest.getInstance(SHA-256);sha1.reset();sha1.update(plain.getBytes(UTF-8));return byteToHex(sha1.digest());} catch (Exception e) {throw new Exception(e.getMessage());}}// 字节数组转化成十六进制字符串private static String byteToHex(final byte[] hash) {Formatter formatter new Formatter();for (byte b : hash) {formatter.format(%02x, b);}String result formatter.toString();formatter.close();return result;}/*** 因为ios端上传递的url是encode过的android是原始的url。开发者使用的也是原始url,* 所以需要把参数进行一般urlDecode** param url* return* throws Exception*/private static String decodeUrl(String url) throws Exception {URL urler new URL(url);StringBuilder urlBuffer new StringBuilder();urlBuffer.append(urler.getProtocol());urlBuffer.append(:);if (urler.getAuthority() ! null urler.getAuthority().length() 0) {urlBuffer.append(//);urlBuffer.append(urler.getAuthority());}if (urler.getPath() ! null) {urlBuffer.append(urler.getPath());}if (urler.getQuery() ! null) {urlBuffer.append(?);urlBuffer.append(URLDecoder.decode(urler.getQuery(), utf-8));}return urlBuffer.toString();}public static String getRandomStr(int count) {String base ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789;Random random new Random();StringBuffer sb new StringBuffer();for (int i 0; i count; i) {int number random.nextInt(base.length());sb.append(base.charAt(number));}return sb.toString();}
}三、创建vue项目或uniapp项目npm引入sdk的依赖
1、使用npm安装。
npm install dingtalk-jsapi --save2、加载 dingtalk-jsapi
import * as dd from dingtalk-jsapi; // 此方式为整体加载也可按需进行加载完整的代码
templateel-maindiv用户名{{name}}/divdiv当前位置{{rrsss.address}}/divbutton clickhandlegetSignAll测试/button/el-main
/templatescriptimport api from /api;
import * as dd from dingtalk-jsapi; // 此方式为整体加载也可按需进行加载export default {data() {return {t1: 0,name: ,agentId: ,appKey: ,corpId: ,sign: ,rrsss: {},}},mounted() {this.handlegetSignAll();},methods: {handlegetSignAll() {this.t1 Date.now()let params {nonceStr: a,timeStamp: this.t1}api.getSignAll(params).then(res {if (res res.status 200) {this.agentId res.data.agentIdthis.appKey res.data.appKeythis.corpId res.data.corpIdthis.sign res.data.signthis.setDDConfig();this.getAuthCode();}})},setDDConfig() {/**钉钉鉴权 */dd.config({agentId: this.agentId, // 必填微应用IDcorpId: this.corpId,//必填企业IDtimeStamp: this.t1, // 必填生成签名的时间戳nonceStr: a, // 必填自定义固定字符串。signature: this.sign, // 必填签名type: 0, //选填。0表示微应用的jsapi,1表示服务窗的jsapi不填默认为0。该参数从dingtalk.js的0.8.3版本开始支持jsApiList: [device.geolocation.get] // 必填需要使用的jsapi列表注意不要带dd。})this.getGeolocation();//该方法必须带上用来捕获鉴权出现的异常信息否则不方便排查出现的问题dd.error(function () {console.log(钉钉鉴权失败,无法定位等,请联系管理员,或重新尝试!);})},getGeolocation() {dd.ready(() {dd.device.geolocation.get({targetAccuracy: 200,coordinate: 1,withReGeocode: true,useCache: false,onSuccess: function (res) {// 调用成功时回调console.log(res)this.rrsss res},onFail: function (err) {// 调用失败时回调console.log(err)}});})},getAuthCode() {dd.requestAuthCode({corpId: this.corpId,clientId: this.appKey,onSuccess: (result) {api.getUserInfo({code:result.code}).then(res {if (res res.status 200) {this.name res.data.name}})},onFail: function () { },});} }
}
/script
style scoped
/style
四、拥有公网域名端口。开发环境可以使用贝锐花生壳等工具
这自己百度映射到本地端口可以直接通过npm运行项目或者nginx运行项目
为了方便只需要部署一个项目我把vue打包成为静态文件放置到Springboot的 static 文件中。五、打开钉钉开发者平台配置钉钉应用的h5公网地址
选择添加应用能力 填写公网域名 同时记得开放权限 六、打开手机钉钉即可看到开发的页面