Semua artikel
Deep diveWaktu baca 8 menit

Ketika pembelian Google Play direfund atau di-chargeback, Voided Purchases API adalah cara Anda mengetahuinya

Google Play membatalkan sebuah pembelian secara diam-diam ketika pembelian itu direfund atau di-chargeback. Voided Purchases API adalah daftar pesanan tersebut, sehingga Anda bisa mencabut akses. Berikut setiap field, jendela 30 hari, opsi revoke yang menyembunyikan pesanan, dan berapa biayanya.

Sebuah smartphone di samping buku besar kertas, gembok kuningan yang terkunci, dan sebuah koin yang meluncur menjauh, menggambarkan Google Play Voided Purchases API yang melaporkan pesanan yang direfund dan di-chargeback

Poin utama

  • Voided Purchases API, yaitu metode purchases.voidedpurchases.list, mengembalikan pesanan yang dibatalkan, direfund, atau di-chargeback oleh Google Play, sehingga Anda bisa membangun sistem pencabutan yang memutus akses ke hal yang tidak lagi dimiliki pelanggan.
  • Hanya pesanan yang direvoke yang muncul. Refund dari developer yang dilakukan tanpa opsi revoke tidak terlihat oleh API ini, jadi jika Anda ingin menarik akses, Anda harus melakukan refund dengan revoke diaktifkan.
  • Jendelanya adalah 30 hari. startTime tidak boleh lebih lama dari 30 hari yang lalu, sehingga server yang mati lebih lama dari sebulan kehilangan pesanan yang dibatalkan itu selamanya. Lakukan polling sesuai jadwal.
  • voidedSource memberi tahu Anda siapa yang membatalkan pesanan: 0 adalah pengguna, 1 adalah developer, 2 adalah Google. voidedReason memberi tahu Anda alasannya, dari 0 Other hingga 7 Chargeback dan 8 Unacknowledged_purchase.
  • Real-time developer notifications mengirimkan VoidedPurchaseNotification pada saat sebuah pembelian dibatalkan, tetapi perlakukan itu sebagai sinyal. Panggil Voided Purchases API untuk mendapatkan daftar yang otoritatif sebelum Anda mencabut akses.
  • Identifikasi perpanjangan langganan berdasarkan orderId, bukan purchaseToken. Satu purchaseToken mencakup setiap perpanjangan sebuah langganan, jadi token itu sendiri tidak bisa membedakan dua perpanjangan.
  • Kuotanya adalah 6,000 kueri per hari dan 30 kueri dalam setiap jendela 30 detik, jadi telusuri hasil per halaman dengan continuation token dan kueri berdasarkan jendela waktu, jangan pernah satu panggilan per pesanan.

Sebuah refund di Google Play tidak mengetuk pintu Anda. Uangnya berpindah, pelanggan tetap membuka aplikasi, dan kecuali Anda memeriksanya, tidak ada yang berubah di sisi Anda. Voided Purchases API adalah tempat Anda memeriksanya. API ini memberi Anda daftar pesanan yang dibatalkan, direfund, atau di-chargeback, sehingga Anda bisa mencabut akses ke hal yang tidak lagi dibayar pelanggan. Arahkan sebuah scheduled job ke sana, baca daftarnya, putus entitlement-nya. Itulah keseluruhan alurnya.

Ada satu jebakan yang menyandung sebagian besar tim, dan itu bukan di dalam kode. Hanya pesanan yang direvoke yang muncul di sini. Jika Anda merefund sebuah pembelian di Play Console tanpa mencentang opsi revoke, pesanan itu tidak akan pernah sampai ke API ini, dan job Anda berjalan mulus sementara pelanggan yang direfund tetap menyimpan semua yang Anda jual kepadanya. Artikel ini membahas API ini field demi field, angka-angka yang membatasinya, dan di mana uang bocor ketika Anda melewatkannya.

Apa yang sebenarnya dikembalikan Voided Purchases API

API ini menjawab satu pertanyaan: pesanan mana untuk aplikasi ini yang baru-baru ini dibatalkan. Sebuah pembatalan (void) mencakup tiga hasil yang semuanya berakhir dengan pelanggan mendapatkan uangnya kembali. Sebuah cancellation, sebuah refund, atau sebuah chargeback. Ini berlaku untuk produk dalam aplikasi sekali beli dan untuk langganan, dan Anda memilih cakupannya dengan satu parameter. Setel type ke 0 dan Anda hanya mendapatkan pembelian produk dalam aplikasi yang dibatalkan, yang merupakan default. Setel ke 1 dan Anda mendapatkan pembelian dalam aplikasi yang dibatalkan dan pembelian langganan yang dibatalkan sekaligus.

