求助:迁移至Play Billing Library解决订阅状态查询异常问题
Hey there! I’ve been through similar migration pains with the old IInAppBillingService and seen those tricky edge cases with subscription activation failures. Let’s break down the key steps to migrate to the Play Billing Library properly, and specifically address that 1% of users who aren’t getting access after purchase:
1. Start with a Robust BillingClient Setup
The old IInAppBillingService relied on manual service binding which was prone to connection drops. The Play Billing Library’s BillingClient handles this more reliably, but you need to make sure you’re handling setup correctly:
- Initialize the client with
BillingClient.newBuilder(context)and set aBillingClientStateListenerto handle connection success/failure. - Always check if the client is connected before making any calls (use
isReady()), and implement reconnection logic if it drops. - Example snippet:
private val billingClient = BillingClient.newBuilder(context) .setListener(purchasesUpdatedListener) .enablePendingPurchases() // Critical for handling pending payments! .build() private fun startBillingConnection() { billingClient.startConnection(object : BillingClientStateListener { override fun onBillingSetupFinished(result: BillingResult) { if (result.responseCode == BillingClient.BillingResponseCode.OK) { // Client is ready - query purchases or launch flow queryActiveSubscriptions() } } override fun onBillingServiceDisconnected() { // Reconnect when service is disconnected startBillingConnection() } }) }
2. Handle Purchases (Including Pending Ones!)
A common culprit for those "success but no access" cases is unhandled pending purchases. The old service didn’t surface these clearly, but the new library makes it mandatory to handle them:
- When launching the billing flow, the
PurchasesUpdatedListenerwill receive purchases withPurchase.PurchaseState.PENDING(e.g., user paid via cash or bank transfer which takes time to clear). - You need to store these pending purchases locally, and periodically query their status until they move to
PURCHASEDorCANCELLED. - Never grant access immediately only on
PURCHASED- make sure you’re not missing pending orders that will resolve later.
3. Reliable Subscription Status Sync
Don’t rely solely on local cache for subscription status - the old service often failed to sync across devices or after app reinstalls. Use these methods to keep status up-to-date:
- Query Active Purchases: Call
queryPurchasesAsync(BillingClient.SkuType.SUBS)on app launch, every time the app comes to foreground, and after any billing action. This fetches the latest status directly from Google Play. - Real-Time Developer Notifications (RTDN): Set up a server-side endpoint to receive real-time updates for subscription events (purchase, cancellation, renewal, etc.). This ensures your app gets notified immediately even if the user isn’t actively using it.
- Avoid Purchase History:
queryPurchaseHistoryAsynconly returns the most recent purchase for each SKU - usequeryPurchasesAsyncfor the current active status.
4. Edge Case Handling
The 1% of users are likely hitting edge cases the old service didn’t handle well. Make sure you cover these:
- Refunds & Chargebacks: The library will return purchases with
Purchase.PurchaseState.REFUNDEDorCANCELLED- revoke access immediately when you detect these. - Auto-Renewal Failures: If a user’s payment method fails for auto-renewal, Google Play will retry, but eventually cancel the subscription. Use RTDN to get notified of these events quickly.
- Account Switching: If a user switches Google accounts on their device,
queryPurchasesAsyncwill return purchases for the current account - make sure your app handles account changes gracefully (e.g., prompt the user to log back into their subscribed account).
5. Debugging the 1%
To pinpoint why those users are having issues:
- Add detailed logging for all billing events: setup results, purchase updates, query responses, and error codes.
- Ask affected users to share their app logs (with consent) or use a crash reporting tool to collect billing-related events.
- Check Google Play Console’s Subscription Analytics and Order Management to see if those users’ orders have any unusual statuses (e.g., pending, held, or refunded).
Migrating to the Play Billing Library should drastically reduce those edge case failures, since it’s designed to handle the messy parts of billing that the old service left up to you. Take it step by step, test with sandbox accounts first, and make sure you’re covering all the status scenarios.
内容的提问来源于stack exchange,提问作者Anton

