前端iOS完成對應的商品購買之后,會得到一個Transaction(交易)的數據結構指針,后端實際上只需要這個結構內的一個東西,那就是 transaction.transactionReceipt。
前端將它進行Base64編碼之后,再請求后端的HTTP接口就行了,我這里着重講一下后端需要做的一些事情。
首先,拿到這個Base64的字符串之后,不用任何修改,只需要將它原封不動的請求給蘋果的驗證接口就行了,下面是一個HTTP請求構造信息:
請求地址:
測試:https://sandbox.itunes.apple.com/verifyReceipt
正式:https://buy.itunes.apple.com/verifyReceipt
請求方式:
HTTP POST
Header:
Content-Type: application/json
請求的Body:
{
"receipt-data":"...接收到的Base64字符串..."
}
返回的響應信息(刪減版):
{
"status": 0
"receipt": {
"bundle_id": "iOS應用標識,需要做校驗。",
"in_app": [
{
"transaction_id": "1000000XXXXXXXXX(未結束的交易ID)",
"product_id": "xxxxxxx(購買的產品ID,用於映射到底買了哪些東西)"
},
...more...
]
}
}
Q/A問答
Q1:我該請求哪一個地址呢?
A1:如果不想設置什么狀態標識,簡單點不管三七二十一,直接請求正式版本的地址,如果在測試環境,返回給你的數據的status字段會為21007,只要檢查這個值再次請求測試版本的鏈接即可。
Q2:我如何得到購買的產品信息呢?
A2:注意返回數據的receipt.in_app是一個數組,里面保存了所有未結束的交易,每一筆交易內,都會有一個product_id用於自行映射相關的產品信息,這個信息的獲取不用我說了吧,你想放到哪里都可以。
Q3:如何防止重復的交易造成多次購買呢?比如客戶端使用一個Base64的參數請求了多次?
A3:注意返回數據的receipt.in_app是一個數組,里面保存了所有未結束的交易,每一筆交易內,都會有一個transaction_id用以唯一標識這個交易。我們可以在我們自己的數據庫內將這個字段設置為唯一索引,這樣的話,當你重復插入相同的transaction_id的時候,會觸發異常,只要根據這個異常進行數據回滾或者簡單的忽略掉這個交易就行了。
Q4:后端因當返回什么樣的數據給前端,讓前端結束交易呢?否則的話,recetpt.in_app這個數組內的值將會無限制累加?
A4:因為receipt.in_app里面保存了不止一筆交易,因此當后端循環這個數據處理完畢之后,應當將處理之后的transaction_id進行收集,然后以列表的形式返回給前端,前端收到這個數據之后,傳遞給SDK,然后結束交易即可。需要注意的是,哪怕有一筆交易在我們的數據庫中是重復的,也要將這個重復的transaction_id一起返回給前端,好讓前端能夠結束掉這筆交易,否則的話將會一直存在,不停的處理這個case。
Q5:如何處理漏單的情況?比如前端支付完畢之后,因為網絡或者其他原因沒有請求后端進行處理。
A5:雖然我不是前端,看了一下蘋果的文檔之后發現,只要在應用啟動時監聽支付Queue,蘋果會調用你的處理函數,再次進行處理,因為存在可能漏單的情況,因此后端的接口一定要具備冪等(防重,可多次調用)。重復的校驗上面A3已經回答了。需要注意的是,不止是后端可能會沒有接收到來自前端的請求,也有可能后端處理完畢之后前端已經關閉,因此無法結束處理完畢的交易。只要前端能夠在啟動APP的時候得到SDK的回調,再次請求一下后端進行處理就行了。