High-Impact Migration Logic
1. Connection Management (The v8+ Reconnection Shift)
Intent: Move from developer-managed state (manual retries) to library-managed state.
- Remove: Manual
startConnection()calls or retry timers insideonServiceDisconnected(). - Add:
.enableAutoServiceReconnection()toBillingClient.Builder. - Logic: In v8+, the library handles transient disconnections. Your
onServiceDisconnectedmust only be used for logging or updating UI state (e.g., "Billing service temporarily unavailable").
2. Product Querying & Models (The v5-v8 Architectural Shift)
Intent: Support the "One Product, Multiple Offers" model introduced in v5 and refined in v8.
- Data Model Swap:
- Legacy:
SkuDetails(1:1 mapping of ID to price). - Modern:
ProductDetails. A singleProductDetailscan contain multipleSubscriptionOfferDetails(Base Plans + Offers).
- Legacy:
- Result Handling (v8+ Logic):
- Change:
queryProductDetailsAsyncno longer returns a list in the listener. - New Intent: You must receive a
QueryProductDetailsResultobject. - Refactor:
kotlin // PBL 8+ Pattern billingClient.queryProductDetailsAsync(params) { result: QueryProductDetailsResult -> val responseCode = result.billingResult.responseCode val productDetailsList = result.productDetailsList // Retrieve list from result object // Process list... }
- Change:
3. Subscription Modernization (v6 & v7)
Intent: Support "Base Plans" and "Offers" instead of legacy standalone SKUs.
Subscription Upgrades/Downgrades (v6+):
- Legacy:
setOldSkuPurchaseToken()inBillingFlowParams. - Modern: Use
SubscriptionUpdateParams. You must specify thePurchaseTokenof the existing subscription and theReplacementMode(which replaces the deprecatedProrationMode). - Logic: Verify that the
ReplacementModematches the business intent (e.g.,CHARGE_FULL_PRICEversusWITH_TIME_PRORATION).
- Legacy:
Installment Plans (v7+):
- Intent: Allow users to pay for a subscription in monthly installments.
- Check: Look for
InstallmentPlanDetailswithinSubscriptionOfferDetails. If the app supports high-ticket subscriptions, it is mandatory to implement theinstallmentPlanDetailsUI.
4. Purchase Handling & History (v6+)
Intent: Move away from local-only purchase caches to real-time status checks.
- Active Purchases:
- Deprecated:
queryPurchases()(synchronous). - Mandatory:
queryPurchasesAsync(). You must passQueryPurchasesParamscontaining theProductType(INAPPorSUBS).
- Deprecated:
- Purchase History (Pagination Intent):
- v6+ Change:
queryPurchaseHistoryAsyncis optimized for pagination. - Logic: If the app has thousands of historical transactions, verify
you are using the
PurchaseHistoryRecordlist correctly to avoid memory overhead.
- v6+ Change:
5. Security & Pending Transactions (The "Always On" Rule)
- Mandatory:
enablePendingPurchases()has been required since v3, but in v8+, verify that it is called before.build(). You must also include.enableOneTimeProducts()on theenablePendingPurchases()builder. - Optional: If the app sells prepaid subscriptions, you must also include
.enablePrepaidPlans(). - Intent: This handles "Slow/Delayed" payments (like cash or bank transfers). Without this, the app will crash on initialization in modern versions.
6. SDK & Environment Requirements
- PBL 7.0: Requires
compileSdk 34or higher. - PBL 8.0: Requires
compileSdk 35. - Kotlin: Verify that
kotlin-stdlibis updated to at least 1.9.x to support new library coroutine extensions.
7. User-Facing Features (Post-Upgrade Recommendations)
Once the upgrade is complete, the following features are enabled by these versions:
- v7: Installments (Monthly payments for annual plans).
- v8: Prepaid Plans (Users can top-up time without auto-renewing).
- v8: Personalized Pricing (Show legal disclosure if price varies by user).