Semua artikel
Ulasan mendalamWaktu baca 8 menit

Verifikasi notifikasi server App Store sebelum Anda menindaklanjuti refund, karena siapa pun dapat mengirim ke URL webhook Anda

Notifikasi refund hanyalah permintaan HTTPS sampai Anda memeriksa tanda tangannya. Berikut cara memverifikasi notifikasi server App Store dan pesan RTDN Google Play, apa yang ditandatangani oleh setiap store, dan berapa kerugian Anda akibat refund palsu atau refund asli yang keliru ditolak.

Stempel segel lilin dari kuningan dan amplop tersegel di samping laptop di atas meja dalam cahaya lampu yang hangat, gambaran mengapa Anda perlu memverifikasi notifikasi server App Store sebelum memercayainya

Poin utama

  • Apple mengirim setiap notifikasi server App Store versi 2 sebagai signedPayload, yaitu JSON Web Signature dengan tiga bagian Base64URL: header, payload, dan tanda tangan.
  • Header JWS pada notifikasi server App Store membawa rantai sertifikat x5c yang terdiri atas tiga sertifikat: sertifikat leaf penanda tangan, sertifikat perantara Apple dengan ekstensi Apple Worldwide Developer Relations 1.2.840.113635.100.6.2.1, dan sertifikat root Apple.
  • App Store Server Library milik Apple memverifikasi notifikasi dengan SignedDataVerifier yang memeriksa rantai sertifikat, bundle ID, environment, dan di produksi juga appAppleId, serta dapat memeriksa pencabutan sertifikat secara online.
  • Real-time developer notifications Google Play tidak ditandatangani oleh Google Play. Pada push subscription, Pub/Sub dapat menyertakan token OpenID Connect bertanda tangan di header Authorization, lalu server Anda memeriksa tanda tangan, audience, dan klaim email token tersebut.
  • Google menyatakan bahwa RTDN hanya memberi tahu Anda bahwa status pembelian telah berubah, sehingga respons yang aman terhadap notifikasi refund apa pun adalah mengonfirmasinya dengan Google Play Developer API sebelum mencabut akses.
  • Apple mengirim notifikasi server App Store dari subnet 17.0.0.0/8, tetapi daftar izin IP hanya membatasi siapa yang dapat menjangkau endpoint Anda. Tanda tanganlah yang membuktikan bahwa pesan berasal dari Apple.
  • Verifier yang keliru menolak pesan asli sama mahalnya dengan verifier yang menerima pesan palsu, karena CONSUMPTION_REQUEST yang Anda abaikan memiliki batas waktu respons 12 jam dan peninjauan chargeback Google Play memiliki batas 24 jam.

Siapa pun yang mengetahui URL webhook Anda dapat mengirimkan refund ke sana. Itulah fakta yang tidak nyaman di balik setiap notifikasi server App Store dan setiap Real-time developer notification Google Play: sampai Anda memverifikasinya, pesan itu hanyalah HTTPS POST yang berisi JSON. Jika server Anda mencabut langganan, menarik kembali kredit, atau memblokir akun karena sebuah permintaan menyebut REFUND, Anda telah menyerahkan kewenangan itu kepada siapa saja yang bisa menulis perintah curl.

Kedua store menyediakan cara untuk memeriksanya. Apple menandatangani notifikasi itu sendiri, sehingga Anda dapat memverifikasi notifikasi server App Store hanya dengan sertifikat root Apple. Google Play menempuh jalan yang berbeda. Pesannya tidak ditandatangani, tetapi pengiriman Pub/Sub dapat ditandatangani, dan Google tetap meminta Anda mengonfirmasi setiap perubahan melalui API-nya. Berikut apa yang dibuktikan oleh masing-masing, dan berapa kerugiannya jika Anda keliru ke salah satu arah.

Apa yang sebenarnya ditandatangani oleh setiap store

