iOS內購遇到刷單問題

問題描述

	最近公司發現公司發現有人通過蘋果內購充值,實際上蘋果後臺查詢充值記錄並沒有相關記錄,初步判斷可能內購流程出現了問題進行排查。

蘋果內購流程圖

IOS SDKSDK SERVEAPPLE 服務1、創建訂單2、返回訂單號支付第一步生下單3、發起支付4、返回支付結果支付第二步 支付5、訂單號、蘋果返回receipt-data6、驗證支付結果7、返回驗證結果8、返回最終支付結果支付第三步完成支付IOS SDKSDK SERVEAPPLE 服務

通用流程梳理

  1. IOS SDK 請求服務器,創建訂單;
  2. 服務器生成訂單,並返回訂單號;
  3. 發起支付,如果沒有登陸會要求用戶登陸appleID,如果已經登陸,會彈出購買確認;
  4. 點擊購買,等待蘋果返回支付結果;
  5. 如果支付成功,蘋果會返回receipt-data 數據,與訂單號一起發到服務器進行校驗;
  6. 接收到IOS SDK參數進行校驗,成功後請求APPLE 服務校驗支付結果;
  7. 驗證返回結果返回進行業務操作,並返回IOS SDK最終支付結果;

問題原因

	蘋果服務器再返回給我們服務器訂單結果。receipt_data 在越獄環境下是可以被插件僞造的,後臺向蘋果驗證時,居然還能驗證通過。下面是幾種receipt_data 請求APPLE 服務器返回的結果
正常返回JSON格式爲:

第一種

{
    "status": 0, 
    "environment": "Sandbox", 
    "receipt": {
        "receipt_type": "ProductionSandbox", 
        "adam_id": 0, 
        "app_item_id": 0, 
        "bundle_id": "com.xxx.xxx", 
        "application_version": "84", 
        "download_id": 0, 
        "version_external_identifier": 0, 
        "receipt_creation_date": "2016-12-05 08:41:57 Etc/GMT", 
        "receipt_creation_date_ms": "1480927317000", 
        "receipt_creation_date_pst": "2016-12-05 00:41:57 America/Los_Angeles", 
        "request_date": "2016-12-05 08:41:59 Etc/GMT", 
        "request_date_ms": "1480927319441", 
        "request_date_pst": "2016-12-05 00:41:59 America/Los_Angeles", 
        "original_purchase_date": "2013-08-01 07:00:00 Etc/GMT", 
        "original_purchase_date_ms": "1375340400000", 
        "original_purchase_date_pst": "2013-08-01 00:00:00 America/Los_Angeles", 
        "original_application_version": "1.0", 
        "in_app": [
            {
                "quantity": "1", 
                "product_id": "*******【支付定義產品ID】*******", 
                "transaction_id": "10000003970", 
                "original_transaction_id": "10000003970", 
                "purchase_date": "2016-12-05 08:41:57 Etc/GMT", 
                "purchase_date_ms": "1480927317000", 
                "purchase_date_pst": "2016-12-05 00:41:57 America/Los_Angeles", 
                "original_purchase_date": "2016-12-05 08:41:57 Etc/GMT", 
                "original_purchase_date_ms": "1480927317000", 
                "original_purchase_date_pst": "2016-12-05 00:41:57 America/Los_Angeles", 
                "is_trial_period": "false"
            }
        ]
    }
}
	這裏邊in_app 可能會出現多條數據情況,每當有一筆交易發起的時候,in_app裏就會添加收據的一些信息。這些信息會一直保存直到你結束這筆交易。在此之後,下次更新收據時會將其從收據中刪除 - 例如,當用戶再次購買時,或者您的應用明確刷新收據時。
	非消耗型項目,自動續期訂閱,非續期訂閱或免費訂閱的應用內購買收據將無限期保留在收據中。

第二種

{
    "receipt": {
        "original_purchase_date_pst": "2016-12-03 01:11:01 America/Los_Angeles", 
        "purchase_date_ms": "1480756261254", 
        "unique_identifier": "96f51b28f628493709966f33a1fe7ba", 
        "original_transaction_id": "1000000255766", 
        "bvrs": "82", 
        "transaction_id": "1000000255766", 
        "quantity": "1", 
        "unique_vendor_identifier": "FE358-1362-40FD-870F-DF788AC5", 
        "item_id": "11822945", 
        "product_id": ""*******【支付定義產品ID】*******"", 
        "purchase_date": "2016-12-03 09:11:01 Etc/GMT", 
        "original_purchase_date": "2016-12-03 09:11:01 Etc/GMT", 
        "purchase_date_pst": "2016-12-03 01:11:01 America/Los_Angeles", 
        "bid": "com.xxx.xxx", 
        "original_purchase_date_ms": "1480756261254"
    }, 
    "status": 0
}
	查看資料說是在IOS7以前版本支付和現在版本支付驗證返回不用的數據結構。
越獄訂單receipt_data向蘋果服務器校驗後如下:
{
    "status": 0, 
    "environment": "Production", 
    "receipt": {
        "receipt_type": "Production", 
        "adam_id": 1377028992, 
        "app_item_id": 1377028992, 
        "bundle_id": "com.xxx.xxx", 
        "application_version": "3", 
        "download_id": 80042231041057, 
        "version_external_identifier": 827853261, 
        "receipt_creation_date": "2018-07-23 07:30:45 Etc/GMT", 
        "receipt_creation_date_ms": "1532331045000", 
        "receipt_creation_date_pst": "2018-07-23 00:30:45 America/Los_Angeles", 
        "request_date": "2018-07-23 07:33:54 Etc/GMT", 
        "request_date_ms": "1532331234485", 
        "request_date_pst": "2018-07-23 00:33:54 America/Los_Angeles", 
        "original_purchase_date": "2018-07-01 12:16:21 Etc/GMT", 
        "original_purchase_date_ms": "1530447381000", 
        "original_purchase_date_pst": "2018-07-01 05:16:21 America/Los_Angeles", 
        "original_application_version": "3", 
        "in_app": [ ]
    }
}

解決方法

將校驗邏輯進行修改,不能只校驗status=0

  • 首先客戶端傳參數需要增加:product_id,transaction_id
//該方法爲監聽內購交易結果的回調
- (void)paymentQueue:(SKPaymentQueue *)queue updatedTransactions:(NSArray<SKPaymentTransaction *> *)transactions
transactions 爲一個數組 遍歷就可以得到 SKPaymentTransaction 對象的元素transaction。然後從transaction裏可以取到以下這兩個個參數,product_id,transaction_id。另外從沙盒裏取到票據信息receipt_data 
我們先看怎麼取到以上的三個參數
//獲取receipt_data
NSData *data = [NSData dataWithContentsOfFile:[[[NSBundle mainBundle] appStoreReceiptURL] path]];
NSString * receipt_data = [data base64EncodedStringWithOptions:0];
//獲取product_id
NSString *product_id = transaction.payment.productIdentifier;
//獲取transaction_id
NSString * transaction_id = transaction.transactionIdentifier;
這是我們必須要傳給服務器的三個字段。以上三個字段需要做好空值校驗,避免崩潰。
下面我們來解釋一下,爲什麼要給服務器傳這三個參數。
receipt_data:這個不解釋了 大家都懂 不傳的話 服務器根本沒法校驗
product_id:這個也不用解釋 內購產品編號 你不傳的話 服務器不知道你買的哪個訂單
transaction_id:這個是交易編號,是必須要傳的。因爲你要是防止越獄下內購被破解就必須要校驗in_app這個參數。而這個參數的數組元素有可能爲多個,你必須得找到一個唯一標示,纔可以區分訂單到底是那一筆。
  • 服務器邏輯修改
    • 先判斷是否重複分發內購產品。收到客戶端上報的transaction_id 後,直接MD5後去數據庫查,能查到說明是重複訂單,返回相應錯誤碼給客戶端,查不到去蘋果那邊校驗。
      沙箱校驗地址 = “https://sandbox.itunes.apple.com/verifyReceipt”;
      正式校驗地址 = “https://buy.itunes.apple.com/verifyReceipt”;
    • 服務器拿到蘋果校驗結果,首先判斷訂單狀態是否成功。
    • 如果訂單成功在判斷格式爲IOS7 之前還是之後。
      • 如果爲IOS7 之前版本直接判斷transaction_id、product_id;
      • 如果爲IOS7 之後判斷in_app 是否有值,如果沒有直接返回失敗,如果存在遍歷查詢對應transaction_id並比較product_id;
    • 以上校驗都正確就可以把訂單充值進去,給用戶分發內購產品。

注:後臺傳入參數一定要進行存儲。

解析

蘋果IAP官方文檔

蘋果文檔上介紹in_app參數內容截圖
在這裏插入圖片描述
說明:in_app參數可能爲空,如果爲空得話,也需要將這筆交易認爲是有效的交易。當然我們肯定不能這麼幹,這個參數是必須必須要校驗的,不然越獄環境下,分分鐘就把你內購破解了。我去校驗了很多正常用戶的內購訂單,沒發現一個in_app參數是爲空的。但爲了保險,還是讓後臺把所有前端傳的receipt_data等參數不管成功失敗都保存下來,萬一哪個用戶因此投訴充值不到賬,我們有據可查。

參考:https://www.jianshu.com/p/5cf686e92924
參考:https://www.jianshu.com/p/7e7c3a918946utm_campaign=hugo&utm_medium=reader_share&utm_content=note&utm_source=qq

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章