IOS --- perfect solution for Apple payment string tickets
When I made Apple pay, I encountered a ticket string problem because Apple did not return any order-related direct parameters no matter whether the payment was successful or failed, I cannot uniquely match the order number of our server. As a result, the order processing will be messy. After several days of exploration, I found the following solution, I think it should perfectly solve the problem of iOS7 and above, but there is no good solution for iOS7 and below!
1. When we initiate a payment request to the Apple Server, Apple will call back the following method:
-(Void) paymentQueue :( SKPaymentQueue *) queue updatedTransactions :( NSArray *) transactions {
For (SKPaymentTransaction * transaction in transactions)
{
Switch (transaction. transactionState)
{
Case SKPaymentTransactionStatePurchased:
[Self completeTransaction: transaction];
Break;
Case SKPaymentTransactionStateFailed:
[Self failedTransaction: transaction];
Break;
Case SKPaymentTransactionStateRestored:
[Self restoreTransaction: transaction];
Break;
Case SKPaymentTransactionStatePurchasing:
LGLog (@ Transaction is being added to the server queue .);
Break;
Default:
Break;
}
}
}
2. After Apple callback, we need
-(Void) completeTransaction :( SKPaymentTransaction *) transaction or
-(Void) restoreTransaction :( SKPaymentTransaction *) transaction or
-(Void) failedTransaction :( SKPaymentTransaction *) called in transaction
[[SKPaymentQueue defaultQueue] finishTransaction: transaction] tells apple that we have received a notification. If this method notifies apple of failure, Apple will always call-(void) paymentQueue :( SKPaymentQueue *) queue updatedTransactions :( NSArray *) transactions, until we notify apple of success, so that a single string problem will occur. Because Apple does not return any order-related parameters to us in the transaction, we cannot have a unique correspondence with orders on our servers.
3. solution:
For successful callback, transaction contains a transaction number transaction. transactionIdentifier, which is unique and can be saved locally to differentiate different orders;
-(Void) completeTransaction :( SKPaymentTransaction *) transaction {
[[SKPaymentQueue defaultQueue] finishTransaction: transaction];
// If Apple already has a successful callback, the callback will be voided.
If (! [ZCTool saveTransactionIdentifier: transaction. transactionIdentifier]) {
Return;
}
}
For failed callback, iOS7 and later (I don't have a good method below iOS7), we can use transaction. payment. applicationUsername to save the order number. The specific practices are as follows:
SKMutablePayment * payment = [SKMutablePayment paymentWithProduct: product];
If (SYSTEM_VERSION> = 7.0 ){
Payment. applicationUsername = ourOrderId;
}
[[SKPaymentQueue defaultQueue] addPayment: payment];
In this way, the failure callback method can be processed as follows, consistent with the processing logic of the successful callback to save the transaction number.
-(Void) failedTransaction :( SKPaymentTransaction *) transaction {
[[SKPaymentQueue defaultQueue] finishTransaction: transaction];
If (SYSTEM_VERSION> = 7.0 ){
// Process iOS7 and later. If an error callback has occurred for Apple, the callback will be voided.
If (! [ZCTool saveAppleFailureOrderId: transaction. payment. applicationUsername]) {
Return;
}
}
}