文章已迁移到新博客 http://cwqqq.com/2017/12/ios_in-app_pay_server_side_code
iOS内购充值,是通过客户端接入iOS的IAP模块(In-App Purchase)后,由客户端发起充值,然后再把充值数据(receipt)发给服务端,最后由服务端远程调用AppStore服务器验证。最近研究了下iOS充值,着实遇到不少麻烦,就利用点时间总结下自己的经验,给大家做个分享。
receipt-data | The base64 encoded receipt data. |
password | Only used for receipts that contain auto-renewable subscriptions. Your app’s shared secret (a hexadecimal string). |
$verification_uri = 'https://buy.itunes.apple.com/verifyReceipt';
if ($is_sandbox) $verification_uri = 'https://sandbox.itunes.apple.com/verifyReceipt';
$post_data = array('receipt-data'=>$receipt_data);
$ch = curl_init($verification_uri);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($post_data));
$response = curl_exec($ch);
$errno = curl_errno($ch);
$errmsg = curl_error($ch);
curl_close($ch);
if ($errno != 0) {
throw new Exception($errmsg, $errno);
}
$data = json_decode($response, 1);
{
receipt = {
"adam_id" = 0,
"app_item_id" = 0,
"application_version" = 1,
"bundle_id" = "com.test",
"download_id" = 0,
"in_app" = {
{
"is_trial_period" = false,
"original_purchase_date" = "2017-01-01 01:01:01 Etc/GMT",
"original_purchase_date_ms" = 1483203661000,
"original_purchase_date_pst" = "2017-01-01 01:01:01 America/Los_Angeles",
"original_transaction_id" = 1000000000000001,
"product_id" = "com.test.10",
"purchase_date" = "2017-01-01 01:01:01 Etc/GMT",
"purchase_date_ms" = 1483203661000,
"purchase_date_pst" = "2017-01-01 01:01:01 America/Los_Angeles",
"transaction_id" = 1000000000000001
},
//......
},
"receipt_type" = ProductionSandbox,
"request_date" = "2017-01-01 01:01:01 Etc/GMT",
"request_date_ms" = 1483203661000,
"request_date_pst" = "2017-01-01 01:01:01 America/Los_Angeles",
"version_external_identifier" = 0,
},
status = 0
}
2、iOS7以下获取的票据返回数据(不包括iOS7):
{
receipt = {
"bid" = "com.test",
"bvrs" = 1,
"item_id" = 573837050,
"original_purchase_date" = "2017-01-01 01:01:01 Etc/GMT",
"original_purchase_date_ms" = 1483203661000,
"original_purchase_date_pst" = "2017-01-01 01:01:01 America/Los_Angeles",
"original_transaction_id" = 1000000000000001,
"product_id" = "com.test.10",
"purchase_date" = "2017-01-01 01:01:01 Etc/GMT",
"purchase_date_ms" = 1483203661000,
"purchase_date_pst" = "2017-01-01 01:01:01 America/Los_Angeles",
"transaction_id" = 1000000000000001
},
status = 0
}
SKPaymentTransactionStateDeferred 即等待确认,主要用于儿童模式,需要询问家长同意。这种情况下不能关闭订单(完成交易),否则这类充值将无法处理。
对各种交易状态的处理如下(这是客户端的逻辑,既然写到这里,也科普下 ^_^):
for (SKPaymentTransaction *transaction in transactions) {
switch (transaction.transactionState) {
case SKPaymentTransactionStatePurchasing:
NSLog(@"正在支付");
break;
case SKPaymentTransactionStateDeferred:
NSLog(@"延迟处理");
break;
case SKPaymentTransactionStateFailed:
NSLog(@"交易失败");
[[SKPaymentQueue defaultQueue] finishTransaction:transaction];
break;
case SKPaymentTransactionStatePurchased:
NSLog(@"交易完成");
[[SKPaymentQueue defaultQueue] finishTransaction:transaction];
break;
case SKPaymentTransactionStateRestored:
NSLog(@"购买过了");
[[SKPaymentQueue defaultQueue] finishTransaction:transaction];
break;
default:
NSLog(@"其他状态 %@", @(transaction.transactionState));
break;
}
}
主动完成交易的目的是,如果没有主动完成交易,下次启动App时(添加Observer),AppStore会再次通知你交易信息,直到你完成交易。当然,如果没有完成交易,是不能再发起同样的一笔充值订单。
参考:http://blog.csdn.net/mycwq/article/details/71852679