Google berkomitmen untuk mendorong terwujudnya keadilan rasial bagi komunitas Kulit Hitam. Lihat caranya.

Menggunakan Library Layanan Penagihan Google Play

Dokumen ini menjelaskan cara menambahkan Layanan Penagihan Google Play ke aplikasi Anda menggunakan Library Google Play. Secara khusus, dokumen ini membahas cara menambahkan fungsi Layanan Penagihan Google Play yang umum digunakan untuk produk sekali beli maupun langganan. Untuk mempelajari cara menambahkan fungsionalitas khusus produk dalam aplikasi ke aplikasi Anda, lihat dokumen yang tercantum di akhir halaman ini.

Sebelum membaca halaman ini, lakukan langkah berikut:

  1. Baca Ringkasan Layanan Penagihan Google Play untuk memahami konsep dan istilah penting.
  2. Konfigurasikan produk dalam aplikasi Anda menggunakan Konsol Google Play:
  3. Jika saat ini Anda terintegrasi dengan Layanan Penagihan Google Play menggunakan AIDL, lihat Panduan migrasi AIDL ke Library Layanan Penagihan Google Play untuk melihat ringkasan lengkap langkah yang diperlukan guna melakukan migrasi dari AIDL ke Library Layanan Penagihan Google Play.

Langkah-langkah untuk menambahkan Layanan Penagihan Google Play ke aplikasi

Ikuti langkah-langkah pada bagian di bawah untuk menambahkan Layanan Penagihan Google Play ke aplikasi Anda.

Mengupdate dependensi aplikasi Anda

Tambahkan baris berikut ke bagian dependensi file build.gradle untuk aplikasi Anda:

dependencies {
    ...
    implementation 'com.android.billingclient:billing:2.1.0'
}

Jika Anda menggunakan Kotlin, modul KTX Library Layanan Penagihan Play berisi ekstensi Kotlin dan dukungan coroutine yang memungkinkan Anda menulis Kotlin idiomatis di solusi Layanan Penagihan Play. Untuk menyertakan ekstensi ini dalam project Anda, tambahkan dependensi berikut ke file build.gradle aplikasi Anda:

dependencies {
    ...
    // be sure to also include the core dependency
    implementation 'com.android.billingclient:billing:2.1.0'
    implementation 'com.android.billingclient:billing-ktx:2.1.0'
}

Untuk memastikan Anda menggunakan versi terbaru Library Layanan Penagihan Google Play, lihat catatan rilis Library Layanan Penagihan Google Play

Hubungkan ke Google Play

Sebelum dapat membuat permintaan Layanan Penagihan Google Play, Anda harus terhubung ke Google Play terlebih dahulu dengan melakukan langkah berikut:

  1. Panggil newBuilder() untuk membuat instance BillingClient Anda juga harus memanggil setListener(), yang meneruskan referensi ke PurchasesUpdatedListener untuk menerima informasi baru tentang pembelian yang diinisiasi oleh aplikasi Anda, serta yang diinisiasi oleh Google Play Store.

  2. Buat koneksi ke Google Play. Proses penyiapannya berjalan secara asinkron, dan Anda harus menerapkan BillingClientStateListener untuk menerima callback setelah penyiapan klien selesai dan siap untuk membuat permintaan lebih lanjut.

  3. Ganti metode callback onBillingServiceDisconnected() dan terapkan kebijakan mencoba ulang Anda sendiri untuk menangani koneksi yang hilang ke Google Play jika koneksi klien terputus. Misalnya, BillingClient mungkin kehilangan koneksinya jika layanan Google Play Store sedang diupdate di latar belakang. BillingClient harus memanggil metode startConnection() untuk memulai ulang koneksi sebelum membuat permintaan lebih lanjut.

Contoh kode berikut menunjukkan cara memulai koneksi dan menguji apakah koneksi sudah siap digunakan:

Kotlin

lateinit private var billingClient: BillingClient
...
billingClient = BillingClient.newBuilder(context).setListener(this).build()
billingClient.startConnection(object : BillingClientStateListener {
    override fun onBillingSetupFinished(billingResult: BillingResult) {
        if (billingResult.responseCode ==  BillingResponseCode.OK) {
            // The BillingClient is ready. You can query purchases here.
        }
    }
    override fun onBillingServiceDisconnected() {
        // Try to restart the connection on the next request to
        // Google Play by calling the startConnection() method.
    }
})

Java

private BillingClient billingClient;
...
billingClient = BillingClient.newBuilder(activity).setListener(this).build();
billingClient.startConnection(new BillingClientStateListener() {
    @Override
    public void onBillingSetupFinished(BillingResult billingResult) {
        if (billingResult.getResponseCode() ==  BillingResponseCode.OK) {
            // The BillingClient is ready. You can query purchases here.
        }
    }
    @Override
    public void onBillingServiceDisconnected() {
        // Try to restart the connection on the next request to
        // Google Play by calling the startConnection() method.
    }
});

Meminta detail produk dalam aplikasi

ID produk unik yang Anda buat saat mengonfigurasi produk dalam aplikasi digunakan untuk meminta Google Play mendapatkan detail produk dalam aplikasi secara asinkron. Untuk meminta Google Play mendapatkan detail produk dalam aplikasi, panggil querySkuDetailsAsync(). Saat memanggil metode ini, teruskan instance SkuDetailsParams yang menentukan daftar string ID produk dan SkuType. SkuType dapat berupa SkuType.INAPP untuk produk sekali beli, atau SkuType.SUBS untuk langganan.

Untuk menangani hasil operasi asinkron, Anda juga harus menentukan pemroses yang menerapkan antarmuka SkuDetailsResponseListener. Kemudian, Anda dapat mengganti onSkuDetailsResponse() yang akan memberi tahu pemroses saat kueri selesai, seperti yang diilustrasikan oleh kode contoh berikut:

Kotlin

fun querySkuDetails() {
    val skuList = ArrayList<String>()
    skuList.add("premium_upgrade")
    skuList.add("gas")
    val params = SkuDetailsParams.newBuilder()
    params.setSkusList(skuList).setType(SkuType.INAPP)
    val skuDetailsResult = withContext(Dispatchers.IO) {
        billingClient.querySkuDetails(params.build())
    }
    // Process the result.
}

Java

List<String> skuList = new ArrayList<> ();
skuList.add("premium_upgrade");
skuList.add("gas");
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.
        }
    });

Aplikasi Anda harus mempertahankan daftar ID produknya sendiri dengan memaketkan daftar tersebut dengan APK Anda, atau dengan membuat kuerinya dari server backend aman Anda sendiri.

Panggil getResponseCode() untuk mengambil kode respons. Jika permintaan berhasil, kode respons tersebut adalah BillingResponse.OK. Untuk daftar kode respons lain yang dapat diperoleh dari Google Play, lihat BillingClient.BillingResponse.

Jika terjadi error, Anda dapat menggunakan getDebugMessage() untuk melihat pesan error yang terkait.

Library Layanan Penagihan Google Play menyimpan hasil kueri dalam List objek SkuDetails. Anda kemudian dapat memanggil berbagai metode pada setiap objek SkuDetails dalam daftar untuk melihat informasi yang relevan tentang produk dalam aplikasi, seperti harga atau deskripsinya. Untuk melihat informasi detail produk yang tersedia, lihat daftar metode dalam class SkuDetails.

Contoh berikut menunjukkan cara mengambil harga untuk produk dalam aplikasi menggunakan objek SkuDetails yang ditampilkan oleh cuplikan kode sebelumnya:

Kotlin

if (result.responseCode == BillingResponse.OK && skuDetailsList != null) {
    for (skuDetails in skuDetailsList) {
        val sku = skuDetails.sku
        val price = skuDetails.price
        if ("premium_upgrade" == sku) {
            premiumUpgradePrice = price
        } else if ("gas" == sku) {
            gasPrice = price
        }
    }
}

Java

if (result.getResponseCode() == BillingResponse.OK && skuDetailsList != null) {
   for (SkuDetails skuDetails : skuDetailsList) {
       String sku = skuDetails.getSku();
       String price = skuDetails.getPrice();
       if ("premium_upgrade".equals(sku)) {
           premiumUpgradePrice = price;
       } else if ("gas".equals(sku)) {
           gasPrice = price;
       }
   }
}

Mengambil harga produk merupakan langkah penting sebelum pengguna dapat membeli suatu produk, karena harga tersebut berbeda untuk setiap pengguna berdasarkan pada negara asalnya.

