Google pay5.0版本接入支付和訂閱功能

1、添加依賴項(xiàng)

在項(xiàng)目的build.gradle文件中添加以下依賴項(xiàng):

dependencies {
    implementation 'com.android.billingclient:billing:5.0.0'
}

從 Google Play 結(jié)算庫版本 4 遷移到版本 5 的遷移指南

2、初始化google請求

   /**
     * 初始化google play
     */
    public static void initPlay(Activity mActivity) {
        activity = mActivity;
        googleBillingUtil = GoogleBillingUtil.getInstance()
                // 注意,監(jiān)聽器設(shè)置是可選的,視個(gè)人需求設(shè)置。
                .setOnPurchaseFinishedListener(mOnPurchaseFinishedListener)//購買回調(diào)接口
                .setOnQueryFinishedListener(mOnQueryFinishedListener) //查詢回調(diào)接口
                .setOnStartSetupFinishedListener(mOnStartSetupFinishedListener) //啟動(dòng)結(jié)果回調(diào)接口
                .build(activity);
    }

 public static GoogleBillingUtil getInstance() {
        cleanListener();
        return mGoogleBillingUtil;
    }

    /**
     * google play初始化
     *
     * @param context
     * @return
     */
    public GoogleBillingUtil build(Context context) {
        if (mBillingClient == null) {
            synchronized (mGoogleBillingUtil) {
                if (mBillingClient == null) {
                    //檢測GooglePlay服務(wù)是否可用
                    if (isGooglePlayServicesAvailable(context)) {
                        builder = BillingClient.newBuilder(context);
                        mBillingClient = builder.enablePendingPurchases().setListener(mGoogleBillingUtil.new MyPurchasesUpdatedListener()).build();
                    } else {
                        if (IS_DEBUG) {
                            log("警告:GooglePlay服務(wù)處于不可用狀態(tài),請檢查");
                        }
                        if (mOnStartSetupFinishedListener != null) {
                            mOnStartSetupFinishedListener.onSetupError();
                        }
                    }
                } else {
                    //Google購買商品回調(diào)接口(訂閱和內(nèi)購都走這個(gè)接口)
                    builder.setListener(mGoogleBillingUtil.new MyPurchasesUpdatedListener());
                }
            }
        } else {
            //Google購買商品回調(diào)接口(訂閱和內(nèi)購都走這個(gè)接口)
            builder.setListener(mGoogleBillingUtil.new MyPurchasesUpdatedListener());
        }
        //請求連接到GooglePay
        synchronized (mGoogleBillingUtil) {
            if (mGoogleBillingUtil.startConnection()) {
            }
        }
        return mGoogleBillingUtil;
    }
  /**
     * 請求連接到GooglePay
     *
     * @return
     */
    public boolean startConnection() {
        if (mBillingClient == null) {
            MyToash.Log("pay", "初始化失敗:mBillingClient==null");
            return false;
        }
        MyToash.Log("pay", "--mBillingClient.isReady()-=" + mBillingClient.isReady());
        if (!mBillingClient.isReady()) {
            mBillingClient.startConnection(new BillingClientStateListener() {
                @Override
                public void onBillingSetupFinished(BillingResult billingResult) {
                    //  MyToash.Log("van--", "--mBillingClient.startConnection-=" + billingResult.getResponseCode() + "===" + billingResult.getDebugMessage());
                    //連接到GooglePay成功
                    if (billingResult.getResponseCode() == BillingClient.BillingResponseCode.OK) {
                        if (mOnStartSetupFinishedListener != null) {
                            mOnStartSetupFinishedListener.onSetupSuccess();
                        }
                    } else {
                        MyToash.Log("pay", "初始化失敗:onSetupFail:code=" + billingResult.getResponseCode());
                        if (mOnStartSetupFinishedListener != null) {
                            mOnStartSetupFinishedListener.onSetupFail(billingResult.getResponseCode());
                        }
                    }
                }

                @Override
                public void onBillingServiceDisconnected() {
                    if (mOnStartSetupFinishedListener != null) {
                        mOnStartSetupFinishedListener.onSetupError();
                    }
                    //log("初始化失敗:onBillingServiceDisconnected");
                    MyToash.Log("pay", "初始化失敗:onBillingServiceDisconnected");
                }
            });
            return false;
        } else {
            return true;
        }
    }

3、調(diào)用google方法,查詢到要購買的商品,去彈出支付彈窗

//購買APP內(nèi)部商品
purchase(activity, skuId, BillingClient.SkuType.INAPP);
//訂閱APP商品
purchase(activity, skuId, BillingClient.SkuType.SUBS);

    /**
     * 發(fā)起google play支付
     *
     * @param activity
     * @param skuId
     * @param skuType
     */
    private void purchase(Activity activity, final String skuId, final String skuType) {
        if (mBillingClient == null) {
            if (mOnPurchaseFinishedListener != null) {
                mOnPurchaseFinishedListener.onPurchaseError();
                MyToash.Log("pay", "-purchase-onPurchaseError");
            }
            return;
        }
        if (startConnection()) {
            MyToash.Log("pay", "-開始調(diào)用google查詢商品接口");
            //新版本
            ImmutableList<QueryProductDetailsParams.Product> productList = ImmutableList.of(QueryProductDetailsParams.Product.newBuilder()
                    .setProductId(skuId)
                    .setProductType(skuType)
                    .build());
            //組裝參數(shù)
            QueryProductDetailsParams params = QueryProductDetailsParams.newBuilder()
                    .setProductList(productList)
                    .build();
            //查詢參數(shù)
            mBillingClient.queryProductDetailsAsync(params, new ProductDetailsResponseListener() {
                @Override
                public void onProductDetailsResponse(@NonNull BillingResult billingResult, @NonNull List<ProductDetails> list) {
                    if (billingResult.getResponseCode() == BillingClient.BillingResponseCode.OK && list != null) {
                        MyToash.Log("pay", "skuDetailsList---=" + list.toString());
                        for (int i = 0; i < list.size(); i++) {
                            ProductDetails productDetailsBean = list.get(i);
                            String sku = productDetailsBean.getProductId();//商品id
                            MyToash.Log("pay", "skuId---=" + skuId + "    sku: " + sku);
                            if (skuId.equals(sku)) {
                                MyToash.Log("pay", "-開始調(diào)用google支付彈窗");
                                ImmutableList<BillingFlowParams.ProductDetailsParams> productDetailsParamsList = null;
                                if (skuType.equals(BillingClient.SkuType.SUBS)) {
                                    //訂閱
                                     String offerToken = productDetailsBean
                                        .getSubscriptionOfferDetails()
                                        .get(0)//這是一個(gè)數(shù)組,要選擇合適的優(yōu)惠方式,我默認(rèn)選擇了第一個(gè)
                                        .getOfferToken();
                                   // MyToash.Log("pay", "offerToken---=" + offerToken);
                                    productDetailsParamsList =
                                            ImmutableList.of(
                                                    BillingFlowParams.ProductDetailsParams.newBuilder()
                                                            .setProductDetails(productDetailsBean)
                                                            .setOfferToken(offerToken)
                                                            .build()
                                            );
                                } else {
                                    //非訂閱
                                    productDetailsParamsList =
                                            ImmutableList.of(
                                                    BillingFlowParams.ProductDetailsParams.newBuilder()
                                                            .setProductDetails(productDetailsBean)
                                                            .build()
                                            );
                                }


                                BillingFlowParams billingFlowParams = BillingFlowParams.newBuilder()
                                        .setProductDetailsParamsList(productDetailsParamsList)
                                        .build();
                                //調(diào)用支付彈窗
                                mBillingClient.launchBillingFlow(activity, billingFlowParams);
                            }
                        }
                    } else {
                        MyToash.Log("pay", "goods search fail");
                    }
                }
            });
        } else {
            if (mOnPurchaseFinishedListener != null) {
                MyToash.Log("pay", "---google連接失敗");
                mOnPurchaseFinishedListener.onPurchaseError();
            }
        }
    }

