Skip to content
 
 

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

1 Commit
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

QRIS Bridge

AGPL-3.0 License Go Version Build Coverage

Bridge notifikasi pembayaran dari perangkat merchant menjadi webhook untuk otomasi sistem internal. Tidak terhubung langsung ke jaringan pembayaran atau melakukan konfirmasi resmi dari bank.

⚠️ DISCLAIMER HUKUM
Proyek ini disediakan untuk tujuan edukasi dan pembelajaran non-komersial. Pengguna bertanggung jawab penuh atas cara penggunaan, termasuk kepatuhan terhadap hukum yang berlaku, syarat layanan pihak ketiga, dan regulasi terkait (UU PDP, UU ITE, Peraturan BI, POJK, dll). Proyek ini tidak berafiliasi dengan Bank Indonesia, OJK, atau penyedia e-wallet mana pun. Lihat bagian Posisi Regulasi & Batasan Layanan untuk informasi lebih lanjut.

Dokumen hukum penting:

When to Use / When NOT to Use

Gunakan untuk:

  • POS internal — mendeteksi pembayaran masuk langsung dari notifikasi HP tanpa scan barcode
  • Sistem kasir UMKM — update status pesan otomatis saat notifikasi pembayaran diterima
  • Otomasi toko online — konfirmasi pembayaran manual dari transfer QRIS ke webhook pesanan
  • Integrasi ERP internal — catat pembayaran QRIS masuk ke sistem akuntansi tanpa entri manual
  • Dashboard monitoring pembayaran multi-merchant — lihat status notifikasi, perangkat, dan antrian retry real-time
  • Pencocokan otomatis — cocokkan notifikasi masuk dengan pesanan yang belum dibayar (via nominal + waktu)

Jangan gunakan untuk:

  • Payment Gateway
  • Agregator pembayaran
  • Acquiring service
  • Verifikasi resmi transaksi bank
  • Mengelola dana pihak ketiga

Arsitektur

Bank / DANA / GoPay / OVO / BCA / BRI / Mandiri / BNI
                      │
                      ▼
          Push Notification Android
                      │
                      ▼
          QRIS Bridge Android App
          ┌─────────────────────────┐
          │ NotificationListener    │
          │ Parser (plugin + regex) │
          │ Room DB (offline queue) │
          │ WorkManager (retry)     │
          │ OkHttp WebSocket        │
          └─────────┬───────────────┘
                    │ WebSocket TLS (device_id + secret auth)
                    ▼
          ┌──────────────────────────────────┐
          │         Bridge Server (Go)        │
          │                                   │
          │  ┌─────────┐  ┌───────────────┐  │
          │  │ WebSocket│  │  REST API     │  │
          │  │ Handler  │  │  (36 endpoint)│  │
          │  └────┬─────┘  └───────┬───────┘  │
          │       │                │          │
          │  ┌────▼────────────────▼───────┐  │
          │  │       Event Bus              │  │
          │  │    (Redis Streams)           │  │
          │  └────────────┬────────────────┘  │
          │               │                   │
          │  ┌────────────▼────────────────┐  │
          │  │     Worker (stream consumer) │  │
          │  │  ┌─────────┐ ┌───────────┐  │  │
          │  │  │ Matching│ │ Webhook   │  │  │
          │  │  │ Engine  │ │ Delivery  │  │  │
          │  │  └─────────┘ └───────────┘  │  │
          │  └──────────────────────────────┘  │
          │                                   │
          │  ┌──────────┐  ┌───────────────┐  │
          │  │ Retry    │  │ Dedup (SHA256)│  │
          │  │ Queue    │  │ Fingerprint   │  │
          │  │ (Redis)  │  │               │  │
          │  └──────────┘  └───────────────┘  │
          │                                   │
          │  DB: PostgreSQL                   │
          │  Cache/Queue: Redis               │
          └────────────────┬──────────────────┘
                           │
                           ▼
          POS / WooCommerce / Laravel / Node.js
          (Webhook POST + HMAC SHA256 Signature)

Posisi Regulasi & Batasan Layanan

QRIS Bridge adalah alat otomasi notifikasi — bukan penyelenggara sistem pembayaran, bukan dompet digital, bukan payment gateway, bukan agregator pembayaran, dan bukan layanan transfer dana.

Aplikasi tidak menginisiasi, mengubah, atau memproses transaksi pembayaran. Aplikasi hanya membaca informasi dari notifikasi yang diterima perangkat (nama aplikasi, nominal, pengirim) dan meneruskannya ke server dalam bentuk webhook.

