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)(ε ̄ *)