最近项目内购,每天有用户反馈无法进行内购或者付款成功后商品未到账的情况,于是进行了分析优化.
分析
- 无法进行内购问题
原因是在从苹果服务器请求产品信息失败导致的.
通常返回错误提示:无法连接iTunes store.(沙盒环境)
即下面请求失败.
SKProductsRequest *productsRequest = [[SKProductsRequest alloc] initWithProductIdentifiers:identifiers];
productsRequest.delegate = delegate;
[productsRequest start];
该问题苹果服务器原因,无解中.(T_T)
但是我们可以曲线救国使用废弃api创建SKPayment进行购买.(亲测可用)
+ (id)paymentWithProductIdentifier:(NSString *)identifier NS_DEPRECATED_IOS(3_0, 5_0, "Use +paymentWithProduct: after fetching the available products using SKProductsRequest");
- 付款成功后,虚拟币或者会员未到账
原因是没有和我们的服务器二次验证成功.
主要有以下两种可能性:
1 . 苹果扣款成功回调后,因为我们服务器或者网络原因等导致二次验证失败.
2 . 苹果扣款成功后,没有进行正确回调.
曾经苹果服务器有两天抽风,导致我们IAP全部失败,奇怪的是别人的虽然也回调失败,但是还是能成功购买.
优化
针对第一种可能:
- 与我们服务器进行二次验证失败的时候,不能完成苹果订单.(wwdc有强调,消耗型)
即不要对这个transaction
调用以下代码:
[[SKPaymentQueue defaultQueue] finishTransaction:transaction];
后续再进行二次验证成功后在finishTransaction.
- 灵活进行二次验证
// Only valid if state is SKPaymentTransactionStatePurchased.
@property(nonatomic, readonly, nullable) NSData *transactionReceipt NS_DEPRECATED_IOS(3_0, 7_0, "Use -[NSBundle appStoreReceiptURL]");
iOS7新方法获取的transactionReceipt在多次进行内购后,会变大,甚至达几百KB.
iOS6老方法获取则小很多,只有几KB.
先尝试用iOS6的transactionReceipt进行验证,失败后再用iOS7的transactionReceipt进行验证,以提高二次验证的成功率.
针对第二种可能:
- 检查购买队列中是否有购买成功但未完成二次验证的
transaction
即[SKPaymentQueue defaultQueue] .transactions
里面.(该属性不支持KVO)
1 . 主要在进入含有内购页面时候进行检查.例如购买虚拟币页面.
2 . 苹果内购addPayment
后,定时3~5秒进行检查,以防苹果没有进行正确回调.
其他优化:
- 不要尝试保存失败信息,维护起来非常困难.(因为内购的容易失败)
如果有需要将我们的订单和内购交易在购买未成功之前就建立关系,可以利用SKPayment
的applicationUsername
属性,来保存我们的订单号或者用户id信息.
介绍如下:
An opaque identifier for the user’s account on your system.
This is used to help the store detect irregular activity. For example, in a game, it would be unusual for dozens of different iTunes Store accounts making purchases on behalf of the same in-game character.
The recommended implementation is to use a one-way hash of the user’s account name to calculate the value for this property.
- 建立对成功二次验证SKPaymentTransaction的transactionIdentifier的缓存机制.
进行二次验证前判断缓存,以防重复的二次验证.(注意在合适的时候清空缓存,例如队列中没有购买成功的SKPaymentTransaction)
上线后,再来更新优化后的效果... C U around.