iOS內購 - 服務端票據驗證及漏單引發的思考
因業務需要實現了APP內購處理,但在過程中出現了部分不可控的因素,導致部分使用者反映有充值不成並漏單的情況。
仔細考慮了幾個付費安全上的問題,凡是涉及到付費的問題都很敏感,任何一方出現損失都是不能接受的,所以在這裡整理一些支付安全的要點分享一下。
支付方式
IAP是指In-App Purchase, 是一種付費方式,而並不是蘋果專有的付費方式,在其它平臺上也會有不同的實現,這裡針對Apple IAP。
說到IAP安全問題,在蘋果的IAP流程中有一個比較明顯的邏輯漏洞,這個邏輯漏洞是建立在我們處理不當的情況下發生的,會導致己方提供的服務和使用者之間出現問題。先看看IAP支付時序圖:
支付流程
1.客戶端向Appstore請求購買產品(假設產品資訊已經取得),Appstore驗證產品成功後,從使用者的Apple賬戶餘額中扣費。
2.Appstore向客戶端返回一段receipt-data,裡面記錄了本次交易的證書和簽名資訊。
3.客戶端向我們可以信任的伺服器提供receipt-data
4.伺服器對receipt-data進行一次base64編碼
5.把編碼後的receipt-data發往itunes.appstore進行驗證
6.itunes.appstore返回驗證結果給伺服器
7.伺服器對商品購買狀態以及商品型別,向客戶端發放相應的道具與推送資料更新通知
8.客戶端收到伺服器的處理狀態,進行相應的結單處理
這八個步驟實際上是一個很安全的流程了。那問題出在哪裡呢?我們談談兩種蘋果IAP的驗證模型。
驗證方式
1.IAP built-in Model,本地驗證
有些APP甚至是網遊,都直接跳過了3~7步驟,在第2步拿到receipt-data之後,直接由客戶端向itunes.appstore傳送驗證請求,並且拿到結果,根據結果修改資料。
我們在設計APP的時候都遵循一個真理,“凡是在客戶端的資料都是不安全的”,深以為然。如果沒有獨立伺服器輔助驗證,這樣也就避免不了資料被修改的事實了,是的,你會少賺錢。
不過如果APP也不通過獨立伺服器驗證,而是在客戶端驗證之後再告知伺服器狀態讓其發放遊戲道具,那就太可怕了點。這是IAP built-in Model
那是不是就完全不能讓這個過程變得安全了呢?也不是,但這個安全保障只是讓修改變得困難而已。蘋果官方提供了 Validating Receipts Locally 在客戶端對receipt-data進行安全驗證,主要是對證書以及簽名的合法性驗證。如果不想自己寫程式碼驗證,也可以藉助第三方機構提供的receipt-data驗證API,比較著名的有 urbanairship和 beeblex 。
但如果能偽造一個完全合法的receipt-data,是不是一樣可以達到欺騙目的。是的,為了繞過Validating Locally,於是黑客開始用自己偽造的receipt-data進行移花接木,所以出現了可以偽造”合法訂單”的 in-appstore 。因此這種本地加強驗證的方法也不能完全避免IAP攻擊。
2.IAP Server Model,伺服器驗證
而如果我們把驗證邏輯移到伺服器上,這個過程就變得容易多了。因為不再需要擔心receipt-data被偽造的問題。不過就算把步驟4~7在伺服器上做了,同樣也會產生一些幼稚的邏輯漏洞:
對驗證receipt-data的reponse content不進行驗證和記錄,只根據Product直接發放商品。這樣只要客戶端不斷提交receipt-data,按照正常邏輯你就需要不斷驗證並且重複發放商品。較為安全的做法是:
在每一次收到receipt-data之後,都把提交的使用者賬號以及receipt-data中的單號建立對映並記錄下來,在每次驗證receipt-data時,先判斷其是否已經存在。
只要做了這樣的驗證,整個支付流程都變得明朗起來。
確保receipt-data的成功提交與異常處理
建立在IAP Server Model的基礎上,並且我們知道手機網路是不穩定的,在付款成功後不能確保把receipt-data一定提交到伺服器。如果出現了這樣的情況,那就意味著使用者被appstore扣費了,卻沒收到伺服器發放的道具。(這樣就引發了漏單)
解決這個問題的方法是在客戶端提交receipt-data給我們的伺服器,讓我們的伺服器向蘋果伺服器傳送驗證請求,驗證這個receipt-data賬單的有效性. 在沒有收到回覆之前,客戶端必須要把receipt-data儲存好,並且定期或在合理的UI介面觸發向服務端發起請求,直至收到服務端的回覆後刪除客戶端的receipt賬單記錄。
如果是客戶端沒成功提交receipt-data,那怎麼辦?就是使用者被扣費了,也收到appstore的消費收據了,卻依然沒收到道具,於是投訴到客服處。
這種情況在以往的經驗中也會出現,常見的使用者和運營商發生的糾紛。客服向使用者索要賬號和appstore的收據單號,通過查詢itunes-connect看是否確有這筆訂單。
如果訂單存在,則要聯絡研發方去查詢伺服器,看訂單號與使用者名稱是否對應,並且是否已經被使用了,做這一點檢查的目的是 為了防止惡意使用者利用已經使用過了的訂單號進行欺騙(已驗證的賬單是可以再次請求驗證的,曾經為了測試,將賬單手動發給伺服器處理併成功),謊稱自己沒收到商品。
當然了,如果查不到這個訂單號,就意味著這個訂單確實還沒使用過,手動給使用者補發商品即可。
有朋友問怎麼通過itunes-connect檢視具體訂單,itunes-connect中無法直接看到訂單資訊,可以用以下方法來查詢
1.可以通過賬單向蘋果傳送賬單驗證,有效可以手動補發
2.用自己的伺服器的記錄賬單列表對比
3.利用第三方的TalkingData等交易函式,會自動記錄賬單資料
建議
為保證稽核的通過,需要在客戶端或server進行雙重驗證,即,先以線上交易驗證地址進行驗證,如果蘋果正式驗證伺服器的返回驗證碼code為21007,則再一次連線沙盒測試伺服器進行驗證即可。
在應用提審時,蘋果IAP提審驗證時是在沙盒環境的進行的,即:蘋果在稽核App時,只會在sandbox環境購買,其產生的購買憑證,也只能連線蘋果的測試驗證伺服器,如果沒有做雙驗證,需要特別注意此問題,否則會被拒。
其他
在sandbox中驗證receipt:https://sandbox.itunes.apple.com/verifyReceipt
在生產環境中驗證receipt:https://buy.itunes.apple.com/verifyReceipt
那麼如何自動的識別收據是否是sandbox receipt呢?
識別沙盒環境下收據的方法有兩種:
- 根據收據欄位 environment = sandbox。
- 根據收據驗證介面返回的狀態碼。
如果status=21007,則表示當前的收據為沙盒環境下收據, 進行驗證。
蘋果反饋的狀態碼
- 21000 App Store無法讀取你提供的JSON資料
- 21002 收據資料不符合格式
- 21003 收據無法被驗證
- 21004 你提供的共享金鑰和賬戶的共享金鑰不一致
- 21005 收據伺服器當前不可用
- 21006 收據是有效的,但訂閱服務已經過期。當收到這個資訊時,解碼後的收據資訊也包含在返回內容中
- 21007 收據資訊是測試用(sandbox),但卻被髮送到產品環境中驗證
- 21008 收據資訊是產品環境中使用,但卻被髮送到測試環境中驗證
相關文章
- PHP (Laravel) 實現 iOS 內購服務端驗證PHPLaraveliOS服務端
- IOS內購驗證iOS
- Java財政票據查驗介面、醫療票據查驗、發票驗真介面Java
- Oracle服務端驗證機制Oracle服務端
- SMSSDK驗證碼服務端校驗介面服務端
- 訂單服務的設計思考
- 思考:如何保證服務穩定性?
- 蘋果遠端裝置管理服務DEP含有驗證缺陷蘋果
- 用fluent-validator,進行Java服務端驗證Java服務端
- jwt驗證的思考JWT
- 簡單票據檢測方法
- 極驗高併發驗證服務背後的技術實現
- MVC驗證10-到底用哪種方式實現客戶端服務端雙重非同步驗證MVC客戶端服務端非同步
- 如何使用ssh_scan遠端驗證SSH服務的配置和策略
- JavaScript 表單及表單驗證JavaScript
- ZooKeeper服務發現客戶端--重連認證客戶端
- 服務端常見服務安裝及配置服務端
- 驗證碼服務釋出上線
- SpringBoot 實戰 (十五) | 服務端引數校驗之一Spring Boot服務端
- 遠端終端服務的簡單實現
- iOS 微信支付(服務端下單)iOS服務端
- 深圳哪裡有開具住宿電子發票-開票服務大廳-深圳百度經驗
- 上海哪裡有開具住宿電子發票-開票服務大廳-上海百度經驗
- 北京哪裡有開具住宿電子發票-開票服務大廳-北京百度經驗
- 天津哪裡有開具住宿電子發票-開票服務大廳-天津百度經驗
- 成都哪裡有開具住宿電子發票-開票服務大廳-成都百度經驗
- 杭州哪裡有開具住宿電子發票-開票服務大廳-杭州百度經驗
- 蘋果內購二次驗證 PHP程式碼蘋果PHP
- Netty服務端開發及效能最佳化Netty服務端
- netty建立聊天室服務端及單機併發測試結果Netty服務端
- 一次簡單的驗證碼識別以及思考
- Flutter 全棧開發體驗——爬蟲與服務端Flutter全棧爬蟲服務端
- 西安哪裡有開具住宿費電子發票-開票服務大廳-西安百度經驗
- 武漢哪裡有開具住宿費電子發票-開票服務大廳-武漢百度經驗
- 合肥哪裡有開具住宿費電子發票-開票服務大廳-合肥百度經驗
- 南昌哪裡有開具住宿費電子發票-開票服務大廳-南昌百度經驗
- 河源哪裡有開具住宿費電子發票-開票服務大廳-河源百度經驗
- for...in引發的思考