How to check In App Purchase Auto Renewable Subscription is valid How to check In App Purchase Auto Renewable Subscription is valid ios ios

How to check In App Purchase Auto Renewable Subscription is valid


Today, I have trouble with this problem.

Follow Apple doc here, I used this way to check subscription is expired or not. My idea: user APPLE REST API response: (request time + expired time) to check expired or not

+ (BOOL)checkInAppPurchaseStatus{    // Load the receipt from the app bundle.    NSURL *receiptURL = [[NSBundle mainBundle] appStoreReceiptURL];    NSData *receipt = [NSData dataWithContentsOfURL:receiptURL];    if (receipt) {        BOOL sandbox = [[receiptURL lastPathComponent] isEqualToString:@"sandboxReceipt"];        // Create the JSON object that describes the request        NSError *error;        NSDictionary *requestContents = @{                                          @"receipt-data": [receipt base64EncodedStringWithOptions:0],@"password":@"SHARE_SECRET_CODE"                                          };        NSData *requestData = [NSJSONSerialization dataWithJSONObject:requestContents                                                              options:0                                                                error:&error];        if (requestData) {            // Create a POST request with the receipt data.            NSURL *storeURL = [NSURL URLWithString:@"https://buy.itunes.apple.com/verifyReceipt"];            if (sandbox) {                storeURL = [NSURL URLWithString:@"https://sandbox.itunes.apple.com/verifyReceipt"];            }            NSMutableURLRequest *storeRequest = [NSMutableURLRequest requestWithURL:storeURL];            [storeRequest setHTTPMethod:@"POST"];            [storeRequest setHTTPBody:requestData];            BOOL rs = NO;            //Can use sendAsynchronousRequest to request to Apple API, here I use sendSynchronousRequest            NSError *error;            NSURLResponse *response;            NSData *resData = [NSURLConnection sendSynchronousRequest:storeRequest returningResponse:&response error:&error];            if (error) {                rs = NO;            }            else            {                NSDictionary *jsonResponse = [NSJSONSerialization JSONObjectWithData:resData options:0 error:&error];                if (!jsonResponse) {                    rs = NO;                }                else                {                    NSLog(@"jsonResponse:%@", jsonResponse);                    NSDictionary *dictLatestReceiptsInfo = jsonResponse[@"latest_receipt_info"];                    long long int expirationDateMs = [[dictLatestReceiptsInfo valueForKeyPath:@"@max.expires_date_ms"] longLongValue];                    long long requestDateMs = [jsonResponse[@"receipt"][@"request_date_ms"] longLongValue];                    NSLog(@"%lld--%lld", expirationDateMs, requestDateMs);                    rs = [[jsonResponse objectForKey:@"status"] integerValue] == 0 && (expirationDateMs > requestDateMs);                }            }            return rs;        }        else        {            return NO;        }    }    else    {        return NO;    }}

Hope this help.


IF you want to check on it from a web server, you ping their API and it returns the status of the auto-renewable subscription and info about the last payment. link

If you are on the device then you probably have to call restoreCompletedTransactions which I guess asks for the password.

I don't see any other method. I suppose from the device you could verify the subscription by contacting the same web service used on the server side? I don't know how the pros and cons of that.


Better to validate a receipt locally before making any calls to the Apple API. Every time the app runs it's a good practice to validate the local receipt and if you need to check whether user has any active subscriptions, you can retrieve all purchases from the local receipt and see if there is a purchase which is still active.

I have implemented a small library written in Swift to simplify to work with In-App Receipt locally. You can easily fetch the object that represents the receipt (InAppReceipt) and retrieve an active purchase/all purchases.

Feel free to use. Github link

Here is an example of solving your problem:

import TPInAppReceiptdo {    let receipt = try InAppReceiptManager.shared.receipt()        //retrive active auto renewable subscription for a specific product and date    let purchase = receipt.activeAutoRenewableSubscriptionPurchases(ofProductIdentifier: "ProductName", forDate: Date())        //retrive all auto renewable subscription purchases for a specific product    let allAutoRenewableSubscriptionPurchases = receipt.purchases(ofProductIdentifier: "productName").filter({ return $0.isRenewableSubscription })} catch {    print(error)}