1. 程式人生 > >Google play之應用內支付接入

Google play之應用內支付接入

前言

官方文件

官方Sample

google提供的官方sample是已經對官方api經過封裝了的,而google官方文件是按照最原裝的程式碼進行
描述的,所以本文將按照sample方式接入

SDK接入

  • google應用內支付不用新增jar包,不用新增依賴,只需要一個aidl檔案:IInAppBillingService.aidl 可以從sample中獲得,並且將其放在: com.android.vending.billing包下
  • 將sample中的util中的所用類拷貝到自己的專案的util下,這些類是已經對官方的api進行二次封裝了

配置資原始檔

在AndroidManifest.xml檔案中,新增以下許可權:

<uses-permission android:name="com.android.vending.BILLING" />

SDK中的API呼叫

  • 初始化
//設定自己從google控制檯得到的公鑰
 mHelper = new IabHelper(activity, "YOUR_PUBLIC_KEY");
        //除錯模式
        mHelper.enableDebugLogging(true);
        Log.d(TAG, "Starting setup.");
        mHelper.startSetup(new IabHelper.
OnIabSetupFinishedListener() { @Override public void onIabSetupFinished(IabResult result) { Log.d(TAG, "Setup finished."); if (!result.isSuccess()) { Log.d(TAG, "Setup fail."); return; } if
(mHelper == null){ Log.d(TAG, "Setup fail."); return; } Log.d(TAG, "Setup success."); } });
  • 查詢庫存
/**
     * 查詢庫存
     * */
 private void queryInventory(){
        Log.e(TAG, "Query inventory start");
        try {
            mHelper.queryInventoryAsync(mGotInventoryListener);
        } catch (IabHelper.IabAsyncInProgressException e) {
            e.printStackTrace();
        }
    }

/**查詢庫存的回撥*/
private IabHelper.QueryInventoryFinishedListener mGotInventoryListener = new IabHelper.QueryInventoryFinishedListener() {
        @Override
        public void onQueryInventoryFinished(IabResult result, Inventory inventory) {
            Log.e(TAG, "Query inventory finished.");
            if (result.isFailure()) {
                Log.e(TAG, "Failed to query inventory: " + result);
                return;
            }
            Log.e(TAG, "Query inventory was successful." + inventory.getPurchase(mPayInfo.getProductId()));
            if (inventory.hasPurchase(mPayInfo.getProductId())){
                //庫存存在使用者購買的產品,先去消耗
            }else{
                //庫存不存在
            }
        }
    };
  • 購買商品
    google應用內支付呼叫購買介面的時候,應先確保使用者沒有存在這個商品的購買(買了但是沒有消耗)
//在合適的地方呼叫購買
mHelper.launchPurchaseFlow(mActivity, sku, RC_REQUEST, mPurchaseFinishedListener, extra);

購買的回撥

private IabHelper.OnIabPurchaseFinishedListener mPurchaseFinishedListener = new IabHelper.OnIabPurchaseFinishedListener() {
        @Override
        public void onIabPurchaseFinished(IabResult result, Purchase purchase) {
            Log.d(TAG, "Purchase finished: " + result + ", purchase: " + purchase);
            if (result.isFailure()) {
                // Oh noes! pay fail
                Log.d(TAG,"Error purchasing: " + result);
                return;
            }

            Log.d(TAG, "Purchase successful.");
            //模擬檢測public key
            checkPk(purchase);
        }
    };

購買成功後,應該將購買返回的資訊傳送到自己的服務端,自己的服務端再去利用public key去驗籤

  • 消耗商品
    使用者購買成功後,如果是可重複購買的商品,應該立刻將這個商品消耗掉,以及在購買之前應確保使用者不存在這個商品,如果存在就呼叫消耗商品的介面去將商品消耗掉
mHelper.consumeAsync(purchase, mConsumeFinishedListener);

消耗商品的回撥

 private IabHelper.OnConsumeFinishedListener mConsumeFinishedListener = new IabHelper.OnConsumeFinishedListener() {
        @Override
        public void onConsumeFinished(Purchase purchase, IabResult result) {
            Log.d(TAG, "Consumption finished. Purchase: " + purchase + ", result: " + result);
            if (result.isSuccess()) {
                Log.d(TAG, "Consumption successful. Provisioning.");
            }
            else {
                Log.d(TAG,"Error while consuming: " + result);
            }
        }
    };

安全問題

  • 由於利用官方的sample實現方式是在app客戶端利用公鑰進行驗籤, 也就是將支付的回撥暴露在客戶端了,這種方式不可取,可以對sample裡面進行驗籤的部分程式碼進行改造,取消本地驗籤,然後將支付成功回撥的資訊傳輸到自己伺服器,在伺服器驗籤再將結果返回給客戶端

常見問題

  • 確保包名和google控制檯配置一致
  • 確保購買時候傳輸的productId和在google控制檯配置一致
  • 確保App的version和google控制檯的version一致
  • 確保keystore和上傳到google控制檯的keystore一致