NEOCODES
Akun

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.

NEO javascript 7 dilihat 17 Jun 2026, 02:02
Integrasi Payment Gateway ke Bot WhatsApp
JAVASCRIPT
/**
 * @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;