Skip to content
velixioPublic

About

Self-hosted payment orchestration in one Go binary: Razorpay, Stripe, Cashfree, PayU, Zoho Payments and Whop behind one API, one ledger and one webhook endpoint, with GST invoicing, subscriptions and UPI AutoPay.

Topics

Resources

Contributing

Security policy

Stars

3 stars

Watchers

0 watching

Forks

Latest commit

ย 

History

1,630 Commits

Folders and files

NameName
Last commit message
Last commit date
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 

Repository files navigation

Paymux

Self-hosted payment orchestration for small teams

One webhook endpoint. One ledger. Every payment gateway.
Razorpay ยท Stripe ยท Cashfree ยท PayU ยท Zoho Payments ยท Whop, or any gateway you add, in a single Go binary with GST invoicing built in.

Release CI License: Apache-2.0 Go SQLite or PostgreSQL Status: beta views

Quick start ยท Why Paymux ยท Gateways ยท GST for India ยท Docs ยท FAQ

Paymux dashboard: payments from every app and gateway in one list

๐Ÿ˜ฉ Why Paymux

Payment gateways give your company one account and one webhook URL. The moment you run two or three products on it, every product receives every payment notification, and each app grows its own copy of the same refund screen, dispute tracking and reconciliation code. Your accountant still wants GST invoices.

Paymux sits between your apps and your gateways and does that work once.

Without Paymux With Paymux
Every app integrates every gateway Each app integrates once, with a small JSON API
One gateway webhook URL shared by all your sites Paymux receives, verifies and forwards a signed event to the right app only
Payments, refunds and disputes spread over five dashboards One ledger, one dashboard
Changing gateway means rewriting checkout code Routing rules pick the gateway by currency, app or amount
GST invoices typed by hand Tax invoices and credit notes issued automatically
 app A โ”€โ”                                    โ”Œโ”€ Razorpay
 app B โ”€โ”ผโ”€โ”€ /v1 API โ”€โ”€โ–บ   Paymux   โ—„โ”€ webhooks โ”€โ”ผโ”€ Stripe ยท Cashfree
 app C โ”€โ”˜ โ—„โ”€โ”€ signed webhooks โ”€โ”€โ”˜            โ”œโ”€ PayU India ยท Zoho Payments
                                             โ”œโ”€ Whop
                                             โ””โ”€ your own gateway (Go package or HTTP service)

โœจ What you get

  • ๐Ÿ”€ Smart routing. Rules by app, currency, country and amount, daily/weekly/monthly sales or amount limits, and a circuit breaker that skips a gateway that keeps failing.
  • ๐Ÿ“’ One trustworthy ledger. Payments, refunds, disputes, subscriptions and payouts. A gateway webhook is only a hint: Paymux re-fetches the truth before it changes anything.
  • ๐Ÿงพ GST invoices out of the box. CGST/SGST or IGST, LUT exports, credit notes, e-invoice JSON, digitally signed PDFs.
  • ๐Ÿ” Subscriptions. Gateway-managed (Razorpay, Stripe, Whop) and Paymux-managed on UPI AutoPay, card and e-mandates, with dunning and RBI pre-debit rules.
  • ๐Ÿ”” Signed webhooks to your apps in the Standard Webhooks format, with retries, exact attempt history and replay; optional email or Telegram operator notifications cover important payment and dispute events.
  • ๐Ÿ”— Hosted pay pages and payment links. Themed, translated (English, Hindi), mobile-friendly, on your own domains.
  • ๐Ÿ–ฅ๏ธ A real dashboard. Payments, disputes, reconciliation, invoices, reports, alerts, audit log, roles, 2FA, and an error log you can search by request id.
  • ๐Ÿงฉ Extensible. Write a connector for any gateway, add Go or JavaScript hooks, theme the pages. Your changes survive upgrades.
  • ๐Ÿ“ฆ One binary, no cluster. SQLite out of the box, PostgreSQL when you grow. Sized for small teams: the load test holds 20 payment requests a second (docs/performance.md). No Kubernetes fleet required.

The complete list is in docs/features.md.

๐Ÿฆ Supported payment gateways

Gateway Payments Refunds Subscriptions Disputes Checked against the real sandbox
Razorpay โœ… โœ… โœ… INR โœ… โœ… payments, refunds, subscriptions, webhooks
Stripe โœ… โœ… โœ… โœ… โœ… payments, refunds, subscriptions, webhooks
Cashfree โœ… โœ… none none โœ… payments, refunds, webhooks
PayU India โœ… โœ… ๐ŸŸก mandates ๐ŸŸก chargebacks โœ… payments, refunds. Recurring needs PayU to enable it on the merchant
Zoho Payments โœ… ๐ŸŸก ๐ŸŸก UPI AutoPay none ๐ŸŸก payments โœ… (sandbox, Oct 2026); refunds and UPI AutoPay pending
Whop โœ… โœ… โœ… ๐ŸŸก โœ… payments, refunds, subscriptions, webhooks
Your own any any any any Go package or a small signed HTTP service

โœ… working and tested ยท ๐ŸŸก built, one external step still open. What each gateway can do, exactly: docs/capabilities.md.

Any other gateway can be added. Paymux is not limited to the list above. A connector can be:

  • A Go package compiled into your binary, written against a small public SDK.
  • A small HTTP service in any language (TypeScript, Python, PHPโ€ฆ) that Paymux calls over signed requests. You deploy and upgrade it on its own, with no fork of Paymux.

Either way, the same conformance kit the built-in gateways pass tells you when your connector is right. Once added, it works like any other gateway: routing, refunds, subscriptions, disputes, reconciliation and the dashboard. See docs/connectors.md.

๐Ÿš€ Quick start in 5 minutes

You do not need a gateway account to try it: the built-in simulator plays one.

Download

Prebuilt binaries of the latest release. Each link always points at the newest version.

Platform Download
Linux, x86-64 paymux_linux_amd64.tar.gz
Linux, ARM64 paymux_linux_arm64.tar.gz
macOS, Intel paymux_darwin_amd64.tar.gz
macOS, Apple silicon paymux_darwin_arm64.tar.gz

Install it with one command. The script picks the right binary, checks its checksum and, when cosign is installed, its signature, then installs it (options):

curl -fsSL https://github.com/velixio/paymux/releases/latest/download/install.sh | sh

Or verify a download by hand. SHA256SUMS is signed with cosign by the release workflow itself:

f=paymux_linux_amd64.tar.gz; base=https://github.com/velixio/paymux/releases/latest/download
curl -LO $base/$f -LO $base/SHA256SUMS -LO $base/SHA256SUMS.sigstore.json
cosign verify-blob --bundle SHA256SUMS.sigstore.json --new-bundle-format \
  --certificate-identity-regexp '^https://github\.com/velixio/paymux/\.github/workflows/release\.yml@refs/tags/v' \
  --certificate-oidc-issuer https://token.actions.githubusercontent.com SHA256SUMS
sha256sum --ignore-missing -c SHA256SUMS && tar xzf $f

The signature is a Sigstore bundle, so use cosign v3 (v2.6 also works with --new-bundle-format). v0.1.0 was signed before the bundle: for it, download SHA256SUMS.sig and SHA256SUMS.pem and verify with --signature SHA256SUMS.sig --certificate SHA256SUMS.pem instead.

Later, paymux update installs a newer release and checks the same signature.

Build from source

You need Go and Bun. Go fetches the pinned toolchain by itself.

git clone https://github.com/velixio/paymux.git && cd paymux
make build               # the hub, the website and the examples, into bin/

Then run it.

cp .env.example .env     # then set PAYMUX_MASTER_KEY:  head -c32 /dev/urandom | base64
./bin/paymux             # starts on :8080 and prints a one-time setup code

Open http://localhost:8080/setup: the first-run setup wizard asks for the code, creates your admin account (with 2FA) and a first app. Then take a payment:

curl -s localhost:8080/v1/payments \
  -H "Authorization: Bearer pmx_test_sk_..." \
  -H "Idempotency-Key: order-123" \
  -d '{"amount":49900,"currency":"INR","order_ref":"order-123","description":"Pro plan"}'
# โ†’ { "id": "TuSgrD0tRwOTok", "status": "created", "checkout_mode": "hosted", "checkout_url": "https://โ€ฆ/pay/TuSgrD0tRwOTok?t=โ€ฆ" }

Send your customer to checkout_url. Your app learns the result from a signed webhook or from GET /v1/payments/{id}. Never trust the browser redirect on its own.

JavaScript and TypeScript SDK

Install the published SDK in your application:

npm install @paymux-js/sdk

Create payments only on your backend, where the API key stays private:

import { Paymux } from "@paymux-js/sdk";

const paymux = new Paymux({
  apiKey: process.env.PAYMUX_API_KEY!,
  baseURL: "https://payments.example.com",
});

const payment = await paymux.payments.create(
  {
    amount: 49900,
    currency: "INR",
    order_ref: "order-123",
    return_url: "https://shop.example.com/orders/order-123",
  },
  { idempotencyKey: "order-123-payment-v1" },
);

For the default hosted App mode, either redirect the customer to payment.checkout_url, or return that URL to the authenticated order page and let the browser entry point open the selected provider:

import { checkout } from "@paymux-js/sdk/checkout";

const { checkout_url } = await fetch("/api/orders/order-123/payment", {
  method: "POST",
}).then((response) => response.json());

await checkout({ checkoutUrl: checkout_url });

To keep the Paymux URL out of the browser entirely, select provider_action under Apps โ†’ your app โ†’ Settings โ†’ checkout_mode. Payment creation immediately creates the provider order and returns its executable action, so the merchant backend returns only payment.checkout:

const payment = await paymux.payments.create(
  {
    amount: 49900,
    currency: "INR",
    order_ref: "order-123",
    customer: { name: "Asha Rao", billing: { country: "IN", state_code: "27" } },
  },
  { idempotencyKey: "order-123-payment-v1" },
);

return payment.checkout;
import { executeCheckout } from "@paymux-js/sdk/checkout";

await executeCheckout(await merchantBackend.startCheckout("order-123"));

Use payments.checkoutAction only to recover a failed provider launch or to request an intentionally fresh attempt.

The browser entry point never receives the Paymux API key. Fulfill the order only after a verified webhook or authenticated backend lookup. See the complete JavaScript SDK guide for refunds, subscriptions, invoices, payouts, webhook verification, CSP, and provider checkout behavior. Coding agents can use llms.txt for discovery and llms-full.txt as the complete merchant integration contract.

No code on your side? Create a shareable payment link instead:

curl -s localhost:8080/v1/payment_links \
  -H "Authorization: Bearer pmx_test_sk_..." \
  -d '{"amount":49900,"currency":"INR","description":"Pro plan, annual","single_use":true}'

The full, step-by-step tour (test payment, webhook, invoice, refund) is docs/quickstart.md. Your running hub also serves its API reference at /docs.

Tip: make dev builds everything and runs the hub and the public website together.

๐Ÿ‡ฎ๐Ÿ‡ณ Built for India

  • GST invoicing. Gapless numbering per fiscal year, CGST/SGST or IGST by place of supply, LUT exports, credit notes, tax-inclusive or tax-exclusive prices, FX rates, GST reports as CSV.
  • E-invoice. IRP-ready INV-01 JSON for B2B and export documents and their credit notes. Record the IRN and QR code from the portal and they are printed on the PDF.
  • Signed PDFs. PAdES digital signature with your DSC certificate.
  • UPI AutoPay, cards and e-NACH with the RBI and NPCI rules built in: pre-debit notice, the โ‚น15,000 limit, UPI execution windows, retry limits.
  • Buyer details captured the GST way. State, country, optional GSTIN; a buyer abroad makes the sale an export.

๐Ÿ”’ Security

  • A gateway webhook is verified first and only used as a hint: Paymux fetches the payment from the gateway before it changes your ledger.
  • No card data ever touches Paymux. Customers pay on the gateway's own page.
  • Secrets are encrypted at rest (AES-256-GCM) under a master key you hold, with a paymux secrets reseal command to rotate it.
  • Dashboard: 2FA (TOTP), optional single sign-on, roles and custom roles, scoped API keys, login lockout, "remember me" sessions that ask for your password again before sensitive changes.
  • Outbound webhooks are SSRF-guarded and signed. The error log removes secrets and customer details before it stores anything.
  • Money paths that hold up under retries and races. An Idempotency-Key is stored on the payout or refund itself. One provider payment settles one payment. Payouts with an unknown outcome go to review instead of being sent twice. Ledger rules are enforced by the database, and the ledger is append-only.
  • Releases you can verify. Archives are signed with cosign and carry build provenance. CI runs vulnerability and secret scans.
  • Independently reviewed: over 50 findings across several review rounds are tracked, with their fixes, in docs/security-review.md. The October 2026 audit and its remediation are in docs/security-audit.md and docs/security-remediation-plan.md.

๐Ÿงฉ Make it yours

  • Add a gateway. A connector is a Go package against a small public SDK, with a conformance kit that tells you when it is right. Or write it in any language and run it as a signed HTTP service. See docs/connectors.md.
  • React to events. Go hooks and sandboxed JavaScript hooks run after commit and cannot move money. See docs/extending.md.
  • Themes and translations. Drop your own themes or a language catalog into your data folder. No restart, no fork.
  • Merchant SDKs. The independent Go SDK and JavaScript SDK cover backend payments, refunds, links, subscriptions, invoices, payouts, and verified app webhooks. The JavaScript package also has an API-key-free browser entry point for provider checkout.
  • Examples. Small, tested programs in examples/: a raw HTTP API client, a framework-mode binary, a remote connector, and signed-webhook receivers in Go, JavaScript and Python.

๐Ÿ“ฆ Run it for real

  • Deploy kit in deploy/: Docker image, hardened systemd unit, Caddy (automatic HTTPS for custom domains) or nginx, Litestream for continuous SQLite backups.
  • Operate it: /healthz, /readyz, Prometheus /metrics, daily reconciliation against each gateway, an alerts center, paymux update with signature checks (see upgrades), scripts/release.sh builds checksummed release archives for Linux and macOS (amd64, arm64).
  • Configure it with environment variables or a .env file: docs/configuration.md. The runbook covers install, backups, restore and "the hub is down": docs/runbook.md.

โ“ FAQ

What is Paymux? A self-hosted payment orchestration and webhook-routing hub. Your apps call one API; Paymux talks to the gateways, keeps the ledger, sends you signed events and issues invoices.

Is it a Hyperswitch alternative? For small teams, yes. Hyperswitch is built for payment companies at large scale. Paymux keeps the useful ideas (routing, one API, a ledger, a dashboard, extensibility) in a single binary you can run on one small server.

Can I use several gateways at once, for example Razorpay for rupees and Stripe for dollars? Yes. Routing rules choose the gateway by app, currency, country and amount, and fall through to the next one when a gateway is down.

Does Paymux handle GST? Yes: tax invoices, credit notes, place-of-supply rules, exports, e-invoice JSON and signed PDFs. Whop is a merchant of record, so Paymux issues no invoice for its payments.

Which databases does it support? SQLite (default) and PostgreSQL, with the same code and the same tests on both.

Is Paymux production-ready? It is beta: v0.1.0 is the first signed release. Razorpay, Stripe, Cashfree, PayU and Whop have been run end to end against their real sandboxes, and Zoho Payments has had its payments checked there. The October 2026 audit's findings are fixed. Before you take live money, run your own test payments and read docs/provider-verification.md: the checklist of what still needs a live account, per gateway.

How do I add a gateway that is not listed? Write a connector (a Go package or a small HTTP service). The SDK, the conformance kit and a worked example are in docs/connectors.md.

๐Ÿ“š Documentation

Quick start From nothing to a test payment, webhook, invoice and refund
Documentation index Every guide, in reading order
API guide ยท Reference Integrate your app
Webhooks ยท Payments ยท Billing The core concepts
Runbook ยท Upgrades ยท Troubleshooting Run it in production
Features ยท Access control ยท Security The complete lists
Dashboard themes Make, share and choose dashboard themes
Writing connectors ยท Extending Make it yours
Development ยท Testing Contribute

๐Ÿค Contributing

Issues and pull requests are welcome. Branch from main, run make ci (it runs everything CI runs: formatting, vet, the public-API snapshot, static analysis, the vulnerability scan, the full test suite on SQLite and PostgreSQL, the browser tests and the Docker build), then open a pull request. The template lists what to check. CodeRabbit reviews every pull request automatically, with rules written for this codebase in .coderabbit.yaml. Details: .github/CONTRIBUTING.md and docs/development.md.

๐Ÿ“„ License

Apache License 2.0.

Keywords: payment orchestration, payment gateway aggregator, payment router, webhook router, IPN, Razorpay, Stripe, Cashfree, PayU, Zoho Payments, Whop, GST invoice, e-invoice, UPI AutoPay, e-mandate, subscription billing, refunds, disputes, reconciliation, self-hosted, open source, Go, SQLite, PostgreSQL, Hyperswitch alternative.

About

Self-hosted payment orchestration in one Go binary: Razorpay, Stripe, Cashfree, PayU, Zoho Payments and Whop behind one API, one ledger and one webhook endpoint, with GST invoicing, subscriptions and UPI AutoPay.

Topics

Resources

Contributing

Security policy

Stars

3 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages