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 mencakup cara menambahkan fungsionalitas Layanan Penagihan Google Play yang umum untuk semua jenis produk dalam aplikasi: produk sekali beli, produk bonus, dan langganan. Untuk mempelajari cara menambahkan fungsionalitas khusus produk dalam aplikasi ke aplikasi Anda, baca dokumen yang tercantum di akhir halaman ini.

Sebelum membaca halaman ini, lakukan hal berikut:

  1. Baca Ringkasan Layanan Penagihan Google Play untuk memahami konsep dan istilah penting.
  2. Konfigurasikan produk dalam aplikasi Anda menggunakan Konsol 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.

Perbarui dependensi aplikasi Anda

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

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

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

Sambungkan ke Google Play

Agar dapat membuat permintaan Layanan Penagihan Google Play, terlebih dahulu Anda harus membuat sambungan ke Google Play dengan melakukan langkah-langkah berikut:

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

  2. Buat sambungan ke Google Play. Proses penyiapan ini bersifat asinkron, dan Anda harus mengimplementasikan BillingClientStateListener untuk menerima callback setelah penyiapan klien selesai, dan klien siap membuat permintaan lebih lanjut.

  3. Ganti metode callback onBillingServiceDisconnected() dan implementasikan kebijakan mencoba ulang Anda sendiri untuk menangani sambungan ke Google Play yang terputus jika klien kehilangan koneksi. Misalnya, BillingClient dapat terputus 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 == BillingResponse.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() == BillingResponse.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.
    }
});

Membuat kueri tentang detail produk dalam aplikasi

ID produk unik yang Anda buat saat mengonfigurasi produk dalam aplikasi digunakan untuk secara asinkron membuat kueri Google Play tentang detail produk dalam aplikasi. Untuk membuat kueri Google Play tentang 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 produk bonus, atau SkuType.SUBS untuk langganan.

Untuk menangani hasil operasi asinkron ini, Anda juga harus menentukan pemroses yang mengimplementasikan antarmuka SkuDetailsResponseListener. Selanjutnya, Anda dapat mengganti onSkuDetailsResponse() yang memberi tahu pemroses saat kueri selesai, seperti yang diilustrasikan dalam contoh kode berikut:

Kotlin

val skuList = ArrayList<String>()
skuList.add("premium_upgrade")
skuList.add("gas")
val params = SkuDetailsParams.newBuilder()
params.setSkusList(skuList).setType(SkuType.INAPP)
billingClient.querySkuDetailsAsync(params.build(), { billingResult, skuDetailsList ->
    // 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 ini berhasil, kode responsnya adalah BillingResponse.OK. Untuk daftar kode respons yang mungkin 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. Selanjutnya, Anda 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 adalah langkah penting sebelum pengguna dapat membeli suatu produk, karena harga tersebut berbeda untuk setiap pengguna sesuai 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 asli SKU:

Mengaktifkan pembelian produk dalam aplikasi

Beberapa ponsel Android mungkin memiliki aplikasi Google Play Store versi lama yang tidak mendukung tipe produk tertentu, seperti langganan. Oleh karena itu, sebelum aplikasi Anda memasuki alur penagihan, panggil isFeatureSupported() untuk memeriksa apakah perangkat mendukung produk yang ingin Anda jual atau tidak. Untuk mengetahui daftar tipe produk, lihat BillingClient.FeatureType.

Untuk memulai permintaan pembelian dari aplikasi Anda, panggil metode launchBillingFlow() dari UI thread. Teruskan referensi ke objek BillingFlowParams yang memuat data terkait untuk menyelesaikan pembelian, seperti ID produk (skuId) item dan tipe produk (SkuType.INAPP untuk produk sekali beli atau produk bonus, atau SkuType.SUBS untuk langganan). Untuk mendapatkan instance dari 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);

Setelah 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 di BillingClient.BillingResponse. Google Play memanggil metode onPurchasesUpdated() untuk mengirimkan hasil operasi pembelian ke pemroses yang mengimplementasikan antarmuka PurchasesUpdatedListener. Pemroses ditentukan menggunakan metode setListener() seperti yang ditunjukkan sebelumnya di bagian Sambungkan ke Google Play.

Anda harus mengimplementasikan metode onPurchasesUpdated() untuk menangani kode respons yang dimungkinkan. 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 mirip 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 dan produk bonus. Namun, karena langganan dibeli satu kali dan otomatis diperpanjang pada periode penagihan reguler, token pembelian untuk langganan tetap sama untuk setiap periode penagihan.

Pengguna juga akan menerima email tanda terima transaksi yang berisi ID pesanan atau ID unik transaksi. Pengguna menerima email yang berisi ID pesanan unik untuk setiap pembelian produk sekali beli, dan 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 mengetahui detail lebih lanjut, baca Melihat 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 Anda (in-app) atau di luar aplikasi Anda (out-of-app). Agar Google Play dapat memberikan pengalaman pembelian yang konsisten di mana pun pengguna membeli produk Anda, Anda harus mengonfirmasi semua pembelian berstatus SUCCESS yang diterima melalui Library Layanan Penagihan Google Play sesegera mungkin setelah memberikan hak kepada pengguna. Jika Anda tidak mengonfirmasi pembelian dalam waktu tiga hari, pengguna akan secara otomatis menerima pengembalian dana, dan Google Play mencabut pembelian tersebut. Untuk transaksi yang tertunda, rentang waktu tiga hari ini tidak berlaku jika pembelian berstatus PENDING. Sebagai gantinya, rentang waktu ini dimulai saat status pembelian berganti menjadi SUCCESS.

Anda dapat mengonfirmasi pembelian menggunakan salah satu metode berikut:

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

Untuk langganan, Anda harus mengonfirmasi setiap pembelian 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 mencakup metode isAcknowledged() yang menunjukkan apakah pembelian telah dikonfirmasi atau belum. Selain itu, API pada sistem server sekarang 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 = ...
val acknowledgePurchaseResponseListener: AcknowledgePurchaseResponseListener = ...

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)
                    .build()
            client.acknowledgePurchase(acknowledgePurchaseParams, acknowledgePurchaseResponseListener)
        }
     }
}

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 hak 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 mengaktifkan pembelian tertunda, panggil enablePendingPurchases() saat menginisialisasi aplikasi Anda. Perlu diperhatikan bahwa jika Anda tidak memanggil enablePendingPurchases(), Anda tidak dapat membuat instance Library Layanan Penagihan Google Play.

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

  1. Saat memulai aplikasi, panggil BillingClient.queryPurchases() untuk mengambil daftar produk yang tidak terpakai yang terkait dengan pengguna, lalu panggil getPurchaseState() untuk 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 mencakup kolom payload developer, seperti yang ditunjukkan dalam contoh berikut:

