Blog · Terbit
Melaporkan masalah pembayaran ke dukungan: satu id yang membuat laporan bisa ditelusuri, dan tiga hal yang tidak boleh ikut terkirim
Jawaban singkatnya: laporan yang bisa diselesaikan dalam satu balasan membawa satu id yang menunjuk tepat ke kejadiannya, ditambah Kode Merchant, mode tes atau live, dan waktu lengkap dengan zona waktunya. Id yang tepat berbeda per jenis masalah, dan tabel di bawah memetakannya. Tiga hal tidak pernah boleh ikut terkirim: API key utuh, signing secret webhook, serta kata sandi atau kode verifikasi. Jalur dukungan publik Kasera Pay adalah email ke halo@kasera.id.
Laporan tanpa id, misalnya “pembayaran kemarin sore tidak masuk”, memaksa penelusuran dimulai dari tebakan: rentang waktu, kira-kira nominalnya, mungkin nama pembelinya. Setiap tebakan yang meleset menambah satu putaran tanya jawab, dan pada masalah uang satu putaran bisa berarti satu hari.
Id mana untuk masalah apa
| Masalahnya | Id yang disertakan | Di mana menemukannya |
|---|---|---|
| Permintaan API ditolak (4xx atau 5xx) | request_id, error.code, dan Idempotency-Key yang dipakai | Body galat (error.request_id) atau header X-Request-Id |
| Pembayaran tidak sesuai harapan: masih pending, nominal janggal, metode keliru | ID transaksi | Rincian pembayaran di dasbor, tombol Salin ID, atau id berawalan payreq_ dari response API |
| Webhook tidak sampai atau ditolak endpoint | Id event, dan id pembayarannya | Header Kasera-Event-Id, atau halaman event di log pengiriman |
| Akun, verifikasi, rekening pencairan | Kode Merchant dan email akun | Halaman Merchant di pengaturan dasbor |
| Dasbor menampilkan layar “Terjadi kesalahan” | Kode referensi | Tertulis di layar galat itu sendiri |
Kode Merchant layak ada di setiap laporan, apa pun jenisnya. Kode itu tidak pernah berubah, dan halaman Merchant sendiri memintanya disebut saat menghubungi dukungan.
Permintaan API yang ditolak: request_id dan header yang selalu ada
Setiap galat dari /v1 berbentuk sama, dan field ketiganya adalah request_id. Nilai itu sama persis dengan header response X-Request-Id, dan dengan id yang tercatat di log server Kasera Pay untuk permintaan tersebut. Satu nilai itu menggantikan seluruh cerita “sekitar pukul dua, nominalnya sekian”.
Header X-Request-Id dipasang pada setiap response, termasuk yang berhasil. Mencatatnya pada kedua cabang membuat permintaan yang diterima tetapi hasilnya aneh sama mudahnya ditelusuri dengan yang ditolak:
// Node.js. Header ini ada di setiap response /v1, bukan hanya pada galat.
const res = await fetch("https://pay.kasera.id/v1/transactions", {
method: "POST",
headers: {
Authorization: `Bearer ${process.env.KASERA_PAY_KEY}`,
"Idempotency-Key": order.idempotencyKey,
"Content-Type": "application/json",
},
body: JSON.stringify(payload),
});
const requestId = res.headers.get("X-Request-Id");
if (!res.ok) {
const { error } = await res.json();
// error.request_id sama persis dengan requestId di atas.
log.warn("kasera pay ditolak", {
status: res.status,
code: error.code,
request_id: error.request_id,
order: order.number,
});
} else {
log.info("kasera pay dibuat", { request_id: requestId, order: order.number });
}Sertakan juga error.code apa adanya. Kode itulah kontraknya, dan teks error.message bisa berubah susunan katanya. Sebelum melapor, baca baris kode tersebut di dokumentasi galat: setiap kode di sana membawa kapan ia muncul dan apa yang harus dilakukan, dan sebagian besar 4xx selesai di situ tanpa perlu email. Yang layak dilaporkan adalah galat yang tidak cocok dengan penjelasannya, atau 500 yang berulang dengan Idempotency-Key yang sama.
Pembayaran yang tidak sesuai harapan: ID transaksi
Setiap pembayaran di dasbor punya ID transaksi di bagian bawah rinciannya, lengkap dengan tombol Salin ID. Integrasi API mendapatkan pembayaran yang sama sebagai id berawalan payreq_ di response create, dan sebagai data.payment_request_id di setiap webhook. Salah satunya cukup.
Kolom pencarian daftar transaksi hanya mencocokkan deskripsi dan nomor pesanan, jadi menempel ID transaksi di sana tidak menemukan apa pun. Itu bukan tanda pembayarannya hilang. Penjual yang belum menyimpan ID-nya bisa mencari lewat nomor pesanan atau deskripsi, lalu menyalin ID dari rinciannya.
Untuk kasus paling umum, pembeli yang mengaku sudah membayar sementara statusnya belum succeeded, jalankan dulu tiga kemungkinan di panduan menangani pembeli yang bilang sudah bayar. Kalau laporannya tetap perlu dikirim, sertakan metodenya (QRIS atau Virtual Account bank mana), nominal yang dibayar menurut pembeli, dan waktu pembayaran menurut bukti pembeli. Bukti transfer dilampirkan sebagai petunjuk, bukan sebagai pengganti ID transaksi.
Webhook yang tidak sampai: id event, tanpa awalan evt_
Sebelum melapor, buka halaman event itu di log pengiriman webhook. Di sana tersedia body JSON yang dikirim, setiap percobaan, dan Respons endpoint, yaitu balasan server penjual sendiri. Banyak laporan “webhook tidak masuk” selesai di baris itu: 403 atau 422 dari perlindungan CSRF, 401 atau 302 dari middleware login, atau 500 dari handler yang gagal. Semuanya ada di sisi penerima, dan tidak butuh email.
Satu jebakan kecil saat mencarinya. Id di body webhook berbentuk evt_ diikuti id, sedangkan kolom pencarian log mencocokkan id event tanpa awalan itu, dan harus sama persis. Nilai header Kasera-Event-Id sudah tanpa awalan dan bisa langsung ditempel. Id pembayaran boleh ditempel dengan atau tanpa payreq_. Kalau laporan tetap perlu dikirim, sertakan id event, id pembayarannya, URL endpoint, dan kode status yang tercatat di percobaan terakhir.
Mode tes atau live, dan waktu dengan zonanya
Dua keterangan ini paling sering hilang, padahal keduanya mengubah tempat mencari. Dasbor menampilkan satu mode dalam satu waktu. Pembayaran tes yang dicari di tampilan live, atau sebaliknya, terlihat seperti hilang. Tulis modenya secara eksplisit: awalan kunci yang dipakai (kp_test_ atau kp_live_, awalannya saja) atau nilai livemode di payload webhook.
Seluruh waktu di API ditulis dengan offset +07:00. Laporan yang menulis “jam 7 malam” dari server berzona UTC meleset tujuh jam dari log yang dibaca. Tulis waktu dengan zonanya, WIB atau UTC, dan kalau memungkinkan salin timestamp dari log sendiri apa adanya.
Tiga hal yang tidak boleh ikut terkirim
- API key utuh. Awalannya cukup untuk menyatakan mode. Kunci
kp_live_yang lengkap di badan email berarti setiap orang yang bisa membaca email itu bisa membuat tagihan atas nama usaha. Hal yang sama berlaku untuk tangkapan layar file.envatau panel konfigurasi hosting. - Signing secret webhook. Siapa pun yang memegangnya bisa membuat kiriman palsu yang lolos verifikasi di server penjual. Dukungan tidak membutuhkannya untuk menelusuri pengiriman.
- Kata sandi, kode OTP, atau kode autentikator. Tidak ada penelusuran yang membutuhkannya, dan permintaan untuk mengirimkannya adalah tanda penipuan, dari siapa pun datangnya.
Kalau salah satunya terlanjur terkirim, rotasi hari itu juga. Rotasi API key mematikan kunci lama seketika tanpa masa tumpang tindih, jadi urutannya perlu disiapkan dulu; langkahnya ada di tulisan tentang menyimpan dan merotasi kunci API. Data pembeli pun cukup seperlunya: nama dan nominal membantu penelusuran, sedangkan nomor identitas pembeli tidak pernah dibutuhkan.
Dua templat yang bisa disalin
Untuk integrasi API yang menerima penolakan:
Subjek: [live] create ditolak 422 validation_failed, ORD-1234
Kode Merchant: <dari halaman Merchant di pengaturan>
Mode: live (kunci kp_live_, tidak disertakan)
Waktu: 2026-09-23 14:05 WIB
Endpoint: POST /v1/transactions
request_id: 0af7651916cd43dd8448eb211c80319c
error.code: validation_failed
Idempotency-Key yang dipakai: order-1234
Yang diharapkan: tagihan QRIS Rp 150.000 terbit
Yang terjadi: ditolak, error.fields menyebut expires_in_minutes
Sudah dicoba: mengirim ulang dengan body yang sama, hasil samaUntuk penjual yang memakai dasbor dan tautan pembayaran tanpa koding:
Subjek: pembayaran pembeli belum berstatus succeeded
Kode Merchant: <dari halaman Merchant di pengaturan>
Email akun: <email yang dipakai masuk>
ID transaksi: <tombol Salin ID di rincian pembayaran>
Metode: Virtual Account BCA
Nominal: Rp 275.000
Waktu pembeli membayar menurut pembeli: 2026-09-23 19:40 WIB
Status di dasbor saat ini: pending
Lampiran: bukti transfer dari pembeliSatu masalah, satu email. Tiga pembayaran bermasalah yang penyebabnya mungkin berbeda lebih cepat selesai sebagai tiga laporan dengan tiga ID transaksi daripada satu email panjang. Kalau masalah muncul di dasbor, layar galatnya sudah menyediakan tombol Email dukungan dengan Kode referensi terisi, dan tombol itu jalur tercepatnya.
Pertanyaan yang sering muncul
Apakah request_id perlu disimpan untuk permintaan yang berhasil?
Layak disimpan. Header X-Request-Id ada di setiap response /v1, termasuk yang berhasil, dan nilainya menunjuk satu permintaan di log Kasera Pay. Masalah yang paling sulit ditelusuri justru permintaan yang diterima tetapi hasilnya tidak sesuai harapan, misalnya tagihan yang terbit dengan metode yang tidak diduga. Tanpa request_id, penelusurannya harus dimulai dari waktu dan nominal. Untuk pembayaran yang sudah terbit, id payreq_ dari response sudah cukup.
Kenapa id event yang ditempel ke kolom pencarian log pengiriman tidak menemukan apa pun?
Karena id di body webhook berawalan evt_, sedangkan kolom pencarian log pengiriman mencocokkan id event dalam bentuk tanpa awalan itu, dan pencocokannya harus sama persis. Nilai di header Kasera-Event-Id sudah berbentuk tanpa awalan dan bisa ditempel langsung. Id pembayaran boleh ditempel dengan atau tanpa awalan payreq_, dan merchant_ref juga bisa dicari di kolom yang sama.
API key sudah terlanjur terkirim di email atau tangkapan layar. Apa yang harus dilakukan?
Anggap kunci itu bocor dan rotasi hari itu juga dari menu Developer di dasbor. Kunci lama berhenti bekerja saat itu juga, jadi siapkan dulu cara mengganti nilainya di server supaya jeda penolakan 401 sesingkat mungkin. Menghapus email tidak menarik kembali salinan yang sudah sampai di kotak masuk lain. Dukungan tidak membutuhkan API key untuk menelusuri masalah apa pun: Kode Merchant dan id yang tepat sudah cukup.