Cara menerima pembayaran crypto di website
Langkah demi langkah: buat pembayaran dari server Anda, arahkan pelanggan ke halaman pembayaran, tangani webhook, dan uji. Dengan kode Node.js yang berfungsi.

Untuk menerima crypto di website, Anda butuh dua hal di server: panggilan yang membuat pembayaran untuk sebuah pesanan dan endpoint yang menerima hasilnya. Panduan ini membahas keduanya dengan kode yang berfungsi, lalu pengujian, kasus khusus, dan kesalahan yang membuat merchant rugi.
Yang Anda butuhkan sebelum mulai
Anda tidak perlu menjalankan node blockchain atau menyimpan wallet pelanggan. Yang Anda perlukan:
- akun gateway dengan sebuah proyek, kunci API, dan, jika ingin menentukan metode pembayaran sendiri, ID metode tersebut dari proyek Anda;
- endpoint HTTPS publik di server Anda untuk webhook, disimpan di proyek sebagai callback URL;
- tempat di sistem pesanan Anda untuk menyimpan status pembayaran, dicocokkan dengan nomor pesanan Anda sendiri.
Putuskan satu hal sejak awal: apakah pelanggan memilih aset dan jaringan di halaman pembayaran, atau Anda yang memilihnya terlebih dahulu. Membiarkan pelanggan memilih lebih sederhana dan cocok untuk sebagian besar toko. Jika Anda mengirim metode pembayaran, halaman terbuka dengan metode itu sudah terpilih.
Bagaimana seluruh alurnya menyatu
Inilah jalur satu pesanan, dari checkout Anda sampai status dibayar:
- Pelanggan memilih «Bayar dengan crypto» di checkout dan server Anda membuat pembayaran untuk pesanan itu.
- Gateway mengembalikan tautan ke halaman pembayaran yang di-host.
- Anda mengarahkan pelanggan ke halaman itu. Ia memilih aset dan jaringan lalu mengirim jumlah yang tepat dari wallet-nya sendiri.
- Gateway memantau blockchain dan, setelah pembayaran final, memanggil webhook Anda.
- Webhook Anda menandai pesanan sebagai dibayar dan mulai memproses pengiriman pesanan.
Perhatikan apa yang tidak pernah terjadi di sisi Anda: Anda tidak membuat alamat, memindai blok, atau membandingkan jumlah. Kode Anda mengerjakan dua tugas kecil: membuat pembayaran dan bereaksi terhadap status akhir.
Langkah 1: buat pembayaran dari server Anda
Panggil gateway dari backend Anda, tidak pernah dari browser, karena permintaan membawa kunci API rahasia Anda. Di Qvard ini satu POST ke https://api.qvard.com/api/v1/payment dengan kunci Anda di header x-api-key dan body JSON:
id: nomor pesanan Anda sendiri, sebagai string. Nilai ini dikembalikan kepada Anda nanti di webhook, jadi gunakan sesuatu yang bisa Anda cari.price: jumlah dalam dolar AS. Pelanggan membayar dengan nilai setara dalam aset yang dipilih.paymentSystemId(opsional): ID metode pembayaran dari proyek Anda, untuk memilih aset dan jaringan lebih dulu.
Jika berhasil, responsnya 201 dengan id pembayaran dan redirectUrl. Mengirim id yang sama lagi untuk metode pembayaran yang sama mengembalikan pembayaran yang sudah ada, bukan membuat duplikat, sehingga aman mencoba ulang setelah timeout.
Jika permintaan salah, Anda mendapat 400 dengan teks Error validation dan satu pesan per kolom; jumlah di bawah minimum metode yang dipilih ditolak dengan cara yang sama. Kunci yang hilang atau salah mengembalikan 401.
// Called from your checkout handler when the customer chooses "Pay with crypto".
async function createQvardPayment(order) {
const res = await fetch('https://api.qvard.com/api/v1/payment', {
method: 'POST',
headers: {
'x-api-key': process.env.QVARD_API_KEY,
'Content-Type': 'application/json'
},
body: JSON.stringify({
id: String(order.id), // your order number, also used to match the webhook
price: order.totalUsd // amount in US dollars
})
});
if (!res.ok) throw new Error('Qvard ' + res.status + ' ' + (await res.text()));
const { redirectUrl } = await res.json();
return redirectUrl; // send the customer to this page
}Langkah 2: arahkan pelanggan ke halaman pembayaran
Arahkan pelanggan ke redirectUrl, yang bentuknya https://my.qvard.com/pay/<ID pembayaran>. Di halaman itu ia memilih aset dan jaringan, melihat jumlah yang tepat dan alamatnya, lalu membayar dari wallet-nya. Kurs dikunci selama satu jam, sehingga jumlahnya tidak berubah saat ia membayar.
Dua hal yang perlu direncanakan:
- Saat pelanggan kembali. URL tujuan setelah pembayaran belum tersedia, sehingga pelanggan kembali ke situs Anda dengan sendirinya. Beri ia halaman pesanan yang menampilkan status terkini dan diperbarui saat webhook Anda tiba.
- Jangan anggap kembalinya pelanggan sebagai pembayaran. Pelanggan yang kembali ke situs Anda belum tentu sudah membayar. Hanya webhook yang memberi tahu bahwa uang sudah masuk.
Langkah 3: terima webhook
Saat pembayaran selesai, Qvard mengirim POST ke callback URL proyek Anda dengan JSON kecil: id yang Anda kirim dan status pembayaran. Permintaan membawa kunci API Anda di header x-api-key. Ini header autentikasi, bukan tanda tangan kriptografis: bandingkan dengan kunci Anda dan tolak yang lain.
Cara kerja pengiriman penting bagi handler Anda:
- Qvard menganggap webhook terkirim hanya ketika endpoint Anda menjawab persis HTTP 200. Status lain atau timeout dihitung gagal.
- Pengiriman yang gagal dicoba ulang: total lima percobaan, dalam kira-kira enam menit.
- Redirect tidak diikuti, sehingga jawaban
3xxjuga gagal. - Anda juga bisa mengirim ulang notifikasi sebuah pembayaran dari dasbor.
Karena ada percobaan ulang, handler Anda harus idempoten: melihat peristiwa yang sama dua kali tidak boleh mengirim pesanan dua kali. Contoh di bawah memeriksa kunci, menemukan pesanan lewat id Anda, dan menandainya dibayar hanya jika belum dibayar.
import crypto from 'node:crypto';
import express from 'express';
const app = express();
app.post('/webhooks/qvard', express.json(), async (req, res) => {
// Qvard sends your API key in the x-api-key header: compare it with yours.
const received = Buffer.from(String(req.get('x-api-key') || ''));
const expected = Buffer.from(process.env.QVARD_API_KEY);
const valid = received.length === expected.length && crypto.timingSafeEqual(received, expected);
if (!valid) return res.sendStatus(401);
const { id, status } = req.body; // id is the order number you sent
const order = await db.orders.findById(id);
if (!order) return res.sendStatus(200); // unknown order: nothing to retry
if (status === 'completed' && order.state !== 'paid') {
await markOrderPaid(order); // safe to run twice: the check above skips repeats
}
return res.sendStatus(200); // must be exactly 200, otherwise Qvard retries
});Tangani pembayaran yang tidak mulus
Sebuah pembayaran punya salah satu dari empat status:
wait: dibuat, menunggu pelanggan.partial: pelanggan mengirim kurang dari yang diperlukan.completed: jumlah penuh telah masuk; inilah yang memicu webhook.rejected: pembayaran ditolak.
Putuskan sebelumnya apa yang dilakukan toko Anda untuk masing-masing. Untuk partial, pilihan umumnya menjaga pesanan tetap terbuka dan meminta pelanggan mengirim sisanya, atau mengembalikan dana. Jaga logika tetap sederhana: tandai pesanan dibayar hanya pada completed dan tampilkan pesan yang jelas kepada pelanggan untuk semua status lain.
Uji sebelum meluncur
Rencana uji singkat yang menangkap sebagian besar masalah:
- Buka invoice demo untuk melihat halaman pembayaran seperti yang dilihat pelanggan Anda.
- Buat pembayaran dari server Anda dan pastikan Anda menerima
redirectUrl. - Bayar jumlah nyata yang kecil dan pastikan webhook tiba dan pesanan menjadi dibayar.
- Buat endpoint Anda mengembalikan error sekali, pastikan Qvard mencoba ulang dan handler Anda tidak memproses pesanan dua kali.
- Tarik jumlah kecil dari saldo ke wallet Anda agar Anda tahu seluruh jalurnya berfungsi.
Qvard belum punya sandbox terpisah; sebuah sandbox ada di roadmap, jadi gunakan jumlah nyata yang kecil untuk langkah 3 sampai 5.
Daftar periksa keamanan
- Simpan kunci API hanya di server. Jangan pernah menaruhnya di kode front-end atau repositori publik.
- Bandingkan header
x-api-keypada setiap webhook dan tolak yang tidak cocok, dengan perbandingan waktu konstan. - Layani endpoint lewat HTTPS dan jaga tetap cepat; kerjakan hal yang lambat setelah Anda menjawab.
- Cocokkan pembayaran dengan pesanan lewat
idAnda sendiri dan abaikan peristiwa untuk pesanan yang tidak Anda kenal. - Catat setiap webhook beserta statusnya, agar sengketa bisa diselesaikan nanti.
Selengkapnya di cara mengamankan webhook pembayaran crypto.
Bagaimana dengan WooCommerce, Shopify, atau platform lain?
Berlaku dua panggilan yang sama: kode platform Anda membuat pembayaran dan menerima webhook. Qvard belum punya plugin siap pakai, jadi di platform seperti WooCommerce integrasinya berupa potongan kode kustom kecil atau satu jam kerja developer, bukan instalasi sekali klik. Lihat integrasi untuk status terkini, dan halaman developer untuk referensi API. Jika Anda ingin gambaran besarnya dulu, mulailah dengan apa itu payment gateway crypto.
FAQ
Apakah saya perlu menguasai pengembangan blockchain?
Tidak. Anda membuat satu permintaan HTTP untuk membuat pembayaran dan menangani satu webhook. Alamat, pemantauan jaringan, dan konfirmasi ditangani gateway.
Bisakah saya menerima crypto tanpa menulis kode?
Belum dengan Qvard. Tautan pembayaran dan cara tanpa kode lainnya sedang dikembangkan; saat ini integrasi lewat API, yang memerlukan developer.
Bagaimana jika server saya mati saat pembayaran selesai?
Notifikasi dicoba ulang lima kali dalam kira-kira enam menit. Jika server Anda mati lebih lama, kirim ulang notifikasi pembayaran itu dari dasbor dan rekonsiliasi dari sana.
Dalam mata uang apa saya menetapkan harga?
Dalam dolar AS. Pelanggan membayar dengan nilai setara dalam aset dan jaringan yang ia pilih di halaman pembayaran, dengan kurs yang dikunci selama satu jam.
