Skip to content

feat(paykit): add stripe managedPayments and apiVersion options#111

Merged
maxktz merged 4 commits intogetpaykit:mainfrom
aristotl-dylan:feat/stripe-managed-payments
Apr 13, 2026
Merged

feat(paykit): add stripe managedPayments and apiVersion options#111
maxktz merged 4 commits intogetpaykit:mainfrom
aristotl-dylan:feat/stripe-managed-payments

Conversation

@aristotl-dylan
Copy link
Copy Markdown
Contributor

@aristotl-dylan aristotl-dylan commented Apr 11, 2026

Closes #109

Summary

Adds two new options to the Stripe provider config so users can pin the Stripe API version and opt into Stripe Managed Payments on subscription checkout sessions.

  • apiVersion (optional, defaults to PAYKIT_STRIPE_API_VERSION = "2025-10-29.clover") — pins the Stripe SDK to a known-good version so account-level default drift or a Stripe SDK bump doesn't silently change behavior in user integrations. Users can override it, including to opt into preview versions.
  • managedPayments (optional, default false) — when true, adds managed_payments: { enabled: true } to subscription checkout sessions so Stripe takes over tax calculation, payment method selection, and billing address collection. Requires apiVersion: "2026-03-04.preview" (the preview channel Stripe currently ships the feature on); construction throws with a clear error otherwise.
import { stripe } from "@paykitjs/stripe";
import { createPayKit } from "paykitjs";

export const paykit = createPayKit({
  // ...
  provider: stripe({
    secretKey: process.env.STRIPE_SECRET_KEY!,
    webhookSecret: process.env.STRIPE_WEBHOOK_SECRET!,
    apiVersion: "2026-03-04.preview",
    managedPayments: true,
  }),
});

Why

managed_payments is a Stripe Checkout Session field that is only available on Stripe API version 2026-03-04.preview and is not yet in the stripe Node SDK types. Previously the stripe() config surface had no way to set apiVersion at all, so users couldn't opt into this (or any other) preview feature, and the SDK fell back to the account-level default. Fixing this needed a small extension to StripeProviderOptions plus threading the version through to new StripeSdk(...).

Because Managed Payments is preview and has strict restrictions (digital products only, no shipping, mutually exclusive with payment_method_types, automatic_tax, Connect fields, etc.), the feature is gated behind an explicit opt-in flag and documented with a preview warning.

Changes

File Change
packages/paykit/src/providers/provider.ts Added apiVersion?: string and managedPayments?: boolean to StripeProviderOptions with JSDoc
packages/paykit/src/providers/stripe.ts Exported PAYKIT_STRIPE_API_VERSION, threaded apiVersion into new StripeSdk(...), added validation at createStripeRuntime, added managed_payments field to subscription checkout sessions via an inline type intersection (no @ts-expect-error)
packages/paykit/src/core/errors.ts New error code PROVIDER_INVALID_CONFIG
packages/paykit/src/index.ts Re-export PAYKIT_STRIPE_API_VERSION
packages/stripe/src/stripe-provider.ts Re-export PAYKIT_STRIPE_API_VERSION from @paykitjs/stripe
packages/paykit/src/providers/__tests__/stripe.test.ts 4 new tests covering the new behavior
landing/content/docs/providers/stripe.mdx New "API version" and "Managed Payments" sections with preview warning

Design decisions

  • Pin a default apiVersion rather than leaving it unset. This shields users from Stripe's account-default drift (the one well-known footgun on the Stripe Node SDK). Users who need a newer or preview version pass it explicitly.
  • Fail loudly on bad config. managedPayments: true without the required preview apiVersion throws at createStripeRuntime construction time with a message that points at the Stripe Managed Payments docs. No auto-forcing, no silent fallback.
  • Inline intersection type for the managed_payments field rather than @ts-expect-error. Preserves type safety on the rest of SessionCreateParams and silently absorbs the change if Stripe later adds managed_payments to official SDK types.
  • No appInfo changes in this PR (kept scope tight to the issue).

