Bisakah aplikasi order Dapur Maria memakai WhatsApp API?
Mockup demo menyimulasikan WhatsApp Business, POS, pembayaran QRIS, dan kurir instan di dalam browser. Halaman ini menjelaskan cara membangunnya untuk produksi. Platform ini tidak bisa bekerja di gateway WhatsApp tidak resmi.
💬 Ingin platform chatbot WhatsApp untuk usahamu?1Ringkasan jawaban
Platform ini memakai API resmi dan tidak bisa bekerja di gateway WhatsApp tidak resmi.
WhatsApp Business Platform resmi DISARANKAN
Cloud API dari Meta, langsung atau lewat BSP (Business Solution Provider).
- Semua fitur mockup bisa dibuat: tombol, daftar pilihan, katalog dan keranjang, minta lokasi, link pembayaran, notifikasi status.
- Nomor bisnis terverifikasi, ada centang/nama tampilan resmi.
- Ada kontrak, kebijakan data, dan dukungan resmi, jadi kepatuhan ISO 27001 & UU PDP bisa dipenuhi.
Gateway tidak resmi TIDAK DIDUKUNG
Platform ini tidak bisa bekerja di gateway WhatsApp tidak resmi (unofficial).
2Arsitektur produksi
Semua token dan rahasia API ada di server. Browser (dashboard owner) tidak pernah memegang kunci API.
Kanal
WhatsApp Cloud API: Meta yang menjalankan servernya, kamu cukup menyediakan URL webhook HTTPS.
Inti bisnis
Backend milikmu: mesin chatbot, pembuatan pesanan, stok, perhitungan ongkir. Mockup demo menjalankan bagian ini di browser.
Mitra
Payment gateway QRIS dan kurir/agregator mengirim status lewat webhook bertanda tangan ke backend.
3Fitur mockup → fitur API resmi
Setiap layar di mockup punya padanan resmi. Batasan teknis dicantumkan supaya desain produksi menyesuaikan.
| Fitur di mockup | Fitur WhatsApp Business Platform | Catatan / batasan |
|---|---|---|
| Sapaan + tombol Lihat Katalog / Paket Hemat / Lokasi | Interactive reply buttons | Maks. 3 tombol per pesan, judul tombol maks. 20 karakter. |
| Pilih kurir (GoSend / GrabExpress) | Interactive list message | Maks. 10 baris; judul baris maks. 24 karakter, deskripsi maks. 72 karakter. |
| Katalog, keranjang, “Kirim pesanan” | Katalog di Commerce Manager + catalog / product message; checkout masuk sebagai webhook pesan bertipe order | Produk harus mematuhi WhatsApp Commerce Policy (makanan & minuman diperbolehkan). |
| Edit harga, stok, tampil/sembunyi di dashboard | Catalog API (Commerce) untuk update batch | Stok riil tetap dihitung di POS kamu; katalog hanya menampilkan ketersediaan. |
| Kirim lokasi / alamat kirim | Location request message atau WhatsApp Flows (formulir) | Flows cocok untuk alamat lengkap + patokan + penerima dalam satu form. |
| Ringkasan tagihan + tombol “Bayar dengan QRIS” | Pesan teks + CTA URL button | Fitur bayar langsung di WhatsApp belum tersedia di Indonesia, jadi pembayaran lewat halaman payment gateway. |
| “Pembayaran berhasil”, “Driver ditemukan”, link lacak | Pesan bebas (dalam jendela 24 jam) atau template utility | Di luar 24 jam sejak pesan terakhir pembeli, hanya template yang disetujui Meta yang boleh dikirim. |
| Rating ⭐ & “Pesan lagi” | Reply buttons | Tidak perlu template karena dikirim di dalam jendela 24 jam. |
| Log integrasi | Webhook messages & statuses (sent/delivered/read/failed) | Simpan log dengan nomor tersamarkan (A.8.11 / A.8.15). |
4Alur end-to-end (produksi)
Urutannya sama dengan mockup. Label hitam menunjukkan panggilan API atau webhook yang terjadi.
- Pembeli menyapa, lalu Meta mengirim webhook ke server, dan server membalas dengan tombol.
← webhook messages[type=text]→ POST /{phone_number_id}/messages (interactive:button) - Pembeli membuka katalog dan checkout, lalu server menerima pesanan, memvalidasi stok di POS, dan membuat draf order.
← webhook messages[type=order]POS: reserve stock - Server meminta lokasi, pembeli membagikan lokasi atau mengisi form Flows.
→ interactive:location_request_message← webhook messages[type=location] - Hitung jarak dan ongkir: jarak rute dari koordinat toko ke pembeli, lalu tarif dari kurir/agregator.
→ Maps routing API→ Kurir: estimate/rates - Pembeli memilih kurir dari list message.
→ interactive:list← webhook interactive.list_reply - Buat tagihan QRIS dinamis (nominal pas, berlaku misalnya 15 menit), lalu kirim ringkasan + tombol bayar.
→ PG: create QRIS charge→ interactive:cta_url - Pembeli membayar. Payment gateway mengirim webhook, server memverifikasi tanda tangan, menandai order Diproses, dan memotong stok. Proses ini idempoten: webhook ganda tidak memotong stok dua kali.
← PG webhook: settlementPOS: status=PROCESSING - Booking kurir: kurir menugaskan driver dan mengirim link lacak, lalu server meneruskannya ke pembeli.
→ Kurir: create delivery← webhook driver.assigned→ messages (link lacak) - Owner menandai siap → driver ambil → tiba. Setiap perubahan status diteruskan ke pembeli, dan pesanan ditutup dengan rating.
← webhook picked_up / delivered→ messages / template utility
5Contoh payload & kode
Format mengikuti dokumentasi Cloud API. Ganti {versi} dengan versi Graph API terbaru, {PHONE_NUMBER_ID} dengan ID nomor bisnismu. Nomor di contoh fiktif.
Authorization: Bearer {ACCESS_TOKEN}, token disimpan di server.POST https://graph.facebook.com/{versi}/{PHONE_NUMBER_ID}/messages { "messaging_product": "whatsapp", "to": "6281200001234", "type": "interactive", "interactive": { "type": "button", "body": { "text": "Halo Kak 👋 Selamat datang di Dapur Maria! Mau pesan apa hari ini?" }, "action": { "buttons": [ { "type": "reply", "reply": { "id": "KATALOG", "title": "Lihat Katalog" } }, { "type": "reply", "reply": { "id": "PAKET", "title": "Paket Hemat" } }, { "type": "reply", "reply": { "id": "LOKASI", "title": "Lokasi Toko" } } ] } } }
interactive.list_reply.id.{
"messaging_product": "whatsapp",
"to": "6281200001234",
"type": "interactive",
"interactive": {
"type": "list",
"body": { "text": "Jarak ke lokasi Kakak ±6,0 km. Silakan pilih kurir:" },
"action": {
"button": "Pilih kurir",
"sections": [{
"title": "Pengiriman instan",
"rows": [
{ "id": "gosend_instant", "title": "GoSend Instant", "description": "Rp15.000 · tiba ±38 mnt" },
{ "id": "grab_instant", "title": "GrabExpress Instant", "description": "Rp16.000 · tiba ±40 mnt" }
]
}]
}
}
}
product_retailer_id = SKU di POS.{
"object": "whatsapp_business_account",
"entry": [{ "changes": [{ "field": "messages", "value": {
"messages": [{
"from": "6281200001234",
"id": "wamid.HBgM...",
"type": "order",
"order": {
"catalog_id": "1234567890",
"text": "makaroni level sedang",
"product_items": [
{ "product_retailer_id": "SN03", "quantity": 2, "item_price": 4000, "currency": "IDR" },
{ "product_retailer_id": "MN04", "quantity": 1, "item_price": 10000, "currency": "IDR" }
]
}
}]
}}]}]
}
location (latitude, longitude, nama, alamat).{
"messaging_product": "whatsapp",
"to": "6281200001234",
"type": "interactive",
"interactive": {
"type": "location_request_message",
"body": { "text": "Pesanan mau diantar ke mana Kak? Bagikan lokasi ya, ongkir dihitung otomatis." },
"action": { "name": "send_location" }
}
}
{
"messaging_product": "whatsapp",
"to": "6281200001234",
"type": "interactive",
"interactive": {
"type": "cta_url",
"body": { "text": "Total bayar Rp43.000 untuk pesanan #DM-1028. Berlaku 15 menit." },
"action": {
"name": "cta_url",
"parameters": { "display_text": "Bayar dengan QRIS", "url": "https://pay.contoh-pg.id/qris/7f3a9c..." }
}
}
}
{
"messaging_product": "whatsapp",
"to": "6281200001234",
"type": "template",
"template": {
"name": "driver_assigned",
"language": { "code": "id" },
"components": [{
"type": "body",
"parameters": [
{ "type": "text", "text": "DM-1028" },
{ "type": "text", "text": "Hendra W. (B 4418 TJK)" },
{ "type": "text", "text": "https://track.contoh-kurir.id/t/GS-8F2K" }
]
}]
}
}
X-Hub-Signature-256, lalu langsung balas 200 dan proses di antrean.<?php // webhook.php – rahasia dibaca dari environment / secret manager, BUKAN ditulis di kode $verifyToken = getenv('WA_VERIFY_TOKEN'); $appSecret = getenv('WA_APP_SECRET'); // 1) Verifikasi saat mendaftarkan URL webhook (hub.mode → hub_mode di PHP) if ($_SERVER['REQUEST_METHOD'] === 'GET') { if (($_GET['hub_mode'] ?? '') === 'subscribe' && hash_equals($verifyToken, $_GET['hub_verify_token'] ?? '')) { echo $_GET['hub_challenge']; exit; } http_response_code(403); exit; } // 2) Validasi tanda tangan setiap event $raw = file_get_contents('php://input'); $sig = $_SERVER['HTTP_X_HUB_SIGNATURE_256'] ?? ''; if (!hash_equals('sha256=' . hash_hmac('sha256', $raw, $appSecret), $sig)) { http_response_code(401); exit; } // 3) Balas cepat, proses async (idempoten berdasarkan message id) http_response_code(200); $event = json_decode($raw, true); foreach ($event['entry'] ?? [] as $entry) { foreach ($entry['changes'] ?? [] as $change) { foreach ($change['value']['messages'] ?? [] as $msg) { enqueue_once($msg['id'], $msg); // order / location / interactive / text } } }
6QRIS, kurir & perhitungan jarak
💳 Pembayaran QRIS
- Gunakan payment gateway berizin Bank Indonesia yang mendukung QRIS dinamis (nominal terkunci per pesanan).
- Tetapkan masa berlaku (misalnya 15 menit), lalu batalkan order otomatis bila kedaluwarsa.
- Status “dibayar” hanya dari webhook bertanda tangan atau cek status ke server PG, bukan dari halaman pembeli.
- Webhook dibuat idempoten, rekonsiliasi harian dengan laporan settlement.
- Pilihan penyedia & contoh kode ada di §7.
🛵 Kurir instan
- API GoSend / GrabExpress langsung biasanya butuh kerja sama bisnis dengan masing-masing penyedia.
- Alternatif untuk UKM: agregator pengiriman yang sudah terhubung ke beberapa kurir (satu API, satu tagihan).
- Simpan nomor booking dan link lacak resmi dari kurir, lalu teruskan ke pembeli.
🗺️ Jarak & ongkir
- Mockup memakai perkiraan: jarak garis lurus (haversine) × 1,3.
- Produksi: pakai tarif resmi dari API kurir/agregator (sudah menghitung rute), atau routing API untuk jarak rute nyata.
- Validasi radius maksimum dan jam operasional sebelum membuat tagihan.
7Integrasi payment gateway (Midtrans, Xendit, iPaymu, dll.)
Halaman “Sandbox Payment Gateway” di mockup diganti dengan QRIS dinamis dari penyedia berizin. Pola integrasinya sama untuk semua vendor: buat tagihan → tampilkan QR → terima webhook → verifikasi → tandai lunas.
Kriteria memilih penyedia
Legalitas & keamanan
- Berizin Penyelenggara Jasa Pembayaran (PJP) dari Bank Indonesia; cek daftar resmi di situs BI.
- Sertifikasi keamanan (mis. PCI DSS untuk kartu, ISO/IEC 27001), DPA, lokasi data.
Fitur teknis
- QRIS dinamis dengan masa berlaku.
- Webhook bertanda tangan + API cek status.
- Sandbox, SDK/contoh PHP, dokumentasi jelas.
Bisnis
- MDR QRIS & biaya tambahan penyedia.
- Waktu settlement dana ke rekening owner.
- Metode lain bila perlu (VA bank, e-wallet, kartu), plus dukungan pelanggan.
Penyedia populer di Indonesia
| Penyedia | Produk / API untuk QRIS | Autentikasi | Verifikasi notifikasi | Catatan |
|---|---|---|---|---|
| Midtrans | Core API /v2/charge (payment_type: qris) atau Snap (halaman bayar siap pakai) | Basic auth (Server Key) | signature_key = SHA-512(order_id + status_code + gross_amount + ServerKey) | Bagian dari GoTo Financial; banyak dipakai UKM, sandbox lengkap. |
| Xendit | QR Codes API (type: DYNAMIC) atau Payment Request API | Basic auth (Secret Key) | Header x-callback-token dicocokkan dengan token di dashboard | Dokumentasi developer kuat, ada fitur disbursement. |
| iPaymu | API v2 direct payment (paymentMethod: qris) | Header va, signature (HMAC-SHA256), timestamp | Callback ke notifyUrl; konfirmasi ulang lewat API cek transaksi | Populer di UMKM; cek field wajib tiap metode. |
| DOKU | Checkout / Direct API (QRIS) | Client-Id + Signature HMAC; mendukung standar SNAP BI | Signature pada header notifikasi | Pemain lama, banyak metode pembayaran. |
| Duitku | API / POP checkout (QRIS) | Merchant code + signature | Signature pada callback | Biaya bersaing untuk UMKM. |
| Faspay, Flip for Business, OY! Indonesia, Tripay, Nicepay, dll. | Bervariasi | Bervariasi | Bervariasi | Konfirmasi izin PJP, dukungan QRIS dinamis, dan biaya langsung ke penyedia. |
Alur teknis yang sama untuk semua penyedia
- Buat tagihan QRIS dengan
order_idunik (mis.DM-1028), nominal pas, dan masa berlaku 15 menit.
→ PG: create charge / QR - Tampilkan QR: render
qr_stringmenjadi gambar di halaman bayar milikmu (library QR disimpan lokal), atau pakai halaman bayar bawaan penyedia (Snap/Checkout). Link halaman dikirim lewat tombol CTA WhatsApp.
→ WA: interactive cta_url - Terima notifikasi di endpoint HTTPS, lalu verifikasi tanda tangan/token. Notifikasi tanpa tanda tangan yang valid ditolak.
← PG webhook - Konfirmasi ulang status ke API penyedia (GET status), lalu cocokkan nominal & order_id dengan database.
→ PG: get status - Update idempoten: ubah status UNPAID → PROCESSING hanya sekali, potong stok, dan antrekan sinkron POS (§8). Status expire/cancel mengembalikan reservasi stok.
orders.statuspos_outbox - Rekonsiliasi laporan settlement harian dengan pesanan & faktur POS.
PG settlement report
Contoh kode
api.sandbox.midtrans.com, produksi: api.midtrans.com.# Buat tagihan QRIS POST https://api.sandbox.midtrans.com/v2/charge Authorization: Basic base64(SERVER_KEY + ":") Content-Type: application/json { "payment_type": "qris", "transaction_details": { "order_id": "DM-1028", "gross_amount": 43000 }, "custom_expiry": { "expiry_duration": 15, "unit": "minute" }, "qris": { "acquirer": "gopay" } } → { "transaction_status": "pending", "qr_string": "00020101...", "actions": [ { "name": "generate-qr-code", "url": "..." } ] } <?php // notifikasi (HTTP notification URL) $n = json_decode(file_get_contents('php://input'), true); $expected = hash('sha512', $n['order_id'] . $n['status_code'] . $n['gross_amount'] . getenv('MIDTRANS_SERVER_KEY')); if (!hash_equals($expected, $n['signature_key'] ?? '')) { http_response_code(401); exit; } match ($n['transaction_status']) { 'settlement' => markPaid($n['order_id'], $n), // QRIS lunas 'expire', 'cancel', 'deny' => markExpired($n['order_id']), default => null, };
x-callback-token.POST https://api.xendit.co/qr_codes
Authorization: Basic base64(SECRET_KEY + ":")
api-version: 2022-07-31
Content-Type: application/json
{
"reference_id": "DM-1028",
"type": "DYNAMIC",
"currency": "IDR",
"amount": 43000,
"expires_at": "2026-10-17T13:15:00+07:00"
}
→ { "id": "qr_...", "reference_id": "DM-1028", "qr_string": "00020101...", "status": "ACTIVE" }
<?php // callback pembayaran QR
if (!hash_equals(getenv('XENDIT_CALLBACK_TOKEN'), $_SERVER['HTTP_X_CALLBACK_TOKEN'] ?? '')) {
http_response_code(401); exit;
}
$cb = json_decode(file_get_contents('php://input'), true);
// cocokkan reference_id & amount dengan DB, lalu markPaid() secara idempoten
<?php $va = getenv('IPAYMU_VA'); $apiKey = getenv('IPAYMU_API_KEY'); $body = json_encode([ 'name' => 'Pelanggan WhatsApp', 'amount' => 43000, 'referenceId' => 'DM-1028', 'paymentMethod' => 'qris', 'paymentChannel' => 'qris', 'notifyUrl' => 'https://api.contoh-toko.id/webhook/ipaymu', // + field kontak lain bila diwajibkan (cek dokumentasi) ]); $stringToSign = 'POST:' . $va . ':' . strtolower(hash('sha256', $body)) . ':' . $apiKey; $headers = [ 'Content-Type: application/json', 'va: ' . $va, 'signature: ' . hash_hmac('sha256', $stringToSign, $apiKey), 'timestamp: ' . date('YmdHis'), ]; // POST https://sandbox.ipaymu.com/api/v2/payment/direct // Saat notifyUrl dipanggil: jangan percaya isi callback mentah, // konfirmasi status ke API cek transaksi iPaymu sebelum markPaid().
<?php interface PaymentGateway { /** @return array{qr_string:string, pay_url:?string, expires_at:string, provider_ref:string} */ public function createQris(string $orderId, int $amount, int $ttlMinutes): array; public function verifyNotification(array $headers, string $rawBody): bool; /** @return 'PAID'|'PENDING'|'EXPIRED'|'FAILED' */ public function fetchStatus(string $orderId): string; } final class MidtransGateway implements PaymentGateway { /* ... */ } final class XenditGateway implements PaymentGateway { /* ... */ } final class IpaymuGateway implements PaymentGateway { /* ... */ } // Pilih lewat konfigurasi, bukan kode: PAYMENT_PROVIDER=midtrans|xendit|ipaymu $pg = match (getenv('PAYMENT_PROVIDER')) { 'xendit' => new XenditGateway(), 'ipaymu' => new IpaymuGateway(), default => new MidtransGateway(), };
- Penyedia PG adalah pemroses data: minta DPA, cek izin PJP BI dan sertifikasi keamanannya. (A.5.19–A.5.22)
- Kirim data pembeli seminimal mungkin. Aplikasi ini tidak pernah menyimpan data kartu/rekening; QRIS dibayar di aplikasi bank/e-wallet pembeli.
- Server Key / Secret Key / callback token hanya di server (secret manager), dengan kunci sandbox & produksi terpisah dan dirotasi. (A.5.17, A.8.24, A.8.31)
- Status lunas hanya dari notifikasi terverifikasi + cek status, tidak pernah dari parameter URL/halaman pembeli. (A.8.26)
- Log transaksi tanpa data pribadi mentah, dan simpan bukti settlement untuk audit. (A.8.11, A.8.15)
8Integrasi ke POS di pasaran (Accurate, Moka, majoo, dll.)
Tab Pesanan (POS) dan Inventori di mockup bisa diganti atau disambungkan ke POS/akuntansi yang sudah dipakai owner, sehingga stok, harga, dan penjualan WhatsApp tercatat di satu tempat.
Tiga pola integrasi
A. POS jadi sumber data utama
Harga & stok diedit di POS, lalu backend menyalinnya ke katalog WhatsApp. Pesanan WA yang sudah dibayar dikirim ke POS sebagai penjualan. Paling disarankan bila owner sudah memakai POS.
B. POS sendiri + kirim ke akuntansi
Dashboard seperti di mockup jadi POS-nya, lalu ringkasan penjualan dikirim ke Accurate / Jurnal untuk pembukuan dan pajak.
C. POS tanpa API
Ekspor/impor CSV terjadwal atau input manual. Murah, tetapi rawan selisih stok. Hanya cocok untuk volume kecil, sebagai solusi sementara.
Peta POS & akuntansi populer di Indonesia
| Produk | Jenis | Akses API* | Cocok untuk | Yang diintegrasikan |
|---|---|---|---|---|
| Accurate Online (+ Accurate POS) | Akuntansi & persediaan, POS kasir | Publik OAuth 2.0 untuk aplikasi pihak ketiga; daftar di portal developer Accurate | UKM yang butuh pembukuan, stok gudang, laporan pajak | Barang (item), pelanggan, faktur penjualan, penerimaan penjualan |
| Mekari Jurnal | Akuntansi & persediaan | Publik lewat Mekari Developer (autentikasi HMAC) | Pembukuan online, multi-cabang | Produk, faktur penjualan, pembayaran |
| Loyverse | POS kasir (gratis untuk fitur dasar) | Publik access token + webhook | UKM yang mau mulai cepat & murah | Item/varian, stok, struk (receipt), webhook perubahan stok |
| Odoo POS | ERP open source | Publik External API JSON-RPC / XML-RPC | Butuh kustomisasi penuh, ada developer | Produk, stok, pesanan, akuntansi |
| Moka POS | POS F&B & ritel | Mitra aplikasi terhubung lewat program partner | Kafe/resto yang sudah memakai Moka | Item, stok, transaksi (tergantung izin mitra) |
| majoo | POS + back-office UMKM | Mitra / konfirmasi | UMKM multi-outlet | Konfirmasi ke tim kemitraan majoo |
| Pawoon | POS F&B & ritel | Mitra / konfirmasi | Outlet kecil–menengah | Konfirmasi ke tim kemitraan Pawoon |
| iSeller | POS omnichannel | Tergantung paket | Toko dengan banyak kanal online | Produk, stok, pesanan |
| Olsera, ESB, Qasir, dll. | POS | Konfirmasi | — | Tanyakan dokumentasi API, sandbox, dan biaya ke vendor |
Pemetaan data pesanan WhatsApp → POS
| Data di aplikasi WA | Accurate Online | Loyverse | Tips |
|---|---|---|---|
SKU produk (product_retailer_id, mis. SN03) | Kode barang (itemNo) | variant_id (dipetakan dari SKU) | Samakan SKU katalog WA dengan kode barang di POS sejak awal. |
| Paket Hemat (3 tahu isi + es teh) | Barang paket/grup, atau barang jadi + resep | Item dengan komponen (composite) | Pastikan stok komponen ikut terpotong. |
| Pelanggan | Pelanggan umum, mis. WA-ONLINE | Opsional | Minimisasi data: tidak perlu kirim nomor HP ke POS bila tidak dibutuhkan. |
| Ongkir & biaya kemasan | Barang non-persediaan ONGKIR, KEMASAN | Item non-stok / catatan | Pisahkan dari omzet makanan agar laporan margin akurat. |
| Pembayaran QRIS | Penerimaan penjualan ke akun Kas/Bank “QRIS – Payment Gateway” | Tipe pembayaran “QRIS” | Biaya MDR dicatat saat dana settlement masuk. |
No. pesanan DM-1028 & ref QRIS | Keterangan / nomor referensi faktur | Catatan struk | Dipakai sebagai kunci idempotensi dan untuk rekonsiliasi. |
| Outlet | Cabang & gudang | store_id | Penting bila punya lebih dari satu dapur. |
Alur sinkronisasi
- Master data POS → WhatsApp: ambil daftar barang, harga, dan stok tersedia dari POS, lalu update katalog WA. Pakai webhook bila POS menyediakan; bila tidak, polling tiap 1–5 menit.
POS: list items/stock→ WA Catalog batch update - Validasi stok saat checkout: cek ulang stok di POS sebelum membuat tagihan QRIS, untuk mencegah overselling dengan penjualan di kasir.
POS: get stock - Pesanan dibayar → catat penjualan di POS: setelah webhook QRIS valid, buat faktur/struk beserta pembayarannya. Gunakan pola outbox (antrean + retry), supaya POS yang sedang gangguan tidak menggagalkan pesanan.
→ POS: create sales invoice / receipt→ POS: payment - Simpan ID dokumen POS (mis. nomor faktur) di tabel pesanan, sehingga pengiriman ulang tidak membuat faktur ganda.
orders.pos_doc_id - Rekonsiliasi harian: cocokkan laporan settlement payment gateway, faktur di POS, dan pesanan WA. Selisih dikirim sebagai notifikasi ke owner.
PG settlement reportPOS sales report
Contoh panggilan API
# 1) Tukar authorization code → access token (dijalankan di server) POST https://account.accurate.id/oauth/token Authorization: Basic base64(CLIENT_ID:CLIENT_SECRET) grant_type=authorization_code&code={CODE}&redirect_uri={REDIRECT_URI} # 2) Buka database Accurate milik owner → dapat host & session GET https://account.accurate.id/api/open-db.do?id={DB_ID} Authorization: Bearer {ACCESS_TOKEN} → { "host": "https://{server}.accurate.id", "session": "{SESSION_ID}" } # 3) Simpan faktur penjualan untuk pesanan WA #DM-1028 POST {host}/accurate/api/sales-invoice/save.do Authorization: Bearer {ACCESS_TOKEN} X-Session-ID: {SESSION_ID} customerNo=WA-ONLINE transDate=17/10/2026 description=WhatsApp #DM-1028 · QRIS ref QRLMBZEA7TF4 detailItem[0].itemNo=SN03 detailItem[0].quantity=2 detailItem[0].unitPrice=4000 detailItem[1].itemNo=MN04 detailItem[1].quantity=1 detailItem[1].unitPrice=10000 detailItem[2].itemNo=PK01 detailItem[2].quantity=1 detailItem[2].unitPrice=9000 detailItem[3].itemNo=KEMASAN detailItem[3].quantity=1 detailItem[3].unitPrice=1000 detailItem[4].itemNo=ONGKIR detailItem[4].quantity=1 detailItem[4].unitPrice=15000 # 4) Catat penerimaan pembayaran QRIS (sales-receipt) ke akun "QRIS – Payment Gateway"
POST https://api.loyverse.com/v1.0/receipts
Authorization: Bearer {LOYVERSE_ACCESS_TOKEN}
Content-Type: application/json
{
"store_id": "{STORE_ID}",
"note": "WhatsApp #DM-1028 · QRIS ref QRLMBZEA7TF4",
"line_items": [
{ "variant_id": "{VARIANT_SN03}", "quantity": 2 },
{ "variant_id": "{VARIANT_MN04}", "quantity": 1 },
{ "variant_id": "{VARIANT_PK01}", "quantity": 1 }
],
"payments": [
{ "payment_type_id": "{PAYMENT_TYPE_QRIS}", "money_amount": 43000 }
]
}
# Stok POS → katalog WA: daftarkan webhook perubahan stok (inventory levels)
# lalu backend memperbarui ketersediaan item di katalog WhatsApp.
<?php // Dipanggil dari webhook QRIS yang tanda tangannya sudah valid function onPaymentSettled(PDO $db, string $orderId, array $pay): void { $db->beginTransaction(); $upd = $db->prepare("UPDATE orders SET status='PROCESSING', paid_ref=? WHERE id=? AND status='UNPAID'"); $upd->execute([$pay['ref'], $orderId]); if ($upd->rowCount() === 1) { // idempoten: webhook ganda diabaikan $db->prepare("INSERT INTO pos_outbox (order_id, action, attempts, next_run_at) VALUES (?, 'create_sale', 0, NOW())") ->execute([$orderId]); } $db->commit(); } // worker.php – dijalankan cron tiap menit foreach ($db->query("SELECT * FROM pos_outbox WHERE done=0 AND next_run_at <= NOW() LIMIT 20") as $job) { try { $docId = $posClient->createSale(loadOrder($db, $job['order_id'])); // Accurate / Loyverse / dll. $db->prepare("UPDATE orders SET pos_doc_id=? WHERE id=?")->execute([$docId, $job['order_id']]); $db->prepare("UPDATE pos_outbox SET done=1 WHERE id=?")->execute([$job['id']]); } catch (Throwable $e) { $n = $job['attempts'] + 1; // backoff: 1, 2, 4, 8 ... menit $db->prepare("UPDATE pos_outbox SET attempts=?, next_run_at=NOW() + INTERVAL ? MINUTE, last_error=? WHERE id=?") ->execute([$n, 2 ** min($n, 6), substr($e->getMessage(), 0, 250), $job['id']]); if ($n >= 5) notifyOwner("Sinkron POS gagal untuk " . $job['order_id']); } }
Memilih jalur integrasi
Sudah pakai Accurate / Jurnal
Integrasikan langsung lewat API resminya. Pesanan WA otomatis menjadi faktur, stok dan laporan pajak tetap di satu sistem.
Belum punya POS, anggaran minim
Pakai POS dengan API publik (mis. Loyverse), atau jadikan dashboard aplikasi ini POS-nya, lalu tambahkan akuntansi belakangan.
Sudah pakai Moka / majoo / Pawoon
Hubungi tim kemitraan vendor untuk akses API. Selama menunggu, pakai pola C (ekspor/impor) atau input manual dari dashboard.
- Kirim data pelanggan seminimal mungkin (pelanggan umum
WA-ONLINE; nomor HP tidak perlu dikirim ke POS). - Token OAuth/API POS disimpan terenkripsi di server, dengan izin (scope) seminimal mungkin, dan dicabut bila integrasi dihentikan. (A.5.15, A.5.17, A.8.24)
- Minta DPA, informasi lokasi data, dan sertifikasi keamanan vendor. Catat integrasi ini di daftar aset & pemasok. (A.5.9, A.5.20)
- Log sinkronisasi tanpa data pribadi mentah, dengan masking. (A.8.11, A.8.15)
9Syarat & biaya API resmi
Syarat
- Meta Business Portfolio (dulu Business Manager) yang terverifikasi, dengan dokumen legal usaha (misalnya NIB).
- Nomor telepon untuk API, dan nama tampilan yang disetujui Meta.
- Nomor yang sudah dipakai di aplikasi WhatsApp Business bisa disambungkan lewat fitur coexistence, bila tersedia untuk nomormu/BSP-mu.
- Server dengan HTTPS publik untuk webhook (hosting atau VPS; XAMPP lokal hanya untuk pengembangan).
- Template pesan untuk notifikasi di luar jendela 24 jam, disetujui Meta.
Biaya
- Meta menagih per pesan template yang terkirim, dengan tarif berbeda per kategori (marketing, utility, authentication) dan per negara.
- Balasan biasa di dalam jendela layanan 24 jam (setelah pembeli mengirim pesan) tidak dikenakan biaya. Alur order umumnya terjadi di dalam jendela ini.
- Cloud API langsung: tanpa biaya platform tambahan. Lewat BSP: ada biaya langganan, tapi penyiapan dan dashboard lebih mudah.
- Ditambah: MDR QRIS dari payment gateway, ongkir kurir, dan hosting server.
- Selalu cek tarif terbaru di halaman pricing resmi Meta (lihat referensi), karena tarifnya berubah berkala.
10Gateway WhatsApp tidak resmi
Platform ini tidak bisa bekerja di gateway WhatsApp tidak resmi (unofficial). Platform hanya berjalan di WhatsApp Business Platform resmi (Cloud API).
11Checklist keamanan & pelindungan data (implementasi resmi)
Memakai API resmi saja belum cukup. Implementasinya juga harus memenuhi kontrol berikut.
- Access token, app secret, kunci PG & kurir disimpan di secret manager / environment server, dirotasi berkala, tidak pernah di front-end atau repo. A.5.17, A.8.24
- Semua webhook (WhatsApp, PG, kurir) diverifikasi tanda tangannya dan diproses idempoten. A.8.26
- Seluruh lalu lintas melalui HTTPS (TLS 1.2+); database & backup terenkripsi. A.8.24, A.8.13
- Dashboard owner dengan login + MFA dan peran (owner, kasir, dapur) sesuai kebutuhan. A.5.15, A.8.2, A.8.5
- Masking nomor HP & nama di dashboard dan log, alamat lengkap hanya untuk peran yang perlu. A.8.11
- Log audit tersentralisasi, dipantau, tanpa data pribadi mentah. A.8.15, A.8.16
- Minimisasi & retensi: hanya simpan data yang perlu untuk pesanan; hapus/anonimkan setelah periode retensi. A.8.10, UU PDP
- Pemberitahuan privasi di pesan pertama dan link kebijakan privasi, beserta cara pembeli meminta akses/penghapusan data. A.5.34, UU PDP
- Perjanjian pemrosesan data dengan BSP, payment gateway, kurir & hosting; tinjau sertifikasi keamanannya. A.5.19–A.5.22
- Prosedur insiden, termasuk notifikasi kegagalan pelindungan data ≤ 3×24 jam. A.5.24–A.5.26, UU PDP
- Secure coding, review, dan uji keamanan sebelum go-live. A.8.25, A.8.28, A.8.29
12Roadmap migrasi dari mockup ke produksi
Perkiraan untuk 1–2 developer. Durasi verifikasi bisnis & kerja sama mitra tergantung pihak terkait.
- Verifikasi Meta Business
- Nomor & nama tampilan
- Akun sandbox PG QRIS & kurir/agregator
- Kebijakan privasi
- Webhook WhatsApp
- DB pesanan & inventori, atau sambung ke POS (§8)
- Chatbot: tombol, list, lokasi
- Sinkron katalog
- QRIS dinamis + webhook
- Booking kurir & link lacak
- Template utility
- Outbox sinkron POS / Accurate
- Dashboard + login MFA
- Uji end-to-end di sandbox
- Uji keamanan & checklist §11
- Pilot terbatas
- Monitoring
Bagian mockup yang bisa langsung dipakai ulang: desain percakapan, struktur data menu/stok (assets/data.js), logika ongkir & status pesanan, serta tampilan dashboard. Bagian yang wajib dipindah ke server: pengiriman pesan, pembuatan tagihan, booking kurir, penyimpanan data pelanggan.
13FAQ
Apakah nomor WhatsApp Business yang sekarang bisa dipakai?
Bisa. Pilihannya: pindahkan nomor ke API (aplikasi WhatsApp Business di HP tidak bisa dipakai lagi untuk nomor itu), atau gunakan fitur coexistence agar aplikasi dan API berjalan bersamaan, bila tersedia untuk nomor/BSP-mu.
Harus lewat BSP atau langsung ke Meta?
Keduanya resmi. Langsung ke Cloud API lebih murah dan fleksibel bila ada developer. BSP lebih cepat untuk tim non-teknis dan biasanya menyediakan inbox bersama, tetapi ada biaya langganan. Pastikan BSP menandatangani perjanjian pemrosesan data.
Kenapa pembayaran tidak langsung di dalam WhatsApp?
Fitur pembayaran native WhatsApp belum tersedia untuk Indonesia. Pola yang umum dipakai: tombol link ke halaman QRIS dinamis dari payment gateway, lalu konfirmasi otomatis lewat webhook.
Bagaimana kalau pembeli baru membayar besok?
Tagihan QRIS sebaiknya kedaluwarsa (misalnya 15 menit) dan stok dilepas lagi. Bila perlu menghubungi pembeli setelah 24 jam, gunakan template yang sudah disetujui Meta.
Boleh pakai gateway tidak resmi dulu, nanti pindah ke resmi?
Tidak. Platform ini tidak bisa bekerja di gateway WhatsApp tidak resmi. Untuk percobaan, pakai nomor tes gratis dari Cloud API.
Kasir offline juga menjual stok yang sama. Bagaimana mencegah stok minus?
Jadikan POS sumber stok utama (pola A di §8), cek ulang stok di POS sebelum membuat tagihan QRIS, dan sisakan stok cadangan kecil khusus kanal online untuk item yang cepat habis.
Bisakah tetap memakai Accurate kalau POS kasirnya merek lain?
Bisa. Aplikasi WA mengirim penjualan ke POS (stok outlet) dan ringkasan/penerimaan ke Accurate (pembukuan), atau POS kasir yang sudah terhubung ke Accurate meneruskannya. Hindari mencatat penjualan yang sama dua kali di Accurate.
Apakah makanan & minuman boleh dijual lewat katalog WhatsApp?
Ya, kategori ini diizinkan dalam WhatsApp Commerce Policy. Yang dilarang antara lain alkohol, obat-obatan tertentu, dan produk ilegal.
14Referensi resmi
- WhatsApp Cloud API: dokumentasi developer Meta
- WhatsApp Business Platform: pricing
- WhatsApp Business Messaging Policy & Commerce Policy
- WhatsApp Terms of Service
- ISO/IEC 27001:2022: Information security management systems
- Undang-Undang Republik Indonesia No. 27 Tahun 2022 tentang Pelindungan Data Pribadi
💬 Ingin punya platform chatbot WhatsApp untuk usahamu?
Untuk business owner yang ingin menerima pesanan otomatis lewat WhatsApp seperti demo ini, hubungi Kukuh TW untuk konsultasi.
- Chatbot order di WhatsApp Business Platform resmi
- Pembayaran QRIS & pengiriman GoSend / GrabExpress
- Terhubung ke POS / akuntansi (Accurate, dll.)
- Dirancang sesuai prinsip ISO/IEC 27001 & UU PDP