前端:Angular5.2
后端: 用dgate模擬后端返回?cái)?shù)據(jù)置蜀。(業(yè)務(wù)需要)
Github地址:https://github.com/DTeam-Top/dgate/blob/master/docs/user_guide.md
創(chuàng)建釘釘微應(yīng)用及其免登流程請(qǐng)查看釘釘官方文檔。
微應(yīng)用https://oa.dingtalk.com/index.htm#/microApp/microAppList
一. 準(zhǔn)備工作
將dingtalk.js集成到angular5中
1. 下載dingtalk.js 放到src目錄下。(見(jiàn)釘釘官網(wǎng))
2. 在src目錄下新建dingtalk.d.ts文件,并聲明變量dd以便調(diào)用jsapi。
declare var dd: any;
3. 在angular-cli.json文件中“scripts”中添加:
"scripts": [
"dingtalk.js",
...
],
4. 在tsconfig.json文件中添加:
"types": ["dingtalk.d.ts"],
dingtalk.js集成完畢缕题。
配置環(huán)境
在environment.ts以及dgate中配置好自己的ip。
為了讓手機(jī)訪問(wèn)angular項(xiàng)目需要開(kāi)啟ip訪問(wèn)胖腾,可以啟動(dòng)的時(shí)候:
ng serve --host 0.0.0.0
也可以在package.json中更改“scripts”對(duì)應(yīng)“start”的配置烟零。
新建dingding.ts文件,存放微應(yīng)用的corpId咸作,secret锨阿,agentId以便后面直接讀取。
請(qǐng)將手機(jī)和電腦位于同一局域網(wǎng)中记罚。
用戶數(shù)據(jù)準(zhǔn)備
本地創(chuàng)建一個(gè)mock-user.ts文件墅诡,以便存放用戶信息。主要用于登錄桐智,存放用戶名末早,密碼烟馅,以及dd_userid即可。(dd_userid為通過(guò)dd獲取到的userid荐吉,初始為空焙糟。)
二. 項(xiàng)目思路
用戶通過(guò)釘釘手機(jī)端訪問(wèn)自己創(chuàng)建的微應(yīng)用口渔。首次登錄時(shí)通過(guò)用戶名密碼登錄样屠,然后記錄該用戶的userid。下次登錄時(shí)匹配該userid即可缺脉。
dingding-backend.service.ts模擬實(shí)際項(xiàng)目中后端請(qǐng)求釘釘接口痪欲。
dingding-web.service.ts模擬實(shí)際項(xiàng)目中前端使用釘釘jsapi。
三. 實(shí)現(xiàn)
- 獲取access_token:https://oapi.dingtalk.com
/gettoken?corpid=id&corpsecret=secrect (后端)
- 根據(jù)access_token獲取ticket:https://oapi.dingtalk.com
/get_jsapi_ticket?access_token=ACCESS_TOKE(后端)
- 根據(jù)ticket獲取簽名signature鑒權(quán)(后端)
根據(jù)官網(wǎng)上https://open-doc.dingtalk.com/docs/doc.htm?spm=a219a.7386797.0.0.Sfinbc&source=search&treeId=168&articleId=107551&docType=1#s6 計(jì)算攻礼。
在angular5中簽名算法代碼如下:
getSign(access_token,ticket:string) {
// signature, nonstr, url, timestamp, CorpId, agentId
var origUrl = decodeURIComponent(window.location.href);
var origUrlObj = url.parse(origUrl);
delete origUrlObj['hash'];
var newUrl = url.format(origUrlObj);
var nonceStr = 'abcdefg';
var timeStamp = new Date().getTime();
var ticket = ticket;
var plain = 'jsapi_ticket=' + ticket +
'&noncestr=' + nonceStr +
'×tamp=' + timeStamp +
'&url=' + newUrl;
var sha1 = CryptoJS.SHA1(plain);
var signature = sha1.toString(CryptoJS.enc.hax)
let config = {
accessToken:access_token,
signature: signature,
nonceStr: nonceStr,
timeStamp: timeStamp,
corpId: dingding.corpId,
agentId: dingding.agentId
};
this.dingding.emit({type: 'config', config: config});
}
其中用到了CryptoJs使用SHA1加密业踢,具體請(qǐng)參考官方文檔。
然后通過(guò)EventEmitter模擬將config發(fā)送到“前端”礁扮。
- dingding-web-service.ts獲取到condig后知举,通過(guò)JSAPI獲取免登code。
ddJSAPI(config){
const $this = this;
dd.config({
agentId: config.agentId,
corpId: config.corpId,
timeStamp: config.timeStamp,
nonceStr: config.nonceStr,
signature: config.signature,
jsApiList: ['device.notification.confirm',
'device.notification.alert',
'device.notification.prompt',
'biz.chat.chooseConversation',
'biz.ding.post','biz.user.get']
});
dd.ready(function() {
dd.runtime.permission.requestAuthCode({
corpId: dingding.corpId,
onSuccess: function(result) {
$this.dingding.emit({type: 'code', code:result.code});
},
onFail : function(err) {}
});
// dd.biz.user.get({
// corpId:"dingbb55d760782ca6d535c2f4657eb6378f",
// onSuccess: function (info) {
// console.log('======.info===');
// console.log(info);
// alert(JSON.stringify(info))
// },
// onFail: function (err) {}
// });
})
}
獲取到免登code后傳遞給“后端”太伊。
可以通過(guò)dd.biz.user.get獲取用戶信息雇锡,為了安全起見(jiàn),官方推薦將code傳給后臺(tái)僚焦,由后端來(lái)獲取用戶信息锰提。
- 后端通過(guò)免登code獲取用戶info
獲取info:https://oapi.dingtalk.com
/user/getuserinfo?access_token=ACCESS_TOKEN&code=CODE
返回:
- 通過(guò)userid獲取詳細(xì)信息(非必要)
獲取詳細(xì)信息:https://oapi.dingtalk.com
/user/get?access_token=ACCESS_TOKEN&userid=zhangsan
- 獲取到userid后即可結(jié)合用戶名密碼進(jìn)行綁定。
下次該用戶訪問(wèn)時(shí)即可通過(guò)userid確定身份芳悲。
調(diào)試:
- 下載釘釘開(kāi)發(fā)版立肘,將手機(jī)通過(guò)usb連接電腦,打開(kāi)usb調(diào)試名扛。
釘釘開(kāi)發(fā)版以及配置:https://open-doc.dingtalk.com/docs/doc.htm?treeId=171&articleId=104908&docType=1
打開(kāi)chrome,輸入chrome://inspect/#devices 進(jìn)入調(diào)試頁(yè)面谅年。
-
進(jìn)入微應(yīng)用。這個(gè)時(shí)候會(huì)出現(xiàn)一個(gè)錯(cuò)誤:
image.png
vendor.bundle.js文件太大肮韧。所以啟動(dòng)的時(shí)候還需要加上--aot
-
現(xiàn)在應(yīng)該可以正常訪問(wèn)微應(yīng)用了融蹂,但是請(qǐng)求釘釘接口的時(shí)候,會(huì)報(bào)錯(cuò):
image.png
angular解決跨域的問(wèn)題是設(shè)置反向代理惹苗。
(1)在項(xiàng)目下添加proxy.config.json文件(和package.json同級(jí))
(2)添加文件內(nèi)容:
{
"/gettoken":{
"target": "https://oapi.dingtalk.com",
"secure": "false",
"changeOrigin": true
},
"/get_jsapi_ticket":{
"target": "https://oapi.dingtalk.com",
"secure": "false",
"changeOrigin": true
},
"/user":{
"target": "https://oapi.dingtalk.com",
"secure": "false",
"changeOrigin": true
}
}
(3)修改請(qǐng)求:
由于設(shè)置了反向代理殿较,所以請(qǐng)求為:
this.http.get('/gettoken', {params}).subscribe((res:any)=>{
this.access_token = res.access_token;
this.getTicket(res.access_token);
})
啟動(dòng)時(shí)加上 --proxy-configproxy.config.json
最終啟動(dòng)命令為:
"start": "ng serve --host 0.0.0.0 --aot --proxy-config proxy.config.json",
更多反向代理信息請(qǐng)查看Angular官方文檔。
- 訪問(wèn)釘釘接口后獲取到token等數(shù)據(jù)桩蓉,但是發(fā)現(xiàn)頁(yè)面并沒(méi)有出現(xiàn)淋纲,chrome控制臺(tái)報(bào)錯(cuò):‘null’ is not a function
通過(guò)排查發(fā)現(xiàn)是angular和android瀏覽器兼容問(wèn)題。
解決:
將polyfills.ts文件中支持IE瀏覽器的特性打開(kāi):
/** IE9, IE10 and IE11 requires all of the following polyfills. **/
// import 'core-js/es6/symbol';
import 'core-js/es6/object';
import 'core-js/es6/function';
import 'core-js/es6/parse-int';
import 'core-js/es6/parse-float';
import 'core-js/es6/number';
import 'core-js/es6/math';
import 'core-js/es6/string';
import 'core-js/es6/date';
import 'core-js/es6/array';
import 'core-js/es6/regexp';
import 'core-js/es6/map';
import 'core-js/es6/weak-map';
import 'core-js/es6/set';
現(xiàn)在可以看到頁(yè)面了院究。
- 免登流程完畢洽瞬。但是發(fā)現(xiàn)angular從dgate獲取的數(shù)據(jù)本涕,
不能主動(dòng)渲染頁(yè)面。
解決:
必須手動(dòng)觸發(fā)變更檢測(cè)伙窃。
- 導(dǎo)入ChangeDetectorRef
import { Component, OnInit, OnDestroy, ChangeDetectorRef } from '@angular/core';
- 構(gòu)造中
constructor(...
, private _ref: ChangeDetectorRef) {
...
this._ref.detach();
- 獲取到數(shù)據(jù)后
this._ref.detectChanges();
更多變更檢測(cè)信息請(qǐng)查看Angular官方文檔菩颖。
由于每個(gè)component都需要加上變更檢測(cè),所以如果項(xiàng)目中component相互之間的結(jié)構(gòu)復(fù)雜为障,那么對(duì)項(xiàng)目性能有很大的影響晦闰。