4、消耗普通商品

 /**
     * 公共消費(fèi)商品接口
     */
    public void getConsumeGoods(Activity activity, Purchase purchase, String price) {
        if (purchase != null) {
            MyToash.Log("pay", "-----開始消耗商品:" + purchase.toString());
            //本地發(fā)送書券成功之后,調(diào)用消耗接口
            ConsumeParams.Builder consumeParams = ConsumeParams.newBuilder();
            consumeParams.setPurchaseToken(purchase.getPurchaseToken());
            //調(diào)用消耗商品方法
            consumeAsync(activity, consumeParams.build(), purchase, price);
        }
    }


 public void consumeAsync(Activity activity, ConsumeParams consumeParams, Purchase purchase, String price) {
        if (mBillingClient == null) {
            return;
        }
        //本地記錄消費(fèi)的商品
        saveRecordLoaclConsumeGoods(activity, purchase, 1);

        mBillingClient.consumeAsync(consumeParams, new ConsumeResponseListener() {
            @Override
            public void onConsumeResponse(@NonNull BillingResult billingResult, @NonNull String token) {
//                MyToash.Log("van---", "--consumeAsync--=" + billingResult.toString() + "---" + token);
                if (billingResult.getResponseCode() == BillingClient.BillingResponseCode.OK) {
                    // ----------- 沙盒代碼 - 正式環(huán)境要上報(bào)-------- -
                    try {
                        String pId = purchase.getSkus().get(0);
                        String currentPrice = "0";
                        if (TextUtils.isEmpty(price)) {
                            currentPrice = CommonOkHttpUtils.INSTANCE.getPayPrice(activity, pId);
                            MyToash.Log("pay", "本地價(jià)格-----消耗商品成功 " + "價(jià)格:" + currentPrice);
                        } else {
                            currentPrice = price;
                            MyToash.Log("pay", "傳遞過來的價(jià)格-----消耗商品成功 " + "價(jià)格:" + currentPrice);
                        }
                        AdjustEvent event = new AdjustEvent(Constant.MD_ADJUST_czcg);
                        double upPrice = Double.parseDouble(currentPrice);
                        event.setRevenue(upPrice, "USD");
                        Adjust.trackEvent(event);
                    } catch (Exception e) {
                        e.printStackTrace();
                        MyToash.Log("pay", "異常處理-----e:" + e.toString());
                    }
                    //請求本地接口
                    getHttpPay(activity, purchase);
                    //移除
                    saveRecordLoaclConsumeGoods(activity, purchase, 2);
                } else {
                    MyToash.Log("pay", "-----消耗商品失敗" + billingResult.toString() + "---" + token + "--code:" + billingResult.getResponseCode());
                }
            }
        });
    }

5、消耗訂閱商品


    /**
     * 公共訂閱方法消費(fèi)
     */
    public void getConsumeSubscribeGoods(Activity activity, Purchase purchase, String price){
        if (purchase != null) {
            if (purchase.getPurchaseState() == Purchase.PurchaseState.PURCHASED) {
                if (!purchase.isAcknowledged()) {
                    AcknowledgePurchaseParams acknowledgePurchaseParams =
                            AcknowledgePurchaseParams.newBuilder()
                                    .setPurchaseToken(purchase.getPurchaseToken())
                                    .build();
                    mBillingClient.acknowledgePurchase(acknowledgePurchaseParams, new AcknowledgePurchaseResponseListener(){

                        @Override
                        public void onAcknowledgePurchaseResponse(@NonNull BillingResult billingResult) {
                            if (billingResult.getResponseCode() == BillingClient.BillingResponseCode.OK) {
                                MyToash.Log("pay","-------消費(fèi)訂閱商品成功");
                                //請求本地接口
                                getHttpPay(activity, purchase);
                            }
                        }
                    });
                }
            }

        }
    }

6、查詢未完成的商品狀態(tài)

老的方法:

 /**
     * 查詢失敗的訂單
     * skuType :,BillingClient.SkuType.INAPP;  BillingClient.SkuType.SUBS
     * 0:PurchaseState.UNSPECIFIED_STATE:未知狀態(tài)
     * 1:PurchaseState.PURCHASED:付款完成
     * 2:PurchaseState.PENDING:購買正在等待付款完成。
     */
    public void queryFailOrder(Activity activity, String skuType) {
        MyToash.Log("pay", "-----查詢需要補(bǔ)貨的商品:");
        if (mBillingClient != null) {
            Purchase.PurchasesResult result = mBillingClient.queryPurchases(skuType);
            if (BillingClient.BillingResponseCode.OK == result.getResponseCode()) {
                for (Purchase purchase : result.getPurchasesList()) {
                    //PURCHASED --已購買
                    if (Purchase.PurchaseState.PURCHASED == purchase.getPurchaseState()) {
                        //MyToash.Log("pay", "----------需要補(bǔ)貨的商品:");
                        //調(diào)用google去消費(fèi)
                        getConsumeGoods(activity, purchase, "");
                    }
                }
            }
    
        }
    }

5.0新的方法:

 /**
     * 查詢失敗的訂單
     * skuType :,BillingClient.SkuType.INAPP;  BillingClient.SkuType.SUBS
     * 0:PurchaseState.UNSPECIFIED_STATE:未知狀態(tài)
     * 1:PurchaseState.PURCHASED:付款完成
     * 2:PurchaseState.PENDING:購買正在等待付款完成。
     */
    public void queryFailOrder(Activity activity, String skuType) {
        MyToash.Log("pay", "-----查詢需要補(bǔ)貨的商品:");
        if (mBillingClient != null) {
            QueryPurchasesParams queryPurchasesParams = QueryPurchasesParams.newBuilder()
                    .setProductType(skuType)
                    .build();
            mBillingClient.queryPurchasesAsync(queryPurchasesParams, new PurchasesResponseListener() {

                @Override
                public void onQueryPurchasesResponse(@NonNull BillingResult billingResult, @NonNull List<Purchase> list) {
                    if (list != null) {
                        if (billingResult.getResponseCode() == BillingClient.BillingResponseCode.OK) {
                            for (Purchase purchase : list) {
                                //PURCHASED --已購買
                                if (Purchase.PurchaseState.PURCHASED == purchase.getPurchaseState()) {
                                    //MyToash.Log("pay", "----------需要補(bǔ)貨的商品:");
                                    //調(diào)用google去消費(fèi)
                                    getConsumeGoods(activity, purchase, "");
                                }
                            }
                        }
                    }
                }
            });
        }
    }


7、完整代碼

package com.youjiakeji.yjkjreader.pay;

import android.app.Activity;
import android.content.Context;
import android.text.TextUtils;
import android.util.Log;

import androidx.annotation.NonNull;
import androidx.annotation.Nullable;

import com.adjust.sdk.Adjust;
import com.adjust.sdk.AdjustEvent;
import com.android.billingclient.api.AcknowledgePurchaseParams;
import com.android.billingclient.api.AcknowledgePurchaseResponseListener;
import com.android.billingclient.api.BillingClient;
import com.android.billingclient.api.BillingClientStateListener;
import com.android.billingclient.api.BillingFlowParams;
import com.android.billingclient.api.BillingResult;
import com.android.billingclient.api.ConsumeParams;
import com.android.billingclient.api.ConsumeResponseListener;
import com.android.billingclient.api.ProductDetails;
import com.android.billingclient.api.ProductDetailsResponseListener;
import com.android.billingclient.api.Purchase;
import com.android.billingclient.api.PurchasesResponseListener;
import com.android.billingclient.api.PurchasesUpdatedListener;
import com.android.billingclient.api.QueryProductDetailsParams;
import com.android.billingclient.api.QueryPurchasesParams;
import com.android.billingclient.api.SkuDetails;
import com.android.billingclient.api.SkuDetailsParams;
import com.android.billingclient.api.SkuDetailsResponseListener;
import com.google.common.collect.ImmutableList;
import com.youjiakeji.yjkjreader.base.BWNApplication;
import com.youjiakeji.yjkjreader.base.BaseConfig;
import com.youjiakeji.yjkjreader.base.BaseKey;
import com.youjiakeji.yjkjreader.constant.Api;
import com.youjiakeji.yjkjreader.constant.CommonConstantUtils;
import com.youjiakeji.yjkjreader.constant.Constant;
import com.youjiakeji.yjkjreader.eventbus.RefreshMine;
import com.youjiakeji.yjkjreader.eventbus.RefreshRead;
import com.youjiakeji.yjkjreader.kotlin.utils.CommonPayUtilsKt;
import com.youjiakeji.yjkjreader.model.OrderFailBean;
import com.youjiakeji.yjkjreader.net.CommonOkHttpUtils;
import com.youjiakeji.yjkjreader.net.HttpUtils;
import com.youjiakeji.yjkjreader.net.ReaderParams;
import com.youjiakeji.yjkjreader.ui.dialog.PublicPurchaseDialog;
import com.youjiakeji.yjkjreader.ui.dialog.WaitDialogUtils;
import com.youjiakeji.yjkjreader.ui.utils.MyToash;
import com.google.android.gms.common.ConnectionResult;
import com.google.android.gms.common.GoogleApiAvailability;
import com.youjiakeji.yjkjreader.ui.utils.MmkvUtils;
import com.youjiakeji.yjkjreader.utils.GsonUtil;
import com.youjiakeji.yjkjreader.utils.ShareUitls;
import com.youjiakeji.yjkjreader.utils.UserUtils;

