WhatsApp API Integration Skill
Skill untuk integrasi WhatsApp Business API dalam aplikasi — kirim tagihan, notifikasi pesanan, reminder, dan customer service.
Opsi Integrasi
| Provider | Harga | Kelebihan | Kekurangan |
|---|---|---|---|
| wa.me link | Gratis | Tanpa API, langsung buka WA | Manual, tidak bisa broadcast |
| WhatsApp Cloud API (Meta) | Per conversation | Official, gratis 1000 convo/bulan | Setup rumit, perlu Meta Business |
| Fonnte | Mulai 30rb/bulan | Mudah, API REST simple, Indonesia | Third-party, risiko banned |
| Wablas | Mulai 50rb/bulan | Mudah, support grup | Third-party |
1. wa.me Link (Tanpa API — Paling Simple)
Buka Chat Langsung
const kirimWA = (nomor, pesan) => {
// Format nomor: hapus 0 di depan, ganti +62
const nomorClean = nomor.replace(/^0/, '62').replace(/[^0-9]/g, '')
const pesanEncoded = encodeURIComponent(pesan)
window.open(`https://wa.me/${nomorClean}?text=${pesanEncoded}`, '_blank')
}
Template Tagihan
const templateTagihan = (pesanan, pengaturan) => {
const template = pengaturan.templateWA || defaultTemplate
return template
.replace('{nama}', pesanan.pelangganNama)
.replace('{invoice}', pesanan.nomorInvoice)
.replace('{total}', formatRp(pesanan.total))
.replace('{sisa}', formatRp(pesanan.total - (pesanan.dp || 0) - (pesanan.pelunasan || 0)))
.replace('{tanggal}', formatTgl(pesanan.tanggalAmbil))
.replace('{rekening}', pengaturan.nomorRekening)
}
const defaultTemplate = `Halo {nama},
Pesanan Anda *{invoice}* senilai *{total}*.
Sisa pembayaran: *{sisa}*
Mohon transfer sebelum tanggal {tanggal} ke:
{rekening}
Konfirmasi pembayaran via chat ini.
Terima kasih! 🙏`
Tombol Kirim WA di UI
const KirimWAButton = ({ pesanan, pengaturan }) => {
const pelanggan = getPelanggan(pesanan.pelangganId)
const handleKirim = () => {
const pesan = templateTagihan(pesanan, pengaturan)
kirimWA(pelanggan.kontak, pesan)
}
return (
<button className="btn bg-green-600 hover:bg-green-700 text-white">
<MessageCircle size={16} /> Kirim via WA
</button>
)
}
2. WhatsApp Cloud API (Official Meta)
Setup
- Buat Meta Business Account di business.facebook.com
- Buat App di developers.facebook.com → tipe "Business"
- Tambahkan produk "WhatsApp" → dapatkan Phone Number ID & Token
- Simpan credentials di environment variables
Kirim Pesan Text
const WHATSAPP_TOKEN = process.env.WHATSAPP_TOKEN
const PHONE_NUMBER_ID = process.env.WHATSAPP_PHONE_ID
const kirimPesanWA = async (nomorTujuan, pesan) => {
const response = await fetch(
`https://graph.facebook.com/v18.0/${PHONE_NUMBER_ID}/messages`,
{
method: 'POST',
headers: {
'Authorization': `Bearer ${WHATSAPP_TOKEN}`,
'Content-Type': 'application/json',
},
body: JSON.stringify({
messaging_product: 'whatsapp',
to: nomorTujuan, // format: 6281234567890
type: 'text',
text: { body: pesan },
}),
}
)
return response.json()
}
Kirim Template Message (untuk notifikasi)
const kirimTemplateWA = async (nomorTujuan, templateName, params) => {
const response = await fetch(
`https://graph.facebook.com/v18.0/${PHONE_NUMBER_ID}/messages`,
{
method: 'POST',
headers: {
'Authorization': `Bearer ${WHATSAPP_TOKEN}`,
'Content-Type': 'application/json',
},
body: JSON.stringify({
messaging_product: 'whatsapp',
to: nomorTujuan,
type: 'template',
template: {
name: templateName,
language: { code: 'id' },
components: [
{
type: 'body',
parameters: params.map(p => ({ type: 'text', text: p })),
},
],
},
}),
}
)
return response.json()
}
// Contoh: kirim notifikasi pesanan
kirimTemplateWA('6281234567890', 'order_confirmation', [
'Ibu Sari', // {1} nama
'INV-2024-001', // {2} invoice
'Rp285.000', // {3} total
'28 Mar 2024', // {4} tanggal ambil
])
Kirim Document (PDF Invoice)
const kirimDocumentWA = async (nomorTujuan, documentUrl, filename, caption) => {
const response = await fetch(
`https://graph.facebook.com/v18.0/${PHONE_NUMBER_ID}/messages`,
{
method: 'POST',
headers: {
'Authorization': `Bearer ${WHATSAPP_TOKEN}`,
'Content-Type': 'application/json',
},
body: JSON.stringify({
messaging_product: 'whatsapp',
to: nomorTujuan,
type: 'document',
document: {
link: documentUrl,
filename: filename,
caption: caption,
},
}),
}
)
return response.json()
}
Webhook — Terima Pesan Masuk
// Express endpoint
app.post('/webhook/whatsapp', (req, res) => {
const { entry } = req.body
for (const e of entry) {
for (const change of e.changes) {
if (change.value.messages) {
for (const msg of change.value.messages) {
const from = msg.from // nomor pengirim
const text = msg.text?.body // isi pesan
const type = msg.type // text, image, document, dll
handleIncomingMessage(from, text, type)
}
}
}
}
res.sendStatus(200)
})
// Verifikasi webhook
app.get('/webhook/whatsapp', (req, res) => {
const VERIFY_TOKEN = process.env.WHATSAPP_VERIFY_TOKEN
if (req.query['hub.verify_token'] === VERIFY_TOKEN) {
res.send(req.query['hub.challenge'])
} else {
res.sendStatus(403)
}
})
3. Fonnte (Third-party — Indonesia)
Kirim Pesan
const FONNTE_TOKEN = process.env.FONNTE_TOKEN
const kirimViaFonnte = async (nomorTujuan, pesan) => {
const response = await fetch('https://api.fonnte.com/send', {
method: 'POST',
headers: {
'Authorization': FONNTE_TOKEN,
'Content-Type': 'application/json',
},
body: JSON.stringify({
target: nomorTujuan,
message: pesan,
}),
})
return response.json()
}
Kirim dengan File
const kirimFileViaFonnte = async (nomorTujuan, pesan, fileUrl) => {
const response = await fetch('https://api.fonnte.com/send', {
method: 'POST',
headers: { 'Authorization': FONNTE_TOKEN },
body: JSON.stringify({
target: nomorTujuan,
message: pesan,
url: fileUrl, // URL file (PDF, image)
filename: 'invoice.pdf',
}),
})
return response.json()
}
Template Pesan
Konfirmasi Pesanan
Halo {nama}! 👋
Pesanan Anda sudah kami terima:
📋 No: *{invoice}*
🛒 {items}
💰 Total: *{total}*
Akan siap tanggal *{tanggal}*.
Terima kasih sudah memesan! 🙏
Reminder Pembayaran
Halo {nama},
Ini reminder untuk pesanan *{invoice}*:
💰 Total: *{total}*
✅ Terbayar: *{terbayar}*
⏳ Sisa: *{sisa}*
Mohon transfer ke:
🏦 {rekening}
Konfirmasi via chat ini setelah transfer.
Terima kasih! 🙏
Pesanan Siap
Halo {nama}! 🎉
Pesanan Anda *{invoice}* sudah *SIAP*!
📍 Pengambilan: {metode}
📅 Tanggal: {tanggal}
{catatan_pengiriman}
Terima kasih! 😊
Pesanan Selesai
Halo {nama}! ✨
Pesanan *{invoice}* sudah *SELESAI*.
Terima kasih sudah menjadi pelanggan kami!
Jangan ragu untuk pesan lagi ya 😊
⭐ Puas dengan layanan kami? Ceritakan ke teman-teman ya!
Format Nomor Indonesia
// Normalisasi nomor WA
const formatNomorWA = (nomor) => {
let clean = nomor.replace(/[^0-9]/g, '')
// 08xxx → 628xxx
if (clean.startsWith('0')) {
clean = '62' + clean.slice(1)
}
// +62xxx → 62xxx (sudah clean dari replace)
return clean
}
// Validasi nomor WA Indonesia
const isValidWANumber = (nomor) => {
const clean = formatNomorWA(nomor)
return /^62[0-9]{9,13}$/.test(clean)
}
Aturan
- Jangan spam — kirim pesan hanya untuk transaksi yang relevan
- Hormati jam operasional — jangan kirim di luar jam 08:00-20:00
- Sediakan opt-out — pelanggan harus bisa berhenti terima pesan
- Jangan simpan WhatsApp token di frontend — selalu di backend/env
- Rate limit: WA Cloud API max 80 pesan/detik, Fonnte sesuai plan
- Handle error & retry: network timeout, invalid number, blocked
- Log semua pesan terkirim untuk audit trail