Source Code Self-hosted Payment Gateway QRIS GoPay Merchant
Source code self-hosted payment gateway menggunakan akun GoPay Merchant. Dirancang untuk kebutuhan sistem pembayaran yang memerlukan alur pembayaran seperti payment gateway pada umumnya dengan validasi transaksi otomatis secara realtime.
Item Details
Cara Kerja Singkat
- Create payment melalui API → sistem langsung menghasilkan QRIS dinamis (string dan PNG) secara instan.
- Customer melakukan pembayaran dengan memindai QRIS tersebut.
- Sistem mendeteksi settlement secara otomatis → status transaksi berubah menjadi "Paid" dan webhook terkirim secara otomatis.
Fitur Utama
-
Pembuatan Transaksi
- Pembuatan transaksi melalui REST API yang langsung menghasilkan QRIS dinamis (string dan PNG) secara instant.
- Dua mode nominal: client-managed (nominal ditentukan sepenuhnya oleh pengguna) dan server-managed (nominal dasar ditambah kode unik 0–999 secara otomatis).
-
Deteksi Pembayaran & Settlement
- Deteksi pembayaran otomatis melalui poller yang mengambil mutasi langsung dari API GoPay Merchant.
- Pencocokan berbasis nominal dengan toleransi tertentu; setiap transaksi hanya dapat menyelesaikan satu pembayaran untuk mencegah double-settle.
- Auto-expire transaksi yang tidak dibayar dalam durasi tertentu, disertai pengiriman webhook
payment.expired. - Auto-login dan auto-refresh token GoPay Merchant: jika token belum tersedia atau sudah expired, sistem otomatis melakukan login ulang dan menyimpan token baru, sehingga poll berikutnya dapat langsung menggunakan token yang valid tanpa perlu login berulang kali.
- Proses login pada source code ini tidak memengaruhi sesi GoPay Merchant di perangkat lain; login melalui source code tidak akan membuat sesi pada device/aplikasi lain menjadi logout.
-
Webhook & Notifikasi
- Pengiriman webhook/callback pada kondisi paid dan expired, disertai signature HMAC-SHA256 (
X-Signature) dan headerX-Event. - Retry webhook otomatis hingga 5 kali dengan backoff 1–60 detik, setiap percobaan tercatat dalam log, serta tersedia opsi resend manual melalui panel.
- Pengiriman webhook/callback pada kondisi paid dan expired, disertai signature HMAC-SHA256 (
-
Panel Admin
- Panel admin dengan tampilan premium, terinspirasi dari dashboard modern, sepenuhnya responsif termasuk tampilan mobile.
- Update status transaksi secara realtime menggunakan Server-Sent Events (SSE) tanpa perlu memuat ulang halaman.
- Manajemen API key lengkap dengan paginasi dan filter status (Active/Revoked/All).
- Paginasi global diterapkan pada seluruh tabel data (Payments, Transactions, API Keys).
- Halaman Merchant Profile menampilkan informasi lengkap merchant, QRIS, ASPI, dan settlement, dengan sinkronisasi otomatis static QRIS dari profil GoPay Merchant.
-
Keamanan & Autentikasi
- Autentikasi menggunakan API key untuk endpoint pembayaran.
- Login administrator dilengkapi rate limiter berbasis IP (mencegah lockout akibat serangan DoS).
- Token GoPay Merchant disimpan dalam bentuk terenkripsi (AES-256-GCM).
-
Lainnya
- Mendukung berbagai zona waktu (WIB/WITA/WIT/UTC).
- Dokumentasi API lengkap, mencakup seluruh endpoint dengan contoh request/response, spesifikasi webhook (payload, header, cara verifikasi signature) beserta contoh handler dalam Node.js, PHP, dan Python, dilengkapi tabel error code dan aturan autentikasi.
Teknologi yang Digunakan
- Backend: Node.js (ESM) dengan Fastify v5
- Panel: SvelteKit dan Tailwind CSS v4 (native Vite plugin), Vite v8
- Database: SQLite (better-sqlite3 v12, mode WAL)
- Koneksi ke GoPay Merchant: native fetch
- Autentikasi dan kriptografi: scrypt, SHA-256, AES-256-GCM, HMAC-SHA256
- Realtime: Server-Sent Events (SSE)
- Deployment: PM2 dan Nginx (opsional)
Cocok Digunakan Untuk
- Integrasi pembayaran QRIS ke aplikasi atau website sendiri (SaaS, membership, langganan)
- Layanan top-up otomatis: game, pulsa, e-wallet, atau voucher
- Toko online dengan halaman checkout custom
- Sistem kasir/POS yang membutuhkan QRIS dinamis per-transaksi
- Bot (Telegram/WhatsApp/Discord) yang menerima pembayaran dan membutuhkan callback otomatis
- Sistem deposit/saldo yang harus terverifikasi otomatis saat pembayaran masuk
- Layanan donasi atau penggalangan dana pribadi
- Backend internal yang ingin menerima pembayaran tanpa biaya per-transaksi dari payment gateway pihak ketiga
Keunggulan
- Menggunakan shared adaptive poller: hanya satu poller untuk seluruh transaksi, aktif hanya ketika terdapat pembayaran pending, dan berhenti otomatis saat idle sehingga hemat resource.
- Poll pertama langsung dijalankan begitu transaksi dibuat, tanpa perlu menunggu satu interval penuh.
- Interval polling dapat diubah melalui panel tanpa perlu restart proses.
- Keunikan nominal antartransaksi pending dijaga secara atomik di level database sehingga aman dari race condition.
- Tanpa browser maupun Playwright sehingga ringan dan dapat berjalan pada VPS dengan spesifikasi rendah.
- Panel menerapkan pola BFF (Backend-for-Frontend); cookie session dan API key tidak pernah terekspos ke browser.
- Dilengkapi test suite lengkap (548 backend tests dan 49 frontend tests) untuk menjaga fungsi inti tetap berjalan dengan baik.
- Storage-agnostic (DAL terpisah) sehingga mudah dimigrasikan dari SQLite ke database lain.
- Auto-migration saat startup (bersifat non-destructive), sehingga aman digunakan saat melakukan pembaruan tanpa risiko kehilangan data.
Contoh Output (Webhook Payload)
Event: Paid
{
"payment_id": "4ad4f8df-a549-482d-8b73-2e25d74f2b28",
"payment_status": "paid",
"amount": 25000,
"created_at": 1782688700000,
"paid_at": 1782689000000,
"created_at_iso": "2026-06-29T06:18:20.000+07:00",
"paid_at_iso": "2026-06-29T06:23:20.000+07:00",
"tz": "Asia/Jakarta",
"provider_transaction": {
"id": "019f1089-10b0-7000-81da-4b096275ca9b",
"order_id": "QRIS-0120260628232046WY1VVrAgVQID",
"wallstreet_transaction_id": "0120260628232046WY1VVrAgVQID",
"transaction_status": "SETTLEMENT",
"payment_type": "QRIS",
"transaction_time": "2026-06-29T06:20:46+07:00",
"settlement_time": "2026-06-29T06:20:46.904351+07:00",
"gross_amount": 500000,
"real_gross_amount": 500000,
"currency": "IDR",
"qris_provider_aspi_issuer": "GOPAY",
"qris_provider_aspi_acquirer": "gopay",
"shares": [ { "merchant_share": 498500, "platform_total_fee": 1500, "merchant_percentage_fee": 0.003 } ],
"promo_details": { "promo_code": "", "promo_original_amount": 0 },
"transaction_history": [ { "action_name": "Settlement Transaction", "amount": 500000, "action_status": "SETTLEMENT" } ]
}
}
Event: Expired
{
"payment_id": "4ad4f8df-a549-482d-8b73-2e25d74f2b28",
"payment_status": "expired",
"amount": 25000,
"created_at": 1782688700000,
"expires_at": 1782689000000,
"created_at_iso": "2026-06-29T06:18:20.000+07:00",
"expires_at_iso": "2026-06-29T06:23:20.000+07:00",
"tz": "Asia/Jakarta"
}
(setiap webhook dikirim disertai header X-Signature (HMAC-SHA256) dan X-Event sesuai jenis event)
Arsitektur
flowchart LR
subgraph Client["Your System"]
C1[POST /payment] --> API
WH[(Webhook Receiver)]
end
subgraph Backend["Backend — Fastify (Port 3000)"]
API["REST API<br/>+ API-key Auth"]
SVC["Payment Service<br/>Lifecycle + Matching"]
POLL["Adaptive Shared Poller"]
WHD["Webhook Dispatcher<br/>HMAC + Retry"]
DAL[("SQLite DAL<br/>WAL")]
BUS[("Event Bus → SSE")]
GM["GoMerch Client"]
end
subgraph Panel["Admin Panel — SvelteKit (Port 3001)"]
UI["Dashboard / Create / Payments<br/>Transactions / API Keys / Config / Docs"]
end
API --> SVC --> DAL
POLL -->|getRecentTransactions| GM --> GoMerch[(GoPay Merchant API)]
POLL --> SVC
SVC -->|paid / expired| WHD --> WH
SVC --> BUS
UI -->|BFF Proxy| API
UI -->|EventSource| BUS
⚠️ Disclaimer
- Produk ini menggunakan API GoPay Merchant, bukan scraping maupun automation browser.
- Pembeli bertanggung jawab penuh atas penggunaan akun GoPay Merchant sesuai ketentuan yang berlaku.
- Source code disediakan dalam kondisi "as is." Pembaruan minor diberikan selama 1 tahun, sedangkan pembaruan major tersedia hingga 3 bulan setelah pembelian. Di luar periode tersebut, pembaruan tetap dapat diberikan dengan biaya tambahan sesuai jenis dan cakupan pembaruan.
Change Log
v2.0.0 - Major Tech-Stack Overhaul
A major tech-stack overhaul focused on modernizing the entire infrastructure. All core dependencies upgraded to their absolute latest major versions, unlocking performance improvements, better developer experience, and a robust foundation for the future.
Frontend:
- Tailwind CSS v4
- Removed tailwind.config.js and postcss.config.js
- Vite v8 engine
- SvelteKit and plugins upgraded to latest
- UI polish on Admin Panel layout/page components
Backend:
- Fastify v4 -> v5.10.0
- better-sqlite3 -> v12.11.1
Quality:
- 548 backend tests + 49 frontend tests passing
- Backwards-compatible with existing GoMerch integration
v1.4.0 - Premium Mobile UI, Global Pagination & API Keys Management
Focus on delivering a significantly improved premium interface, especially for mobile, alongside major feature additions like robust pagination across all data tables and API Keys management enhancements.
Highlights:
- Overhauled 2-row sticky mobile header with animated drawer (fly/fade transitions)
- Minimalist topbar chips with new Version indicator (v1.4.0), replacing Merchant ID chip
- Symmetrical margins/padding/borders across entire dashboard
- Modernized cards with premium gradient icon boxes
- Removed redundant H1 titles across all pages
- API Keys: pagination (20/page) + status filter (Active/Revoked/All)
- Global pagination expanded to Payments and Transactions pages
- Upgraded sqlite-storage and migrations for pagination/status filter support
- Improved Webhook Dispatcher and GoMerch response adapters
- Expanded test coverage (Admin routes, webhook dispatching, page components)
- Repository cleanup: removed output.json, synced lockfiles
v1.3.0 - Premium UI/UX Refinements & Merchant Profile Revamp
Heavy focus on UI/UX polish and premium layout adjustments, inspired by modern dashboards (Vercel, Stripe style).
Highlights:
- Merchant profile page split into 3 structured cards (Details, Settlement, Owner Identity)
- Gradient icon boxes, full-width header dividers, symmetrical padding
- Removed redundant H1 titles across major pages, relying on sticky topbar
- New GET /admin/merchant/info endpoint with full merchant/QRIS/ASPI/settlement data
- GoMerchClient now fetches full merchant payload
- Auto-sync Static QRIS from GoMerch profile on startup
- Sidebar 'Merchant' renamed to 'Merchant Profile'
- Topbar changed from glassmorphism to solid white
- Dashboard CTA swapped to 'Merchant Profile'
v1.2.0 - GoPay Transaction Limits Alignment
Critical adjustments to payment amount limitations to align with GoPay's transaction limits, plus frontend UI refinements and full test suite stability (544/544 passing).
Features:
- MIN_AMOUNT: 1,000 (was 1)
- MAX_AMOUNT: 9,999,000 (was 999,999,999)
- Amount auto-formatting with thousand separators
- Strict min/max validation on timeout & tolerance inputs
Fixes:
- PBT generator context bug (pending-amount-uniqueness.pbt.test.js)
- Svelte cursor-jump on auto-format binding
v1.1.0 - Enhanced Security & IP-Based Rate Limiting
Highlights:
- Migrate admin rate limiter from username-based to IP-based tracking (fixes DoS lockout vuln)
- Add Cloudflare/reverse proxy IP resolution support
- Restructure DB: new login_attempts table, drop failed_attempts/lockout_until from admin_users
- Prevent race conditions via SQLite INSERT ON CONFLICT
- 545 tests passing, auto-migration on boot (non-destructive)
v1.0.0 — Initial Release
First public release of GoPay Merchant, a self-hosted QRIS payment-gateway middleware on top of a GoPay Merchant account: dynamic QRIS creation, automatic settlement detection, signed paid/expired webhooks, a realtime admin panel, and a REST API.