### iOS 內購后端處理操作基本流程:
步驟1:App 下單,觸發后臺下單接口,**接口生成一個商戶訂單號并返回給 App。**
步驟2:App 拿到商戶訂單號之后調用 IPA 創建一個 IPA 交易,并且添加到支付隊列。 然后 IAP 會調用 Apple ID 支付頁面等待用戶確認支付,IPA 和蘋果自己的 IPA 服務器通訊,回調購買成功,并且把收據寫入 App 沙盒。
步驟3: 然后 App 去沙盒獲取收據并且下發到自己的服務器。
步驟4: **服務器去 IAP 服務器查詢收據的有效性并且對應到某個訂單號,把驗證收據支付情況返回給 App。**
步驟5: App 根據返回的驗證情況,來顯示相應提示,然后 App 調用IAP 支付隊列去結束該 IPA 交易。
<br><br>
根據以上流程,后端只需要做兩個操作:一、生成訂單號;二、驗證收據
[收據驗證下發數據-文檔鏈接](https://developer.apple.com/documentation/appstorereceipts/requestbody)
```
//一、生成訂單號
let?outTradeId?=?'wx' + Date.now().toString();
//二、驗證收據
let receipt = req.body['receipt']; //服務端接收APP返回的憑證【一大串加密字符】
/*1.生產網址驗證*/
let postData = JSON.stringify({"receipt-data": receipt});
request.post({
url: 'https://buy.itunes.apple.com/verifyReceipt',
form: postData
}, function (error, response, body) {
if (!error && response.statusCode == 200) {
let status = JSON.parse(body).status;
if (status == 0) {
//生產網址驗證通過,進行商品開通的業務操作
...... 業務代碼......
//業務代碼完成后,返回成功開通數據,至此,后端處理結束。
app.res.send('訂單支付成功!');
} else if (status == 21007) { //沙盒再次驗證
getSandbox(postData);
} else {
app.res.send('訂單支付失敗!');
}
} else {
app.res.send('訂單支付失敗!');
}
});
/*2.沙盒驗證*/
function getSandbox(datas) {
request.post({
url: 'https://sandbox.itunes.apple.com/verifyReceipt',
form: datas
}, function (error, response, body) {
if (!error && response.statusCode == 200) {
let status = JSON.parse(body).status;
if (status == 0) {
//沙盒驗證通過,生產網址驗證通過,進行商品開通的業務操作
...... 業務代碼......
//業務代碼完成后,返回成功開通數據,至此,后端處理結束。
app.res.send('訂單支付成功!');
} else {
app.res.send('訂單支付失敗!');
}
} else {
app.res.send('訂單支付失敗!');
}
});
}
```
<br><br>
驗證通過后蘋果返回的 body 數據:
```
~~~
{
"status": 0,
"environment": "Sandbox"
"receipt": {
"receipt_type": "ProductionSandbox",
"adam_id": 0,
"app_item_id": 0,
"bundle_id": "com.BlueMobi.Phonics",
"application_version": "1.5.0",
"download_id": 0,
"version_external_identifier": 0,
"receipt_creation_date": "2018-06-28 14:08:26 Etc/GMT",
"receipt_creation_date_ms": "1530194906000",
"receipt_creation_date_pst": "2018-06-28 07:08:26 America/Los_Angeles",
"request_date": "2018-08-05 04:50:58 Etc/GMT",
"request_date_ms": "1533444658147",
"request_date_pst": "2018-08-04 21:50:58 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": "*******",
"transaction_id": "1000000404314890", //這個蘋果的交易唯一標識符,但不是交易訂單號(流水號),蘋果不生成返回流水號,也不返回商品價格,所以對賬很不友好!
"original_transaction_id": "1000000404314890",
"purchase_date": "2018-06-04 09:58:41 Etc/GMT",
"purchase_date_ms": "1528106321000",
"purchase_date_pst": "2018-06-04 02:58:41 America/Los_Angeles",
"original_purchase_date": "2018-06-04 09:58:41 Etc/GMT",
"original_purchase_date_ms": "1528106321000",
"original_purchase_date_pst": "2018-06-04 02:58:41 America/Los_Angeles",
"is_trial_period": "false"
},
{
"quantity": "1",
"product_id": "*******",
"transaction_id": "1000000404523773",
"original_transaction_id": "1000000404523773",
"purchase_date": "2018-06-05 02:21:26 Etc/GMT",
"purchase_date_ms": "1528165286000",
"purchase_date_pst": "2018-06-04 19:21:26 America/Los_Angeles",
"original_purchase_date": "2018-06-05 02:21:26 Etc/GMT",
"original_purchase_date_ms": "1528165286000",
"original_purchase_date_pst": "2018-06-04 19:21:26 America/Los_Angeles",
"is_trial_period": "false"
}
]
}
}
~~~
```
<br><br>
**我如何得到購買的產品信息呢?**
注意返回數據的receipt.in\_app是一個數組,里面保存了所有未結束的交易,每一筆交易內,都會有一個product\_id用于自行映射相關的產品信息
<br><br>