AI Decision System
Replayable, offline-verifiable records for AI-assisted go/no-go decisions: experiment promotions, typed model answers and human-approved actions.
翻译准备中
个人 GitHub 账号下公开仓库的所有者可以登录并验证所有权,自行管理介绍,无需管理员批准。
登录并生成验证文件,在 30 分钟内将其提交到此仓库的默认分支。其他分支或分叉仓库中的文件无效。然后在下方检查文件,即可无需管理员批准直接管理项目。请保留文件以维持管理权限。
如需登录,将前往登录页面。登录后请回到此处,再次点击所选的验证按钮。
在项目文件夹中运行 /nomorevibe verify,即可验证所有权并自行管理介绍。
一分钟完成验证Local payment-infrastructure emulator for Paystack, Stripe, Flutterwave and Kora. Point an existing integration at localhost and reproduce what's hard to test: pending mobile-money authorization, webhook retries and duplicates, timeouts, refunds, idempotency. Deterministic, and no provider sandbox needed.
翻译准备中
取自仓库 README
正在加载完整 README。 以下为已保存的摘录。
A local payment infrastructure emulator. Point an existing Paystack, Stripe,
Flutterwave, Kora, Quid Payments, Tingg, WeWire or Wise integration at
localhost and test the parts of payments that are hard to test: pending
transactions, asynchronous mobile-money authorization, duplicate webhooks,
retries, timeouts, refunds, idempotency and flaky networks.
Every adapter is partially implemented, and each one's coverage is
documented honestly — see the table below.
If your production payment integration can hit it, you should be able to
reproduce it locally.查看完整 README ↗A local payment infrastructure emulator. Point an existing Paystack, Stripe,
Flutterwave, Kora, Quid Payments, Tingg, WeWire, Wise or Bachs integration
at localhost and test the parts of payments that are hard to test: pending
transactions, asynchronous mobile-money authorization, duplicate webhooks,
retries, timeouts, refunds, idempotency and flaky networks.
Every adapter is partially implemented, and each one's coverage is documented honestly — see the table below.
If your production payment integration can hit it, you should be able to reproduce it locally.
paybox is not a mock server. Every request drives a real state machine, appends to an append-only event log, and produces the same events and webhooks the equivalent organic flow would.
No real money can move through this process. It has no code path that reaches a payment network, and it refuses live API keys.
| Provider | Base path | Endpoints | Coverage |
|---|---|---|---|
| Paystack | /paystack | 64 | Partial — what works |
| Stripe | /stripe | 92 | Partial — what works |
| Flutterwave v3 | /flutterwave | 26 | Partial — what works |
| Flutterwave v4 | /flutterwave/v4 | 11 | Partial — what works |
| Kora | /kora | 29 | Partial — what works |
| Quid Payments | /quiddpay | 36 | Partial — what works |
| Tingg | /tingg | 11 | Partial — what works |
| WeWire | /wewire | 25 | Partial — what works |
| Wise | /wise | 30 | Partial — what works |
| Bachs | /bachs | 119 | Partial — what works |
Endpoint counts are generated from each adapter's coverage manifest and checked
against the router by tests/coverage-drift.test.ts — the table cannot claim an
endpoint the emulator does not serve. paybox coverage prints the same figures,
and paybox coverage <provider> breaks them down.
Partial means partial. Each docs/<provider>.md is a contract, not
marketing: it lists what is implemented, what differs and what is absent. If
something is missing from that file, assume it is not there.
Flutterwave ships two live APIs with different authentication, envelopes and webhook signatures, so paybox implements them as two adapters rather than one with a flag.
The engine is provider-independent, and ten adapters across nine providers now sit on it. Anything a provider needs from the engine reaches it as an injected function — a status mapping, an instrument table, an authorization minter — never an import, so no adapter can see another and the engine sees none of them.
npx paybox-emulator start
No clone, no database server, no compiler — Node 22.5 or newer is the only
requirement. npm install -g paybox-emulator puts the paybox command on your
PATH for everything below; each command also works as npx paybox-emulator ….
Without Node, the same thing as a container:
docker run --rm -p 127.0.0.1:8080:8080 dsasante1/paybox
paybox — local payment emulator
───────────────────────────────────────────────
API http://127.0.0.1:8080
Dashboard http://127.0.0.1:8080/dashboard
API docs http://127.0.0.1:8080/docs
Test credentials (local only — these are not real keys)
secret sk_test_local_a1b2c3...
Point your app at it:
PAYSTACK_BASE_URL=http://127.0.0.1:8080/paystack
PAYSTACK_SECRET_KEY=sk_test_local_a1b2c3...
Or any of the others — paybox status prints the credentials each one issued:
STRIPE_API_BASE=http://127.0.0.1:8080/stripe
FLW_BASE_URL=http://127.0.0.1:8080/flutterwave # v3, FLWSECK_TEST-… keys
KORA_BASE_URL=http://127.0.0.1:8080/kora
Then initialize a payment exactly as you would against Paystack:
curl -X POST http://127.0.0.1:8080/paystack/transaction/initialize \
-H "Authorization: Bearer sk_test_local_a1b2c3..." \
-H "content-type: application/json" \
-d '{"email":"[email protected]","amount":10000,"currency":"GHS","reference":"order_1"}'
{
"status": true,
"message": "Authorization URL created",
"data": {
"authorization_url": "http://127.0.0.1:8080/paystack/checkout/48zrdrkbqv7e",
"access_code": "48zrdrkbqv7e",
"reference": "order_1"
}
}
Open that URL — it is a real checkout page with the test instruments listed on it. Or drive it from the CLI:
paybox webhook add http://localhost:3000/webhooks/paystack
paybox payment success order_1
Your app receives a signed charge.success webhook, and verify now returns
"status": "success".
# A mobile-money charge answers immediately; the customer has not approved yet.
paybox payment create --amount 25000 --method mobile_money --reference momo_1
# → requires_action, "Please approve the payment prompt on your phone"
# Fast-forward instead of waiting. Every job that comes due runs before this returns.
paybox time advance 5s
# → successful, charge.success delivered
# Make every webhook fail, then watch the retry ladder run to exhaustion.
paybox webhook fail http_500
paybox time advance 2h
paybox webhook list
# Replay a delivery with a byte-identical signed payload — does your handler
# double-credit the customer?
paybox webhook replay whd_...
# Duplicate and reorder every webhook.
paybox webhook chaos --duplicate true --out-of-order true
# Hold the API response open so the webhook lands before the call returns.
paybox network latency 3000
The documentation index maps every page to a question. The ones most people need first:
| Getting started | Install, point an app at it, first payment, first webhook |
| Concepts | Canonical statuses, the event log, virtual time, determinism |
| Providers | Base URL, credential, webhook verification and SDK settings for each of the nine |
| Contracts | What each adapter does and does not implement: Paystack, Stripe, Flutterwave, Kora, Quid Payments, Tingg, WeWire, Wise, Bachs |
| Test instruments | Which card or phone number produces which outcome |
npm install
npm start # the server, straight from the TypeScript source
npm run cli -- time advance 5s # the CLI, likewise — nothing is built
npm test # unit, integration, provider compatibility
npm run typecheck # strict, project references
npm run lint # includes the determinism rules
npm run build # bundles the publishable package into apps/paybox/dist
npm run smoke:package # installs that package into an empty directory and runs it
The lint rules are load-bearing, not cosmetic: Date.now(), new Date(),
Math.random() and raw timers are banned outside packages/core/src/time/.
Everything reads from an injected Clock and a seeded Random. That is what
makes time advance work and what makes PAYBOX_SEED=x reproduce a run
byte for byte.
A release is a tag. Pushing v0.2.0 runs the full verification again and then
publishes that one version to npm, to Docker Hub and as a GitHub Release from a
single workflow — docs/releasing.md has the one-time setup.
Source comments cite design decisions as spec §N. Those refer to a build
brief that is not published with the code; docs/spec-references.md
indexes every section the code cites, and docs/architecture.md explains the
three decisions everything else follows from.
MIT. Not affiliated with, endorsed by, or connected to Paystack, Stripe, Flutterwave, Kora or Quid Payments. Provider names are used only to describe API compatibility.
| Payment lifecycle | Statuses, transitions, refunds, transfers, subscriptions, disputes |
| Time control | What time advance runs, and what it does not |
| Webhooks | Signing, retries, replay, failure simulation |
| Scenarios | Reusable multi-step flows |
| CLI | Every command |
| Control API | Every /api route the CLI and dashboard use |
| Configuration | Every key and environment variable |
| Testing with paybox | A complete automated test, CI blocks, and a recipe per failure mode |
| Dashboard | The five views and the live event stream |
| Troubleshooting | Symptoms and what to do |
| Docker | The published image, compose, CI services |
| Architecture | How it works and why it is built this way |
| Changelog | What each published version shipped |
| Releasing | How a tag becomes an npm package and a container image |
| Security | The safety guarantees and their limits |