本主題說明如何從使用 Android 介面定義語言 (AIDL) 的整合帳款服務中移轉出來。使用 AIDL 存取 Google Play 的帳款服務系統這種方式已淘汰,未來所有整合作業皆須使用 Google Play 帳款服務程式庫。
移轉步驟
匯入 Google Play 帳款服務程式庫
首先,在 Google Play 帳款服務程式庫中新增一個依附元件。如果您是使用 Gradle,可以將下列程式碼新增至應用程式的 build.gradle
檔中:
Groovy
dependencies { def billing_version = "6.1.0" implementation "com.android.billingclient:billing:$billing_version" }
Kotlin
dependencies { val billing_version = "6.1.0" implementation("com.android.billingclient:billing:$billing_version") }
您可以刪除任何「附著」的程式碼,例如 IabHelper
,這些程式碼可能是您從之前的參照代碼複製而來。IabHelper
提供的功能現已併入 Google Play 帳款服務程式庫。
移除 com.android.vending.BILLING
權限
Google Play 帳款服務程式庫會在資訊清單中嵌入 com.android.vending.BILLING
權限。再也不需要在應用程式的資訊清單中明確新增這項權限。
連線至 Google Play 帳款服務
Google Play 帳款服務程式庫的 BillingClient
方法會替您處理連線管理。如要遷移,請對應用程式進行以下變更:
- 建立
BillingClient
的執行個體。 - 實作
BillingClientStateListener
以接收關於服務狀態的回呼。 - 在
BillingClient
執行個體上呼叫startConnection()
。 - 移除與應用程式內購的相關
onActivityResult()
程式碼,然後移至PurchasesUpdatedListener
。
以下範例為應用程式在變更前後的可能內容:
之前
mServiceConn = new ServiceConnection() {
@Override
public void onServiceDisconnected(ComponentName name) {
...
}
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
...
}
};
Intent serviceIntent = new Intent("com.android.vending.billing.InAppBillingService.BIND");
serviceIntent.setPackage("com.android.vending");
List<ResolveInfo> intentServices = mContext.getPackageManager()
.queryIntentServices(serviceIntent, 0);
if (intentServices != null && !intentServices.isEmpty()) {
mContext.bindService(serviceIntent, mServiceConn, Context.BIND_AUTO_CREATE);
} else {
// Handle errors.
...
}
...
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
IabResult result;
if (requestCode != mRequestCode || data == null) {
// Handle errors.
...
}
int responseCode = getResponseCodeFromIntent(data);
String purchaseData = data.getStringExtra(RESPONSE_INAPP_PURCHASE_DATA);
String dataSignature = data.getStringExtra(RESPONSE_INAPP_SIGNATURE);
if (resultCode != Activity.RESULT_OK || responseCode != BILLING_RESPONSE_RESULT_OK) {
// Handle errors.
...
}
// Process successful purchase.
...
return true;
}
之後
Kotlin
class MyBillingImpl(private var billingClient: BillingClient) : PurchasesUpdatedListener { init { billingClient = BillingClient.newBuilder(activity).setListener(this).build() billingClient.startConnection(object : BillingClientStateListener { override fun onBillingSetupFinished(billingResult: BillingResult?) { // Logic from ServiceConnection.onServiceConnected should be moved here. } override fun onBillingServiceDisconnected() { // Logic from ServiceConnection.onServiceDisconnected should be moved here. } }) } override fun onPurchasesUpdated( billingResult: BillingResult?, purchases: MutableList<Purchase>? ) { // Logic from onActivityResult should be moved here. } }
Java
public class MyBillingImpl implements PurchasesUpdatedListener { private BillingClient billingClient; ... public void initialize() { billingClient = BillingClient.newBuilder(activity).setListener(this).build(); billingClient.startConnection(new BillingClientStateListener() { @Override public void onBillingSetupFinished(BillingResult billingResult) { // Logic from ServiceConnection.onServiceConnected should be moved here. } @Override public void onBillingServiceDisconnected() { // Logic from ServiceConnection.onServiceDisconnected should be moved here. } }); } @Override public void onPurchasesUpdated( @BillingResponse int responseCode, @Nullable List<Purchase> purchases) { // Logic from onActivityResult should be moved here. } }
購買商品
如要啟動購買交易對話方塊,請按照下列步驟操作:
- 將 SKU 詳細資料
Bundle
轉換為SkuDetailsParams
。 - 切換
mService.getSkuDetails()
呼叫,改爲使用BillingClient.querySkuDetailsAsync()
。 - 將購買意圖
Bundle
轉換為BillingFlowParams
物件。 - 切換
mService.getBuyIntent()
呼叫,改爲使用BillingClient.launchBillingFlow()
。 - 從
onActivityResult()
中移除任何與應用程式內購相關的程式碼,接著將這個程式碼移至PurchasesUpdatedListener
。
以下範例為應用程式在變更前後的可能內容:
之前
// Query Skus
String skuToSell = "premium_upgrade";
ArrayList<String> skus = new Arraylist<>();
skus.add(skuToSell);
Bundle querySkus = new Bundle();
querySkus.putStringArrayList(GET_SKU_DETAILS_ITEM_LIST, skus);
Bundle skuDetails = mService.getSkuDetails(3,
mContext.getPackageName(),
itemType,
querySkus);
if (!skuDetails.containsKey(RESPONSE_GET_SKU_DETAILS_LIST)) {
// Handle errors.
...
}
// Launch Buy Flow
Bundle buyIntentBundle = mService.getBuyIntent(3,
mContext.getPackageName(),
skuToSell,
"Inapp",
"");
int response = getResponseCodeFromBundle(buyIntentBundle);
if (response != BILLING_RESPONSE_RESULT_OK) {
// Handle errors.
...
}
PendingIntent pendingIntent = buyIntentBundle.getParcelable(RESPONSE_BUY_INTENT);
act.startIntentSenderForResult(pendingIntent.getIntentSender(),
requestCode,
new Intent(),
Integer.valueOf(0),
Integer.valueOf(0),
Integer.valueOf(0));
// Purchase is handled in onActivityResult illustrated in the previous section.
之後
Kotlin
val skuToSell = "premium_upgrade" val skuList = mutableListOf<String>() skuList.add(skuToSell) val params = SkuDetailsParams.newBuilder() params.setSkusList(skuList).setType(BillingClient.SkuType.INAPP) billingClient.querySkuDetailsAsync(params.build(), object : SkuDetailsResponseListener { override fun onSkuDetailsResponse( billingResult: BillingResult?, skuDetailsList: MutableList<SkuDetails>?) { // Process the result. } }) // SkuDetails object obtained above. val skuDetails = ... val purchaseParams = BillingFlowParams.newBuilder() .setSkuDetails(skuDetails) .build() billingClient.launchBillingFlow(activity, purchaseParams) // Purchase is handled in onPurchasesUpdated illustrated in the previous section
Java
String skuToSell = "premium_upgrade"; List<String> skuList = new ArrayList<> (); skuList.add(skuToSell); SkuDetailsParams.Builder params = SkuDetailsParams.newBuilder(); params.setSkusList(skuList).setType(SkuType.INAPP); billingClient.querySkuDetailsAsync(params.build(), new SkuDetailsResponseListener() { @Override public void onSkuDetailsResponse(BillingResult billingResult, List<SkuDetails> skuDetailsList) { // Process the result. ... } }); // SkuDetails object obtained above. SkuDetails skuDetails = ...; BillingFlowParams purchaseParams = BillingFlowParams.newBuilder() .setSkuDetails(skuDetails) .build(); mBillingClient.launchBillingFlow(mActivity, purchaseParams); // Purchase is handled in onPurchasesUpdated illustrated in the previous section.
消耗購買產品
如要使用 Google Play 帳款服務程式庫消耗購買產品,請按照下列步驟操作:
以下範例為應用程式在變更前後的可能內容:
之前
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
int responseCode = data.getIntExtra(RESPONSE_CODE);
JSONObject purchaseData =
new JSONObject(data.getStringExtra("INAPP_PURCHASE_DATA"));
String token = purchaseData.get("purchaseToken");
...
// Consume purchase
int response = mService.consumePurchase(3, mContext.getPackageName(), token);
if (response != BILLING_RESPONSE_RESULT_OK) {
// Handle errors.
...
}
// Handle successful consumption.
}
之後
Kotlin
class MyBillingImpl(private val billingClient: BillingClient) : ... , ConsumeResponseListener { fun consumePurchase(purchaseToken: String) { val consumeParams = ConsumeParams .newBuilder() .setPurchaseToken(purchaseToken) .build() } override fun onConsumeResponse( billingResult: BillingResult?, purchaseToken: String?) { // Handle consumption } }
Java
public class MyBillingImpl implements ..., ConsumeResponseListener { private BillingClient billingClient; ... public void consumePurchase(String purchaseToken) { ConsumeParams consumeParams = ConsumeParams.newBuilder() .setPurchaseToken(purchaseToken) .build(); } @Override void onConsumeResponse(BillingResult billingResult, String purchaseToken) { // Handle consumption. ... } }
確認購買交易
從 Google Play 帳款服務程式庫 2.0 版開始,應用程式必須消耗或確認所有購買交易。
如果您未在三天內消耗或確認購買交易,Google 會自動撤銷該購買交易並退款給使用者。詳情請參閱確認購買交易。
辨識應用程式外購
如要將應用程式外購交易的處理程序遷移至 Google Play 帳款服務程式庫,請按照下列步驟操作:
- 確保應用程式在其
onResume()
回呼中呼叫BillingClient.queryPurchasesAsync()
。 - 移除
com.android.vending.billing.PURCHASES_UPDATED
的廣播接收器,將對應的回呼程式碼移至PurchasesUpdatedListener
。
之前當 Google Play 帳款服務與 AIDL 整合時,應用程式必須註冊一個事件監聽器才能接收 com.android.vending.billing.PURCHASES_UPDATED
意圖,以便處理應用程式外的購買交易。
使用 Google Play 帳款服務程式庫時,首先讓應用程式一律在其 onResume()
回呼中呼叫 queryPurchasesAsync()
,以確保未執行應用程式時進行的所有購買交易都能獲得確認。應用程式執行時,Google Play 帳款服務程式庫會自動監聽應用程式外購,並透過 PurchasesUpdatedListener
通知您。
處理未完成交易
自 Google Play 帳款服務程式庫 2.0 版開始,應用程式必須先處理「未完成交易」,這些交易必須在購買後執行其他操作才能授予權限。舉例來說,使用者可能會選擇在實體商店以現金購買應用程式內產品。這代表交易是在應用程式外完成。在這種情況下,必須在使用者完成交易後再授予相關權限。
詳情請參閱支援未完成交易。
開發人員酬載
過去開發人員酬載用於多種目的,包括防範詐欺行為以及將購買交易認定為來自正確的使用者。Google Play 帳款服務程式庫現在支援這些用途,因此從 Google Play 帳款服務程式庫 2.2 版開始已將開發人員酬載功能淘汰。詳情請參閱開發人員酬載。
詳細錯誤訊息
從 Google Play 帳款服務程式庫 2.0 版開始,所有錯誤都會有對應的偵錯相關訊息。呼叫 BillingResult.getDebugMessage()
即可取得這些訊息。