华为In App Purchase:短时间内执行多个请求导致错误

Huawei In App Purchase : Performing multiple requests in short time leads to an error

我在我的应用程序中使用了华为应用内购买。问题是当用户在短时间内(假设大约 2 秒)向 IapClient 发出多个请求(假设大约 5 个)然后我的应用程序抛出错误

我的日志如下:

com.huawei.hms.iap.IapApiException: -1: Core error
   at com.huawei.hms.iap.f.doExecute(IsEnvReadyTaskApiCall.java:1068)
   at com.huawei.hms.common.internal.TaskApiCall.onResponse(TaskApiCall.java:190)
   at com.huawei.hms.common.internal.HuaweiApiManager$ConnectionManager.onCallback(HuaweiApiManager.java:272)
   at com.huawei.hms.common.internal.HmsClient$a.onError(HmsClient.java:134)
   at com.huawei.hms.adapter.BaseAdapter$BaseRequestResultCallback.onResult(BaseAdapter.java:205)
   at com.huawei.hms.adapter.BaseAdapter$BaseRequestResultCallback.onResult(BaseAdapter.java:175)
   at com.huawei.hms.support.api.PendingResultImpl$a.b(PendingResultImpl.java:490)
   at com.huawei.hms.support.api.PendingResultImpl$a.handleMessage(PendingResultImpl.java:467)
   at android.os.Handler.dispatchMessage(Handler.java:110)
   at android.os.Looper.loop(Looper.java:219)
   at android.app.ActivityThread.main(ActivityThread.java:8347)
   at java.lang.reflect.Method.invoke(Native Method)
   at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:513)
   at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1055)

IAP 调用的 number/frequency 有什么限制吗?在这种情况下你有什么建议?

您得到的错误代码是-1 在官方文档中,解决方案描述为

If this error code is returned during the purchase request, you are advised to use the obtainOwnedPurchases API to check whether the user has purchased the product.

文档:https://developer.huawei.com/consumer/en/doc/development/HMS-References/iap-ExceptionHandlingAndGeneralErrorCodes-v4

IAP服务中的网络请求采用异步方式处理。

从检查服务是否可用到完成交易的过程都是按步骤进行的。这些步骤必须按顺序执行。每个步骤都包含异常处理。

如果一个步骤出现异常,没有处理,则无法进行下一步。我的建议是遵循购买流程并仔细处理每个步骤的结果以完成交易并确保良好的用户体验。

请致电

isEnvReady()

确保 IAP 环境已准备好在您每次购买东西时进行购买的任务。

错误代码-1表示建议您使用obtainOwnedPurchasesAPI查询用户是否购买了商品。

解决方法:使用obtainOwnedPurchasesAPI查询用户是否购买了商品

已购买的消耗品,发货后调用consumeOwnedPurchaseAPI消耗商品。消费后,下次可以购买该产品。如果产品是非消耗品或订阅产品,则无法再次购买该产品。

查询所有已购买的应用内商品信息,包括消耗品、非消耗品和自动续订订阅。

如果返回耗材信息,可能是因为某些异常导致耗材无法发货。在这种情况下,您的应用需要检查耗材是否送达。如果没有,应用程序需要交付它们并调用 consumeOwnedPurchase API 来消费它们。 如果返回非消耗品信息,则表示该非消耗品不需要消耗。 如果返回订阅信息,则返回该用户在应用内已有的所有订阅关系。

如果 purchaseState 是 0,这意味着产品是 PURCHASED.

如果 purchaseState 是 1 那意味着产品是 CANCELED.

如果 purchaseState 是 2 这意味着产品是 PURCHASED.

代码:

public void checkUserOwnedTheProduct(final Context context) {
    OwnedPurchasesReq ownedPurchasesReq = new OwnedPurchasesReq();
    ownedPurchasesReq.setPriceType(productType);
    Task<OwnedPurchasesResult> task = Iap.getIapClient(context).obtainOwnedPurchases(ownedPurchasesReq);
    task.addOnSuccessListener(new OnSuccessListener<OwnedPurchasesResult>() {
        @Override
        public void onSuccess(OwnedPurchasesResult result) {
            // Obtain the execution result.
            if (result != null && result.getInAppPurchaseDataList() != null) {
                for (int i = 0; i < result.getInAppPurchaseDataList().size(); i++) {
                    String inAppPurchaseData = result.getInAppPurchaseDataList().get(i);
                    String inAppSignature = result.getInAppSignature().get(i);
                    boolean success = CipherUtil.doCheck(inAppPurchaseData, inAppSignature, Key.getPublicKey());
                    if (success) {
                        try {
                            InAppPurchaseData inAppPurchaseDataBean = new InAppPurchaseData(inAppPurchaseData);
                            int purchaseState = inAppPurchaseDataBean.getPurchaseState();                            

                        } catch (JSONException e) {
                        }
                    }
                }
            } else {
                if (productType == IapClient.PriceType.IN_APP_NONCONSUMABLE) {
                    ((HmsInAppPurchaseList) context).loadList();
                    return;
                }
            }
        }
    }).addOnFailureListener(new OnFailureListener() {
        @Override
        public void onFailure(Exception e) {
            if (e instanceof IapApiException) {
                IapApiException apiException = (IapApiException) e;
                Status status = apiException.getStatus();
                int returnCode = apiException.getStatusCode();
            } else {
                // Other external errors
            }
        }
    });
}

有关更多信息,您可以访问这些链接:

应用内购买文章:

客户端: https://forums.developer.huawei.com/forumPortal/en/topicview?tid=0201255229704010231&fid=0101187876626530001

服务器端: https://forums.developer.huawei.com/forumPortal/en/topicview?tid=0201273064244120101&fid=0101187876626530001

应用内购买 Github Link:

客户端: https://github.com/DTSE-India-Community/HMS-In-App-Purchase-Kit

服务器端: https://github.com/DTSE-India-Community/Huawei-In-App-Purchase-And-Push-Kit-Server_Side-Implementation