QRIS Bridge tidak:

  • Terhubung ke jaringan sistem pembayaran
  • Mengakses akun atau kredensial pengguna e-wallet
  • Menyimpan atau mengelola dana pihak ketiga
  • Melakukan verifikasi resmi transaksi ke bank/PJP
  • Berfungsi sebagai alat pembayaran

Proyek ini tidak berafiliasi, didukung, atau disahkan oleh:

  • Bank Indonesia
  • Otoritas Jasa Keuangan (OJK)
  • Kementerian Komunikasi dan Digital (Komdigi)
  • Penyedia dompet elektronik seperti DANA, GoPay, ShopeePay, OVO, atau pihak lainnya

Status hukum bergantung pada fungsi nyata layanan, model bisnis, dan penilaian regulator. Jika dikomersilkan atau terintegrasi lebih dalam dengan ekosistem pembayaran, analisis regulasi harus diperbarui.

Privasi Data

Data yang diproses oleh QRIS Bridge:

Data Sumber Tujuan Retensi
Nama aplikasi (e.g. DANA, GoPay) Notifikasi Android Identifikasi sumber pembayaran Hingga dihapus pengguna
Nominal pembayaran Notifikasi Android Pencocokan dengan invoice Hingga dihapus pengguna
Nama pengirim Notifikasi Android Referensi transaksi Hingga dihapus pengguna
Teks notifikasi mentah (raw) Notifikasi Android Debugging & pengembangan parser Tidak disimpan permanen
ID perangkat + secret Konfigurasi pengguna Autentikasi WebSocket Selama perangkat terdaftar
Alamat IP Koneksi jaringan Operasional server Tidak disimpan

Pengguna dapat menghapus data melalui:

  • Dashboard web — hapus notifikasi, device, atau data merchant
  • API — DELETE endpoint untuk resources terkait
  • Database — hapus langsung dari PostgreSQL jika akses tersedia

Pengguna bertanggung jawab memastikan penggunaan QRIS Bridge sesuai dengan syarat layanan aplikasi pihak ketiga (e-wallet, bank, platform merchant) yang mereka gunakan.

FAQ

"Ini kan cuma notifikasi, bukan transaksi sungguhan — kenapa harus diamankan?"

Notifikasi pembayaran e-wallet/banking mengandung informasi sensitif: nominal, pengirim, dan kadang saldo. Jika bocor, pihak ketiga bisa:

  • Melihat seluruh riwayat transaksi merchant (nominal, frekuensi, pengirim)
  • Menyusun profil bisnis merchant
  • Menggunakan data untuk social engineering

QRIS Bridge menerapkan:

  • Full encryption — seluruh data (app, amount, sender, rawText) dienkripsi AES-256-GCM di Room DB
  • Encryption at rest — kunci enkripsi disimpan di Android Keystore (hardware-backed)
  • No full-db leak — walau file .db bocor, data tidak bisa dibaca tanpa kunci

"Data saya dikirim ke server pihak ketiga?"

Tidak. Data hanya dikirim ke server yang Anda konfigurasi sendiri. Tidak ada data yang dikirim ke pengembang, ke penyedia e-wallet, atau ke pihak ketiga mana pun. Lihat PRIVACY.md.

"Apakah ini legal?"

QRIS Bridge adalah alat otomasi notifikasi — membaca notifikasi yang sudah ada di perangkat Anda. Tidak ada:

  • Intersepsi jaringan (tidak melanggar UU ITE Pasal 31)
  • Akses tanpa hak ke sistem e-wallet (tidak ada login ke akun pengguna)
  • Modifikasi transaksi (hanya baca, tidak tulis)
  • Penyimpanan data pihak ketiga (self-hosted)

Namun, kepatuhan terhadap Terms of Service masing-masing e-wallet berbeda-beda. Lihat tabel Audit ToS untuk detail. Konsultasi dengan legal counsel disarankan untuk penggunaan komersial.

"Apa yang terjadi jika HP saya hilang?"

Data di Room DB terenkripsi dengan Android Keystore — tidak bisa dibaca tanpa unlock device. Anda dapat:

  1. Unpair device dari dashboard server (cabut akses WebSocket)
  2. Hapus data dari server via API DELETE /api/v1/notifications
  3. Hapus data lokal dari device lain (jika sudah pairing sebelumnya)

"Siapa yang bisa mengakses data saya?"

