BisnisUKM Connect Panduan integrasi produksi
📝 Pesan Chatbot ← Kembali ke mockup demo

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.

WhatsApp Business Platform (Cloud API)QRIS dinamisGoSend / GrabExpressISO/IEC 27001:2022UU No. 27/2022 (PDP)
💬 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.

📱 Pembeli aplikasi WhatsApp Meta WhatsApp Cloud API katalog · template Server Backend PHP / Laravel / Node • webhook receiver • order & chatbot engine • secret manager • audit log (masked) 🗄️ POS & Database pesanan · inventori · lokasi toko 💳 Payment Gateway QRIS dinamis · berizin BI 🛵 Kurir / Agregator GoSend · GrabExpress 🗺️ Maps / Routing API jarak rute · geocoding 🧾 Dashboard Owner login + MFA · RBAC HTTPS webhook REST API ⇄ webhook bertanda tangan

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 mockupFitur WhatsApp Business PlatformCatatan / batasan
Sapaan + tombol Lihat Katalog / Paket Hemat / LokasiInteractive reply buttonsMaks. 3 tombol per pesan, judul tombol maks. 20 karakter.
Pilih kurir (GoSend / GrabExpress)Interactive list messageMaks. 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 orderProduk harus mematuhi WhatsApp Commerce Policy (makanan & minuman diperbolehkan).
Edit harga, stok, tampil/sembunyi di dashboardCatalog API (Commerce) untuk update batchStok riil tetap dihitung di POS kamu; katalog hanya menampilkan ketersediaan.
Kirim lokasi / alamat kirimLocation 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 buttonFitur bayar langsung di WhatsApp belum tersedia di Indonesia, jadi pembayaran lewat halaman payment gateway.
“Pembayaran berhasil”, “Driver ditemukan”, link lacakPesan bebas (dalam jendela 24 jam) atau template utilityDi luar 24 jam sejak pesan terakhir pembeli, hanya template yang disetujui Meta yang boleh dikirim.
Rating ⭐ & “Pesan lagi”Reply buttonsTidak perlu template karena dikirim di dalam jendela 24 jam.
Log integrasiWebhook 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.

  1. Pembeli menyapa, lalu Meta mengirim webhook ke server, dan server membalas dengan tombol.
    ← webhook messages[type=text]→ POST /{phone_number_id}/messages (interactive:button)
  2. Pembeli membuka katalog dan checkout, lalu server menerima pesanan, memvalidasi stok di POS, dan membuat draf order.
    ← webhook messages[type=order]POS: reserve stock
  3. Server meminta lokasi, pembeli membagikan lokasi atau mengisi form Flows.
    → interactive:location_request_message← webhook messages[type=location]
  4. Hitung jarak dan ongkir: jarak rute dari koordinat toko ke pembeli, lalu tarif dari kurir/agregator.
    → Maps routing API→ Kurir: estimate/rates
  5. Pembeli memilih kurir dari list message.
    → interactive:list← webhook interactive.list_reply
  6. Buat tagihan QRIS dinamis (nominal pas, berlaku misalnya 15 menit), lalu kirim ringkasan + tombol bayar.
    → PG: create QRIS charge→ interactive:cta_url
  7. 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
  8. Booking kurir: kurir menugaskan driver dan mengirim link lacak, lalu server meneruskannya ke pembeli.
    → Kurir: create delivery← webhook driver.assigned→ messages (link lacak)
  9. 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.

Sapaan dengan 3 tombol. Header: 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" } }
      ]
    }
  }
}
Daftar kurir dengan ongkir hasil hitung jarak. Jawaban pembeli masuk sebagai 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" }
        ]
      }]
    }
  }
}
Isi webhook saat pembeli mengirim keranjang dari katalog (dipotong ke bagian penting). 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" }
        ]
      }
    }]
  }}]}]
}
Menampilkan tombol “Kirim lokasi” di chat pembeli. Balasan masuk sebagai pesan bertipe 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" }
  }
}
Tombol yang membuka halaman QRIS dari payment gateway. URL berisi token sekali pakai, bukan data pribadi.
{
  "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..." }
    }
  }
}
Template kategori utility (harus disetujui Meta dulu) untuk notifikasi di luar jendela 24 jam, misalnya link lacak driver.
{
  "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" }
      ]
    }]
  }
}
Penerima webhook minimal (PHP, cocok untuk XAMPP). Verifikasi token saat pendaftaran, cek tanda tangan 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

