Perbandingan · Terbit
SDK resmi atau memanggil API langsung: apa yang benar-benar dibungkus paket PHP dan JavaScript Kasera Pay, apa yang tetap ditulis sendiri, dan kapan HTTP biasa justru lebih tepat
Jawaban singkatnya: untuk backend PHP 8.1+ atau JavaScript/TypeScript (Node 20.19+, Deno, Bun, atau edge runtime) yang membuat permintaan pembayaran dan menerima webhook, pakai SDK resmi, terutama karena verifikasi webhooknya. Panggil API HTTP langsung kalau bahasanya lain, kalau integrasinya memakai endpoint Langganan, atau kalau butuh field API yang lebih baru dari paket yang terpasang. Kedua jalur memanggil endpoint, kunci API, dan tarif yang sama. Yang berbeda hanya berapa banyak kode yang ditulis dan dirawat sendiri.
Perbandingan ini dibuat dari kode sumber kedua paket versi 0.1.0, bukan dari daftar fitur: paket npm kasera-pay dan paket Composer kasera/kasera-pay, keduanya tanpa dependency, dengan contoh pemakaian di halaman SDK resmi.
Yang dibungkus SDK, dan yang tidak
| Urusan | SDK 0.1.0 | HTTP langsung |
|---|---|---|
| Membuat, mengambil, dan mendaftar permintaan pembayaran | createTransaction, getTransaction, listTransactions | POST dan GET /v1/transactions, ditulis sendiri |
| Metode yang aktif di akun | listPaymentMethods | GET /v1/payment_methods |
| Header Idempotency-Key | Dikirim kalau key diberikan, tidak dibuat otomatis | Ditulis sendiri |
| Error | Exception berisi status, kode, fields, dan request id. Gangguan jaringan menjadi status 0 dengan kode network_error | Membaca status dan body sendiri |
| Batas waktu | 30 detik per request (PHP: 10 detik untuk tersambung) | Diatur sendiri |
| Verifikasi webhook | Satu fungsi, lengkap | Ditulis sendiri, bagian yang paling sering salah |
| Retry dan backoff | Tidak ada | Tidak ada |
| Endpoint Langganan | Tidak ada | Semua endpoint di spesifikasi |
| Type | TypeScript dibangkitkan dari spesifikasi API saat paket dirilis | Tidak ada, kecuali dibangkitkan sendiri |
Alasan terkuat memakai SDK: verifikasi webhook
Membuat permintaan pembayaran dengan HTTP biasa hanya beberapa baris, dan kesalahannya langsung terlihat sebagai error. Verifikasi webhook sebaliknya: kode yang salah sering tetap berjalan di uji pertama, lalu gagal diam-diam atau menerima kiriman yang seharusnya ditolak. Fungsi Webhook::constructEvent di PHP dan constructWebhookEvent di JavaScript menangani empat hal yang paling sering terlewat saat header Kasera-Signature-V1 diverifikasi sendiri:
- HMAC-SHA256 dihitung atas
t, titik, lalu body mentah persis seperti yang diterima. Framework yang sudah mengurai JSON lalu men-serialize ulang menghasilkan byte yang berbeda, dan tanda tangannya tidak pernah cocok. - Selama 24 jam setelah signing secret dirotasi, header membawa dua entri
v1, satu per secret. Kode yang hanya membaca entri pertama menolak kiriman yang sah di hari rotasi. - Timestamp yang selisihnya lebih dari 300 detik dari jam server ditolak, supaya kiriman lama yang direkam tidak bisa diputar ulang.
- Perbandingan tanda tangan memakai fungsi waktu-konstan, bukan operator sama dengan.
Integrasi HTTP yang sudah lama berjalan tidak perlu dipindah seluruhnya. Mengganti fungsi verifikasinya dengan milik SDK sudah menutup keempat celah itu. Format header lengkapnya ada di dokumentasi webhook, dan urutan rotasi secret yang aman di artikel rotasi signing secret.
Yang tetap ditulis sendiri walau memakai SDK
SDK tidak mengulang request yang gagal. Satu request yang habis waktunya setelah 30 detik berakhir sebagai exception, padahal permintaan pembayarannya mungkin sudah dibuat di server. Satu-satunya pencegah tagihan ganda saat mengulang adalah header Idempotency-Key yang sama: key yang sama dengan body yang sama mengembalikan permintaan yang asli, dan key itu tidak pernah kedaluwarsa. Tanpa key, setiap percobaan ulang menjadi permintaan pembayaran baru. external_id tidak mencegahnya.
Kode berikut mengulang hanya yang layak diulang (gangguan jaringan, 429, dan 5xx) dengan key yang sama, dan berhenti seketika pada 422, karena request yang salah tetap salah kalau dikirim ulang tanpa perubahan:
import { KaseraPay, KaseraPayError } from "kasera-pay";
const kasera = new KaseraPay(process.env.KASERA_API_KEY!);
const tunggu = (ms: number) => new Promise((r) => setTimeout(r, ms));
async function buatPembayaran(orderId: string, amount: number) {
for (let percobaan = 1; ; percobaan++) {
try {
return await kasera.createTransaction(
{ amount, external_id: orderId, checkout: {} },
{ idempotencyKey: orderId },
);
} catch (e) {
const layakDiulang =
e instanceof KaseraPayError &&
(e.status === 0 || e.status === 429 || e.status >= 500);
if (!layakDiulang || percobaan === 4) throw e;
await tunggu(2 ** percobaan * 1000);
}
}
}Kode ini diuji dengan SDK 0.1.0 terhadap backend palsu: gangguan jaringan lalu 429 lalu 201 berakhir dengan satu permintaan pembayaran dan tiga request yang membawa key yang sama; 422 berhenti di percobaan pertama. Jeda 2, 4, lalu 8 detik dipilih karena batas 300 request per menit per kunci menjawab 429 rate_limited tanpa header Retry-After, jadi tidak ada yang bisa ditunggu selain jeda sendiri. Rinciannya ada di artikel rate limit dan lonjakan permintaan.
Dua hal lain juga tetap tugas integrasi: mencatat id setiap event webhook supaya kiriman ulang tidak diproses dua kali, dan memetakan status permintaan pembayaran, seperti pending, succeeded, dan expired, ke status pesanan sendiri.
Saat API lebih baru dari paketnya
Type TypeScript di SDK dibangkitkan dari spesifikasi API saat paket dirilis. Paket npm 0.1.0 dirilis 28 September 2026. Sesudahnya API menerima send_receipt pada create, field yang menyalakan atau mematikan email bukti pembayaran per pembayaran, dan field itu sudah ada di /v1/openapi.json. Di paket yang terpasang belum ada. Menulis send_receipt: true di object literal untuk createTransaction ditolak compiler dengan error TS2353 (diuji dengan TypeScript 5.9). Saat dijalankan, field itu tetap terkirim apa adanya, karena SDK meneruskan body dengan JSON.stringify.
Jalan keluarnya sempit dan disengaja: simpan body di variabel lalu beri type CreateTransactionRequest dengan as di satu tempat itu saja, dengan komentar yang menyebut field mana yang belum ada di paket. PHP tidak mengalami ini, karena SDK PHP menerima array biasa. Field yang ditambahkan ke API berikutnya akan bernasib sama selama paket yang terpasang belum memuatnya, termasuk field yang wajib untuk pembayaran di atas Rp 1.000.000 mulai 26 Oktober 2026 menurut referensi membuat transaksi.
Versi 0.1.0 juga berarti paketnya masih di bawah 1.0. Kunci versinya lewat lock file, dan baca catatan rilis sebelum menaikkan versi minor.
Kapan HTTP langsung yang tepat
- Bahasa selain PHP dan JavaScript. Python, Go, Java, C#, Ruby, dan Dart belum punya SDK resmi. API-nya HTTPS dan JSON biasa, dan klien bisa dibangkitkan dari spesifikasinya seperti di panduan membuat klien dari spesifikasi OpenAPI.
- Tagihan langganan lewat API. Plan, pelanggan, langganan, dan invoice langganan tidak ada di SDK 0.1.0. Integrasi seperti ini tetap bisa memakai SDK untuk permintaan pembayaran dan webhook, lalu HTTP biasa untuk endpoint Langganan.
- Runtime lama. PHP di bawah 8.1 atau Node di bawah 20.19 tidak didukung paketnya.
- Kebutuhan transport khusus. Proxy keluar, mTLS, atau pencatatan request yang ketat. SDK PHP menerima fungsi transport sendiri dan SDK JavaScript menerima
fetchsendiri, jadi sebagian kebutuhan ini masih bisa dipenuhi tanpa meninggalkan SDK.
Ringkasnya, per situasi
| Situasi | Pilihan |
|---|---|
| Laravel, WordPress, atau PHP biasa, checkout dan webhook | SDK PHP |
| Next.js, Express, Hono, atau Cloudflare Workers | SDK JavaScript |
| Integrasi HTTP lama yang sudah berjalan | Tetap HTTP, ganti verifikasi webhook dengan milik SDK kalau belum lengkap |
| Python, Go, Java, dan lainnya | HTTP langsung atau klien dari OpenAPI |
| Langganan lewat API | SDK untuk pembayaran dan webhook, HTTP untuk Langganan |
| Butuh field yang lebih baru dari paket | SDK dengan satu cast yang dikomentari, atau HTTP untuk panggilan itu |
Apa pun pilihannya, uji dulu dengan kunci kp_test_: semua panggilan berjalan dari awal sampai akhir tanpa uang berpindah, dan pindah ke live cukup dengan mengganti kunci.
Pertanyaan yang sering muncul
Apakah memakai SDK mengubah tarif atau batas akun?
Tidak. SDK memanggil endpoint yang sama dengan kunci API yang sama, jadi tarif per metode, batas nominal, batas 300 request per menit per kunci, dan status pembayaran sama persis dengan panggilan HTTP biasa.
Bisakah SDK dipakai di browser atau aplikasi ponsel?
Jangan. Kedua SDK memegang kunci API rahasia, jadi tempatnya di server. Aplikasi ponsel dan halaman web meminta backend sendiri membuat permintaan pembayaran, lalu backend itulah yang memakai SDK atau HTTP biasa.
Ada SDK untuk Python, Go, atau Java?
SDK resmi saat ini hanya PHP dan JavaScript/TypeScript. Bahasa lain memanggil API HTTP langsung, atau membangkitkan klien dari spesifikasi OpenAPI di /v1/openapi.json.
Kalau sudah menulis integrasi HTTP sendiri, perlukah pindah ke SDK?
Tidak perlu kalau verifikasi webhooknya sudah benar: memakai body mentah, membandingkan semua entri v1, menolak timestamp yang lebih dari lima menit, dan membandingkan dengan fungsi waktu-konstan. Kalau salah satu belum, mengganti fungsi verifikasi itu saja dengan milik SDK sudah cukup, tanpa memindahkan panggilan lainnya.