Gilli Danda v1.1.5版本的 MD5 值为:bcf5cb835fbff288fa65b9651dd21e30

以下内容为反编译后的 IabHelper.java 源代码,内容仅作参考


package com.unity.purchasing.googleplay;

import android.app.Activity;
import android.app.PendingIntent;
import android.content.Context;
import android.content.Intent;
import android.content.IntentSender;
import android.os.Bundle;
import android.os.Handler;
import android.os.Looper;
import android.os.RemoteException;
import android.text.TextUtils;
import android.util.Log;
import com.android.vending.billing.IInAppBillingService;
import com.google.vr.ndk.base.DaydreamApi;
import com.unity.purchasing.common.SaneJSONObject;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import org.json.JSONException;

public class IabHelper {
    public static final int BILLING_RESPONSE_RESULT_BILLING_UNAVAILABLE = 3;
    public static final int BILLING_RESPONSE_RESULT_DEVELOPER_ERROR = 5;
    public static final int BILLING_RESPONSE_RESULT_ERROR = 6;
    public static final int BILLING_RESPONSE_RESULT_ITEM_ALREADY_OWNED = 7;
    public static final int BILLING_RESPONSE_RESULT_ITEM_NOT_OWNED = 8;
    public static final int BILLING_RESPONSE_RESULT_ITEM_UNAVAILABLE = 4;
    public static final int BILLING_RESPONSE_RESULT_OK = 0;
    public static final int BILLING_RESPONSE_RESULT_SERVICE_UNAVAILABLE = 2;
    public static final int BILLING_RESPONSE_RESULT_USER_CANCELED = 1;
    public static final String GET_SKU_DETAILS_ITEM_LIST = "ITEM_ID_LIST";
    public static final String GET_SKU_DETAILS_ITEM_TYPE_LIST = "ITEM_TYPE_LIST";
    public static final int IABHELPER_BAD_RESPONSE = -1002;
    public static final int IABHELPER_ERROR_BASE = -1000;
    public static final int IABHELPER_INVALID_CONSUMPTION = -1010;
    public static final int IABHELPER_MISSING_TOKEN = -1007;
    public static final int IABHELPER_REMOTE_EXCEPTION = -1001;
    public static final int IABHELPER_SEND_INTENT_FAILED = -1004;
    public static final int IABHELPER_SUBSCRIPTIONS_NOT_AVAILABLE = -1009;
    public static final int IABHELPER_UNKNOWN_ERROR = -1008;
    public static final int IABHELPER_UNKNOWN_PURCHASE_RESPONSE = -1006;
    public static final int IABHELPER_USER_CANCELLED = -1005;
    public static final int IABHELPER_VERIFICATION_FAILED = -1003;
    public static final String INAPP_CONTINUATION_TOKEN = "INAPP_CONTINUATION_TOKEN";
    public static final String ITEM_TYPE_INAPP = "inapp";
    public static final String ITEM_TYPE_SUBS = "subs";
    public static final String RESPONSE_BUY_INTENT = "BUY_INTENT";
    public static final String RESPONSE_CODE = "RESPONSE_CODE";
    public static final String RESPONSE_GET_SKU_DETAILS_LIST = "DETAILS_LIST";
    public static final String RESPONSE_INAPP_ITEM_LIST = "INAPP_PURCHASE_ITEM_LIST";
    public static final String RESPONSE_INAPP_PURCHASE_DATA = "INAPP_PURCHASE_DATA";
    public static final String RESPONSE_INAPP_PURCHASE_DATA_LIST = "INAPP_PURCHASE_DATA_LIST";
    public static final String RESPONSE_INAPP_SIGNATURE = "INAPP_DATA_SIGNATURE";
    public static final String RESPONSE_INAPP_SIGNATURE_LIST = "INAPP_DATA_SIGNATURE_LIST";
    public static HashMap<Integer, String> billingResponseCodeNames = new HashMap<>();
    private IActivityLauncher launcher;
    Context mContext;
    OnIabPurchaseFinishedListener mPurchaseListener;
    String mPurchasingItemType;
    int mRequestCode;
    private IBillingServiceManager serviceManager;
    boolean mDebugLog = false;
    String mDebugTag = "IabHelper";
    volatile boolean mSetupDone = false;
    volatile boolean mDisposed = false;
    boolean mSubscriptionsSupported = false;
    boolean mSubscriptionPurchaseHistorySupported = false;
    private boolean mVrSupported = false;
    private boolean mUnityVrEnabled = false;
    private boolean mDaydreamApiAvailable = false;
    String mAsyncOperation = "";
    private Inventory inv = new Inventory();

