今天這篇文章主要講微信和支付寶的離線付款碼的一種實現(xiàn)思路阀参。
付款碼就是我們出示給商家掃碼的一種碼乳幸,這種碼在首次初始化之后瞪讼,不用聯(lián)網(wǎng)也可以動態(tài)生成。
本文僅代表個人的一種實現(xiàn)原理的探索反惕,僅供參考尝艘,不代表實際支付寶的付款碼實現(xiàn)方案,也許支付寶的付款碼實現(xiàn)方案算法更加完美姿染,更加好背亥。
如果有更好的算法和想法,歡迎評論和我探討悬赏。
下面是摘自支付寶的付款碼功能說明:
離線使用
首次使用時狡汉,需要網(wǎng)絡(luò)才可以進行支付。之后無須網(wǎng)絡(luò)也可以支付付款安全
二維碼闽颇,條形碼每分鐘會自動更新盾戴,并會在生成之后短時間之內(nèi)有效。
從首次使用兵多,需要網(wǎng)絡(luò)這一點可以看出尖啡,支付寶客戶端肯定是向服務(wù)器請求了用來生成付款碼的秘鑰的。
下面是支付寶付款碼的數(shù)字
2816 7565 2589 992104
微信付款碼的數(shù)字
1345 7744 7121 375039
都是一樣的格式剩膘,前面三個四位數(shù)的數(shù)字加上后面一個6位數(shù)的數(shù)字
再看看一下付款碼的商家側(cè)的流程衅斩,詳細可以看微信支付的付款碼文檔
這里簡單描述一下流程就是
掃碼槍等商家的設(shè)備在獲取到用戶的付款碼之后,把付款碼發(fā)送到商戶后臺系統(tǒng)怠褐,商戶后臺系統(tǒng)再向微信支付系統(tǒng)發(fā)起支付請求畏梆,然后查詢支付結(jié)果。
這里有一點需要注意的是:和上一篇文章講的將軍令的六位數(shù)的動態(tài)密碼不一樣的是,將軍令是知道你的對應(yīng)的用戶信息的奠涌。但是商戶后臺在把付款碼發(fā)送到微信支付請求支付的時候宪巨,商戶后臺是不知道這個付款碼是哪個用戶的。因為掃碼設(shè)備溜畅,只是掃到了付款碼的數(shù)字捏卓,然后就發(fā)送到商戶后臺了,是不可能追蹤到時哪個用戶的付款am的慈格。所以可以肯定的是這18位的付款碼數(shù)字是包含了用戶信息的天吓。
所以這里和上一篇文章的6位動態(tài)密碼有很大區(qū)別,那就是這18位付款碼數(shù)字需要攜帶用戶的個人信息峦椰。
這樣子的話,生成18位付款碼需要的條件是:
- 每分鐘隨機生成
- 一旦截圖或者退出后臺汰规,付款碼需要重新生成
- 攜帶用戶的信息
- 必須是18位數(shù)字
- 付款碼是一次性使用的汤功,使用過的不能重新使用
- 和設(shè)備綁定
- 生成后的付款碼在一定時間內(nèi)是有效的,也就是說假設(shè)有效期是20秒溜哮,那么為了安全滔金,20秒前生成的付款碼就報廢了
所以如果要實現(xiàn)付款碼的功能,那么需要滿足上面的條件才可以茂嗓。
付款碼應(yīng)該有兩個部分餐茵,一個部分是需要解密的部分,另一個部分是純哈希
解密部分就是需要獲取到這個付款碼是屬于哪個用戶的述吸,純哈希指的就是將用戶設(shè)備的時間分鐘級別忿族,半分鐘級別加上用戶的設(shè)備識別碼,用戶的ip蝌矛,用戶的手機等信息道批,用戶的地址,等等一系列信息做一個哈希入撒。
然后服務(wù)器在根據(jù)解密的用戶信息隆豹,在數(shù)據(jù)庫里面查詢用戶的相關(guān)信息,同樣做一個哈希茅逮,如果能匹配的話璃赡,就能證明是這個用戶。
哈希這一點和上一篇文章一樣很好理解献雅,關(guān)鍵在于解密用戶信息碉考,同樣要支持動態(tài)生成。
用戶信息這個東西字段是很大的惩琉,像支付寶這種級別的應(yīng)用豆励,用戶超過好幾億,就算使用簡單的數(shù)字遞增算法,講過加密之后良蒸,加密的內(nèi)容也是比原文多的技扼。任何加密算法都是一樣的,密文肯定是比原文的字節(jié)數(shù)要多的嫩痰。否則的話剿吻,信息就要丟失,那就是哈希算法了串纺,而不是加密算法丽旅。
假設(shè)用戶的支付寶id是794850067,這里就有9位數(shù)了纺棺。9位數(shù)的話榄笙,意味著可以容納大約10億個id,放寬到10位數(shù)祷蝌,那么支付寶就可以標(biāo)記一個用戶了茅撞。往前填充位數(shù)為0。
因此假設(shè)的支付寶id就是0794 8500 67 一共10位數(shù)巨朦。
接下來就是哈希信息米丘,這個需要服務(wù)器和客戶端使用相同的哈希算法和加密算法。
讀者可以回到上一章節(jié)的信息糊啡,假設(shè)客戶端和服務(wù)端計算得到的哈希碼是676890拄查,注意這個哈希碼是和時間有關(guān)的。
假設(shè)當(dāng)前時間是1561648680(秒級別)棚蓄,也就是10位數(shù)堕扶。
那么支付寶id加上時間組成前面十位數(shù)。當(dāng)然支付寶肯定不會這么簡單把前面十位數(shù)表示成時間戳加上支付寶id
這個時間戳生成肯定是有動態(tài)算法混淆的癣疟,比如當(dāng)處于聯(lián)網(wǎng)的時候挣柬,可能就把十位數(shù)再加上一個固定的數(shù)字,這個數(shù)字是保存到支付寶客戶端的睛挚。
這樣的話邪蛔,支付寶id加上時間位數(shù),最多不超過12位數(shù)用來表示身份信息扎狱。
然后剩下的6位數(shù)用來存放上一篇文章講到的哈希密碼侧到。
這樣支付寶在獲取到付款碼的時候,先解開前面的12位信息淤击,獲取到用戶信息匠抗。再計算出對應(yīng)的動態(tài)哈希,這樣就可以驗證成功了污抬。
簡單表述一下:
alipay_id = 794850067
unix_time_id = 1561648688
dynamic_id = 156677889 # 這個額外id是我自己的一種設(shè)計汞贸,假想支付寶服務(wù)器和客戶端協(xié)商的绳军,每天生成不同序列的id,同步
hash_id = 66777888 # 這個hash id是客戶端計算用戶各種信息做一個匯總得出的哈希
final_id = str(alipay_id+unix_time_id+dynamic_id) + str(hash_id)
print(len(final_id))
所以動態(tài)生成變化的就是unix_time_id ,dynamic_id矢腻,hash_id
因為前面12位數(shù)是alipay_id+unix_time_id+dynamic_id這幾個相加的门驾,所以是會動態(tài)變化的。
后面的hashid也是會變化的多柑。
支付寶服務(wù)器收到付款碼之后奶是,可以用前面12位數(shù)減去動態(tài)id再減去時間id就可以得到用戶id
然后再根據(jù)用戶id計算hashid