Pengingat: Anda harus mendukung penangguhan dan pemulihan akun di aplikasi Anda paling lambat 1 November 2020. Penjedaan langganan dan berlangganan lagi juga akan diaktifkan secara default, kecuali Anda secara eksplisit memilih tidak ikut. Pelajari lebih lanjut.

Panduan migrasi AIDL ke Library Layanan Penagihan Google Play

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:

dependencies {
    def billing_version = "3.0.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.

Hubungkan ke Layanan Penagihan Google Play

BillingClient Library Layanan Penagihan Google Play menangani pengelolaan koneksi untuk Anda. Untuk melakukan migrasi, lakukan perubahan berikut pada aplikasi Anda:

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:

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:

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:

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 queryPurchases() dalam callback onResume() aplikasi sebagai langkah pertama agar semua pembelian yang dilakukan saat aplikasi tidak berjalan dapat dikenali. Saat aplikasi Anda berjalan, library 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 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().