    public interface OnConsumeFinishedListener {
        void onConsumeFinished(Purchase purchase, IabResult iabResult) throws JSONException;
    }

    public interface OnConsumeMultiFinishedListener {
        void onConsumeMultiFinished(List<Purchase> list, List<IabResult> list2);
    }

    public interface OnIabPurchaseFinishedListener {
        void onIabPurchaseFinished(IabResult iabResult, Purchase purchase);
    }

    public interface OnIabSetupFinishedListener {
        void onIabSetupFinished(IabResult iabResult);
    }

    public interface QueryInventoryFinishedListener {
        void onQueryInventoryFinished(IabResult iabResult, Inventory inventory) throws Exception;
    }

    static {
        billingResponseCodeNames.put(0, "BILLING_RESPONSE_RESULT_OK");
        billingResponseCodeNames.put(1, "BILLING_RESPONSE_RESULT_USER_CANCELED");
        billingResponseCodeNames.put(2, "BILLING_RESPONSE_RESULT_SERVICE_UNAVAILABLE");
        billingResponseCodeNames.put(3, "BILLING_RESPONSE_RESULT_BILLING_UNAVAILABLE");
        billingResponseCodeNames.put(4, "BILLING_RESPONSE_RESULT_ITEM_UNAVAILABLE");
        billingResponseCodeNames.put(5, "BILLING_RESPONSE_RESULT_DEVELOPER_ERROR");
        billingResponseCodeNames.put(6, "BILLING_RESPONSE_RESULT_ERROR");
        billingResponseCodeNames.put(7, "BILLING_RESPONSE_RESULT_ITEM_ALREADY_OWNED");
        billingResponseCodeNames.put(8, "BILLING_RESPONSE_RESULT_ITEM_NOT_OWNED");
        billingResponseCodeNames.put(-1000, "IABHELPER_ERROR_BASE");
        billingResponseCodeNames.put(Integer.valueOf(IABHELPER_REMOTE_EXCEPTION), "IABHELPER_REMOTE_EXCEPTION");
        billingResponseCodeNames.put(Integer.valueOf(IABHELPER_BAD_RESPONSE), "IABHELPER_BAD_RESPONSE");
        billingResponseCodeNames.put(Integer.valueOf(IABHELPER_VERIFICATION_FAILED), "IABHELPER_VERIFICATION_FAILED");
        billingResponseCodeNames.put(Integer.valueOf(IABHELPER_SEND_INTENT_FAILED), "IABHELPER_SEND_INTENT_FAILED");
        billingResponseCodeNames.put(Integer.valueOf(IABHELPER_USER_CANCELLED), "IABHELPER_USER_CANCELLED");
        billingResponseCodeNames.put(Integer.valueOf(IABHELPER_UNKNOWN_PURCHASE_RESPONSE), "IABHELPER_UNKNOWN_PURCHASE_RESPONSE");
        billingResponseCodeNames.put(Integer.valueOf(IABHELPER_MISSING_TOKEN), "IABHELPER_MISSING_TOKEN");
        billingResponseCodeNames.put(Integer.valueOf(IABHELPER_UNKNOWN_ERROR), "IABHELPER_UNKNOWN_ERROR");
        billingResponseCodeNames.put(Integer.valueOf(IABHELPER_SUBSCRIPTIONS_NOT_AVAILABLE), "IABHELPER_SUBSCRIPTIONS_NOT_AVAILABLE");
        billingResponseCodeNames.put(Integer.valueOf(IABHELPER_INVALID_CONSUMPTION), "IABHELPER_INVALID_CONSUMPTION");
    }

    public IabHelper(Context ctx, IBillingServiceManager manager, IActivityLauncher launcher) {
        this.mContext = ctx.getApplicationContext();
        this.serviceManager = manager;
        this.launcher = launcher;
        logDebug("IAB helper created.");
    }

    public void enableDebugLogging(boolean enable, String tag) {
        this.mDebugLog = enable;
        this.mDebugTag = tag;
    }

    public void enableDebugLogging(boolean enable) {
        this.mDebugLog = enable;
    }

    public void enableUnityVr(boolean enabled) {
        this.mUnityVrEnabled = enabled;
    }

    public void enableDaydreamApi(boolean enabled) {
        this.mDaydreamApiAvailable = enabled;
    }

    public void startSetup(final OnIabSetupFinishedListener listener) {
        if (this.mSetupDone) {
            throw new IllegalStateException("IAB helper is already set up.");
        }
        logDebug("Starting in-app billing setup.");
        this.serviceManager.workWith(new BillingServiceProcessor() {
            @Override
            public void workWith(IInAppBillingService service) {
                IabHelper.this.finishSetup(listener, service);
            }
        });
    }

    public void finishSetup(OnIabSetupFinishedListener listener, IInAppBillingService service) {
        String packageName = this.mContext.getPackageName();
        try {
            logDebug("Checking for in-app billing 3 support.");
            int response = service.isBillingSupported(3, packageName, "inapp");
            if (response != 0) {
                listener.onIabSetupFinished(new IabResult(response, "Billing V3 not supported."));
                this.mSubscriptionsSupported = false;
                return;
            }
            logDebug("In-app billing version 3 supported for " + packageName);
            int response2 = service.isBillingSupported(3, packageName, "subs");
            if (response2 == 0) {
                logDebug("Subscriptions AVAILABLE.");
                this.mSubscriptionsSupported = true;
                int response_v6 = service.isBillingSupported(6, packageName, "subs");
                if (response_v6 == 0) {
                    this.mSubscriptionPurchaseHistorySupported = true;
                    logDebug("Subscriptions information parse AVAILABLE.");
                } else {
                    logDebug("Subscriptions information parse NOT AVAILABLE.");
                }
            } else {
                logDebug("Subscriptions NOT AVAILABLE. Response: " + response2);
            }
            Bundle bundle = new Bundle();
            bundle.putBoolean("vr", true);
            int response3 = service.isBillingSupportedExtraParams(7, this.mContext.getPackageName(), "inapp", bundle);
            if (response3 == 0) {
                logDebug("VR supported.");
                this.mVrSupported = true;
            } else {
                logDebug("VR purchases  NOT AVAILABLE. Response: " + response3);
            }
            this.mSetupDone = true;
            listener.onIabSetupFinished(new IabResult(0, "Setup successful."));
        } catch (RemoteException e) {
            listener.onIabSetupFinished(new IabResult(IABHELPER_REMOTE_EXCEPTION, "RemoteException while setting up in-app billing."));
        }
    }

    public void dispose() {
        logDebug("Disposing.");
        this.mSetupDone = false;
        this.serviceManager.dispose();
        this.mDisposed = true;
    }

    public boolean subscriptionsSupported() {
        return this.mSubscriptionsSupported;
    }

    public boolean subscriptionPurchaseHistorySupported() {
        return this.mSubscriptionPurchaseHistorySupported;
    }

    public void launchPurchaseFlow(Activity act, String sku, int requestCode, OnIabPurchaseFinishedListener listener) {
        launchPurchaseFlow(act, sku, requestCode, listener, "");
    }

    public void launchPurchaseFlow(Activity act, String sku, int requestCode, OnIabPurchaseFinishedListener listener, String extraData) {
        launchPurchaseFlow(act, sku, "inapp", requestCode, listener, extraData);
    }

    public void launchSubscriptionPurchaseFlow(Activity act, String sku, int requestCode, OnIabPurchaseFinishedListener listener) {
        launchSubscriptionPurchaseFlow(act, sku, requestCode, listener, "");
    }

    public void launchSubscriptionPurchaseFlow(Activity act, String sku, int requestCode, OnIabPurchaseFinishedListener listener, String extraData) {
        launchPurchaseFlow(act, sku, "subs", requestCode, listener, extraData);
    }

    public void launchPurchaseFlow(final Activity act, final String sku, final String itemType, final int requestCode, final OnIabPurchaseFinishedListener listener, final String extraData) {
        checkSetupDone("launchPurchaseFlow");
        if (itemType.equals("subs") && !this.mSubscriptionsSupported) {
            IabResult r = new IabResult(IABHELPER_SUBSCRIPTIONS_NOT_AVAILABLE, "Subscriptions are not available.");
            if (listener != null) {
                listener.onIabPurchaseFinished(r, null);
                return;
            }
            return;
        }
        this.serviceManager.workWith(new BillingServiceProcessor() {
            @Override
            public void workWith(IInAppBillingService service) {
                Bundle buyIntentBundle;
                Purchase purchase;
                try {
                    IabHelper.this.logDebug("Constructing buy intent for " + sku + ", item type: " + itemType);
                    if (IabHelper.this.mVrSupported && IabHelper.this.mUnityVrEnabled) {
                        Bundle bundle = new Bundle();
                        bundle.putBoolean("vr", true);
                        IabHelper.this.logDebug("Initiating VR purchase intent");
                        buyIntentBundle = service.getBuyIntentExtraParams(7, IabHelper.this.mContext.getPackageName(), sku, itemType, extraData, bundle);
                    } else {
                        buyIntentBundle = service.getBuyIntent(3, IabHelper.this.mContext.getPackageName(), sku, itemType, extraData);
                    }
                    int response = IabHelper.this.getResponseCodeFromBundle(buyIntentBundle);
                    if (response != 0) {
                        IabHelper.this.logError("Unable to buy item, Error response: " + IabHelper.getResponseDesc(response));
                        IabResult result = new IabResult(response, "Unable to buy item");
                        SaneJSONObject o = new SaneJSONObject();
                        o.put("productId", sku);
                        if (response == 7) {
                            try {
                                if (IabHelper.this.inv.hasPurchase(sku)) {
                                    purchase = IabHelper.this.inv.getPurchase(sku);
                                    act.finish();
                                    if (listener == null) {
                                        listener.onIabPurchaseFinished(result, purchase);
                                        return;
                                    }
                                    return;
                                }
                            } catch (JSONException e) {
                                e.printStackTrace();
                                return;
                            }
                        }
                        purchase = new Purchase(itemType, o.toString(), "");
                        act.finish();
                        if (listener == null) {
                        }
                    } else {
                        final PendingIntent pendingIntent = (PendingIntent) buyIntentBundle.getParcelable(IabHelper.RESPONSE_BUY_INTENT);
                        IabHelper.this.logDebug("Launching buy intent for " + sku + ". Request code: " + requestCode);
                        IabHelper.this.mRequestCode = requestCode;
                        IabHelper.this.mPurchaseListener = listener;
                        IabHelper.this.mPurchasingItemType = itemType;
                        if (IabHelper.this.mVrSupported && IabHelper.this.mUnityVrEnabled && IabHelper.this.mDaydreamApiAvailable) {
                            Runnable task = new Runnable() {
                                @Override
                                public void run() {
                                    DaydreamApi api = DaydreamApi.create(act);
                                    api.launchInVrForResult(act, pendingIntent, requestCode);
                                    api.close();
                                }
                            };
                            new Handler(Looper.getMainLooper()).post(task);
                        } else {
                            pendingIntent.getIntentSender();
                            IabHelper.this.launcher.startIntentSenderForResult(act, pendingIntent, requestCode, new Intent(), sku);
                        }
                    }
                } catch (IntentSender.SendIntentException e2) {
                    IabHelper.this.logError("SendIntentException while launching purchase flow for sku " + sku);
                    e2.printStackTrace();
                    IabResult result2 = new IabResult(IabHelper.IABHELPER_SEND_INTENT_FAILED, "Failed to send intent.");
                    if (listener != null) {
                        listener.onIabPurchaseFinished(result2, null);
                    }
                } catch (RemoteException e3) {
                    IabHelper.this.logError("RemoteException while launching purchase flow for sku " + sku);
                    e3.printStackTrace();
                    IabResult result3 = new IabResult(IabHelper.IABHELPER_REMOTE_EXCEPTION, "Remote exception while starting purchase flow");
                    if (listener != null) {
                        listener.onIabPurchaseFinished(result3, null);
                    }
                }
            }
        });
    }

    public boolean handleActivityResult(int requestCode, int resultCode, Intent data) {
        if (requestCode != this.mRequestCode) {
            return false;
        }
        checkSetupDone("handleActivityResult");
        if (data == null) {
            logError("Null data in IAB activity result.");
            IabResult result = new IabResult(IABHELPER_BAD_RESPONSE, "Null data in IAB result");
            if (this.mPurchaseListener != null) {
                this.mPurchaseListener.onIabPurchaseFinished(result, null);
            }
            return true;
        }
        int responseCode = getResponseCodeFromIntent(data);
        String purchaseData = data.getStringExtra(RESPONSE_INAPP_PURCHASE_DATA);
        String dataSignature = data.getStringExtra(RESPONSE_INAPP_SIGNATURE);
        if (resultCode == -1 && responseCode == 0) {
            logDebug("Successful resultcode from purchase activity.");
            logDebug("Purchase data: " + purchaseData);
            logDebug("Data signature: " + dataSignature);
            logDebug("Extras: " + data.getExtras());
            logDebug("Expected item type: " + this.mPurchasingItemType);
            if (purchaseData == null || dataSignature == null) {
                logError("BUG: either purchaseData or dataSignature is null.");
                logDebug("Extras: " + data.getExtras().toString());
                IabResult result2 = new IabResult(IABHELPER_UNKNOWN_ERROR, "IAB returned null purchaseData or dataSignature");
                if (this.mPurchaseListener != null) {
                    this.mPurchaseListener.onIabPurchaseFinished(result2, null);
                }
                return true;
            }
            try {
                Purchase purchase = new Purchase(this.mPurchasingItemType, purchaseData, dataSignature);
                try {
                    purchase.getSku();
                    if (this.mPurchaseListener != null) {
                        this.mPurchaseListener.onIabPurchaseFinished(new IabResult(0, "Success"), purchase);
                    }
                } catch (JSONException e) {
                    e = e;
                    logError("Failed to parse purchase data.");
                    e.printStackTrace();
                    IabResult result3 = new IabResult(IABHELPER_BAD_RESPONSE, "Failed to parse purchase data.");
                    if (this.mPurchaseListener != null) {
                        this.mPurchaseListener.onIabPurchaseFinished(result3, null);
                    }
                    return true;
                }
            } catch (JSONException e2) {
                e = e2;
            }
        } else if (resultCode == -1) {
            logDebug("Result code was OK but in-app billing response was not OK: " + getResponseDesc(responseCode));
            if (this.mPurchaseListener != null) {
                IabResult result4 = new IabResult(responseCode, "Problem purchasing item.");
                this.mPurchaseListener.onIabPurchaseFinished(result4, null);
            }
        } else if (resultCode == 0) {
            logDebug("Purchase canceled - Response: " + getResponseDesc(responseCode));
            IabResult result5 = new IabResult(IABHELPER_USER_CANCELLED, "User canceled.");
            if (this.mPurchaseListener != null) {
                this.mPurchaseListener.onIabPurchaseFinished(result5, null);
            }
        } else {
            logError("Purchase failed. Result code: " + Integer.toString(resultCode) + ". Response: " + getResponseDesc(responseCode));
            IabResult result6 = new IabResult(IABHELPER_UNKNOWN_PURCHASE_RESPONSE, "Unknown purchase response.");
            if (this.mPurchaseListener != null) {
                this.mPurchaseListener.onIabPurchaseFinished(result6, null);
            }
        }
        return true;
    }

    public Inventory queryInventory(boolean querySkuDetails, List<String> moreSkus, IInAppBillingService service) throws IabException {
        return queryInventory(querySkuDetails, moreSkus, null, service);
    }

    public Inventory queryInventory(boolean querySkuDetails, List<String> moreItemSkus, List<String> moreSubsSkus, IInAppBillingService service) throws IabException {
        int r;
        int r2;
        int r3;
        checkSetupDone("queryInventory");
        try {
            int r4 = queryPurchases(this.inv, "inapp", service);
            if (r4 != 0) {
                throw new IabException(r4, "Error refreshing inventory (querying owned items).");
            }
            if (querySkuDetails && (r3 = querySkuDetails("inapp", this.inv, moreItemSkus, service)) != 0) {
                throw new IabException(r3, "Error refreshing inventory (querying prices of items).");
            }
            if (this.mSubscriptionsSupported) {
                int r5 = queryPurchases(this.inv, "subs", service);
                if (r5 != 0) {
                    throw new IabException(r5, "Error refreshing inventory (querying owned subscriptions).");
                }
                if (querySkuDetails && (r2 = querySkuDetails("subs", this.inv, moreItemSkus, service)) != 0) {
                    throw new IabException(r2, "Error refreshing inventory (querying prices of subscriptions).");
                }
            }
            if (this.mSubscriptionPurchaseHistorySupported && (r = queryPurchaseHistory(this.inv, "subs", service)) != 0) {
                throw new IabException(r, "Error query Purchase History");
            }
            return this.inv;
        } catch (RemoteException e) {
            throw new IabException(IABHELPER_REMOTE_EXCEPTION, "Remote exception while refreshing inventory.", e);
        } catch (SecurityException e2) {
            throw new IabException(IABHELPER_UNKNOWN_ERROR, "SecurityException querying inventory, update Google Play - https://github.com/googlesamples/android-play-billing/issues/26", e2);
        } catch (JSONException e3) {
            throw new IabException(IABHELPER_BAD_RESPONSE, "Error parsing JSON response while refreshing inventory.", e3);
        }
    }

    public void queryInventoryAsync(final boolean querySkuDetails, final List<String> moreSkus, final QueryInventoryFinishedListener listener, final long delay) {
        checkSetupDone("queryInventory");
        this.serviceManager.workWith(new BillingServiceProcessor() {
            @Override
            public void workWith(IInAppBillingService service) {
                try {
                    Thread.sleep(delay);
                } catch (InterruptedException e) {
                }
                IabResult result = new IabResult(0, "Inventory refresh successful.");
                Inventory inv = null;
                try {
                    inv = IabHelper.this.queryInventory(querySkuDetails, moreSkus, service);
                } catch (IabException ex) {
                    result = ex.getResult();
                }
                IabResult result_f = result;
                Inventory inv_f = inv;
                if (!IabHelper.this.mDisposed && listener != null) {
                    try {
                        listener.onQueryInventoryFinished(result_f, inv_f);
                    } catch (Exception e2) {
                        e2.printStackTrace();
                    }
                }
            }
        });
    }

    public void queryInventoryAsync(QueryInventoryFinishedListener listener) {
        queryInventoryAsync(true, null, listener, 0L);
    }

    public void queryInventoryAsync(boolean querySkuDetails, QueryInventoryFinishedListener listener) {
        queryInventoryAsync(querySkuDetails, null, listener, 0L);
    }

    void consume(Purchase itemInfo, IInAppBillingService service) throws IabException {
        if (!itemInfo.mItemType.equals("inapp")) {
            throw new IabException(IABHELPER_INVALID_CONSUMPTION, "Items of type '" + itemInfo.mItemType + "' can't be consumed.");
        }
        try {
            String token = itemInfo.getToken();
            String sku = itemInfo.getSku();
            if (token == null || token.equals("")) {
                logError("Can't consume " + sku + ". No token.");
                throw new IabException(IABHELPER_MISSING_TOKEN, "PurchaseInfo is missing token for sku: " + sku + " " + itemInfo);
            }
            logDebug("Consuming sku: " + sku + ", token: " + token);
            int response = service.consumePurchase(3, this.mContext.getPackageName(), token);
            if (response == 0) {
                logDebug("Successfully consumed sku: " + sku);
            } else {
                logDebug("Error consuming consuming sku " + sku + ". " + getResponseDesc(response));
                throw new IabException(response, "Error consuming sku " + sku);
            }
        } catch (RemoteException e) {
            throw new IabException(IABHELPER_REMOTE_EXCEPTION, "Remote exception while consuming. PurchaseInfo: " + itemInfo, e);
        }
    }

    public void consumeAsync(Purchase purchase, OnConsumeFinishedListener listener) {
        checkSetupDone("consume");
        List<Purchase> purchases = new ArrayList<>();
        purchases.add(purchase);
        consumeAsyncInternal(purchases, listener, null);
    }

    public void consumeAsync(List<Purchase> purchases, OnConsumeMultiFinishedListener listener) {
        checkSetupDone("consume");
        consumeAsyncInternal(purchases, null, listener);
    }

    public static String getResponseDesc(int code) {
        String[] iab_msgs = "0:OK/1:User Canceled/2:Unknown/3:Billing Unavailable/4:Item unavailable/5:Developer Error/6:Error/7:Item Already Owned/8:Item not owned".split("/");
        String[] iabhelper_msgs = "0:OK/-1001:Remote exception during initialization/-1002:Bad response received/-1003:Purchase signature verification failed/-1004:Send intent failed/-1005:User cancelled/-1006:Unknown purchase response/-1007:Missing token/-1008:Unknown error/-1009:Subscriptions not available/-1010:Invalid consumption attempt".split("/");
        if (code <= -1000) {
            int index = (-1000) - code;
            return (index < 0 || index >= iabhelper_msgs.length) ? String.valueOf(code) + ":Unknown IAB Helper Error" : iabhelper_msgs[index];
        }
        if (code < 0 || code >= iab_msgs.length) {
            return String.valueOf(code) + ":Unknown";
        }
        return iab_msgs[code];
    }

    void checkSetupDone(String operation) {
        if (!this.mSetupDone) {
            logError("Illegal state for operation (" + operation + "): IAB helper is not set up.");
            throw new IllegalStateException("IAB helper is not set up. Can't perform operation: " + operation);
        }
    }

    int getResponseCodeFromBundle(Bundle b) {
        Object o = b.get("RESPONSE_CODE");
        if (o == null) {
            logDebug("Bundle with null response code, assuming OK (known issue)");
            return 0;
        }
        if (o instanceof Integer) {
            return ((Integer) o).intValue();
        }
        if (o instanceof Long) {
            return (int) ((Long) o).longValue();
        }
        logError("Unexpected type for bundle response code.");
        logError(o.getClass().getName());
        throw new RuntimeException("Unexpected type for bundle response code: " + o.getClass().getName());
    }

    int getResponseCodeFromIntent(Intent i) {
        Object o = i.getExtras().get("RESPONSE_CODE");
        if (o == null) {
            logError("Intent with no response code, assuming OK (known issue)");
            return 0;
        }
        if (o instanceof Integer) {
            return ((Integer) o).intValue();
        }
        if (o instanceof Long) {
            return (int) ((Long) o).longValue();
        }
        logError("Unexpected type for intent response code.");
        logError(o.getClass().getName());
        throw new RuntimeException("Unexpected type for intent response code: " + o.getClass().getName());
    }

    int queryPurchaseHistory(Inventory inv, String itemType, IInAppBillingService service) throws JSONException, RemoteException {
        if (this.mDisposed) {
            logDebug("queryPurchase History - Biller disposed. Returning...");
            return 0;
        }
        logDebug("Querying owned items' purchase history, item type: " + itemType);
        logDebug("Package name: " + this.mContext.getPackageName());
        String continueToken = null;
        do {
            logDebug("Calling getPurchaseHistory with continuation token: " + continueToken);
            Bundle ownedItems = service.getPurchaseHistory(6, this.mContext.getPackageName(), itemType, continueToken, new Bundle());
            int response = getResponseCodeFromBundle(ownedItems);
            logDebug("Purchase history response: " + String.valueOf(response));
            if (response != 0) {
                logDebug("getPurchaseHistory() failed: " + getResponseDesc(response));
                return response;
            }
            if (!ownedItems.containsKey(RESPONSE_INAPP_ITEM_LIST) || !ownedItems.containsKey(RESPONSE_INAPP_PURCHASE_DATA_LIST) || !ownedItems.containsKey(RESPONSE_INAPP_SIGNATURE_LIST)) {
                logError("Bundle returned from getPurchaseHistory() doesn't contain required fields.");
                return IABHELPER_BAD_RESPONSE;
            }
            ArrayList<String> ownedSkus = ownedItems.getStringArrayList(RESPONSE_INAPP_ITEM_LIST);
            for (int i = 0; i < ownedSkus.size(); i++) {
                String sku = ownedSkus.get(i);
                logDebug("This sku has purchase history: " + sku);
                inv.addPurchaseToSubscriptionPurchaseHistory(sku);
            }
            continueToken = ownedItems.getString(INAPP_CONTINUATION_TOKEN);
            logDebug("Continuation token: " + continueToken);
        } while (!TextUtils.isEmpty(continueToken));
        return 0 != 0 ? IABHELPER_VERIFICATION_FAILED : 0;
    }

    public int queryPurchases(Inventory inv, String itemType, IInAppBillingService service) throws JSONException, RemoteException {
        if (this.mDisposed) {
            logDebug("queryPurchases - Biller disposed. Returning...");
            return 0;
        }
        logDebug("Querying owned items, item type: " + itemType);
        logDebug("Package name: " + this.mContext.getPackageName());
        String continueToken = null;
        do {
            logDebug("Calling getPurchases with continuation token: " + continueToken);
            Bundle ownedItems = service.getPurchases(3, this.mContext.getPackageName(), itemType, continueToken);
            int response = getResponseCodeFromBundle(ownedItems);
            logDebug("Owned items response: " + String.valueOf(response));
            if (response != 0) {
                logDebug("getPurchases() failed: " + getResponseDesc(response));
                return response;
            }
            if (!ownedItems.containsKey(RESPONSE_INAPP_ITEM_LIST) || !ownedItems.containsKey(RESPONSE_INAPP_PURCHASE_DATA_LIST) || !ownedItems.containsKey(RESPONSE_INAPP_SIGNATURE_LIST)) {
                logError("Bundle returned from getPurchases() doesn't contain required fields.");
                return IABHELPER_BAD_RESPONSE;
            }
            ArrayList<String> ownedSkus = ownedItems.getStringArrayList(RESPONSE_INAPP_ITEM_LIST);
            ArrayList<String> purchaseDataList = ownedItems.getStringArrayList(RESPONSE_INAPP_PURCHASE_DATA_LIST);
            ArrayList<String> signatureList = ownedItems.getStringArrayList(RESPONSE_INAPP_SIGNATURE_LIST);
            for (int i = 0; i < purchaseDataList.size(); i++) {
                String purchaseData = purchaseDataList.get(i);
                String signature = signatureList.get(i);
                String sku = ownedSkus.get(i);
                logDebug("Sku is owned: " + sku);
                Purchase purchase = new Purchase(itemType, purchaseData, signature);
                if (TextUtils.isEmpty(purchase.getToken())) {
                    logWarn("BUG: empty/null token!");
                    logDebug("Purchase data: " + purchaseData);
                }
                inv.addPurchase(purchase);
            }
            continueToken = ownedItems.getString(INAPP_CONTINUATION_TOKEN);
            logDebug("Continuation token: " + continueToken);
        } while (!TextUtils.isEmpty(continueToken));
        return 0 != 0 ? IABHELPER_VERIFICATION_FAILED : 0;
    }

    int querySkuDetails(String itemType, Inventory inv, List<String> moreSkus, IInAppBillingService iInAppBillingService) throws RemoteException, JSONException {
        logDebug("Querying SKU details.");
        ArrayList<String> skuList = new ArrayList<>();
        skuList.addAll(inv.getAllOwnedSkus(itemType));
        if (moreSkus != null) {
            skuList.addAll(moreSkus);
        }
        if (skuList.size() == 0) {
            logDebug("queryPrices: nothing to do because there are no SKUs.");
            return 0;
        }
        while (skuList.size() > 0) {
            int endIndex = Math.min(20, skuList.size());
            ArrayList<String> chunk = new ArrayList<>();
            for (int t = 0; t < endIndex; t++) {
                chunk.add(skuList.get(t));
            }
            Bundle querySkus = new Bundle();
            querySkus.putStringArrayList(GET_SKU_DETAILS_ITEM_LIST, chunk);
            Bundle skuDetails = iInAppBillingService.getSkuDetails(3, this.mContext.getPackageName(), itemType, querySkus);
            skuList.removeAll(chunk);
            if (!skuDetails.containsKey(RESPONSE_GET_SKU_DETAILS_LIST)) {
                int response = getResponseCodeFromBundle(skuDetails);
                if (response != 0) {
                    logDebug("getSkuDetails() failed: " + getResponseDesc(response));
                    return response;
                }
                logError("getSkuDetails() returned a bundle with neither an error nor a detail list.");
                return IABHELPER_BAD_RESPONSE;
            }
            ArrayList<String> responseList = skuDetails.getStringArrayList(RESPONSE_GET_SKU_DETAILS_LIST);
            Iterator<String> it = responseList.iterator();
            while (it.hasNext()) {
                String thisResponse = it.next();
                SkuDetails d = new SkuDetails(itemType, thisResponse);
                inv.addSkuDetails(d);
            }
        }
        return 0;
    }

    void consumeAsyncInternal(final List<Purchase> purchases, final OnConsumeFinishedListener singleListener, final OnConsumeMultiFinishedListener multiListener) {
        this.serviceManager.workWith(new BillingServiceProcessor() {
            @Override
            public void workWith(IInAppBillingService service) {
                List<IabResult> results = new ArrayList<>();
                for (Purchase purchase : purchases) {
                    try {
                        IabHelper.this.consume(purchase, service);
                        results.add(new IabResult(0, "Successful consume of sku " + purchase.getSku()));
                    } catch (IabException ex) {
                        results.add(ex.getResult());
                    }
                }
                if (!IabHelper.this.mDisposed && singleListener != null) {
                    try {
                        singleListener.onConsumeFinished((Purchase) purchases.get(0), results.get(0));
                    } catch (JSONException e) {
                        e.printStackTrace();
                    }
                }
                if (!IabHelper.this.mDisposed && multiListener != null) {
                    multiListener.onConsumeMultiFinished(purchases, results);
                }
            }
        });
    }

    public static String byteArrayToHexString(byte[] a) {
        StringBuilder sb = new StringBuilder(a.length * 2);
        for (byte b : a) {
            sb.append(String.format("%02x", Integer.valueOf(b & 255)));
        }
        return sb.toString();
    }

    void logDebug(String msg) {
        Log.i("UnityIAP", msg);
    }

    void logError(String msg) {
        Log.e(this.mDebugTag, "In-app billing error: " + msg);
    }

    void logWarn(String msg) {
        Log.w(this.mDebugTag, "In-app billing warning: " + msg);
    }
}