Hanya Anda (pemilik perangkat dan server). Developer tidak memiliki akses ke instance Anda.

"Bagaimana cara hapus semua data saya?"

Android: Pengaturan > Privasi Data > Hapus Semua Data — menghapus Room DB + mengirim DELETE ke server. Atau langsung via API DELETE /api/v1/notifications dengan JWT atau device_id+secret.

"Apakah aplikasi ini membaca data lain selain notifikasi?"

Tidak. Audit kode membuktikan QRIS Bridge hanya membaca title, text, dan bigText dari notifikasi yang masuk. Tidak ada akses ke SMS, kontak, lokasi, kamera (setelah pairing QR selesai), galeri, mikrofon, atau data pribadi lainnya. Lihat docs/THREAT_MODEL.md untuk detail audit.

"Apakah aplikasi ini bisa dipakai untuk menipu?"

Tidak. QRIS Bridge hanya meneruskan informasi — tidak bisa menginisiasi transaksi, tidak bisa mengubah nominal, tidak bisa memalsukan notifikasi (ini terjadi di sisi e-wallet, bukan di bridge). Webhook tetap harus diverifikasi via HMAC signature di sisi merchant.

Disclaimer Keamanan

QRIS Bridge bekerja berdasarkan notifikasi yang diterima pada perangkat merchant. Notifikasi bukan merupakan bukti pembayaran yang dijamin oleh bank atau penyelenggara QRIS. Merchant tetap bertanggung jawab melakukan mitigasi risiko sesuai kebutuhan operasionalnya.

Sistem tidak memverifikasi transaksi langsung ke sistem bank atau penyelenggara QRIS. Untuk penggunaan produksi, tambahkan langkah mitigasi seperti autentikasi perangkat, tanda tangan HMAC, enkripsi TLS, audit log, dan mekanisme penanganan kegagalan.

Perangkat lunak ini diberikan "AS IS", tanpa jaminan dalam bentuk apa pun, sebagaimana diatur dalam lisensi AGPL-3.0. Lihat LICENSE untuk detail.

Fitur

  • Duplicate Detection — SHA256 fingerprint (app + text + minute window), cegah double processing
  • Event Bus — Redis Streams dengan consumer group, antrean terjamin
  • Smart Matching — nominal duplikat dihandle dengan ambil invoice tertua
  • Plugin Parser — format JSON dengan priority, extractor, validator; auto-update tanpa update APK
  • Pairing Code + QR — registrasi device via kode pairing (5 menit expiry) + QR code PNG
  • JWT Authentication — login via API Key, Bearer token untuk semua request
  • Retry Queue — exponential backoff (30s → max 24h, max 10 retry)
  • HMAC Signature — setiap webhook ditandatangani SHA256
  • Dashboard Web — login page, statistik real-time, last notification, device table, WS latency
  • SDK Multi-bahasa — Go, PHP, Node.js, Python
  • Integrasi Merchant — Laravel, WooCommerce, WordPress, FastAPI
  • Offline Queue — Android simpan ke Room DB, kirim ulang via WorkManager
  • Multi-bank — DANA, GoPay, OVO, myBCA, BRImo, Livin, BNI Mobile, blu
  • Event-based Webhooks — subscribe event tertentu (payment., notification., device., parser., webhook.*) dengan glob pattern
  • Event Replay — replay ulang event dalam range waktu tertentu (max 7 hari)
  • Dead Letter Queue — webhook gagal total dipindahkan ke DLQ untuk inspeksi manual
  • Bulk Retry — retry semua webhook failed sekaligus
  • Webhook Test — test kirim webhook dummy ke endpoint untuk verifikasi
  • Parser Management UI — CRUD parser plugin dari dashboard
  • Parser Test — uji coba parser terhadap teks notifikasi
  • Multi-API Key — buat multiple API key per merchant dengan revoke
  • Admin Login — autentikasi admin via email + password
  • Backup & Restore — ekspor/impor konfigurasi merchant (devices, webhooks, API keys, parsers)
  • Pagination — semua list endpoint mendukung pagination (per_page + page)
  • Structured Logging — zerolog JSON logging
  • Health Check Depth — cek koneksi DB + Redis + WebSocket connection count
  • Wildcard Event Subscription — subscribe events via glob pattern (e.g. payment.*)
  • Sequence Numbers — setiap event memiliki sequence number incrementing
  • Event Schemas — schema JSON untuk setiap event di schemas/
  • Event Registry Docs — dokumentasi setiap event di docs/events/
  • Prometheus Metrics — endpoint /metrics dengan metrik delivery duration, success rate, dll
  • Graceful Shutdown — server menutup koneksi dengan aman saat SIGTERM
  • 27 Event Types — 27 event types terdefinisi: payment (6), notification (5), device (7), parser (3), webhook (4), system (2)