PenyediaProduk / API untuk QRISAutentikasiVerifikasi notifikasiCatatan
MidtransCore 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.
XenditQR Codes API (type: DYNAMIC) atau Payment Request APIBasic auth (Secret Key)Header x-callback-token dicocokkan dengan token di dashboardDokumentasi developer kuat, ada fitur disbursement.
iPaymuAPI v2 direct payment (paymentMethod: qris)Header va, signature (HMAC-SHA256), timestampCallback ke notifyUrl; konfirmasi ulang lewat API cek transaksiPopuler di UMKM; cek field wajib tiap metode.
DOKUCheckout / Direct API (QRIS)Client-Id + Signature HMAC; mendukung standar SNAP BISignature pada header notifikasiPemain lama, banyak metode pembayaran.
DuitkuAPI / POP checkout (QRIS)Merchant code + signatureSignature pada callbackBiaya bersaing untuk UMKM.
Faspay, Flip for Business, OY! Indonesia, Tripay, Nicepay, dll.BervariasiBervariasiBervariasiKonfirmasi izin PJP, dukungan QRIS dinamis, dan biaya langsung ke penyedia.
Biaya & ketentuan berubah, jadi verifikasi sebelum memilih MDR QRIS ditetapkan Bank Indonesia per kategori merchant (ketentuan yang kami ketahui: 0% untuk usaha mikro pada transaksi s.d. Rp500.000, 0,7% untuk kategori reguler). Penyedia dapat menambah biaya layanan. Cek ketentuan BI terbaru dan halaman harga tiap penyedia. Nama endpoint/field di bawah diringkas; cocokkan dengan dokumentasi resmi masing-masing.

Alur teknis yang sama untuk semua penyedia

  1. Buat tagihan QRIS dengan order_id unik (mis. DM-1028), nominal pas, dan masa berlaku 15 menit.
    → PG: create charge / QR
  2. Tampilkan QR: render qr_string menjadi 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
  3. Terima notifikasi di endpoint HTTPS, lalu verifikasi tanda tangan/token. Notifikasi tanpa tanda tangan yang valid ditolak.
    ← PG webhook
  4. Konfirmasi ulang status ke API penyedia (GET status), lalu cocokkan nominal & order_id dengan database.
    → PG: get status
  5. Update idempoten: ubah status UNPAID → PROCESSING hanya sekali, potong stok, dan antrekan sinkron POS (§8). Status expire/cancel mengembalikan reservasi stok.
    orders.statuspos_outbox
  6. Rekonsiliasi laporan settlement harian dengan pesanan & faktur POS.
    PG settlement report

Contoh kode

Core API, charge QRIS + verifikasi notifikasi. Sandbox: 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,
};
QR Codes API dengan QR dinamis. Callback divalidasi dengan header 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
API v2 iPaymu memakai signature HMAC-SHA256 atas isi request. Isi data pembeli seminimal yang diwajibkan penyedia.
<?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().
Satu antarmuka untuk semua penyedia, sehingga pindah dari Midtrans ke Xendit/iPaymu cukup mengganti adapter.
<?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(),
};
🔒 Kepatuhan saat integrasi payment gateway
  • 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

ProdukJenisAkses API*Cocok untukYang diintegrasikan
Accurate Online (+ Accurate POS)Akuntansi & persediaan, POS kasirPublik
OAuth 2.0 untuk aplikasi pihak ketiga; daftar di portal developer Accurate
UKM yang butuh pembukuan, stok gudang, laporan pajakBarang (item), pelanggan, faktur penjualan, penerimaan penjualan
Mekari JurnalAkuntansi & persediaanPublik
lewat Mekari Developer (autentikasi HMAC)
Pembukuan online, multi-cabangProduk, faktur penjualan, pembayaran
LoyversePOS kasir (gratis untuk fitur dasar)Publik
access token + webhook
UKM yang mau mulai cepat & murahItem/varian, stok, struk (receipt), webhook perubahan stok
Odoo POSERP open sourcePublik
External API JSON-RPC / XML-RPC
Butuh kustomisasi penuh, ada developerProduk, stok, pesanan, akuntansi
Moka POSPOS F&B & ritelMitra
aplikasi terhubung lewat program partner
Kafe/resto yang sudah memakai MokaItem, stok, transaksi (tergantung izin mitra)
majooPOS + back-office UMKMMitra / konfirmasiUMKM multi-outletKonfirmasi ke tim kemitraan majoo
PawoonPOS F&B & ritelMitra / konfirmasiOutlet kecil–menengahKonfirmasi ke tim kemitraan Pawoon
iSellerPOS omnichannelTergantung paketToko dengan banyak kanal onlineProduk, stok, pesanan
Olsera, ESB, Qasir, dll.POSKonfirmasi—Tanyakan dokumentasi API, sandbox, dan biaya ke vendor
* Status API wajib dikonfirmasi ke vendor sebelum memilih Ketersediaan API, paket berlangganan yang diperlukan, biaya, batas request (rate limit), sandbox, dan program kemitraan dapat berubah. Minta ke vendor: dokumentasi API resmi, akun sandbox, perjanjian pemrosesan data (DPA), dan informasi lokasi penyimpanan data.

Pemetaan data pesanan WhatsApp → POS

Data di aplikasi WAAccurate OnlineLoyverseTips
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 + resepItem dengan komponen (composite)Pastikan stok komponen ikut terpotong.
PelangganPelanggan umum, mis. WA-ONLINEOpsionalMinimisasi data: tidak perlu kirim nomor HP ke POS bila tidak dibutuhkan.
Ongkir & biaya kemasanBarang non-persediaan ONGKIR, KEMASANItem non-stok / catatanPisahkan dari omzet makanan agar laporan margin akurat.
Pembayaran QRISPenerimaan penjualan ke akun Kas/Bank “QRIS – Payment Gateway”Tipe pembayaran “QRIS”Biaya MDR dicatat saat dana settlement masuk.
No. pesanan DM-1028 & ref QRISKeterangan / nomor referensi fakturCatatan strukDipakai sebagai kunci idempotensi dan untuk rekonsiliasi.
OutletCabang & gudangstore_idPenting bila punya lebih dari satu dapur.

Alur sinkronisasi

  1. 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
  2. Validasi stok saat checkout: cek ulang stok di POS sebelum membuat tagihan QRIS, untuk mencegah overselling dengan penjualan di kasir.
    POS: get stock
  3. 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
  4. Simpan ID dokumen POS (mis. nomor faktur) di tabel pesanan, sehingga pengiriman ulang tidak membuat faktur ganda.
    orders.pos_doc_id
  5. 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

Alur OAuth 2.0 → buka database owner → simpan faktur penjualan. Nama field diringkas; cocokkan dengan dokumentasi API Accurate terbaru (Accurate juga menyediakan metode token API untuk integrasi internal).
# 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"
Membuat struk penjualan dari pesanan WA. ID toko, varian, dan tipe pembayaran diambil sekali dari API Loyverse lalu disimpan sebagai pemetaan. Verifikasi field dengan dokumentasi API Loyverse.
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.
Pesanan dan antrean ke POS ditulis dalam satu transaksi database, lalu worker (cron tiap menit) mengirim ke POS dengan retry. Pesanan tidak hilang walau POS sedang down.
<?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.

🔒 Kepatuhan saat menyambung ke POS / akuntansi Vendor POS adalah pemroses data, jadi berlaku ISO/IEC 27001:2022 A.5.19–A.5.22 (keamanan pemasok) dan UU PDP:
  • 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.

Fase 1 · Persiapan± 1–2 minggu
  • Verifikasi Meta Business
  • Nomor & nama tampilan
  • Akun sandbox PG QRIS & kurir/agregator
  • Kebijakan privasi
Fase 2 · Backend inti± 2–3 minggu
  • Webhook WhatsApp
  • DB pesanan & inventori, atau sambung ke POS (§8)
  • Chatbot: tombol, list, lokasi
  • Sinkron katalog
Fase 3 · Pembayaran & kurir± 2 minggu
  • QRIS dinamis + webhook
  • Booking kurir & link lacak
  • Template utility
  • Outbox sinkron POS / Accurate
  • Dashboard + login MFA
Fase 4 · Uji & go-live± 1–2 minggu
  • 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

Catatan Batasan teknis, ketersediaan fitur, dan tarif WhatsApp dapat berubah. Verifikasi ke dokumentasi resmi sebelum implementasi. Panduan ini bukan nasihat hukum; konsultasikan aspek UU PDP dengan tim legal/kepatuhan.

💬 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

← Kembali ke mockup demo