Integrasi Payment Gateway ke Bot WhatsApp
Contoh implementasi API pembayaran NEOCODES FOR DEVELOPER pada bot WhatsApp. Kode ini membuat invoice pembayaran, mengirim link/QRIS ke user, lalu mengecek status pembayaran otomatis setiap 10 detik sampai transaksi berhasil, gagal, atau waktu pengecekan habis.
/**
* @project : NEOCODES Payment Gateway
* @author : Neo 👨💻
* @license : MIT / Personal
* @description: WhatsApp bot integrasi NEOCODES Payment Gateway
* Website : https://neocodes.web.id
**/
case "payment": {
const NEOCODES_BASE_URL = "https://neocodes.web.id";
const NEOCODES_API_KEY = "ISI_LIVE_API_KEY_MERCHANT"; // contoh: nc_live_xxxxx
const amount = Number(text);
if (!amount || isNaN(amount)) {
return m.reply("Contoh:\n.neopay 1000");
}
if (amount < 1000) {
return m.reply("Minimal pembayaran Rp1.000");
}
const orderId = `BOTWA-${Date.now()}`;
let createJson;
try {
const createRes = await fetch(`${NEOCODES_BASE_URL}/api/v1/payments`, {
method: "POST",
headers: {
"Authorization": `Bearer ${NEOCODES_API_KEY}`,
"Content-Type": "application/json",
"Idempotency-Key": `${orderId}-create-v1`
},
body: JSON.stringify({
amount: amount,
external_id: orderId,
customer_name: m.pushName || "User WhatsApp",
description: `Pembayaran order ${orderId}`
})
});
createJson = await createRes.json();
if (!createRes.ok || !createJson?.success) {
return m.reply(
`Gagal membuat pembayaran.\n\n` +
`Pesan: ${createJson?.message || "Terjadi kesalahan pada server."}`
);
}
} catch (err) {
console.log("NEOCODES create payment error:", err);
return m.reply("Gagal terhubung ke server pembayaran.");
}
const payment = createJson.data;
if (!payment?.invoice_id) {
return m.reply("Gagal membuat invoice pembayaran.");
}
const invoiceId = payment.invoice_id;
const totalPayment = Number(payment.total_payment || payment.amount || amount);
const expiredAt = payment.expired_at || "-";
const qrImageUrl = payment.qr_image_url || null;
const paymentUrl = payment.payment_url || "-";
const caption = `乂 PAYMENT NEOCODES
• Invoice : ${invoiceId}
• Order ID : ${orderId}
• Nominal : Rp${totalPayment.toLocaleString("id-ID")}
• Metode : QRIS
• Status : Menunggu Pembayaran
• Expired : ${expiredAt}
Silakan scan QRIS di atas.
Link pembayaran:
${paymentUrl}
Status pembayaran dicek otomatis setiap 10 detik.`;
let qrisMsg;
if (qrImageUrl) {
qrisMsg = await conn.sendMessage(
m.chat,
{
image: { url: qrImageUrl },
caption
},
{ quoted: m }
);
} else {
qrisMsg = await conn.sendMessage(
m.chat,
{
text: caption
},
{ quoted: m }
);
}
let selesai = false;
const hapusQris = async () => {
try {
if (qrisMsg?.key) {
await conn.sendMessage(m.chat, {
delete: qrisMsg.key
});
}
} catch {}
};
const interval = setInterval(async () => {
try {
const detailRes = await fetch(
`${NEOCODES_BASE_URL}/api/v1/payments/${encodeURIComponent(invoiceId)}`,
{
method: "GET",
headers: {
"Authorization": `Bearer ${NEOCODES_API_KEY}`
}
}
);
const detailJson = await detailRes.json();
if (!detailRes.ok || !detailJson?.success) {
console.log("NEOCODES check payment failed:", detailJson?.message || detailRes.status);
return;
}
const trx = detailJson.data;
const status = String(trx?.status || "").toLowerCase();
if (["paid", "success", "completed", "settlement"].includes(status)) {
selesai = true;
clearInterval(interval);
clearTimeout(timeout);
await hapusQris();
return conn.sendMessage(
m.chat,
{
text: `✅ PAYMENT BERHASIL
• Invoice : ${trx.invoice_id}
• Order ID : ${trx.external_id || orderId}
• Nominal : Rp${Number(trx.total_payment || trx.amount || totalPayment).toLocaleString("id-ID")}
• Status : PAID
Pembayaran berhasil diterima.`
},
{ quoted: m }
);
}
if (["expired", "cancelled", "canceled", "failed"].includes(status)) {
selesai = true;
clearInterval(interval);
clearTimeout(timeout);
await hapusQris();
return conn.sendMessage(
m.chat,
{
text: `❌ PAYMENT TIDAK AKTIF
• Invoice : ${trx.invoice_id}
• Order ID : ${trx.external_id || orderId}
• Nominal : Rp${Number(trx.total_payment || trx.amount || totalPayment).toLocaleString("id-ID")}
• Status : ${status.toUpperCase()}
Silakan buat pembayaran baru.`
},
{ quoted: m }
);
}
} catch (err) {
console.log("NEOCODES check payment error:", err.message);
}
}, 10000);
const timeout = setTimeout(async () => {
if (selesai) return;
selesai = true;
clearInterval(interval);
await hapusQris();
return conn.sendMessage(
m.chat,
{
text: `⏰ PAYMENT EXPIRED
• Invoice : ${invoiceId}
• Order ID : ${orderId}
• Nominal : Rp${totalPayment.toLocaleString("id-ID")}
• Status : EXPIRED
Silakan buat pembayaran baru.`
},
{ quoted: m }
);
}, 5 * 60 * 1000);
}
break;