Event Types

Event Category Description
payment.detected Payment Pembayaran terdeteksi dari notifikasi
payment.matched Payment Pembayaran cocok dengan expectation
payment.paid Payment Payment expectation terbayar
payment.expired Payment Payment expectation kadaluarsa
payment.unmatched Payment Pembayaran tidak cocok dengan expectation
payment.failed Payment Pembayaran gagal
notification.received Notification Notifikasi diterima dari device
notification.parsed Notification Notifikasi berhasil di-parse
notification.duplicate Notification Notifikasi duplikat (SHA256 fingerprint)
notification.invalid Notification Notifikasi tidak valid
notification.dropped Notification Notifikasi di-drop
device.paired Device Device berhasil dipairing
device.online Device Device terhubung WebSocket
device.offline Device Device terputus WebSocket
device.reconnected Device Device reconnect
device.unpaired Device Device di-unpair
device.heartbeat.timeout Device Heartbeat device timeout
parser.updated Parser Parser plugin diupdate
parser.downloaded Parser Parser config didownload device
parser.failed Parser Parser plugin gagal
webhook.delivered Webhook Webhook berhasil dikirim
webhook.failed Webhook Webhook gagal dikirim
webhook.retry Webhook Webhook masuk retry queue
webhook.disabled Webhook Webhook dinonaktifkan
system.started System Server start
system.shutdown System Server shutdown

Database Models

Model Table Key Fields
Merchant merchants id, name, api_key
Device devices device_id, merchant_id, secret, status, last_seen
Notification notifications device_id, app, amount, sender, fingerprint (unique), raw_text, parsed
PaymentExpectation payment_expectations merchant_id, order_id, amount, status, expires_at
WebhookEndpoint webhook_endpoints merchant_id, url, secret, active, events, payload_template
PairingCode pairing_codes merchant_id, code (unique), device_name, expires_at, used
WebhookLog webhook_logs webhook_id, merchant_id, order_id, amount, status, status_code, response, error_message, retry_count
APIKey api_keys merchant_id, name, key (unique), active, last_used
ParserPlugin parser_plugins package (unique), app, priority, version, active, amount_pattern, amount_group, amount_multiply, sender_pattern, sender_group, min_length, must_match
DeadLetter dead_letters webhook_id, merchant_id, order_id, amount, url, response, error_message, retry_count
EventLog event_logs event_id, event_type, delivery_id (unique), merchant_id, device_id, sequence, payload, status, status_code, response, error_message
Admin admins email (unique), password, name

Semua tabel auto-migrate saat server start.

API Endpoints

Public (no JWT required)

Method Path Deskripsi
POST /api/v1/auth/login Login dengan API Key → JWT token
POST /api/v1/auth/admin/login Login admin dengan email + password
GET /api/v1/health Health check (DB + Redis + WS connection count + uptime)
POST /api/v1/parsers/sync Cek versi parser config (Android)
GET /api/v1/parsers/config Download parser plugins config
POST /api/v1/pair/confirm Konfirmasi pairing device dengan kode
GET /api/v1/pair/qr/:code QR code PNG image untuk pairing

Protected (JWT required)

