You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Play Billing 1.0:如何知晓订阅已取消?未实现queryPurchases是否有影响?

Troubleshooting Subscription Cancellation Detection in Play Billing Library

Hey there! Let's dig into your problem and fix that subscription cancellation detection gap.

Short Answer: Yes, Missing queryPurchases Implementation Is Likely the Root Cause

The Play Billing Library doesn’t automatically push subscription status changes (like cancellations, expirations, or refunds) to your app. You need to actively fetch the latest purchase state, and the queryPurchases (or its modern async counterpart) is the core method for doing this. Without it, your app has no way to check if a user canceled their subscription after the initial purchase.

Step-by-Step Fixes

The old queryPurchases method is deprecated, so use queryPurchasesAsync for subscriptions in your BillingManager.java. This will fetch all active and inactive subscriptions tied to the user's account:

private static final String TAG = "BillingManager";

public void fetchCurrentSubscriptions() {
    if (!billingClient.isReady()) {
        Log.w(TAG, "BillingClient isn't ready yet—wait for initialization first!");
        return;
    }

    QueryPurchasesParams params = QueryPurchasesParams.newBuilder()
            .setProductType(BillingClient.SkuType.SUBS)
            .build();

    billingClient.queryPurchasesAsync(params, new PurchasesResponseListener() {
        @Override
        public void onQueryPurchasesResponse(BillingResult billingResult, List<Purchase> purchases) {
            if (billingResult.getResponseCode() == BillingClient.BillingResponseCode.OK) {
                updateSubscriptionStatus(purchases);
            } else {
                Log.e(TAG, "Failed to fetch subscriptions: " + billingResult.getDebugMessage());
            }
        }
    });
}

// Helper method to process subscription states
private void updateSubscriptionStatus(List<Purchase> purchases) {
    for (Purchase purchase : purchases) {
        // Check if auto-renew is disabled (user canceled subscription)
        boolean isSubscriptionCanceled = !purchase.isAutoRenewing();
        // Check purchase state (PURCHASED = active, PENDING = waiting for payment, etc.)
        int purchaseState = purchase.getPurchaseState();

        if (isSubscriptionCanceled) {
            // Handle cancellation logic here (e.g., update UI, restrict premium features)
            Log.i(TAG, "User canceled subscription for SKU: " + purchase.getSkus().get(0));
        } else if (purchaseState == Purchase.PurchaseState.PURCHASED) {
            // Subscription is active
            Log.i(TAG, "Active subscription for SKU: " + purchase.getSkus().get(0));
        }
    }
}

2. Add Real-Time Purchase Update Listener

Catch immediate subscription changes (like when a user cancels via Google Play while your app is open) by setting a PurchasesUpdatedListener when initializing the BillingClient:

billingClient = BillingClient.newBuilder(context)
        .setListener(new PurchasesUpdatedListener() {
            @Override
            public void onPurchasesUpdated(BillingResult billingResult, List<Purchase> purchases) {
                if (billingResult.getResponseCode() == BillingClient.BillingResponseCode.OK && purchases != null) {
                    updateSubscriptionStatus(purchases);
                } else if (billingResult.getResponseCode() == BillingClient.BillingResponseCode.USER_CANCELED) {
                    // Note: This only means the user canceled the current purchase flow, not their existing subscription
                    Log.i(TAG, "User exited the purchase flow");
                } else {
                    Log.e(TAG, "Purchase update error: " + billingResult.getDebugMessage());
                }
            }
        })
        .enablePendingPurchases() // Required for handling pending payments
        .build();

3. Schedule Regular Subscription Checks

Since some status changes (like subscription expiration) won't trigger a real-time callback, schedule periodic calls to fetchCurrentSubscriptions():

  • Call it when your app starts up
  • Set a daily background task (using WorkManager, for example) to refresh the status

4. Validate Subscriptions on Your Backend (Optional but Critical for Security)

To prevent client-side tampering, send the purchase.getPurchaseToken() to your backend server. Use the Google Play Developer API's subscription verification endpoint to confirm the true subscription status (including cancellation date, expiration time, and auto-renew status). This is the most reliable way to confirm subscription state.

Final Notes

Once you implement the queryPurchasesAsync flow and combine it with real-time listening and periodic checks, your app will accurately detect when a user cancels their subscription. Don't forget to test edge cases, like users canceling and then resubscribing, to ensure your logic handles all scenarios correctly.

内容的提问来源于stack exchange,提问作者CJara

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.21 08:25:17