Skip to content

feat(payments-next): Move subscription creation after SetupIntent validation#20523

Open
david1alvarez wants to merge 1 commit intomainfrom
PAY-3675
Open

feat(payments-next): Move subscription creation after SetupIntent validation#20523
david1alvarez wants to merge 1 commit intomainfrom
PAY-3675

Conversation

@david1alvarez
Copy link
Copy Markdown
Contributor

Because:

  • Currently if a SetupIntent fails, the subscription has been created in Stripe already. When the SetupIntent fails, we cancel the created subscription. This causes the creation and cancellation Stripe webhooks to fire, which triggers unexpected emails for the customer.

This commit:

  • In the case of creating a subscription via a SetupIntent, the subscription creation is processed once the SetupIntent has been confirmed.

Closes #PAY-3675

Checklist

Put an x in the boxes that apply

  • My commit is GPG signed.
  • If applicable, I have modified or added tests which pass locally.
  • I have added necessary documentation (if appropriate).
  • I have verified that my changes render correctly in RTL (if appropriate).
  • I have manually reviewed all AI generated code.

…idation

Because:

* Currently if a SetupIntent fails, the subscription has been created in Stripe already. When the SetupIntent fails, we cancel the created subscription. This causes the creation and cancellation Stripe webhooks to fire, which triggers unexpected emails for the customer.

This commit:

* In the case of creating a subscription via a SetupIntent, the subscription creation is processed once the SetupIntent has been confirmed.

Closes #PAY-3675
Copilot AI review requested due to automatic review settings May 6, 2026 00:53
@david1alvarez david1alvarez requested a review from a team as a code owner May 6, 2026 00:53
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

This PR changes the zero-initial Stripe checkout flow in payments-next so subscriptions are created only after a SetupIntent has been validated, aiming to avoid create/cancel webhook churn and the customer emails that follow from failed SetupIntents.

Changes:

  • Adds a setup-intent-first Stripe path for free-trial and zero-amount checkouts, with a follow-up finalize step after submitNeedsInput.
  • Threads attribution and request metadata through the needs-input action so deferred subscription creation still has checkout context.
  • Refactors shared attribution extraction and updates tests/error handling around the new flow.

Reviewed changes

Copilot reviewed 13 out of 13 changed files in this pull request and generated 2 comments.

Show a summary per file
File Description
libs/payments/ui/src/lib/utils/getAttributionFromSearchParams.ts Adds a shared helper to normalize attribution fields from Next.js search params.
libs/payments/ui/src/lib/nestapp/validators/SubmitNeedsInputActionArgs.ts Expands action validation to accept attribution and request metadata.
libs/payments/ui/src/lib/nestapp/nextjs-actions.service.ts Forwards the new submit-needs-input payload to cart service.
libs/payments/ui/src/lib/client/components/PaymentInputHandler/index.tsx Keeps the needs-input client flow calling the redirect action after Stripe next-action handling.
libs/payments/ui/src/lib/client/components/CheckoutForm/index.tsx Reuses the shared attribution helper in checkout form submission paths.
libs/payments/ui/src/lib/actions/submitNeedsInputAndRedirect.ts Sends attribution/request context when completing needs-input and redirecting.
libs/payments/ui/src/index.ts Re-exports the new attribution helper.
libs/payments/cart/src/lib/checkout.service.ts Introduces deferred subscription creation for zero-initial Stripe checkouts and helper methods around SetupIntent finalization.
libs/payments/cart/src/lib/checkout.service.spec.ts Adds tests for zero-initial Stripe flows and deferred setup-intent finalization.
libs/payments/cart/src/lib/checkout.error.ts Adds a new checkout error for missing SetupIntent responses.
libs/payments/cart/src/lib/cart.service.ts Updates needs-input handling to finalize subscription creation after a successful SetupIntent when no subscription exists yet.
libs/payments/cart/src/lib/cart.service.spec.ts Adds coverage for setup-intent cleanup and the new submit-needs-input branch.
libs/payments/cart/src/lib/cart.error.ts Removes the obsolete “missing subscription id” cart error for submit-needs-input.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines +834 to +836
await this.cartManager.updateProcessingCart(cart.id, version, {
stripeSubscriptionId: subscription.id,
});
Comment on lines +2206 to +2217
it('retrieves setup intent and creates subscription', async () => {
await checkoutService.finalizeSetupIntentAndCreateSubscription(
mockCart,
mockAttributionData,
mockRequestArgs
);

expect(setupIntentManager.retrieve).toHaveBeenCalledWith(
mockCart.stripeIntentId
);
expect(subscriptionManager.create).toHaveBeenCalled();
expect(checkoutService.postPaySteps).toHaveBeenCalled();
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.

2 participants