Dokumentasi REST API & Panduan Aplikasi Kasir Offline-First
Selamat datang di dokumentasi resmi Eza POS REST API. Dirancang khusus bagi pengembang (Android Native Java/Kotlin, Flutter, React Native, mau pun Web App) untuk membangun aplikasi kasir Offline-First yang tangguh, super cepat, dan tidak terganggu oleh koneksi internet yang lambat.
https://pos.ezapedia.my.id/api/pos_api.php
X-API-KEY: {username_kasir}
Konsep & Tatacara Membuat Aplikasi POS Offline-First
Panduan arsitektur bagaimana aplikasi berjalan secara offline tanpa lag internet.
Di aplikasi Android/Mobile, kasir tidak perlu menghafal token rumit. Pada halaman awal cukup sediakan input Username Kasir. Username ini langsung menjadi API Key untuk mengambil semua hak akses dan data toko yang bersangkutan.
Saat kasir klik "Buka Shift" dan memasukkan modal awal, aplikasi secara real-time memanggil endpoint action=catalog untuk menarik seluruh produk, stok aktif, harga regular & reseller, deskripsi produk, voucher, dan metode pembayaran, lalu disimpan ke database lokal HP (SQLite/Room).
Semua aktivitas kasir (tambah item ke cart, input note kecil pada produk, potong stok lokal, hitung diskon voucher, pembayaran cash/tunai, serta cetak struk Bluetooth thermal) diproses langsung dari SQLite HP. Kasir tidak akan merasakan lag sama sekali meskipun sinyal internet drop.
Hanya 3 proses yang membutuhkan internet:
• Pembayaran QRIS Eza Pedia (generate QRIS & cek status live).
• Notifikasi Lonceng Pesanan Self-Order pelanggan masuk.
• Sync Background transaksi offline ke cloud dan monitoring owner toko.
Meskipun aplikasi berjalan offline, kasir tetap dapat menambah stok masuk barang langsung melalui menu pengaturan aplikasi (seperti fitur di menu Kasir Online) dengan memanggil endpoint action=update_stock saat perangkat terhubung internet.
Autentikasi Berbasis Username Kasir (API Key)
Bagaimana cara mengirim kredensial pada setiap permintaan API.
Untuk mempermudah integrasi pihak ketiga dan developer APK Android, sistem ini menggunakan Username Kasir sebagai API Key utama. Anda dapat mengirimkan username kasir melalui salah satu metode berikut:
X-API-KEY: kasir1 atau X-Cashier-Username: kasir1
https://pos.ezapedia.my.id/api/pos_api.php?action=catalog&api_key=kasir1
Authorization: Bearer kasir1
Panduan Pengaturan Printer Kasir Offline (Direct Bluetooth ESC/POS)
Standar pencetakan nota struk 100% lokal dari HP/Tablet kasir tanpa perantara web server.
Pada aplikasi kasir offline native (Android Kotlin / Java / Flutter / React Native), proses cetak struk nota WAJIB dieksekusi secara lokal (offline) dari smartphone/tablet langsung ke printer thermal thermal Bluetooth (atau kabel USB OTG) menggunakan protokol komunikasi byte ESC/POS.
⚠️ Aplikasi TIDAK BOLEH memanggil server web untuk melakukan perintah cetak, agar saat toko mati lampu atau internet padam, kasir tetap dapat mencetak struk belanja secara instan (kecepatan cetak < 100 milidetik).
Saat buka shift, aplikasi menarik pengaturan printer dari endpoint action=printer_settings (Nama Printer Bluetooth tersimpan, ukuran kertas 58mm/80mm, nama toko, alamat, footer struk).
Aplikasi Android membuka koneksi Bluetooth SPP socket (UUID: 00001101-0000-1000-8000-00805F9B34FB) ke printer thermal yang telah di-pairing di HP kasir.
Aplikasi menyusun teks nota dalam memori HP, menghitung perataan kolom, mengonversinya menjadi byte array ESC/POS, lalu mengirimkannya via OutputStream.write().
| Fungsi Cetak | Kode Hex ESC/POS | Deskripsi & Penggunaan |
|---|---|---|
| Initialize Printer | 1B 40 | Wajib dikirim di awal untuk mereset buffer dan font default |
| Rata Tengah (Center) | 1B 61 01 | Untuk Judul Toko, Alamat, dan Ucapan Terima Kasih |
| Rata Kiri (Left) | 1B 61 00 | Untuk nama barang dan rincian transaksi |
| Rata Kanan (Right) | 1B 61 02 | Untuk subtotal harga dan nominal kembalian |
| Bold ON / OFF | 1B 45 01 / 1B 45 00 | Huruf tebal pada nama toko dan Total Belanja |
| Feed Baris Baru | 0A | Baris baru (Enter) |
| Potong Kertas (Auto Cut) | 1D 56 42 00 | Memotong kertas struk secara otomatis di akhir nota |
| Buka Laci Uang (Drawer) | 1B 70 00 19 FA | Membuka laci kasir (Cash Drawer RJ11) otomatis setelah bayar |
// 1. Hubungkan ke Bluetooth Printer SPP
val device = bluetoothAdapter.getRemoteDevice(printerMacAddress)
val uuid = UUID.fromString("00001101-0000-1000-8000-00805F9B34FB")
val socket = device.createRfcommSocketToServiceRecord(uuid)
socket.connect()
val out = socket.outputStream
// 2. Kirim Header (Reset, Center, Bold)
out.write(byteArrayOf(0x1B, 0x40)) // Init
out.write(byteArrayOf(0x1B, 0x61, 0x01)) // Center
out.write(byteArrayOf(0x1B, 0x45, 0x01)) // Bold ON
out.write("EZA COFFEE & ROASTERY\n".toByteArray())
out.write(byteArrayOf(0x1B, 0x45, 0x00)) // Bold OFF
out.write("Jl. Merdeka No. 12, Jakarta\n\n".toByteArray())
// 3. Garis Pembatas (32 karakter untuk 58mm)
out.write(byteArrayOf(0x1B, 0x61, 0x00)) // Left
out.write("--------------------------------\n".toByteArray())
// 4. Rincian Item Barang
out.write("Kopi Susu Gula Aren\n".toByteArray())
out.write(String.format("%-16s %15s\n", "2 x 18.000", "36.000").toByteArray())
out.write(" * Note: Es sedikit\n".toByteArray())
// 5. Total Belanja & Cut Kertas
out.write("--------------------------------\n".toByteArray())
out.write(String.format("%-16s %15s\n", "TOTAL", "Rp 36.000").toByteArray())
out.write("\n\n\n".toByteArray())
out.write(byteArrayOf(0x1D, 0x56, 0x42, 0x00)) // Auto Cut
out.flush()
socket.close()
Panduan Desain Tampilan UI/UX & Alur Fitur Kasir Offline
Panduan lengkap tata cara implementasi seluruh menu kasir online agar tersedia di aplikasi offline.
Buat form sederhana yang meminta Username Kasir saja. Begitu kasir menekan tombol "Masuk", aplikasi memverifikasi akun ke API (action=profile&api_key={username}). Jika valid, simpan username tersebut di local storage sebagai API Key permanen perangkat.
Tampilkan modal/halaman Buka Shift dengan input modal kas awal (kas kecil). Saat tombol "Buka Shift" ditekan, panggil action=open_shift dan langsung tarik seluruh katalog (action=catalog). Seluruh produk, stok, metode pembayaran, voucher, profil printer, dan pesanan ditahan langsung disimpan ke SQLite lokal.
Layout 2 kolom: Kiri berupa grid katalog produk dengan filter kategori horizontal & tombol scan barcode kamera; Kanan berupa keranjang belanja (list item, qty +/- stepper, subtotal, tombol diskon voucher, tombol modal bayar).
Sediakan tombol "Tunda Pesanan" di bawah keranjang belanja. Jika antrian pelanggan tertunda, kasir memasukkan nama pesanan (misal: "Meja 4 / Pak Anton"), lalu keranjang disimpan ke tabel SQLite held_orders (dan sinkron ke action=save_held_order). Kasir dapat melanjutkan pesanan kapan saja melalui menu daftar pesanan ditahan (action=resume_held_order).
Sebelum Bayar: Tombol "Kosongkan Keranjang" untuk menghapus seluruh item yang salah input.
Setelah Bayar: Pada menu Riwayat Transaksi, kasir memiliki tombol "Batal / Refund" untuk mengajukan pembatalan transaksi dengan alasan (action=cancel_sale / action=request_refund). Admin toko otomatis menerima notifikasi WhatsApp permohonan refund.
Sediakan tombol Buku Telepon di header atas aplikasi. Kasir dapat mencari kontak pelanggan lama, memilih pelanggan untuk otomatis mengisi data pembeli di struk, atau menambahkan kontak pelanggan baru langsung dari aplikasi kasir (action=add_contact).
Kasir dapat membuka menu "Kelola Stok" untuk melihat sisa stok produk. Saat ada pasokan baru tiba dari supplier/gudang, kasir dapat langsung menambah jumlah stok barang masuk melalui endpoint action=update_stock (mode add atau set).
Pilihan metode pembayaran dipisahkan secara cerdas:
• Tunai / Transfer Manual / QRIS Statis / EDC: Diproses 100% offline di SQLite lokal dan langsung mencetak struk.
• QRIS Eza Pedia Gateway (Online): Aplikasi memanggil action=create_qris, menampilkan QR dinamis di layar HP kasir, dan melakukan polling action=check_qris_status sampai lunas.
Spesifikasi Endpoint REST API
Daftar endpoint lengkap untuk integrasi sinkronisasi, kasir, dan pelaporan.
?action=catalog
Mengambil seluruh data kategori, produk yang diizinkan untuk kasir ini, stok terkini, deskripsi produk, voucher yang berlaku, metode pembayaran toko, serta profil toko. Digunakan saat pertama kali buka aplikasi atau saat Buka Shift.
X-API-KEY: username_kasir
{
"status": "success",
"success": true,
"message": "Data katalog lengkap, stok, dan pengaturan berhasil disinkronkan.",
"data": {
"sync_timestamp": 1729938000,
"categories": [
{ "id": 1, "name": "Makanan Utama" },
{ "id": 2, "name": "Minuman Segar" }
],
"products": [
{
"id": 101,
"name": "Kopi Susu Gula Aren",
"description": "Espresso robusta dengan susu segar dan gula aren asli",
"category_id": 2,
"category_name": "Minuman Segar",
"base_price": 8000,
"regular_price": 18000,
"reseller_price": 15000,
"stock_quantity": 45,
"image": "kopi.jpg",
"image_url": "https://domain.com/uploads/kopi.jpg",
"type": "physical",
"is_pack": false
}
],
"vouchers": [
{
"id": 5,
"code": "DISKON10",
"description": "Diskon 10% minimal belanja 50rb",
"type": "percentage",
"value": 10,
"min_purchase": 50000,
"max_discount": 15000
}
],
"payment_methods": {
"cash": { "enabled": true, "label": "Tunai / Cash" },
"transfer": { "enabled": true, "label": "Transfer Bank" },
"qris": { "enabled": true, "label": "QRIS Eza Pedia" }
},
"store_info": {
"store_name": "Kedai Kopi Mantap",
"cashier_name": "Kasir Pagi",
"store_address": "Jl. Merdeka No. 12, Jakarta",
"coordinates": "-6.200000,106.816666",
"footer_note": "Terima kasih atas kunjungan Anda"
}
}
}
?action=profile
Mengambil informasi detail akun kasir yang sedang aktif dan identitas toko/merchant.
{
"status": "success",
"data": {
"cashier": {
"id": 3,
"username": "kasir_utama",
"nama_lengkap": "Budi Santoso",
"role": "kasir"
},
"store": {
"admin_id": 1,
"store_name": "Resto Nusantara",
"owner_name": "Mas Eza",
"store_address": "Jl. Pemuda No. 45",
"coordinates": "-6.175392,106.827153",
"store_logo": "https://domain.com/uploads/logo.png",
"qris_image": "https://domain.com/uploads/qris.jpg"
}
}
}
?action=settings
Mengambil konfigurasi nota struk, mode stok (harian/berkelanjutan), aturan delivery self-order, dan channel pembayaran.
?action=payment_methods
Mengembalikan rincian seluruh metode pembayaran aktif toko yang dipisahkan antara Offline Methods (Tunai, Transfer Manual, QRIS Statis, EDC, Kasbon) dan Online Gateway (Eza Pedia Real-Time QRIS / Virtual Account).
{
"status": "success",
"data": {
"offline_methods": [
{
"id": "cash",
"name": "Tunai (Cash)",
"type": "cash",
"is_enabled": true,
"is_offline": true,
"requires_change_calc": true,
"description": "Pembayaran tunai langsung dari pelanggan, diproses 100% offline"
},
{
"id": "transfer",
"name": "Transfer Bank Manual",
"type": "bank_transfer",
"is_enabled": true,
"is_offline": true,
"bank_details": {
"name": "BCA",
"account_name": "Toko Eza POS",
"account_number": "8801234567"
}
},
{
"id": "qris",
"name": "QRIS Statis / Manual",
"type": "static_qris",
"is_enabled": true,
"is_offline": true,
"qris_image_url": "https://domain.com/uploads/qris.jpg"
},
{
"id": "edc",
"name": "Mesin EDC / Debit / Kredit",
"type": "edc",
"is_enabled": true,
"is_offline": true
}
],
"online_gateway": {
"provider": "Eza Pedia Payment Gateway",
"is_active": true,
"channels": [
{
"id": "ezapedia_qris",
"code": "QRIS",
"name": "QRIS Dinamis (Eza Pedia)",
"type": "qris",
"is_online": true,
"create_endpoint": "action=create_qris",
"status_endpoint": "action=check_qris_status",
"fee": 0
}
],
"instructions": "Metode pembayaran online ini membutuhkan koneksi internet saat pelanggan memilihnya untuk generate QRIS dinamis."
}
}
}
?action=printer_settings
GET: Mengambil nama printer Bluetooth tersimpan, ukuran kertas (58mm / 80mm), format teks header, dan footer struk.
POST: Menyimpan nama printer/MAC Address yang dipilih kasir ke server cloud agar tetap tersimpan saat berganti HP.
{
"printer_type": "bluetooth",
"printer_name": "MPT-II (66:22:BB:11:00:AA)",
"paper_width": "58mm", // "58mm" (32 kolom) atau "80mm" (48 kolom)
"auto_print": "yes"
}
?action=get_held_orders
Digunakan untuk fitur Tunda Pesanan (Hold Order). Kasir dapat menyimpan keranjang belanja pelanggan yang antriannya tertahan, melayani pelanggan lain, lalu memulihkan (resume) pesanan kembali ke keranjang kasir.
https://pos.ezapedia.my.id/api/pos_api.php?action=get_held_orders
POST ?action=save_held_order
{
"order_name": "Meja 5 / Pak Bambang",
"cart_data": [
{ "id": 101, "name": "Kopi Susu", "quantity": 2, "price": 18000, "note": "Gula aren sedikit" }
]
}
https://pos.ezapedia.my.id/api/pos_api.php?action=resume_held_order&id=12
Mengembalikan isi keranjang belanja dan secara otomatis menghapus antrian tunda tersebut.
https://pos.ezapedia.my.id/api/pos_api.php?action=delete_held_order&id=12
?action=contacts
Fitur buku telepon di kasir untuk mencari pelanggan, menambahkan kontak baru, memperbarui nomor WhatsApp, dan menghapus kontak.
https://pos.ezapedia.my.id/api/pos_api.php?action=contacts&q=budi
POST ?action=add_contact
{
"name": "Ibu Ratna",
"phone": "081298765432"
}
POST ?action=sync_contacts
Mengirimkan array kontak dari smartphone kasir ke cloud sekaligus.
?action=cancel_sale
Jika kasir salah menginput transaksi yang sudah terlanjur selesai, kasir dapat membatalkan atau mengajukan refund nota dengan menyertakan alasan jelas. Notifikasi WhatsApp otomatis dikirimkan ke Admin Toko untuk persetujuan (approval) di panel web.
{
"sale_id": "TRX-20261026-0001",
"reason": "Salah input jumlah pesanan, pelanggan minta ganti menu"
}
?action=update_stock
Kasir dapat menambah atau mengatur jumlah stok produk secara langsung di pengaturan APK offline saat ada barang masuk (seperti fitur di menu Kasir Online).
// Opsi 1: Update 1 Produk
{
"product_id": 101,
"quantity": 25,
"mode": "add", // "add" (tambah ke stok lama) atau "set" (timpa total stok)
"notes": "Restock kiriman dari gudang pusat"
}
// Opsi 2: Batch Update Banyak Produk Sekaligus
{
"stocks": {
"101": 50,
"102": 30
},
"mode": "set",
"notes": "Stok awal buka toko"
}
?action=sync_up_sales
Mengirimkan transaksi yang telah diproses secara offline saat perangkat mendeteksi sinyal internet. Mendukung pengiriman catatan produk (note kecil pensil), diskon voucher, dan pemotongan stok otomatis di server.
{
"transactions": [
{
"id": "TRX-20261026-0001",
"order_number_daily": 1,
"subtotal": 36000,
"voucher_code": "DISKON10",
"voucher_discount": 3600,
"total_belanja": 32400,
"metode_pembayaran": "cash",
"uang_bayar": 50000,
"kembalian": 17600,
"customer_name": "Pak Joko",
"customer_phone": "08123456789",
"transaction_time": "2026-10-26 10:15:30",
"items": [
{
"id": 101,
"name": "Kopi Susu Gula Aren",
"price": 18000,
"quantity": 2,
"subtotal": 36000,
"note": "Es sedikit, tidak terlalu manis" // Catatan produk per-item
}
]
}
]
}
?action=daily_sales&date=YYYY-MM-DD
Mengambil daftar transaksi kasir per tanggal tertentu lengkap dengan total omzet, rincian pembayaran tunai vs non-tunai, dan detail item.
?action=notifications
Digunakan untuk fitur lonceng notifikasi pada aplikasi kasir. Memberikan informasi jika ada pesanan mandiri pelanggan (Self-Order Dine-in / Takeaway / Delivery) yang masuk ke kasir secara online.
?action=open_shift / ?action=close_shift
Buka Shift: Merekam modal awal uang tunai laci (misal Rp 100.000).
Tutup Shift: Mengirimkan penghitungan uang fisik kasir, menghitung selisih kas otomatis, dan mengirimkan laporan closing shift ke WhatsApp Owner melalui WACS.
?action=check_voucher
Memeriksa keabsahan kode voucher, syarat minimal belanja, dan mengembalikan nominal potongan diskon yang berhak diperoleh.
?action=create_online_payment
(alias: action=create_qris)
Membangkitkan tagihan pembayaran online dan kode QRIS Dinamis resmi dari Eza Pedia Gateway. Aplikasi kasir (seperti APK Android SimpleApp) langsung menerima properti qr_image_url untuk ditampilkan ke pelanggan tanpa membuat data QR dummy lokal.
{
"amount": 50000, // Nominal belanja / tagihan (min. Rp 1.000)
"order_id": "QRIS-1730000000000", // ID Order unik dari APK / POS
"channel": "QRIS", // "QRIS", "BCA", "BRI", "BNI", "MANDIRI", "DANA", "OVO", dll
"payment_method": "QRIS", // Alias channel
"customer_name": "Pelanggan POS" // Nama pelanggan (opsional)
}
{
"status": "success",
"success": true,
"message": "Tagihan pembayaran online Eza Pedia berhasil dibuat.",
"data": {
"order_id": "QRIS-1730000000000",
"amount": 50000,
"unique_code": 87, // Kode unik acak 2 digit (11-99) atau nominal tetap
"total_amount": 50087, // Total tepat yang harus dibayar/ditransfer pelanggan
"fee_amount": 87,
"merchant_name": "TOKO BERKAH JAYA", // Nama Merchant Resmi hasil ekstraksi Tag 59 EMVCo QRIS
"merchant_city": "JAKARTA", // Kota Merchant Tag 60
"nmid": "ID1020023456789", // National Merchant ID Tag 26-51
"postal_code": "12950",
"payment_method": "QRIS",
"channel": "QRIS",
"qr_image_url": "https://api.qrserver.com/v1/create-qr-code/?size=300x300&data=...", // Gambar QRIS dinamis bernominal tepat
"qr_content": "00020101021226600016ID.CO.EZAPEDIA.WWW...", // String EMVCo QRIS dinamis asli
"va_number": "", // Nomor Rekening / VA jika metode Bank / E-Wallet
"account_name": "TOKO BERKAH JAYA",
"status": "PENDING", // Status awal
"paid": false,
"is_paid": false,
"expired_at": "2026-10-30 15:30:00"
}
}
?action=get_merchant_info
(alias: action=get_ezapedia_merchant)
Mengambil data merchant resmi hasil ekstraksi QRIS statis kasir/toko (Tag 59, 60, 26-51, 61) serta pengaturan biaya admin / kode unik. Endpoint ini digunakan oleh aplikasi Android untuk menampilkan nama merchant asli dan NMID tepat di atas bingkai QRIS dinamis yang di-generate.
{
"status": "success",
"success": true,
"message": "Data merchant resmi Eza Pedia Gateway berhasil diambil.",
"data": {
"merchant_name": "TOKO BERKAH JAYA", // Nama toko resmi dari QRIS
"merchant_city": "JAKARTA", // Kota asal toko
"nmid": "ID1020023456789", // NMID resmi
"postal_code": "12950", // Kode pos
"source": "cashier", // Sumber konfigurasi: "cashier" (mandiri), "store", atau "system"
"fee_enabled": true, // Status switch biaya admin/kode unik
"fee_type": "random_2digit", // "random_2digit" (Rp 11-99) atau "fixed"
"fee_amount": 0, // Nominal fee jika tipe fixed
"has_static_qris": true
}
}
?action=get_cashier_gateway
(alias: action=get_user_gateway, get_ezapedia_config)
Mengambil seluruh data konfigurasi Eza Pedia Gateway yang diatur khusus untuk akun kasir/toko cabang dari menu admin/user_form.php?id=. Termasuk: String EMVCo QRIS statis kasir, metadata merchant asli (Tag 59, 60, NMID), daftar saluran pembayaran aktif (QRIS, 11 Bank, 5 E-Wallet), aturan biaya admin (2 digit acak vs nominal tetap), dan paket aplikasi listener terpantau (monitored apps).
Jika parameter amount disertakan (misal amount=4000), endpoint otomatis menghitung kode unik / admin fee dan menghasilkan QRIS dinamis langsung dengan nominal tepat yang siap diproses dan dipantau oleh aplikasi listener Android.
{
"id": 5, // ID Kasir (user_id dari admin/user_form.php?id=5)
"cashier_username": "kasir_utama", // Username kasir (opsional jika id tidak diisi)
"amount": 4000, // Nominal belanja untuk kalkulasi & dynamic QRIS (opsional)
"channel": "QRIS", // "QRIS", "BCA", "DANA", dll (opsional)
"order_id": "QRIS-20261030-001", // ID transaksi (opsional, jika ingin langsung dicatat di riwayat)
"create_transaction": true // Boolean jika ingin dicatat di gateway_transactions & online_transactions
}
{
"status": "success",
"success": true,
"message": "Data Eza Pedia Gateway kasir berhasil dimuat.",
"data": {
"user_id": 5,
"cashier_id": 5,
"admin_id": 1,
"cashier_username": "kasir_utama",
"store_name": "Toko Berkah Cabang 1",
"gateway_enabled": true,
"has_qris": true,
"merchant_name": "Eza Pedia",
"merchant_city": "Kota Tangerang",
"nmid": "ID1026492947555",
"postal_code": "15226",
"static_qris_payload": "00020101021126570011ID.DANA.WWW...",
"fee_enabled": true,
"fee_type": "random_2digit",
"fee_amount": 0,
"channels": [
{ "code": "QRIS", "name": "QRIS Dinamis / Statis", "active": true },
{ "code": "BCA", "name": "Bank BCA", "account_number": "1234567890", "active": true }
],
"monitored_apps": [
"com.bca", "id.co.bri.brimo", "id.bmri.livin", "id.bni.mobile", "id.dana", "ovo.id"
],
"calculation": {
"original_amount": 4000,
"fee_enabled": true,
"fee_type": "random_2digit",
"unique_code": 47,
"total_amount": 4047,
"dynamic_qris_payload": "00020101021226570011ID.DANA.WWW...54044047...",
"dynamic_qris_image": "https://api.qrserver.com/v1/create-qr-code/?size=300x300&data=..."
},
"webhook_url": "https://pos.ezapedia.my.id/api/gateway_receiver.php"
}
}
?action=check_online_payment
(alias: action=check_qris_status)
Aplikasi Android memanggil endpoint ini secara periodik (setiap 3 detik). Sistem memeriksa status dari tabel online_transactions lokal, sinkronisasi webhook otomatis, serta cek langsung ke gateway server. Ketika pelanggan selesai membayar, server langsung mengembalikan "status": "PAID" dan "paid": true sehingga aplikasi kasir langsung auto-refresh, menampilkan notifikasi lunas hijau, dan menyelesaikan transaksi.
{
"order_id": "QRIS-1730000000000"
}
{
"status": "success",
"success": true,
"message": "Pembayaran online berhasil diverifikasi.",
"data": {
"order_id": "QRIS-1730000000000",
"status": "PAID", // HURUF BESAR: Langsung memicu checkRes.data.status === 'PAID'
"paid": true, // BOOLEAN: Memicu checkRes.data.paid === true
"is_paid": true,
"amount": 50000,
"payment_method": "QRIS",
"paid_at": "2026-10-29 15:05:12"
}
}
/api/gateway_receiver.php
Endpoint yang dipanggil oleh aplikasi Android listener (seperti SimpleApp Eza POS) ketika mendeteksi notifikasi mutasi uang masuk dari bank atau e-wallet (BCA, Mandiri, BRI, BNI, DANA, GoPay, OVO, ShopeePay). Tidak perlu pairing code atau scan QR! Cukup sertakan header X-Cashier-Username: username_kasir atau field username pada JSON payload.
{
"amount": 50000, // Nominal mutasi masuk
"bank_name": "BCA", // "BCA", "BRI", "MANDIRI", "DANA", "GOPAY", "OVO", "SHOPEEPAY", dll
"sender_name": "BUDI SANTOSO", // Nama pengirim pada mutasi
"description": "QRIS DARI BUDI SANTOSO", // Keterangan / notifikasi lengkap
"reference_id": "WS123456789", // Ref / ID mutasi bank
"idempotency_key": "idemp_bca_50000_...", // Anti-double processing key
"device_id": "and_dev_982312", // ID perangkat HP kasir
"device_name": "HP Kasir Meja 1", // Nama perangkat HP
"username": "kasir_utama" // USERNAME KASIR TOKO (Identitas unik toko)
}
{
"status": "success",
"success": true,
"message": "Mutasi Rp 50.000 cocok dan tagihan 'QRIS-1730000000000' berhasil ditandai LUNAS.",
"data": {
"matched": true,
"order_id": "QRIS-1730000000000",
"amount": 50000,
"bank_name": "BCA"
}
}
?action=update_payment_status
Digunakan ketika ada perubahan status pembayaran di aplikasi kasir Android (misal: pesanan Tempo/Kasbon yang dilunasi, transfer bank yang telah dikonfirmasi, atau perubahan metode pembayaran). Endpoint ini mempertahankan nomor invoice yang sama di database server tanpa menduplikasi baris transaksi atau memotong stok ulang.
{
"sale_id": "TRX-20261026-0001", // Nomor Invoice / ID Transaksi
"status": "Sudah Dibayar", // "Sudah Dibayar", "Selesai", "Pending", dll
"metode_pembayaran": "cash", // "cash", "transfer", "qris", "edc", dll
"uang_bayar": 50000, // Jumlah uang yang dibayarkan
"kembalian": 14000, // Uang kembalian
"customer_name": "Pak Joko Santoso", // Nama pembeli (opsional)
"customer_phone": "08123456789", // No WA pembeli (opsional)
"transfer_sender_name": "Joko S" // Nama pengirim jika transfer (opsional)
}
{
"status": "success",
"success": true,
"message": "Status transaksi dan pembayaran invoice 'TRX-20261026-0001' berhasil diperbarui di server.",
"data": {
"sale_id": "TRX-20261026-0001",
"order_number_daily": 1,
"status": "Sudah Dibayar",
"metode_pembayaran": "cash",
"total_belanja": 36000,
"uang_bayar": 50000,
"kembalian": 14000,
"customer_name": "Pak Joko Santoso",
"customer_phone": "08123456789",
"updated_at": "2026-10-27 08:50:00"
}
}
?action=update_product
Memungkinkan aplikasi Android luar jaringan untuk memperbarui informasi produk (nama, harga modal, harga jual normal, harga reseller, deskripsi) serta stok fisik produk secara real-time. Juga tersedia endpoint batch ?action=batch_update_products untuk banyak produk sekaligus.
{
"product_id": 101, // ID Produk
"name": "Kopi Susu Gula Aren Premium", // Nama baru (opsional)
"regular_price": 20000, // Harga jual normal
"reseller_price": 17000, // Harga reseller / grosir
"base_price": 9000, // Harga modal
"stock_quantity": 60, // Atur jumlah stok fisik saat ini
"description": "Espresso arabika blend dengan gula aren asli"
}
// POST ?action=batch_update_products
{
"products": [
{ "id": 101, "regular_price": 20000, "stock_quantity": 50 },
{ "id": 102, "regular_price": 15000, "stock_quantity": 35 }
]
}
?action=update_profile
username kasir. Jika ada percobaan pengiriman username yang berbeda, server otomatis menolak request dengan status 403 Forbidden. Username berfungsi sebagai API Key unik dan identitas akun permanen.
Kasir dapat memperbarui nama lengkap, ganti password, nama toko cabang, alamat, no telepon, dan konfigurasi printer thermal.
{
"nama_lengkap": "Budi Santoso, S.Kom", // Nama lengkap tampilan kasir
"password": "password_baru123", // Ganti password (opsional, min 4 karakter)
"store_name": "Kedai Kopi Cabang 2", // Nama toko cabang kasir
"store_address": "Jl. Raya Barat No. 88", // Alamat toko
"store_phone": "081298765432", // Nomor WA toko
"footer_note": "Terima kasih atas kunjungan Anda!",
"printer_name": "MPT-II (Bluetooth)",
"paper_width": "58mm"
}
?action=sync_all
Endpoint all-in-one yang dirancang untuk sinkronisasi total dua arah antara aplikasi Android dan server cloud. Mengirimkan seluruh perubahan lokal (transaksi baru, pelunasan nota, stok, produk, kontak) sekaligus menarik seluruh data master terbaru toko (katalog produk lengkap, stok real-time, kategori, metode pembayaran, printer thermal, voucher, riwayat transaksi) dalam 1 kali network request.
• Jika mengirim JSON Payload: Server memproses pembaruan lokal (sales, stock, status bayar), lalu mengembalikan snapshot data terbaru.
• Jika Request Kosong / GET: Server langsung mengembalikan seluruh snapshot data toko, produk, stok, metode pembayaran, dan riwayat transaksi secara instan tanpa perlu upload.
{
"sales": [ // Transaksi offline (otomatis upsert invoice)
{
"id": "TRX-20261027-0001",
"order_number_daily": 1,
"total_belanja": 45000,
"metode_pembayaran": "cash",
"status": "Sudah Dibayar",
"items": [{ "id": 101, "quantity": 2, "price": 20000 }]
}
],
"payment_updates": [ // Perubahan status pembayaran nota lama
{ "sale_id": "TRX-20261026-0005", "status": "Sudah Dibayar", "metode_pembayaran": "transfer" }
],
"stocks": { // Pembaruan stok produk
"101": 55,
"102": 40
},
"contacts": [ // Kontak pelanggan baru
{ "name": "Pak Rudi", "phone": "0812345678" }
]
}
{
"status": "success",
"success": true,
"message": "Sinkronisasi total seluruh data kasir berhasil diproses di server. Data master toko, katalog produk, stok, metode pembayaran, dan riwayat berhasil dimuat.",
"data": {
"upload_summary": { // Ringkasan hasil upload data lokal
"sales": { "synced": 1, "inserted": 1, "updated": 0, "errors": [] },
"payment_updates": { "updated": 1 },
"stocks": { "updated": 2 },
"products": { "updated": 0 },
"contacts": { "imported": 1 },
"profile_updated": false
},
"store_info": { // Informasi lengkap profil toko & kasir
"admin_id": 1,
"kasir_id": 5,
"username": "kasir",
"store_name": "Toko Berkah Sejahtera",
"cashier_name": "Kasir Utama",
"store_address": "Jl. Merdeka No. 10",
"store_phone": "08123456789",
"footer_note": "Terima kasih atas kunjungan Anda"
},
"categories": [ // Daftar seluruh kategori kasir
{ "id": 1, "name": "Makanan" },
{ "id": 2, "name": "Minuman" }
],
"products": [ // Daftar seluruh produk + stok + harga real-time
{
"id": 101,
"name": "Kopi Susu Gula Aren",
"category_id": 2,
"category_name": "Minuman",
"base_price": 8000,
"regular_price": 18000,
"reseller_price": 15000,
"stock_quantity": 55,
"image_url": "https://domain.com/uploads/kopi.jpg"
}
],
"stock_map": { // Mapping cepat product_id => stok
"101": 55
},
"payment_methods": { ... }, // Metode pembayaran offline & Eza Pedia gateway
"printer_settings": { ... }, // Konfigurasi printer thermal ESC/POS
"vouchers": [ ... ], // Daftar voucher diskon aktif
"daily_sales": [ ... ], // Riwayat transaksi kasir hari ini
"contacts": [ ... ], // Buku telepon pelanggan
"active_shift": { ... }, // Shift kerja kasir yang sedang aktif
"server_time": "2026-10-27 09:20:00"
}
}
Rekomendasi Skema Database SQLite Lokal (Untuk APK Android)
Struktur tabel lokal pada Room / SQLite / WatermelonDB agar aplikasi bekerja optimal secara offline.
-- 1. Tabel Produk Lokal (Disimpan di HP)
CREATE TABLE products (
id INTEGER PRIMARY KEY,
category_id INTEGER,
name TEXT NOT NULL,
description TEXT,
base_price REAL,
regular_price REAL,
reseller_price REAL,
stock_quantity INTEGER DEFAULT 0,
image_url TEXT,
type TEXT DEFAULT 'physical',
is_pack INTEGER DEFAULT 0
);
-- 2. Tabel Kategori Lokal
CREATE TABLE categories (
id INTEGER PRIMARY KEY,
name TEXT NOT NULL
);
-- 3. Tabel Keranjang & Transaksi Offline
CREATE TABLE offline_sales (
id TEXT PRIMARY KEY, -- e.g. "TRX-20261026-0001"
order_number_daily INTEGER,
items_json TEXT NOT NULL, -- JSON array item beserta catatan (note)
subtotal REAL,
voucher_code TEXT,
voucher_discount REAL DEFAULT 0,
total_belanja REAL NOT NULL,
metode_pembayaran TEXT DEFAULT 'cash',
uang_bayar REAL,
kembalian REAL,
customer_name TEXT,
customer_phone TEXT,
transaction_time TEXT NOT NULL,
is_synced INTEGER DEFAULT 0 -- 0 = Belum Sync, 1 = Sudah Terkirim ke Cloud
);
-- 4. Tabel Shift Kasir Lokal
CREATE TABLE shifts (
id INTEGER PRIMARY KEY AUTOINCREMENT,
server_shift_id INTEGER,
start_time TEXT,
end_time TEXT,
start_balance REAL,
end_balance REAL,
status TEXT DEFAULT 'open'
);
-- 5. Tabel Pesanan Ditahan Lokal (Held Orders)
CREATE TABLE held_orders (
id INTEGER PRIMARY KEY AUTOINCREMENT,
server_held_id INTEGER,
order_name TEXT NOT NULL,
cart_json TEXT NOT NULL,
created_at TEXT NOT NULL
);
-- 6. Tabel Buku Telepon & Kontak Lokal
CREATE TABLE contacts (
id INTEGER PRIMARY KEY AUTOINCREMENT,
server_contact_id INTEGER,
contact_name TEXT NOT NULL,
contact_phone TEXT NOT NULL,
created_at TEXT
);
-- 7. Tabel Pengaturan Printer Thermal Lokal
CREATE TABLE printer_settings (
id INTEGER PRIMARY KEY DEFAULT 1,
printer_type TEXT DEFAULT 'bluetooth',
printer_name TEXT,
paper_width TEXT DEFAULT '58mm',
auto_print TEXT DEFAULT 'yes'
);
Live API Tester (Uji Coba Langsung)
Coba kirim permintaan langsung ke server dan lihat format JSON responsnya
* Tip: Untuk sync_all, jika JSON Body diisi data lokal, server akan meng-upload & memperbarui data; jika dikosongkan, server akan otomatis menarik seluruh master data toko & produk secara lengkap.
Klik tombol "Kirim Request Live" di atas untuk mencoba API.