Setiap entri dalam daftar adalah sebuah objek voided purchase. Field-nya sedikit dan setiap field penting.

Field pada sebuah voided purchase

FieldApa isinya
orderIdOrder id yang secara unik mengidentifikasi sebuah pembelian sekali beli, sebuah pembelian langganan, atau satu perpanjangan langganan tunggal. Ini adalah kunci join Anda
purchaseTokenToken yang mengidentifikasi sebuah pembelian sekali beli atau sebuah langganan. Token ini tidak membedakan perpanjangan, jadi gunakan orderId untuk itu
purchaseTimeMillisKapan pembelian dilakukan, dalam milidetik sejak epoch
voidedTimeMillisKapan pembelian dibatalkan, direfund, atau di-chargeback, dalam milidetik sejak epoch
voidedSourceSiapa yang memulai pembatalan: 0 pengguna, 1 developer, 2 Google
voidedReasonMengapa pembelian dibatalkan, sebuah bilangan bulat dari 0 hingga 8
voidedQuantityJumlah yang dibatalkan dari partial refund berbasis kuantitas, dikembalikan hanya ketika includeQuantityBasedPartialRefund bernilai true

Baca voidedReason sebelum Anda bertindak

voidedReason adalah field yang mengubah daftar mentah menjadi sebuah keputusan. Sebuah refund karena penyesalan pembeli dan sebuah chargeback bank sama-sama masuk ke daftar yang sama, tetapi keduanya bukan peristiwa yang sama, dan harga baru di bulan Agustus membuat salah satunya mahal. Berikut himpunan lengkapnya.

voidedReasonLabelApa artinya bagi Anda
0OtherTidak ada kategori yang ditetapkan. Cabut akses dan lanjutkan
1RemorsePembeli berubah pikiran. Sebuah refund biasa
2Not_receivedPelanggan mengatakan mereka tidak pernah menerima produk. Perlu memeriksa pengiriman Anda
3DefectiveProduk tidak berfungsi. Sebuah sinyal kualitas, catat itu
4Accidental_purchaseSebuah pembelian tak disengaja, sering kali pada perangkat yang dipakai bersama
5FraudGoogle menandai transaksi sebagai penipuan
6Friendly_fraudSebuah chargeback di mana pemegang kartu yang sah menyanggah tagihan yang mereka buat sendiri
7ChargebackBank pelanggan membalikkan pembayaran. Final di pihak bank, dan kini ditagihkan kepada Anda
8Unacknowledged_purchaseGoogle secara otomatis merefund sebuah pembelian yang tidak pernah diakui (acknowledge) oleh aplikasi Anda

Jendela 30 hari adalah jebakan yang mengosongkan daftar Anda

Voided Purchases API hanya bisa menampilkan pembelian yang dibatalkan dari 30 hari terakhir. Parameter startTime secara default bernilai waktu saat ini dikurangi 30 hari, dan tidak bisa disetel lebih lama dari itu. endTime secara default bernilai sekarang. Jadi endpoint ini adalah jendela satu bulan yang bergulir, bukan sebuah arsip.

Konsekuensinya gamblang. Jika polling job Anda rusak dan tidak ada yang menyadarinya selama lima minggu, pembatalan dari minggu pertama sudah kedaluwarsa dari API. Tidak ada panggilan yang bisa membawanya kembali. Anda tidak akan mencabut pesanan itu, dan Anda bahkan tidak akan tahu bahwa pesanan itu pernah ada kecuali Anda menangkapnya dengan cara lain. API ini adalah jaring pengaman dengan lubang seukuran gangguan terburuk Anda.

Opsi revoke menentukan apakah sebuah pesanan bahkan muncul

Ini adalah alasan paling umum sebuah tim melaporkan API ini rusak. Hanya pesanan yang direvoke yang dikembalikan. Refund yang dimulai pengguna, pembatalan, chargeback, dan refund yang dimulai Google selalu direvoke, jadi selalu muncul. Refund yang dimulai developer berbeda. Ketika Anda merefund sebuah pesanan sendiri, melalui Play Console atau Orders API, Anda memilih apakah juga akan merevoke-nya. Refund tanpa revoke, dan pesanan itu selesai dengan pelanggan tetapi tidak pernah muncul di Voided Purchases API.

Aturan yang mengikutinya sederhana. Jika niat Anda adalah menarik akses, lakukan refund dengan opsi revoke aktif. Jika tidak, Anda sudah mengembalikan uang dan membiarkan pintu terbuka, dan revocation job Anda, sebaik apa pun ditulis, tidak punya apa pun untuk ditindaklanjuti.

Cara melakukan polling tanpa melampaui kuota

Endpoint ini memiliki rate limit, dan batasnya cukup rendah sehingga loop yang naif akan menabraknya. Anda mendapatkan 6,000 kueri per hari, dihitung dalam Pacific Time, dan tidak lebih dari 30 kueri dalam setiap periode 30 detik. Anggaran itu memadai untuk polling berbasis jendela dan tidak ramah bagi desain satu-permintaan-per-pesanan.

Jendela kueri dan continuation token

maxResults secara default bernilai 1,000, yang juga merupakan batas atasnya. Ketika sebuah jendela memuat lebih dari satu halaman pembatalan, respons membawa sebuah objek tokenPagination dengan nextPageToken. Kirimkan kembali token itu pada panggilan berikutnya untuk menelusuri halaman-halaman. Setel startTime dan endTime untuk membatasi jendela yang Anda pedulikan, telusuri halaman hingga token habis, lalu majukan jendelanya. Pola itu menjaga Anda tetap di dalam batas burst 30 detik dan batas harian sekaligus.

Real-time developer notifications menutup celahnya

Polling setiap hari masih menyisakan hingga satu hari kebutaan, dan jendela 30 hari menghukum celah yang panjang. Real-time developer notifications menghilangkan jeda itu. Google mempublikasikan sebuah VoidedPurchaseNotification ke sebuah topik Cloud Pub/Sub milik Anda pada saat sebuah pembelian dibatalkan, dan backend Anda mengonsumsinya dalam hitungan detik. Pesannya kecil.

RTDN fieldApa isinya
purchaseTokenToken dari pembelian aslinya
orderIdOrder id untuk transaksi yang dibatalkan, satu yang baru untuk setiap perpanjangan langganan
productType1 untuk sebuah langganan, 2 untuk sebuah pembelian sekali beli
refundType1 untuk refund penuh, 2 untuk partial refund berbasis kuantitas
Sebuah tangan menutup gembok kuningan di atas setumpuk struk di samping sebuah smartphone, menggambarkan pencabutan akses setelah sebuah pembelian Google Play dibatalkan

Berapa biayanya bagi Anda dalam bentuk uang

API ini adalah pipa saluran, tetapi alasan untuk memasangnya adalah tagihan. Setiap pembatalan dalam daftar itu memetakan ke sebuah angka nyata, dan dua di antaranya menjadi lebih mahal.

Tagihan chargeback jatuh ke Anda mulai 3 Agustus 2026

Mulai 3 Agustus 2026, Google mengalihkan biaya sebuah chargeback ke developer. Anda kehilangan harga pembelian dan Anda membayar biaya chargeback bank di atasnya. voidedReason bernilai 7 tidak lagi sekadar penjualan yang hilang, itu adalah sebuah item baris dengan biaya yang menyertainya. Anda tidak bisa membalikkan sebuah chargeback, itu final di pihak bank, tetapi Anda bisa menghentikan pendarahan setelahnya. Menangkap pembatalan dengan cepat memungkinkan Anda mencabut entitlement dan, untuk apa pun yang masih Anda kirimkan, berhenti membelanjakan untuk pelanggan yang direfund lalu dibalikkan.

Anda terus membayar untuk melayani pelanggan yang sudah direfund

Harga pembelian lenyap begitu sebuah pembatalan muncul. Yang masih Anda kendalikan adalah biaya untuk terus memberikan layanan. Setiap jam sebuah entitlement yang direfund tetap aktif, Anda terus membayar untuk hal-hal yang tidak lagi didanai pelanggan: komputasi, panggilan API model, penyimpanan, dan pembayaran kreator atau mitra apa pun yang terkait dengan penggunaan mereka. Sebuah sistem pencabutan yang digerakkan oleh API ini adalah cara Anda mematikan meteran itu. Lewati itu, dan Anda mendanai produk untuk orang-orang yang sudah dipulihkan oleh toko.

Friendly fraud adalah pola yang layak ditelusuri trennya

voidedReason bernilai 5 atau 6 bukan kejadian sekali saja. Fraud dan friendly fraud mengelompok berdasarkan akun, berdasarkan perangkat, dan terkadang berdasarkan promosi. API memberi Anda voidedSource dan voidedReason pada setiap pembatalan, yang cukup untuk menelusuri tren penyalahgunaan berdasarkan akun alih-alih memperlakukan setiap pembalikan sebagai biaya yang terisolasi. Seorang pelanggan yang melakukan chargeback dua kali memberi tahu Anda sesuatu yang tidak disampaikan oleh refund pertama.

Memasangnya dengan cara RefundHalt

Modelnya kecil begitu Anda memegang semua kepingannya. Dengarkan VoidedPurchaseNotification secara real time agar tidak ada yang menunggu satu hari penuh. Panggil Voided Purchases API sebagai sumber kebenaran, dengan kunci orderId agar perpanjangan langganan tidak pernah tertukar. Baca voidedSource dan voidedReason agar sebuah chargeback ditangani berbeda dari sebuah refund penyesalan. Lakukan polling dengan jadwal yang cukup rapat sehingga jendela 30 hari tidak pernah menggigit, dan refund dengan opsi revoke aktif kapan pun niat Anda adalah memutus akses.

Ini adalah bagian yang dijalankan RefundHalt untuk Anda. RefundHalt mengonsumsi notifikasi real-time, merekonsiliasi setiap pembatalan terhadap API, mencabut pesanan yang tepat alih-alih seluruh produk, dan memisahkan sebuah chargeback bank dari sebuah refund biasa sehingga yang mahal ditandai, bukan terkubur. Anda mendapatkan akses yang dicabut dalam hitungan detik dan sebuah catatan tentang siapa yang membatalkan apa dan mengapa, tanpa perlu membangun sendiri sebuah pipeline Pub/Sub dan sebuah polling job.

Pertanyaan yang sering diajukan

Mengapa pesanan saya yang sudah direfund tidak muncul di Voided Purchases API?
Karena hanya pesanan yang direvoke yang dikembalikan. Refund pengguna, pembatalan, chargeback, dan refund yang dimulai Google selalu direvoke dan selalu muncul. Refund yang dimulai developer hanya muncul jika Anda juga memilih opsi revoke. Jika Anda merefund sebuah pesanan tanpa merevoke-nya, pesanan itu selesai tetapi tidak terlihat oleh API ini, jadi lakukan refund dengan revoke aktif kapan pun Anda berniat menarik akses.
Seberapa jauh ke belakang Voided Purchases API menjangkau?
Tiga puluh hari. Parameter startTime secara default bernilai waktu saat ini dikurangi 30 hari dan tidak bisa disetel lebih lama dari itu, jadi endpoint ini adalah jendela satu bulan yang bergulir alih-alih sebuah arsip. Sebuah pesanan yang dibatalkan yang melewati 30 hari lenyap dari API tanpa cara untuk mengambilnya kembali, itulah sebabnya Anda melakukan polling sesuai jadwal dan mendukungnya dengan notifikasi real-time.
Haruskah saya menggunakan real-time developer notifications atau Voided Purchases API untuk mencabut akses?
Gunakan keduanya. VoidedPurchaseNotification tiba dalam hitungan detik dan menyuruh Anda melihat, tetapi panduan Google sendiri adalah memperlakukannya sebagai sinyal, bukan sumber kebenaran. Panggil Voided Purchases API untuk mengonfirmasi keadaan saat ini, lalu cabut akses. Notifikasi menghilangkan jeda, dan API memberi Anda voidedSource dan voidedReason otoritatif untuk ditindaklanjuti.
Bagaimana cara membedakan sebuah chargeback dari sebuah refund biasa di API?
Baca field voidedReason. Nilai 7 adalah sebuah chargeback, yang berarti bank pelanggan membalikkan pembayaran, dan 6 adalah friendly fraud. Nilai 1 adalah sebuah refund penyesalan. Ini penting karena mulai 3 Agustus 2026 Google membebankan harga pembelian chargeback dan biaya bank kepada developer, sehingga voidedReason bernilai 7 membuat Anda merugi lebih besar daripada sebuah refund biasa.
Apakah Voided Purchases API mencakup langganan?
Ya. Setel parameter type ke 1 untuk mendapatkan baik pembelian dalam aplikasi yang dibatalkan maupun pembelian langganan yang dibatalkan. Default-nya, type 0, hanya mengembalikan pembelian produk dalam aplikasi. Untuk langganan, identifikasi periode yang tepat yang dibatalkan berdasarkan orderId, karena satu purchaseToken mencakup setiap perpanjangan dan sebuah orderId baru dihasilkan untuk setiap transaksi perpanjangan.

Sumber dan bacaan lanjutan

RefundHalt

Autopilot refund untuk App Store dan Google Play

Baca selanjutnya

Permintaan refund berikutnya sudah menuju kepada Anda.

Siapkan RefundHalt dalam waktu yang dibutuhkan untuk membaca satu lagi email dukungan tentang refund yang tidak sempat Anda sengketakan.