Kotlin

val client: BillingClient = ...
val listener: ConsumeResponseListener = ...

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

client.consumeAsync(consumeParams, listener)

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 mencakup kolom payload developer, seperti yang ditunjukkan dalam contoh berikut:

Kotlin

val client: BillingClient = ...
val listener: AcknowledgePurchaseResponseListener = ...

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

client.acknowledgePurchase(acknowledgePurchaseParams, listener)

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 pembelian adalah PURCHASED dan detail pembelian lain yang diterima aplikasi Anda di 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 pada Google Play Developer API untuk membuat permintaan GET dan mengambil detail pembelian dari Google Play (Purchases.products untuk pembelian produk sekali beli atau produk bonus, atau Purchases.subscriptions untuk berlangganan). 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 sedang diupgrade, didowngrade, atau pengguna berlangganan ulang sebelum langganannya berakhir, periksa kolom linkedPurchaseToken. Kolom linkedPurchaseToken dalam resource Purchases.subscriptions berisi token dari pembelian sebelumnya, atau pembelian "asal". Untuk mengetahui 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 menandatangani string JSON yang berisi data respons untuk suatu pembelian. Google Play menggunakan kunci pribadi yang dikaitkan dengan aplikasi Anda di Konsol Play untuk membuat tanda tangan ini. Konsol Play membuat pasangan kunci RSA untuk setiap aplikasi. Anda mendapatkan respons JSON ini menggunakan metode getOriginalJson() dalam class Purchase.

Kunci publik RSA berenkode Base64 yang dihasilkan oleh Google Play memiliki format X.509 subjectPublicKeyInfo DER SEQUENCE berenkode biner. Ini adalah kunci publik yang sama yang digunakan pada 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 menyamarkan 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 menyamarkan kode aplikasi menggunakan R8 atau ProGuard. Jika melakukannya, Anda harus menambahkan baris berikut ke file konfigurasi ProGuard:

-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 tersebut dan memberikan akses untuk penggunaan di tablet.

Membuat kueri pembelian yang di-cache

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

Kotlin

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

Java

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

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

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

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

  • Panggil queryPurchases() setiap kali aplikasi diluncurkan sehingga Anda dapat memulihkan semua 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 promosi 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 selama aplikasi tidak berjalan. Selain itu, jika ada pengguna yang melakukan pembelian selama aplikasi berjalan, dan aplikasi Anda melewatkannya karena suatu alasan, aplikasi Anda tetap akan mengetahui pembelian tersebut saat aktivitas dilanjutkan lagi 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(), yang akan 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, meski pembelian tersebut telah berakhir, dibatalkan, atau 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 pembelian mereka.

Kode berikut menunjukkan cara mengganti metode onPurchaseHistoryResponse():

Kotlin

billingClient.queryPurchaseHistoryAsync(SkuType.INAPP, { billingResult, purchasesList ->
   if (billingResult.responseCode == BillingResponse.OK && purchasesList != null) {
       for (purchase in purchasesList) {
           // 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: