iOS內購 服務端票據驗證及漏單引發的思考.

來源:互聯網
上載者:User

標籤:電訊廠商   帳號   記錄   一點   否則   es2017   blank   那是   機構   

因業務需要實現了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.伺服器對商品購買狀態以及商品類型,向用戶端發放相應的道具與推送資料更新通知

這七個步驟實際上是一個很安全的流程了。那問題出在哪裡呢?我們談談兩種蘋果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呢?
識別沙箱環境下收據的方法有兩種:

  1. 根據收據欄位 environment = sandbox。
  2. 根據收據驗證介面返回的狀態代碼。
    如果status=21007,則表示當前的收據為沙箱環境下收據, 進行驗證。
蘋果反饋的狀態代碼
  • 21000 App Store無法讀取你提供的JSON資料
  • 21002 收據資料不符合格式
  • 21003 收據無法被驗證
  • 21004 你提供的共用密鑰和賬戶的共用密鑰不一致
  • 21005 收據伺服器當前不可用
  • 21006 收據是有效,但訂閱服務已經到期。當收到這個資訊時,解碼後的收據資訊也包含在返回內容中
  • 21007 收據資訊是測試用(sandbox),但卻被發送到產品環境中驗證
  • 21008 收據資訊是產品環境中使用,但卻被發送到測試環境中驗證

 

By Hgq

iOS內購 服務端票據驗證及漏單引發的思考.

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.