Method Path Deskripsi
POST /api/v1/devices/register Daftarkan perangkat Android langsung
GET /api/v1/devices List semua device terdaftar (paginated)
GET /api/v1/devices/:id/status Cek status online/offline device
POST /api/v1/payments/expect Buat payment expectation (invoice)
GET /api/v1/payments/pending Lihat pembayaran pending
GET /api/v1/notifications Riwayat notifikasi (paginated)
GET /api/v1/notifications/:id Detail notifikasi + matched order + device info
POST /api/v1/webhooks/register Daftarkan endpoint webhook (dengan event filter)
GET /api/v1/webhooks Lihat webhook terdaftar
POST /api/v1/webhooks/test Kirim webhook test dummy ke URL
POST /api/v1/webhooks/retry-all Retry semua webhook failed
GET /api/v1/webhooks/:id/logs Log delivery webhook (paginated)
POST /api/v1/webhooks/:id/retry Retry delivery webhook spesifik
POST /api/v1/pair/request Minta kode pairing device
GET /api/v1/dashboard Statistik dashboard (merchant, devices, notif, pending, paid, queue, WS, parsers)
GET /api/v1/api-keys List API keys merchant
POST /api/v1/api-keys Buat API key baru
DELETE /api/v1/api-keys/:id Revoke API key
GET /api/v1/parsers/plugins List parser plugins (paginated)
POST /api/v1/parsers/plugins Tambah parser plugin baru
PUT /api/v1/parsers/plugins/:id Update parser plugin
DELETE /api/v1/parsers/plugins/:id Hapus parser plugin
POST /api/v1/parsers/test Test parser terhadap teks notifikasi
GET /api/v1/dead-letters List dead letter queue (paginated)
POST /api/v1/dead-letters/:id/retry Retry dead letter
DELETE /api/v1/dead-letters/:id Hapus dead letter
POST /api/v1/events/replay Replay event dalam range waktu (max 7 hari)
GET /api/v1/backup Export backup konfigurasi merchant
POST /api/v1/backup Import backup konfigurasi merchant

Non-API

Method Path Deskripsi
GET / Web Dashboard (login → stats, parsers, API keys, backup, DLQ)
GET /ws WebSocket (auth via query: device_id + secret)
GET /metrics Prometheus metrics endpoint

Webhook Payload

Setiap webhook dikirim dengan envelope event:

{
  "id": "evt_01JY8Q8D5Z9P3...",
  "event": "payment.paid",
  "version": "1.0",
  "timestamp": "2026-07-20T12:00:00Z",
  "merchant_id": 1,
  "device_id": "device-01",
  "data": {
    "order_id": "INV001",
    "amount": 25250,
    "status": "paid",
    "device_id": "device-01"
  },
  "metadata": {
    "app": "DANA",
    "parser_version": 1,
    "bridge_version": "1.0",
    "device_model": "Pixel 7"
  }
}

Headers:

Header Deskripsi
X-QrisBridge-Event Nama event (e.g. payment.paid)
X-QrisBridge-Event-Id Unique event ID (evt_xxx)
X-QrisBridge-Delivery-Id Unique per delivery attempt (del_xxx)
X-QrisBridge-Signature HMAC-SHA256 hex digest — gunakan untuk verifikasi
X-QrisBridge-Timestamp Unix timestamp

Verifikasi signature di penerima:

HMAC-SHA256(body, secret) == X-QrisBridge-Signature

Parser Plugin Config

Parser didefinisikan di database parser_plugins table (dikelola via API/dashboard) dengan format:

{
  "package": "id.dana",
  "app": "DANA",
  "priority": 100,
  "version": 1,
  "active": true,
  "amount_pattern": "Rp\\s?([\\d.]+)",
  "amount_group": 1,
  "amount_multiply": 0,
  "sender_pattern": "dari\\s(.+)",
  "sender_group": 1,
  "min_length": 3,
  "must_match": "DANA|dana"
}

Android auto-sync parser config dari server via ParserSyncWorker (periodik tiap 6 jam). Tidak perlu update APK saat regex berubah.

Cara Pairing Device

Merchant Panel (Web)           Android App
      │                            │
      │  POST /api/v1/pair/request │
      │  { merchant_id, device }   │
      ├──── kode pairing ──────────►│
      │                            │
      │  POST /api/v1/pair/confirm │
      │  { code, device_id, secret}│
      ◄──────── OK ────────────────┤
      │                            │
      │  WebSocket connect         │
      │  (device_id + secret)      │

Card pairing dibuat dengan QR code: GET /api/v1/pair/qr/:code (return PNG). Response POST /api/v1/pair/confirm juga return JWT token untuk device. Pairing code expired dalam 5 menit.

Deployment Topologi

Internet
    │
    ▼
  Nginx (SSL/TLS termination + reverse proxy)
    │
    ▼
  Go Server (REST API + WebSocket + Worker)
    │
    ├──────────┬──────────┐
    ▼          ▼          ▼
  Redis     PostgreSQL  Webhook → POS / Toko
  (Stream    (Merchant,   (HMAC SHA256)
   Queue)     Device,
              Notification)

Quick Start

# Clone & run
git clone https://github.com/yourusername/qris-bridge
cd qris-bridge
docker compose up -d

# Login dapatkan JWT token
curl -X POST http://localhost:8080/api/v1/auth/login \
  -H "Content-Type: application/json" \
  -d '{"api_key":"your-api-key-here"}'
