Formulir HTML
Salah satu cara menambahkan pembayaran kripto ke situs, toko online, atau bot. Pembeli mengeklik tombol, dan halaman pembayaran dengan tagihan terbuka.
Formulir dikirim hanya lewat POST ke https://dash.bitsby.app/invoices/form dan berisi dua field:
| Field | Isinya |
|---|---|
data | base64url dari JSON berisi field tagihan |
signature | HMAC-SHA256 dari string data, 64 karakter heksadesimal |
Sebuah proyek dapat memiliki paling banyak 50 tagihan belum dibayar yang dibuat dengan cara ini pada saat yang sama.
Contoh formulir
<form method="post" action="https://dash.bitsby.app/invoices/form" target="_blank">
<input type="hidden" name="data" value="eyJwcm9qZWN0SWQiOiJhMWIyYzNkNC01ZTZm...">
<input type="hidden" name="signature" value="f77d6da1be35bd2900e0bfed9f202b04...">
<button type="submit">Pay</button>
</form>
Server toko mengisi kedua nilai tersebut saat merender halaman. Kunci rahasianya tidak pernah muncul di markup.
Atribut target="_blank" bersifat opsional: dengannya, keranjang tetap terbuka di tab semula.
Cara membangun kontainer
- Susun objek JSON berisi field tagihan.
- Enkode sebagai base64url. Inilah string
data. - Hitung
signature = HMAC-SHA256(data, formSecret).
String data ditandatangani secara utuh, jadi urutan kunci JSON, indentasi, dan gaya escaping Unicode tidak berpengaruh. Penerima juga menerima base64 standar, dengan atau tanpa padding.
Jangan menyusun ulang data setelah penandatanganan: jika satu byte saja berubah, tanda tangan harus dihitung ulang.
Cara menghitung tanda tangan, dengan contoh siap pakai dalam empat bahasa, dibahas di Tanda tangan formulir HTML.
Kunci di dalam data
| Kunci | Wajib | Isinya |
|---|---|---|
projectId | ya | ID proyek dari pengaturan di dasbor, uuid |
amountFiat | ya | Jumlah dari 1 sampai 100.000, paling banyak dua angka desimal. Sebagai string "10.50" atau angka 10.5 |
currencyFiat | ya | Mata uang fiat: USD, EUR, atau RUB |
timeToPay | ya | Batas waktu pembayaran dalam jam: 0.5, 1, 3, 6, 12. Sebagai string atau angka |
description | tidak | Deskripsi untuk pembeli, hingga 1.000 karakter |
serviceData | tidak | Identifikasi pesanan di sisi toko, hingga 1.000 karakter. Tidak ditampilkan kepada pembeli tetapi terlihat di kode sumber formulir—jangan menaruh apa pun yang sensitif di sini |
output | tidak | errors—menampilkan rincian kesalahan validasi |
Kunci opsional boleh dihilangkan dari JSON—itu sama dengan string kosong. Kunci boleh dalam urutan apa pun; penerima mengabaikan kunci yang tidak dikenal.
Nilai berupa string atau angka JSON. Boolean, array, dan objek bersarang tidak dihitung sebagai nilai field dan tiba sebagai string kosong.
Contoh isi data:
{
"projectId": "a1b2c3d4-5e6f-4a7b-8c9d-0e1f2a3b4c5d",
"amountFiat": 10.5,
"currencyFiat": "USD",
"timeToPay": 1,
"description": "Order #7, delivery",
"serviceData": "order-7"
}
Di sini jumlah dan batas waktu pembayaran dikirim sebagai angka; string juga diterima. Kunci opsional output tidak diisi sama sekali.
Format jumlah
Hanya digit dan titik desimal, paling banyak dua angka desimal: 10, 10.00, 1000.50. Spasi di sekelilingnya dipangkas.
Format lain apa pun ditolak—pemisah ribuan, koma alih-alih titik, notasi eksponensial, tanda di depan angka, simbol mata uang. Tidak ada pembulatan: angka desimal ketiga tidak dipotong, melainkan menyebabkan penolakan.
Kunci rahasia formulir
Kunci rahasia ini berada di pengaturan proyek di dasbor, pada kolom Kunci rahasia formulir (Form secret). Server menerbitkannya saat proyek dibuat. Anda tidak dapat menetapkan nilai sendiri; kunci hanya dapat diterbitkan ulang—misalnya, jika bocor.
Kunci rahasia harus tetap berada di server toko. Jika sampai muncul di HTML etalase, tanda tangan menjadi sia-sia.
Kunci rahasia formulir dan kunci rahasia webhook adalah kunci yang berbeda; jangan tertukar.
Identifikasi pesanan
Selalu isi serviceData: taruh identifikasi pesanan Anda sendiri di sana. Nilainya dikembalikan dalam notifikasi pembayaran—toko menggunakannya untuk menemukan pesanan.
serviceData yang terisi melindungi dari duplikat. Mengirim ulang formulir atau mengeklik tombol dua kali tidak membuat tagihan kedua: pembeli diarahkan ke tagihan belum dibayar yang sudah ada. Pencocokan dilakukan berdasarkan field pesanan—proyek, jumlah, mata uang, deskripsi, dan serviceData—bukan berdasarkan byte data.
Nilainya harus unik untuk setiap pesanan. Dengan nilai yang sama, pembeli kedua mendarat di tagihan belum dibayar milik pembeli pertama.
serviceData yang kosong menghilangkan perlindungan ini: tidak ada yang bisa dipakai untuk mengenali pengiriman ulang, dan setiap kirim membuat tagihan baru. Duplikat menghabiskan batas 50 tagihan belum dibayar, dan saat salah satunya dibayar, toko tidak punya apa-apa untuk mengaitkan pembayaran itu dengan pesanan.
Kesalahan dan mode debug
Formulir melewati dua pemeriksaan: pertama tanda tangan dan kontainer, lalu nilai field.
| Apa yang terjadi | Apa yang ditampilkan layanan |
|---|---|
| Tanda tangan tidak cocok, kontainer tidak terbaca, proyek milik orang lain atau tidak ada | Kesalahan umum, tanpa menyebut alasan |
| Tanda tangan cocok, tetapi ada field yang diisi salah | Kesalahan umum. Dengan "output":"errors"—kesalahan terperinci |
| Kedua pemeriksaan lolos | Halaman pembayaran dengan tagihan |
Pemeriksaan pertama tidak pernah mengungkap alasannya, apa pun pengaturannya.
Pasangan "output":"errors" dalam JSON mengaktifkan rincian untuk pemeriksaan kedua: layanan menyebut field-nya, mencantumkan nilai yang diizinkan, dan melaporkan saat plafon 50 tagihan belum dibayar tercapai. Kunci ini berada di dalam kontainer yang ditandatangani, jadi tidak bisa disuntikkan dari luar.
Selama menyiapkan formulir, taruh "output":"errors" dalam JSON; setelah selesai, hapus kuncinya dan bangun ulang kontainer.
Jika tanda tangannya sendiri tidak cocok, bandingkan data dan tanda tangan Anda dengan set acuan di Tanda tangan formulir HTML.
Langkah selanjutnya
Tagihan yang dibuat lewat formulir diproses sama seperti tagihan dari API atau dasbor:
- Konfirmasi pembayaran tiba di Webhook URL. Verifikasi tanda tangan notifikasi dengan kunci rahasia webhook dan kirim pesanan hanya berdasarkan konfirmasi ini.
- Mengembalikan pembeli ke situs Anda diatur lewat URL sukses (Successful URL) dan URL gagal (Unsuccessful URL)—lihat bagian “Mengembalikan pembeli ke situs toko” di halaman Siklus hidup tagihan. Mendarat di URL tersebut tidak mengonfirmasi pembayaran.
- Status tagihan dan jendela pencarian pembayaran dijelaskan di Siklus hidup tagihan.
- Pembeli mentransfer jumlah yang salah—lihat Pencocokan pembayaran dan selisih jumlah.