Purchase flow - iOS
Purchasing flow is a multistage process, which involves payment collection, purchase validation and consumption.
Starting purchasing flow
We can use previously acquired SKProduct info to create payment and initiate purchase:
- Objective-C
- Swift
SKProduct *product = ...; // previously fetched product
SKPayment *payment = [SKPayment paymentWithProduct:product];
[[SKPaymentQueue defaultQueue] addPayment:payment];
let product = ... // previously fetched product
let payment = SKPayment(product: product)
SKPaymentQueue.default().add(payment)
Validating purchases (recommended)
Although validation is NOT a mandatory step, yet it's highly recommended to minimize the chance of fraud and any other malevolent intents.
For instructions on how to validate your purchases, see Purchase validation.
Consuming purchased goods
The very final step in the chain of purchasing flow stages is to award the purchased goods to the user and mark these goods as "awarded". The process also known as purchase consumption.
Use the code below to do just that:
- Objective-C
- Swift
Purchase result will become known in paymentQueue:updatedTransactions: method:
- (void)paymentQueue:(SKPaymentQueue *)queue updatedTransactions:(NSArray *)transactions {
for(SKPaymentTransaction *transaction in transactions) {
switch (transaction.transactionState) {
case SKPaymentTransactionStateFailed:
// Check if the user cancelled the purchase (don't treat as an error)
if (transaction.error.code == SKErrorPaymentCancelled) {
[[SKPaymentQueue defaultQueue] finishTransaction:transaction];
break;
}
// Always acknowledge transaction and finish it
[[SKPaymentQueue defaultQueue] finishTransaction:transaction];
break;
case SKPaymentTransactionStatePurchased:
// here you can save the purchase and award it to the user
// Always acknowledge transaction and finish it after it was saved
[[SKPaymentQueue defaultQueue] finishTransaction:transaction];
break;
default: break;
}
}
}
Purchase result will become known in paymentQueue(_:updatedTransactions:) method:
func paymentQueue(_: SKPaymentQueue, updatedTransactions: [SKPaymentTransaction]) {
for transaction in updatedTransactions {
switch transaction.transactionState {
case .failed:
// Check if the user cancelled the purchase (don't treat as an error)
if (transaction.error as? SKXError)?.errorCode == .paymentCancelled {
SKPaymentQueue.default().finishTransaction(transaction)
break
}
// Always acknowledge transaction and finish it
SKPaymentQueue.default().finishTransaction(transaction)
case .purchased:
// here you can save the purchase and award it to the user
// Always acknowledge transaction and finish it after it was saved
SKPaymentQueue.default().finishTransaction(transaction)
default:
break
}
}
}
It's highly recommended to perform at least some form of validation before consuming the purchased goods.