Mulai cepat (5 menit)

Panduan ini membawa Anda dari nol sampai menerima webhook payment.paid pertama. Semuanya memakai mode uji: tanpa HP, tanpa app bank, dan tanpa transfer sungguhan. Setelah semuanya berjalan, ikuti daftar Siap go-live di bagian akhir.

Yang Anda perlukan:

1. Daftar dan verifikasi email

  1. Buka https://payment-reader.ragh.co.id lalu pilih Daftar.
  2. Isi nama usaha, nama Anda, email, dan password.
  3. Masukkan kode OTP 6 digit yang dikirim ke email Anda.
    • Kode berlaku 10 menit.
    • Paling banyak 5 kali salah.
    • Kode baru bisa diminta setelah 60 detik, paling banyak 5 kali per jam.

Akun baru langsung bisa memakai mode uji. Mode live baru terbuka setelah verifikasi identitas (KYC), lihat langkah 7.

2. Buat aplikasi

"Aplikasi" adalah sistem Anda yang membuat tagihan, misalnya toko online. Setiap aplikasi punya API key, webhook secret, dan callback_url sendiri.

  1. Di dashboard, buat aplikasi baru.
  2. Isi prefix nomor transaksi, 3–4 huruf, misalnya TKO. Setiap tagihan mendapat nomor seperti TKO-260928-0001.
  3. Isi callback URL, alamat HTTPS publik yang akan menerima webhook. Alamat HTTP biasa atau IP privat ditolak.
  4. Salin webhook secret (whsec_…). Secret hanya ditampilkan sekali.
  5. Buat kunci uji dengan scope payments:read dan payments:write. Pembuatan kunci meminta OTP email. Bentuknya rk_test_ diikuti 40 karakter, dan kunci juga hanya ditampilkan sekali. Simpan di server Anda, jangan di aplikasi HP atau kode frontend.

Kunci uji hanya membuat data uji. Data uji tidak pernah cocok dengan transfer sungguhan, dan tidak ditagih.

3. Buat tagihan uji

curl -X POST https://payment-reader.ragh.co.id/api/v1/payments \
  -H "Authorization: Bearer rk_test_GANTI_DENGAN_KUNCI_ANDA" \
  -H "Content-Type: application/json" \
  -H "Accept: application/json" \
  -d '{
        "reference_id": "ORDER-1001",
        "amount": 150000,
        "description": "Uji coba pertama"
      }'

Balasan 201 Created (dipersingkat):

{
  "id": "pay_01j8zq5v3m7c2k9x4h6t1r0bna",
  "tx_number": "TKO-260928-0001",
  "reference_id": "ORDER-1001",
  "amount": 150000,
  "unique_code": 123,
  "total_amount": 150123,
  "bank": {
    "code": "UJI",
    "name": "Rekening Uji",
    "account_number": "0000000000",
    "account_holder": "Toko Contoh (UJI)"
  },
  "status": "pending",
  "confirmation_delayed": false,
  "late": false,
  "test": true,
  "expires_at": "2026-09-29T10:15:00+07:00",
  "payment_url": "https://payment-reader.ragh.co.id/pay/pay_01j8zq5v3m7c2k9x4h6t1r0bna",
  "reused": false
}

4. Siapkan endpoint webhook

Endpoint Anda wajib:

  1. memverifikasi tanda tangan X-Reader-Signature dari body mentah;
  2. membalas dalam 10 detik dengan HTTP 2xx dan JSON ack:
{ "event_id": "evt_01j8zqa2b3c4d5e6f7g8h9j0km", "status": "accepted" }

event_id harus sama persis dengan event_id di body webhook. Balasan 200 tanpa ack yang benar dianggap gagal (INVALID_ACK) dan dikirim ulang.

Contoh minimal dalam PHP:

<?php
$secret = getenv('READER_WEBHOOK_SECRET');
$raw = file_get_contents('php://input');
$ts  = $_SERVER['HTTP_X_READER_TIMESTAMP'] ?? '';
$sig = $_SERVER['HTTP_X_READER_SIGNATURE'] ?? '';

$expected = 'sha256=' . hash_hmac('sha256', $ts . '.' . $raw, $secret);
if (!ctype_digit($ts) || abs(time() - (int) $ts) > 300 || !hash_equals($expected, $sig)) {
    http_response_code(401);
    exit;
}

$event = json_decode($raw, true);
// ... proses $event['event'] dan $event['data'] di sini ...

header('Content-Type: application/json');
echo json_encode(['event_id' => $event['event_id'], 'status' => 'accepted']);

Versi lengkap untuk Laravel, PHP native, Node, Go, dan Python ada di Contoh kode.

5. Simulasikan dana masuk

Dengan kunci uji, Anda bisa memalsukan notifikasi bank untuk tagihan uji:

curl -X POST https://payment-reader.ragh.co.id/api/v1/test/simulate \
  -H "Authorization: Bearer rk_test_GANTI_DENGAN_KUNCI_ANDA" \
  -H "Content-Type: application/json" \
  -d '{ "payment_id": "pay_01j8zq5v3m7c2k9x4h6t1r0bna" }'

Balasan berisi mutasi simulasi dan tagihan terbarunya (dipersingkat):

{
  "mutation": { "id": "mut_01j8zqb7r2s3t4v5w6x7y8z9a0", "direction": "credit", "amount": 150123, "match_status": "matched", "test": true },
  "payment": { "id": "pay_01j8zq5v3m7c2k9x4h6t1r0bna", "status": "paid", "late": false, "test": true }
}

Beberapa detik kemudian, endpoint Anda menerima webhook payment.paid.

Coba juga cabang lainnya:

Ingin menguji Body test/simulate
Lunas normal {"payment_id": "pay_…"}
Lunas telat (late: true) {"payment_id": "pay_…", "expire_first": true}
Uang dobel (payment.duplicate) Panggil simulasi lunas dua kali untuk tagihan yang sama
Lunas setelah dibatalkan Batalkan dulu lewat POST /api/v1/payments/{id}/cancel, lalu simulasikan
Transfer tanpa pasangan (no_candidate) {"payment_id": "pay_…", "amount": 150000} (tanpa kode unik)
Nama pengirim tertentu Tambahkan "counterparty_name": "BUDI SANTOSO"

6. Periksa hasilnya

curl https://payment-reader.ragh.co.id/api/v1/payments/pay_01j8zq5v3m7c2k9x4h6t1r0bna \
  -H "Authorization: Bearer rk_test_GANTI_DENGAN_KUNCI_ANDA"

Status tagihan sekarang paid. Di dashboard, buka menu webhook untuk melihat setiap percobaan kirim beserta respons endpoint Anda. Bila webhook gagal, kode errornya dijelaskan di Webhook.

7. Siap go-live

Centang semua butir ini sebelum memakai kunci live (rk_live_…).

Akun

HP dan rekening

Integrasi

Rincian setiap butir ada di Webhook.