PertanyaanApp Store Server Notifications V2Google Play RTDN
Apakah pesannya sendiri ditandatangani?Ya, signedPayload adalah JWSTidak, field data berupa JSON yang dienkode base64
Apa yang membuktikan pengirimnyaRantai sertifikat x5c hingga root AppleToken OIDC Pub/Sub pada push, atau pull terautentikasi milik Anda sendiri
Objek bertanda tangan bertingkatsignedTransactionInfo dan signedRenewalInfo, masing-masing JWS tersendiriTidak ada
Field yang harus cocok dengan aplikasi AndabundleId, appAppleId, environmentpackageName
Jaringan sumber17.0.0.0/8, sandbox dan produksiGoogle Cloud Pub/Sub
Konfirmasi sebelum bertindakOpsional, data bertanda tangan adalah catatannyaWajib, Google meminta Anda memanggil Developer API
TransportHTTPS, TLS 1.2 atau lebih baruHTTPS push, atau pull melalui client library

Cara memverifikasi notifikasi server App Store

Dokumentasi Apple menggambarkan signedPayload sebagai string berisi tiga komponen yang dienkode Base64URL dan dipisahkan oleh titik: header, payload, dan tanda tangan, yang ditandatangani sesuai spesifikasi JSON Web Signature. Mendekode payload itu mudah. Memercayainya memerlukan empat pemeriksaan.

  • Baca array x5c dari header yang telah didekode. Apple mendokumentasikan urutannya: pertama sertifikat dengan kunci penanda tangan, kemudian sertifikat perantara Apple, lalu sertifikat root Apple.
  • Validasi rantai tersebut terhadap root Apple yang Anda unduh sendiri dari situs PKI Apple, dalam praktiknya Apple Root CA - G3. Jangan pernah memercayai root yang datang di dalam pesan, karena pemalsu dapat menaruh sertifikat apa pun di sana.
  • Pastikan sertifikat perantara membawa ekstensi Apple Worldwide Developer Relations, 1.2.840.113635.100.6.2.1, lalu verifikasi tanda tangan JWS dengan kunci publik sertifikat leaf.
  • Periksa data yang telah didekode terhadap aplikasi Anda: bundleId, appAppleId di produksi, dan environment. Tanda tangan Apple yang valid pada aplikasi developer lain, atau pada pembelian sandbox yang masuk ke endpoint produksi Anda, tetap bukan refund milik Anda.

Kemudian lakukan hal yang sama untuk isinya. Objek data memuat signedTransactionInfo dan signedRenewalInfo, dan masing-masing adalah JWS terpisah dengan rantai x5c-nya sendiri. Handler REFUND yang memverifikasi amplopnya tetapi membaca transaksi tanpa memverifikasinya telah meninggalkan celah di tengah.

Gunakan library Apple alih-alih menulisnya sendiri

Apple menerbitkan App Store Server Library untuk Swift, Java, Python, dan Node. SignedDataVerifier di dalamnya menerima sertifikat root Anda, flag pemeriksaan online, environment, bundle ID Anda, dan untuk produksi, appAppleId Anda. Kode sumber Node menunjukkan apa yang ditegakkannya: tepat tiga sertifikat dalam rantai, ekstensi leaf Apple 1.2.840.113635.100.6.11.1 dan ekstensi perantara, tanggal masa berlaku sertifikat, serta bundle ID, app ID, dan environment yang cocok. Dengan pemeriksaan online aktif, library ini juga menanyakan kepada responder OCSP apakah sertifikat leaf dan perantara telah dicabut.

Kaca pembesar perhiasan di atas sertifikat kertas bersegel timbul di meja kayu, jenis pemeriksaan teliti yang Anda berikan pada pesan refund sebelum memercayainya

Apakah daftar izin IP sudah cukup?

Tidak. Apple menyatakan bahwa jika server Anda memerlukan daftar izin, Anda sebaiknya menambahkan subnet 17.0.0.0/8, dan ini berlaku untuk sandbox maupun produksi. Itu mengurangi gangguan. Namun itu tidak membuktikan bahwa sebuah pesan asli, dan akan gagal begitu jaringan Apple berubah dengan cara yang tidak Anda ketahui. Pertahankan pemeriksaan tanda tangan sebagai gerbang yang sesungguhnya.

Cara memverifikasi notifikasi refund Google Play

Google Play memublikasikan pesan RTDN ke topik Pub/Sub milik Anda, dan hanya service account google-play-developer-notifications@system.gserviceaccount.com yang boleh memegang peran Pub/Sub Publisher pada topik tersebut. Subscription Anda kemudian mengirimkan pesan dengan salah satu dari dua cara, dan masing-masing memiliki buktinya sendiri.

  • Pull subscription: server Anda membuka koneksi terautentikasi ke Pub/Sub dan mengambil pesan. Tidak ada endpoint publik, sehingga tidak ada tempat bagi orang asing untuk mengirim.
  • Push subscription dengan autentikasi aktif: Pub/Sub menandatangani JSON Web Token dan mengirimkannya di header Authorization sebagai token Bearer. Panduan Google meminta Anda memvalidasi tanda tangan token dan memeriksa bahwa klaim email dan audience-nya cocok dengan nilai yang Anda konfigurasikan, dan contoh kodenya juga mensyaratkan email_verified bernilai true. Token tersebut bisa berumur hingga satu jam.
  • Push subscription tanpa autentikasi: apa pun yang dapat menjangkau URL tersebut dapat mengirim pesan yang berbentuk seperti RTDN.

Mengapa Google ingin Anda mengonfirmasi dengan API

Bahkan RTDN yang terautentikasi sempurna pun tidak membawa cerita lengkapnya. Panduan penyiapan Google menyatakan dengan jelas bahwa notifikasi ini hanya memberi tahu Anda bahwa status pembelian telah berubah dan bahwa Anda harus memanggil Google Play Developer API untuk mendapatkan status lengkapnya. Untuk voidedPurchaseNotification, artinya Anda menemukan pembelian tersebut di Voided Purchases API, atau mengambil status terkininya, sebelum mencabut apa pun. Panggilan API diautentikasi dengan service account Anda sendiri, sehingga jawabannya tidak dapat dipalsukan oleh pemalsu.

Berapa kerugian finansial dari refund palsu atau refund yang ditolak

Notifikasi refund palsu yang Anda percayai membuat Anda kehilangan pelanggan yang membayar. Anda mengunci akses seseorang yang uangnya masih Anda pegang, mereka membuka tiket dukungan, dan sebagian akan pergi ke store untuk meminta refund yang sudah seolah-olah diberikan oleh sistem Anda. Pembelian atau perpanjangan palsu merugikan dari arah sebaliknya: Anda menyerahkan komputasi GPU, panggilan API pihak ketiga berbayar, penyimpanan, dan pembayaran kreator atas pendapatan yang tidak pernah ada.

Kegagalan sebaliknya lebih senyap dan sering kali lebih besar. Verifier yang menolak pesan asli, karena appAppleId yang salah, pengaturan sandbox di produksi, atau sertifikat root yang usang, menggugurkan dua alur refund di mana bukti Anda berpengaruh. Apple meminta data konsumsi dalam 12 jam sejak CONSUMPTION_REQUEST. Google memberi Anda 24 jam untuk menjawab peninjauan chargeback melalui orders.reviewrefund, dan untuk pesanan yang dibuat setelah 3 Agustus 2026, chargeback Google Play yang kalah membebani Anda sebesar harga pembelian dikurangi biaya layanan Play, ditambah biaya yang dikenakan bank pembeli.

KegagalanApa yang terjadiBerapa kerugiannya
REFUND palsu diterimaPelanggan yang membayar kehilangan aksesWaktu dukungan dan permintaan refund nyata yang Anda undang sendiri
Pembelian palsu diterimaAkses gratis ke fitur berbayarKomputasi, panggilan API, penyimpanan, dan pembayaran tanpa pendapatan
CONSUMPTION_REQUEST asli ditolakApple memutuskan tanpa data AndaPenjualan tersebut, ditambah semua biaya yang sudah dikeluarkan untuk menyediakannya
Peninjauan chargeback asli ditolakGoogle memutuskan tanpa bukti AndaHarga pembelian dan biaya bank pada pesanan setelah 3 Agustus 2026

Jangan biarkan bug verifikasi menghabiskan tenggat waktu

  • Simpan permintaan mentah sebelum Anda memverifikasinya, sehingga pesan yang ditolak tidak pernah benar-benar hilang.
  • Pasang peringatan untuk setiap kegagalan verifikasi. Satu pesan palsu hanyalah gangguan. Semua pesan gagal sekaligus berarti bug Anda sendiri.
  • Di Apple, Anda dapat memutar ulang pesan yang Anda tolak. Get Notification History mengembalikan signedPayload asli untuk 180 hari terakhir, jadi perbaiki verifier Anda dan jalankan kembali payload yang tersimpan atau dipulihkan melaluinya.
  • Di Google, peninjauan chargeback yang tertunda hanya ada di notifikasinya, sehingga audience push yang salah dikonfigurasi berarti peninjauan yang terlewat. Uji dengan Send Test Message di Play Console setiap kali ada perubahan.

RefundHalt memverifikasi notifikasi dari kedua store, mengonfirmasi refund dengan API store sebelum ada yang berubah, dan menjawab CONSUMPTION_REQUEST serta peninjauan chargeback dalam batas waktunya, sehingga pesan palsu tidak dapat membuat Anda kehilangan pelanggan dan pesan asli tidak dapat terlewat.

Pertanyaan yang sering diajukan

Bagaimana cara memverifikasi notifikasi server App Store?
Verifikasi signedPayload sebagai JSON Web Signature. Baca rantai sertifikat x5c dari header-nya, validasi terhadap sertifikat root Apple yang Anda unduh dari situs PKI Apple, verifikasi tanda tangan dengan kunci sertifikat leaf, lalu periksa bahwa bundleId, appAppleId, dan environment cocok dengan aplikasi Anda. App Store Server Library milik Apple melakukan semua ini di SignedDataVerifier.
Kunci mana yang saya gunakan untuk memvalidasi notifikasi server App Store?
Anda tidak memerlukan kunci dari App Store Connect. Kunci publiknya ada di sertifikat pertama rantai x5c di dalam header JWS, dan Anda memercayainya hanya setelah memvalidasi rantai tersebut hingga sertifikat root Apple yang Anda peroleh sendiri. Kunci In-App Purchase Anda digunakan untuk memanggil API Apple, bukan untuk memeriksa notifikasi.
Apakah Real-time developer notifications Google Play ditandatangani?
Tidak, Google Play tidak menandatangani pesan RTDN itu sendiri. Pada push subscription yang terautentikasi, Pub/Sub mengirim token OpenID Connect bertanda tangan di header Authorization yang Anda validasi, dan Google meminta Anda memanggil Google Play Developer API setelah setiap notifikasi untuk mendapatkan status lengkap pembelian.
Apakah server saya harus mengembalikan error ketika notifikasi gagal diverifikasi?
Simpan dulu permintaan mentahnya, lalu putuskan. Apple mencoba ulang notifikasi versi 2 setelah respons 40x atau 50x, pada 1, 12, 24, 48, dan 72 jam setelah percobaan sebelumnya. Jika kegagalan berasal dari konfigurasi Anda sendiri, Get Notification History memungkinkan Anda memulihkan signedPayload asli selama 180 hari dan memverifikasinya kembali setelah diperbaiki.
Apakah saya masih perlu memverifikasi notifikasi jika hanya mengizinkan rentang IP Apple?
Ya. Apple meminta server yang memakai daftar izin untuk menerima subnet 17.0.0.0/8, yang membatasi siapa yang dapat terhubung tetapi tidak membuktikan bahwa sebuah pesan asli. Tanda tangan JWS adalah pemeriksaan yang mengikat notifikasi ke Apple dan ke aplikasi Anda.

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.