import org.greenrobot.eventbus.EventBus;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;

/**
 * Created by TJbaobao on 2017/11/2.
 * CSDN:http://blog.csdn.net/u013640004/article/details/78257536
 * <p>
 * 當(dāng)前版本:V1.1.7
 * 更新日志:
 * <p>
 * v1.1.7 2019/01/05
 *
 * <p>
 * v1.1.6 2018/09/05
 * 去掉我項(xiàng)目了的BaseApplication.getContext()的方法,初始現(xiàn)在需要傳入一個(gè)Context,可以使用Application的Context
 * 對isGooglePlayServicesAvailable方法進(jìn)行了說明,因?yàn)檫@個(gè)方法是要導(dǎo)入一個(gè)包才能使用的。
 * --> api "com.google.android.gms:play-services-location:11.8.0"
 * <p>
 * v1.1.5 2018/07/13
 * 優(yōu)化-盡可能處理了一些可能造成的內(nèi)存泄漏的問題。
 * 修改-查詢成功接口增加一個(gè)String skuType,參數(shù),各位在查詢的時(shí)候需要判斷skuType
 * 增加-增加兩處接口為Null的Log提示,tag為GoogleBillingUtil。
 * <p>
 * V1.1.4 2018/01/03
 * 修改-實(shí)現(xiàn)單例模式,避免多實(shí)例導(dǎo)致的谷歌接口回調(diào)錯(cuò)亂問題。
 * <p>
 * V1.1.3 2017/12/19
 * 修復(fù)-服務(wù)啟動(dòng)失敗時(shí)導(dǎo)致的空指針錯(cuò)誤。
 * <p>
 * V1.1.2    2017/12/18
 * 修復(fù)-修復(fù)內(nèi)購未被消耗的BUG。
 * 增加-每次啟動(dòng)都獲取一次歷史內(nèi)購訂單,并且全部消耗。
 * 增加-可以通過設(shè)置isAutoConsumeAsync來確定內(nèi)購是否每次自動(dòng)消耗。
 * 增加-將consumeAsync改為public,你可以手動(dòng)調(diào)用消耗。
 * <p>
 * V1.1.1  2017/11/2
 * 特性-不需要key了,不需要IInAppBillingService.aidl了,不需要那一大堆Utils了,創(chuàng)建新實(shí)例的時(shí)候必須要傳入購買回調(diào)接口。
 * <p>
 * V1.0.3 2017/10/27
 * 增加-支持內(nèi)購
 * <p>
 * V1.0.2  2017/09/11
 * 修復(fù)-修復(fù)BUG
 * <p>
 * v1.0.1 2017/07/29
 * 初始版本
 */

@SuppressWarnings("ALL")
public class GoogleBillingUtil {

    private static final String TAG = "GoogleBillingUtil";
    private static final boolean IS_DEBUG = true;
    public static final String BILLING_TYPE_INAPP = BillingClient.SkuType.INAPP;//內(nèi)購
    public static final String BILLING_TYPE_SUBS = BillingClient.SkuType.SUBS;//訂閱

    private static BillingClient mBillingClient;
    private static BillingClient.Builder builder;
    private static OnPurchaseFinishedListener mOnPurchaseFinishedListener;//購買回調(diào)接口
    private static OnStartSetupFinishedListener mOnStartSetupFinishedListener;//啟動(dòng)結(jié)果回調(diào)接口
    private static OnQueryFinishedListener mOnQueryFinishedListener; //查詢回調(diào)接口
    private static OnConsumeResponseListener mOnConsumeResponseListener; //消耗商品接口

    private boolean isAutoConsumeAsync = true;//是否在購買成功后自動(dòng)消耗商品

    private static final GoogleBillingUtil mGoogleBillingUtil = new GoogleBillingUtil();

    private GoogleBillingUtil() {

    }

    /**
     * 設(shè)置skus
     *
     * @param inAppSKUS 內(nèi)購id
     * @param subsSKUS  訂閱id
     */
    public static void setSkus(@Nullable String[] inAppSKUS, @Nullable String[] subsSKUS) {
      /*  if (inAppSKUS != null) {
            GoogleBillingUtil.inAppSKUS = inAppSKUS;
        }
        if (subsSKUS != null) {
            GoogleBillingUtil.subsSKUS = subsSKUS;
        }*/
    }

    public static GoogleBillingUtil getInstance() {
        cleanListener();
        return mGoogleBillingUtil;
    }

    /**
     * google play初始化
     *
     * @param context
     * @return
     */
    public GoogleBillingUtil build(Context context) {
        if (mBillingClient == null) {
            synchronized (mGoogleBillingUtil) {
                if (mBillingClient == null) {
                    //檢測GooglePlay服務(wù)是否可用
                    if (isGooglePlayServicesAvailable(context)) {
                        builder = BillingClient.newBuilder(context);
                        mBillingClient = builder.enablePendingPurchases().setListener(mGoogleBillingUtil.new MyPurchasesUpdatedListener()).build();
                    } else {
                        if (IS_DEBUG) {
                            log("警告:GooglePlay服務(wù)處于不可用狀態(tài),請檢查");
                        }
                        if (mOnStartSetupFinishedListener != null) {
                            mOnStartSetupFinishedListener.onSetupError();
                        }
                    }
                } else {
                    //Google購買商品回調(diào)接口(訂閱和內(nèi)購都走這個(gè)接口)
                    builder.setListener(mGoogleBillingUtil.new MyPurchasesUpdatedListener());
                }
            }
        } else {
            //Google購買商品回調(diào)接口(訂閱和內(nèi)購都走這個(gè)接口)
            builder.setListener(mGoogleBillingUtil.new MyPurchasesUpdatedListener());
        }
        //請求連接到GooglePay
        synchronized (mGoogleBillingUtil) {
            if (mGoogleBillingUtil.startConnection()) {
            }
        }
        return mGoogleBillingUtil;
    }

    /**
     * 請求連接到GooglePay
     *
     * @return
     */
    public boolean startConnection() {
        if (mBillingClient == null) {
            MyToash.Log("pay", "初始化失敗:mBillingClient==null");
            return false;
        }
        MyToash.Log("pay", "--mBillingClient.isReady()-=" + mBillingClient.isReady());
        if (!mBillingClient.isReady()) {
            mBillingClient.startConnection(new BillingClientStateListener() {
                @Override
                public void onBillingSetupFinished(BillingResult billingResult) {
                    //  MyToash.Log("van--", "--mBillingClient.startConnection-=" + billingResult.getResponseCode() + "===" + billingResult.getDebugMessage());
                    //連接到GooglePay成功
                    if (billingResult.getResponseCode() == BillingClient.BillingResponseCode.OK) {
                        if (mOnStartSetupFinishedListener != null) {
                            mOnStartSetupFinishedListener.onSetupSuccess();
                        }
                    } else {
                        MyToash.Log("pay", "初始化失敗:onSetupFail:code=" + billingResult.getResponseCode());
                        if (mOnStartSetupFinishedListener != null) {
                            mOnStartSetupFinishedListener.onSetupFail(billingResult.getResponseCode());
                        }
                    }
                }

                @Override
                public void onBillingServiceDisconnected() {
                    if (mOnStartSetupFinishedListener != null) {
                        mOnStartSetupFinishedListener.onSetupError();
                    }
                    //log("初始化失敗:onBillingServiceDisconnected");
                    MyToash.Log("pay", "初始化失敗:onBillingServiceDisconnected");
                }
            });
            return false;
        } else {
            return true;
        }
    }