Penawaran yang konsisten

Saat menawarkan SKU diskon, Google Play juga menampilkan harga asli SKU sehingga Anda dapat menunjukkan kepada pengguna bahwa mereka mendapatkan diskon. Sebaiknya Anda menggunakan getPrice() untuk menunjukkan harga diskon kepada pengguna dan juga getOriginalPrice() untuk menunjukkan harga aslinya.

SkuDetails berisi dua metode untuk mengambil harga SKU asli:

Aktifkan pembelian produk dalam aplikasi

Beberapa ponsel Android mungkin memiliki aplikasi Google Play Store versi lama yang tidak mendukung jenis produk tertentu, seperti langganan. Oleh karena itu, sebelum aplikasi Anda masuk ke alur penagihan, panggil isFeatureSupported() untuk memastikan bahwa perangkat mendukung produk yang ingin Anda jual. Untuk daftar jenis produk, lihat BillingClient.FeatureType.

Untuk memulai permintaan pembelian dari aplikasi Anda, panggil metode launchBillingFlow() dari UI thread. Teruskan referensi ke objek BillingFlowParams yang berisi data yang relevan untuk menyelesaikan pembelian, seperti ID produk (skuId) item dan tipe produk (SkuType.INAPP untuk produk sekali beli atau SkuType.SUBS untuk langganan). Untuk mendapatkan instance BillingFlowParams , gunakan class BillingFlowParams.Builder:

Kotlin

// Retrieve a value for "skuDetails" by calling querySkuDetailsAsync().
val flowParams = BillingFlowParams.newBuilder()
        .setSkuDetails(skuDetails)
        .build()
val responseCode = billingClient.launchBillingFlow(activity, flowParams)

Java

// Retrieve a value for "skuDetails" by calling querySkuDetailsAsync().
BillingFlowParams flowParams = BillingFlowParams.newBuilder()
        .setSkuDetails(skuDetails)
        .build();
int responseCode = billingClient.launchBillingFlow(flowParams);

Saat Anda memanggil metode launchBillingFlow(), sistem akan menampilkan layar pembelian Google Play. Gambar 3 menunjukkan layar pembelian untuk produk sekali beli:

Gambar 3. Layar pembelian Google Play untuk produk sekali beli.

Gambar 4 menunjukkan layar pembelian untuk langganan:

Gambar 4. Layar pembelian Google Play untuk langganan.

Metode launchBillingFlow() menampilkan salah satu dari beberapa kode respons yang tercantum dalam BillingClient.BillingResponse. Google Play memanggil metode onPurchasesUpdated() untuk mengirimkan hasil operasi pembelian ke pemroses yang menerapkan antarmuka PurchasesUpdatedListener. Pemroses ditentukan menggunakan metode setListener() seperti yang ditunjukkan sebelumnya di bagian Menghubungkan ke Google Play.

Anda harus menerapkan metode onPurchasesUpdated() untuk menangani kode respons yang mungkin diberikan. Cuplikan kode berikut menunjukkan cara mengganti metode onPurchasesUpdated():

Kotlin

override fun onPurchasesUpdated(billingResult: BillingResult, purchases: List<Purchase>?) {
   if (billingResult.responseCode == BillingResponse.OK && purchases != null) {
       for (purchase in purchases) {
           handlePurchase(purchase)
       }
   } else if (billingResult.responseCode == BillingResponse.USER_CANCELED) {
       // Handle an error caused by a user cancelling the purchase flow.
   } else {
       // Handle any other error codes.
   }
}

Java

@Override
void onPurchasesUpdated(BillingResult billingResult, List<Purchase> purchases) {
    if (billingResult.getResponseCode() == BillingResponse.OK
            && purchases != null) {
        for (Purchase purchase : purchases) {
            handlePurchase(purchase);
        }
    } else if (billingResult.getResponseCode() == BillingResponse.USER_CANCELED) {
        // Handle an error caused by a user cancelling the purchase flow.
    } else {
        // Handle any other error codes.
    }
}

Pembelian yang berhasil akan memunculkan layar berhasil di Google Play yang serupa dengan layar pada Gambar 5.

Gambar 5. Layar berhasil Google Play.

