react-native-iap icon indicating copy to clipboard operation
react-native-iap copied to clipboard

Issue: No clear way to check if user is currently in trial period (IOS)

Open shahrukh25795 opened this issue 4 months ago • 2 comments

Please use the Discussion board if you want to get some help. Please use issues to report bugs.

Description

When fetching subscription products, I can see trial information in the product metadata (e.g. introductoryPrice, introductoryPriceNumberOfPeriodsIOS, etc.). Example:

{
  "countryCode": "USA",
  "currency": "USD",
  "introductoryPrice": "$0.00",
  "introductoryPriceAsAmountIOS": "0",
  "introductoryPriceNumberOfPeriodsIOS": "7",
  "introductoryPricePaymentModeIOS": "FREETRIAL",
  "introductoryPriceSubscriptionPeriodIOS": "DAY",
  "localizedPrice": "$599.00",
  "platform": "ios",
  "price": "599",
  "productId": "my_product_id",
  "subscriptionPeriodNumberIOS": "1",
  "subscriptionPeriodUnitIOS": "YEAR",
  "title": "Yearly Access",
  "type": "subs"
}

This tells me that the product offers a 7-day trial. However, I don’t see a way to check if the user is actually in their trial period right now after they subscribe.

Expected Behavior

I should be able to determine if a user’s active subscription is currently in a trial or has moved into the paid phase.

Actual behavior

The library only exposes the product trial configuration, not whether the active user subscription is in trial or not.

Environment:

  • react-native-iap: "12.16.0"
  • react-native: "0.68.2"
  • Platforms: "IOS"

shahrukh25795 avatar Aug 24 '25 16:08 shahrukh25795

you have to validate the transaction receipt server side

client

import * as RNIap from 'react-native-iap';

async function checkSubscription() {
  try {
    const purchases = await RNIap.getAvailablePurchases();

    if (purchases.length === 0) {
      console.log("No active subscriptions");
      return false;
    }

    // Find your subscription product
    const subscription = purchases.find(
      p => p.productId === "your_subscription_id"
    );

    if (!subscription) {
      console.log("No subscription found");
      return false;
    }
1

    // Send receipt to backend for validation
    if (subscription.transactionReceipt) {
      const res = await fetch("https://your-server.com/validate", {
        method: "POST",
        headers: { "Content-Type": "application/json" },
        body: JSON.stringify({ receipt: subscription.transactionReceipt }),
      });
      const { active } = await res.json();

      return active;
    }

    return false;
  } catch (err) {
    console.warn("Error checking subscription:", err);
    return false;
  }
}

server

import fetch from "node-fetch";

app.post("/validate", async (req, res) => {
  const { receipt } = req.body;

  const response = await fetch("https://buy.itunes.apple.com/verifyReceipt", {
    method: "POST",
    headers: { "Content-Type": "application/json" },
    body: JSON.stringify({
      "receipt-data": receipt,
      "password": process.env.APP_SHARED_SECRET, // from App Store Connect
      "exclude-old-transactions": true
    }),
  });

  const data = await response.json();

  const latest = data.latest_receipt_info?.pop();
  const isActive =
    latest &&
    new Date(parseInt(latest.expires_date_ms, 10)) > new Date() &&
    !latest.cancellation_date;

  res.json({ active: isActive, details: latest });
});

oojr avatar Sep 05 '25 13:09 oojr

@shahrukh25795 I've just updated the docs! Hope this help~ https://hyochan.github.io/react-native-iap/docs/guides/subscription-validation

hyochan avatar Sep 25 '25 17:09 hyochan