android 集成google支付sdk的流程


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


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM