![](https://img.haomeiwen.com/i1320963/dcf6f20d57fcbf09.png)
我们先来看看有哪些请况会发生掉单:
- 在付款成功后由于网络或应用闪退或者强制kill等各种原因没有返回Transaction(SKPaymentTransaction),从而不能得到凭证去Apple Store验证订单的正确性。
2.苹果服务器成功返回了Transaction,但是在APP在上传凭证给服务器(Your Server)时发生了网络或各种原因,造成了凭证的丢失,产生了掉单(用户付了款却没有得到相应的商品)
-(void)restoreCompletedTransactions;
Discussion
Use this method to restore finished transactions—that is, transactions for which you have already called finishTransaction:
. You call this method in one of the following situations:
-
To install purchases on additional devices
-
To restore purchases for an application that the user deleted and reinstalled
...
This method has no effect in the following situations:
...
You tried to restore items that are not restorable, such as a non-renewing subscription or a consumable product.
...
也就是说这个方法无法恢复非续订订阅 . 我必须自己存储购买并实现自己的恢复功能 .
然而我在测试的过程中发现上诉第一种异常情况的订单可以通过这个方法触发这个回调
- (void)paymentQueue:(SKPaymentQueue *)queue updatedTransactions:(NSArray<SKPaymentTransaction *> *)transactions;
是不是很很诡异,,此处有待大神们的再次验证!
![](https://img.haomeiwen.com/i1320963/cd9f437736903a0c.png)
关于苹果服务器验证返回21004的问题说明
在购买类型是自动续订时,服务端做验证就要传入这个共享密钥,传入字段为password,共享密钥获取见附录,如果你们的商品不是自动续订,建议不要传入该字段,否则传入内容不正确可能会导致苹果返回21004
国内连接苹果服务器的稳定性
开发之初,苹果方就很负责的告知:我们的服务器不稳定。真正开发之后,发现苹果方果然是很负责的,不仅是不稳定,而且足够慢。app store server验证一个收据需要3-6s时间
经验总结,如下内容已经过验证
1、程序加入支付队列使用SKMutablePayment和SKPayment的区别
两者拥有的属性一样,唯一区别是属性读写权限不同,SKMutablePayment属性具有读写权限,SKPayment属性只读,如果你要使用applicationUsername透传字段,那么就一定要使用SKMutablePayment加入支付队列
2、透传字段applicationUsername可能返回的是nil
在支付完成后,每笔订单都不调用finishTransaction,如此测试四五笔订单后,重新启动该应用,苹果自动补单会进行,在有些时候该字段就会为空,需要开发者注意
3、updatedTransactions:在App整个生命周期只会走一次,所以只要不把订单finishTransaction掉,重启App就会重新走苹果的补单流程(自动调用updatedTransactions:注意需要[[SKPaymentQueue defaultQueue] addTransactionObserver:instance];添加观察者才可以),逻辑需要自己根据项目实现
4、SKPaymentTransaction *transaction属性官方说明
5、 transaction.transactionDate
将订单交易添加到服务器队列的日期,仅当状态为SKPaymentTransactionStatePurchased或SKPaymentTransactionStateRestored时有效
6、 transaction.transactionIdentifier
transactionIdentifier是唯一标识交易支付成功的字符串,此值的格式与收据中的事务transaction_id相同,但是值可能不相同,仅当状态为SKPaymentTransactionStatePurchased或SKPaymentTransactionStateRestored时有效
7、transaction.originalTransaction
原始交易id,仅当状态为SKPaymentTransactionStateRestored时有效有值
8、 transaction.payment.applicationUsername
获取之前设置的applicationUsername
注意:凭证验证后返回的original_transaction_id和transaction_id一般情况下是相同的,只会在恢复购买时不一样
9、 transactionReceiptData可以无限验证通过,也就是说一个凭证可以被校验多次,这是刷单方法之一,需要开发者注意,有开发者说苹果的补单流程返回的transactionReceiptData即使同一笔订单也会变,测试下来并不会变化
10、transactionReceiptData验证解析后,in_app字段出现为空或者多个购买项目,按照网上部分开发者说法,只要不finishTransaction掉订单,下次再支付成功后,返回的transactionReceiptData凭证,就是包含之前的购买记录,测试多次无法复现
验证凭证,苹果服务器返回的数据
{
"receipt": {
"receipt_type": "ProductionSandbox",
"adam_id": 0,
"app_item_id": 0,
"bundle_id": "com.*****ane",
"application_version": "1",
"download_id": 0,
"version_external_identifier": 0,
"receipt_creation_date": "2019-11-25 10:00:36 Etc/GMT",
"receipt_creation_date_ms": "1574676036000",
"receipt_creation_date_pst": "2019-11-25 02:00:36 America/Los_Angeles",
"request_date": "2019-11-25 10:15:45 Etc/GMT",
"request_date_ms": "1574676945355",
"request_date_pst": "2019-11-25 02:15:45 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": "com.yo*********ond2",
"transaction_id": "10000******112",
"original_transaction_id": "100******112",
"purchase_date": "2019-11-25 10:00:36 Etc/GMT",
"purchase_date_ms": "1574676036000",
"purchase_date_pst": "2019-11-25 02:00:36 America/Los_Angeles",
"original_purchase_date": "2019-11-25 10:00:36 Etc/GMT",
"original_purchase_date_ms": "1574676036000",
"original_purchase_date_pst": "2019-11-25 02:00:36 America/Los_Angeles",
"is_trial_period": "false"
}
]
},
"status": 0,
"environment": "Sandbox"
}
网友评论