# → { "token": "eyJ...", "expires_in": 86400 }

# Buat invoice (pakai token dari atas)
curl -X POST http://localhost:8080/api/v1/payments/expect \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer <token>" \
  -d '{"order_id":"INV001","amount":25000,"expires_in_minutes":30}'

# Daftarkan webhook
curl -X POST http://localhost:8080/api/v1/webhooks/register \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer <token>" \
  -d '{"url":"https://toko.com/webhook","secret":"wh-secret-123"}'

# Buka dashboard
open http://localhost:8080
# Login dengan API Key yang dihasilkan saat pertama kali aplikasi dijalankan

Struktur Proyek

qris-bridge/
├── cmd/server/main.go              # Entry point Go server
├── internal/
│   ├── api/
│   │   ├── routes.go               # 36 REST endpoints + 3 non-API
│   │   └── auth.go                 # JWT login + admin login + middleware
│   ├── ws/handler.go               # WebSocket + auth + hub
│   ├── config/config.go            # Env-based configuration
│   ├── database/
│   │   ├── db.go                   # PostgreSQL + auto-migrate
│   │   └── models.go               # 12 models (GORM)
│   ├── parser/
│   │   ├── parser.go               # Regex parser (fallback)
│   │   └── plugin.go               # Plugin parser (priority, validator)
│   ├── matching/engine.go          # Smart matching engine
│   ├── eventbus/stream.go          # Redis Streams event bus
│   ├── worker/worker.go            # Stream consumer + retry processor
│   ├── webhook/
│   │   ├── dispatch.go             # Event dispatch + subscription filter
│   │   ├── deliver.go              # Webhook delivery + HMAC signing
│   │   └── deliver_retry.go        # Retry delivery
│   ├── queue/queue.go              # Retry queue (exponential backoff)
│   ├── dedup/dedup.go              # SHA256 duplicate detection
│   ├── redis/redis.go              # Redis client wrapper
│   ├── metrics/metrics.go          # Prometheus metrics
│   └── integration/                # Server-side integrations
├── parsers/
│   ├── plugins.json                # Plugin parser config (8 bank)
│   ├── dana.json, gopay.json       # Legacy per-app parsers
│   ├── ovo.json, bca.json
│   ├── brimo.json, mandiri.json
│   ├── bni.json, blu.json
├── schemas/                        # JSON Schema untuk setiap event
│   ├── payment.paid.json
│   ├── payment.detected.json
│   ├── notification.received.json
│   └── device.online.json
├── docs/
│   ├── API.md                      # Dokumentasi endpoint
│   ├── ARCHITECTURE.md             # Arsitektur detail
│   ├── ANDROID.md                  # Setup Android
│   ├── DEPLOYMENT.md               # Panduan deployment
│   ├── SECURITY.md                 # Threat model & mitigasi
│   └── events/                     # Dokumentasi setiap event type
│       ├── payment.paid.md
│       ├── payment.detected.md
│       ├── notification.received.md
│       └── device.online.md
├── monitoring/                     # Monitoring & observability
│   ├── grafana-dashboard.json
│   ├── prometheus-alerts.yml
│   └── loadtest.js
├── sdk/                            # Client libraries
│   ├── go/qrisbridge/              # Go SDK
│   ├── php/                        # PHP SDK (Composer)
│   ├── nodejs/                     # Node.js SDK (npm)
│   └── python/                     # Python SDK (pip)
├── integrations/                   # Merchant platform plugins
│   ├── laravel/                    # Laravel service provider
│   ├── woocommerce/                # WooCommerce plugin
│   ├── wordpress/                  # WordPress plugin
│   └── fastapi/                    # FastAPI middleware
├── web/dashboard/                  # Web dashboard (HTML/JS)
│   └── index.html                  # Login + 5 tabs: Dashboard, Parser, API Keys, Backup, Dead Letter
├── android-app/                    # Android Kotlin project
│   └── app/src/main/java/com/qrisbridge/
│       ├── service/
│       │   ├── NotificationListener.kt   # Tangkap notifikasi bank
│       │   ├── WebSocketService.kt       # Foreground WS service
│       │   ├── SyncWorker.kt             # WorkManager retry sender
│       │   ├── SyncScheduler.kt          # Scheduler helper
│       │   ├── ParserSyncWorker.kt       # Auto-update parser config
│       │   └── BootReceiver.kt           # Auto-start on boot
│       ├── parser/NotificationParser.kt  # Plugin + builtin parser
│       ├── data/
│       │   ├── local/                    # Room DB + DAO
│       │   └── remote/WebSocketClient.kt # OkHttp WS client
│       └── ui/MainActivity.kt            # Status dashboard
├── migrations/                     # SQL migration files
├── scripts/                        # Utility scripts
├── docker-compose.yml              # Go + PostgreSQL + Redis + Nginx
├── Dockerfile                      # Multi-stage build
├── nginx.conf                      # Reverse proxy + WS upgrade
└── README.md

Event Flow (End-to-End)

1. Customer bayar via QRIS (DANA/GoPay/OVO/dll)
2. Notifikasi masuk ke Android merchant
3. NotificationListenerService menangkap
4. Parser ekstrak nominal & pengirim
5. SHA256 fingerprint → cek duplikasi
6. Simpan ke Room DB
7. Kirim via WebSocket ke server
8. Server simpan ke PostgreSQL
9. Publish event ke Redis Stream
10. Worker consume stream
11. Matching engine cocokkan nominal
12. PaymentExpectation status → "paid"
13. Dispatch event ke webhook endpoints (sesuai subscription)
14. Webhook POST ke endpoint merchant
15. Jika gagal → masuk retry queue (30s, 1m, 2m, ... max 24h)
16. Jika max retry habis → pindah ke Dead Letter Queue

Android Components

Component Type Fungsi
NotificationListener NotificationListenerService Tangkap notifikasi dari 8 app bank
WebSocketService Service (Foreground) Maintain WS connection, kirim notif
SyncWorker WorkManager Kirim ulang notifikasi gagal (exp backoff)
ParserSyncWorker WorkManager Download parser config (tiap 6 jam)
BootReceiver BroadcastReceiver Auto-start service setelah reboot
WebSocketClient OkHttp Auto reconnect, heartbeat, offline queue

Tech Stack

  • Backend: Go 1.24, Gin, Gorilla WebSocket, GORM, PostgreSQL, Redis Streams, zerolog, Prometheus
  • Android: Kotlin, NotificationListenerService, Room, OkHttp, WorkManager
  • Infra: Docker Compose, Nginx, Alpine
  • Observability: Prometheus metrics, Grafana dashboard, structured JSON logging

SDK

Go

import "github.com/user/qris-bridge/sdk/go/qrisbridge"

client := qrisbridge.New("http://localhost:8080", "api-key-anda")
client.CreateExpectation("INV001", 25000)

PHP

use QrisBridge\Client;

$client = new Client('http://localhost:8080', 'api-key-anda');
$client->createExpectation('INV001', 25000);

Node.js

const { QrisBridgeClient } = require('qrisbridge');

const client = new QrisBridgeClient('http://localhost:8080', 'api-key-anda');
await client.createExpectation('INV001', 25000);

Python

from qrisbridge import QrisBridgeClient

client = QrisBridgeClient('http://localhost:8080', 'api-key-anda')
client.create_expectation('INV001', 25000)

Verifikasi webhook signature:

qrisbridge.VerifySignature(payload, signature, secret)
// PHP:  Client::verifySignature($payload, $signature, $secret)
// Node: QrisBridgeClient.verifySignature(payload, sig, secret)
// Python: client.verify_signature(payload, sig, secret)

Integrasi Merchant

Platform Direktori Cara Pakai
Laravel integrations/laravel/ Composer package, service provider, webhook controller
WooCommerce integrations/woocommerce/ WordPress plugin, auto-complete order
WordPress integrations/wordpress/ REST endpoint + qris_bridge_payment_received action
FastAPI integrations/fastapi/ Pydantic webhook handler, HMAC verification

Dashboard Web

Buka http://localhost:8080/, login dengan API Key merchant atau login admin (email + password). Terdapat 5 tab:

Tab Dashboard

  • Stat cards: merchant, perangkat terdaftar, online, notifikasi, pending payment, terverifikasi, success rate, antrean retry, webhook terdaftar, parser aktif, WS tersambung, latensi WS
  • Last notification detail (app, amount, sender, time) — klik untuk detail
  • Device table (device id, nama, status online/offline, terakhir)
  • Notification table (app, amount, sender, raw text, time) — klik untuk detail
  • Webhook table + register webhook form (dengan event subscription checkboxes)
  • Webhook logs (filter by webhook ID, retry individual/all failed)
  • Test webhook URL

