question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

IOS check if autorenewal subscription is still active

See original GitHub issue

Version of react-native-iap

2.2.2

Platforms you faced the error (IOS or Android or both?)

IOS

Expected behavior

Using the RNIAP api we could check if a autorenewal subscription is still active

Actual behavior

On android im doing this to check that:

export const isUserSubscriptionActive = async (subscriptionId) =>{
    // Get all the items that the user has
    const availablePurchases = await getAvailablePurchases();
    if(availablePurchases !== null && availablePurchases.length > 0){
        const subscription = availablePurchases.find((element)=>{
            return subscriptionId === element.productId;
        });
        if(subscription){
             // check for the autoRenewingAndroid flag. If it is false the sub period is over
              return subscription["autoRenewingAndroid"] == true;
            }
        }else{
            return false;
        }
    }
}

On ios there is no flag to check that, and the getAvailablePurchases method returns all the purchases made, even the subscriptions that are not active at the moment.

Is there a way to check this?

Regards, Marcos

Issue Analytics

  • State:closed
  • Created 5 years ago
  • Reactions:5
  • Comments:61 (15 by maintainers)

github_iconTop GitHub Comments

53reactions
andrewzeycommented, Oct 27, 2018

Here is the function I am using that works on both Android and iOS, properly sorting on iOS to ensure we get the latest receipt data:

import * as RNIap from 'react-native-iap';
import {ITUNES_CONNECT_SHARED_SECRET} from 'react-native-dotenv';

const SUBSCRIPTIONS = {
  // This is an example, we actually have this forked by iOS / Android environments
  ALL: ['monthlySubscriptionId', 'yearlySubscriptionId'],
}

async function isSubscriptionActive() {
  if (Platform.OS === 'ios') {
    const availablePurchases = await RNIap.getAvailablePurchases();
    const sortedAvailablePurchases = availablePurchases.sort(
      (a, b) => b.transactionDate - a.transactionDate
    );
    const latestAvailableReceipt = sortedAvailablePurchases[0].transactionReceipt;

    const isTestEnvironment = __DEV__;
    const decodedReceipt = await RNIap.validateReceiptIos(
      {
        'receipt-data': latestAvailableReceipt,
        password: ITUNES_CONNECT_SHARED_SECRET,
      },
      isTestEnvironment
    );
    const {latest_receipt_info: latestReceiptInfo} = decodedReceipt;
    const isSubValid = !!latestReceiptInfo.find(receipt => {
      const expirationInMilliseconds = Number(receipt.expires_date_ms);
      const nowInMilliseconds = Date.now();
      return expirationInMilliseconds > nowInMilliseconds;
    });
    return isSubValid;
  }

  if (Platform.OS === 'android') {
    // When an active subscription expires, it does not show up in
    // available purchases anymore, therefore we can use the length
    // of the availablePurchases array to determine whether or not
    // they have an active subscription.
    const availablePurchases = await RNIap.getAvailablePurchases();

    for (let i = 0; i < availablePurchases.length; i++) {
      if (SUBSCRIPTIONS.ALL.includes(availablePurchases[i].productId)) {
        return true;
      }
    }
    return false;
  }
} 
43reactions
kevinEsherickcommented, Feb 5, 2019

I’m working on figuring this out as well. I haven’t tested it yet, but from what I’m reading I’m gathering that it’s possible by creating a “shared secret” in iTunes Connect and passing this to validateReceiptIos with the key ‘password’. I believe this will then return a JSON object which will contain a code indicating the validation status of the subscription and the keys latest_receipt, latest_receipt_info, and latest_expired_receipt info, among others, which you can use to determine the subscription status. I am literally just figuring this out so I have yet to test it. It’s what I’m putting together from the issues and Apple’s docs. If this works, it really should be made very clear in the documentation instead of being buried in the issues. I believe the following links are relevant: https://developer.apple.com/library/archive/releasenotes/General/ValidateAppStoreReceipt/Chapters/ValidateRemotely.html #203 #237

EDIT: I can confirm that the process I mentioned above works. I think we should work to get a full explanation of this in the docs. I would implement something like this on app launch to determine whether a subscription has expired:

RNIap.getPurchaseHistory()
        .then(purchases => {
                RNIap.validateReceiptIos({
                   //Get receipt for the latest purchase
                    'receipt-data': purchases[purchases.length - 1].transactionReceipt,
                    'password': 'whateveryourpasswordis'
                }, __DEV__)
                    .then(receipt => {
                       //latest_receipt_info returns an array of objects each representing a renewal of the most 
                       //recently purchased item. Kinda confusing terminology
                        const renewalHistory = receipt.latest_receipt_info
                       //This returns the expiration date of the latest renewal of the latest purchase
                        const expiration = renewalHistory[renewalHistory.length - 1].expires_date_ms
                       //Boolean for whether it has expired. Can use in your app to enable/disable subscription
                        console.log(expiration > Date.now())
                    })
                    .catch(error => console.log(`Error`))
        })
Read more comments on GitHub >

github_iconTop Results From Across the Web

checking if an auto-rewew subscription expired
1) If the app detect that the subscription has expired it adds a transaction observer and awaits a call to updatedTransactions with a...
Read more >
Check Subscription Status(IOS Users) | ACTIVE.com Help ...
Please follow the steps below to check if your subscription auto renewal is canceled or not. Go to phone Settings; Click iTunes &...
Read more >
Check if an Auto-Renewable Subscription is still valid
Here is several ways to do receipt validation to check is user granted to subscription. Here is two ways of doing it correctly:....
Read more >
Swift tutorial: Auto-renewable subscriptions in iOS - Apphud
An auto-renewable app subscription lets you monetize your apps by charging users for features, services, or content on a recurring basis.
Read more >
iPhone subscriptions: How to check, cancel, and renew
Open the Settings app on iPhone or iPad · Tap your name at the top · Tap Subscriptions · You'll now see all...
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found