Topik ini menjelaskan cara melakukan migrasi dari integrasi penagihan yang menggunakan Android Interface Definition Language (AIDL). Sistem penagihan Google Play tidak dapat diakses lagi menggunakan AIDL, dan selanjutnya semua integrasi harus menggunakan Library Layanan Penagihan Google Play.
Langkah Migrasi
Impor Library Layanan Penagihan Google Play
Pertama, tambahkan dependensi ke Library Layanan Penagihan Google Play. Jika menggunakan Gradle, Anda dapat menambahkan kode berikut ke file build.gradle
aplikasi:
Groovy
dependencies { def billing_version = "5.1.0" implementation "com.android.billingclient:billing:$billing_version" }
Kotlin
dependencies { val billing_version = "5.1.0" implementation("com.android.billingclient:billing:$billing_version") }
Anda dapat menghapus kode “glue” apa pun, seperti IabHelper
, yang mungkin sudah Anda salin dari kode referensi sebelumnya. Fungsionalitas yang ditawarkan oleh IabHelper
kini menjadi bagian dari Library Layanan Penagihan Google Play.
Hapus izin com.android.vending.BILLING
Library Layanan Penagihan Google Play menyematkan izin com.android.vending.BILLING
dalam manifesnya. Anda tidak perlu lagi menambahkan izin ini ke dalam manifes aplikasi secara eksplisit.
Menghubungkan ke Layanan Penagihan Google Play
Metode Library Layanan Penagihan Google Play
BillingClient
menangani pengelolaan koneksi untuk Anda. Untuk melakukan migrasi, lakukan perubahan
berikut pada aplikasi Anda:
- Buat instance
BillingClient
. - Implementasikan
BillingClientStateListener
untuk menerima callback tentang status layanan. - Panggil
startConnection()
pada instanceBillingClient
Anda. - Hapus kode
onActivityResult()
yang terkait dengan pembelian dalam aplikasi dan pindahkan kePurchasesUpdatedListener
.
Contoh berikut menunjukkan contoh tampilan aplikasi Anda sebelum dan sesudah perubahan dilakukan:
Sebelum
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;
}
Setelah
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. } }
Melakukan pembelian
Untuk meluncurkan dialog pembelian, lakukan langkah berikut:
- Konversikan
Bundle
detail SKU Anda menjadiSkuDetailsParams
. - Ganti panggilan
mService.getSkuDetails()
agar menggunakanBillingClient.querySkuDetailsAsync()
. - Konversikan
Bundle
intent pembelian Anda menjadi objekBillingFlowParams
. - Ganti panggilan
mService.getBuyIntent()
agar menggunakanBillingClient.launchBillingFlow()
. - Hapus kode apa pun yang terkait dengan pembelian dalam aplikasi dari
onActivityResult()
, lalu pindahkan kode ini kePurchasesUpdatedListener
.
Contoh berikut menunjukkan contoh tampilan aplikasi Anda sebelum dan sesudah perubahan dilakukan:
Sebelum
// 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.
Setelah
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.
Menggunakan pembelian
Untuk menggunakan pembelian dengan Library Layanan Penagihan Google Play, lakukan langkah berikut:
- Jangan panggil
consumePurchase()
, tetapi panggilBillingClient.consumeAsync()
. - Implementasikan
ConsumeResponseListener
.
Contoh berikut menunjukkan contoh tampilan aplikasi Anda sebelum dan sesudah perubahan dilakukan:
Sebelum
@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.
}
Setelah
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. ... } }
Mengonfirmasi pembelian
Dimulai dari Library Layanan Penagihan Google Play versi 2.0, aplikasi Anda harus menggunakan atau mengonfirmasi semua pembelian.
Jika Anda tidak menggunakan atau mengonfirmasi pembelian dalam tiga hari, Google otomatis akan membatalkan pembelian dan mengembalikan dana pengguna. Untuk informasi selengkapnya, lihat Mengonfirmasi pembelian.
Mengenali pembelian di luar aplikasi
Untuk memigrasikan penanganan pembelian di luar aplikasi ke Library Layanan Penagihan Google Play, lakukan langkah berikut:
- Pastikan aplikasi Anda memanggil
BillingClient.queryPurchasesAsync()
dalam callbackonResume()
aplikasi Anda. - Hapus penerima siaran untuk
com.android.vending.billing.PURCHASES_UPDATED
, lalu pindahkan kode callback yang sesuai kePurchasesUpdatedListener
.
Sebelumnya, saat mengintegrasikan Layanan Penagihan Google Play dengan AIDL, aplikasi Anda harus mendaftarkan pemroses untuk menerima intent com.android.vending.billing.PURCHASES_UPDATED
guna menangani pembelian yang dilakukan di luar aplikasi.
Dengan Library Layanan Penagihan Google Play, aplikasi Anda harus selalu memanggil
queryPurchasesAsync()
dalam
callback onResume()
aplikasi sebagai langkah pertama untuk memastikan semua pembelian yang dilakukan saat
aplikasi tidak berjalan dapat dikenali. Saat aplikasi Anda berjalan,
Library Layanan Penagihan Google Play
akan memproses pembelian di luar aplikasi secara otomatis dan memberi tahu Anda melalui
PurchasesUpdatedListener
.
Menangani transaksi yang tertunda
Dimulai dari Library Layanan Penagihan Google Play versi 2.0, aplikasi Anda harus menangani transaksi tertunda yang memerlukan tindakan tambahan setelah pembelian dilakukan dan sebelum kepemilikan diberikan. Misalnya, pengguna mungkin memilih untuk membeli produk dalam aplikasi Anda di toko fisik menggunakan uang tunai. Hal ini berarti transaksi diselesaikan di luar aplikasi Anda. Dalam skenario ini, sebaiknya Anda hanya memberikan izin setelah pengguna menyelesaikan transaksi tersebut.
Untuk informasi selengkapnya, lihat Mendukung transaksi yang tertunda.
Payload developer
Payload developer sebelumnya telah digunakan untuk berbagai tujuan, termasuk pencegahan penipuan dan mengatribusikan pembelian ke pengguna yang tepat. Setelah Library Layanan Penagihan Google Play mendukung kasus penggunaan ini, kami tidak lagi menggunakan payload developer dimulai dari Library Layanan Penagihan Google Play versi 2.2. Untuk informasi selengkapnya, lihat Payload developer.
Pesan error mendetail
Dimulai dari Library Layanan Penagihan Google Play versi 2.0, semua error memiliki pesan terkait proses debug yang sesuai. Pesan ini dapat diperoleh dengan memanggil BillingResult.getDebugMessage()
.