Test plan

  • pnpm typecheck clean across all workspace packages
  • pnpm exec vitest run in packages/paykit/ — 20/20 passing, including 4 new tests:
    • managed_payments is added to the session create call when enabled
    • managed_payments is absent when disabled
    • createStripeRuntime throws when managedPayments: true but apiVersion is missing/wrong
    • createStripeRuntime succeeds with the preview apiVersion
  • pnpm format:check clean
  • pnpm lint — no new warnings (4 preexisting in landing/, unrelated)
  • Manual smoke against a Stripe test account with managedPayments: true + preview API version (not run; would require a live account)

Summary by CodeRabbit

  • New Features

    • Stripe provider supports configurable API versions and a Managed Payments preview for checkout sessions, with validation around preview requirements.
  • Bug Fixes

    • Improved provider configuration validation and clearer error reporting for invalid setups.
  • Documentation

    • Added guide for Stripe API versioning, enabling Managed Payments, preview/production warnings, and Checkout limitations.
  • Tests

    • Added tests covering Managed Payments behavior and API version validation.

@vercel
Copy link
Copy Markdown

vercel bot commented Apr 11, 2026

@aristotl-dylan is attempting to deploy a commit to the maxktz Team on Vercel.

A member of the Team first needs to authorize it.

@coderabbitai
Copy link
Copy Markdown

coderabbitai bot commented Apr 11, 2026

Caution

Review failed

The pull request is closed.

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro

Run ID: 02c2899c-ae74-47cf-acc6-6e12918b8ec3

📥 Commits

Reviewing files that changed from the base of the PR and between 33c8171 and 7f9699a.

📒 Files selected for processing (1)
  • packages/stripe/src/__tests__/stripe.test.ts

📝 Walkthrough

Walkthrough

Adds Stripe API version pinning and an optional managed payments preview feature to the Stripe provider: new exported PAYKIT_STRIPE_API_VERSION, apiVersion and managedPayments options, validation for preview API usage, and conditional inclusion of managed_payments in checkout session creation; docs and tests updated accordingly.

Changes

Cohort / File(s) Summary
Documentation
landing/content/docs/providers/stripe.mdx
Documented apiVersion pinning, exported PAYKIT_STRIPE_API_VERSION, managedPayments: true preview option, usage example, and warning/limitations for Checkout managed payments.
Provider implementation
packages/stripe/src/stripe-provider.ts, packages/stripe/src/index.ts
Added exported PAYKIT_STRIPE_API_VERSION; extended StripeOptions with apiVersion? and managedPayments?; construct/reuse a single StripeSdk client configured with apiVersion; validate managedPayments requires a .preview API version meeting minimum; conditionally add managed_payments to checkout session params; re-export constant in index.
Errors
packages/paykit/src/core/errors.ts
Added PROVIDER_INVALID_CONFIG error code entry to support provider configuration validation errors.
Tests
packages/stripe/src/__tests__/stripe.test.ts, packages/paykit/src/core/__tests__/logger.test.ts
Added tests for managed payments behavior and apiVersion validation/boundaries; updated logger test expectations for pretty-log customPrettifiers.time and translateTime format string.

Sequence Diagram(s)

sequenceDiagram
    participant Dev as Developer
    participant Provider as Stripe Provider
    participant SDK as Stripe SDK
    participant API as Stripe API

    Dev->>Provider: stripe({ managedPayments: true, apiVersion: "2026-03-04.preview", ... })
    Provider->>Provider: Validate apiVersion ends with ".preview" and meets minimum
    Provider->>SDK: Instantiate StripeSdk client with apiVersion
    Note over Dev,Provider: Later — create subscription checkout
    Dev->>Provider: createSubscriptionCheckout(...)
    Provider->>Provider: Check options.managedPayments
    Provider->>API: checkout.sessions.create({ ..., managed_payments: { enabled: true } })
    API-->>Provider: Session created
    Provider-->>Dev: Return session response
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Poem

🐰 I pinned the API, gentle and neat,
preview hops in with managed_payments sweet,
I check the version, I guard the gate,
a session is built—now payments can skate! ✨

🚥 Pre-merge checks | ✅ 3 | ❌ 2

❌ Failed checks (2 warnings)

