Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Already purchased subscriptions in StoreKit

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."

like image 772
joneswah Avatar asked May 30 '11 15:05

joneswah


People also ask

How do I see recurring app purchases?

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.

How do I restore purchases?

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.

How do I restore in-app purchases Swift?

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.


1 Answers

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

like image 118
zardon Avatar answered Nov 08 '22 21:11

zardon