Background — Google Play’s new subscription model
Google Play now separates Subscriptions from Base Plans. The hierarchy looks like this:
Subscription (e.g. "premium_main_sub")
└── Base Plan: "weekly_prepaid" ← 7-day, prepaid
└── Base Plan: "monthly_prepaid" ← 1-month, prepaid
└── Base Plan: "yearly_prepaid" ← 1-year, prepaid
Previously (GPBL v3 / SkuDetails era) each subscription was a flat product with one billing period. Now Google encourages grouping duration variants under a single container Subscription, where each duration is a Base Plan. To purchase a specific Base Plan, the native GPBL v5+ flow requires:
- Call
queryProductDetailsAsync()on the container subscription ID - From the returned
ProductDetails, callgetSubscriptionOfferDetails()→ gets aList<ProductDetails.SubscriptionOfferDetails> - Each entry has
getBasePlanId()andgetOfferToken() - Pass the chosen
offerTokenintoBillingFlowParams.ProductDetailsParamswhen callinglaunchBillingFlow()
In native Java/Kotlin this is well-documented. The question is how to do it through Unity IAP v5.2.
What we investigated in Unity IAP v5.2
We went through the public API surface carefully, including the official docs and package source. Here is what we found:
GoogleProductMetadata — confirmed public properties
From: Class GoogleProductMetadata | In-App Purchasing | 5.2.0-pre.2
public string freeTrialPeriod { get; }
public string introductoryPrice { get; }
public int introductoryPriceCycles { get; }
public string introductoryPricePeriod { get; }
public string subscriptionPeriod { get; }
public string originalJson { get; } // raw SKU JSON
No SubscriptionOfferDetails. No BasePlanId. No OfferToken.
Despite the docs describing GoogleProductMetadata as “a representation of ProductDetails”, the actual properties make it clear this wraps the legacy SkuDetails object (GPBL v3), not the modern ProductDetails (GPBL v5+). The originalJson field is the old SkuDetails JSON format, which predates the Base Plan system entirely and will not contain subscriptionOfferDetails.
IGooglePlayStoreExtendedPurchaseService — confirmed public methods
From uploaded source (IGooglePlayStoreExtendedPurchaseService.cs):
void UpgradeDowngradeSubscription(Product oldProduct, Product newProduct);
void UpgradeDowngradeSubscription(Product oldProduct, Product newProduct, GooglePlayProrationMode);
void UpgradeDowngradeSubscription(Product oldProduct, Product newProduct, GooglePlayReplacementMode);
void UpgradeDowngradeSubscription(Order currentOrder, Product newProduct, GooglePlayReplacementMode);
bool IsOrderDeferred(Order order);
GooglePurchaseState? GetPurchaseState(Order order);
string? GetObfuscatedAccountId(Order order);
string? GetObfuscatedProfileId(Order order);
event Action<DeferredPaymentUntilRenewalDateOrder> OnDeferredPaymentUntilRenewalDate;
No offer-token or base-plan selection here either. This service only handles switching between existing subscriptions (upgrade/downgrade).
IGooglePlayStoreExtendedService — confirmed via StoreController source
Accessible via storeController.GooglePlayStoreExtendedService. Does not expose base-plan purchase methods.
UnityEngine.Purchasing.Models namespace
Only contains GoogleBillingResponseCode (an enum mapping to BillingClient.BillingResponseCode). Nothing subscription-offer related.
UnityEngine.Purchasing.GoogleBilling.Models namespace
Only contains ExternalBillingProgramClient and supporting types for Google’s external billing program compliance. Nothing subscription-offer related.
UnityEngine.Purchasing.Security namespace
Contains GooglePlayReceipt (purchaseToken, orderID, productID, packageName, purchaseDate, purchaseState) and CrossPlatformValidator. No offer token.
IGooglePlayStoreExtensions (legacy, still present)
Listed in UnityEngine.Purchasing namespace. Marked [Obsolete]. This is the old v4 interface — not the path forward for new code.
Summary of what is and isn’t possible in v5.2
| Goal | Possible in Unity IAP v5.2? |
|---|---|
| Purchase a subscription (Option A — one sub per plan) | storeController.PurchaseProduct(productId) |
| Switch between subscriptions (upgrade/downgrade) | IGooglePlayStoreExtendedPurchaseService.UpgradeDowngradeSubscription() |
| Get subscription metadata (price, period, trial) | GoogleProductMetadata |
Get SubscriptionOfferDetails from ProductDetails |
GoogleProductMetadata wraps SkuDetails, not ProductDetails |
| Select a specific Base Plan by ID | |
| Purchase a specific Base Plan in a container Subscription |
What we’re trying to achieve
We have a Unity project using StoreController (IAP v5.2) and we want to support the modern Google Play subscription model — one container subscription (premium_main_sub) with multiple base plans (3day_prepaid, weekly_prepaid, monthly_prepaid, yearly_prepaid).
Our current workaround is Option A — creating separate Google Play Subscriptions per duration — which works fine. But we’d prefer the modern approach for cleaner Play Console management and because Google now recommends it for new apps.
Questions
-
Is there a public API in Unity IAP v5.2 (or a pre-release 5.x build) that allows purchasing a specific Base Plan by offer token? We may have missed something.
-
Is
GoogleProductMetadataplanned to be updated to wrapProductDetailsinstead ofSkuDetails? The current class exposes only legacy SkuDetails fields. -
Is the recommended path for Base Plan purchasing still Option A (separate Subscription per duration) from Unity IAP’s perspective? Or is there official guidance on Option B (container sub + base plans)?
-
If a native Android plugin /
AndroidJavaObjectbridge is the expected approach, is there any official Unity sample or documentation showing how to integrate a custom native billing flow with Unity IAP’s entitlement and receipt validation pipeline?
Our setup
- Unity IAP:
5.2.0-pre.2 - Unity: 6 (6000.x)
- Target platform: Android (Google Play)
StoreControllerv5 API (not legacyIStoreListener)
Any help or official clarification would be greatly appreciated. If the answer is “use Option A for now”, that’s a perfectly valid answer — we just want to confirm we haven’t missed a v5.2 API surface. Thanks!
@Laurie-Unity @jacobbev @Yannick_D @SashaM
Unity-In-App-Purchases
Monetization-and-Growth-Unity-In-App-Purchases