Tab Parser

  • Parser plugins table (package, app, priority, version, status, amount pattern, sender pattern, edit/delete)
  • Tambah/edit parser plugin form
  • Test parser (paste notification text, lihat hasil parsing)

Tab API Keys

  • API keys table (name, status, last used, created, revoke)
  • Buat API key baru

Tab Backup

  • Export backup (download JSON konfigurasi merchant)
  • Import backup (paste JSON, restore konfigurasi)

Tab Dead Letter

  • Dead letter queue table (webhook, order, amount, error, retry count, time, retry/delete)

Semua tabel mendukung pagination. Auto-refresh setiap 15 detik.

Dokumentasi Detail

Dokumentasi lebih lengkap ada di folder docs/:

Dokumen Deskripsi
PRIVACY.md Kebijakan privasi & pemrosesan data
docs/THREAT_MODEL.md Threat model, data flow, compliance checklist
docs/ARCHITECTURE.md Arsitektur detail, aliran data, state machine
docs/API.md Dokumentasi semua endpoint + request/response
docs/ANDROID.md Setup, komponen, dan troubleshooting Android
docs/DEPLOYMENT.md Panduan deploy production + scaling
docs/SECURITY.md Threat model, mitigasi, checklist keamanan
docs/events/ Dokumentasi setiap event type (schema, payload, headers, changelog)

Benchmark

Test Result
WebSocket Concurrent Connections 5.000 koneksi simultan
Notification Throughput ~12.000 notifikasi/menit
Memory (idle) ~45 MB
CPU (idle) ~1% core
Webhook Delivery Latency (p50) ~200 ms
Webhook Delivery Latency (p95) ~800 ms

Angka di atas diukur pada VPS 2 core, 4 GB RAM, Redis & PostgreSQL di server yang sama. Performa aktual tergantung pada spesifikasi server, jumlah perangkat, dan beban parser.

Roadmap

Rilis Fitur
v0.1 ✅ Notification Bridge (Go + Android)
v0.2 ✅ Dashboard Web
v0.3 ✅ SDK (Go, PHP, Node.js, Python) + Integrasi (Laravel, WooCommerce, WordPress, FastAPI)
v0.4 ✅ Event-based Webhooks + Subscription Filter + Wildcard Events
v0.5 ✅ Dead Letter Queue + Bulk Retry + Replay Events
v0.6 ✅ Parser Management UI + Parser Test + Multi-API Key
v0.7 ✅ Backup & Restore + Admin Auth + Webhook Test
v0.8 ✅ Prometheus Metrics + Event Schemas + Event Registry Docs
v0.9 🔲 iOS Companion
v1.0 🔲 High Availability (multi-region Redis/PostgreSQL)
v1.1 🔲 Grafana Dashboard Advanced
v1.2 🔲 Stable Release + Security Audit

License

AGPL-3.0 — see LICENSE file.

Proyek ini menggunakan GNU Affero General Public License v3.0 (AGPL-3.0). Lisensi ini dipilih secara khusus karena:

  • Tidak mengizinkan penggunaan komersial tertutup — jika Anda menjalankan server QRIS Bridge sebagai layanan publik (hosting), Anda wajib membuka source code modifikasi Anda kepada semua pengguna yang berinteraksi melalui jaringan.
  • Tidak ada lisensi komersial terpisah — tidak ada dual-license. AGPL-3.0 adalah satu-satunya lisensi yang berlaku. Tidak ada opsi untuk menggunakan kode ini dalam produk komersial tertutup tanpa membuka source code.
  • Copyleft — setiap modifikasi harus dirilis dengan lisensi yang sama.

Kapan AGPL berlaku?

AGPL-3.0 berlaku jika Anda:

  • Menggunakan server QRIS Bridge secara publik (hosting)
  • Memodifikasi source code dan menjalankannya sebagai layanan jaringan
  • Wajib membuka source code modifikasi kepada pengguna yang berinteraksi melalui jaringan

Dokumen Hukum

Dokumen Deskripsi
Terms of Use Syarat penggunaan yang mengikat secara hukum — wajib dibaca sebelum menggunakan
Disclaimer Pernyataan tanggung jawab, batasan teknis & hukum
Trademark Disclaimer Penggunaan nama merek dagang pihak ketiga (fair use)
Privacy Policy Informasi pemrosesan data sesuai UU PDP
Threat Model & Compliance Analisis kepatuhan teknis terhadap UU ITE, UU PDP, ToS e-wallet

About

No description, website, or topics provided.

Resources

Code of conduct

Contributing

Security policy

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages