摘要:年度的支付寶賬單果然不負(fù)眾望,再一次刷屏了。于是乎,我決定探究一下支付寶賬單背后的技術(shù)實(shí)現(xiàn)。三后端數(shù)據(jù)整合這部分內(nèi)容將重點(diǎn)介紹支付寶賬單數(shù)據(jù)的形成,純屬個(gè)人對(duì)支付寶技術(shù)架構(gòu)的了解進(jìn)行猜想的,并不代表是真實(shí)的運(yùn)作情況。
2017年度的支付寶賬單果然不負(fù)眾望,再一次刷屏了。
回顧一下這個(gè)年關(guān),現(xiàn)象級(jí)的刷屏活動(dòng)就有三起:
秀“18歲”;秀網(wǎng)易音樂歌單;秀支付寶賬單。
一位網(wǎng)友調(diào)侃道:2018年大型“相親”節(jié)目就此拉開帷幕……
秀“18歲”,看顏值;
秀網(wǎng)易音樂歌單,曬品味;
秀支付寶賬單,炫財(cái)富。
“相親”的三個(gè)重要指標(biāo)不就都齊了嗎?!
玩笑歸玩笑,身為一名程序員的我,“職業(yè)病”又犯了。就像微信出品的“跳一跳”小程序,各種外掛,刷分攻略絡(luò)繹不絕,占領(lǐng)各大技術(shù)媒體頭條。
于是乎,我決定探究一下支付寶賬單背后的技術(shù)實(shí)現(xiàn)。但這并不意味著我會(huì)再造一個(gè)支付寶賬單出來,畢竟這份賬單核心部分是背后的海量消費(fèi)數(shù)據(jù),這并不是我等刁民能獲取得到的。
由于個(gè)人經(jīng)驗(yàn)水平有限,本文所作猜想如有不足之處,敬請(qǐng)指正。如果有螞蟻金服的同學(xué)愿意分享賬單背后的技術(shù)架構(gòu),想必也是非常受歡迎的。
本文是對(duì)支付寶賬單技術(shù)實(shí)現(xiàn)的個(gè)人猜想,我將此簡單粗暴的分成了兩部分:前端,后端。由表及里,從看得見的前端展示來推測看不見的后端邏輯。
一、尋找突破口整個(gè)探索過程的第一步就是找入口,我認(rèn)為這是一個(gè)非常關(guān)鍵的突破口。我將賬單通過釘釘分享出來,然后進(jìn)入釘釘?shù)腜C版,右鍵那條分享記錄,即可復(fù)制整個(gè)URL。
為了方便講解,這里把整個(gè)URL放出來給大家看看:
https://render.alipay.com/p/s/i/?scheme=alipays://platformapi/startapp?appId=68687017&showOptionMenu=NO&allowsBounceVertical=NO&transparentTitle=auto&bizScenario=Share&url=https://render.alipay.com/p/f/fd-jbg7if4k/index.html
整個(gè)scheme參數(shù)的作用就是會(huì)去嘗試打開手機(jī)上的支付寶應(yīng)用,這對(duì)于做移動(dòng)開發(fā)的同學(xué)來說是很容易看懂的。當(dāng)然這種嘗試不一定都是成功的,這要看瀏覽器的安全策略了,以下是在Safari(iPhone)和Chrome(PC)中打開的結(jié)果:
scheme自帶了6個(gè)參數(shù),這都將會(huì)傳入到APP中,執(zhí)行相應(yīng)的操作。本以為每個(gè)用戶分享出來的scheme參數(shù)會(huì)有所不同,但是經(jīng)過我一番對(duì)比后,發(fā)現(xiàn)都是同樣的參數(shù)。經(jīng)過后面對(duì)源碼的一番研究后,發(fā)現(xiàn)「bizScenario」參數(shù)會(huì)不同,因?yàn)槲沂菑尼斸敺窒碚业酵黄瓶诘模詁izScenario的值都是Share,但如果是從其他渠道打開的,取值就不一定是一樣了。
至于用戶信息,應(yīng)該是在頁面中通過js與native進(jìn)行交互獲取的。如果我們想看最終的賬單頁面的話,直接把scheme當(dāng)中的url參數(shù)copy出來,在瀏覽器中打開即可。
至此,我們就打開了一扇探索支付寶賬單的大門了。
二、前端頁面實(shí)現(xiàn)首先需要明白的是支付寶賬單是一個(gè)Single Page Application,換言之,就是一個(gè)由html+js實(shí)現(xiàn)的單頁應(yīng)用,我了解到的是靜態(tài)背景圖片+過場動(dòng)畫+數(shù)據(jù)圖層。這樣做不僅有效解決了跨平臺(tái)問題,而且更有利于傳播。
值得一提的是整個(gè)應(yīng)用的css和js文件,包括資源請(qǐng)求url等,都做了一定的加密和混淆,要想讀懂,還是有一定困難的,尤其是js代碼。
靜態(tài)背景圖片總共有9張,我這里放三張,大家可以感受一下。
過場動(dòng)畫其實(shí)是一系列的mp4文件組成的,放在video標(biāo)簽里播放,篇幅有限,這里只放一段視頻,讓大家感受一下。
至于數(shù)據(jù)來源及其圖層都是通過js來完成的,下面的截圖來自chrome控制臺(tái),展現(xiàn)了頁面的主體DOM元素。
大致分為了三個(gè)部分:加載,賬單主體內(nèi)容,錯(cuò)誤提示。
加載過程中主要有兩個(gè)元素,一個(gè)是加載動(dòng)畫,其實(shí)就是一個(gè)翻日歷的gif動(dòng)畫;另一個(gè)就是進(jìn)度百分比,這個(gè)不用細(xì)想,肯定做的是假的進(jìn)度指示。通過「AlipayJSBridge」,委托Native APP發(fā)送賬單數(shù)據(jù)請(qǐng)求,在這個(gè)過程中,進(jìn)度指示按照一定的速率增長,大概是到了97%的時(shí)候會(huì)停下來,直到數(shù)據(jù)獲取完畢了再正式進(jìn)入賬單頁面。
賬單主體內(nèi)容由三部分組成:第一個(gè)是swiper,滑動(dòng)屏幕切換場景,其下有9個(gè)子元素,9張靜態(tài)圖片,分別對(duì)應(yīng)了9個(gè)場景;第二個(gè)和第三個(gè)部分則是兩個(gè)video標(biāo)簽,分別播放下一個(gè)場景和上一個(gè)場景的mp4文件。
錯(cuò)誤提示的部分沒什么好解釋的,一行提示文字,一個(gè)重試按鈕,一目了然。
有讀者可能會(huì)問,這些圖片、視頻之類的資源怎么得到的?這是我接下來要講解的內(nèi)容。
先來看一段數(shù)據(jù)結(jié)構(gòu)的定義:
// 靜態(tài)資源。 window.resource = [ { "scene": "https://gw.alipayobjects.com/zos/rmsportal/epRpbpBcCZIKasROmxcL.jpg", "video": { "forward": "", "back": "" }, "__key": 9 }, { "scene": "https://gw.alipayobjects.com/zos/rmsportal/epRpbpBcCZIKasROmxcL.jpg", "video": { "forward": "https://gw.alipayobjects.com/os/rmsportal/KwIPQNAHVfCMQSToOqxX.mp4", "back": "https://gw.alipayobjects.com/os/rmsportal/zRAHVrBufLRAlmOMwXgA.mp4" }, "__key": 1 }, { "scene": "https://gw.alipayobjects.com/zos/rmsportal/ALzmXZZYrnFDqYFFrGjY.jpg", "video": { "forward": "https://gw.alipayobjects.com/os/rmsportal/QuZvhHxfIyRqgNxGQRqq.mp4", "back": "https://gw.alipayobjects.com/os/rmsportal/zRAHVrBufLRAlmOMwXgA.mp4" }, "__key": 2 }, { "scene": "https://gw.alipayobjects.com/zos/rmsportal/ZcmJnyzRQNuFspDzfoxX.jpg", "video": { "forward": "https://gw.alipayobjects.com/os/rmsportal/CLryDglMNEQLfDxmYnUW.mp4", "back": "https://gw.alipayobjects.com/os/rmsportal/nmqWCcwURUxRdUqgdJje.mp4" }, "__key": 3 }, { "scene": "https://gw.alipayobjects.com/zos/rmsportal/qQLBJCGEDtXCoCiOtPzc.jpg", "video": { "forward": "https://gw.alipayobjects.com/os/rmsportal/TUKbyXyonamHXwQifpDQ.mp4", "back": "https://gw.alipayobjects.com/os/rmsportal/rwcPCPShQgxvVYfobSeU.mp4" }, "__key": 4 }, { "scene": "https://gw.alipayobjects.com/zos/rmsportal/zQzcNkGFJJqHinrABCDa.jpg", "video": { "forward": "https://gw.alipayobjects.com/os/rmsportal/OBocUmcqGaHuZJJkNQvV.mp4", "back": "https://gw.alipayobjects.com/os/rmsportal/HbyqRtKZMlKFQZcxwCJy.mp4" }, "__key": 5 }, { "scene": "https://gw.alipayobjects.com/zos/rmsportal/JzzNsINqFRVOCAMNJonO.jpg", "video": { "forward": "https://gw.alipayobjects.com/os/rmsportal/kBYTpmZElHykGKYytIIG.mp4", "back": "https://gw.alipayobjects.com/os/rmsportal/zvFLfvTTgXdUUCFHuIlv.mp4" }, "__key": 6 }, { "scene": "https://gw.alipayobjects.com/zos/rmsportal/vOpPBFXzjbvlSAxZBcSB.jpg", "video": { "forward": "https://gw.alipayobjects.com/os/rmsportal/dIPIDFjkwlJkxwjbtmRO.mp4", "back": "https://gw.alipayobjects.com/os/rmsportal/VIbUIjvACyUlBSVULXbB.mp4" }, "__key": 7 }, { "scene": "https://gw.alipayobjects.com/zos/rmsportal/HJUaMfRgdvNwrxJgibsJ.jpg", "video": { "forward": "https://gw.alipayobjects.com/os/rmsportal/egQUtbPUbknxskiWkGgU.mp4", "back": "https://gw.alipayobjects.com/os/rmsportal/JlBuZvsTbtOGIiUDNTuW.mp4" }, "__key": 8, "poster": "https://gw.alipayobjects.com/zos/rmsportal/guBrTMglMdSRsWcRnaXB.jpg" } ];
這段代碼出自賬單頁面,從Chrome控制臺(tái)里復(fù)制出來的。
scene 為靜態(tài)圖片,用作背景;forward 為前進(jìn)動(dòng)畫,back 為后退動(dòng)畫;poster 似乎意義不大(從實(shí)現(xiàn)上考慮),可以認(rèn)為是對(duì)scene的“備胎”;至于__key字段最值得斟酌,在以下給出的代碼中,會(huì)有我對(duì)此字段的理解。
特別注意一下最后一組場景對(duì)象,forward 里面的視頻內(nèi)容在整個(gè)賬單似乎都沒有出現(xiàn)過,一個(gè)不小心就讓我看到了動(dòng)畫制作的外包商名字了,這是程序猿哥哥加的“雞腿”嗎?
還需要注意的是 forward 和 back 的取值含義。forward 字段的取值含義還是比較好理解,就是當(dāng)前場景滑向下一個(gè)場景所播放的過場動(dòng)畫,而 back 字段的取值含義稍微有點(diǎn)繞,我直接舉個(gè)例子:__key=3的場景對(duì)象中,back字段記錄的是回退到__key=2的場景的過場動(dòng)畫。
因?yàn)閖s源代碼被混淆得實(shí)在是沒法看懂了,只能根據(jù)交互的效果來猜想代碼實(shí)現(xiàn)。以下是場景切換的代碼:
//此處也可以直接賦值為0,猜想__key的作用,為了用上此字段 var index = window.resource[0].__key; var len = window.resource.length; function next() { if(index == window.resource[len - 1].__key) return; //at the last page index = (index + 1) % len; var resource = window.resource[index]; //1. play video in resource.forward. //2. video player listener binding. //3. to display data with animations after forward video completed. } function previous() { if(index == window.resource[0].__key) return; //at the first page var resource = window.resource[index]; //1. play video in resource.back. //2. video player listener binding. //3. to display data with animations after back video completed. //4. set value for index variable. index = (index == window.resource[1].__key) ? window.resource[0].__key : index--; }
主要是通過對(duì)len取模,對(duì)場景進(jìn)行前后切換,這樣做可以達(dá)到循環(huán)播放的效果。對(duì)于__key字段的猜想也在代碼中體現(xiàn)了,值得一提的是,在所有的js源代碼中搜索了一番,并沒有發(fā)現(xiàn)有任何地方用到了這個(gè)字段,不知道是不是被加密混淆了。
至此,關(guān)于前端的頁面展示部分的介紹就結(jié)束了。
三、后端數(shù)據(jù)整合這部分內(nèi)容將重點(diǎn)介紹支付寶賬單數(shù)據(jù)的形成,純屬個(gè)人對(duì)支付寶技術(shù)架構(gòu)的了解進(jìn)行猜想的,并不代表是真實(shí)的運(yùn)作情況。
以上是我認(rèn)為比較合理的架構(gòu)圖,架構(gòu)的視角放在了Data層面。
1、Database,這一個(gè)層次表示的是云數(shù)據(jù)庫集群,整個(gè)集群中的數(shù)據(jù)庫極有可能是異構(gòu)的,如MySQL,Oracle,PostgreSQL,MongoDB等等,此外,這里所說的集群也涵蓋了淘寶,天貓,支付寶等阿里體系中的產(chǎn)品所使用的數(shù)據(jù)庫,所以這一部分承載了較多的數(shù)據(jù)輸入輸出的工作,至關(guān)重要。
2、DW,Data Warehouse,即數(shù)據(jù)倉庫。其中重要的數(shù)據(jù)來源是云數(shù)據(jù)庫集群,也會(huì)有一些直接來自文件。在數(shù)據(jù)倉庫里面能實(shí)現(xiàn)的功能就非常多了,其中當(dāng)屬ETL工作,這也是BI的必經(jīng)之路,配合Reporting System,可以實(shí)現(xiàn)數(shù)據(jù)可視化,日志分析,運(yùn)維監(jiān)控等功能。
3、MaxCompute,這個(gè)其實(shí)是屬于阿里云的一個(gè)大規(guī)模分布式計(jì)算平臺(tái),其中以Hadoop、Spark為代表的分布式計(jì)算框架,Hadoop擅長離線計(jì)算,Spark則可以完成快速實(shí)時(shí)計(jì)算。
4、DRDS和REST APIs。DRDS同樣也是阿里云出品的數(shù)據(jù)庫中間件產(chǎn)品,上述提到過云數(shù)據(jù)庫集群是異構(gòu)的,必須有一個(gè)中間件參與數(shù)據(jù)的讀寫工作。至于REST APIs,主要是提供一些列的API,以便客戶端進(jìn)行數(shù)據(jù)操作。
解釋完了整張架構(gòu)圖后,我再進(jìn)一步將整個(gè)數(shù)據(jù)請(qǐng)求流程梳理一遍。
1、數(shù)據(jù)的產(chǎn)生。主要是用戶2017年度的消費(fèi)記錄,來自天貓,淘寶,支付寶,螞蟻信用等平臺(tái),這些數(shù)據(jù)大部分被結(jié)構(gòu)化的存儲(chǔ)在了數(shù)據(jù)庫集群中;
2、年度賬單數(shù)據(jù)的生成。將用戶2017年度的消費(fèi)數(shù)據(jù)導(dǎo)入到數(shù)據(jù)倉庫中,經(jīng)由分布式計(jì)算平臺(tái)離線計(jì)算出每位用戶的賬單數(shù)據(jù),將這份結(jié)構(gòu)化的賬單數(shù)據(jù)再放入數(shù)據(jù)庫集群中。這里使用離線計(jì)算是比較明智的,畢竟數(shù)據(jù)都是PB級(jí)別的,實(shí)時(shí)計(jì)算也只能針對(duì)個(gè)別用戶,不然的話,會(huì)對(duì)用戶體驗(yàn)造成一定的影響。這部分的工作,簡單地說,就是寫若干個(gè)MapReduce任務(wù),在分布式計(jì)算平臺(tái)上跑2~3天應(yīng)該就差不多了;
3、數(shù)據(jù)獲取。到這個(gè)步驟,說明賬單數(shù)據(jù)已經(jīng)準(zhǔn)備就緒了,客戶端只需要調(diào)用API即可獲取,也就能做出我們現(xiàn)在所看到的賬單頁面了。
四、一點(diǎn)小改進(jìn)基于對(duì)前端展示的研究,我才做出了上述架構(gòu)的猜想,但這并不是我第一直覺的產(chǎn)物。我一直認(rèn)為像支付寶賬單,網(wǎng)易歌單這類年度盤點(diǎn)的營銷活動(dòng),可以使用「頁面靜態(tài)化」技術(shù)。當(dāng)然,這樣的架構(gòu)也是有利有弊,先看一張改進(jìn)后的架構(gòu)圖。
可以看到,前端和后端可以說已經(jīng)處于一個(gè)高度解耦的狀態(tài)了,后端只負(fù)責(zé)賬單數(shù)據(jù)的生成,并填充好用戶的賬單頁面,而前端訪問指定的靜態(tài)HTML頁面即可。針對(duì)這個(gè)架構(gòu),我們來討論如下三個(gè)問題:
1、html文件命名方式。這個(gè)想象空間還是很大的,規(guī)則也各式各樣,比如簡單粗暴地將用戶id,生成時(shí)間等元素進(jìn)行Hash。當(dāng)然,對(duì)于文件目錄也是有要求的,這里就不再深究了。
2、頁面靜態(tài)化技術(shù)選型。理論上,最佳的選擇就是CDN技術(shù),這方面的技術(shù)在市面上已經(jīng)比較成熟了,可以放心使用。如果不用CDN的話,那可以考慮利用squid,做一個(gè)緩存代理緩存服務(wù),可以認(rèn)為是精簡版的CDN,如果只需要內(nèi)容分發(fā)而不考慮其他更高級(jí)的功能,squid不失為一個(gè)好的解決方案。
3、適用場景分析。頁面靜態(tài)化最吸引我的地方就是減輕了大量后端數(shù)據(jù)訪問的壓力,將壓力轉(zhuǎn)移給了CDN,但是大可不必?fù)?dān)心,因?yàn)檫@是CDN的長項(xiàng),實(shí)現(xiàn)成本低,不易觸及瓶頸,此外,沒有額外的網(wǎng)絡(luò)數(shù)據(jù)訪問,不僅不會(huì)暴露API,有一定的安全保障,前端頁面也可以做到秒開,給用戶帶來了絕佳的體驗(yàn)。因此,既然是頁面靜態(tài)化,那么肯定就不適合那些頁面頻繁改動(dòng),或者有強(qiáng)交互的場景。
本來這次支付寶賬單頁面完全可以靜態(tài)化,后來發(fā)生的「授權(quán)協(xié)議門」事件讓我打消了這個(gè)念頭,這個(gè)小插曲的出現(xiàn)就意味著需要將之前生成好的頁面全部失效并整改,又會(huì)引起一大波流量,也會(huì)引起存儲(chǔ)空間的浪費(fèi),除非是替換之前的文件。不過細(xì)想一下,支付寶賬單頁面嵌入了動(dòng)態(tài)授權(quán),也就不好做頁面靜態(tài)化了。
五、總結(jié)本文從前端到后端兩個(gè)層面,對(duì)支付寶賬單的技術(shù)實(shí)現(xiàn)做了一次非常淺顯的剖析,對(duì)于一些無法得知的技術(shù)細(xì)節(jié),也給了一部分自己的實(shí)現(xiàn)思路。如果讀者看了這篇文章之后,對(duì)此也非常感興趣,也可以針對(duì)這個(gè)話題發(fā)表自己的想法。
每日干貨分享,傳遞互聯(lián)網(wǎng)世界有價(jià)值的訊息,微信公眾號(hào):技術(shù)匯
文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請(qǐng)注明本文地址:http://specialneedsforspecialkids.com/yun/11821.html
摘要:關(guān)于無輸出錯(cuò)誤最近接入支付寶支付時(shí)遇到一個(gè)問題,在做支付回調(diào)函數(shù)的時(shí)候我先是寫了一個(gè)用來記錄回調(diào)時(shí)的支付寶請(qǐng)求參數(shù),但發(fā)現(xiàn)無論如何日志都沒有任何記錄,而且回調(diào)函數(shù)里面的東西也沒用執(zhí)行,于是我自己請(qǐng)求該回調(diào)地址,發(fā)現(xiàn)服務(wù)器上狀態(tài)碼為但是沒有 關(guān)于LUMEN無輸出500錯(cuò)誤 最近接入支付寶支付時(shí)遇到一個(gè)問題,在做支付回調(diào)函數(shù)的時(shí)候我先是寫了一個(gè) Log::info(alipay_notif...
摘要:另外小程序云應(yīng)用有一套高可用架構(gòu),提供監(jiān)控預(yù)警能力。自主可控小程序云應(yīng)用提供服務(wù)器,開發(fā)者可以擁有登錄或重啟,也可以修改密碼。也就是說,服務(wù)器是由小程序云應(yīng)用提供,但使用權(quán)歸開發(fā)者。 前不久有一個(gè)朋友問我,到底是做什么端的小程序比較好? 我只問了一句,你的產(chǎn)品里是否涉及錢和服務(wù),如果涉及這兩者,建議你選擇支付寶小程序。你可以通過其他小程序玩裂變,但如果你想做服務(wù)和商業(yè),一定要考慮支付寶...
閱讀 795·2021-11-24 09:38
閱讀 998·2021-11-11 11:01
閱讀 3236·2021-10-19 13:22
閱讀 1523·2021-09-22 15:23
閱讀 2827·2021-09-08 09:35
閱讀 2765·2019-08-29 11:31
閱讀 2119·2019-08-26 11:47
閱讀 1563·2019-08-26 11:44