android - Google Play 计费库 - querySkuDetailsAsync 偶尔会返回 BillingResponseCode.ERROR (6)

标签 android response in-app-billing android-inapp-purchase play-billing-library

我正在使用 Google Play 计费库 2.0.3 ( implementation 'com.android.billingclient:billing:2.0.3' ) 并且它在大多数情况下都可以正常工作,但对于某些用户来说,原因不明,querySkuDetailsAsync() method occasionally fails with BillingResponseCode.ERROR (6) error code...
有人知道吗?这个错误的原因没有在任何地方解释,除了它是“API操作期间的 fatal error ”。谁能告诉它为什么会发生?

编辑:
我正在使用文档中的方法(https://developer.android.com/google/play/billing/billing_library_overview):

public interface QuerySkuDetailsListener {
        void onSuccess(List<SkuDetails> skuDetailsList);

        void onErrorProductsHaveDifferentTypes();

        void onBillingClientError(int error_code);
    }

    public void querySkuDetails(final QuerySkuDetailsListener querySkuDetailsListener, final Product... products) {
        if (products.length < 1) {
            //ERROR_NO_PRODUCTS_TO_QUERY
            throw new NullPointerException();
        }

        String querySkuType = products[0].getSkuType();

        SkuDetailsParams.Builder params = SkuDetailsParams.newBuilder();
        List<String> skuList = new ArrayList<>();
        for (Product product : products) {
            skuList.add(product.getSku());
            if (!product.getSkuType().equals(querySkuType)) {
                //ERROR_SKU_TYPE_CANT_BE_DIFFERENT
                querySkuDetailsListener.onErrorProductsHaveDifferentTypes();
                return;
            }
        }
        params.setSkusList(skuList).setType(querySkuType);

        billingClient.querySkuDetailsAsync(params.build(), new SkuDetailsResponseListener() {
            @Override
            public void onSkuDetailsResponse(BillingResult billingResult, List<SkuDetails> skuDetailsList) {
                if (billingResult.getResponseCode() == BillingClient.BillingResponseCode.OK && skuDetailsList != null) {
                    querySkuDetailsListener.onSuccess(skuDetailsList);
                }
                else {
                    //ERROR QUERYING SKU DETAILS
                    querySkuDetailsListener.onBillingClientError(billingResult.getResponseCode());
                }
            }
        });
    }

然后我像这样使用它:
        private void initiatePurchaseFlow(final Activity activity, @Nullable final Product oldProduct, final Product product, final JsonObject metadata, final InitiatePurchaseListener initiatePurchaseListener) {

                //Check if billingClient is ready
                if (billingClient.isReady()) {
                    querySkuDetails(new QuerySkuDetailsListener() {
                            @Override
                            public void onSuccess(List<SkuDetails> skuDetailsList) {
                                // Process the result.
                                BillingFlowParams.Builder flowParamsBuilder = BillingFlowParams.newBuilder();
                                flowParamsBuilder.setSkuDetails(skuDetailsList.get(0));
                                if (null != oldProduct) {
                                    flowParamsBuilder.setOldSku(oldProduct.getSku());
                                    flowParamsBuilder.setReplaceSkusProrationMode(BillingFlowParams.ProrationMode.IMMEDIATE_WITH_TIME_PRORATION);
                                }
                                BillingFlowParams flowParams = flowParamsBuilder.build();
                                int responseCode = billingClient.launchBillingFlow(activity, flowParams).getResponseCode();
                                if (responseCode == BillingClient.BillingResponseCode.OK) {
                                    //SUCCESS, OK
                                    ...Rest of the irrelevant code...
                                }
                                else {
                                    //ERROR_IN_LAUNCHING_BILLING_FLOW
                                    dispenseInitiatePurchaseFlowError(activity, initiatePurchaseListener, InitiatePurchaseErrorCodes.ERROR_IN_LAUNCHING_BILLING_FLOW, getBillingClientErrorDescription(responseCode));
                                }
                            }

                            @Override
                            public void onErrorProductsHaveDifferentTypes() {
                                //ERROR_IN_QUERYING_SKU_DETAILS_PRODUCTS_HAVE_DIFFERENT_TYPES
                                dispenseInitiatePurchaseFlowError(activity, initiatePurchaseListener, InitiatePurchaseErrorCodes.ERROR_IN_QUERYING_SKU_DETAILS_PRODUCTS_HAVE_DIFFERENT_TYPES, getBillingClientErrorDescription(0));
                            }

                            @Override
                            public void onBillingClientError(int error_code) {
                                //ERROR_IN_QUERYING_SKU_DETAILS
                                dispenseInitiatePurchaseFlowError(activity, initiatePurchaseListener, InitiatePurchaseErrorCodes.ERROR_IN_QUERYING_SKU_DETAILS, getBillingClientErrorDescription(error_code));
                            }
                        }, product);
                }
                else {
                    //ERROR_BILLING_CLIENT_IS_NOT_READY
                    //Trying to reconnect once          
                    billingClient.startConnection(new BillingClientStateListener() {
                        @Override
                        public void onBillingSetupFinished(BillingResult billingResult) {
                            if (billingResult.getResponseCode() == BillingResponse.OK) {
                                //launching again
                                initiatePurchaseFlow(activity, oldProduct, product, metadata, initiatePurchaseListener);
                            }
                            else {
                            // showing an error dialog
                            dispenseInitiatePurchaseFlowError(activity, initiatePurchaseListener, InitiatePurchaseErrorCodes.ERROR_BILLING_CLIENT_IS_NOT_READY, getBillingClientErrorDescription(billingResult.getResponseCode()));
                            }
                        }
                        @Override
                        public void onBillingServiceDisconnected() {
                            // showing an error dialog
                        }
                    });
                }
            }

编辑:
用户可以简单地作弊吗?例如使用破解的谷歌游戏商店/其他会影响购买的软件?因为无论我做什么,我都没有在我拥有的任何设备上收到此错误。

编辑:
到目前为止,我发现 onPurchasesUpdated(BillingResult billingResult, @Nullable List<Purchase> purchases)如果您使用幸运补丁破解应用程序,计费客户端的方法会返回此错误代码 (BillingResponseCode.ERROR),但我在 querySkuDetailsAsync() 中没有收到任何错误……这有关系吗?

编辑:
此外,我在 google issuetracker 中创建了一个问题,如果您愿意,请到那里支持我。 https://issuetracker.google.com/issues/139631105

最佳答案

为了将来引用和其他一些遭受此困扰的人(例如 IAB 3.0.1 中的我),OP 打开的问题跟踪器错误中的某个人发表了评论,如果我们收到此代码,我们应该如何 react

Error 6 (https://developer.android.com/reference/com/android/billingclient/api/BillingClient.BillingResponseCode#error) usually represents a transient error from our backend servers. This error code should trigger a retry which in most cases should succeed.


链接:https://issuetracker.google.com/issues/139631105#comment11
示例代码:
@Override
public void onSkuDetailsResponse(@NonNull BillingResult billingResult, @Nullable List<SkuDetails> list) {
    Utils.log("BILLING: onSkuDetailsResponse(). Result (" + billingResult.getResponseCode() + ") List size: " + (list == null ? "null" : list.size()));
    if (billingResult.getResponseCode() == BillingClient.BillingResponseCode.OK && list != null) {
        if (mSkuQueryErrorCounter > 0) mSkuQueryErrorCounter--;
        // process the SkuDetail list...
        }
    } else {
        // https://issuetracker.google.com/issues/139631105#comment11
        mSkuQueryErrorCounter++;
        if (mSkuQueryErrorCounter <= 2) scheduleUpdate(NOW);
        else if (mSkuQueryErrorCounter < 5) scheduleUpdate(TEN_SECONDS);
        else if (mSkuQueryErrorCounter < 10) scheduleUpdate(ONE_HOUR);
        else scheduleUpdate(ONE_DAY);
    }
}

关于android - Google Play 计费库 - querySkuDetailsAsync 偶尔会返回 BillingResponseCode.ERROR (6),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57550575/

相关文章:

android - 如何从 json 数组访问单个 json 对象?

php - 如何访问 POSTMAN 正文中的响应

ruby-on-rails - 如何摆脱Rails中响应头上的字符集

android - startIntentSenderForResult 处的 NullPointer,inappbilling V3

android - 如何在应用内计费应用程序android中调用getpurchase方法?

android - 在 iphone 或 android 上检测触摸形状?

android - 重用 HttpURLConnection 以保持 session Activity

Android Studio : Facebook show.(内容)不工作

java - JSON 数据的 Ajax 响应

android - 用于应用内订阅收据检查的 Google Developer API(权限不足问题)