本篇文章是官網(wǎng)中文版。有外網(wǎng)的小伙伴可以直接訪問官網(wǎng)地址和代碼示例
https://developer.android.com/google/play/billing/billing_integrate?hl=zh-cn
https://github.com/googlesamples/android-play-billing
In-app Billing API
您的應(yīng)用會(huì)通過相應(yīng) API (由設(shè)備上安裝的 Google Play 應(yīng)用提供)來訪問應(yīng)用內(nèi)購(gòu)買結(jié)算服務(wù)。 然后,Google Play 應(yīng)用會(huì)在您的應(yīng)用和 Google Play 服務(wù)器之間傳送購(gòu)買結(jié)算請(qǐng)求和響應(yīng)。 實(shí)際上,您的應(yīng)用從不直接與 Google Play 服務(wù)器通信。 而是通過進(jìn)程間通信 (IPC) 向 Google Play 應(yīng)用發(fā)送購(gòu)買結(jié)算請(qǐng)求并接收 Google Play 應(yīng)用發(fā)來的響應(yīng)。此外,您的應(yīng)用也不管理其與 Google Play 服務(wù)器之間的任何網(wǎng)絡(luò)連接。
應(yīng)用內(nèi)購(gòu)買結(jié)算只能在您通過 Google Play 發(fā)布的應(yīng)用中實(shí)現(xiàn)。 要完成應(yīng)用內(nèi)購(gòu)買請(qǐng)求,Google Play 應(yīng)用必須能夠通過網(wǎng)絡(luò)訪問 Google Play 服務(wù)器。
應(yīng)用內(nèi)購(gòu)買結(jié)算版本 3 是最新版本,依然具有非常廣泛的兼容性,可用于各種 Android 設(shè)備。 運(yùn)行 Android 2.2(API 級(jí)別 8)或更高版本且安裝了最新版本的 Google Play 應(yīng)用的設(shè)備(絕大多數(shù)有效設(shè)備)都支持使用應(yīng)用內(nèi)購(gòu)買結(jié)算版本 3。
版本 3 的功能
應(yīng)用內(nèi)購(gòu)買結(jié)算版本 3 提供以下功能:
- 您的應(yīng)用通過簡(jiǎn)化的 API 發(fā)送請(qǐng)求,讓用戶可以輕松地向 Google Play 請(qǐng)求商品詳情并訂購(gòu)應(yīng)用內(nèi)商品。 API 可以根據(jù)用戶對(duì)商品的所有權(quán)快速恢復(fù)商品。
- API 會(huì)在購(gòu)買完成時(shí)將訂單信息同步傳送至設(shè)備。
- 所有購(gòu)買都是托管的(也就是說,Google Play 負(fù)責(zé)跟蹤用戶對(duì)應(yīng)用內(nèi)商品的所有權(quán))。 用戶無(wú)論何時(shí)都只能擁有同一應(yīng)用內(nèi)商品的一個(gè)副本而不能擁有多個(gè)副本。
- 您可以消耗所購(gòu)商品。消耗后,此商品將切換回未被擁有狀態(tài),且可被用戶從 Google Play 中再次購(gòu)買。
- API 支持訂閱。
如需了解有關(guān)其他版本的應(yīng)用內(nèi)購(gòu)買結(jié)算的詳情,請(qǐng)參閱版本說明。
應(yīng)用內(nèi)商品
應(yīng)用內(nèi)商品是您在應(yīng)用內(nèi)向用戶出售的數(shù)字商品。 包括游戲內(nèi)貨幣、旨在改善用戶體驗(yàn)的應(yīng)用功能升級(jí)以及應(yīng)用中的新增內(nèi)容。
應(yīng)用內(nèi)購(gòu)買結(jié)算只能用于銷售數(shù)字內(nèi)容,而不能用于銷售實(shí)體商品、個(gè)人服務(wù)或任何需要進(jìn)行實(shí)物交付的商品/服務(wù)。 與明碼標(biāo)價(jià)的應(yīng)用不同,在用戶購(gòu)買應(yīng)用內(nèi)商品后,系統(tǒng)不會(huì)提供退款窗口。
Google Play 不提供任何形式的內(nèi)容交付。您需要自行負(fù)責(zé)在應(yīng)用中出售的數(shù)字內(nèi)容的交付。 應(yīng)用內(nèi)商品始終僅與一個(gè)應(yīng)用明確關(guān)聯(lián)。 也就是說,在一個(gè)應(yīng)用中不能購(gòu)買為另一個(gè)應(yīng)用發(fā)布的應(yīng)用內(nèi)商品,即使這兩個(gè)應(yīng)用來自相同的開發(fā)者也是如此。
商品類型
應(yīng)用內(nèi)購(gòu)買結(jié)算支持多種商品類型,因此您可靈活選擇如何通過您的應(yīng)用獲利。 無(wú)論是哪種商品,您均能通過 Google Play Developer Console 進(jìn)行定義。
您可以為應(yīng)用內(nèi)購(gòu)買結(jié)算應(yīng)用指定以下兩類商品:托管的應(yīng)用內(nèi)商品和訂閱。 Google Play 會(huì)針對(duì)每位用戶處理和跟蹤您應(yīng)用中的應(yīng)用內(nèi)商品和訂閱的所有權(quán)。詳細(xì)了解應(yīng)用內(nèi)購(gòu)買結(jié)算版本 3 支持的商品類型。
Google Play Developer Console
在 Developer Console 上,您不僅能發(fā)布應(yīng)用內(nèi)購(gòu)買結(jié)算應(yīng)用,還能管理在您應(yīng)用中可以購(gòu)買的各種應(yīng)用內(nèi)商品。
對(duì)于與您的應(yīng)用相關(guān)聯(lián)的數(shù)字商品(包括一次性商品和定期訂閱),您可以為其創(chuàng)建商品列表。 對(duì)于每件商品,您都可以定義下列信息:
- 唯一商品 ID(也稱為 SKU)。
- 商品類型。
- 定價(jià)。
- 說明。
- Google Play 應(yīng)如何處理和跟蹤用戶對(duì)該商品的購(gòu)買。
如果您以相同價(jià)格出售多個(gè)應(yīng)用或應(yīng)用內(nèi)商品,可以添加定價(jià)模板,從集中的位置來管理這些價(jià)格。 使用定價(jià)模板時(shí),您可以在提供的價(jià)格中包含地方稅,或者您也可以提供價(jià)格并讓系統(tǒng)為這些價(jià)格添加地方稅。 您可以對(duì)定價(jià)模板中的價(jià)格進(jìn)行更改(例如更新一些國(guó)家/地區(qū)的匯率),您的更改會(huì)應(yīng)用到與此模板關(guān)聯(lián)的應(yīng)用和應(yīng)用內(nèi)商品。
您還可以創(chuàng)建測(cè)試帳戶,授權(quán)這些帳戶測(cè)試尚未發(fā)布的應(yīng)用。
要了解如何使用 Developer Console 配置您的應(yīng)用內(nèi)商品和商品列表,請(qǐng)參閱管理應(yīng)用內(nèi)購(gòu)買結(jié)算 。
Google Play 購(gòu)買流程
Google Play 使用的結(jié)賬后端服務(wù)與用于應(yīng)用購(gòu)買的服務(wù)相同,因此您的用戶將獲得一致且熟悉的購(gòu)買流程體驗(yàn)。
重要說明:您必須有 Google Payments 商家?guī)ぬ?hào)才能在 Google Play 上使用應(yīng)用內(nèi)購(gòu)買結(jié)算服務(wù)。
購(gòu)買開始時(shí),您的應(yīng)用需要針對(duì)相應(yīng)的應(yīng)用內(nèi)商品發(fā)送購(gòu)買結(jié)算請(qǐng)求。 然后,Google Play 會(huì)處理此次交易的所有結(jié)賬詳情,包括請(qǐng)求和驗(yàn)證付款方式以及處理財(cái)務(wù)交易。
結(jié)賬流程完成后,Google Play 會(huì)向您的應(yīng)用發(fā)送購(gòu)買詳情,例如訂單號(hào)、訂單日期和時(shí)間以及所付價(jià)格。 您的應(yīng)用從不需要處理任何財(cái)務(wù)交易,這些事宜完全由 Google Play 負(fù)責(zé)。
示例應(yīng)用
為了幫助您將應(yīng)用內(nèi)購(gòu)買結(jié)算集成到應(yīng)用中,Android SDK 提供了一個(gè)示例應(yīng)用,向您演示如何在應(yīng)用內(nèi)銷售應(yīng)用內(nèi)商品和訂閱。
適用于 Version 3 API 的 TrivialDrive 示例演示了如何使用 In-app Billing Version 3 API 在賽車游戲中實(shí)現(xiàn)應(yīng)用內(nèi)商品和訂閱購(gòu)買。 該應(yīng)用不僅演示了如何發(fā)送應(yīng)用內(nèi)購(gòu)買結(jié)算請(qǐng)求以及處理來自 Google Play 的同步響應(yīng), 還演示了如何通過此 API 記錄商品的消耗情況。 版本 3 示例包括多種工具類,非常便于處理應(yīng)用內(nèi)購(gòu)買結(jié)算操作和執(zhí)行自動(dòng)簽名驗(yàn)證。
建議:請(qǐng)務(wù)必在發(fā)布應(yīng)用前混淆其中的代碼。 如需了解詳細(xì)信息,請(qǐng)參閱安全性和設(shè)計(jì)。
混淆您的代碼
您應(yīng)混淆應(yīng)用內(nèi)購(gòu)買結(jié)算代碼,讓攻擊者難以對(duì)您的安全協(xié)議和其他應(yīng)用組件進(jìn)行反向工程。 我們建議您至少對(duì)代碼運(yùn)行 Proguard 等代碼混淆工具。
除了運(yùn)行代碼混淆程序以外,我們還建議您使用以下技術(shù)混淆您的應(yīng)用內(nèi)購(gòu)買結(jié)算代碼。
- 將方法內(nèi)嵌入其他方法中。
- 創(chuàng)建動(dòng)態(tài)字符串,而不是將其定義為常量。
- 使用 Java 反射來調(diào)用方法。
使用這些技術(shù)有助于縮小應(yīng)用的受攻擊范圍,并最大程度幫助您抵御會(huì)對(duì)應(yīng)用內(nèi)購(gòu)買結(jié)算實(shí)現(xiàn)造成損害的攻擊。
-keep class com.android.vending.billing.**
遷移注意事項(xiàng)
In-app Billing Version 2 API 已于 2015 年 1 月關(guān)閉。如果您現(xiàn)有的應(yīng)用內(nèi)購(gòu)買結(jié)算實(shí)現(xiàn)使用的是 API 版本 2 或更低版本,則必須遷移到應(yīng)用內(nèi)購(gòu)買結(jié)算版本 3。
遷移后,托管和未托管的商品處理方式如下:
- 您之前在 Developer Console 中定義的托管商品和訂閱仍能使用版本 3。
- 對(duì)于您已經(jīng)為現(xiàn)有應(yīng)用定義的非托管商品,如果您使用 Version 3 API 針對(duì)這些商品發(fā)起購(gòu)買請(qǐng)求,這些商品將被視為托管商品。 您無(wú)需在 Developer Console 中為這些商品創(chuàng)建新的商品條目,且能使用相同的商品 ID 來管理這些商品。
實(shí)現(xiàn)應(yīng)用內(nèi)購(gòu)買結(jié)算
Google Play 上的應(yīng)用內(nèi)購(gòu)買結(jié)算提供了一個(gè)直接、簡(jiǎn)單的界面,讓您可以使用 Google Play 發(fā)送應(yīng)用內(nèi)購(gòu)買結(jié)算請(qǐng)求和管理應(yīng)用內(nèi)購(gòu)買結(jié)算交易。 下面的信息涵蓋了如何使用 API 版本 3 從您的應(yīng)用調(diào)用應(yīng)用內(nèi)購(gòu)買結(jié)算服務(wù)的基本知識(shí)。
注:要查看完整實(shí)現(xiàn)并了解如何測(cè)試您的應(yīng)用,請(qǐng)參閱出售應(yīng)用內(nèi)商品培訓(xùn)課程。 培訓(xùn)課程提供了一個(gè)完整的示例應(yīng)用內(nèi)購(gòu)買結(jié)算應(yīng)用,包括多種工具類,便于處理關(guān)鍵任務(wù)(例如設(shè)置您的連接、發(fā)送購(gòu)買結(jié)算請(qǐng)求和處理來自 Google Play 的響應(yīng)以及管理后臺(tái)線程),這樣您就可以從主 Activity 調(diào)用應(yīng)用內(nèi)購(gòu)買結(jié)算。
開始前,請(qǐng)務(wù)必閱讀應(yīng)用內(nèi)購(gòu)買結(jié)算概覽,以便熟悉一些概念,使您能夠輕松實(shí)現(xiàn)應(yīng)用內(nèi)購(gòu)買結(jié)算。
要在您的應(yīng)用中實(shí)現(xiàn)應(yīng)用內(nèi)購(gòu)買結(jié)算,您需要執(zhí)行以下操作:
- 將應(yīng)用內(nèi)購(gòu)買結(jié)算庫(kù)添加到您的項(xiàng)目中。
- 更新您的
AndroidManifest.xml
文件。 - 創(chuàng)建
ServiceConnection
并將其綁定到IInAppBillingService
。 - 從您的應(yīng)用發(fā)送應(yīng)用內(nèi)購(gòu)買結(jié)算請(qǐng)求至
IInAppBillingService
。 - 處理來自 Google Play 的應(yīng)用內(nèi)購(gòu)買結(jié)算請(qǐng)求響應(yīng)。
將 AIDL 文件添加到您的項(xiàng)目中
IInAppBillingService.aidl
是一種定義應(yīng)用內(nèi)購(gòu)買結(jié)算版本 3 服務(wù)接口的 Android 接口定義語(yǔ)言 (AIDL) 文件。 您可以使用此接口通過調(diào)用 IPC 方法調(diào)用來發(fā)送結(jié)算請(qǐng)求。
要獲取 AIDL 文件,請(qǐng)執(zhí)行以下操作:
- 打開 Android SDK 管理器。
- 在 SDK 管理器中,展開
Extras
部分。 - 選擇 Google Play Billing Library。
- 點(diǎn)擊 Install packages 完成下載。
IInAppBillingService.aidl
文件將安裝到 <sdk>/extras/google/play_billing/
。
要將 AIDL 添加到您的項(xiàng)目,請(qǐng)執(zhí)行以下操作:
- 首先,下載 Google Play Billing Library 到您的 Android 項(xiàng)目:
- 選擇 Tools > Android > SDK Manager。
- 在 Appearance & Behavior > System Settings > Android SDK 下面,選擇 SDK Tools 標(biāo)簽以選擇并下載 Google Play Billing Library。
- 接下來,復(fù)制
IInAppBillingService.aidl
文件到您的項(xiàng)目。- 如果您使用的是 Android Studio,請(qǐng)執(zhí)行以下操作:
- 導(dǎo)航至 Project 工具窗口中的
src/main
。 - 選擇 File > New > Directory,然后在 New Directory 窗口中輸入
aidl
,再選擇 OK。 - 選擇 File > New > Package,然后在 New Package 窗口中輸入
com.android.vending.billing
,再選擇 OK。 - 使用您的操作系統(tǒng)文件資源管理器,導(dǎo)航至
<sdk>/extras/google/play_billing/
,復(fù)制IInAppBillingService.aidl
文件,然后將其粘貼到項(xiàng)目中的com.android.vending.billing
軟件包。
- 導(dǎo)航至 Project 工具窗口中的
- 如果您在非 Android Studio 環(huán)境中開發(fā),請(qǐng)執(zhí)行以下操作:創(chuàng)建目錄
/src/com/android/vending/billing
,并將IInAppBillingService.aidl
文件復(fù)制到此目錄。 將 AIDL 文件添加到您的項(xiàng)目中并使用 Gradle 工具構(gòu)建項(xiàng)目,從而生成IInAppBillingService.java
文件。
- 如果您使用的是 Android Studio,請(qǐng)執(zhí)行以下操作:
- 開發(fā)您的應(yīng)用。您會(huì)在項(xiàng)目的
/gen
目錄中看到名為IInAppBillingService.java
的生成文件。
更新您的應(yīng)用清單
應(yīng)用內(nèi)購(gòu)買結(jié)算依賴于 Google Play 應(yīng)用,后者將處理應(yīng)用與 Google Play 服務(wù)器之間的所有通信。 要使用 Google Play 應(yīng)用,您的應(yīng)用必須請(qǐng)求適當(dāng)?shù)臋?quán)限。 您可以通過將 com.android.vending.BILLING
權(quán)限添加到 AndroidManifest.xml 文件執(zhí)行此操作。 如果您的應(yīng)用未聲明應(yīng)用內(nèi)購(gòu)買結(jié)算權(quán)限,但試圖發(fā)送結(jié)算請(qǐng)求,Google Play 將拒絕請(qǐng)求并使用錯(cuò)誤響應(yīng)。
要為您的應(yīng)用授予必要的權(quán)限,請(qǐng)?jiān)?AndroidManifest.xml
文件中添加以下代碼行:
<uses-permission android:name="com.android.vending.BILLING" />
創(chuàng)建 ServiceConnection
您的應(yīng)用必須擁有 ServiceConnection才能實(shí)現(xiàn)應(yīng)用與 Google Play 之間的通信。 您的應(yīng)用至少需要執(zhí)行以下操作:
- 綁定到
IInAppBillingService
。 - 發(fā)送結(jié)算請(qǐng)求(作為 IPC 方法調(diào)用)至 Google Play 應(yīng)用。
- 處理每個(gè)結(jié)算請(qǐng)求返回的同步響應(yīng)消息。
綁定到 InAppBillingService
要在 Google Play 上與應(yīng)用內(nèi)購(gòu)買結(jié)算服務(wù)建立連接,請(qǐng)實(shí)現(xiàn) ServiceConnection
,以便將您的 Activity 綁定到 IInAppBillingService
。
建立連接后,重寫 onServiceDisconnected(android.content.ComponentName))
和 onServiceConnected(android.content.ComponentName, android.os.IBinder))
方法以獲取 IInAppBillingService
實(shí)例的引用。
IInAppBillingService mService;
ServiceConnection mServiceConn = new ServiceConnection()
{
@Override
public void onServiceDisconnected(ComponentName name)
{
mService = null;
}
@Override
public void onServiceConnected(ComponentName name, IBinder service)
{
mService = IInAppBillingService.Stub.asInterface(service);
}
};
在您 Activity 的 onCreate(android.os.Bundle))
方法中,通過調(diào)用 bindService(android.content.Intent,android.content.ServiceConnection,int))
方法執(zhí)行綁定。 向方法傳遞引用應(yīng)用內(nèi)購(gòu)買結(jié)算服務(wù)的 Intent(
和您創(chuàng)建的一個(gè) ServiceConnection
實(shí)例,并明確地將 Intent 的目標(biāo)軟件包名稱設(shè)置為 com.android.vending
— Google Play 應(yīng)用的軟件包名稱。
注意:要保護(hù)結(jié)算交易的安全性,請(qǐng)始終確保使用下面示例中所示的 setPackage()(java.lang.String))
明確地將 Intent 的目標(biāo)軟件包名稱設(shè)置為 com.android.vending
。 明確地設(shè)置軟件包名稱能夠確保只有 Google Play 應(yīng)用可以處理來自您的應(yīng)用的結(jié)算請(qǐng)求,從而防止其他應(yīng)用攔截這些請(qǐng)求。
@Override
public void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Intent serviceIntent = new Intent("com.android.vending.billing.InAppBillingService.BIND");
serviceIntent.setPackage("com.android.vending");
bindService(serviceIntent, mServiceConn, Context.BIND_AUTO_CREATE);
}
現(xiàn)在,您可以使用 mService 引用來與 Google Play 服務(wù)通信。
重要說明:完成您的 Activity
后,請(qǐng)務(wù)必與應(yīng)用內(nèi)購(gòu)買結(jié)算服務(wù)解除綁定。 如果不解除綁定,開啟的服務(wù)連接會(huì)導(dǎo)致您的設(shè)備性能下降。 此示例說明了如何通過重寫 Activity 的 onDestroy()
方法對(duì)到應(yīng)用內(nèi)購(gòu)買結(jié)算的服務(wù)連接 mServiceConn
執(zhí)行解除綁定操作。
@Override public void onDestroy()
{
super.onDestroy();
if (mService != null)
{
unbindService(mServiceConn);
}
}
如需了解綁定到 IInAppBillingService
的服務(wù)連接的完整實(shí)現(xiàn),請(qǐng)參閱[出售應(yīng)用內(nèi)商品]培訓(xùn)課程和相關(guān)示例。
發(fā)起應(yīng)用內(nèi)購(gòu)買結(jié)算請(qǐng)求
將應(yīng)用連接到 Google Play 后,您可以對(duì)應(yīng)用內(nèi)商品發(fā)送購(gòu)買請(qǐng)求。 Google Play 為用戶進(jìn)入他們的付款方式提供了一個(gè)結(jié)賬界面,這樣您的應(yīng)用就無(wú)需直接處理付款交易。 在商品被用戶購(gòu)買后,Google Play 會(huì)識(shí)別用戶擁有此商品,并在此商品被消耗前阻止用戶購(gòu)買具有相同商品 ID 的另一商品。 您可以控制如何在應(yīng)用中消耗商品,并通知 Google Play 該商品可供再次購(gòu)買。 您也可以查詢 Google Play,以便快速地檢索用戶的購(gòu)買列表。 這樣十分有用,例如,非常適合您希望在用戶啟動(dòng)應(yīng)用時(shí)恢復(fù)用戶購(gòu)買的情況。
查詢可供購(gòu)買的商品
在您的應(yīng)用中,可以使用 In-app Billing Version 3 API 從 Google Play 查詢商品詳情。 要將請(qǐng)求傳遞至應(yīng)用內(nèi)購(gòu)買結(jié)算服務(wù),首先需要?jiǎng)?chuàng)建一個(gè)包含商品 ID 字符串 ArrayList
的 Bundle
,該字符串帶有鍵“ITEM_ID_LIST”,每個(gè)字符串是可購(gòu)買商品的商品 ID。
ArrayList<String> skuList = new ArrayList<String> ();
skuList.add("premiumUpgrade");
skuList.add("gas");
Bundle querySkus = new Bundle();
querySkus.putStringArrayList(“ITEM_ID_LIST”, skuList);
要從 Google Play 檢索此信息,請(qǐng)?jiān)?In-app Billing Version 3 API 上調(diào)用 getSkuDetails
方法,然后將 In-app Billing API 版本(3)、發(fā)起調(diào)用的應(yīng)用的軟件包名稱、商品類型(應(yīng)用內(nèi))以及您創(chuàng)建的 Bundle
傳遞給方法。
Bundle skuDetails = mService.getSkuDetails(3, getPackageName(), "inapp", querySkus);
如果請(qǐng)求成功,返回的 Bundle
將包含響應(yīng)代碼 BILLING_RESPONSE_RESULT_OK
(0)。
警告:請(qǐng)不要在主線程上調(diào)用 getSkuDetails
方法。 調(diào)用此方法會(huì)觸發(fā)網(wǎng)絡(luò)請(qǐng)求,進(jìn)而阻塞主線程。 請(qǐng)創(chuàng)建單獨(dú)的線程并從該線程內(nèi)部調(diào)用 getSkuDetails
方法。
要從 Google Play 查看所有可能的響應(yīng)代碼,請(qǐng)參閱應(yīng)用內(nèi)購(gòu)買結(jié)算參考。
查詢結(jié)果將保存在帶有鍵 DETAILS_LIST
的字符串 ArrayList 中。購(gòu)買信息存儲(chǔ)在 JSON 格式的字符串中。 要查看返回的商品類型詳細(xì)信息,請(qǐng)參閱應(yīng)用內(nèi)購(gòu)買結(jié)算參考。
在此示例中,您將從之前代碼段返回的 skuDetails Bundle 中檢索您的應(yīng)用內(nèi)商品的價(jià)格。
int response = skuDetails.getInt("RESPONSE_CODE");
if (response == 0) {
ArrayList<String> responseList = skuDetails.getStringArrayList("DETAILS_LIST");
for (String thisResponse : responseList) {
JSONObject object = new JSONObject(thisResponse);
String sku = object.getString("productId");
String price = object.getString("price");
if (sku.equals("premiumUpgrade"))
mPremiumUpgradePrice = price;
else if (sku.equals("gas"))
mGasPrice = price;
}
}
購(gòu)買商品
要從您的應(yīng)用發(fā)起購(gòu)買請(qǐng)求,請(qǐng)?jiān)趹?yīng)用內(nèi)購(gòu)買結(jié)算服務(wù)上調(diào)用 getBuyIntent
方法。 將 In-app Billing API 版本(3)、發(fā)起調(diào)用的應(yīng)用的軟件包名稱、要購(gòu)買商品的商品 ID、商品類型(應(yīng)用內(nèi)或訂閱)以及 developerPayload
字符串傳遞給方法。 developerPayload
字符串用于指定您想要 Google Play 隨購(gòu)買信息一同發(fā)送的任何其他參數(shù)。
Bundle buyIntentBundle = mService.getBuyIntent(3, getPackageName(), sku, "inapp", "bGoa+V7g/yqDXvKRqq+JTFn4uQZbPiQJo4pf9RzJ");
如果請(qǐng)求成功,返回的 Bundle 將包含響應(yīng)代碼 BILLING_RESPONSE_RESULT_OK
(0) 和您可以用于開始購(gòu)買流程的 PendingIntent。接下來,請(qǐng)使用鍵 BUY_INTENT
從響應(yīng) Bundle
中提取 `PendingIntent。
PendingIntent pendingIntent = buyIntentBundle.getParcelable("BUY_INTENT");
要完成購(gòu)買交易,請(qǐng)調(diào)用 startIntentSenderForResult(android.content.IntentSender,int,android.content.Intent,int,int,int))
方法并使用您創(chuàng)建的 PendingIntent
。 在此示例中,您將任意值 1001 用于請(qǐng)求代碼。
startIntentSenderForResult(pendingIntent.getIntentSender(), 1001, new Intent(), Integer.valueOf(0), Integer.valueOf(0), Integer.valueOf(0));
Google Play 會(huì)將對(duì)您 PendingIntent
的響應(yīng)發(fā)送至應(yīng)用的 onActivityResult((int,int,android.content.Intent))
方法。 onActivityResult(int,int,android.content.Intent))
方法將獲得結(jié)果代碼 Activity.RESULT_OK
(1) 或 Activity.RESULT_CANCELED
(0)。
訂單的購(gòu)買數(shù)據(jù)是 JSON 格式的字符串,將映射到響應(yīng) Intent 中的 INAPP_PURCHASE_DATA
鍵,例如:
{
"orderId":"GPA.1234-5678-9012-34567",
"packageName":"com.example.app",
"productId":"exampleSku",
"purchaseTime":1345678900000,
"purchaseState":0,
"developerPayload":"bGoa+V7g/yqDXvKRqq+JTFn4uQZbPiQJo4pf9RzJ",
"purchaseToken":"opaque-token-up-to-1000-characters" }
注:Google Play 會(huì)為購(gòu)買生成令牌。此令牌是不透明的字符序列,最長(zhǎng)可為 1,000 字符。 將整個(gè)令牌傳遞至其他方法(例如在您消耗購(gòu)買時(shí),如消耗購(gòu)買(https://developer.android.com/training/in-app-billing/purchase-iab-products.html?hl=zh-cn#Consume)中所述)。 不要省略或者截?cái)啻肆钆疲仨毐4娌⒎祷卣麄€(gè)令牌。
繼續(xù)前面的示例,您將從響應(yīng) Intent獲得響應(yīng)代碼、購(gòu)買數(shù)據(jù)和簽名。
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
if (requestCode == 1001) {
int responseCode = data.getIntExtra("RESPONSE_CODE", 0);
String purchaseData = data.getStringExtra("INAPP_PURCHASE_DATA");
String dataSignature = data.getStringExtra("INAPP_DATA_SIGNATURE");
if (resultCode == RESULT_OK) {
try {
JSONObject jo = new JSONObject(purchaseData);
String sku = jo.getString("productId");
alert("You have bought the " + sku + ". Excellent choice,adventurer!");
} catch (JSONException e) {
alert("Failed to parse purchase data.");
e.printStackTrace();
}
}
}
}
安全性建議:在您發(fā)送購(gòu)買請(qǐng)求時(shí),請(qǐng)創(chuàng)建一個(gè)可以對(duì)此購(gòu)買請(qǐng)求進(jìn)行唯一標(biāo)識(shí)的字符串令牌并在 developerPayload
中包含此令牌。您可以將隨機(jī)生成的字符串作為令牌。 從 Google Play 接收到購(gòu)買響應(yīng)時(shí),請(qǐng)確保檢查返回的數(shù)據(jù)簽名、orderId
和 developerPayload
字符串。 為了增強(qiáng)安全性,您應(yīng)在自己安全的服務(wù)器上執(zhí)行檢查。 請(qǐng)確保驗(yàn)證 orderId
為您之前未處理的唯一值,且 developerPayload
字符串與您之前通過購(gòu)買請(qǐng)求發(fā)送的令牌相匹配。
查詢已購(gòu)買商品
要從您的應(yīng)用檢索用戶所發(fā)起購(gòu)買的相關(guān)信息,請(qǐng)?jiān)趹?yīng)用內(nèi)購(gòu)買結(jié)算版本 3 服務(wù)上調(diào)用 getPurchases
方法。 將 In-app Billing API 版本(3)、發(fā)起調(diào)用的應(yīng)用的軟件包名稱以及商品類型(應(yīng)用內(nèi)或訂閱)傳遞給方法。
Bundle ownedItems = mService.getPurchases(3, getPackageName(), "inapp", null);
Google Play 服務(wù)僅會(huì)返回由當(dāng)前登錄設(shè)備的用戶帳戶發(fā)起的購(gòu)買。 如果請(qǐng)求成功,返回的 Bundle
將包含響應(yīng)代碼 0。響應(yīng) Bundle
也會(huì)包含商品 ID 列表、每個(gè)購(gòu)買的訂單詳情列表以及每個(gè)購(gòu)買的簽名。
為了提升性能,第一次調(diào)用 getPurchase
時(shí),應(yīng)用內(nèi)購(gòu)買結(jié)算服務(wù)僅會(huì)返回由用戶擁有的最多 700 個(gè)商品。 如果用戶擁有大量商品,Google Play 會(huì)在響應(yīng) Bundle
中包含映射到鍵 INAPP_CONTINUATION_TOKEN
的字符串令牌,以表明可以檢索更多的商品。 然后,您的應(yīng)用可以進(jìn)行后續(xù) getPurchases
調(diào)用,并將此令牌作為參數(shù)傳遞。 Google Play 會(huì)繼續(xù)在響應(yīng) Bundle
中返回繼續(xù)令牌,直到用戶擁有的所有商品都發(fā)送到您的應(yīng)用。
如需了解有關(guān)由 getPurchases
返回的數(shù)據(jù)的詳細(xì)信息,請(qǐng)參閱應(yīng)用內(nèi)購(gòu)買結(jié)算參考。 下面的示例說明了如何從響應(yīng)中檢索此數(shù)據(jù)。
int response = ownedItems.getInt("RESPONSE_CODE");
if (response == 0) {
ArrayList<String> ownedSkus = ownedItems.getStringArrayList("INAPP_PURCHASE_ITEM_LIST");
ArrayList<String> purchaseDataList = ownedItems.getStringArrayList("INAPP_PURCHASE_DATA_LIST");
ArrayList<String> signatureList = ownedItems.getStringArrayList("INAPP_DATA_SIGNATURE_LIST");
String continuationToken = ownedItems.getString("INAPP_CONTINUATION_TOKEN");
for (int i = 0; i < purchaseDataList.size(); ++i) {
String purchaseData = purchaseDataList.get(i);
String signature = signatureList.get(i);
String sku = ownedSkus.get(i);
// do something with this purchase information
// e.g. display the updated list of products owned by user
}
// if continuationToken != null, call getPurchases again
// and pass in the token to retrieve more items
}
消耗購(gòu)買
您可以使用 In-app Billing Version 3 API 跟蹤在 Google Play 中購(gòu)買的應(yīng)用內(nèi)商品的所有權(quán)。 應(yīng)用內(nèi)商品一經(jīng)購(gòu)買,就會(huì)被視為“被擁有”且無(wú)法從 Google Play 購(gòu)買。 您必須對(duì)應(yīng)用內(nèi)商品發(fā)送消耗請(qǐng)求,然后 Google Play 才能允許再次購(gòu)買。
重要說明:可以消耗托管的應(yīng)用內(nèi)商品,但不能消耗訂閱。
如何在應(yīng)用中使用消耗機(jī)制取決于您。通常情況下,您可以對(duì)用戶想要購(gòu)買多次、能夠提供短期效益的應(yīng)用內(nèi)商品實(shí)現(xiàn)消耗(例如,游戲中使用的貨幣或設(shè)備)。 您通常不必對(duì)僅供購(gòu)買一次和具有永久效應(yīng)的應(yīng)用內(nèi)商品實(shí)現(xiàn)消耗(例如,高級(jí)版升級(jí))。
要記錄購(gòu)買消耗,請(qǐng)將 consumePurchase
方法發(fā)送到應(yīng)用內(nèi)購(gòu)買結(jié)算服務(wù)并在標(biāo)識(shí)要移除購(gòu)買的 purchaseToken
字符串值中傳遞。 purchaseToken
是由購(gòu)買請(qǐng)求成功后 Google Play 服務(wù)在 INAPP_PURCHASE_DATA
字符串中所返回?cái)?shù)據(jù)的一部分。 在此示例中,您會(huì)將使用 purchaseToken
標(biāo)識(shí)的商品的消耗記錄在 token
變量中。
int response = mService.consumePurchase(3, getPackageName(), token);
警告:請(qǐng)不要在主線程上調(diào)用 consumePurchase
方法。 調(diào)用此方法會(huì)觸發(fā)網(wǎng)絡(luò)請(qǐng)求,進(jìn)而阻塞主線程。 請(qǐng)創(chuàng)建單獨(dú)的線程并從該線程內(nèi)部調(diào)用 consumePurchase
方法。
您負(fù)責(zé)控制和跟蹤如何向用戶配置應(yīng)用內(nèi)商品。 例如,如果用戶購(gòu)買了游戲內(nèi)貨幣,您應(yīng)使用購(gòu)買的貨幣金額更新玩家的庫(kù)存。
安全性建議:您必須首先發(fā)送消耗請(qǐng)求,才能向用戶配置可消耗的應(yīng)用內(nèi)購(gòu)買商品。 確保已從 Google Play 接收到成功的消耗請(qǐng)求,然后再配置商品。
實(shí)現(xiàn)訂閱
啟動(dòng)訂閱的購(gòu)買流程與啟動(dòng)商品的購(gòu)買流程相似,不同之處是商品類型必須設(shè)置為“訂閱”。 購(gòu)買結(jié)果會(huì)傳送至您 Activity 的onActivityResult(int,int,android.content.Intent))
方法,與應(yīng)用內(nèi)商品的情況完全一樣。
Bundle bundle = mService.getBuyIntent(3, "com.example.myapp", MY_SKU, "subs", developerPayload);
PendingIntent pendingIntent = bundle.getParcelable(RESPONSE_BUY_INTENT);
if (bundle.getInt(RESPONSE_CODE) == BILLING_RESPONSE_RESULT_OK)
{
// Start purchase flow (this brings up the Google Play UI).
// Result will be delivered through onActivityResult().
startIntentSenderForResult(pendingIntent, RC_BUY, new Intent(), Integer.valueOf(0), Integer.valueOf(0), Integer.valueOf(0));
}
要查詢有效訂閱,請(qǐng)使用 getPurchases
方法,并將商品類型參數(shù)設(shè)置為“訂閱”。
Bundle activeSubs = mService.getPurchases(3, "com.example.myapp", "subs", continueToken);
調(diào)用會(huì)返回 Bundle
,其包含由用戶擁有的所有有效訂閱。 如果訂閱到期且不續(xù)訂,將不會(huì)出現(xiàn)在返回的 Bundle
中。
保證您的應(yīng)用安全
為了確保發(fā)送到您應(yīng)用的交易信息的完整性,Google Play 會(huì)簽署包含購(gòu)買訂單響應(yīng)數(shù)據(jù)的 JSON 字符串。 Google Play 會(huì)使用 Developer Console 中與您的應(yīng)用關(guān)聯(lián)的私鑰來創(chuàng)建此簽名。 Developer Console 會(huì)為每個(gè)應(yīng)用生成一個(gè) RSA 密鑰對(duì)。
注:要找到此密鑰對(duì)的公鑰部分,請(qǐng)?jiān)?Developer Console 中打開應(yīng)用的詳細(xì)信息,然后點(diǎn)擊 Services & APIs,并查看命名為 Your License Key for This Application 的字段。
由 Google Play 生成的以 Base64 編碼的 RSA 公鑰為二進(jìn)制編碼,格式為 X.509 subjectPublicKeyInfo DER SEQUENCE。 它與 Google Play 許可使用的公鑰相同。