钉钉 ISV 应用开发的一些心得
1. 背景
前段時間從前到后完整地做完了一個簡單的釘釘上的 ISV 應(yīng)用 —— 猿活動。
最開始想做這么一個小工具,是想到,平時部門中經(jīng)常會組織一些分享活動,但是這些分享活動卻沒有一個比較直觀的“站點(diǎn)”來記錄一次又一次的,很多人的努力的付出,這是很可惜的事。同時,在做這些活動的時候,也缺少一些互動的手段,比如現(xiàn)場簽到,打賞什么的。
好吧,剛開始的時候是這樣想的,當(dāng)然,在做的過程中,也發(fā)現(xiàn)釘釘?shù)幕凇敖M織”的應(yīng)用場景,在某些情況下限制挻大的(比如現(xiàn)場的交互,因為到現(xiàn)場的人并不一定是某個“企業(yè)”的成員),所以功能上也簡化了很多。(其實(shí)真相是只有 3 個周末時間,只能先搞出目前這些簡單功能了)
中間在做的過程中碰到了另一個朋友,他有一些想法,并且自己也盡力做了很多工作,就差個程序員。我見功能很簡單(就是最簡單的文章呈現(xiàn)功能),就幫他做出來了。之后,我也隨便把他的這塊內(nèi)容管理功能,及我之前想的活動相關(guān)的功能,合在一起,變成了現(xiàn)在這個應(yīng)用的樣子了。
http://ape.fgt.im?這個頁面中的 5 張圖就把這個小東西的功能說完了。
有興趣的,可以掃描上面的二維碼安裝試試看(需要企業(yè)管理員權(quán)限才能安裝應(yīng)用),或者直接訪問?http://ape.fgt.im?。
技術(shù)方面,前后端是完全分離的。
后端用 Python 寫的,一套東西是 tornado 和 sqlalchemy 。代碼在:(附件)
前端是 AngularJS 那套,代碼在:TODO (前端代碼目前跟我工作上的業(yè)務(wù)代碼是一起的,對外就不方便了哈,以后有機(jī)會拆出來我再回來補(bǔ)吧)
其實(shí)還有另外一套東西,掃碼登錄的那個簡單后臺,也是一個單獨(dú)的前端項目(配合約定的后端服務(wù)的格式工作),代碼在:TODO (代碼目前跟我工作上的業(yè)務(wù)代碼是一起的,對外就不方便了哈,以后有機(jī)會拆出來我再回來補(bǔ)吧)
2. 做一個套件與做 N 個套件沒區(qū)別
先說第一點(diǎn)心得。這方面你應(yīng)該已經(jīng)理解 ISV 中的套件是如何工作的了,如果不清楚,可以先看看:
- 釘釘手機(jī)端應(yīng)用獲取當(dāng)前用戶信息流程?https://www.zouyesheng.com/dingding-userinfo.html
- 釘釘 ISV 接入流程?https://www.zouyesheng.com/dingding-isv.html
一般我們最開始來做一個套件時,會習(xí)慣性地把套件相關(guān)信息(?suite_key,?suite_secret,token?等)作為配置寫到配置文件當(dāng)中。最開始我也是這樣干的。但是在對接流程時,這樣我經(jīng)常會有非常別扭的感覺。原因是,除了套件本身的信息,在 ISV 的授權(quán)流程當(dāng)中,企業(yè)相關(guān)的信息,你還是得作一般化的,比較正式的持久化處理,因為會有 N 個企業(yè)用到你的套件,每個企業(yè)都有自己的一套“配置信息”。簡單來說,企業(yè)這套信息你要放到關(guān)系數(shù)據(jù)庫的表中保存。
再者釘釘?shù)膽?yīng)用場景一般是基于“組織”的,也就是說你的業(yè)務(wù)數(shù)據(jù)模型中,“企業(yè)”一定是一個獨(dú)立的實(shí)體(很多業(yè)務(wù)的實(shí)體表中,都會有一個“企業(yè)”的外鍵)。
現(xiàn)在,“企業(yè)”已經(jīng)是一個連接業(yè)務(wù)流程,跟釘釘授權(quán)流程的一個中間角色了。再細(xì)想釘釘?shù)氖跈?quán)流程,企業(yè)的授權(quán)對象,是“套件”,而企業(yè)的授權(quán)狀態(tài)本身有多種,這也是一個需要在記錄的東西。到這里,其實(shí)已經(jīng)能看出來,如果在數(shù)據(jù)模型中沒有“套件”這個實(shí)體,已經(jīng)會讓人不舒服了。
更進(jìn)一步,套件本身還有近 10 個屬性,而且有幾個屬性還是動態(tài)的。(這跟你接一個統(tǒng)一的用戶系統(tǒng),只在相關(guān)表中記一個用戶 ID 完全不是一回事了)
與其在配置文件中寫死套件的幾屬性,再搞個緩存系統(tǒng)什么的去維護(hù)這個套件另外幾個屬性,同時忍受數(shù)據(jù)模型中因為沒有“套件”這個實(shí)體的不完整感:
你就專門為套件建一個表,每個套件作為一條記錄來維護(hù)相關(guān)信息,是一個更直觀,更經(jīng)濟(jì),更靈活的處理方式。
而多出“套件”這個維度的代價,僅僅受限在 ISV 授權(quán)流程中,并不會蔓延到你的業(yè)務(wù)流程中去,因為你的業(yè)務(wù)流程只關(guān)注這是哪個企業(yè)的數(shù)據(jù),而不關(guān)心它到底是從哪個應(yīng)用來的。
我用 6 張表處理 ISV 授權(quán)的流程數(shù)據(jù):
- dingding_isv_corp_relieve?是企業(yè)取消授權(quán)時的一個歷史記錄。
- dingding_isv_corp_app_agent?是?app_id?與?agent_id?的對應(yīng)關(guān)系,這在獲取企業(yè)授權(quán)之后,通過服務(wù)端服務(wù)可以查詢到,并且在激活應(yīng)用時需要用到相關(guān)信息,在 jsapi 簽名響應(yīng)時也需要響應(yīng)?agent_id?信息。
- dingding_isv_agent?這個記錄企業(yè)中的?agent?的狀態(tài)。
把套件作為單獨(dú)是的實(shí)體在系統(tǒng)中處理之后,創(chuàng)建套件本身就是一個隨手的事了。
- 新建一條記錄,填上新建套件的?token?和?aes_key?。
- 新建套件的回調(diào)地址中,需要標(biāo)識套件。(用參數(shù)或?qū)懺诼窂街?#xff0c;我是寫在路徑中的,比如http://ape.fgt.im/dingding-isv-callback/SUITE)
成功創(chuàng)建套之后,再把?suite_key?等信息補(bǔ)到數(shù)據(jù)庫中就好了。
這一步開發(fā)出的,隨時隨手創(chuàng)建套件的能力,為之后我們的調(diào)試提供了巨大的方便。
整個流程的視頻演示:
(優(yōu)酷沒有 HTTPS 的支持,視頻在http://v.youku.com/v_show/id_XMTY1MjI4ODMzMg==.html)
3. 使用 SSH 遠(yuǎn)程轉(zhuǎn)發(fā)調(diào)試后端
這算是所有跟公網(wǎng)回調(diào)相關(guān)的場景的標(biāo)準(zhǔn)處理方式了吧,以前做微信的公眾號開發(fā)時就這樣干的。
簡單來說,像釘釘?shù)耐扑瓦@種,它需要訪問公網(wǎng)機(jī)器,并且之后的調(diào)試你也不方便在手機(jī)上作靜態(tài)的 DNS 設(shè)置,這在開發(fā)時是比較不方便的,直接登錄服務(wù)器寫代碼畢竟沒有自己本地機(jī)器舒服。
所以我們想到的一個辦法,就是通過代理把遠(yuǎn)端服務(wù)器上的訪問導(dǎo)到本機(jī)。而這種遠(yuǎn)端轉(zhuǎn)發(fā)的能力,是 SSH 自帶的。兩步就可以了:
- 在?sshd?的配置中(比如?/etc/ssh/sshd_config)添加: GatewayPorts clientspecified 這讓客戶端可以指定轉(zhuǎn)發(fā)端口。
- 然后本機(jī)啟: ssh -R 0.0.0.0:9000:localhost:8888 root@host 就是把到達(dá)遠(yuǎn)端任意網(wǎng)卡的 9000 端口訪問都轉(zhuǎn)到本機(jī)的 8888 端口上來。這樣我們本機(jī)服務(wù)啟到 8888 上就可以正常響應(yīng)釘釘服務(wù)器對公網(wǎng)機(jī)器的訪問了。
更多的細(xì)節(jié)可以參考:?http://www.ibm.com/developerworks/cn/linux/l-cn-sshforward/
4. 為各個環(huán)境創(chuàng)建利于前端調(diào)試的應(yīng)用
因為是前后端代碼完全分離的結(jié)構(gòu),所以前端的調(diào)試上需要稍微單獨(dú)設(shè)計一下。前后完全分離,就是后端除了渲染一個頁面(里面會加載前端資源)之外,剩下的全是響應(yīng) json 的服務(wù)。
之前開發(fā) PC 上的頁面是,我們的做法是本地啟一個靜態(tài) Web 服務(wù)就好了,后端資源的地址前端隨意控制的。這樣我改前端代碼,直接在瀏覽器刷新就能看到效果,調(diào)試很方便。
但是換到做釘釘?shù)囊苿佣隧撁鏁r,情況有點(diǎn)不同,就是登錄流程及釘釘?shù)?jsapi 部分。業(yè)務(wù)上的登錄流程需要在釘釘環(huán)境才能完成,單獨(dú)的瀏覽器環(huán)境無法登錄(當(dāng)然你可以單獨(dú)做另一套登錄機(jī)制)。釘釘?shù)?jsapi 部分在單獨(dú)的瀏覽器上更沒辦法。
所以,我們需要在釘釘上調(diào)試。這方面,最簡單直接的辦法就是讓釘釘掃二維碼來打開指定頁面(同網(wǎng)內(nèi)部地址都可以)。不過在登錄上有個小問題,就是?corp_id,?app_id?這些參數(shù),為了登錄流程正常完成,你可能總是需要自己把這些參數(shù)寫死加上之后,再生成二維碼讓釘釘來掃。(而為了找這些參數(shù),可能你總是需要多次登錄管理后臺,相信我,這事一點(diǎn)也不有趣)
“開發(fā)體驗”對心情的影響是很重要的,也效率的影響也是極大的,我希望的環(huán)境是打開電腦寫完代碼就能看到結(jié)果,還要去找參數(shù),還去拼地址,還去生成二維碼,還去掃碼,太麻煩。
我現(xiàn)在的作法是,直接創(chuàng)建一個為開發(fā)調(diào)試而用的套件,里面又為各個前端環(huán)境創(chuàng)建不同的應(yīng)用(比如CDN測試環(huán)境,公司時的本機(jī)環(huán)境,家里時的本機(jī)環(huán)境)。這樣,我只需要本機(jī)啟一個靜態(tài) Web 服務(wù)器(本機(jī) IP 相對是固定的),改完前端代碼,在釘釘中直接打開相應(yīng)的應(yīng)用就可以了,其它事都不用管,世界清靜了。
總結(jié)
以上是生活随笔為你收集整理的钉钉 ISV 应用开发的一些心得的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 前端接入HTTP协议浅析
- 下一篇: 使用系统的CoreLocation定位