    /**
     * getResponseCode值:
     * <p>
     * Google購買商品回調(diào)接口(訂閱和內(nèi)購都走這個(gè)接口)
     * int SERVICE_TIMEOUT = -3;//服務(wù)超時(shí)
     * int FEATURE_NOT_SUPPORTED = -2;//不支持功能
     * int SERVICE_DISCONNECTED = -1;//服務(wù)單元已斷開
     * int OK = 0;//成功
     * int USER_CANCELED = 1;//用戶按上一步或取消對話框
     * int SERVICE_UNAVAILABLE = 2;//網(wǎng)絡(luò)連接斷開
     * int BILLING_UNAVAILABLE = 3;//所請求的類型不支持 Google Play 結(jié)算服務(wù) AIDL 版本
     * int ITEM_UNAVAILABLE = 4;//請求的商品已不再出售。
     * int DEVELOPER_ERROR = 5;//提供給 API 的參數(shù)無效。此錯(cuò)誤也可能說明應(yīng)用未針對結(jié)算服務(wù)正確簽名或設(shè)置,或者在其清單中缺少必要的權(quán)限。
     * int ERROR = 6;//API 操作期間出現(xiàn)嚴(yán)重錯(cuò)誤
     * int ITEM_ALREADY_OWNED = 7;//未能購買,因?yàn)橐呀?jīng)擁有此商品
     * int ITEM_NOT_OWNED = 8;//未能消費(fèi),因?yàn)樯形磽碛写松唐?     */
    private class MyPurchasesUpdatedListener implements PurchasesUpdatedListener {
        @Override
        public void onPurchasesUpdated(BillingResult billingResult, @Nullable List<Purchase> list) {
            MyToash.Log("pay", "--MyPurchasesUpdatedListener--調(diào)用本地接口");
            //支付成功
            if (billingResult.getResponseCode() == BillingClient.BillingResponseCode.OK && list != null && !list.isEmpty()) {
                MyToash.Log("pay", "--onPurchasesUpdated--=" + list.size());
                //回調(diào)支付成功
                if (mOnPurchaseFinishedListener != null) {
                    //消耗商品
                    Purchase purchase = list.get(0);
                    mOnPurchaseFinishedListener.onPurchaseSuccess(purchase);
                }
            } else {
                MyToash.Log("pay", "--onPurchasesUpdatedFail--=" + billingResult.getResponseCode());
                mOnPurchaseFinishedListener.onPurchaseFail(billingResult.getResponseCode());
            }
        }

    }

    /**
     * 查詢內(nèi)購商品信息
     */
    public void queryInventoryInApp() {
        queryInventory(BillingClient.SkuType.INAPP);
    }

    /**
     * 查詢訂閱商品信息
     */
    public void queryInventorySubs() {
        queryInventory(BillingClient.SkuType.SUBS);
    }

    private void queryInventory(final String skuType) {

       /* Runnable runnable = new Runnable() {
            @Override
            public void run() {
                if (mBillingClient == null) {
                    if (mOnQueryFinishedListener != null) {
                        mOnQueryFinishedListener.onQueryError();
                    }
                    return;
                }
                ArrayList<String> skuList = new ArrayList<>();
                if (skuType.equals(BillingClient.SkuType.INAPP)) {
                    Collections.addAll(skuList, inAppSKUS);
                } else if (skuType.equals(BillingClient.SkuType.SUBS)) {
                    Collections.addAll(skuList, subsSKUS);
                }
                SkuDetailsParams.Builder params = SkuDetailsParams.newBuilder();
                params.setSkusList(skuList).setType(skuType);
                mBillingClient.querySkuDetailsAsync(params.build(), new MySkuDetailsResponseListener(skuType));
            }
        };
        executeServiceRequest(runnable);*/
    }


    /**
     * Google查詢商品信息回調(diào)接口
     */
    private class MySkuDetailsResponseListener implements SkuDetailsResponseListener {
        private String skuType;

        public MySkuDetailsResponseListener(String skuType) {
            this.skuType = skuType;
        }

        @Override
        public void onSkuDetailsResponse(BillingResult billingResult, List<SkuDetails> list) {
            if (mOnQueryFinishedListener == null) {
                if (IS_DEBUG) {
                    log("警告:接收到查詢商品回調(diào),但查詢商品接口為Null,請?jiān)O(shè)置購買接口。eg:setOnQueryFinishedListener()");
                }
                return;
            }
            if (billingResult.getResponseCode() == BillingClient.BillingResponseCode.OK && list != null) {
                mOnQueryFinishedListener.onQuerySuccess(skuType, list);
            } else {
                mOnQueryFinishedListener.onQueryFail(billingResult.getResponseCode());
            }
        }

    }

    /**
     * 發(fā)起內(nèi)購
     *
     * @param activity
     * @param skuId:googleID
     * @param goods_id:商品ID
     */
    public void purchaseInApp(Activity activity, String skuId, String goods_id) {
        //創(chuàng)建本地訂單
        WaitDialogUtils.showDialog(activity);
        getCreateOrder(activity, goods_id, "1", new CallCheckOrder() {
            @Override
            public void call(String result) {
                if (!TextUtils.isEmpty(result)) {
                    //初次必須賦值
                    GooglePayCommonUtils.CURRENTPAYMODE = BillingClient.SkuType.INAPP;
                    purchase(activity, skuId, BillingClient.SkuType.INAPP);
                }

            }
        });

    }

    /**
     * 發(fā)起訂閱
     *
     * @param skuId
     * @return
     */
    public void purchaseSubs(Activity activity, String skuId, String goods_id) {
        //創(chuàng)建本地訂單
        WaitDialogUtils.showDialog(activity);
        //初次必須賦值
        GooglePayCommonUtils.CURRENTPAYMODE = BillingClient.SkuType.SUBS;
        purchase(activity, skuId, BillingClient.SkuType.SUBS);
    }

    /**
     * 發(fā)起google play支付
     *
     * @param activity
     * @param skuId
     * @param skuType
     */
    private void purchase(Activity activity, final String skuId, final String skuType) {
        if (mBillingClient == null) {
            if (mOnPurchaseFinishedListener != null) {
                mOnPurchaseFinishedListener.onPurchaseError();
                MyToash.Log("pay", "-purchase-onPurchaseError");
            }
            return;
        }
        if (startConnection()) {
            MyToash.Log("pay", "-開始調(diào)用google查詢商品接口");
            //新版本
            ImmutableList<QueryProductDetailsParams.Product> productList = ImmutableList.of(QueryProductDetailsParams.Product.newBuilder()
                    .setProductId(skuId)
                    .setProductType(skuType)
                    .build());
            //組裝參數(shù)
            QueryProductDetailsParams params = QueryProductDetailsParams.newBuilder()
                    .setProductList(productList)
                    .build();
            //查詢參數(shù)
            mBillingClient.queryProductDetailsAsync(params, new ProductDetailsResponseListener() {
                @Override
                public void onProductDetailsResponse(@NonNull BillingResult billingResult, @NonNull List<ProductDetails> list) {
                    if (billingResult.getResponseCode() == BillingClient.BillingResponseCode.OK && list != null) {
                        MyToash.Log("pay", "skuDetailsList---=" + list.toString());
                        for (int i = 0; i < list.size(); i++) {
                            ProductDetails productDetailsBean = list.get(i);
                            String sku = productDetailsBean.getProductId();//商品id
                            MyToash.Log("pay", "skuId---=" + skuId + "    sku: " + sku);
                            if (skuId.equals(sku)) {
                                MyToash.Log("pay", "-開始調(diào)用google支付彈窗");
                                ImmutableList<BillingFlowParams.ProductDetailsParams> productDetailsParamsList = null;
                                if (skuType.equals(BillingClient.SkuType.SUBS)) {
                                    //訂閱
                                    String offerToken = productDetailsBean
                                            .getSubscriptionOfferDetails()
                                            .get(0)//這是一個(gè)數(shù)組,要選擇合適的優(yōu)惠方式,我默認(rèn)選擇了第一個(gè)
                                            .getOfferToken();
                                    // MyToash.Log("pay", "offerToken---=" + offerToken);
                                    productDetailsParamsList =
                                            ImmutableList.of(
                                                    BillingFlowParams.ProductDetailsParams.newBuilder()
                                                            .setProductDetails(productDetailsBean)
                                                            .setOfferToken(offerToken)
                                                            .build()
                                            );
                                } else {
                                    //非訂閱
                                    productDetailsParamsList =
                                            ImmutableList.of(
                                                    BillingFlowParams.ProductDetailsParams.newBuilder()
                                                            .setProductDetails(productDetailsBean)
                                                            .build()
                                            );
                                }


                                BillingFlowParams billingFlowParams = BillingFlowParams.newBuilder()
                                        .setProductDetailsParamsList(productDetailsParamsList)
                                        .build();
                                //調(diào)用支付彈窗
                                mBillingClient.launchBillingFlow(activity, billingFlowParams);
                            }
                        }
                    } else {
                        MyToash.Log("pay", "goods search fail");
                        WaitDialogUtils.dismissDialog();
                    }
                }
            });
        } else {
            if (mOnPurchaseFinishedListener != null) {
                MyToash.Log("pay", "---google連接失敗");
                mOnPurchaseFinishedListener.onPurchaseError();
                WaitDialogUtils.dismissDialog();
            }
        }
    }

    /**
     * 消耗商品
     *
     * @param purchaseToken int SERVICE_TIMEOUT = -3; //服務(wù)超時(shí)
     *                      int FEATURE_NOT_SUPPORTED = -2; //不支持功能
     *                      int SERVICE_DISCONNECTED = -1; //服務(wù)單元已斷開
     *                      int OK = 0; //成功
     *                      int USER_CANCELED = 1; //用戶按上一步或取消對話框
     *                      int SERVICE_UNAVAILABLE = 2; //網(wǎng)絡(luò)連接斷開
     *                      int BILLING_UNAVAILABLE = 3; //所請求的類型不支持 Google Play 結(jié)算服務(wù) AIDL 版本
     *                      int ITEM_UNAVAILABLE = 4; //請求的商品已不再出售。
     *                      int DEVELOPER_ERROR = 5; //提供給 API 的參數(shù)無效。此錯(cuò)誤也可能說明應(yīng)用未針對結(jié)算服務(wù)正確簽名或設(shè)置,或者在其清單中缺少必要的權(quán)限。
     *                      int ERROR = 6; //API 操作期間出現(xiàn)嚴(yán)重錯(cuò)誤
     *                      int ITEM_ALREADY_OWNED = 7; //未能購買,因?yàn)橐呀?jīng)擁有此商品
     *                      int ITEM_NOT_OWNED = 8; //未能消費(fèi),因?yàn)樯形磽碛写松唐?     */
    public void consumeAsync(Activity activity, ConsumeParams consumeParams, Purchase purchase, String price) {
        if (mBillingClient == null) {
            return;
        }
        //本地記錄消費(fèi)的商品
        saveRecordLoaclConsumeGoods(activity, purchase, 1, BillingClient.ProductType.INAPP);

        mBillingClient.consumeAsync(consumeParams, new ConsumeResponseListener() {
            @Override
            public void onConsumeResponse(@NonNull BillingResult billingResult, @NonNull String token) {
//                MyToash.Log("van---", "--consumeAsync--=" + billingResult.toString() + "---" + token);
                if (billingResult.getResponseCode() == BillingClient.BillingResponseCode.OK) {
                    // ----------- 沙盒代碼 - 正式環(huán)境要上報(bào)-------- -
                    try {
                        String pId = purchase.getSkus().get(0);
                        String currentPrice = "0";
                        if (TextUtils.isEmpty(price)) {
                            currentPrice = CommonOkHttpUtils.INSTANCE.getPayPrice(activity, pId);
                            MyToash.Log("pay", "本地價(jià)格-----消耗商品成功 " + "價(jià)格:" + currentPrice);
                        } else {
                            currentPrice = price;
                            MyToash.Log("pay", "傳遞過來的價(jià)格-----消耗商品成功 " + "價(jià)格:" + currentPrice);
                        }
                        AdjustEvent event = new AdjustEvent(Constant.MD_ADJUST_czcg);
                        double upPrice = Double.parseDouble(currentPrice);
                        event.setRevenue(upPrice, "USD");
                        Adjust.trackEvent(event);
                    } catch (Exception e) {
                        e.printStackTrace();
                        MyToash.Log("pay", "異常處理-----e:" + e.toString());
                    }
                    //請求本地接口
                    getHttpPay(activity, purchase, BillingClient.ProductType.INAPP);
                    //移除
                    saveRecordLoaclConsumeGoods(activity, purchase, 2, BillingClient.ProductType.INAPP);
                } else {
                    WaitDialogUtils.dismissDialog();
                    MyToash.Log("pay", "-----消耗商品失敗" + billingResult.toString() + "---" + token + "--code:" + billingResult.getResponseCode());
                }
            }
        });
    }

    /**
     * 記錄本地消費(fèi)的商品
     *
     * @param activity
     * @param purchase
     * @param type:    1:是保存;2:移除
     */
    private void saveRecordLoaclConsumeGoods(Activity activity, Purchase purchase, int type, String skuType) {
        try {
            if (purchase != null) {
                String uid_key = UserUtils.getUID() + CommonConstantUtils.CONSUME;
                List<String> list = new ArrayList<>();
                //獲取存儲(chǔ)的值
                String lastJson = MmkvUtils.decodeString(uid_key);

                String pId = purchase.getSkus().get(0);
                String purchaseToken = purchase.getPurchaseToken();
                String packageName = purchase.getPackageName();
                //鍵值對唯一的key
                String onlyKey = purchaseToken + CommonConstantUtils.CONSUME;
                if (type == 1) {  //保存
                    //不是空
                    if (!lastJson.isEmpty()) {
                        List<String> list2 = GsonUtil.GsonToList(lastJson, String.class);
                        for (int i = 0; i < list2.size(); i++) {
                            String data = list2.get(i);
                            OrderFailBean bean = GsonUtil.GsonToBean(data, OrderFailBean.class);
                            String tokenKey = bean.getPurchaseToken() + CommonConstantUtils.CONSUME;
                            //是否要保存一條數(shù)據(jù)
                            if (!tokenKey.equals(onlyKey)) {
                                list.add(data);
                            }
                        }
                    }
                    //沒有相同單據(jù),保存
                    HashMap map = new HashMap();
                    map.put("pId", pId);
                    map.put("purchaseToken", purchaseToken);
                    map.put("packageName", packageName);
                    map.put("skuType", skuType);
                    map.put("time", CommonPayUtilsKt.isSaveCurrentTime());
                    list.add(GsonUtil.BeanToJson(map));
                    String json = GsonUtil.BeanToJson(list);
                    //保存上傳失敗的訂單
                    MmkvUtils.encode(uid_key, json);
                    MyToash.Log("pay", "--保存消耗的商品json:" + purchaseToken);
                    // MyToash.Log("pay", "--保存消耗的商品json:" + json);
                } else if (type == 2) { //移除
                    //不是空
                    if (!lastJson.isEmpty()) {
                        int currentIndex = -1;
                        List<String> list3 = GsonUtil.GsonToList(lastJson, String.class);
                        for (int i = 0; i < list3.size(); i++) {
                            String data = list3.get(i);
                            list.add(data);
                            OrderFailBean bean = GsonUtil.GsonToBean(data, OrderFailBean.class);
                            String tokenKey = bean.getPurchaseToken() + CommonConstantUtils.CONSUME;
                            if (tokenKey.equals(onlyKey)) {
                                currentIndex = i;
                            }
                        }
                        if (currentIndex != -1) {
                            list.remove(currentIndex);
                            String json = GsonUtil.BeanToJson(list);
                            //保存上傳失敗的訂單
                            MmkvUtils.encode(uid_key, json);
                            MyToash.Log("pay", "--移除消耗的商品json:" + json);
                        }
                    }
                }
            }

        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /**
     * 查詢本地消費(fèi)商品未返回?cái)?shù)據(jù)
     *
     * @param type
     * @param activity
     * @param purchase
     */
    public void checkRecordLoaclConsumeGoods(Activity activity) {
        try {
            String uid = UserUtils.getUID();
            String uid_key = UserUtils.getUID() + CommonConstantUtils.CONSUME;
            List<String> list = new ArrayList<>();
            //獲取存儲(chǔ)的值
            String lastJson = MmkvUtils.decodeString(uid_key);
            MyToash.Log("pay", "--查詢本地消費(fèi)后商品未返回?cái)?shù)據(jù)lastJson:" + lastJson);
            if (!lastJson.isEmpty()) {
                //不是空
                list = GsonUtil.GsonToList(lastJson, String.class);
                if (list != null && list.size() > 0) {
                    //上傳
                    for (int i = 0; i < list.size(); i++) {
                        String data = list.get(i);
                        OrderFailBean bean = GsonUtil.GsonToBean(data, OrderFailBean.class);
                        String pId = bean.getpId();
                        long time = bean.getTime();
                        String purchaseToken = bean.getPurchaseToken();
                        String packageName = bean.getPackageName();
                        String skuType = bean.getSkuType();
                        MyToash.Log("pay", "--查詢本地消費(fèi)后商品未返回?cái)?shù)據(jù)上傳本地單據(jù):" + purchaseToken);
                        if (CommonPayUtilsKt.isUploadLocalFailOrder(time)) {
                            //上傳本地單據(jù)
                            UploadLocalFailOrder(activity, uid, pId, packageName, purchaseToken, skuType);
                            Thread.sleep(1000);
                        }
                    }
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }


    /**
     * 獲取已經(jīng)內(nèi)購的商品
     *
     * @return
     */
    public List<Purchase> queryPurchasesInApp() {
        return queryPurchases(BillingClient.SkuType.INAPP);
    }

    /**
     * 獲取已經(jīng)訂閱的商品
     *
     * @return
     */
    public List<Purchase> queryPurchasesSubs() {
        return queryPurchases(BillingClient.SkuType.SUBS);
    }

    /**
     * 查詢最近的購買交易
     *
     * @param skuType
     * @return
     */
    private List<Purchase> queryPurchases(String skuType) {
        List<Purchase> purchaseList = new ArrayList<>();
        if (mBillingClient == null) {
            return null;
        }
        if (!mBillingClient.isReady()) {
            //如果斷開google連接,重新開始連接
            startConnection();
        } else {
            QueryPurchasesParams queryPurchasesParams = QueryPurchasesParams.newBuilder()
                    .setProductType(skuType)
                    .build();
            mBillingClient.queryPurchasesAsync(queryPurchasesParams, new PurchasesResponseListener() {
                @Override
                public void onQueryPurchasesResponse(@NonNull BillingResult billingResult, @NonNull List<Purchase> list) {
                    if (list != null) {
                        if (billingResult.getResponseCode() == BillingClient.BillingResponseCode.OK) {
                            purchaseList.clear();
                            purchaseList.addAll(list);
                        }
                    }
                }
            });
            return purchaseList;
//            Purchase.PurchasesResult purchasesResult = mBillingClient.queryPurchases(skuType);
//
//            if (purchasesResult != null) {
//                if (purchasesResult.getResponseCode() == BillingClient.BillingResponseCode.OK) {
//                    List<Purchase> purchaseList = purchasesResult.getPurchasesList();
//                  /*  if (isAutoConsumeAsync) {
//                        if (purchaseList != null) {
//                            for (Purchase purchase : purchaseList) {
//                                if (skuType.equals(purchase.getSku())) {
//                                    ConsumeParams.Builder consumeParams = ConsumeParams.newBuilder();
//                                    consumeParams.setPurchaseToken(purchase.getPurchaseToken());
//                            *//*        consumeParams
//                                    consumeParams.setDeveloperPayload(purchase.getDeveloperPayload());*//*
//                                    consumeAsync(consumeParams.build(), purchase);
//                                }
//                            }
//                        }
//                    }*/
//                    return purchaseList;
//                }
//            }

        }
        return null;
    }

    /**
     * 獲取有效訂閱的數(shù)量
     *
     * @return -1查詢失敗,0沒有有效訂閱,>0具有有效的訂閱
     */
    public int getPurchasesSizeSubs() {
        List<Purchase> list = queryPurchasesSubs();
        if (list != null) {
            return list.size();
        }
        return -1;
    }

    /**
     * 通過sku獲取訂閱商品序號
     *
     * @param sku
     * @return
     */
    public int getSubsPositionBySku(String sku) {
        return getPositionBySku(sku, BillingClient.SkuType.SUBS);
    }

    /**
     * 通過sku獲取內(nèi)購商品序號
     *
     * @param sku
     * @return 成功返回需要 失敗返回-1
     */
    public int getInAppPositionBySku(String sku) {
        return getPositionBySku(sku, BillingClient.SkuType.INAPP);
    }

    private int getPositionBySku(String sku, String skuType) {

       /* if (skuType.equals(BillingClient.SkuType.INAPP)) {
            int i = 0;
            for (String s : inAppSKUS) {
                if (s.equals(sku)) {
                    return i;
                }
                i++;
            }
        } else if (skuType.equals(BillingClient.SkuType.SUBS)) {
            int i = 0;
            for (String s : subsSKUS) {
                if (s.equals(sku)) {
                    return i;
                }
                i++;
            }
        }*/
        return -1;
    }

    private void executeServiceRequest(final Runnable runnable) {
        if (startConnection()) {
            runnable.run();
        }
    }

    /**
     * 通過序號獲取訂閱sku
     *
     * @param position
     * @return
     */
    public String getSubsSkuByPosition(int position) {
       /* if (position >= 0 && position < subsSKUS.length) {
            return subsSKUS[position];
        } else {
            return null;
        }*/
        return null;
    }

    /**
     * 通過序號獲取內(nèi)購sku
     *
     * @param position
     * @return
     */
    public String getInAppSkuByPosition(int position) {
      /*  if (position >= 0 && position < inAppSKUS.length) {
            return inAppSKUS[position];
        } else {
            return null;
        }*/
        return null;
    }

    /**
     * 通過sku獲取商品類型(訂閱獲取內(nèi)購)
     *
     * @param sku
     * @return inapp內(nèi)購,subs訂閱
     */
    public String getSkuType(String sku) {
       /* if (Arrays.asList(inAppSKUS).contains(sku)) {
            return BillingClient.SkuType.INAPP;
        } else if (Arrays.asList(subsSKUS).contains(sku)) {
            return BillingClient.SkuType.SUBS;
        }*/
        return null;
    }

    /**
     * 檢測GooglePlay服務(wù)是否可用(需要導(dǎo)入包api "com.google.android.gms:play-services-location:11.8.0",也可以不檢查,跳過這個(gè)代碼)
     *
     * @param context
     * @return
     */
    public static boolean isGooglePlayServicesAvailable(Context context) {
        GoogleApiAvailability googleApiAvailability = GoogleApiAvailability.getInstance();
        if (googleApiAvailability != null) {
            int resultCode = googleApiAvailability.isGooglePlayServicesAvailable(context);
            return resultCode == ConnectionResult.SUCCESS;
        }
        return false;
        //return_img true;//不檢查直接跳過
    }

    public GoogleBillingUtil setOnQueryFinishedListener(OnQueryFinishedListener onQueryFinishedListener) {
        mOnQueryFinishedListener = onQueryFinishedListener;
        return mGoogleBillingUtil;
    }

    public GoogleBillingUtil setOnPurchaseFinishedListener(OnPurchaseFinishedListener onPurchaseFinishedListener) {
        mOnPurchaseFinishedListener = onPurchaseFinishedListener;
        return mGoogleBillingUtil;
    }

    public OnStartSetupFinishedListener getOnStartSetupFinishedListener() {
        return mOnStartSetupFinishedListener;
    }

    public GoogleBillingUtil setOnStartSetupFinishedListener(OnStartSetupFinishedListener onStartSetupFinishedListener) {
        mOnStartSetupFinishedListener = onStartSetupFinishedListener;
        return mGoogleBillingUtil;
    }

    public static OnConsumeResponseListener getmOnConsumeResponseListener() {
        return mOnConsumeResponseListener;
    }

    public GoogleBillingUtil setOnConsumeResponseListener(OnConsumeResponseListener onConsumeResponseListener) {
        mOnConsumeResponseListener = onConsumeResponseListener;
        return mGoogleBillingUtil;
    }

    /**
     * 本工具查詢回調(diào)接口
     */
    public interface OnQueryFinishedListener {
        //Inapp和sub都走這個(gè)接口查詢的時(shí)候一定要判斷skuType
        public void onQuerySuccess(String skuType, List<SkuDetails> list);

        public void onQueryFail(int responseCode);

        public void onQueryError();
    }

    /**
     * 本工具購買回調(diào)接口(內(nèi)購與訂閱都走這接口)
     */
    public interface OnPurchaseFinishedListener {

        public void onPurchaseSuccess(Purchase purchase);

        public void onPurchaseFail(int responseCode);

        public void onPurchaseError();

    }

    /**
     * google服務(wù)啟動(dòng)接口
     */
    public interface OnStartSetupFinishedListener {
        public void onSetupSuccess();

        public void onSetupFail(int responseCode);

        public void onSetupError();
    }

    /**
     * 消耗回調(diào)監(jiān)聽器
     */
    public interface OnConsumeResponseListener {
        public void onConsumeSuccess(String purchaseToken);

        public void onConsumeFail(int responseCode);
    }

    public boolean isReady() {
        return mBillingClient != null && mBillingClient.isReady();
    }

    public boolean isAutoConsumeAsync() {
        return isAutoConsumeAsync;
    }

    public void setIsAutoConsumeAsync(boolean isAutoConsumeAsync) {
        this.isAutoConsumeAsync = isAutoConsumeAsync;
    }

    /**
     * 清除所有監(jiān)聽器,防止內(nèi)存泄漏
     * 如果有多個(gè)頁面使用了支付,需要確保上個(gè)頁面的cleanListener在下一個(gè)頁面的GoogleBillingUtil.getInstance()前使用。
     * 所以不建議放在onDestory里調(diào)用
     */
    public static void cleanListener() {
        mOnPurchaseFinishedListener = null;
        mOnQueryFinishedListener = null;
        mOnStartSetupFinishedListener = null;
        mOnConsumeResponseListener = null;
        if (builder != null) {
            builder.setListener(null);
        }
    }

    /**
     * 斷開連接google服務(wù)
     * 注意?。?!一般情況不建議調(diào)用該方法,讓google保留連接是最好的選擇。
     */
    public static void endConnection() {
        //注意?。?!一般情況不建議調(diào)用該方法,讓google保留連接是最好的選擇。
        if (mBillingClient != null) {
            if (mBillingClient.isReady()) {
                mBillingClient.endConnection();
                mBillingClient = null;
            }
        }
    }

    private static void log(String msg) {
        if (IS_DEBUG) {
            Log.i(TAG, msg);
        }
    }

    /**
     * 查詢失敗的訂單
     * skuType :,BillingClient.SkuType.INAPP;  BillingClient.SkuType.SUBS
     * 0:PurchaseState.UNSPECIFIED_STATE:未知狀態(tài)
     * 1:PurchaseState.PURCHASED:付款完成
     * 2:PurchaseState.PENDING:購買正在等待付款完成。
     */
    public void queryFailOrder(Activity activity, String skuType) {
        MyToash.Log("pay", "-----查詢需要補(bǔ)貨的商品:");
        if (mBillingClient != null) {
//            Purchase.PurchasesResult result = mBillingClient.queryPurchases(skuType);
//            if (BillingClient.BillingResponseCode.OK == result.getResponseCode()) {
//                for (Purchase purchase : result.getPurchasesList()) {
//                    //PURCHASED --已購買
//                    if (Purchase.PurchaseState.PURCHASED == purchase.getPurchaseState()) {
//                        //MyToash.Log("pay", "----------需要補(bǔ)貨的商品:");
//                        //調(diào)用google去消費(fèi)
//                        getConsumeGoods(activity, purchase, "");
//                    }
//                }
//            }
            QueryPurchasesParams queryPurchasesParams = QueryPurchasesParams.newBuilder()
                    .setProductType(skuType)
                    .build();
            mBillingClient.queryPurchasesAsync(queryPurchasesParams, new PurchasesResponseListener() {

                @Override
                public void onQueryPurchasesResponse(@NonNull BillingResult billingResult, @NonNull List<Purchase> list) {
                    if (list != null) {
                        if (billingResult.getResponseCode() == BillingClient.BillingResponseCode.OK) {
                            for (Purchase purchase : list) {
                                //PURCHASED --已購買
                                if (Purchase.PurchaseState.PURCHASED == purchase.getPurchaseState()) {
                                    MyToash.Log("pay", "----------需要補(bǔ)貨的商品:");
                                    //調(diào)用google去消費(fèi)
                                    getConsumeGoods(activity, purchase, "", skuType);
                                }
                            }
                        }
                    }
                }
            });
        }
    }

    /**
     * 公共消費(fèi)商品接口
     */
    public void getConsumeGoods(Activity activity, Purchase purchase, String price, String skuType) {
        if (purchase != null) {
            MyToash.Log("pay", "-----開始消耗商品:" + purchase.toString());

            if (skuType == BillingClient.ProductType.INAPP) {
                //普通消耗-本地發(fā)送書券成功之后,調(diào)用消耗接口
                ConsumeParams.Builder consumeParams = ConsumeParams.newBuilder();
                consumeParams.setPurchaseToken(purchase.getPurchaseToken());
                //調(diào)用普通消耗-商品方法
                consumeAsync(activity, consumeParams.build(), purchase, price);
            } else {
                //調(diào)用訂閱消耗-商品方法
                getConsumeSubscribeGoods(activity, purchase, price);
            }
        }
    }


    /**
     * 公共訂閱方法消費(fèi)
     */
    public void getConsumeSubscribeGoods(Activity activity, Purchase purchase, String price) {
        if (purchase != null) {
            if (purchase.getPurchaseState() == Purchase.PurchaseState.PURCHASED) {
                if (!purchase.isAcknowledged()) {

                    //本地記錄消費(fèi)的商品
                    saveRecordLoaclConsumeGoods(activity, purchase, 1, BillingClient.ProductType.SUBS);

                    AcknowledgePurchaseParams acknowledgePurchaseParams =
                            AcknowledgePurchaseParams.newBuilder()
                                    .setPurchaseToken(purchase.getPurchaseToken())
                                    .build();
                    mBillingClient.acknowledgePurchase(acknowledgePurchaseParams, new AcknowledgePurchaseResponseListener() {

                        @Override
                        public void onAcknowledgePurchaseResponse(@NonNull BillingResult billingResult) {
                            if (billingResult.getResponseCode() == BillingClient.BillingResponseCode.OK) {
                                MyToash.Log("pay", "-------消費(fèi)訂閱商品成功");
                                //移除
                                saveRecordLoaclConsumeGoods(activity, purchase, 2, BillingClient.ProductType.SUBS);
                                //請求本地接口
                                getHttpPay(activity, purchase, BillingClient.ProductType.SUBS);
                            } else {
                                MyToash.Log("pay", "-------消費(fèi)訂閱商品失?。? + billingResult.getResponseCode());
                            }
                        }
                    });
                } else {
                    WaitDialogUtils.dismissDialog();
                }
            } else {
                WaitDialogUtils.dismissDialog();
            }

        }
    }


    /**
     * 正常流程-調(diào)用本地接口發(fā)送書券和書幣
     */
    public void getHttpPay(Activity activity, Purchase purchase, String skuType) {
        if (purchase != null) {
            String pId = purchase.getSkus().get(0);
            String purchaseToken = purchase.getPurchaseToken();
            String packageName = purchase.getPackageName();
            //保存本地單據(jù)
            saveLocalFaileOrder(activity, purchase, skuType);
            //調(diào)用本地發(fā)書券接口
            GoPay.httpPay(activity, pId, purchaseToken, "", packageName, skuType, new GooglePayActivity.UpPay() {
                @Override
                public void paySuccess(String success) {
                    MyToash.Log("pay", "--本地接口調(diào)用成功:" + success);
                    //書的id
                    String bookId = MmkvUtils.decodeString(BaseKey.SP_BOOKID);
                    MmkvUtils.encode(BaseKey.SP_BOOKID, "");
                    ShareUitls.putString(activity, "goods_id", null);
                    ShareUitls.putString(activity, "productId", null);
                    ShareUitls.putString(activity, "productToken", null);

                    if (!TextUtils.isEmpty(bookId)) {
                        //不是空刷新閱讀器的支付頁面
                        EventBus.getDefault().post(new RefreshRead());
                    }
                    //通知刷新頁面
                    EventBus.getDefault().post(new RefreshMine());
                    //成功提示
                    MyToash.ToashSuccess(activity, success);
                    //刪除本地的數(shù)據(jù)
                    deleteLocalFaileOrder(activity, purchaseToken, skuType);
                    WaitDialogUtils.dismissDialog();
                }

                @Override
                public void payFail(String msg) {
                    //本地接口調(diào)用失敗
                    MyToash.Log("pay", "----本地接口調(diào)用失敗:" + msg);
                    WaitDialogUtils.dismissDialog();
                }
            });
        }
    }

    /**
     * 保存本地失敗的單據(jù)
     *
     * @param activity
     */
    private void saveLocalFaileOrder(Activity activity, Purchase purchase, String skuType) {
        try {
            String pId = purchase.getSkus().get(0);
            String purchaseToken = purchase.getPurchaseToken();
            String packageName = purchase.getPackageName();
            //用戶id
            String uid = UserUtils.getUID();
            List<String> list = new ArrayList<>();

            //獲取存儲(chǔ)的值
            String lastJson = MmkvUtils.decodeString(uid);
            if (!lastJson.isEmpty()) {
                //不是空,只有第一次請求失敗保存
                List<String> list2 = GsonUtil.GsonToList(lastJson, String.class);
                for (int i = 0; i < list2.size(); i++) {
                    String data = list2.get(i);
                    list.add(data);
                }
            }
            //沒有相同單據(jù),保存
            HashMap map = new HashMap();
            map.put("pId", pId);
            map.put("purchaseToken", purchaseToken);
            map.put("packageName", packageName);
            map.put("skuType", skuType);
            map.put("time", CommonPayUtilsKt.isSaveCurrentTime());
            list.add(GsonUtil.BeanToJson(map));

            String json = GsonUtil.BeanToJson(list);
            //保存上傳失敗的訂單
            MmkvUtils.encode(uid, json);
            MyToash.Log("pay", "----保存上傳失敗的訂單json:" + json);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /**
     * 刪除本地失敗的單據(jù)
     *
     * @param activity
     */
    private void deleteLocalFaileOrder(Activity activity, String purchaseToken, String skuType) {
        try {
            //用戶id
            String uid = UserUtils.getUID();
            String lastJson = MmkvUtils.decodeString(uid);
            if (!lastJson.isEmpty()) {
                MyToash.Log("pay", "----查詢準(zhǔn)備要?jiǎng)h除上傳失敗的訂單:" + lastJson);
                //不是空
                List<String> list = GsonUtil.GsonToList(lastJson, String.class);
                //是否有相等的下標(biāo)
                int index = -1;
                for (int i = 0; i < list.size(); i++) {
                    String data = list.get(i);
                    OrderFailBean bean = GsonUtil.GsonToBean(data, OrderFailBean.class);
                    String token = bean.getPurchaseToken();
                    if (purchaseToken.equals(token)) {
                        index = i;
                    }
                }
                //刪除數(shù)據(jù)
                if (index != -1) {
                    list.remove(index);
                    String json = GsonUtil.BeanToJson(list);
                    //保存數(shù)據(jù)
                    MmkvUtils.encode(uid, json);
                    MyToash.Log("pay", "----刪除上傳失敗的訂單:" + json);
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /**
     * 查詢訂單失敗--調(diào)用本地接口發(fā)送書券和書幣
     */
    public void getLocalFailOrder(Activity activity) {
        try {
            //用戶id
            String uid = UserUtils.getUID();
            List<String> list = new ArrayList<>();
            //獲取存儲(chǔ)的值
            String lastJson = MmkvUtils.decodeString(uid);
            MyToash.Log("pay", "---查詢失敗的訂單lastJson:" + lastJson);
            if (!lastJson.isEmpty()) {
                //不是空
                list = GsonUtil.GsonToList(lastJson, String.class);
                for (int i = 0; i < list.size(); i++) {
                    String data = list.get(i);
                    OrderFailBean bean = GsonUtil.GsonToBean(data, OrderFailBean.class);
                    String pId = bean.getpId();
                    long time = bean.getTime();
                    String purchaseToken = bean.getPurchaseToken();
                    String packageName = bean.getPackageName();
                    String skuType = bean.getSkuType();
                    if (CommonPayUtilsKt.isUploadLocalFailOrder(time)) {
                        //上傳失敗的單據(jù)
                        UploadLocalFailOrder(activity, uid, pId, packageName, purchaseToken, skuType);
                        Thread.sleep(1000);
                    }
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /**
     * 上傳本地單據(jù)
     *
     * @param pId
     * @param packageName
     * @param purchaseToken
     */
    private void UploadLocalFailOrder(Activity activity, String uid, String pId, String packageName, String purchaseToken, String skuType) {
        try {

            //調(diào)用本地發(fā)書券接口
            GoPay.httpPay(activity, pId, purchaseToken, "", packageName, skuType, new GooglePayActivity.UpPay() {
                @Override
                public void paySuccess(String success) {
                    MyToash.Log("pay", "后臺(tái)上傳失敗訂單成功:" + success);
                    //WaitDialogUtils.dismissDialog();
                    MmkvUtils.encode(BaseKey.SP_BOOKID, "");
                    ShareUitls.putString(activity, "goods_id", null);
                    ShareUitls.putString(activity, "productId", null);
                    ShareUitls.putString(activity, "productToken", null);
                    //通知刷新頁面
                    EventBus.getDefault().post(new RefreshMine());
                    //刪除本地的數(shù)據(jù)
                    deleteLocalFaileOrder(activity, purchaseToken, skuType);
                    //移除消費(fèi)無響應(yīng)數(shù)據(jù)
                    deleteRecordLoaclConsumeGoods(activity, pId, purchaseToken, packageName);
                }

                @Override
                public void payFail(String msg) {
                    //本地接口調(diào)用失敗
                    try {
                        if (!TextUtils.isEmpty(msg)) {
                            int subIndex = msg.indexOf(",");
                            if (subIndex > 0) {
                                String code = msg.substring(0, subIndex);
                                String message = msg.substring(subIndex, msg.length());
                                if ("806".equals(code)) {
                                    //刪除本地的數(shù)據(jù)
                                    deleteLocalFaileOrder(activity, purchaseToken, skuType);
                                    //移除消費(fèi)無響應(yīng)數(shù)據(jù)
                                    deleteRecordLoaclConsumeGoods(activity, pId, purchaseToken, packageName);
                                }
                            }
                        }
                        MyToash.Log("pay", "后臺(tái)上傳失敗訂單失敗:" + msg);
                    } catch (Exception e) {
                        e.printStackTrace();
                    }
                }
            });
        } catch (Exception e) {
            e.printStackTrace();
        }
    }


    /**
     * 新-只刪除消費(fèi)商品無響應(yīng)的狀態(tài)
     *
     * @param activity
     * @param lastJson
     * @param pId
     * @param purchaseToken
     * @param packageName
     */
    private void deleteRecordLoaclConsumeGoods(Activity activity, String pId, String purchaseToken, String packageName) {
        try {
            String uid_key = UserUtils.getUID() + CommonConstantUtils.CONSUME;
            List<String> list = new ArrayList<>();
            //獲取存儲(chǔ)的值
            String lastJson = MmkvUtils.decodeString(uid_key);
            //不是空
            if (!lastJson.isEmpty()) {
                int currentIndex = -1;
                List<String> list3 = GsonUtil.GsonToList(lastJson, String.class);
                for (int i = 0; i < list3.size(); i++) {
                    String data = list3.get(i);
                    list.add(data);
                    OrderFailBean bean = GsonUtil.GsonToBean(data, OrderFailBean.class);
                    String tokenKey = bean.getPurchaseToken() + CommonConstantUtils.CONSUME;
                    if ((tokenKey).equals(purchaseToken + CommonConstantUtils.CONSUME)) {
                        currentIndex = i;
                    }
                }
                if (currentIndex != -1) {
                    list.remove(currentIndex);
                    String json = GsonUtil.BeanToJson(list);
                    //保存上傳失敗的訂單
                    MmkvUtils.encode(uid_key, json);
                    MyToash.Log("pay", "--移除消耗的商品json:" + json);
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /**
     * 調(diào)用支付之前創(chuàng)建訂單
     * goods_id:商品ID
     * content_type:內(nèi)容類型 1小說
     */
    public void getCreateOrder(Activity activity, String goods_id, String content_type, CallCheckOrder CallCheckOrder) {
        ReaderParams params = new ReaderParams(activity);
        params.putExtraParams("goods_id", goods_id);
        params.putExtraParams("content_type", content_type);
        params.putExtraParams("book_id", MmkvUtils.decodeString(BaseKey.SP_BOOKID));
        String json = params.generateParamsJson();
        //調(diào)用本地發(fā)書券接口
        //MyToash.Log("lyy", "--json:" + json);
        HttpUtils.getInstance().sendRequestRequestParams(activity, Api.mCreateOrderUrl, json, new HttpUtils.ResponseListener() {
                    @Override
                    public void onResponse(final String result) {
                        WaitDialogUtils.dismissDialog();
                        MyToash.Log("pay", "--創(chuàng)建訂單成功" + result);
                        if (CallCheckOrder != null) {
                            CallCheckOrder.call("success");
                        }
                    }

                    @Override
                    public void onErrorResponse(String error) {
                        WaitDialogUtils.dismissDialog();
                        MyToash.Log("pay", "--創(chuàng)建訂單失敗" + error);
                    }
                }
        );
    }

    public interface CallCheckOrder {
        void call(String result);
    }
}
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請結(jié)合常識與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容