Topik ini menjelaskan cara mengintegrasikan Library Layanan Penagihan Google Play ke aplikasi Anda untuk mulai menjual produk.
Umur pembelian
Berikut ini alur pembelian yang biasa untuk pembelian satu kali atau langganan.
- Menunjukkan kepada pengguna apa yang dapat mereka beli.
- Meluncurkan alur pembelian bagi pengguna untuk menerima pembelian.
- Memverifikasi pembelian di server Anda.
- Memberikan konten kepada pengguna.
- Mengonfirmasi pengiriman konten. Untuk produk habis pakai, pakai item yang telah dibeli agar pengguna dapat membeli item itu lagi.
Langganan diperpanjang secara otomatis hingga dibatalkan. Langganan dapat melalui status berikut:
- Aktif: Pengguna memiliki reputasi baik dan memiliki akses ke langganan.
- Dibatalkan: Pengguna telah membatalkan langganan, tetapi masih memiliki akses hingga masa berlakunya berakhir.
- Dalam masa tenggang: Pengguna mengalami masalah pembayaran, tetapi masih dapat mengakses saat Google mencoba kembali metode pembayaran.
- Ditangguhkan: Pengguna mengalami masalah pembayaran dan tidak lagi memiliki akses saat Google mencoba kembali metode pembayaran.
- Dijeda: Pengguna menjeda aksesnya dan tidak memiliki akses hingga mereka melanjutkan.
- Berakhir: Pengguna telah membatalkan dan kehilangan akses ke langganan. Pengguna dianggap churn out (berhenti menggunakan aplikasi) saat masa berlaku habis.
Melakukan inisialisasi pada koneksi ke Google Play
Langkah pertama untuk berintegrasi dengan sistem penagihan Google Play adalah menambahkan Library Layanan Penagihan Google Play ke aplikasi Anda dan melakukan inisialisasi koneksi.
Menambahkan dependensi Library Layanan Penagihan Google Play
Tambahkan dependensi Library Layanan Penagihan Google Play ke file build.gradle
aplikasi Anda
seperti yang ditunjukkan:
Groovy
dependencies { def billing_version = "7.0.0" implementation "com.android.billingclient:billing:$billing_version" }
Kotlin
dependencies { val billing_version = "7.0.0" implementation("com.android.billingclient:billing:$billing_version") }
Jika Anda menggunakan Kotlin, modul KTX Library Layanan Penagihan Google Play berisi
ekstensi Kotlin dan dukungan coroutine yang memungkinkan Anda menulis
Kotlin idiomatis saat menggunakan Library Layanan Penagihan Google Play. Untuk menyertakan ekstensi ini
dalam project Anda, tambahkan dependensi berikut ke file build.gradle
aplikasi
Anda seperti yang ditunjukkan:
Groovy
dependencies { def billing_version = "7.0.0" implementation "com.android.billingclient:billing-ktx:$billing_version" }
Kotlin
dependencies { val billing_version = "7.0.0" implementation("com.android.billingclient:billing-ktx:$billing_version") }
Melakukan inisialisasi pada BillingClient
Setelah menambahkan dependensi pada Google Play Billing Library, Anda perlu
melakukan inisialisasi instance BillingClient
. BillingClient
adalah antarmuka utama
untuk komunikasi antara Library Layanan Penagihan Google Play dan bagian
lain aplikasi Anda. BillingClient
menyediakan metode praktis, baik sinkron
maupun asinkron, untuk berbagai operasi penagihan umum. Sebaiknya Anda memiliki satu
koneksi BillingClient
aktif yang terbuka pada satu waktu untuk
menghindari beberapa callback PurchasesUpdatedListener
untuk satu peristiwa.
Untuk membuat BillingClient
, gunakan newBuilder()
. Anda dapat meneruskan konteks
ke newBuilder()
, dan BillingClient
akan menggunakannya untuk mendapatkan konteks aplikasi.
Dengan demikian, Anda tidak perlu mengkhawatirkan kebocoran memori. Untuk menerima update tentang
pembelian, Anda juga harus memanggil setListener()
, yang meneruskan referensi ke
PurchasesUpdatedListener
. Pemroses ini menerima update untuk semua
pembelian di aplikasi Anda.
Kotlin
private val purchasesUpdatedListener = PurchasesUpdatedListener { billingResult, purchases -> // To be implemented in a later section. } private var billingClient = BillingClient.newBuilder(context) .setListener(purchasesUpdatedListener) // Configure other settings. .build()
Java
private PurchasesUpdatedListener purchasesUpdatedListener = new PurchasesUpdatedListener() { @Override public void onPurchasesUpdated(BillingResult billingResult, List<Purchase> purchases) { // To be implemented in a later section. } }; private BillingClient billingClient = BillingClient.newBuilder(context) .setListener(purchasesUpdatedListener) // Configure other settings. .build();
Menghubungkan ke Google Play
Setelah membuat BillingClient
, Anda harus membuat koneksi ke
Google Play.
Agar terhubung ke Google Play, panggil startConnection()
. Proses koneksi
bersifat asinkron, dan Anda harus menerapkan
BillingClientStateListener
untuk menerima callback setelah penyiapan klien
selesai dan siap untuk membuat permintaan lebih lanjut.
Anda juga harus menerapkan logika mencoba ulang untuk menangani koneksi yang terputus ke Google Play.
Untuk menerapkan logika mencoba ulang, ganti metode callback
onBillingServiceDisconnected()
, dan pastikan BillingClient
memanggil
metode startConnection()
untuk terhubung kembali ke Google Play sebelum membuat
permintaan lebih lanjut.
Contoh berikut menunjukkan cara memulai koneksi dan menguji apakah koneksi siap digunakan:
Kotlin
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
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. } });
Menampilkan produk yang tersedia untuk dibeli
Setelah terhubung ke Google Play, Anda siap membuat kueri untuk produk yang tersedia dan menampilkannya kepada pengguna.
Kueri untuk detail produk merupakan langkah penting sebelum menampilkan produk kepada pengguna, karena proses ini akan menampilkan informasi produk yang dilokalkan. Untuk langganan, pastikan tampilan produk Anda mengikuti semua kebijakan Play.
Untuk membuat kueri detail produk dalam aplikasi, panggil queryProductDetailsAsync()
.
Untuk menangani hasil operasi asinkron, Anda juga harus menentukan
pemroses yang menerapkan antarmuka ProductDetailsResponseListener
.
Anda kemudian dapat mengganti onProductDetailsResponse()
, yang memberi tahu
pemroses ketika kueri selesai, seperti yang ditunjukkan dalam contoh berikut:
Kotlin
val queryProductDetailsParams = QueryProductDetailsParams.newBuilder() .setProductList( ImmutableList.of( Product.newBuilder() .setProductId("product_id_example") .setProductType(ProductType.SUBS) .build())) .build() billingClient.queryProductDetailsAsync(queryProductDetailsParams) { billingResult, productDetailsList -> // check billingResult // process returned productDetailsList }
Java
QueryProductDetailsParams queryProductDetailsParams = QueryProductDetailsParams.newBuilder() .setProductList( ImmutableList.of( Product.newBuilder() .setProductId("product_id_example") .setProductType(ProductType.SUBS) .build())) .build(); billingClient.queryProductDetailsAsync( queryProductDetailsParams, new ProductDetailsResponseListener() { public void onProductDetailsResponse(BillingResult billingResult, List<ProductDetails> productDetailsList) { // check billingResult // process returned productDetailsList } } )
Saat membuat kueri untuk detail produk, teruskan instance
QueryProductDetailsParams
yang menentukan daftar string ID produk
yang dibuat di Konsol Google Play bersama dengan ProductType
. ProductType
dapat berupa ProductType.INAPP
untuk produk sekali beli, atau
ProductType.SUBS
untuk langganan.
Membuat kueri dengan ekstensi Kotlin
Jika menggunakan ekstensi Kotlin, Anda dapat membuat kueri untuk detail produk
dalam aplikasi dengan memanggil fungsi ekstensi queryProductDetails()
.
queryProductDetails()
memanfaatkan coroutine Kotlin sehingga Anda tidak perlu
menentukan pemroses terpisah. Sebagai gantinya, fungsi tersebut akan ditangguhkan hingga kueri
selesai, setelah itu Anda dapat memproses hasilnya:
suspend fun processPurchases() {
val productList = listOf(
QueryProductDetailsParams.Product.newBuilder()
.setProductId("product_id_example")
.setProductType(BillingClient.ProductType.SUBS)
.build()
)
val params = QueryProductDetailsParams.newBuilder()
params.setProductList(productList)
// leverage queryProductDetails Kotlin extension function
val productDetailsResult = withContext(Dispatchers.IO) {
billingClient.queryProductDetails(params.build())
}
// Process the result.
}
Meskipun jarang terjadi, beberapa perangkat mungkin tidak dapat mendukung ProductDetails
dan
queryProductDetailsAsync()
, biasanya karena versi Layanan Google Play yang sudah tidak
berlaku. Untuk memastikan dukungan yang tepat untuk skenario ini, pelajari cara menggunakan
fitur kompatibilitas mundur dalam panduan migrasi Library Layanan Penagihan
Play 5.
Memproses hasil
Library Layanan Penagihan Google Play menyimpan hasil kueri dalam List
objek ProductDetails
. Anda kemudian dapat memanggil berbagai metode pada setiap
objek ProductDetails
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 ProductDetails
.
Sebelum menawarkan item untuk dijual, pastikan pengguna belum memiliki item tersebut. Jika pengguna memiliki item habis pakai yang masih ada dalam library item, mereka harus memakai item tersebut sebelum dapat membelinya lagi.
Sebelum menawarkan langganan, verifikasi bahwa pengguna belum berlangganan. Selain itu, perhatikan hal-hal berikut:
queryProductDetailsAsync()
menampilkan detail produk langganan dan maksimum 50 penawaran per langganan.queryProductDetailsAsync()
hanya menampilkan penawaran bagi pengguna yang memenuhi syarat. Jika pengguna mencoba membeli penawaran sedangkan mereka tidak memenuhi syarat (misalnya, jika aplikasi menampilkan daftar yang tidak berlaku lagi tentang penawaran yang memenuhi syarat), Play akan memberi tahu pengguna bahwa mereka tidak memenuhi syarat, dan sebagai gantinya, pengguna dapat memilih untuk membeli paket dasar.
Meluncurkan alur pembelian
Untuk memulai permintaan pembelian dari aplikasi Anda, panggil metode launchBillingFlow()
dari thread utama aplikasi Anda. Metode ini mengambil referensi ke
objek BillingFlowParams
yang berisi objek ProductDetails
yang relevan dan diperoleh dari panggilan
queryProductDetailsAsync()
. Untuk membuat objek BillingFlowParams
, gunakan
class BillingFlowParams.Builder
.
Kotlin
// An activity reference from which the billing flow will be launched. val activity : Activity = ...; val productDetailsParamsList = listOf( BillingFlowParams.ProductDetailsParams.newBuilder() // retrieve a value for "productDetails" by calling queryProductDetailsAsync() .setProductDetails(productDetails) // For One-time product, "setOfferToken" method shouldn't be called. // For subscriptions, to get an offer token, call ProductDetails.subscriptionOfferDetails() // for a list of offers that are available to the user .setOfferToken(selectedOfferToken) .build() ) val billingFlowParams = BillingFlowParams.newBuilder() .setProductDetailsParamsList(productDetailsParamsList) .build() // Launch the billing flow val billingResult = billingClient.launchBillingFlow(activity, billingFlowParams)
Java
// An activity reference from which the billing flow will be launched. Activity activity = ...; ImmutableList<ProductDetailsParams> productDetailsParamsList = ImmutableList.of( ProductDetailsParams.newBuilder() // retrieve a value for "productDetails" by calling queryProductDetailsAsync() .setProductDetails(productDetails) // For one-time products, "setOfferToken" method shouldn't be called. // For subscriptions, to get an offer token, call // ProductDetails.subscriptionOfferDetails() for a list of offers // that are available to the user. .setOfferToken(selectedOfferToken) .build() ); BillingFlowParams billingFlowParams = BillingFlowParams.newBuilder() .setProductDetailsParamsList(productDetailsParamsList) .build(); // Launch the billing flow BillingResult billingResult = billingClient.launchBillingFlow(activity, billingFlowParams);
Metode launchBillingFlow()
menampilkan salah satu dari beberapa kode respons yang tercantum dalam
BillingClient.BillingResponseCode
. Pastikan Anda memeriksa hasil ini untuk
memastikan tidak ada error saat meluncurkan alur pembelian. BillingResponseCode
yang menyatakan OK
menunjukkan peluncuran yang berhasil.
Jika panggilan ke launchBillingFlow()
berhasil, sistem akan menampilkan layar pembelian
Google Play. Gambar 1 menunjukkan layar pembelian untuk langganan:
Google Play memanggil onPurchasesUpdated()
untuk mengirimkan hasil operasi
pembelian ke pemroses yang menerapkan antarmuka
PurchasesUpdatedListener
. Pemroses ditentukan menggunakan metode setListener()
saat Anda
melakukan inisialisasi klien.
Anda harus menerapkan onPurchasesUpdated()
untuk menangani kode respons yang mungkin diberikan. Contoh
berikut menunjukkan cara mengganti onPurchasesUpdated()
:
Kotlin
override fun onPurchasesUpdated(billingResult: BillingResult, purchases: List<Purchase>?) { if (billingResult.responseCode == BillingResponseCode.OK && purchases != null) { for (purchase in purchases) { handlePurchase(purchase) } } else if (billingResult.responseCode == BillingResponseCode.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() == BillingResponseCode.OK && purchases != null) { for (Purchase purchase : purchases) { handlePurchase(purchase); } } else if (billingResult.getResponseCode() == BillingResponseCode.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 keberhasilan melakukan pembelian di Google Play yang serupa dengan gambar 2.
Pembelian yang berhasil juga akan memunculkan token pembelian, yakni ID unik yang mewakili pengguna dan ID produk untuk produk dalam aplikasi yang mereka beli. Aplikasi Anda dapat menyimpan token pembelian secara lokal, meskipun sebaiknya Anda meneruskan token ke server backend yang aman, tempat Anda dapat memverifikasi pembelian dan melindungi dari penipuan. Proses ini dijelaskan lebih lanjut di bagian berikutnya.
Pengguna juga akan menerima melalui 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, juga untuk pembelian langganan awal dan perpanjangan otomatis berulang berikutnya. Anda dapat menggunakan ID Pesanan ini untuk mengelola pengembalian dana di Konsol Google Play.
Menunjukkan harga yang dipersonalisasi
Jika aplikasi Anda dapat didistribusikan kepada pengguna di Uni Eropa, gunakan
metode setIsOfferPersonalized()
untuk mengungkapkan kepada pengguna bahwa harga item
dipersonalisasi menggunakan pengambilan keputusan otomatis.
Anda harus membaca Seni. 6 (1) (ea) CRD dari Pedoman Hak Konsumen 2011/83/EU untuk menentukan apakah harga yang Anda tawarkan kepada pengguna dipersonalisasi.
setIsOfferPersonalized()
akan mengambil input boolean. Saat true
, UI Play akan
menyertakan pengungkapan. Saat false
, UI akan menghilangkan pengungkapan. Nilai default-nya
adalah false
.
Lihat Pusat Bantuan Konsumen untuk informasi selengkapnya.
Memproses pembelian
Setelah pengguna menyelesaikan pembelian, aplikasi Anda perlu memproses pembelian tersebut.
Biasanya, aplikasi Anda akan diberi notifikasi tentang pembelian melalui
PurchasesUpdatedListener
. Namun, terkadang aplikasi Anda akan diberi tahu terkait
pembelian dengan memanggil BillingClient.queryPurchasesAsync()
seperti yang dijelaskan dalam Mengambil pembelian.
Selain itu, jika Anda memiliki klien Notifikasi Developer Real Time di
backend aman, Anda dapat mendaftarkan pembelian baru dengan menerima
subscriptionNotification
atau oneTimeProductNotification
yang memberi tahu tentang
pembelian baru. Setelah menerima notifikasi ini, panggil Google Play
Developer API untuk mendapatkan status lengkap dan memperbarui status backend Anda sendiri.
Aplikasi Anda harus memproses pembelian dengan cara berikut:
- Memverifikasi pembelian.
- Memberikan konten kepada pengguna, dan mengonfirmasi pengiriman konten. Anda juga dapat menandai item sebagai telah dipakai sehingga pengguna dapat membeli item itu lagi.
Untuk memverifikasi pembelian, periksa terlebih dahulu apakah status pembelian
adalah PURCHASED
. Jika pembelian berstatus PENDING
, Anda harus memproses
pembelian seperti yang dijelaskan dalam Menangani transaksi yang tertunda. Untuk pembelian
yang diterima dari onPurchasesUpdated()
atau queryPurchasesAsync()
, Anda
harus memverifikasi pembelian lebih lanjut untuk memastikan keabsahan sebelum aplikasi
memberikan hak. Untuk mempelajari cara memverifikasi pembelian dengan benar, lihat Memverifikasi pembelian
sebelum memberikan hak.
Setelah Anda memverifikasi pembelian, aplikasi Anda siap memberikan hak kepada
pengguna tersebut. Akun pengguna yang terkait dengan pembelian dapat diidentifikasi dengan
ProductPurchase.obfuscatedExternalAccountId
yang ditampilkan oleh
Purchases.products:get
untuk pembelian produk dalam aplikasi dan
SubscriptionPurchase.obfuscatedExternalAccountId
yang ditampilkan oleh
Purchases.subscriptions:get
untuk langganan di sisi server, atau
obfuscatedAccountId
dari Purchase.getAccountIdentifiers()
di sisi klien, jika ditetapkan dengan setObfuscatedAccountId
saat
pembelian dilakukan.
Setelah memberikan hak, aplikasi Anda kemudian harus mengonfirmasi pembelian. Konfirmasi ini menyampaikan kepada Google Play bahwa Anda telah memberikan hak atas pembelian tersebut.
Proses untuk memberikan hak dan mengonfirmasi pembelian bergantung pada apakah pembelian tersebut untuk produk yang habis pakai, tidak habis pakai, atau langganan.
Produk Habis Pakai
Untuk produk habis pakai, jika aplikasi Anda memiliki backend aman, sebaiknya gunakan
Purchases.products:consume
untuk memakai pembelian dengan andal. Pastikan
pembelian belum dipakai dengan memeriksa consumptionState
dari hasil panggilan
Purchases.products:get
. Jika aplikasi Anda hanya untuk klien
tanpa backend, gunakan consumeAsync()
dari
Library Layanan Penagihan Google Play. Kedua metode tersebut memenuhi persyaratan
konfirmasi dan menunjukkan bahwa aplikasi Anda telah memberikan hak kepada pengguna.
Metode ini juga memungkinkan aplikasi Anda membuat produk sekali beli yang sesuai dengan
token pembelian input yang bisa dibeli kembali. Anda juga harus
meneruskan objek yang menerapkan antarmuka ConsumeResponseListener
dengan consumeAsync()
. Objek ini menangani hasil operasi pemakaian. Anda dapat
mengganti metode onConsumeResponse()
, yang dipanggil oleh
Google Play Billing Library saat operasi selesai.
Contoh berikut menggambarkan pemakaian produk dengan Library Layanan Penagihan Google Play menggunakan token pembelian yang terkait:
Kotlin
suspend fun handlePurchase(purchase: Purchase) { // Purchase retrieved from BillingClient#queryPurchasesAsync or your PurchasesUpdatedListener. val purchase : Purchase = ...; // Verify the purchase. // Ensure entitlement was not already granted for this purchaseToken. // Grant entitlement to the user. val consumeParams = ConsumeParams.newBuilder() .setPurchaseToken(purchase.getPurchaseToken()) .build() val consumeResult = withContext(Dispatchers.IO) { client.consumePurchase(consumeParams) } }
Java
void handlePurchase(Purchase purchase) { // Purchase retrieved from BillingClient#queryPurchasesAsync or your PurchasesUpdatedListener. Purchase purchase = ...; // Verify the purchase. // Ensure entitlement was not already granted for this purchaseToken. // Grant entitlement to the user. ConsumeParams consumeParams = ConsumeParams.newBuilder() .setPurchaseToken(purchase.getPurchaseToken()) .build(); ConsumeResponseListener listener = new ConsumeResponseListener() { @Override public void onConsumeResponse(BillingResult billingResult, String purchaseToken) { if (billingResult.getResponseCode() == BillingResponseCode.OK) { // Handle the success of the consume operation. } } }; billingClient.consumeAsync(consumeParams, listener); }
Produk Tidak Habis Pakai
Untuk mengonfirmasi pembelian produk tidak habis pakai, jika aplikasi Anda memiliki backend
aman, sebaiknya gunakan Purchases.products:acknowledge
untuk mengonfirmasi
pembelian dengan andal. Pastikan pembelian belum pernah dikonfirmasi dengan
memeriksa acknowledgementState
dari hasil panggilan
Purchases.products:get
.
Jika aplikasi Anda hanya untuk klien, gunakan BillingClient.acknowledgePurchase()
dari Library Layanan Penagihan Google Play di aplikasi Anda. Sebelum mengonfirmasi
pembelian, aplikasi Anda harus memeriksa apakah pembelian itu sudah dikonfirmasi dengan menggunakan
metode isAcknowledged()
di Library Layanan Penagihan Google Play.
Contoh berikut menunjukkan cara mengonfirmasi pembelian menggunakan Library Layanan Penagihan Google Play:
Kotlin
val client: BillingClient = ... val acknowledgePurchaseResponseListener: AcknowledgePurchaseResponseListener = ... suspend fun handlePurchase() { if (purchase.purchaseState === PurchaseState.PURCHASED) { 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) { if (!purchase.isAcknowledged()) { AcknowledgePurchaseParams acknowledgePurchaseParams = AcknowledgePurchaseParams.newBuilder() .setPurchaseToken(purchase.getPurchaseToken()) .build(); client.acknowledgePurchase(acknowledgePurchaseParams, acknowledgePurchaseResponseListener); } } }
Langganan
Langganan ditangani dengan cara yang sama seperti item yang tidak habis pakai. Jika memungkinkan,
gunakan Purchases.subscriptions.acknowledge
dari
Google Play Developer API untuk mengonfirmasi pembelian dari backend aman Anda
dengan andal. Pastikan bahwa pembelian belum pernah dikonfirmasi
sebelumnya dengan memeriksa acknowledgementState
di resource pembelian dari
Purchases.subscriptions:get
. Jika tidak, Anda dapat mengonfirmasi
langganan menggunakan BillingClient.acknowledgePurchase()
dari Library Layanan Penagihan Google Play setelah memeriksa isAcknowledged()
. Semua
pembelian langganan awal harus dikonfirmasi. Perpanjangan langganan
tidak perlu dikonfirmasi. Untuk informasi selengkapnya terkait kapan
langganan perlu dikonfirmasi, lihat topik Menjual langganan.
Mengambil pembelian
Memproses update pembelian menggunakan PurchasesUpdatedListener
tidak
cukup untuk memastikan aplikasi Anda memproses semua pembelian. Ada kemungkinan bahwa
aplikasi Anda tidak mengetahui semua pembelian yang dilakukan pengguna. Berikut ini beberapa
skenario saat aplikasi Anda tidak dapat melacak atau tidak mengetahui pembelian:
- Masalah Jaringan selama pembelian: Pengguna melakukan pembelian yang berhasil
dan menerima konfirmasi dari Google, tetapi perangkat mereka kehilangan
konektivitas jaringan sebelum perangkat mereka menerima notifikasi
pembelian melalui
PurchasesUpdatedListener
. - Beberapa perangkat: Pengguna membeli item di satu perangkat, lalu mengharapkan untuk melihat item tersebut saat beralih perangkat.
- Menangani pembelian yang dilakukan di luar aplikasi: Beberapa pembelian, seperti penukaran promosi, dapat dilakukan di luar aplikasi Anda.
Untuk menangani situasi ini, pastikan aplikasi Anda memanggil
BillingClient.queryPurchasesAsync()
dalam metode onResume()
untuk
memastikan semua pembelian berhasil diproses seperti yang dijelaskan dalam memproses
pembelian.
Contoh berikut menunjukkan cara mengambil pembelian langganan pengguna.
Perlu diperhatikan bahwa queryPurchasesAsync()
hanya menampilkan langganan aktif dan
pembelian satu kali yang tidak digunakan.
Kotlin
val params = QueryPurchasesParams.newBuilder() .setProductType(ProductType.SUBS) // uses queryPurchasesAsync Kotlin extension function val purchasesResult = billingClient.queryPurchasesAsync(params.build()) // check purchasesResult.billingResult // process returned purchasesResult.purchasesList, e.g. display the plans user owns
Java
billingClient.queryPurchasesAsync( QueryPurchasesParams.newBuilder() .setProductType(ProductType.SUBS) .build(), new PurchasesResponseListener() { public void onQueryPurchasesResponse(BillingResult billingResult, List<Purchase> purchases) { // check billingResult // process returned purchase list, e.g. display the plans user owns } } );
Menangani pembelian yang dilakukan di luar aplikasi
Beberapa pembelian dapat terjadi di luar aplikasi Anda, seperti penukaran promosi atau pengingat pengabaian keranjang untuk pembelian dalam aplikasi (IAP) Google Play Game. Saat pengguna melakukan pembelian di luar aplikasi, mereka berharap aplikasi Anda menampilkan pesan dalam aplikasi, atau menggunakan mekanisme notifikasi tertentu untuk memberi tahu pengguna bahwa aplikasi telah menerima dan memproses pembelian dengan benar. Mekanisme yang dapat diterima antara lain:
- Menampilkan pop-up dalam aplikasi.
- Mengirim pesan ke kotak pesan dalam aplikasi, dan menyatakan dengan jelas bahwa ada pesan baru di kotak pesan dalam aplikasi.
- Menggunakan pesan notifikasi OS.
Perlu diingat bahwa aplikasi Anda mungkin berada dalam keadaan apa pun saat aplikasi mengenali pembelian. Aplikasi Anda bahkan mungkin belum diinstal saat pembelian dilakukan. Pengguna berharap menerima pembelian mereka saat melanjutkan aplikasi, terlepas dari status aplikasi tersebut.
Anda harus mendeteksi pembelian terlepas dari status aplikasi saat pembelian dilakukan. Namun, ada beberapa pengecualian yang mungkin membuat kami tidak dapat segera memberi tahu pengguna bahwa item telah diterima. Contoh:
- Selama bagian tindakan dalam game, di mana menampilkan pesan dapat mengalihkan perhatian pengguna. Dalam hal ini, Anda harus memberi tahu pengguna setelah bagian tindakan itu selesai.
- Selama cutscene, saat menampilkan pesan dapat mengganggu perhatian pengguna. Dalam hal ini, Anda harus memberi tahu pengguna setelah cutscene berakhir.
- Selama tutorial awal dan bagian penyiapan pengguna dalam game. Sebaiknya beri tahu pengguna baru tentang reward segera setelah mereka membuka game atau selama penyiapan pengguna awal. Namun, Anda masih dapat menunggu hingga urutan game utama tersedia untuk memberi tahu pengguna.
Selalu perhatikan pengguna saat memutuskan kapan dan bagaimana cara memberi tahu pengguna tentang pembelian yang dilakukan di luar aplikasi. Setiap kali pengguna tidak langsung menerima notifikasi, mereka mungkin akan bingung, dan dapat berhenti menggunakan aplikasi Anda, menghubungi dukungan pengguna, atau mengeluhkannya di media sosial.
Pengingat Pengabaian Keranjang di beranda Google Play Game (diaktifkan secara default)
Untuk developer Game yang melakukan monetisasi melalui IAP, satu cara untuk menjual unit pengelolaan inventaris (SKU) yang aktif di Konsol Google Play di luar aplikasi Anda adalah fitur Pengingat Pengabaian Keranjang, yang mendorong pengguna untuk menyelesaikan pembelian yang sebelumnya ditinggalkan saat menjelajahi Google Play Store. Pembelian ini terjadi di luar aplikasi Anda, dari beranda Google Play Game di Google Play Store.
Fitur ini diaktifkan secara default untuk membantu pengguna melanjutkan dari tempat terakhir mereka berhenti dan membantu developer memaksimalkan penjualan. Namun, Anda dapat memilih untuk tidak menggunakan fitur ini dengan mengirimkan formulir untuk tidak menggunakan fitur Pengingat Pengabaian Keranjang. Untuk praktik terbaik dalam mengelola SKU dalam Konsol Google Play, lihat Membuat produk dalam aplikasi.
Gambar berikut menunjukkan Pengingat Pengabaian Keranjang yang muncul di Google Play Store:
Menangani transaksi yang tertunda
Google Play mendukung transaksi yang tertunda, atau transaksi yang memerlukan satu atau beberapa langkah tambahan antara saat pengguna memulai pembelian dan saat metode pembayaran untuk pembelian tersebut diproses. Aplikasi Anda tidak boleh memberikan hak atas jenis pembelian ini sampai Google memberi tahu Anda bahwa metode pembayaran pengguna berhasil ditagih.
Misalnya, pengguna dapat memulai transaksi dengan memilih toko fisik tempat mereka akan membayar nanti dengan uang tunai. Pengguna menerima kode melalui notifikasi dan email. Saat pengguna tiba di toko fisik, mereka dapat menukarkan kode dengan kasir dan membayar dengan uang tunai. Kemudian, Google memberi tahu Anda dan pengguna bahwa pembayaran telah diterima. Kemudian, aplikasi Anda dapat memberikan hak kepada pengguna.
Panggil enablePendingPurchases()
sebagai bagian dari inisialisasi
BillingClient
untuk mengaktifkan transaksi yang tertunda untuk aplikasi Anda. Aplikasi Anda harus
mengaktifkan dan mendukung transaksi yang tertunda untuk produk sekali beli. Sebelum
menambahkan dukungan, pastikan Anda memahami siklus proses pembelian untuk transaksi
yang tertunda.
Jika aplikasi Anda menerima pembelian baru, baik melalui
PurchasesUpdatedListener
atau sebagai hasil dari panggilan
queryPurchasesAsync()
, gunakan metode getPurchaseState()
untuk
menentukan apakah status pembelian tersebut adalah PURCHASED
atau PENDING
. Anda harus
memberikan hak hanya jika statusnya adalah PURCHASED
.
Jika aplikasi Anda berjalan saat pengguna menyelesaikan pembelian,
PurchasesUpdatedListener
akan dipanggil lagi, dan PurchaseState
sekarang menjadi
PURCHASED
. Pada tahap ini, aplikasi Anda dapat memproses pembelian menggunakan metode
standar untuk memproses pembelian. Aplikasi Anda juga harus memanggil
queryPurchasesAsync()
di metode onResume()
aplikasi untuk menangani pembelian
yang telah dialihkan ke status PURCHASED
saat aplikasi Anda tidak berjalan.
Saat pembelian bertransisi dari PENDING
ke
PURCHASED
, klien Notifikasi developer real time Anda akan menerima
notifikasi ONE_TIME_PRODUCT_PURCHASED
atau
SUBSCRIPTION_PURCHASED
. Jika pembelian dibatalkan, Anda
akan menerima notifikasi ONE_TIME_PRODUCT_CANCELED
atau
SUBSCRIPTION_PENDING_PURCHASE_CANCELED
. Hal ini dapat terjadi jika
pelanggan tidak menyelesaikan pembayaran dalam jangka waktu yang diperlukan. Perhatikan bahwa Anda
selalu dapat menggunakan Google Play Developer API untuk memeriksa status
pembelian saat ini.
Menangani pembelian multikuantitas
Dengan tersedianya dukungan untuk Library Layanan Penagihan Google Play versi 4.0 dan yang lebih baru, Google Play memungkinkan pelanggan membeli lebih dari satu produk dalam aplikasi yang sama dalam satu transaksi dengan menentukan kuantitas dari keranjang pembelian. Aplikasi Anda diharapkan dapat menangani pembelian multikuantitas dan memberikan hak berdasarkan jumlah pembelian yang ditentukan.
Untuk memenuhi pembelian multikuantitas, logika penyediaan aplikasi Anda harus memeriksa
jumlah item. Anda dapat mengakses kolom quantity
dari salah satu
API berikut:
getQuantity()
dari Library Layanan Penagihan Google Play.Purchases.products.quantity
dari Google Play Developer API.
Setelah menambahkan logika untuk menangani pembelian multikuantitas, Anda harus mengaktifkan fitur multikuantitas untuk produk yang sesuai di halaman pengelolaan produk dalam aplikasi di Konsol Google Play.
Membuat Kueri Konfigurasi Penagihan Pengguna
getBillingConfigAsync()
menunjukkan negara yang dipilih pengguna untuk
Google Play.
Anda dapat membuat kueri konfigurasi penagihan pengguna setelah
membuat BillingClient
. Cuplikan kode berikut menjelaskan
cara melakukan panggilan ke getBillingConfigAsync()
. Tangani respons dengan
mengimplementasikan BillingConfigResponseListener
. Pemroses ini menerima
update untuk semua kueri konfigurasi penagihan yang dimulai dari aplikasi Anda.
Jika BillingResult
yang ditampilkan tidak berisi error, Anda dapat memeriksa
kolom countryCode
di objek BillingConfig
untuk mendapatkan negara pilihan
pengguna di Play.
Kotlin
// Use the default GetBillingConfigParams.
val getBillingConfigParams = GetBillingConfigParams.newBuilder().build()
billingClient.getBillingConfigAsync(getBillingConfigParams,
object : BillingConfigResponseListener {
override fun onBillingConfigResponse(
billingResult: BillingResult,
billingConfig: BillingConfig?
) {
if (billingResult.responseCode == BillingResponseCode.OK
&& billingConfig != null) {
val countryCode = billingConfig.countryCode
...
} else {
// TODO: Handle errors
}
}
})
Java
// Use the default GetBillingConfigParams.
GetBillingConfigParams getBillingConfigParams = GetBillingConfigParams.newBuilder().build();
billingClient.getBillingConfigAsync(getBillingConfigParams,
new BillingConfigResponseListener() {
public void onBillingConfigResponse(
BillingResult billingResult, BillingConfig billingConfig) {
if (billingResult.getResponseCode() == BillingResponseCode.OK
&& billingConfig != null) {
String countryCode = billingConfig.getCountryCode();
...
} else {
// TODO: Handle errors
}
}
});