Pembelian yang berhasil juga akan memunculkan token pembelian, yakni ID unik yang mewakili pengguna dan ID produk untuk produk dalam aplikasi yang dibelinya. Aplikasi Anda dapat menyimpan token pembelian secara lokal atau, idealnya, meneruskannya ke server backend aman Anda, tempat token dapat digunakan untuk memverifikasi pembelian dan melindungi dari penipuan. Token pembelian bersifat unik untuk setiap pembelian produk sekali beli. Namun, karena langganan dibeli satu kali dan diperpanjang secara otomatis pada periode penagihan reguler, token pembelian untuk langganan akan tetap sama pada setiap periode penagihan.

Pengguna juga akan menerima tanda terima transaksi yang berisi ID pesanan atau ID unik transaksi melalui email. Pengguna menerima email yang berisi ID pesanan unik untuk setiap pembelian produk sekali beli, juga untuk pembelian langganan awal dan perpanjangan otomatis berulang berikutnya. Anda dapat menggunakan ID pesanan ini untuk mengelola pengembalian dana di Konsol Google Play. Untuk detail lebih lanjut, baca Menampilkan dan mengembalikan dana untuk pesanan dan langganan aplikasi Anda.

Mengonfirmasi pembelian

Jika menggunakan Library Layanan Penagihan Google Play versi 2.0 atau lebih baru, Anda harus mengonfirmasi semua pembelian dalam waktu tiga hari. Kegagalan untuk mengonfirmasi pembelian akan menyebabkan pengembalian dana pembelian.

Google Play mendukung pembelian produk dari dalam aplikasi (in-app) atau di luar aplikasi (out-of-app). Agar Google Play dapat memberikan pengalaman pembelian yang konsisten di mana pun pengguna membeli produk Anda, konfirmasikan semua pembelian dengan status SUCCESS yang diterima melalui Library Layanan Penagihan Google Play sesegera mungkin setelah Anda memberikan hak kepada pengguna. Jika pembelian tidak dikonfirmasi dalam tiga hari, pengguna akan menerima pengembalian dana secara otomatis, dan Google Play akan membatalkan pembelian tersebut. Untuk transaksi yang tertunda, jangka waktu tiga hari ini tidak berlaku jika pembelian berstatus PENDING. Jangka waktu ini dimulai ketika status pembelian berubah menjadi SUCCESS.

Anda dapat mengonfirmasi pembelian menggunakan salah satu metode berikut:

  • Untuk produk habis pakai, gunakan consumeAsync(), yang tersedia dalam API klien.
  • Untuk produk tidak habis pakai, gunakan acknowledgePurchase(), yang tersedia dalam API klien.
  • Metode acknowledge() baru juga tersedia di API server.

Untuk langganan, Anda harus mengonfirmasi pembelian apa pun yang berisi token pembelian baru. Ini berarti semua pembelian awal, perubahan paket, dan pendaftaran ulang harus dikonfirmasi, tetapi Anda tidak perlu mengonfirmasi perpanjangan selanjutnya. Untuk menentukan apakah pembelian memerlukan konfirmasi, Anda dapat memeriksa kolom konfirmasi pada pembelian.

Objek Purchase menyertakan metode isAcknowledged() yang menunjukkan apakah pembelian telah dikonfirmasi atau belum. Selain itu, API sisi server kini menyertakan nilai boolean konfirmasi untuk Product.purchases.get() dan Product.subscriptions.get(). Sebelum mengonfirmasi pembelian, gunakan metode ini untuk menentukan apakah pembelian telah dikonfirmasi atau belum.

Contoh berikut menunjukkan cara mengonfirmasi pembelian langganan:

Kotlin

val client: BillingClient = ...
fun handlePurchase() {
    if (purchase.purchaseState === PurchaseState.PURCHASED) {
        // Grant entitlement to the user.
        ...
        // Acknowledge the purchase if it hasn't already been acknowledged.
        if (!purchase.isAcknowledged) {
            val acknowledgePurchaseParams = AcknowledgePurchaseParams.newBuilder()
                    .setPurchaseToken(purchase.purchaseToken)
            val ackPurchaseResult = withContext(Dispatchers.IO) {
               client.acknowledgePurchase(acknowledgePurchaseParams.build())
            }
        }
     }
}

Java

BillingClient client = ...
AcknowledgePurchaseResponseListener acknowledgePurchaseResponseListener = ...

void handlePurchase(Purchase purchase) {
    if (purchase.getPurchaseState() == PurchaseState.PURCHASED) {
        // Grant entitlement to the user.
        ...

        // Acknowledge the purchase if it hasn't already been acknowledged.
        if (!purchase.isAcknowledged()) {
            AcknowledgePurchaseParams acknowledgePurchaseParams =
                AcknowledgePurchaseParams.newBuilder()
                    .setPurchaseToken(purchase.getPurchaseToken())
                    .build();
            client.acknowledgePurchase(acknowledgePurchaseParams, acknowledgePurchaseResponseListener);
        }
    }
}

Menguji konfirmasi pembelian dengan penguji lisensi

Untuk pembelian yang dilakukan oleh penguji lisensi, rentang waktu konfirmasinya menjadi lebih singkat. Pembelian akan dikembalikan dananya dan dicabut jika tidak dikonfirmasi dalam waktu lima menit, bukan tiga hari.

Mendukung transaksi yang tertunda

Saat menerapkan solusi Layanan Penagihan Google Play, Anda harus mendukung pembelian yang memerlukan tindakan tambahan sebelum memberikan hak. Misalnya, pengguna mungkin memilih untuk membeli produk dalam aplikasi Anda di toko fisik menggunakan uang tunai. Jika demikian, artinya transaksi tersebut diselesaikan di luar aplikasi Anda. Dalam skenario ini, sebaiknya hanya berikan hak setelah pengguna menyelesaikan transaksi.

Untuk mengaktifkan pembelian tertunda, panggil enablePendingPurchases() saat Anda menginisialisasi aplikasi. Perlu diketahui bahwa jika enablePendingPurchases() tidak dipanggil, Anda tidak akan dapat membuat instance Library Layanan Penagihan Google Play.

Gunakan metode Purchase.getPurchaseState() untuk menentukan apakah pembelian berstatus PURCHASED atau PENDING. Perlu diketahui bahwa Anda sebaiknya hanya memberikan hak jika statusnya adalah PURCHASED. Anda dapat memeriksa perubahan status dengan melakukan tindakan berikut:

  1. Saat memulai aplikasi, panggil BillingClient.queryPurchases() untuk mendapatkan daftar produk tidak terpakai yang terkait dengan pengguna, lalu panggil getPurchaseState() pada setiap objek Purchase yang ditampilkan.
  2. Implementasikan metode onPurchasesUpdated() untuk merespons perubahan pada objek Purchase.

Berikut adalah contoh yang menunjukkan cara menangani transaksi tertunda:

Kotlin

fun handlePurchase(purchase: Purchase) {
    if (purchase.purchaseState == PurchaseState.PURCHASED) {
        // Grant the item to the user, and then acknowledge the purchase
    } else if (purchase.purchaseState == PurchaseState.PENDING) {
        // Here you can confirm to the user that they've started the pending
        // purchase, and to complete it, they should follow instructions that
        // are given to them. You can also choose to remind the user in the
        // future to complete the purchase if you detect that it is still
        // pending.
    }
}

Java

void handlePurchase(Purchase purchase) {
    if (purchase.getPurchaseState() == PurchaseState.PURCHASED) {
        // Acknowledge purchase and grant the item to the user
    } else if (purchase.getPurchaseState() == PurchaseState.PENDING) {
        // Here you can confirm to the user that they've started the pending
        // purchase, and to complete it, they should follow instructions that
        // are given to them. You can also choose to remind the user in the
        // future to complete the purchase if you detect that it is still
        // pending.
    }
}

Menguji transaksi yang tertunda dengan penguji lisensi

Transaksi yang tertunda dapat diuji menggunakan penguji lisensi. Selain dua kartu kredit uji, penguji lisensi memiliki akses ke dua instrumen uji untuk metode pembayaran tertunda yang secara otomatis selesai atau batal setelah beberapa menit.

Saat menguji aplikasi, sebaiknya Anda memverifikasi bahwa aplikasi Anda tidak memberikan hak atau segera mengonfirmasi jika pembelian dilakukan menggunakan salah satu dari kedua instrumen tersebut. Jika pembelian dilakukan menggunakan instrumen uji yang otomatis selesai, sebaiknya Anda memverifikasi bahwa aplikasi Anda memberikan hak dan mengonfirmasi pembelian begitu pembelian tersebut selesai.

Saat membeli menggunakan instrumen uji yang secara otomatis membatalkan, Anda harus memverifikasi bahwa aplikasi Anda tidak memberikan hak, karena tidak ada pembelian yang berhasil.

Menambahkan payload developer

Anda dapat menambahkan string arbitrer, atau payload developer, ke pembelian. Namun, perlu diketahui bahwa payload developer hanya dapat ditambahkan setelah pembelian dikonfirmasi atau dipakai. Ini berbeda dengan payload developer di AIDL, di mana payload dapat ditentukan saat memulai alur pembelian.

Untuk produk habis pakai, consumeAsync() akan mengambil objek ConsumeParams yang menyertakan kolom payload developer, seperti pada contoh berikut:

Kotlin

val client: BillingClient = ...
fun consumePurchase() {
    val consumeParams =
        ConsumeParams.newBuilder()
            .setPurchaseToken(/* token */)
            .setDeveloperPayload(/* payload */)
            .build()
    val consumeResult = withContext(Dispatchers.IO) {
        client.consumePurchase(consumeParams)
    }
}

Java

BillingClient client = ...
ConsumeResponseListener listener = ...

ConsumeParams consumeParams =
    ConsumeParams.newBuilder()
        .setPurchaseToken(/* token */)
        .setDeveloperPayload(/* payload */)
        .build();

client.consumeAsync(consumeParams, listener);

Untuk produk tidak habis pakai, acknowledgePurchase() akan mengambil objek AcknowledgePurchaseParams yang menyertakan kolom payload developer, seperti yang ditunjukkan pada contoh berikut:

Kotlin

val client: BillingClient = ...
fun acknowledgePurchase() {
    val acknowledgePurchaseParams =
        AcknowledgePurchaseParams.newBuilder()
            .setPurchaseToken(/* token */)
            .setDeveloperPayload(/* payload */)
            .build()
    val ackPurchaseResult = withContext(Dispatchers.IO) {
        client.acknowledgePurchase(acknowledgePurchaseParams)
    }
}

Java

BillingClient client = ...
AcknowledgePurchaseResponseListener listener = ...

AcknowledgePurchaseParams acknowledgePurchaseParams =
    AcknowledgePurchaseParams.newBuilder()
        .setPurchaseToken(/* token */)
        .setDeveloperPayload(/* payload */)
        .build();

client.acknowledgePurchase(acknowledgePurchaseParams, listener);

Untuk mengakses payload developer, panggil getDeveloperPayload() pada objek Purchase yang terkait.

Anda hanya dapat memakai atau mengonfirmasi pembelian di status pembelian PURCHASED.

Memverifikasi pembelian

Anda harus selalu memverifikasi bahwa status pembeliannya adalah PURCHASED, dan memastikan detail pembelian lain yang diterima aplikasi Anda dalam onPurchasesUpdated() sebelum memberi pengguna akses ke item yang telah mereka beli.

Memverifikasi pembelian di server

Dengan menerapkan logika verifikasi pembelian di server, Anda dapat melindungi aplikasi dari penyerang yang mencoba merekayasa balik file APK Anda dan menonaktifkan logika verifikasinya. Untuk memverifikasi detail pembelian pada server backend aman, lakukan langkah-langkah berikut:

  1. Dari aplikasi Anda, kirim token pembelian dan kredensial akun pengguna ke server backend aman. Server backend aman akan mengaitkan pembelian ini dengan pengguna setelah verifikasi berhasil.

  2. Setelah Anda mendapatkan token dari aplikasi:

    1. Gunakan bagian Langganan dan Pembelian dari Google Play Developer API untuk menjalankan permintaan GET guna mengambil detail pembelian dari Google Play (Purchases.products untuk pembelian produk sekali beli atau Purchases.subscriptions untuk langganan). Permintaan GET mencakup nama paket aplikasi, ID produk, dan token (token pembelian).

    2. Google Play menampilkan detail pembelian.

    3. Server backend aman memverifikasi bahwa ID pesanan memiliki nilai unik yang tidak mewakili pembelian sebelumnya.

    4. Server backend aman menggunakan kredensial akun pengguna yang diterima pada langkah 1 untuk mengaitkan token pembelian tersebut dengan pengguna instance aplikasi tempat pembelian dilakukan.

    5. (opsional) Jika Anda memvalidasi langganan dan langganan tersebut sedang diupgrade, didowngrade, atau pengguna telah berlangganan kembali sebelum masa langganan berakhir, periksa kolom linkedPurchaseToken. Kolom linkedPurchaseToken di dalam resource Purchases.subscriptions berisi token dari pembelian sebelumnya, atau pembelian "asal". Untuk informasi selengkapnya tentang linkedPurchaseToken, lihat Purchases.subscriptions).

    6. Produk dalam aplikasi disediakan untuk pengguna.

Memverifikasi pembelian di perangkat

Jika tidak dapat menjalankan server Anda sendiri, Anda masih dapat memvalidasi detail pembelian dari dalam aplikasi Android Anda.

Untuk membantu memastikan integritas informasi transaksi yang dikirim ke aplikasi Anda, Google Play akan menandatangani string JSON yang berisi data respons untuk suatu pembelian. Google Play menggunakan kunci pribadi yang terkait dengan aplikasi Anda di Konsol Play untuk membuat tanda tangan ini. Konsol Play akan membuat pasangan kunci RSA untuk setiap aplikasi. Untuk mendapatkan JSON respons ini, gunakan metode getOriginalJson() dalam class Purchase.

Kunci publik RSA yang dienkode dengan Base64 yang dihasilkan oleh Google Play memiliki format X.509 subjectPublicKeyInfo DER SEQUENCE yang dienkode dengan biner. Kunci publik ini sama seperti yang digunakan dengan pemberian lisensi Google Play.

Setelah aplikasi Anda menerima respons bertanda tangan ini, Anda dapat menggunakan bagian kunci publik dari pasangan kunci RSA untuk memverifikasi tanda tangan. Dengan memverifikasi tanda tangan, Anda dapat mendeteksi apakah ada respons yang telah dimodifikasi atau dipalsukan.

Anda harus meng-obfuscate kunci publik Google Play dan kode Layanan Penagihan Google Play untuk menyulitkan penyerang merekayasa balik protokol keamanan dan komponen aplikasi lainnya. Setidaknya, kami merekomendasikan Anda untuk menggunakan taktik obfuscation pada kode aplikasi menggunakan R8 atau ProGuard. Jika demikian, Anda harus menambahkan baris berikut ke file konfigurasi ProGuard Anda:

-keep class com.android.vending.billing.**

Setelah menyamarkan kunci publik Google Play dan kode Layanan Penagihan Google Play, Anda siap meminta aplikasi agar memvalidasi detail pembelian. Saat aplikasi Anda memverifikasi tanda tangan, pastikan kunci aplikasi Anda menandatangani data JSON yang terdapat dalam tanda tangan tersebut.

Menjaga pembelian selalu terupdate

Bisa jadi Anda akan kesulitan melacak pembelian yang dilakukan pengguna. Berikut adalah dua skenario di mana aplikasi tidak bisa melacak pembelian dan pembuatan kueri pembelian menjadi penting.

Menangani gangguan server

  1. Seorang pengguna membeli produk sekali beli, seperti bahan bakar tambahan untuk game mengemudi.
  2. Aplikasi mengirimkan token pembelian ke server backend aman untuk diverifikasi.
  3. Server sedang mengalami gangguan sementara.
  4. Aplikasi mengetahui bahwa server sedang mengalami gangguan dan memberi tahu pengguna bahwa ada masalah dengan pembelian.
  5. Aplikasi Android mencoba mengirim kembali token pembelian ke server backend aman, dan menyelesaikan pembelian segera setelah server kembali normal.
  6. Aplikasi merilis konten.

Menangani beberapa perangkat

  1. Seorang pengguna membeli langganan dari ponsel Android.
  2. Aplikasi mengirimkan token pembelian ke server backend aman untuk diverifikasi.
  3. Server memverifikasi token pembelian.
  4. Aplikasi merilis konten.
  5. Pengguna beralih ke tablet Android untuk menggunakan langganannya.
  6. Aplikasi pada tablet mengkueri daftar pembelian terbaru.
  7. Aplikasi mengenali langganan itu dan memberikan akses untuk penggunaan di tablet.

