Skip to main content

How I Finally Made Google Play Subscriptions Work in a React Native App Using React Native IAP

 

I recently spent an exhausting amount of time trying to get Google Play subscriptions to work with my React Native app using the react-native-iap library. Surprisingly, setting up subscriptions for iOS was relatively straightforward, but Android proved to be much more challenging.

Initially, I expected iOS to be more difficult to configure, considering Apple’s well-known strict rules and regulations. However, I was totally wrong. Although some of the hurdles I faced were due to my own unfamiliarity with Google Play’s subscription setup process, the experience was frustrating. I want to share my journey in the hopes that it saves others some time.

The Battle Begins: Offer Tokens and Testers

My first issue was with the offerToken. On iOS, subscriptions worked fine without any additional setup for offer tokens. But on Android, I kept encountering problems, which led me to spend a lot of time googling solutions and trying different approaches.

After some research, I learned that I needed to create an “offer” after setting up the subscription itself. So, I added an offer in the Google Play Console, thinking this would solve the problem. Unfortunately, it didn’t.

The Mystifying getSubscriptions() Returning null

The next clue came when I realized that getSubscriptions() was returning null. Naturally, I assumed my code was incorrect because I was new to using react-native-iap. I spent hours trying to fix the code, but nothing worked.

Setting Up Testers: The Never-Ending Story

I eventually found out that I needed to set up testers in the Google Play Console to test in-app subscriptions. I set up testers, but it still didn’t work. Then, I found out I had to accept the “Join on Android” or “Join on the web” link from my actual device using the test email account.

Even after setting up the testers, I still couldn’t get the link to work. I then discovered that I had to create a track under “Closed Testing” in the Google Play Console. I created the track, but nothing changed.

After more digging, I learned that I had to release the closed testing version for testing. Again, no luck.

License Testing: Checkbox Confusion

Another step was adding my email list to “License Testing” in the Google Play Console. I thought I had already done this, but I was wrong. It turns out that just seeing my email on the page wasn’t enough — I had to actually check the checkbox and save the changes. This also applied to closed testers and any other testers I had set up.

Once I properly checked the checkboxes and saved, the “Join on Android” link finally worked.

The Subscription Finally Shows Up… But Another Error Appears

After following all of the steps above, getSubscriptions() finally started returning data. However, when I tried to call requestSubscription(), I got yet another error. I was about to pull my hair out.

I tried various things to fix the error, including changing the order of the sku and offerToken in my code, even though they were part of an object and the order shouldn't matter.

The Final Solution

Here’s the code that finally worked for me:

const purchaseSubscription = async () => {
try {
if (Platform.OS === "android") {
const subscriptions: any = await getSubscriptions({
skus: itemSkus,
});
const purchase = await requestSubscription({
subscriptionOffers: [
{
sku: subscriptions[0]?.productId,
offerToken: subscriptions[0]?.subscriptionDetails[0]?.offerToken,
},
],
});
console.log("Subscription purchased:", purchase);
} else {
const purchase = await requestSubscription({
sku: itemSkus,
});
console.log("Subscription purchased:", purchase);
}
} catch (error) {
console.error("Purchase error:", error);
}
};

The key was to first call getSubscriptions() and then use the returned values to call requestSubscription(). For some reason, trying to use hardcoded values or values from my initial setup didn’t work. By dynamically fetching the subscription details, I was finally able to get everything working.

Lessons Learned

  1. Don’t assume iOS will be more difficult. In my case, Android had a steeper learning curve and more hidden steps.
  2. Testers need proper setup. Simply adding an email doesn’t mean it’s set up correctly. Make sure to check all relevant checkboxes.
  3. Fetching subscription details dynamically helped. Calling getSubscriptions() before requestSubscription() made a big difference.
  4. Documentation isn’t always enough. Even after reading the official documentation and searching online, I still had to do a lot of trial and error.

Conclusion

I hope sharing my journey will help other developers who face similar issues. The lack of up-to-date resources for Google Play subscriptions with react-native-iap can make things tricky, but hopefully, this guide can serve as a helpful resource for anyone who encounters the same problems.


With this code and approach, I was able to get my subscription-based app running smoothly on both iOS and Android. If you’re struggling with this yourself, don’t give up — keep digging, and you’ll get there!

Happy coding! ๐Ÿš€

    Popular posts from this blog

    Xcode and iOS Version Mismatch: Troubleshooting "Incompatible Build Number" Errors

    Have you ever encountered a frustrating error while trying to run your iOS app in Xcode, leaving you scratching your head? A common issue arises when your device's iOS version is too new for the Xcode version you're using. This often manifests as an "incompatible build number" error, and looks like this: DVTDeviceOperation: Encountered a build number "" that is incompatible with DVTBuildVersion. This usually happens when you are testing with beta versions of either iOS or Xcode, and can prevent Xcode from properly compiling your storyboards. Let's explore why this occurs and what you can do to resolve it. Why This Error Occurs The core problem lies in the mismatch between the iOS version on your test device and the Software Development Kit (SDK) supported by your Xcode installation. Xcode uses the SDK to understand how to build and run apps for specific iOS versions. When your device runs a newer iOS version than Xcode anticipates, Xcode mi...

    How to Fix the “Invariant Violation: TurboModuleRegistry.getEnforcing(…): ‘RNCWebView’ Could Not Be Found” Error in React Native

    When working with React Native, especially when integrating additional libraries like react-native-signature-canvas , encountering errors can be frustrating. One such error is: Invariant Violation: TurboModuleRegistry. getEnforcing (...): 'RNCWebView' could not be found This error often occurs when the necessary dependencies for a module are not properly linked or when the environment you’re using doesn’t support the required native modules. Here’s a breakdown of how I encountered and resolved this issue. The Problem I was working on a React Native project where I needed to add the react-native-signature-canvas library to capture user signatures. The installation process seemed straightforward: Installed the package: npm install react-native-signature- canvas 2. Since react-native-signature-canvas depends on react-native-webview , I also installed the WebView package: npm install react- native -webview 3. I navigated to the iOS directory and ran: cd ios pod install Everythi...

    Fixing FirebaseMessagingError: Requested entity was not found.

    If you’re working with Firebase Cloud Messaging (FCM) and encounter the error: FirebaseMessagingError: Requested entity was not found. with the error code: messaging/registration-token-not-registered this means that the FCM registration token is invalid, expired, or unregistered . This issue can prevent push notifications from being delivered to users. ๐Ÿ” Possible Causes & Solutions 1️⃣ Invalid or Expired FCM Token FCM tokens are not permanent and may expire over time. If you’re storing tokens in your database, some might be outdated. ✅ Solution: Remove invalid tokens from your database when sending push notifications. Refresh and store the latest FCM token when the app starts. Example: Automatically Refresh Token firebase. messaging (). onTokenRefresh ( ( newToken ) => { // Send newToken to your backend and update the stored token }); 2️⃣ Token Unregistered on Client Device A token might become unregistered if: The app is uninstalled on the user’s device. ...