Skip to content

feat(core): gateway-agnostic PaymentProvider interface (Stripe adapter + mock)#18

Open
moset15 wants to merge 1 commit into
emdashCommerce:mainfrom
FIKANOVA:feat/payment-provider-interface
Open

feat(core): gateway-agnostic PaymentProvider interface (Stripe adapter + mock)#18
moset15 wants to merge 1 commit into
emdashCommerce:mainfrom
FIKANOVA:feat/payment-provider-interface

Conversation

@moset15

@moset15 moset15 commented Jul 19, 2026

Copy link
Copy Markdown

What

Introduces a payment seam so processors beyond Stripe can plug into core without forking it: initCheckout (hosted), verifyWebhook (constant-time, hash-algorithm-agnostic), parseWebhookEvent (normalised event shape), refund, formatAmount.

Why

We are building a Paystack provider (cards + M-Pesa STK — the dominant payment rail in Kenya) for a production store on DashCommerce. Paystack's webhook signing is HMAC-SHA512 and its checkout is hosted-page-first, so the seam is deliberately shaped around what both gateways share rather than around Stripe's API surface.

What this PR does not do

  • src/stripe/* is untouched — the Stripe adapter (payment-provider/stripe-provider.ts) wraps the existing modules.
  • routes/checkout.ts and routes/webhook.ts still call stripe/* directly; wiring them onto registry.resolveProvider() is staged as a follow-up commit so this diff stays reviewable and behaviour-neutral (the registry defaults to "stripe", so existing installs behave identically).
  • Stripe Connect and Subscriptions/Billing are intentionally out of scope — no structural Paystack equivalent to abstract over (see the module comment in payment-provider/types.ts).

Testing

19 unit tests (bun test) across types/adapter/mock/registry; tsc --noEmit clean; Biome formatted; tsdown build emits the new ./payment-provider entry.

Happy to reshape the interface if you'd prefer different seams — the Paystack implementation living at FIKANOVA/dashcommerce-paystack is the second consumer and keeps this honest.

🤖 Generated with Claude Code

…nd mock

Adds a gateway-agnostic payment seam so additional processors (e.g.
Paystack for the African market) can plug in without touching core
checkout code:

- payment-provider/types.ts: the PaymentProvider interface — init hosted
  checkout, verify webhook (constant-time, algorithm-agnostic), parse
  webhook event into a normalised shape, refund, format amount.
- payment-provider/stripe-provider.ts: thin adapter implementing the
  interface over the existing stripe/* modules — no changes to any file
  under src/stripe/.
- payment-provider/mock-provider.ts: in-memory implementation for tests
  and credential-free local checkout runs.
- payment-provider/registry.ts: runtime provider selection via
  settings:paymentProvider (plugin KV), defaulting to "stripe" so
  existing installs behave identically.
- New ./payment-provider subpath export + tsdown entry.
- 19 unit tests (bun test) across the three new modules; tsc --noEmit
  clean; Biome formatted.

Routes (checkout.ts / webhook.ts) still call stripe/* directly — wiring
them onto resolveProvider() is staged as a follow-up commit so this diff
stays reviewable and behaviour-neutral.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant