Skip to content

[Android] Isssue: "replacementModeAndroid: 6", Google Play message: "Something went wrong on our end. Please try again." #3093

@arseni-siniauski

Description

@arseni-siniauski

Image
Image

Issue

hi, one here is my code for buying a subscription, upgrade/downgrade is already enabled here (the problem occurs with Android during downgrade)
one, it seems like I did everything according to the documentation, but every time I try to downgrade to replacementModeAndroid: 6, I get this screenshot
maybe I did something wrong or on the contrary I have to finalize something.
I will also attach a second screenshot of the organization of my subscriptions (maybe I got something wrong here?)

Buy subscription code

const buySubscription = async (isUpgradingPlan: boolean) => {
if (!selectedPlanId) return;

if (selectedPlanId === FREE_SUBSCRIPTION_PRODUCT.id) {
  handleBuySubscriptionCallback?.();
  return;
}

setIsPurchaseLoading(true);

try {
  const available = await getAvailablePurchases();
  const alreadyActive = available.some(p => selectedPlanId === p.productId);

  if (alreadyActive) {
    console.log("[IAP] Subscription already active, skipping new purchase");
    setIsPurchaseLoading(false);
    handleBuySubscriptionCallback?.();
    return;
  }

  const activeSubscription =
    available.find(p => p.productId === subscriptionsIAP[0]?.id) ??
    undefined;
  const purchaseTokenAndroid = activeSubscription?.purchaseToken;

  const subscription = subscriptionsIAP[0] as ProductSubscriptionAndroid;
  const androidSelectedPlanId = selectedPlanId.replace("_", "-"); // because android offers are named like this: "premium-month" but ios subscriptions are named like this: "premium_month"

  const replacementModeAndroid = isUpgradingPlan ? 1 : 6;

  const chosenOfferToken =
    subscription?.subscriptionOfferDetailsAndroid?.find(
      offer => offer.basePlanId === androidSelectedPlanId,
    )?.offerToken ?? "";
  const otherOffers =
    subscription?.subscriptionOfferDetailsAndroid
      ?.filter(offer => offer.basePlanId !== androidSelectedPlanId)
      ?.map(offer => ({
        sku: subscription.id,
        offerToken: offer.offerToken,
      })) ?? [];

  console.log("skus:", [androidSelectedPlanId]);
  console.log("offerToken:", chosenOfferToken);
  console.log("purchaseToken:", purchaseTokenAndroid);
  console.log("replacementMode:", replacementModeAndroid);

  await requestPurchase({
    request: {
      ios: { sku: selectedPlanId, appAccountToken: userPublicId },
      android: {
        skus: [subscription.id],
        subscriptionOffers: [
          { sku: subscription.id, offerToken: chosenOfferToken },
          ...otherOffers,
        ],
        purchaseTokenAndroid,
        replacementModeAndroid,
        obfuscatedAccountIdAndroid: userPublicId,
      },
    },
    type: "subs",
  });

  dispatch(getUserInfoThunk());
  dispatch(getUserLimitsLeftThunk());
  handleBuySubscriptionCallback?.();
} catch (error) {
  console.error("Buy subscription error:", error);
} finally {
  setIsPurchaseLoading(false);
}
};

Environment:

react-native-iap: "14.4.19"
react-native: "0.81.0"
Platforms: "Android"

Metadata

Metadata

Assignees

No one assigned

    Labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions