最近因爲項目需要加入googleplay的內購功能~所以網上找了很多資料,這裏做個記號~
官方的內購支付接入文檔:https://developer.android.com/training/in-app-billing/index.html
網上別人的資料:http://zengrong.net/post/1801.htm
下面用到的所有代碼都來自Google官方給的Demo,大概路徑是:<android_sdk>/extras/google/play_billing/
Google Play開發者後臺需要的配置
1.測試時需要把app正式簽名後上傳到googlepay的後臺
2.網上說測試需要把賬號添加到後臺而且得用信用卡來測試(這個本人沒測過)
3.需要在google play後臺給對應的apk添加產品
關於產品的說明:
a.產品分爲不受管理的商品(消耗品,比如遊戲中的金幣)和受管理的商品(一次性購買即屬於本賬號,比如某些遊戲需要玩家付費後纔可以使用完整版本)
b.受管理類產品需要考慮如果玩家用同一個支付賬號到別的設備完同一款遊戲,這時需要考慮把那個設備也設置成已支付
c.產品的id是唯一的字符串定義,比如com.engine.produce01
d.後臺添加產品後需要激活
代碼部分(使用的是version3 api)
IabHelper類
初始化方法
mHelper=new IabHelper(this, base64EncodedPublicKey);
這裏的base64EncodedPublicKey是googleplay後臺的發佈產品的時候生成提供的
mHelper.startSetup(new IabHelper.OnIabSetupFinishedListener() {
public void onIabSetupFinished(IabResult result) {
Log.d(TAG, "Setup finished.");
if (!result.isSuccess()) {
// Oh noes, there was a problem.
complain("Problem setting up in-app billing: " + result);
return;
}
// Hooray, IAB is fully set up. Now, let's get an inventory of stuff we own.
Log.d(TAG, "Setup successful. Querying inventory.");
mHelper.queryInventoryAsync(mGotInventoryListener);
}
});
startSetup 的操作是檢查是否有權限和連接到Google Billing service是否成功;這裏回調的操作是如果成功,調用queryInventoryAsync查看產品id是否可以使用;
查詢完成後會調用IabHelper.QueryInventoryFinishedListener 這個回調接口進行通知,在這個接口中可以獲取商品的詳細信息SkuDetails和Purchase信息。
點擊購買按鈕,需要調用的支付方法
String payload = "";
mHelper.launchPurchaseFlow(Activity act, String sku, String itemType, int requestCode, OnIabPurchaseFinishedListener listener, String payload);
boolean verifyDeveloperPayload(Purchase p) {
String payload = p.getDeveloperPayload();
/*
* TODO: verify that the developer payload of the purchase is correct. It will be
* the same one that you sent when initiating the purchase.
*
* WARNING: Locally generating a random string when starting a purchase and
* verifying it here might seem like a good approach, but this will fail in the
* case where the user purchases an item on one device and then uses your app on
* a different device, because on the other device you will not have access to the
* random string you originally generated.
*
* So a good developer payload has these characteristics:
*
* 1. If two different users purchase an item, the payload is different between them,
* so that one user's purchase can't be replayed to another user.
*
* 2. The payload must be such that you can verify it even when the app wasn't the
* one who initiated the purchase flow (so that items purchased by the user on
* one device work on other devices owned by the user).
*
* Using your own server to store and verify developer payloads across app
* installations is recommended.
*/
return true;
}
verifyDeveloperPayload這個方法是在支付完成的時候在回調裏頭去驗證用的,關於payload的生產,看上面官方給的demo的註釋,大概理解了下:
1.不同的玩家所生成的payload需要不一樣
2.即使玩家在不同設備上初始化payload,也要可以通過~
大概是這個意思(如果翻譯有問題~砸磚吧~)
下面是支付方法回調的監聽:
IabHelper.OnIabPurchaseFinishedListener mPurchaseFinishedListener = new IabHelper.OnIabPurchaseFinishedListener() {
public void onIabPurchaseFinished(IabResult result, Purchase purchase) {
Log.d(TAG, "Purchase finished: " + result + ", purchase: " + purchase);
if (result.isFailure()) {
complain("Error purchasing: " + result);
setWaitScreen(false);
return;
}
if (!verifyDeveloperPayload(purchase)) {
complain("Error purchasing. Authenticity verification 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, "Purchase is gas. 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. Congratulating user.");
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);
}
}
};
上面有中文註釋的地方調用了mHelper.consumeAsync這個方法,這裏應該是隻有非管理類的產品才需要調用的方法;相當於在購買成功後調用消耗(可以理解爲消耗一個道具)
在IabHelper.OnConsumeFinishedListener的回調用於處理成功調用成功支付的邏輯(這裏可能還需要一步去調用遠程服務器驗證)