Check name Status Explanation Resolution
Out of Scope Changes check ⚠️ Warning The PR introduces an unrelated change to logger test expectations (time format and customPrettifiers) that is not connected to the Stripe managed payments feature objectives. Remove or revert the logger test changes in packages/paykit/src/core/tests/logger.test.ts as they are unrelated to the Stripe managed payments feature.
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (3 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title 'feat(paykit): add stripe managedPayments and apiVersion options' accurately summarizes the main changes, clearly identifying the new Stripe options being added.
Linked Issues check ✅ Passed The PR implementation fully addresses the objectives from issue #109: adds apiVersion option for pinning Stripe SDK version, implements managedPayments option for subscription checkouts, validates configuration to require preview versions, and includes documentation with warnings.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Comment @coderabbitai help to get the list of available commands and usage tips.

Adds `apiVersion` and `managedPayments` options to the Stripe provider
config. `apiVersion` defaults to the pinned `PAYKIT_STRIPE_API_VERSION`
so upstream Stripe changes don't silently break integrations. Setting
`managedPayments: true` adds `managed_payments: { enabled: true }` to
subscription checkout sessions and requires a preview apiVersion,
validated at runtime construction.

Refs getpaykit#109
@aristotl-dylan aristotl-dylan force-pushed the feat/stripe-managed-payments branch from 75583de to b322e0b Compare April 11, 2026 21:39
Copy link
Copy Markdown

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧹 Nitpick comments (1)
packages/paykit/src/providers/stripe.ts (1)

909-920: Consider moving the managedPayments validation to a shared helper to protect all construction paths.

The preview-version guard (lines 910–916) only runs in createStripeRuntime. While the public library API is protected—createStripeRuntime is the documented entry point—the exported createStripeProvider factory function can still be called directly with managedPayments: true and an incompatible API version without validation. Direct callers (whether tests or future internal code) would then pass invalid config to checkout.sessions.create(...) without the clearer PROVIDER_INVALID_CONFIG error.

To improve encapsulation, extract the guard into a shared validation function called by both createStripeRuntime and createStripeProvider, or make createStripeProvider module-local if it is only intended for internal use.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@packages/paykit/src/providers/stripe.ts` around lines 909 - 920, The
managedPayments/API-version guard is only performed in createStripeRuntime, so
callers of createStripeProvider can bypass the
STRIPE_MANAGED_PAYMENTS_API_VERSION check; extract the validation into a shared
helper (e.g., validateStripeManagedPayments(options)) that checks
options.managedPayments against options.apiVersion (comparing to
STRIPE_MANAGED_PAYMENTS_API_VERSION) and throws PayKitError.from("BAD_REQUEST",
PAYKIT_ERROR_CODES.PROVIDER_INVALID_CONFIG, ...) when mismatched, then call that
helper from both createStripeRuntime and createStripeProvider (or alternatively
make createStripeProvider non-exported if it should be internal-only).
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Nitpick comments:
In `@packages/paykit/src/providers/stripe.ts`:
- Around line 909-920: The managedPayments/API-version guard is only performed
in createStripeRuntime, so callers of createStripeProvider can bypass the
STRIPE_MANAGED_PAYMENTS_API_VERSION check; extract the validation into a shared
helper (e.g., validateStripeManagedPayments(options)) that checks
options.managedPayments against options.apiVersion (comparing to
STRIPE_MANAGED_PAYMENTS_API_VERSION) and throws PayKitError.from("BAD_REQUEST",
PAYKIT_ERROR_CODES.PROVIDER_INVALID_CONFIG, ...) when mismatched, then call that
helper from both createStripeRuntime and createStripeProvider (or alternatively
make createStripeProvider non-exported if it should be internal-only).

ℹ️ Review info
⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro

Run ID: d80565b1-6fea-4dc4-bfaf-b523bc3223ec

📥 Commits

Reviewing files that changed from the base of the PR and between 75583de and b322e0b.

📒 Files selected for processing (7)
  • landing/content/docs/providers/stripe.mdx
  • packages/paykit/src/core/errors.ts
  • packages/paykit/src/index.ts
  • packages/paykit/src/providers/__tests__/stripe.test.ts
  • packages/paykit/src/providers/provider.ts
  • packages/paykit/src/providers/stripe.ts
  • packages/stripe/src/stripe-provider.ts
✅ Files skipped from review due to trivial changes (4)
  • packages/paykit/src/index.ts
  • packages/paykit/src/core/errors.ts
  • packages/stripe/src/stripe-provider.ts
  • landing/content/docs/providers/stripe.mdx
🚧 Files skipped from review as they are similar to previous changes (1)
  • packages/paykit/src/providers/tests/stripe.test.ts


async createSubscriptionCheckout(data) {
const sessionParams: StripeSdk.Checkout.SessionCreateParams = {
const sessionParams: StripeSdk.Checkout.SessionCreateParams & {
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I presume once the managed payments feature is out of preview it will be generally available the SDK and we won't need this union?

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yep, but some people ask for it already, managed payment is very useful (taxes handled)

export function createStripeRuntime(options: StripeProviderConfig): StripeRuntime {
return createStripeProvider(new StripeSdk(options.secretKey), options);
const apiVersion = options.apiVersion ?? PAYKIT_STRIPE_API_VERSION;
if (options.managedPayments && apiVersion !== STRIPE_MANAGED_PAYMENTS_API_VERSION) {
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If Stripe update the SDK preview version and someone tries to use it, it will throw here, even though it shouldn't... I presume?

Trying to think of a better way to manage that.

@maxktz
Copy link
Copy Markdown
Contributor

maxktz commented Apr 12, 2026

@CodeRabbit review

@coderabbitai
Copy link
Copy Markdown

coderabbitai bot commented Apr 12, 2026

✅ Actions performed

Review triggered.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

@maxktz
Copy link
Copy Markdown
Contributor

maxktz commented Apr 12, 2026

yo @aristotl-dylan, why do you have an empty account?

@ducitymp
Copy link
Copy Markdown

ducitymp commented Apr 12, 2026

yo @aristotl-dylan, why do you have an empty account?

I made the pr with my work account on accident lol

Replaces strict equality check with >= comparison so newer Stripe
preview versions are accepted without requiring a PayKit update.
Copy link
Copy Markdown

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
packages/paykit/src/providers/stripe.ts (1)

508-514: ⚠️ Potential issue | 🟠 Major

Enforce the managed-payments/apiVersion invariant in createStripeProvider() too.

createSubscriptionCheckout() uses options.managedPayments (line 597), but validation only runs in createStripeRuntime(). Direct callers of createStripeProvider() (including the test helper at line 143) bypass validation entirely, allowing managed_payments to be enabled without the required preview API version.

Suggested refactor
+function assertManagedPaymentsConfig(options: StripeProviderConfig): string {
+  const apiVersion = options.apiVersion ?? PAYKIT_STRIPE_API_VERSION;
+  if (options.managedPayments && !isManagedPaymentsApiVersion(apiVersion)) {
+    throw PayKitError.from(
+      "BAD_REQUEST",
+      PAYKIT_ERROR_CODES.PROVIDER_INVALID_CONFIG,
+      `stripe({ managedPayments: true }) requires a preview API version >= "${STRIPE_MANAGED_PAYMENTS_MIN_VERSION}.preview" (got "${apiVersion}"). Managed Payments is a Stripe preview feature; see https://docs.stripe.com/payments/managed-payments`,
+    );
+  }
+  return apiVersion;
+}
+
 export function createStripeProvider(
   client: StripeSdk,
   options: StripeProviderConfig,
 ): StripeRuntime {
+  assertManagedPaymentsConfig(options);
   const currency = options.currency ?? "usd";
   ...
 }
 
 export function createStripeRuntime(options: StripeProviderConfig): StripeRuntime {
-  const apiVersion = options.apiVersion ?? PAYKIT_STRIPE_API_VERSION;
-  if (options.managedPayments) {
-    ...
-  }
+  const apiVersion = assertManagedPaymentsConfig(options);
   const client = new StripeSdk(options.secretKey, {
     apiVersion: apiVersion as StripeSdk.LatestApiVersion,
   });
-  return createStripeProvider(client, options);
+  return createStripeProvider(client, { ...options, apiVersion });
 }

Also applies to: 588-603, 908-927

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@packages/paykit/src/providers/stripe.ts` around lines 508 - 514,
createStripeProvider currently allows options.managedPayments to be true without
verifying the required preview API version (the same invariant enforced in
createStripeRuntime), which lets callers (and tests) bypass the safety check;
fix by enforcing the same validation inside createStripeProvider: when
options.managedPayments is true, assert options.apiVersion meets the required
preview/API version (or call the existing validation used by
createStripeRuntime), otherwise throw a clear error; extract the check into a
shared helper (e.g., validateManagedPaymentsApiVersion) and call it from both
createStripeProvider and createStripeRuntime so createSubscriptionCheckout and
test helpers cannot enable managed_payments without the correct apiVersion.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@packages/paykit/src/providers/stripe.ts`:
- Around line 910-921: The preview-version validation around
options.managedPayments is too permissive; replace the endsWith + naive prefix
compare with a regex that enforces the canonical Stripe preview format and then
compare the date prefix against STRIPE_MANAGED_PAYMENTS_MIN_VERSION.
Specifically, in the stripe provider block that checks options.managedPayments
and uses apiVersion, validate apiVersion with a regex like
/^\d{4}-\d{2}-\d{2}\.preview$/ (reject otherwise), extract the YYYY-MM-DD
prefix, then compare that prefix against STRIPE_MANAGED_PAYMENTS_MIN_VERSION
(string compare is safe for zero-padded YYYY-MM-DD) and if either the format is
invalid or it’s less than the minimum throw the same PayKitError.from(...,
PAYKIT_ERROR_CODES.PROVIDER_INVALID_CONFIG, ...) with an updated message that
includes the offending apiVersion and the required minimum.

---

Outside diff comments:
In `@packages/paykit/src/providers/stripe.ts`:
- Around line 508-514: createStripeProvider currently allows
options.managedPayments to be true without verifying the required preview API
version (the same invariant enforced in createStripeRuntime), which lets callers
(and tests) bypass the safety check; fix by enforcing the same validation inside
createStripeProvider: when options.managedPayments is true, assert
options.apiVersion meets the required preview/API version (or call the existing
validation used by createStripeRuntime), otherwise throw a clear error; extract
the check into a shared helper (e.g., validateManagedPaymentsApiVersion) and
call it from both createStripeProvider and createStripeRuntime so
createSubscriptionCheckout and test helpers cannot enable managed_payments
without the correct apiVersion.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro

Run ID: 3f77a4ff-4fc5-44b8-a2c3-fc8efd6d34ab

📥 Commits

Reviewing files that changed from the base of the PR and between b322e0b and 5fa4815.

📒 Files selected for processing (2)
  • packages/paykit/src/providers/__tests__/stripe.test.ts
  • packages/paykit/src/providers/stripe.ts

Comment on lines +910 to +921
if (options.managedPayments) {
const isPreview = apiVersion.endsWith(".preview");
const datePrefix = apiVersion.split(".preview")[0];
const meetsMinimum =
datePrefix !== undefined && datePrefix >= STRIPE_MANAGED_PAYMENTS_MIN_VERSION;

if (!(isPreview && meetsMinimum)) {
throw PayKitError.from(
"BAD_REQUEST",
PAYKIT_ERROR_CODES.PROVIDER_INVALID_CONFIG,
`stripe({ managedPayments: true }) requires a preview API version >= "${STRIPE_MANAGED_PAYMENTS_MIN_VERSION}.preview" (got "${apiVersion}"). Managed Payments is a Stripe preview feature; see https://docs.stripe.com/payments/managed-payments`,
);
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
python - <<'PY'
MIN = "2026-03-04"
for api_version in [
    "zzz.preview",
    "2026-3-4.preview",
    "2026-03-04.preview",
]:
    is_preview = api_version.endswith(".preview")
    date_prefix = api_version.split(".preview")[0]
    meets_minimum = date_prefix >= MIN
    print(api_version, {"accepted": is_preview and meets_minimum})
PY

Repository: getpaykit/paykit

Length of output: 164


🏁 Script executed:

cd packages/paykit && wc -l src/providers/stripe.ts

Repository: getpaykit/paykit

Length of output: 87


🏁 Script executed:

cd packages/paykit && sed -n '905,925p' src/providers/stripe.ts

Repository: getpaykit/paykit

Length of output: 1001


🏁 Script executed:

cd packages/paykit && sed -n '1,20p' src/providers/stripe.ts | grep -E "(PAYKIT_STRIPE_API_VERSION|STRIPE_MANAGED_PAYMENTS_MIN_VERSION)"

Repository: getpaykit/paykit

Length of output: 179


🏁 Script executed:

cd packages/paykit && find . -name "*.test.ts" -o -name "*.spec.ts" | xargs grep -l "managedPayments" 2>/dev/null

Repository: getpaykit/paykit

Length of output: 100


🏁 Script executed:

cd packages/paykit && rg "managedPayments" src/providers/__tests__/stripe.test.ts -A 3 -B 3

Repository: getpaykit/paykit

Length of output: 1663


🏁 Script executed:

# Verify the suggested fix logic
python - <<'PY'
import re

MIN = "2026-03-04"

def isManagedPaymentsApiVersion(apiVersion: str) -> bool:
    match = re.match(r'^(\d{4}-\d{2}-\d{2})\.preview$', apiVersion)
    datePrefix = match.group(1) if match else None
    return datePrefix is not None and datePrefix >= MIN

test_cases = [
    ("zzz.preview", False),
    ("2026-3-4.preview", False),
    ("2026-03-04.preview", True),
    ("2026-03-05.preview", True),
    ("2026-03-03.preview", False),
    ("2025-10-29.clover", False),
    ("2026-03-04", False),  # missing .preview
]

for api_version, expected in test_cases:
    result = isManagedPaymentsApiVersion(api_version)
    status = "✓" if result == expected else "✗"
    print(f"{status} {api_version}: {result} (expected {expected})")
PY

Repository: getpaykit/paykit

Length of output: 352


Extract API version validation into a regex-based predicate to reject malformed preview versions.

The current validation accepts arbitrary strings like "zzz.preview" or "2026-3-4.preview" because it only checks endsWith(".preview") and then applies lexicographic >= comparison on an unvalidated prefix. This weakens fail-fast validation and pushes the error to the Stripe SDK.

Replace the inline string operations with a regex-based validation that enforces the canonical Stripe API version format (YYYY-MM-DD.preview):

Suggested fix
+function isManagedPaymentsApiVersion(apiVersion: string): boolean {
+  const datePrefix = /^(\d{4}-\d{2}-\d{2})\.preview$/.exec(apiVersion)?.[1];
+  return datePrefix != null && datePrefix >= STRIPE_MANAGED_PAYMENTS_MIN_VERSION;
+}
+
 export function createStripeRuntime(options: StripeProviderConfig): StripeRuntime {
   const apiVersion = options.apiVersion ?? PAYKIT_STRIPE_API_VERSION;
   if (options.managedPayments) {
-    const isPreview = apiVersion.endsWith(".preview");
-    const datePrefix = apiVersion.split(".preview")[0];
-    const meetsMinimum =
-      datePrefix !== undefined && datePrefix >= STRIPE_MANAGED_PAYMENTS_MIN_VERSION;
-
-    if (!(isPreview && meetsMinimum)) {
+    if (!isManagedPaymentsApiVersion(apiVersion)) {
       throw PayKitError.from(
         "BAD_REQUEST",
         PAYKIT_ERROR_CODES.PROVIDER_INVALID_CONFIG,
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@packages/paykit/src/providers/stripe.ts` around lines 910 - 921, The
preview-version validation around options.managedPayments is too permissive;
replace the endsWith + naive prefix compare with a regex that enforces the
canonical Stripe preview format and then compare the date prefix against
STRIPE_MANAGED_PAYMENTS_MIN_VERSION. Specifically, in the stripe provider block
that checks options.managedPayments and uses apiVersion, validate apiVersion
with a regex like /^\d{4}-\d{2}-\d{2}\.preview$/ (reject otherwise), extract the
YYYY-MM-DD prefix, then compare that prefix against
STRIPE_MANAGED_PAYMENTS_MIN_VERSION (string compare is safe for zero-padded
YYYY-MM-DD) and if either the format is invalid or it’s less than the minimum
throw the same PayKitError.from(..., PAYKIT_ERROR_CODES.PROVIDER_INVALID_CONFIG,
...) with an updated message that includes the offending apiVersion and the
required minimum.

@lassejlv
Copy link
Copy Markdown

apiVersion is the best way since it match the original stripe sdk.

Resolve conflicts from provider adapter layer refactor. Adapt managed
payments feature to use new PaymentProvider interface. Fix logger test
for time-only dev format.
Copy link
Copy Markdown

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🧹 Nitpick comments (1)
packages/stripe/src/__tests__/stripe.test.ts (1)

133-146: Align test fixture with public managedPayments invariant.

When managedPayments is enabled, this helper should also set a preview apiVersion; otherwise the test is exercising a configuration that public stripe(...) rejects.

Proposed test-helper adjustment
     function createCheckoutRuntime(
       createSession: ReturnType<typeof vi.fn>,
       managedPayments: boolean,
     ) {
       return createStripeProvider(
         {
           checkout: { sessions: { create: createSession } },
         } as never,
         {
+          apiVersion: managedPayments ? "2026-03-04.preview" : undefined,
           managedPayments,
           secretKey: "sk_test_123",
           webhookSecret: "whsec_123",
         },
       );
     }
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@packages/stripe/src/__tests__/stripe.test.ts` around lines 133 - 146, The
test helper createCheckoutRuntime currently calls createStripeProvider with
managedPayments true but doesn't set a preview apiVersion, causing tests to
exercise a config that the public stripe(...) API would reject; update
createCheckoutRuntime so that when the managedPayments parameter is true it also
passes an apiVersion (preview) in the provider options (i.e., include apiVersion
alongside managedPayments, secretKey, webhookSecret) so the fixture matches the
public managedPayments invariant expected by createStripeProvider/stripe(...).
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@packages/stripe/src/__tests__/stripe.test.ts`:
- Around line 132-217: Add a JSDoc `@see` tag linking the issue URL (e.g., `#109`)
to this regression test block: put a short JSDoc comment with `@see` and the issue
reference immediately above the describe("managed payments", ...) block so the
tests for createCheckoutRuntime/createSubscriptionCheckout and the stripe(...)
apiVersion checks are annotated as regression coverage for that issue.

---

Nitpick comments:
In `@packages/stripe/src/__tests__/stripe.test.ts`:
- Around line 133-146: The test helper createCheckoutRuntime currently calls
createStripeProvider with managedPayments true but doesn't set a preview
apiVersion, causing tests to exercise a config that the public stripe(...) API
would reject; update createCheckoutRuntime so that when the managedPayments
parameter is true it also passes an apiVersion (preview) in the provider options
(i.e., include apiVersion alongside managedPayments, secretKey, webhookSecret)
so the fixture matches the public managedPayments invariant expected by
createStripeProvider/stripe(...).
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro

Run ID: 578340e2-7dc1-4f72-8fb7-de6bfd01b9d9

📥 Commits

Reviewing files that changed from the base of the PR and between 5fa4815 and 33c8171.

📒 Files selected for processing (5)
  • packages/paykit/src/core/__tests__/logger.test.ts
  • packages/paykit/src/core/errors.ts
  • packages/stripe/src/__tests__/stripe.test.ts
  • packages/stripe/src/index.ts
  • packages/stripe/src/stripe-provider.ts
🚧 Files skipped from review as they are similar to previous changes (2)
  • packages/paykit/src/core/errors.ts
  • packages/stripe/src/stripe-provider.ts

@maxktz maxktz merged commit e3c1685 into getpaykit:main Apr 13, 2026
0 of 2 checks passed
@maxktz
Copy link
Copy Markdown
Contributor

maxktz commented Apr 13, 2026

Thank you

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.

feat(pay): stripe managed_payments support

5 participants