问题
I am using renewable subscriptions in app purchases in an iOS app. When a user attempts to purchase a subscription that they already have paid for a message is displayed from iTunes "You're currently subscribed to this".
How I can detect when this event has occurred so that I can process the transaction and grant access to my app.
In the paymentQueue:updatedTransactions: method of the observer it is coming through as a SKPaymentTransactionStateFailed. How do I distinguish between this type of failure and other failures such as the user pressing the cancel buttons?
Do I submit the transaction that is returned or do I need to call restorePreviousTransactions.
In the Apple documents it states "If the user attempts to purchase a non-consumable product or a renewable subscription they have already purchased, your application receives a regular transaction for that item, not a restore transaction. However, the user is not charged again for that product. Your application should treat these transactions identically to those of the original transaction."
回答1:
Q: How I can detect when this event (currently subscribed) has occurred so that I can process the transaction and grant access to my app.
You detect when the subscription exists via validation with Apple (I use php website code to do this), you get a "status code" response back, and can verify whether it is a code 21006 (subscription is expired), or others (I consider anything other than 0 and 21006 to be an actual error).
The way I do things is I store the transaction details inside a PLIST file which I store in the documents directory.
You could add extra fields to the PLIST such as expiryDates, boolean flags, etc.
This way you have a copy of the receipt, although you should always validate it because it might have expired.
Q: In the paymentQueue:updatedTransactions: method of the observer it is coming through as a SKPaymentTransactionStateFailed. How do I distinguish between this type of failure and other failures such as the user pressing the cancel buttons?
You use a switch statement in the updatedTransactions method to determine the different types of responses.
Example
-(void)paymentQueue:(SKPaymentQueue *)queue restoreCompletedTransactionsFailedWithError:(NSError *)error
{
NSString *message = [NSString stringWithFormat:@"Transaction failed with error - %@", error.localizedDescription];
NSLog(@"Error - %@", message);
UIAlertView *alertView = [[UIAlertView alloc] initWithTitle:@"Error"
message:message
delegate:nil
cancelButtonTitle:@"OK"
otherButtonTitles:nil];
[alertView show];
[alertView release];
}
-(void)paymentQueue:(SKPaymentQueue *)queue updatedTransactions:(NSArray *)transactions
{
NSLog(@"updatedTransactions");
for (SKPaymentTransaction *transaction in transactions)
{
switch (transaction.transactionState)
{
case SKPaymentTransactionStatePurchasing:
// take action whilst processing payment
break;
case SKPaymentTransactionStatePurchased:
// take action when feature is purchased
break;
case SKPaymentTransactionStateRestored:
// take action to restore the app as if it was purchased
break;
case SKPaymentTransactionStateFailed:
if (transaction.error.code != SKErrorPaymentCancelled)
{
// Do something with the error
} // end if
break;
default:
break;
} // end switch
} // next
The TransactionStateFailed handles the failures, although I do not code for cancellation as there is no reason for me to do so in my app.
Q: Do I submit the transaction that is returned or do I need to call restorePreviousTransactions.
I believe StoreKit handles this internally with finishTransaction method and restorePreviousTransaction methods
ie,
[[SKPaymentQueue defaultQueue] finishTransaction: transaction];
to finish off transactions
I hope this helps
来源:https://stackoverflow.com/questions/6177940/already-purchased-subscriptions-in-storekit