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."
To view and manage your Android subscriptions, open the Google Play Store app on your device, then tap the menu button (the three horizontal lines in the top left), then choose Subscriptions. You'll see a list of all the subscriptions, such as Google Play Music, handled through Google.
All transactions made on Android are tied to your Google account (or Amazon if you downloaded the app from Amazon Appstore). This means that you can restore your BetterSleep Premium content on any Android-powered device as long as you use the same account.
To restore your purchases:Open the drawer from the upper left corner of the screen and select Support. Select Purchases and Paid App from the menu. Tap on the menu option, located in the upper right-hand corner of the screen. Tap on Recover Paid App.
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
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With