- 原文地址:Implementing linkedPurchaseToken correctly to prevent duplicate subscriptions
- 原文做者:Emilie Roberts
- 譯文出自:掘金翻譯計劃
- 本文永久連接:github.com/xitu/gold-m…
- 譯者:yuwhuawang
- 校對者:zx-Zhu
你是否在使用 Google Play 的訂閱功能?要確保你的後端服務實現的方式是正確的。前端
訂閱 REST APIs 是管理用戶訂閱的真實可信來源。Purchases.subscriptions API 的返回包括一個很是重要的字段叫作 linkedPurchaseToken。 恰當的處理這個字段,對於保證正確的用戶可以訪問你的內容是很是重要的。android
就像 訂閱文檔 裏指出的, 每一筆新的 Google Play 的購買流程 —— 初始化購買、升級和降級還有 從新註冊¹ —— 都會產生一個新的購買令牌。而 linkedPurchaseToken 字段則能夠用來識別屬於同一個訂閱的多個購買令牌。ios
打個比方,一個用戶購買了一個訂閱而且收到一個購買令牌 A。linkedPurchaseToken 字段(灰色圓圈)在 API 的返回裏沒有值,由於這個購買令牌屬於一個全新的訂閱。git
若是用戶升級了他們的訂閱,一個新的購買令牌 B 產生了。既然這個升級替代了購買令牌 A 表明的訂閱,令牌 B 的 linkedPurchaseToken 字段(灰色圓圈顯示的)將會指向令牌 A。注意它按照時間的逆序指向原始的購買令牌。github
購買令牌 B 將會是惟一被更新的令牌。購買令牌 A 不該該用來受權用戶獲取你的內容。算法
注意: 更新訂閱時,若是你查詢 Google Play 的訂單服務器,購買令牌 A 和 B 都會是激活的。咱們會在 下一節 裏討論這個問題。數據庫
如今,讓咱們假設一個另外一個用戶執行了如下操做:訂閱、升級和降級。原始的訂閱會建立購買令牌 C,升級操做會建立購買令牌 D,降級操做會建立購買令牌 E。每個令牌都會按照時間的逆序指向前一個令牌。apache
讓咱們在這個例子里加上第三個用戶。這個用戶一直在改變主意。在初始化訂閱以後,用戶又一連三次取消了訂閱而後從新訂閱(從新訂閱)。初始化訂閱建立了購買令牌 F,從新訂閱建立了 G、H 和 I。購買令牌 I 是最近的令牌。後端
最近的令牌 B、E 和 I 分別表明了用戶 一、二、3 的最終受權和付帳的訂閱。只有這些最近的令牌纔有相應的權利。然而對於 Google Play 來說,若是初始的過時時間還沒到,全部的令牌都是「有效的」。api
也就是說,若是你經過 獲取訂閱 API 來查詢這些令牌,包括上面的圖表內的 A, D, F, G和H,你會獲得 訂閱資源響應 ,響應裏代表訂閱尚未過時而且付款已經收到,即使如此你也只應該根據最近的令牌來受權。
第一眼看上去很奇怪:爲何最初的令牌仍是在被更新後仍是有效的?簡單來講是這樣實現能讓開發者更靈活地提供內容和服務,也讓 Google 更好的保護用戶隱私。然而這也確實須要你在後端服務器上進行重點記錄
每次當你確認一個訂閱,你的後臺服務都應該檢查 linkedPurchaseToken 字段有沒有被設定。若是已經被設定,該字段的值就表明着前一個被替換的令牌。你應該馬上把前一個令牌標記爲失效,這樣用戶就不能使用這個令牌訪問你的內容。
咱們再來看看上面例子裏的用戶 1, 當後端服務器收到了表明初始購買的憑證 A,該憑證 A 的 linkedPurchaseToken 字段爲空,這時應根據憑證進行受權。接下來,當後端服務器接收到更新後新的購買憑證 B,服務器會檢查 linkedPurchaseToken 字段,發現它被設置爲令牌 A,因而就禁掉令牌 A 的受權。
這樣的話,後端數據庫老是保存有效權限的購買憑證。以用戶 3 的例子來講,數據庫的狀態變化應該以下圖:
檢查 linkedPurchaseToken 的僞代碼:
你能夠在一個開源的,端對端訂閱的應用 優雅出租車 的後臺 Firebase 上看一些例子,特別是看 disableReplacedSubscription 方法,它在 PurchasesManager.ts 裏。
如今你的後端應該和最新的,接連到來的購買令牌保持同步,你會檢查每個購買的 linkedPurchaseToken 字段,而且每個對應着被替換訂閱的令牌,都被正確的禁用了。這太棒了!
可是若是你有一個已有的訂閱數據的數據庫,而且沒有根據 linkedPurchaseToken 字段來調整?你須要在這個數據庫上跑一個一次性的清理算法。
在不少狀況下清理數據庫中最重要的工做就是,一個令牌是否被可以受權相應的內容和服務。也就是說:並不須要對每個訂閱從新建立升級/降級/從新訂閱的購買歷史,而只須要肯定每一個令牌正確的受權狀況。一次性的數據庫清理任務就能夠把訂閱狀態整理清楚。接下來,新到來的訂閱就須要像上一節中描述的那樣處理。
想象一下上面三個用戶的購買憑證都存在數據庫裏。這些購買可能出如今任什麼時候間,順序也不同。若是清理功能正確處理的話,令牌 B、E 和 I 最終會被標記爲有效受權,而其餘的令牌則會被禁用。
對數據庫進行一次遍歷,並檢查每一項。若是 linkedPurchaseToken 字段被設置,就把這個字段包括的字段禁用。根據下面的圖表,咱們從上到下移動:
元素 A:linkedPurchaseToken 沒有被設定,移至下一項 元素 D:linkedPurchaseToken == C,禁用 C 元素 G:linkedPurchaseToken == F,禁用 F 元素 E:linkedPurchaseToken == D,禁用 D 元素 F:linkedPurchaseToken 沒有被設定,移至下一項 等等。
清理現有數據庫的僞代碼:
執行完一次性的清理以後,全部的舊令牌都會被禁用,你的數據庫也就準備好了。
如今你已經理解 linkedPurchaseToken 字段是怎麼工做的,確保在你的後端正確的處理它。每個有訂閱功能的應用都應該檢查這個字段。正確的追蹤受權對於保證正確的用戶,在正確的時間,被授予了正確的權利這一點來講,很是關鍵。
¹從新註冊 是指當一個用戶訂閱,而後取消訂閱,接着又在初始的訂閱過時以前從新訂閱。儘管用戶不會丟失受權,新的訂閱也和以前的同樣,他們仍是會經歷另外一個付款流程,由於他們承諾了將來的付款。他們會收到新的購買令牌而且 linkedPurchaseToken 字段會在升級或者降級的時候被設置。
本文全部的代碼都遵循 Apache 2.0 許可。本文不包括 Google 正式產品任何部分,而且只是爲了參考使用。
若是發現譯文存在錯誤或其餘須要改進的地方,歡迎到 掘金翻譯計劃 對譯文進行修改並 PR,也可得到相應獎勵積分。文章開頭的 本文永久連接 即爲本文在 GitHub 上的 MarkDown 連接。
掘金翻譯計劃 是一個翻譯優質互聯網技術文章的社區,文章來源爲 掘金 上的英文分享文章。內容覆蓋 Android、iOS、前端、後端、區塊鏈、產品、設計、人工智能等領域,想要查看更多優質譯文請持續關注 掘金翻譯計劃、官方微博、知乎專欄。