Administering In-app Billing
Security and Design
AndroidManifest.xml中必須增加底下宣告:
<uses-permission android:name="com.android.vending.BILLING" />Package的名稱必須Rename,
package com.wsj.android.trivialdrivesample;換入你上傳App後的金鑰,
String base64EncodedPublicKey = "MIIBIjANBgkqhkiG9w0B...省略.....";Google Play Console中,產生程式中購買的對應物品,以便測試
- 手機的primary gmail帳號要設成測試gmail帳號,不能用開發者的gmail帳號!
- APK必須發佈Alpha或Beta才能測試,利用所附的URL成為測試人員,然後下載APP.
- "錯誤!此項目目前無法購買"<----退出計畫,後重新成為測試人員!!
- 所欲購買項目必須啟動(in Active)
- "錯誤!請先入登入GOOGLE帳戶"<---加入Alpha/Beta測試計畫
- 測試帳號須登登錄信用卡資訊才能完成測試購買
//Does the user have the premium upgrade? boolean mIsPremium = false; //Does the user have an active subscription to the infinite gas plan? boolean mSubscribedToInfiniteGas = false; //SKUs for 產品:the premium upgrade(non-consumable)and gas(consumable) static final String SKU_PREMIUM = "premium"; static final String SKU_GAS = "gas"; //SKU for our 訂閱subscription (infinite gas) static final String SKU_INFINITE_GAS = "infinite_gas"; //(arbitrary) request code for the purchase flow static final int RC_REQUEST = 10001; //The helper object IabHelper mHelper; @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); //load game data loadData(); //建議不要直接用一個字串來設定,這樣比較容易被破解! String base64EncodedPublicKey ="...."; //產生helper物件,傳入context和金鑰 mHelper = new IabHelper(this, base64EncodedPublicKey); //設定debug logging(for a production app, set it to false) mHelper.enableDebugLogging(true); // Start setup. This is asynchronous and the specified listener // will be called once setup completes. mHelper.startSetup(new IabHelper.OnIabSetupFinishedListener() { public void onIabSetupFinished(IabResult result) { Log.d(TAG, "Setup finished."); if (!result.isSuccess()) { //有問題發生! complain("Problem in in-app billing:"+result); return; } // 起始成功,接著查詢此裝置已經擁有的物品 Log.d(TAG, "Setup successful.Querying inventory."); mHelper.queryInventoryAsync(mGotInventoryListener); } }); }
//當我們查詢購買物品和訂閱資訊時,系統會呼叫此Callback IabHelper.QueryInventoryFinishedListener mGotInventoryListener = new IabHelper.QueryInventoryFinishedListener() { public void onQueryInventoryFinished(IabResult result, Inventory inventory) { Log.d(TAG, "Query inventory finished."); if (result.isFailure()) { complain("Failed to query inventory: " + result); return; } Log.d(TAG, "Query inventory was successful."); /* *Check items we own.Notice that for each purchase,we check *the developer payload to see if it's correct! See *verifyDeveloperPayload(). */ // 檢查是否有升級成premium? Purchase premiumPurchase=inventory.getPurchase(SKU_PREMIUM); mIsPremium = (premiumPurchase != null && verifyDeveloperPayload(premiumPurchase)); Log.d(TAG,"User is"+(mIsPremium ?"PREMIUM":"NOT PREMIUM")); // 有訂閱無限汽油嗎?infinite gas subscription? Purchase infiniteGasPurchase= inventory.getPurchase(SKU_INFINITE_GAS); mSubscribedToInfiniteGas =(infiniteGasPurchase != null && verifyDeveloperPayload(infiniteGasPurchase)); Log.d(TAG, "User " + (mSubscribedToInfiniteGas ? "HAS": "DOES NOT HAVE")+ " infinite gas subscription."); if (mSubscribedToInfiniteGas) mTank = TANK_MAX; // 檢查是否有買汽油gas -- 如果有買,則立刻加入油箱。 Purchase gasPurchase = inventory.getPurchase(SKU_GAS); if(gasPurchase!=null&&verifyDeveloperPayload(gasPurchase)){ Log.d(TAG, "We have gas. Consuming it."); // 將汽油用掉 mHelper.consumeAsync(inventory.getPurchase(SKU_GAS), mConsumeFinishedListener); return; } updateUi(); setWaitScreen(false); Log.d(TAG, "Initial inventory query finished."); } };
//買汽油按"Buy Gas"按鈕 public void onBuyGasButtonClicked(View arg0) { Log.d(TAG, "Buy gas button clicked."); if (mSubscribedToInfiniteGas) { complain("No need!You're subscribed to infinite gas."); return; } if (mTank >= TANK_MAX) { complain("Your tank is full. Drive around a bit!"); return; } // launch the gas purchase UI flow. // notified of completion via mPurchaseFinishedListener setWaitScreen(true); Log.d(TAG, "Launching purchase flow for gas."); /*TODO:for security,generate your payload here for verification *verifyDeveloperPayload() for more info.We use *an empty string for example */ String payload = ""; mHelper.launchPurchaseFlow(this, SKU_GAS, RC_REQUEST, mPurchaseFinishedListener, payload); } //按"Upgrade to Premium"按鈕 public void onUpgradeAppButtonClicked(View arg0) { Log.d(TAG, "launching purchase flow for upgrade."); setWaitScreen(true); /*TODO:for security,generate your payload here for verification*/ String payload = ""; mHelper.launchPurchaseFlow(this, SKU_PREMIUM, RC_REQUEST, mPurchaseFinishedListener, payload); } //訂閱infinite gas public void onInfiniteGasButtonClicked(View arg0) { if (!mHelper.subscriptionsSupported()) { complain("Subscriptions not supported on your device yet!"); return; } String payload = ""; setWaitScreen(true); Log.d(TAG, "Launching purchase for infinite gas subscription."); mHelper.launchPurchaseFlow(this, SKU_INFINITE_GAS, IabHelper.ITEM_TYPE_SUBS, RC_REQUEST, mPurchaseFinishedListener, payload); } //當購買程序完成時,呼叫此Callback IabHelper.OnIabPurchaseFinishedListener mPurchaseFinishedListener = new IabHelper.OnIabPurchaseFinishedListener() { public void onIabPurchaseFinished(IabResult result,Purchase purchase){ Log.d(TAG,"Purchase ok:"+result+",purchase:"+purchase); if (result.isFailure()) { complain("Error purchasing: " + result); setWaitScreen(false); return; } if (!verifyDeveloperPayload(purchase)) { complain("Error purchasing.Authenticity failed."); setWaitScreen(false); return; } Log.d(TAG, "Purchase successful."); if (purchase.getSku().equals(SKU_GAS)) { // bought 1/4 tank of gas. So consume it. Log.d(TAG, "Starting gas consumption."); mHelper.consumeAsync(purchase, mConsumeFinishedListener); } else if (purchase.getSku().equals(SKU_PREMIUM)) { // bought the premium upgrade! Log.d(TAG,"Purchase is premium upgrade."); alert("Thank you for upgrading to premium!"); mIsPremium = true; updateUi(); setWaitScreen(false); } else if (purchase.getSku().equals(SKU_INFINITE_GAS)) { // bought the infinite gas subscription Log.d(TAG, "Infinite gas subscription purchased."); alert("Thank you for subscribing to infinite gas!"); mSubscribedToInfiniteGas = true; mTank = TANK_MAX; updateUi(); setWaitScreen(false); } } }; //當物品完成使用時,呼叫此callback IabHelper.OnConsumeFinishedListener mConsumeFinishedListener = new IabHelper.OnConsumeFinishedListener() { public void onConsumeFinished(Purchase purchase,IabResult result){ Log.d(TAG,"Consumption ok.Purchase:"+purchase+",result:"+result); //This is "gas" sku because it's the only one we consume, //so don't check which sku was consumed.If have more than one //sku, you probably should check... if (result.isSuccess()) { //successfully consumed,so apply effects of the item in //game world's,which means filling the gas tank a bit Log.d(TAG, "Consumption successful. Provisioning."); mTank = mTank == TANK_MAX ? TANK_MAX : mTank + 1; saveData(); alert("It's now"+String.valueOf(mTank)+"/4 full!"); } else { complain("Error while consuming: " + result); } updateUi(); setWaitScreen(false); Log.d(TAG, "End consumption flow."); } }; // 記得要在這裡釋放helper物件! @Override public void onDestroy() { super.onDestroy(); // very important: Log.d(TAG, "Destroying helper."); if (mHelper != null) mHelper.dispose(); mHelper = null; }
執行截圖:
沒有留言:
張貼留言