Search code examples
androidhuawei-mobile-serviceshuawei-developers

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


I am using Huawei In App Purchase in my application. The problem is when the user makes multiple requests (lets say around 5) to IapClient in short time (lets say around 2 sec) then my application throws an error

My log is below :

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$1.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)

Is there any limitation on number/frequency of IAP calls? What is your advice in such situation?


Solution

  • Error Code -1 means you are advised to use the obtainOwnedPurchases API to check whether the user has purchased the product.

    Solution: Use the obtainOwnedPurchases API to check whether the user has purchased the product.

    For a consumable that has been purchased, call the consumeOwnedPurchase API to consume the product after it is delivered. After being consumed, the product can be purchased next time. If the product is a non-consumable product or a subscription, the product cannot be purchased again.

    Queries information about all purchased in-app products, including consumables, non-consumables, and auto-renewable subscriptions.

    If the information about consumables is returned, the consumables might not be delivered due to some exceptions. In this case, your app needs to check whether the consumables are delivered. If not, the app needs to deliver them and calls the consumeOwnedPurchase API to consume them. If the information about non-consumables is returned, the non-consumables do not need to be consumed. If the information about subscriptions is returned, all existing subscription relationships of the user in the app are returned.

    If purchaseState is 0 that means product is PURCHASED.

    If purchaseState is 1 that means product is CANCELED.

    If purchaseState is 2 that means product is PURCHASED.

    Code:

    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
                }
            }
        });
    }
    

    For More Information you can visit these links:

    In-App Purchase Article:

    Client Side: https://forums.developer.huawei.com/forumPortal/en/topicview?tid=0201255229704010231&fid=0101187876626530001

    Server Side: https://forums.developer.huawei.com/forumPortal/en/topicview?tid=0201273064244120101&fid=0101187876626530001

    In-App Purchase Github Link:

    Client Side: https://github.com/DTSE-India-Community/HMS-In-App-Purchase-Kit

    Server Side: https://github.com/DTSE-India-Community/Huawei-In-App-Purchase-And-Push-Kit-Server_Side-Implementation