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