feat(paykit): harden subscription checkout sessions
Closed
PA
3mo ago+1002+1002+0123456789012345678901234567890123456789-19-19-01234567890123456789
Summary
This PR hardens subscription Checkout Sessions without adding app-specific billing behavior.
It is stacked on #201 (subscription-quantity). After #201 merges, this branch should be rebased so this PR contains only the checkout hardening commit.
Changes
- Add optional subscription Checkout options for idempotency, promotion codes, automatic tax, billing address collection, Tax ID collection, and customer update behavior.
- Return
checkoutSessionIdfrom subscription checkout results. - Add a server-side
expireCheckoutSessionPayKit method that verifies provider customer ownership before expiring a Stripe Checkout Session. - Pass Checkout hardening options through the provider contract and Stripe provider.
- Add generic PayKit error codes for checkout session not found, customer mismatch, and non-expireable sessions.
- Add a changeset for a minor
paykitjsrelease.
Out of scope
- Automatic resume of open Checkout Sessions.
- Application-level storage of checkout attempts.
- Fooodly-specific org mapping or reconciliation.
- Annual/monthly multi-price logic.
Verification
pnpm --filter paykitjs typecheckpnpm lintpnpm test:unitpnpm --filter paykitjs buildpnpm exec oxfmt --check <touched files>
Note: pnpm format:check currently fails on this Windows shell because the quoted glob is not expanded for oxfmt, so touched files were checked explicitly instead.
Summary by cubic
Hardens subscription Checkout Sessions and adds quantity-aware subscriptions across paykitjs. Adds a secure server method to expire Stripe sessions, returns checkoutSessionId from subscribe, and avoids top‑level eval during runtime init.
-
New Features
- Checkout hardening for subscription Checkout: promotion codes, automatic tax, billing/tax ID collection, customer update, and idempotency; passed through the provider to Stripe.
- New server method
expireCheckoutSessionthat verifies customer ownership, treats already-expired sessions as idempotent, and expires only open sessions. subscribenow returnscheckoutSessionIdand supportsquantity; quantity is persisted and synced across create/update/schedule flows.- Added PayKit error codes: checkout session not found, customer mismatch, and not-expireable.
-
Migration
- Custom providers: implement
expireCheckoutSession; addquantitytocreateSubscription,updateSubscription,scheduleSubscriptionChange, andcreateSubscriptionCheckout; includequantityin returned subscriptions. - API usage:
subscribeacceptscheckoutandquantity; handlecheckoutSessionIdin the result.
- Custom providers: implement
Summary by CodeRabbit
-
New Features
- Added support for subscription quantities across checkout, updates, scheduling, and syncing.
- Added a new option to include checkout session hardening settings such as tax, billing, promotion codes, and idempotency.
- Added a way to expire checkout sessions, with customer ownership checks.
-
Bug Fixes
- Subscription results can now include checkout session IDs.
- Improved validation and error handling for checkout session expiration and invalid checkout options.