[{"data":1,"prerenderedAt":-1},["ShallowReactive",2],{"project-81762":3},{"id":4,"name":5,"fullName":6,"owner":7,"repo":5,"description":8,"homepage":9,"htmlUrl":10,"language":11,"languages":10,"totalLinesOfCode":10,"stars":12,"forks":13,"watchers":14,"openIssues":15,"contributorsCount":16,"subscribersCount":16,"size":16,"stars1d":16,"stars7d":14,"stars30d":14,"stars90d":16,"forks30d":16,"starsTrendScore":16,"compositeScore":17,"rankGlobal":10,"rankLanguage":10,"license":18,"archived":19,"fork":19,"defaultBranch":20,"hasWiki":21,"hasPages":21,"topics":22,"createdAt":10,"pushedAt":10,"updatedAt":32,"readmeContent":33,"aiSummary":34,"trendingCount":16,"starSnapshotCount":16,"syncStatus":14,"lastSyncTime":35,"discoverSource":36},81762,"rute-bayar","pendig\u002Frute-bayar","pendig","Open source payment router for Indonesian payment gateways.","http:\u002F\u002Frutebayar.id\u002F",null,"Go",26,6,2,18,0,43.74,"MIT License",false,"main",true,[23,24,25,26,27,28,29,30,31],"cli","go","indonesia","midtrans","payment-gateway","payment-router","sqlite","webhook","xendit","2026-06-12 04:01:35","# Rute Bayar\n\n![Rute Bayar banner](.\u002Fassets\u002Fbrand\u002Frutebayarid-banner-compress.png)\n\n[![CI](https:\u002F\u002Fgithub.com\u002Fpendig\u002Frute-bayar\u002Factions\u002Fworkflows\u002Fci.yml\u002Fbadge.svg)](https:\u002F\u002Fgithub.com\u002Fpendig\u002Frute-bayar\u002Factions\u002Fworkflows\u002Fci.yml)\n[![Release](https:\u002F\u002Fgithub.com\u002Fpendig\u002Frute-bayar\u002Factions\u002Fworkflows\u002Frelease.yml\u002Fbadge.svg)](https:\u002F\u002Fgithub.com\u002Fpendig\u002Frute-bayar\u002Factions\u002Fworkflows\u002Frelease.yml)\n[![GitHub Release](https:\u002F\u002Fimg.shields.io\u002Fgithub\u002Fv\u002Frelease\u002Fpendig\u002Frute-bayar?include_prereleases)](https:\u002F\u002Fgithub.com\u002Fpendig\u002Frute-bayar\u002Freleases)\n[![License: MIT](https:\u002F\u002Fimg.shields.io\u002Fbadge\u002FLicense-MIT-yellow.svg)](.\u002FLICENSE)\n[![Go Reference](https:\u002F\u002Fpkg.go.dev\u002Fbadge\u002Fgithub.com\u002Fpendig\u002Frute-bayar.svg)](https:\u002F\u002Fpkg.go.dev\u002Fgithub.com\u002Fpendig\u002Frute-bayar)\n\nRute Bayar is an open source payment router for Indonesian payment gateways.\n\nThe 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.\n\n> Status: stable `v0.1.4`. The repository 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. Real sandbox proof covers Midtrans\u002FXendit webhook callbacks and Xendit refund reconciliation through final `refund.succeeded` callback. Webhook forwarding target management is also available via CLI.\n\nLatest release: [v0.1.4](https:\u002F\u002Fgithub.com\u002Fpendig\u002Frute-bayar\u002Freleases\u002Ftag\u002Fv0.1.4)\n\n## Features\n\n- Modular provider adapters.\n- CLI-first onboarding and operations.\n- Webhook daemon per provider.\n- Pass-through webhook forwarding.\n- Raw inbound and outbound JSON storage for debugging and audit.\n- SQLite-first local storage.\n- Initial support target: Xendit Payment Sessions and Midtrans.\n\n## Quick Start\n\nClone the repository:\n\n```bash\ngit clone git@github.com:pendig\u002Frute-bayar.git\ncd rute-bayar\n```\n\nInstall Go 1.22 or newer, then check the CLI:\n\n```bash\ngo build -o bin\u002Frutebayar .\u002Fcmd\u002Frute-bayar\n.\u002Fbin\u002Frutebayar version\n.\u002Fbin\u002Frutebayar provider list\n```\n\nOnboard Xendit credentials into local SQLite:\n\n```bash\n.\u002Fbin\u002Frutebayar onboard xendit --secret-key \"$XENDIT_SECRET_KEY\" --environment sandbox\n.\u002Fbin\u002Frutebayar provider accounts\n```\n\nOnboard Midtrans credentials into local SQLite:\n\n```bash\n.\u002Fbin\u002Frutebayar onboard midtrans --merchant-id \"$MIDTRANS_MERCHANT_ID\" --client-key \"$MIDTRANS_CLIENT_KEY\" --server-key \"$MIDTRANS_SERVER_KEY\" --environment sandbox\n.\u002Fbin\u002Frutebayar provider test midtrans\n```\n\nStart the webhook daemon:\n\n```bash\n.\u002Fbin\u002Frutebayar webhook serve --addr :8080 --environment sandbox\n```\n\nCheck the daemon:\n\n```bash\ncurl http:\u002F\u002Flocalhost:8080\u002Fhealthz\n```\n\n### Local Webhook + Health Check\n\nRun daemon and verify:\n\n```bash\n.\u002Fbin\u002Frutebayar webhook serve --addr :8080 --environment sandbox\ncurl -i http:\u002F\u002Flocalhost:8080\u002Fhealthz\n```\n\nExpected:\n\n```json\n{\"status\":\"ok\"}\n```\n\nSend a local webhook simulation:\n\n```bash\ncurl -X POST http:\u002F\u002Flocalhost:8080\u002Fwebhooks\u002Fxendit \\\n  -H 'Content-Type: application\u002Fjson' \\\n  -d '{\"event\":\"payment_session.created\",\"status\":\"ACTIVE\"}'\n```\n\n### Cloudflare Tunnel Test (temporary)\n\nIf you need a public URL for provider callback testing:\n\n```bash\nwrangler tunnel quick-start http:\u002F\u002Flocalhost:8080\n```\n\nAfter Cloudflare prints a public URL (for example `https:\u002F\u002Fxxxx.trycloudflare.com`), verify:\n\n```bash\ncurl -i https:\u002F\u002Fxxxx.trycloudflare.com\u002Fhealthz\n```\n\nSet provider webhook URL to:\n\n```text\nhttps:\u002F\u002Fxxxx.trycloudflare.com\u002Fwebhooks\u002Fxendit\nhttps:\u002F\u002Fxxxx.trycloudflare.com\u002Fwebhooks\u002Fmidtrans\n```\n\nThe daemon verifies webhook signatures when provider credentials\u002Fconfiguration support it:\n- Midtrans: `signature_key` is validated with `order_id + status_code + gross_amount + server_key`.\n- Xendit: callback token validation uses `X-Callback-Token` when configured on onboarding.\n\nNote: if the provider credentials\u002Fconfiguration are not present, webhook verification is skipped and requests are stored as raw inbound payloads for debugging.\n\n## Installation\n\n### Fast install\n\nUse one command to detect OS and install latest stable binary:\n\n```bash\ncurl -fsSL https:\u002F\u002Fraw.githubusercontent.com\u002Fpendig\u002Frute-bayar\u002Fmain\u002Fscripts\u002Finstall.sh | bash\n```\n\nOptional flags:\n\n```bash\n# install to local user bin only\ncurl -fsSL https:\u002F\u002Fraw.githubusercontent.com\u002Fpendig\u002Frute-bayar\u002Fmain\u002Fscripts\u002Finstall.sh | bash -s -- --local\n\n# pin version\ncurl -fsSL https:\u002F\u002Fraw.githubusercontent.com\u002Fpendig\u002Frute-bayar\u002Fmain\u002Fscripts\u002Finstall.sh | bash -s -- --version v0.1.4\n```\n\n### Make sure command is in your shell PATH\n\nIf installation succeeds but `rutebayar` command is not found, ensure your binary folder is on PATH.\n\nHomebrew paths are usually:\n\n- Apple Silicon macOS: `\u002Fopt\u002Fhomebrew\u002Fbin`\n- Intel macOS: `\u002Fusr\u002Flocal\u002Fbin`\n- Linuxbrew: `~\u002F.linuxbrew\u002Fbin` or `\u002Fhome\u002Flinuxbrew\u002F.linuxbrew\u002Fbin`\n\n```bash\nif command -v brew >\u002Fdev\u002Fnull 2>&1; then\n  eval \"$(brew shellenv)\"\nfi\nwhich rutebayar\n```\n\nIf you used binary download and placed it in a local folder, run from that folder with `.\u002Frutebayar`, or move it to a PATH folder:\n\n```bash\nchmod +x .\u002Frutebayar\nmkdir -p ~\u002F.local\u002Fbin\nmv .\u002Frutebayar ~\u002F.local\u002Fbin\u002Frutebayar\nexport PATH=\"$HOME\u002F.local\u002Fbin:$PATH\"\n```\nTo persist PATH for future shells, add to your shell profile:\n\n```bash\n# For zsh\necho 'export PATH=\"$HOME\u002F.local\u002Fbin:$PATH\"' >> ~\u002F.zshrc\n\n# For bash\necho 'export PATH=\"$HOME\u002F.local\u002Fbin:$PATH\"' >> ~\u002F.bashrc\n```\n\nInstall with Homebrew:\n\n```bash\nbrew tap pendig\u002Ftap\nbrew install rutebayar\nrutebayar version\n```\n\nBuild a local binary:\n\n```bash\ngo build -o bin\u002Frutebayar .\u002Fcmd\u002Frute-bayar\n```\n\nRun it:\n\n```bash\n.\u002Fbin\u002Frutebayar version\n```\n\nInstall into your Go binary path:\n\n```bash\ngo install github.com\u002Fpendig\u002Frute-bayar\u002Fcmd\u002Frute-bayar@latest\nmv $(go env GOPATH)\u002Fbin\u002Frute-bayar $(go env GOPATH)\u002Fbin\u002Frutebayar\n```\n\nFor stable builds, prefer the latest tagged release or a local build from `main`.\n\n\n## Usage\n\nAvailable command skeleton:\n\n```bash\nrutebayar onboard\nrutebayar onboard xendit --secret-key \u003Ckey> --environment sandbox\nrutebayar onboard midtrans --merchant-id \u003Cid> --client-key \u003Ckey> --server-key \u003Ckey> --environment sandbox\nrutebayar provider list\nrutebayar provider accounts\nrutebayar provider test midtrans\nrutebayar provider test xendit\nrutebayar pay create --provider xendit --method payment_link --reference rb-xnd-001 --amount 15000\nrutebayar pay create --provider midtrans --method bank_transfer --bank bca --reference rb-0001 --amount 15000\nrutebayar pay create --provider midtrans --method qris --bank gopay --reference rb-qris-001 --amount 15000 --notification-url https:\u002F\u002F\u003Cpublic-domain>\u002Fwebhooks\u002Fmidtrans\nrutebayar pay status --provider midtrans --reference rb-0001\nrutebayar pay refund\nrutebayar webhook serve --addr :8080\nrutebayar webhook forward list\nrutebayar webhook forward add\nrutebayar webhook forward update\nrutebayar webhook forward remove\nrutebayar webhook replay --event-id \u003Cid> [--provider midtrans|xendit]\nrutebayar webhook forward attempts list --status failed\nrutebayar webhook forward attempts show \u003Cattempt-id>\nrutebayar webhook forward attempts retry \u003Cattempt-id>\nrutebayar db migrate\nrutebayar reconcile\nrutebayar version\n```\n\nThese commands establish the current user experience for alpha internal usage.\n\n## Configuration\n\nCopy the example environment file:\n\n```bash\ncp .env.example .env\n```\n\nDefault local configuration:\n\n```env\nRUTE_BAYAR_ENV=sandbox\nRUTE_BAYAR_DB_PATH=.\u002Frute-bayar.sqlite3\nRUTE_BAYAR_WEBHOOK_ADDR=:8080\n```\n\nDo not commit `.env` or provider credentials. The file is ignored by Git.\n\n### Troubleshooting\n\n- `bind: operation not permitted` when starting daemon: environment may block local socket binding; try another port or run in a normal local terminal.\n- `502` from `trycloudflare.com`: confirm the local daemon is running and still reachable at the forwarded local URL.\n- DNS resolve failure for `*.trycloudflare.com`: usually environment\u002Fnetwork-restricted; retry in another network\u002Ftool environment.\n\n## Development\n\nRun formatting and tests:\n\n```bash\ngofmt -w .\u002Fcmd .\u002Finternal\ngo test .\u002F...\n.\u002Fscripts\u002Fsmoke-local.sh\n```\n\nValidate the SQLite migration:\n\n```bash\nsqlite3 :memory: \".read migrations\u002F0001_initial.sql\"\n```\n\nProject layout:\n\n- `cmd\u002Frute-bayar`: CLI entrypoint.\n- `internal\u002Fcli`: command routing.\n- `internal\u002Fdaemon`: HTTP daemon for webhook receiving.\n- `internal\u002Fdomain`: provider-neutral domain types.\n- `internal\u002Fprovider`: provider adapter contracts and registry.\n- `internal\u002Fforwarding`: pass-through webhook forwarding service.\n- `internal\u002Fstorage`: storage implementations.\n- `migrations`: SQLite schema migrations.\n- `docs`: product and technical documentation.\n\nUseful docs:\n\n- [Production Deployment](.\u002Fdocs\u002Fproduction-deployment.md)\n- [Operations Runbook](.\u002Fdocs\u002Foperations-runbook.md)\n- [Release Readiness](.\u002Fdocs\u002Frelease-readiness.md)\n\nRun the initial migration through the CLI:\n\n```bash\nrutebayar db migrate\n```\n\n## Provider Notes\n\nXendit sandbox simulation has been tested with Payment Sessions and refund callbacks:\n\n- `POST \u002Fsessions` creates a Payment Session.\n- `GET \u002Fsessions\u002F{session_id}` retrieves status.\n- `POST \u002Frefunds` creates an async refund request.\n- Initial Xendit `ACTIVE` status maps naturally to Rute Bayar `pending`.\n- Final Xendit `refund.succeeded` callbacks reconcile stored refunds and update the local payment intent to `refunded`.\n- `items[].category` is required for the tested Payment Session payload.\n\nSee [docs\u002Fxendit-sandbox-simulation.md](.\u002Fdocs\u002Fxendit-sandbox-simulation.md) and [docs\u002Frelease\u002Fissue-40-xendit-refund-e2e-proof.md](.\u002Fdocs\u002Frelease\u002Fissue-40-xendit-refund-e2e-proof.md).\n\n## Design Principles\n\n- Modular per provider.\n- Keep provider-specific behavior inside adapter packages.\n- Store inbound and outbound payloads as raw JSON.\n- Keep webhook forwarding pass-through by default.\n- Make CLI onboarding simple before asking users to configure providers manually.\n- Start with SQLite, but keep the domain portable.\n\n## Documentation\n\nRead the project docs:\n\n- [Product Requirements](.\u002Fdocs\u002Fprd.md)\n- [Architecture](.\u002Fdocs\u002Farchitecture.md)\n- [Model Data](.\u002Fdocs\u002Fdata-model.md)\n- [CLI Onboarding](.\u002Fdocs\u002Fcli-onboarding.md)\n- [Provider Integration](.\u002Fdocs\u002Fprovider-integration.md)\n- [Implementation Status](.\u002Fdocs\u002Fimplementation-status.md)\n- [Webhook Forwarding](.\u002Fdocs\u002Fwebhook-forwarding.md)\n- [Status Mapping](.\u002Fdocs\u002Fstatus-mapping.md)\n- [Operations Runbook](.\u002Fdocs\u002Foperations-runbook.md)\n- [End-to-End Smoke Test](.\u002Fdocs\u002Fend-to-end-smoke.md)\n- [Development](.\u002Fdocs\u002Fdevelopment.md)\n- [Changelog](.\u002FCHANGELOG.md)\n- [Xendit Sandbox Simulation](.\u002Fdocs\u002Fxendit-sandbox-simulation.md)\n- [Midtrans Sandbox Simulation](.\u002Fdocs\u002Fmidtrans-sandbox-simulation.md)\n- [Release Readiness](.\u002Fdocs\u002Frelease-readiness.md)\n\n## Community\n\n- [Contributing](.\u002FCONTRIBUTING.md)\n- [Code of Conduct](.\u002FCODE_OF_CONDUCT.md)\n- [Security Policy](.\u002FSECURITY.md)\n- [Support](.\u002FSUPPORT.md)\n- [Issues](https:\u002F\u002Fgithub.com\u002Fpendig\u002Frute-bayar\u002Fissues)\n- [Releases](https:\u002F\u002Fgithub.com\u002Fpendig\u002Frute-bayar\u002Freleases)\n\n## License\n\nRute Bayar is released under the [MIT License](.\u002FLICENSE).\n\nCopyright (c) 2026 Wahyu Adi Putra Pena Digital.\n\n## Roadmap\n\n- Stabilize Midtrans refund E2E when sandbox payable balance is available.\n- Complete final stable readiness pass for `v0.1.0` before publishing a non-alpha release.\n- Add more Midtrans payment methods and provider-specific diagnostics.\n- Improve operational observability for webhook forwarding and replay.\n- Add Doku as the next provider family.\n","Rute Bayar 是一个面向印尼支付网关的开源支付路由工具。该项目通过统一的内部接口支持多个支付提供商，目前包括Xendit和Midtrans，提供创建支付、接收并处理提供商的webhook、存储原始JSON数据以便于调试及审计等功能，并可选择性地将接收到的webhook转发到用户配置的目标地址。它采用Go语言编写，以CLI形式运行，并使用SQLite作为首选本地存储方案。Rute Bayar适用于需要整合多种支付渠道但希望简化集成过程的企业或开发者，在电子商务平台、在线服务等领域特别有用。","2026-06-11 04:06:17","CREATED_QUERY"]