Mengkueri pembelian yang di-cache

Untuk mengambil informasi tentang pembelian yang dilakukan pengguna dari aplikasi Anda, panggil queryPurchases() dengan jenis pembelian (SkuType.INAPP atau SkuType.SUBS) yang ada pada BillingClient, seperti yang ditunjukkan pada contoh berikut:

Kotlin

val purchasesResult: PurchasesResult =
        billingClient.queryPurchases(SkuType.INAPP)

Java

PurchasesResult purchasesResult = billingClient.queryPurchases(SkuType.INAPP);

Google Play akan menampilkan pembelian yang dilakukan oleh akun pengguna yang login ke perangkat. Jika permintaan tersebut berhasil, Library Layanan Penagihan Play akan menyimpan hasil kueri dalam List dari objek Purchase.

Untuk mengambil daftar ini, panggil getPurchasesList() pada PurchasesResult. Anda kemudian dapat memanggil berbagai metode pada objek Purchase untuk menampilkan informasi yang relevan tentang item tersebut, seperti status atau waktu pembeliannya. Untuk menampilkan jenis informasi detail produk yang tersedia, lihat daftar metode dalam class Purchase.

Anda harus memanggil queryPurchases() setidaknya dua kali dalam kode Anda:

  • Panggil queryPurchases() setiap kali aplikasi diluncurkan sehingga Anda dapat memulihkan setiap pembelian yang dilakukan pengguna sejak aplikasi terakhir berhenti.
  • Panggil queryPurchases() dalam metode onResume(), karena pengguna dapat melakukan pembelian saat aplikasi Anda berjalan di latar belakang (misalnya, menukarkan kode promo di aplikasi Google Play Store).

Memanggil queryPurchases() pada saat aplikasi dimulai dan dilanjutkan akan menjamin bahwa aplikasi Anda mengetahui semua pembelian dan penukaran yang mungkin dilakukan pengguna saat aplikasi tidak berjalan. Selain itu, jika pengguna melakukan pembelian saat aplikasi sedang berjalan dan aplikasi Anda melewatkannya karena suatu alasan, aplikasi akan tetap mengetahui pembelian tersebut pada saat aktivitas dilanjutkan dan memanggil queryPurchases().

Membuat kueri pembelian terbaru

Metode queryPurchases() menggunakan cache aplikasi Google Play Store tanpa memulai permintaan jaringan. Jika perlu memeriksa pembelian terakhir yang dilakukan pengguna untuk setiap ID produk, Anda dapat menggunakan queryPurchaseHistoryAsync() dengan meneruskan jenis pembelian dan PurchaseHistoryResponseListener untuk menangani hasil kueri.

queryPurchaseHistoryAsync() menampilkan objek PurchaseHistory yang berisi informasi pembelian terakhir yang dilakukan pengguna untuk setiap ID produk, meskipun pembelian tersebut telah berakhir, dibatalkan, atau habis terpakai. Gunakan queryPurchases() jika memungkinkan, karena metode tersebut menggunakan cache lokal, bukan queryPurchaseHistoryAsync(). Jika menggunakan queryPurchaseHistoryAsync(), Anda juga dapat mengombinasikannya dengan tombol Refresh sehingga pengguna dapat memperbarui daftar pembeliannya.

Kode berikut menunjukkan cara mengganti metode onPurchaseHistoryResponse():

Kotlin

val billingClient: BillingClient = ...
fun queryPurchaseHistory() {
    val purchaseHistoryResult = withContext(Dispatchers.IO) {
        billingClient.queryPurchaseHistory(skuType)
    }
    // Process the result.
}

Java

billingClient.queryPurchaseHistoryAsync(SkuType.INAPP,
                                         new PurchaseHistoryResponseListener() {
    @Override
    public void onPurchaseHistoryResponse(BillingResult billingResult,
                                          List<Purchase> purchasesList) {
        if (billingResult.getResponseCode() == BillingResponse.OK
                && purchasesList != null) {
            for (Purchase purchase : purchasesList) {
                // Process the result.
            }
         }
    }
});

Langkah berikutnya

Setelah dapat mengizinkan pengguna untuk membeli produk Anda, Anda perlu mempelajari cara menangani skenario produk tertentu: