我們在商場買東西一碼付二維碼,下單生成的訂單號,使用到的優惠券碼,聯合商品兌換券碼,這些是在網上購物經常使用到的單號,那么為什么有些單號那么長,有些只有幾位數?有些單號一看就知道年月日的信息,有些卻看不出任何意義?下面展開分析下訂單系統中不同場景的id服務的具體實現。
## **1、一碼付**
我們常見的一碼付,指的是一個二維碼可以使用支付寶或者微信進行掃碼支付。
二維碼的本質是一個字符串。聚合碼的本質就是一個鏈接地址。用戶使用支付寶微信直接掃一個碼付錢,不用擔心拿支付寶掃了微信的收款碼或者用微信掃了支付寶的收款碼,這極大減少了用戶掃碼支付的時間。
實現原理是當客戶用APP掃碼后,網站后臺就會判斷客戶的掃碼環境。(微信、支付寶、QQ錢包、京東支付、云閃付等)。
判斷掃碼環境的原理就是根據打開鏈接瀏覽器的 HTTP header。任何瀏覽器打開http鏈接時,請求的header都會有User-Agent(UA、用戶代理)信息。
UA是一個特殊字符串頭,服務器依次可以識別出客戶使用的操作系統及版本、CPU 類型、瀏覽器及版本、瀏覽器渲染引擎、瀏覽器語言、瀏覽器插件等很多信息。
各渠道對應支付產品的名稱不一樣,一定要仔細看各支付產品的API介紹。
1. 微信支付:JSAPI支付支付
2. 支付寶:手機網站支付
3. QQ錢包:公眾號支付
其本質均為在APP內置瀏覽器中實現HTML5支付。

在這個思路上優化迭代,動態生成一碼付的二維碼 可以預先綁定用戶所選的商品信息和價格,根據用戶所選的商品動態更新。
這樣不僅支持一碼多平臺調起支付,而且不用用戶選擇商品輸入金額,即可完成訂單支付的功能,很絲滑。
用戶在真正掃碼后,服務端才通過前端獲取用戶UID,結合二維碼綁定的商品信息,真正的生成訂單,發送支付信息到第三方(qq、微信、支付寶),第三方生成支付訂單推給用戶設備,從而調起支付。
區別于固定的一碼付,在實際應用中,使用到了動態二維碼,二維碼本質是一個短網址,ID服務提供短網址的唯一標志參數。唯一的短網址映射的ID綁定了商品的訂單信息,技術和業務的深度結合,縮短了支付流程,提升用戶的支付體驗。
## **2、訂單號**
訂單號在實際的業務過程中作為一個訂單的唯一標識碼存在,一般實現以下業務場景:
1. 用戶訂單遇到問題,需要找客服進行協助;
2. 對訂單進行操作,如線下收款,訂單核銷;
3. 下單,改單,成單,退單,售后等系統內部的訂單流程處理和跟進。
很多時候搜索訂單相關信息的時候都是以訂單ID作為唯一標識符,這是由于訂單號的生成規則的唯一性決定的。從技術角度看,除了ID服務必要的特性之外,在訂單號的設計上需要體現幾個特性:
**(1)信息安全**
編號不能透露公司的運營情況,比如日銷、公司流水號等信息,以及商業信息和用戶手機號,身份證等隱私信息。并且不能有明顯的整體規律(可以有局部規律),任意修改一個字符就能查詢到另一個訂單信息,這也是不允許的。
類比于我們高考時候的考生編號的生成規則,一定不能是連號的,否則只需要根據順序往下查詢就能搜索到別的考生的成績,這是絕對不可允許。
**(****2)部分可讀**
位數要便于操作,因此要求訂單號的位數適中,且局部有規律。這樣可以方便在訂單異常,或者退貨時客服查詢。
過長的訂單號或易讀性差的訂單號會導致客服輸入困難且易錯率較高,影響用戶體驗的售后體驗。因此在實際的業務場景中,訂單號的設計通常都會適當攜帶一些允許公開的對使用場景有幫助的信息,如時間,星期,類型等等,這個主要根據所涉及的編號對應的使用場景來。
而且像時間、星期這些自增長的屬于作為訂單號的設計的一部分元素,有助于解決業務累積而導致的訂單號重復的問題。
**(3)查詢效率**
常見的電商平臺訂單號大多是純數字組成,兼具可讀性的同時,int類型相對varchar類型的查詢效率更高,對在線業務更加友好。
## **3、優惠券和兌換券**
優惠券、兌換券是運營推廣最常用的促銷工具之一,合理使用它們,可以讓買家得到實惠,商家提升商品銷量。常見場景有:
1. 在購買【騰訊視頻VIP+QQ音樂年卡】聯合商品,支付成功后會得到QQ音樂年卡的兌換碼,可以去QQ音樂App兌換音樂會員年卡;
2. 疫情期間,部分地方政府發放的消費券;
3. 瓶裝飲料經常會出現輸入優惠編碼兌換獎品。

從技術角度看,有些場景適合ID即時生成,比如電商平臺購物領取的優惠券,只需要在用戶領取時分配優惠券信息即可。有些線上線下結合的場景,比如疫情優惠券,瓶蓋開獎,京東卡,超市卡這種,則需要預先生成,預先生成的券碼具備以下特性:
1.預先生成,在活動正式開始前提供出來進行活動預熱;
2.優惠券體量大,以萬為單位,通常在10萬級別以上;
3.不可破解、仿制券碼;
4.支持用后核銷;
5.優惠券、兌換券屬于廣撒網的策略,所以利用率低,也就不適合使用數據。
**庫進行存儲(占空間,有效的數據有少)**
設計思路上,需要設計一種有效的兌換碼生成策略,支持預先生成,支持校驗,內容簡潔,生成的兌換碼都具有唯一性,那么這種策略就是一種特殊的編解碼策略,按照約定的編解碼規則支撐上述需求。
既然是一種編解碼規則,那么需要約定編碼空間(也就是用戶看到的組成兌換碼的字符),編碼空間由字符a-z,A-Z,數字0-9組成,為了增強兌換碼的可識別度,剔除大寫字母O以及I,可用字符如下所示,共60個字符:
abcdefghijklmnopqrstuvwxyzABCDEFGHJKLMNPQRSTUVWXZY0123456789?
之前說過,兌換碼要求近可能簡潔,那么設計時就需要考慮兌換碼的字符數,假設上限為12位,而字符空間有60位,那么可以表示的空間范圍為60^12=130606940160000000000000(也就是可以12位的兌換碼可以生成天量,應該夠運營同學揮霍了),轉換成2進制:1001000100000000101110011001101101110011000000000000000000000(61位)
**兌換碼組成成分分析**
兌換碼可以預先生成,并且不需要額外的存儲空間保存這些信息,每一個優惠方案都有獨立的一組兌換碼(指運營同學組織的每一場運營活動都有不同的兌換碼,不能混合使用, 例如雙11兌換碼不能使用在雙12活動上),每個兌換碼有自己的編號,防止重復,為了保證兌換碼的有效性,對兌換碼的數據需要進行校驗,當前兌換碼的數據組成如下所示:
優惠方案ID + 兌換碼序列號i + 校驗碼
**編碼方案**
1. 兌換碼序列號i,代表當前兌換碼是當前活動中第i個兌換碼,兌換碼序列號的空間范圍決定了優惠活動可以發行的兌換碼數目,當前采用30位bit位表示,可表示范圍:1073741824(10億個券碼)。
2. 優惠方案ID, 代表當前優惠方案的ID號,優惠方案的空間范圍決定了可以組織的優惠活動次數,當前采用15位表示,可以表示范圍:32768(考慮到運營活動的頻率,以及ID的初始值10000,15位足夠,365天每天有運營活動,可以使用54年)。
3. 校驗碼,校驗兌換碼是否有效,主要為了快捷的校驗兌換碼信息的是否正確,其次可以起到填充數據的目的,增強數據的散列性,使用13位表示校驗位,其中分為兩部分,前6位和后7位。
深耕業務還會有區分通用券和單獨券的情況,分別具備以下特點,技術實現需要因地制宜地思考。
1. 通用券:多個玩家都可以輸入兌換,然后有總量限制,期限限制。
2. 單獨券:運營同學可以在后臺設置兌換碼的獎勵物品、期限、個數,然后由后臺生成兌換碼的列表,兌換之后核銷。