Rute Bayar is an open source payment router for Indonesian payment gateways.
The project provides one internal interface for multiple providers, starting with Xendit and Midtrans. It is designed as a Go CLI and daemon that can create payments, receive provider webhooks, store raw JSON traffic for debugging, and optionally forward incoming webhooks to user-configured targets.
Status: alpha preview. The repository already includes webhook signature verification for Midtrans and callback-token verification for Xendit, plus Midtrans and Xendit
pay create,pay status,pay refund,reconcile, and SQLite persistence. Webhook forwarding target management is also available via CLI.
Latest alpha release: v0.1.0-alpha.3
- Modular provider adapters.
- CLI-first onboarding and operations.
- Webhook daemon per provider.
- Pass-through webhook forwarding.
- Raw inbound and outbound JSON storage for debugging and audit.
- SQLite-first local storage.
- Initial support target: Xendit Payment Sessions and Midtrans.
Clone the repository:
git clone git@github.com:pendig/rute-bayar.git
cd rute-bayarInstall Go 1.22 or newer, then check the CLI:
go run ./cmd/rute-bayar version
go run ./cmd/rute-bayar provider listOnboard Xendit credentials into local SQLite:
rute-bayar onboard xendit --secret-key "$XENDIT_SECRET_KEY" --environment sandbox
rute-bayar provider accountsOnboard Midtrans credentials into local SQLite:
rute-bayar onboard midtrans --merchant-id "$MIDTRANS_MERCHANT_ID" --client-key "$MIDTRANS_CLIENT_KEY" --server-key "$MIDTRANS_SERVER_KEY" --environment sandbox
rute-bayar provider test midtransStart the webhook daemon:
go run ./cmd/rute-bayar webhook serve --addr :8080 --environment sandboxCheck the daemon:
curl http://localhost:8080/healthzRun daemon and verify:
go run ./cmd/rute-bayar webhook serve --addr :8080 --environment sandbox
curl -i http://localhost:8080/healthzExpected:
{"status":"ok"}Send a local webhook simulation:
curl -X POST http://localhost:8080/webhooks/xendit \
-H 'Content-Type: application/json' \
-d '{"event":"payment_session.created","status":"ACTIVE"}'If you need a public URL for provider callback testing:
wrangler tunnel quick-start http://localhost:8080After Cloudflare prints a public URL (for example https://xxxx.trycloudflare.com), verify:
curl -i https://xxxx.trycloudflare.com/healthzSet provider webhook URL to:
https://xxxx.trycloudflare.com/webhooks/xendit
https://xxxx.trycloudflare.com/webhooks/midtrans
The daemon verifies webhook signatures when provider credentials/configuration support it:
- Midtrans:
signature_keyis validated withorder_id + status_code + gross_amount + server_key. - Xendit: callback token validation uses
X-Callback-Tokenwhen configured on onboarding.
Note: if the provider credentials/configuration are not present, webhook verification is skipped and requests are stored as raw inbound payloads for debugging.
Build a local binary:
go build -o bin/rute-bayar ./cmd/rute-bayarRun it:
./bin/rute-bayar versionInstall into your Go binary path:
go install github.com/pendig/rute-bayar/cmd/rute-bayar@latestFor alpha builds, prefer the latest tagged release or a local build from main.
Available command skeleton:
rute-bayar onboard
rute-bayar onboard xendit --secret-key <key> --environment sandbox
rute-bayar onboard midtrans --merchant-id <id> --client-key <key> --server-key <key> --environment sandbox
rute-bayar provider list
rute-bayar provider accounts
rute-bayar provider test midtrans
rute-bayar provider test xendit
rute-bayar pay create --provider xendit --method payment_link --reference rb-xnd-001 --amount 15000
rute-bayar pay create --provider midtrans --method bank_transfer --bank bca --reference rb-0001 --amount 15000
rute-bayar pay status --provider midtrans --reference rb-0001
rute-bayar pay refund
rute-bayar webhook serve --addr :8080
rute-bayar webhook forward list
rute-bayar webhook forward add
rute-bayar webhook forward update
rute-bayar webhook forward remove
rute-bayar webhook replay --event-id <id> [--provider midtrans|xendit]
rute-bayar webhook forward attempts list --status failed
rute-bayar webhook forward attempts show <attempt-id>
rute-bayar webhook forward attempts retry <attempt-id>
rute-bayar db migrate
rute-bayar reconcile
rute-bayar versionThese commands establish the current user experience for alpha internal usage.
Copy the example environment file:
cp .env.example .envDefault local configuration:
RUTE_BAYAR_ENV=sandbox
RUTE_BAYAR_DB_PATH=./rute-bayar.sqlite3
RUTE_BAYAR_WEBHOOK_ADDR=:8080Do not commit .env or provider credentials. The file is ignored by Git.
bind: operation not permittedwhen starting daemon: environment may block local socket binding; try another port or run in a normal local terminal.502fromtrycloudflare.com: confirm the local daemon is running and still reachable at the forwarded local URL.- DNS resolve failure for
*.trycloudflare.com: usually environment/network-restricted; retry in another network/tool environment.
Run formatting and tests:
gofmt -w ./cmd ./internal
go test ./...
./scripts/smoke-local.shValidate the SQLite migration:
sqlite3 :memory: ".read migrations/0001_initial.sql"Project layout:
cmd/rute-bayar: CLI entrypoint.internal/cli: command routing.internal/daemon: HTTP daemon for webhook receiving.internal/domain: provider-neutral domain types.internal/provider: provider adapter contracts and registry.internal/forwarding: pass-through webhook forwarding service.internal/storage: storage implementations.migrations: SQLite schema migrations.docs: product and technical documentation.
Run the initial migration through the CLI:
rute-bayar db migrateXendit sandbox simulation has been tested with Payment Sessions:
POST /sessionscreates a Payment Session.GET /sessions/{session_id}retrieves status.- Initial Xendit
ACTIVEstatus maps naturally to Rute Bayarpending. items[].categoryis required for the tested Payment Session payload.
See docs/xendit-sandbox-simulation.md.
- Modular per provider.
- Keep provider-specific behavior inside adapter packages.
- Store inbound and outbound payloads as raw JSON.
- Keep webhook forwarding pass-through by default.
- Make CLI onboarding simple before asking users to configure providers manually.
- Start with SQLite, but keep the domain portable.
Read the project docs:
- Product Requirements
- Architecture
- Model Data
- CLI Onboarding
- Provider Integration
- Implementation Status
- Webhook Forwarding
- Status Mapping
- Operations Runbook
- End-to-End Smoke Test
- Development
- Changelog
- Xendit Sandbox Simulation
- Midtrans Sandbox Simulation
Rute Bayar is released under the MIT License.
Copyright (c) 2026 Wahyu Adi Putra Pena Digital.
- Stabilize Midtrans refund E2E when sandbox payable balance is available.
- Add more Midtrans payment methods and provider-specific diagnostics.
- Improve operational observability for webhook forwarding and replay.
- Prepare stable
v0.1.0once release-readiness checks are complete.