1. 需要在google play console后台注冊開發者賬號,配置相關內購的商品等這是屬於運營來做
2. 在項目build.gradle文件添加
implementation 'com.google.android.gms:play-services-wallet:18.1.3' implementation 'com.android.billingclient:billing:3.0.3'
3.這邊是參考了網上的資料封裝的一個google支付工具類,這個類只支持4.0之前的google支付sdk,4.0的支付sdk有大的調整,這個暫時沒做兼容。后續有時間會寫一個兼容4.0的
public class GoogleBillingUtil {
private static final String TAG = "```GoogleBillingUtil";
private static final boolean IS_DEBUG = true;
private static String[] inAppSKUS;
private String[] subsSKUS = new String[]{"6"};//訂閱ID,必填
public static final String BILLING_TYPE_INAPP = BillingClient.SkuType.INAPP;//內購
public static final String BILLING_TYPE_SUBS = BillingClient.SkuType.SUBS;//訂閱
private static BillingClient mBillingClient;
private static BillingClient.Builder builder ;
private static OnPurchaseFinishedListener mOnPurchaseFinishedListener;
private static OnStartSetupFinishedListener mOnStartSetupFinishedListener ;
private static OnQueryFinishedListener mOnQueryFinishedListener;
private boolean isAutoConsumeAsync = true;//是否在購買成功后自動消耗商品
private static final GoogleBillingUtil mGoogleBillingUtil = new GoogleBillingUtil() ;
private GoogleBillingUtil()
{
}
public static GoogleBillingUtil getInstance(String productId)
{
//googleplay應用內商品欄,添加商品后得到
inAppSKUS = new String[]{productId};//內購ID,必填
cleanListener();
return mGoogleBillingUtil;
}
public GoogleBillingUtil build(Context context)
{
if(mBillingClient==null)
{
synchronized (mGoogleBillingUtil)
{
if(mBillingClient==null)
{
if(isGooglePlayServicesAvailable(context))
{
builder = BillingClient.newBuilder(context);
mBillingClient = builder.setListener(mGoogleBillingUtil.new MyPurchasesUpdatedListener()).enablePendingPurchases().build();
}
else
{
if(IS_DEBUG)
{
log("警告:GooglePlay服務處於不可用狀態,請檢查");
}
if(mOnStartSetupFinishedListener!=null)
{
mOnStartSetupFinishedListener.onSetupError();
}
}
}
else
{
builder.setListener(mGoogleBillingUtil.new MyPurchasesUpdatedListener());
}
}
}
else
{
builder.setListener(mGoogleBillingUtil.new MyPurchasesUpdatedListener());
}
synchronized (mGoogleBillingUtil)
{
if(mGoogleBillingUtil.startConnection())
{
mGoogleBillingUtil.queryInventoryInApp();
// mGoogleBillingUtil.queryInventorySubs();
mGoogleBillingUtil.queryPurchasesInApp();
}
}
return mGoogleBillingUtil;
}
public boolean startConnection()
{
if(mBillingClient==null)
{
log("初始化失敗:mBillingClient==null");
return false;
}
if(!mBillingClient.isReady())
{
mBillingClient.startConnection(new BillingClientStateListener() {
@Override
public void onBillingSetupFinished(@NonNull BillingResult billingResult) {
if (billingResult.getResponseCode() == BillingClient.BillingResponseCode.OK) {
queryInventoryInApp();
// queryInventorySubs();
queryPurchasesInApp();
if(mOnStartSetupFinishedListener!=null)
{
mOnStartSetupFinishedListener.onSetupSuccess();
}
}
else
{
log("初始化失敗:onSetupFail:code="+billingResult.getResponseCode());
if(mOnStartSetupFinishedListener!=null)
{
mOnStartSetupFinishedListener.onSetupFail(billingResult.getResponseCode());
}
}
}
@Override
public void onBillingServiceDisconnected() {
if(mOnStartSetupFinishedListener!=null)
{
mOnStartSetupFinishedListener.onSetupError();
}
log("初始化失敗:onBillingServiceDisconnected");
}
});
return false;
}
else
{
return true;
}
}
/**
* Google購買商品回調接口(訂閱和內購都走這個接口)
*/
private class MyPurchasesUpdatedListener implements PurchasesUpdatedListener
{
@Override
public void onPurchasesUpdated(@NonNull BillingResult billingResult, @Nullable List<Purchase> list) {
if(mOnPurchaseFinishedListener==null)
{
if(IS_DEBUG)
{
log("警告:接收到購買回調,但購買商品接口為Null,請設置購買接口。eg:setOnPurchaseFinishedListener()");
}
return ;
}
if(billingResult.getResponseCode()== BillingClient.BillingResponseCode.OK&&list!=null)
{
if(isAutoConsumeAsync)
{
//消耗商品
for(Purchase purchase:list)
{
// ArrayList<String> sku = purchase.getSkus();
String sku = purchase.getSku();
if(sku!=null)
{
// String skuType = getSkuType(sku.get(0));
String skuType = getSkuType(sku);
if(skuType!=null)
{
if(skuType.equals(BillingClient.SkuType.INAPP))
{
consumeAsync(purchase.getPurchaseToken());
}
}
}
}
}
mOnPurchaseFinishedListener.onPurchaseSuccess(list);
}
else
{
mOnPurchaseFinishedListener.onPurchaseFail(billingResult.getResponseCode());
}
}
}
/**
* 查詢內購商品信息
*/
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(mOnQueryFinishedListener,skuType));
}
};
executeServiceRequest(runnable);
}
/**
* Google查詢商品信息回調接口
*/
private class MySkuDetailsResponseListener implements SkuDetailsResponseListener
{
private OnQueryFinishedListener mOnQueryFinishedListener ;
private String skuType ;
private List<SkuDetails> list=new ArrayList<>();
public MySkuDetailsResponseListener(OnQueryFinishedListener onQueryFinishedListener,String skuType) {
mOnQueryFinishedListener = onQueryFinishedListener;
this.skuType = skuType;
}
@Override
public void onSkuDetailsResponse(@NonNull BillingResult billingResult, @Nullable List<SkuDetails> list) {
this.list=list;
if(mOnQueryFinishedListener==null)
{
if(IS_DEBUG) {
log("警告:接收到查詢商品回調,但查詢商品接口為Null,請設置購買接口。eg:setOnQueryFinishedListener()");
}
return ;
}
if(billingResult.getResponseCode()== BillingClient.BillingResponseCode.OK&&list!=null)
{
mOnQueryFinishedListener.onQuerySuccess(skuType,list);
}
else
{
mOnQueryFinishedListener.onQueryFail(billingResult.getResponseCode());
}
}
}
/**
* 發起內購
* @param skuId
* @return
*/
public void purchaseInApp(Activity activity,SkuDetails skuId)
{
purchase(activity,skuId, BillingClient.SkuType.INAPP);
}
/**
* 發起訂閱
* @param skuId
* @return
*/
public void purchaseSubs(Activity activity,SkuDetails skuId)
{
purchase(activity,skuId, BillingClient.SkuType.SUBS);
}
private void purchase(Activity activity,final SkuDetails skuId,final String skuType)
{
if(mBillingClient==null)
{
if(mOnPurchaseFinishedListener!=null)
{
mOnPurchaseFinishedListener.onPurchaseError();
}
return ;
}
if(startConnection())
{
BillingFlowParams flowParams = BillingFlowParams.newBuilder()
.setSkuDetails(skuId)
.build();
mBillingClient.launchBillingFlow(activity,flowParams);
}
else
{
if(mOnPurchaseFinishedListener!=null)
{
mOnPurchaseFinishedListener.onPurchaseError();
}
}
}
/**
* 消耗商品
* @param purchaseToken
*/
public void consumeAsync(String purchaseToken)
{
if(mBillingClient==null)
{
return ;
}
ConsumeParams consumeParams =
ConsumeParams.newBuilder()
.setPurchaseToken(purchaseToken)
.build();
mBillingClient.consumeAsync(consumeParams, new MyConsumeResponseListener());
}
/**
* Googlg消耗商品回調
*/
private class MyConsumeResponseListener implements ConsumeResponseListener
{
@Override
public void onConsumeResponse(@NonNull BillingResult billingResult, @NonNull String s) {
if (billingResult.getResponseCode() == BillingClient.BillingResponseCode.OK) {
Log.e("googlePayWay","消耗成功");
}
}
}
/**
* 獲取已經內購的商品
* @return
*/
public List<Purchase> queryPurchasesInApp()
{
return queryPurchases(BillingClient.SkuType.INAPP);
}
/**
* 獲取已經訂閱的商品
* @return
*/
public List<Purchase> queryPurchasesSubs()
{
return queryPurchases(BillingClient.SkuType.SUBS);
}
private List<Purchase> queryPurchases(String skuType)
{
if(mBillingClient==null)
{
return null;
}
if(!mBillingClient.isReady())
{
startConnection();
}
else
{
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(BillingClient.SkuType.INAPP))
{
consumeAsync(purchase.getPurchaseToken());
}
}
}
}
return purchaseList;
}
}
}
return null;
}
/**
* 獲取有效訂閱的數量
* @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獲取內購商品序號
* @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;
}
}
/**
* 通過序號獲取內購sku
* @param position
* @return
*/
public String getInAppSkuByPosition(int position)
{
if(position>=0&&position<inAppSKUS.length)
{
return inAppSKUS[position];
}
else
{
return null;
}
}
/**
* 通過sku獲取商品類型(訂閱獲取內購)
* @param sku
* @return inapp內購,subs訂閱
*/
private 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服務是否可用(需要導入包api "com.google.android.gms:play-services-location:11.8.0",也可以不檢查,跳過這個代碼)
* @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 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 interface OnQueryFinishedListener{
//Inapp和sub都走這個接口查詢的時候一定要判斷skuType
public void onQuerySuccess(String skuType, List<SkuDetails> list);
public void onQueryFail(int responseCode);
public void onQueryError();
}
/**
* 本工具購買回調接口(內購與訂閱都走這接口)
*/
public interface OnPurchaseFinishedListener{
public void onPurchaseSuccess(List<Purchase> list);
public void onPurchaseFail(int responseCode);
public void onPurchaseError();
}
/**
* google服務啟動接口
*/
public interface OnStartSetupFinishedListener{
public void onSetupSuccess();
public void onSetupFail(int responseCode);
public void onSetupError();
}
public boolean isReady() {
return mBillingClient!=null&&mBillingClient.isReady();
}
public boolean isAutoConsumeAsync()
{
return isAutoConsumeAsync;
}
public void setIsAutoConsumeAsync(boolean isAutoConsumeAsync)
{
this.isAutoConsumeAsync= isAutoConsumeAsync;
}
/**
* 清除所有監聽器,防止內存泄漏
* 如果有多個頁面使用了支付,需要確保上個頁面的cleanListener在下一個頁面的GoogleBillingUtil.getInstance()前使用。
* 所以不建議放在onDestory里調用
*/
public static void cleanListener()
{
mOnPurchaseFinishedListener = null;
mOnQueryFinishedListener = null;
mOnStartSetupFinishedListener = null;
if(builder!=null)
{
builder.setListener(null);
}
}
/**
* 斷開連接google服務
* 注意!!!一般情況不建議調用該方法,讓google保留連接是最好的選擇。
*/
public static void endConnection()
{
//注意!!!一般情況不建議調用該方法,讓google保留連接是最好的選擇。
if(mBillingClient!=null)
{
if(mBillingClient.isReady())
{
mBillingClient.endConnection();
mBillingClient = null;
}
}
}
private static void log(String msg)
{
if(IS_DEBUG)
{
Log.e(TAG,msg);
}
}
/**
* 是否支持內購
*/
public boolean isIabServiceAvailable(Context context)
{
final PackageManager packageManager = context.getPackageManager();
List<ResolveInfo> list = packageManager.queryIntentServices(getBindServiceIntent(), 0);
return list != null && list.size() > 0;
}
private Intent getBindServiceIntent()
{
Intent intent = new Intent("com.android.vending.billing.InAppBillingService.BIND");
intent.setPackage("com.android.vending");
return intent;
}
}
4.如何使用
首先需要定義三個類來實現購買回調接口,查詢商品回調接口,服務初始化結果回調接口
//服務初始化結果回調接口
private class MyOnStartSetupFinishedListener implements GoogleBillingUtil.OnStartSetupFinishedListener
{
@Override
public void onSetupSuccess() {
Log.e("googlePay","初始化成功");
}
@Override
public void onSetupFail(int responseCode) {
Log.e("googlePay","初始化失敗="+responseCode);
}
@Override
public void onSetupError() {
Log.e("googlePayWay","初始化錯誤");
}
//...;
}
//購買商品回調接口
private class MyOnPurchaseFinishedListener implements GoogleBillingUtil.OnPurchaseFinishedListener
{
@RequiresApi(api = Build.VERSION_CODES.O)
@Override
public void onPurchaseSuccess(List<Purchase> list) {
//內購或者訂閱成功,可以通過purchase.getSku()獲取suk進而來判斷是哪個商品
}
@Override
public void onPurchaseFail(int responseCode) {
Log.e("googlePayWay","購買失敗碼="+responseCode);
}
@Override
public void onPurchaseError() {
Log.e("googlePayWay","購買錯誤碼=");
}
}
//查詢商品信息回調接口
private class MyOnQueryFinishedListener implements GoogleBillingUtil.OnQueryFinishedListener
{
@Override
public void onQuerySuccess(String skuType,List<SkuDetails> list) {
//查詢成功,返回商品列表,
}
@Override
public void onQueryFail(int responseCode) {
//查詢失敗
Log.e("googlePayWay","查詢失敗="+responseCode);
}
@Override
public void onQueryError() {
//查詢錯誤
Log.e("googlePayWay","查詢錯誤");
}
}
然后在需要的地方加入以下代碼
private MyOnPurchaseFinishedListener mOnPurchaseFinishedListener = new MyOnPurchaseFinishedListener();//購買回調接口
private MyOnQueryFinishedListener mOnQueryFinishedListener = new MyOnQueryFinishedListener();//查詢回調接口
private MyOnStartSetupFinishedListener mOnStartSetupFinishedListener = new MyOnStartSetupFinishedListener();//服務初始化結果回調接口
GoogleBillingUtil googleBillingUtil = GoogleBillingUtil.getInstance(id)//這個id是google play console后台配置的商品id
.setOnPurchaseFinishedListener(mOnPurchaseFinishedListener)//購買回調接口
.setOnQueryFinishedListener(mOnQueryFinishedListener)//查詢商品回調接口
.setOnStartSetupFinishedListener(mOnStartSetupFinishedListener)//服務初始化結果回調接口
.build(context); googleBillingUtil.setIsAutoConsumeAsync(true);//購買成功之后是否消耗商品
到此支付流程集成完成,如果不能支付成功返回碼是3的話 這邊存在很多因素,首先檢查支付賬號是否可以購買paly商店商品,如何檢查可以直接去paly商店點擊付費,看列表是否有數據,如果沒有說明賬號不支持支付也google支付也就不能支付成功,在確保賬號沒問題的情況下還不能支付成功,看google play console后台是否添加了測試賬號,還有一點就是要測試必須要先上google play console內測才能測試,還有其他一些因素像paly商店是否支持sdk相對應的版本
到此結束,有問題的話可以留言一起探討(*  ̄3)(ε ̄ *)
