The payment orchestration kernel for TypeScript.
Type-safe payment orchestration for MENA + global providers — Moyasar, PayPal, Paymob, Stripe, Tap, MyFatoorah, Hesabe — with portable webhook inbox, reconciliation, and multi-store adapters. Built for modern server runtimes: Node, Bun, Deno, Cloudflare Workers.
Repository: aashahin/paykernel · npm scope: @paykernel · Docs: paykernel-docs.abshahin.workers.dev · License: MIT
- One client, many gateways — unified
createPayment,capture,refund,void,getPaymentacross providers. Money is alwaysMoney(bigint minor units), nevernumber. - Correct by default —
outcome+status === "paid"gates, indeterminate reconciliation, lease-fenced webhook inbox, and idempotency claims. No double-fulfillment, nosuccess:truetraps. - Portable — pure Web APIs + Web Crypto. No hard Express/Hono dependency. Works on Node 18+, Bun 1+, Deno, and Cloudflare Workers.
- Composable storage — pick Postgres, Redis/Valkey/Upstash, SQLite, Turso/libSQL, D1, or Durable Objects. Core never mandates a store.
- Observable & testable — redacting telemetry, OTEL bridge, and a full testkit with mock gateway + conformance harnesses.
On 2026-09-11, the deployed payment lab completed Paymob payments plus full and partial refunds, and a Moyasar card payment with 3-D Secure, using real provider sandbox accounts and authenticated settlement inquiries. Stripe and PayPal authentication/configuration checks also passed. These are sandbox results; account coverage varies by gateway.
See the gateway validation matrix for the exact tested flows, simulator coverage, and remaining account-test gaps, or read it on the docs website.
bun add @paykernel/core
# or
npm install @paykernel/core
# or
pnpm add @paykernel/coreimport { createPaymentClient, moyasarGateway, money, isPaidOutcome } from "@paykernel/core";
const client = createPaymentClient({
gateways: {
moyasar: moyasarGateway({
secretKey: process.env.MOYASAR_SECRET_KEY!,
webhookSecret: process.env.MOYASAR_WEBHOOK_SECRET,
}),
},
defaultGateway: "moyasar",
});
const result = await client.createPayment({
amount: money("100.00", "SAR"),
currency: "SAR",
orderId: "order_123",
callbackUrl: "https://example.com/callback",
moyasarSource: { type: "token", token: "token_xxx" },
});
if (isPaidOutcome(result)) {
// fulfilled only on outcome === "succeeded" && status === "paid"
} else if (result.redirectUrl) {
// 3DS redirect — do not fulfill yet
} else if (result.outcome === "indeterminate") {
// reconcile via getPayment — do not retry create
}Full composition (verify → claim → fulfill → reconcile): docs/getting-started.md
| Package | npm | Description |
|---|---|---|
packages/core |
@paykernel/core |
Core SDK — Moyasar, PayPal, Paymob, Stripe + plugin registry |
packages/webhooks |
@paykernel/webhooks |
Portable webhook inbox engine (claim, lease fencing, processing outcomes) |
packages/reconciliation |
@paykernel/reconciliation |
Portable reconciliation primitives (drift, decision-only policy, store-backed scheduling) |
packages/observability |
@paykernel/opentelemetry |
Portable metrics/spans + redacting telemetry + optional OTEL bridge |
packages/routing |
@paykernel/routing |
Select-only gateway routing + restricted post-attempt fallback |
packages/gateway-tap |
@paykernel/gateway-tap |
Tap Payments adapter (charges, auth/capture/void, refunds, webhooks) |
packages/gateway-myfatoorah |
@paykernel/gateway-myfatoorah |
MyFatoorah adapter (V3 hosted payments, refunds, Webhook V2) |
packages/gateway-hesabe |
@paykernel/gateway-hesabe |
Hesabe adapter (KWD hosted payments, enquiry, refunds, verified callbacks/webhooks) |
packages/testkit |
@paykernel/testkit |
Mock gateway, conformance suites, NON-PRODUCTION memory stores |
packages/store-contracts |
@paykernel/store-contracts |
Portable store contracts (lease stores, errors, manifests) |
packages/sql-foundation |
@paykernel/sql-foundation |
Relational schemas, migrations, claim SQL templates |
packages/store-postgres |
@paykernel/store-postgres |
PostgreSQL durable stores (idempotency, webhook inbox, reconciliation) |
packages/store-redis |
@paykernel/store-redis |
Redis/Valkey/Upstash stores (Lua claims) — optional, never required |
packages/store-sqlite |
@paykernel/store-sqlite |
Single-host SQLite stores (Bun/Node/better-sqlite3) |
packages/store-turso |
@paykernel/store-turso |
Multi-host remote Turso/libSQL stores |
packages/store-d1 |
@paykernel/store-d1 |
Multi-host Cloudflare D1 stores (Workers binding) |
packages/store-durable-objects |
@paykernel/store-durable-objects |
Multi-host partitioned Durable Object stores |
packages/integration-http |
@paykernel/integration-http |
Portable HTTP mapping + processWebhookHttp (framework-agnostic) |
packages/integration-hono |
@paykernel/integration-hono |
Thin Hono adapter for webhooks |
packages/integration-elysia |
@paykernel/integration-elysia |
Thin Elysia adapter for webhooks |
packages/integration-express |
@paykernel/integration-express |
Thin Express adapter (raw-body safe, Node-only) |
packages/integration-cloudflare-workers |
@paykernel/integration-cloudflare-workers |
Thin Cloudflare Workers adapter |
internal/sql-store (@paykernel/internal-sql-store) is a private BC shim — never published. Adapters depend on @paykernel/sql-foundation.
bun add @paykernel/core # core SDK
bun add @paykernel/webhooks # inbox engine
bun add @paykernel/reconciliation # reconciliation
bun add @paykernel/opentelemetry # observability
bun add @paykernel/routing # routing policies
bun add @paykernel/gateway-tap @paykernel/gateway-myfatoorah @paykernel/gateway-hesabe # extra gateways
bun add @paykernel/store-postgres # Postgres (app layer)
bun add @paykernel/store-redis # Redis/Valkey/Upstash (optional)
bun add @paykernel/store-sqlite # SQLite single-host
bun add @paykernel/store-turso # Turso/libSQL multi-host
bun add @paykernel/store-d1 # Cloudflare D1
bun add @paykernel/store-durable-objects # Durable Objects
bun add @paykernel/integration-http @paykernel/integration-hono # HTTP adapters
# or with npm: npm install @paykernel/coreimport { PaymentClient } from "@paykernel/core";
// optional:
// import { createWebhookInboxEngine } from "@paykernel/webhooks";
// import { createPaymentReconciler } from "@paykernel/reconciliation";
// import { withPaymentOperation, createInMemoryPaymentMetrics } from "@paykernel/opentelemetry";
// import { createPaymentRouter, route } from "@paykernel/routing";
// import { createPostgresStores } from "@paykernel/store-postgres";
// import { createRedisStores } from "@paykernel/store-redis";
// import { createSqliteStores } from "@paykernel/store-sqlite";
// import { createTursoStores } from "@paykernel/store-turso";
// import { createD1PaymentStores } from "@paykernel/store-d1";
// import { createDoPaymentStores } from "@paykernel/store-durable-objects";Workspaces are packages/*, internal/*, and examples/*. The root package is private and is never published. Layout, build order, and commands: docs/monorepo.md.
Root scripts forward into workspace packages so Phase 0 command names stay stable:
bun install
bun run build
bun test
bun test examples
bun run test:coverage
bun run typecheck
bun run typecheck:types
bun run typecheck:all
bun run format
bun run format:check
bun run lint
bun run check:boundaries
bun run check:runtime-portability
bun run test:runtime
bun run pack:check
bun run publint
bun run attw
bun run validate:package
bun run baselinePackage-local work:
cd packages/core
bun run build
bun test
cd packages/webhooks
bun run build
bun test
cd packages/testkit
bun run build
bun test
cd packages/store-postgres
bun run build
bun test
# live PG: export PAYMENTS_SDK_PG_URL=postgres://… then bun test
cd packages/store-redis
bun run build
bun test
# live Redis: export PAYMENTS_SDK_REDIS_URL=redis://… then bun test
cd packages/store-sqlite
bun run build
bun test
cd packages/store-turso
bun run build
bun test
# live Turso: export TURSO_DATABASE_URL=… TURSO_AUTH_TOKEN=… then bun test
cd packages/store-d1
bun run build
bun test
# default: mock D1 CI path; live/miniflare skip unless harness env set
cd packages/store-durable-objects
bun run build
bun test
# default: mock DO SQL CI path; live/miniflare skip unless harness env setSee docs/monorepo.md for layout details, boundary rules, and release notes.
Docs site: https://paykernel-docs.abshahin.workers.dev — start at Quickstart.
Start here (in-repo): docs/README.md · docs/getting-started.md (create payment → verify → inbox claim → fulfill → reconcile)
roadmap.md is a completed phase log (0–25 shipped, Phase 23 leftover gateways) plus leftover product work. It is not the consumer index. Phase 25 (1.0): 1.0 contract cut, compat CI, bun-hono-postgres RC.
MIT — see LICENSE. Copyright © Abdelrahman Shaheen.