### 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>