chore(payments-next): update Stripe SDK to 22.3.1 (2026-06-24.dahlia)#20811
Conversation
6de05dc to
014ff53
Compare
There was a problem hiding this comment.
Pull request overview
Updates FxA’s Stripe integration to stripe@22.3.1 while pinning requests to the 2026-06-24.dahlia Stripe API version, and migrates code/fixtures/tests to the post-“basil” invoice/subscription/payment schemas (including preview-invoice changes and transitional webhook dual-read for subscription references).
Changes:
- Upgrade Stripe SDK and pin a shared
STRIPE_API_VERSIONacross Stripe client construction sites (with a yarn patch to restore type resolution). - Migrate invoice/subscription reads to basil-era shapes (
parent.subscription_details,payments[], item-level current period fields,createPreview,discounts[].source.coupon,total_taxes, etc.). - Update factories, fixtures, and unit/integration tests to match new Stripe object shapes and expanded-field expectations.
Reviewed changes
Copilot reviewed 107 out of 108 changed files in this pull request and generated 2 comments.
Show a summary per file
| File | Description |
|---|---|
| yarn.lock | Updates resolved Stripe dependency to v22.3.1 and records patched variant. |
| package.json | Bumps stripe to 22.3.1 and adds a yarn patch + documentation comment. |
| .yarn/patches/stripe-npm-22.3.1-291b1ac8f8.patch | Re-adds top-level types to keep TS resolution working with the exports map. |
| packages/fxa-shared/test/subscriptions/stripe.ts | Updates shared Stripe filtering tests for new invoice/payment shapes. |
| packages/fxa-shared/test/fixtures/stripe/subscription_expanded.json | Updates fixture to basil invoice/subscription/payment nesting. |
| packages/fxa-shared/test/fixtures/stripe/customer1_with_subscription.json | Moves period fields to subscription items in fixture. |
| packages/fxa-shared/subscriptions/types.ts | Adjusts shared subscription/invoice preview types for new Stripe schema. |
| packages/fxa-shared/subscriptions/stripe.ts | Updates shared Stripe filtering logic to match new invoice fields. |
| packages/fxa-shared/payments/stripe.ts | Updates Stripe response event typing for metrics hook. |
| packages/fxa-shared/payments/stripe-firestore.ts | Makes Firestore persistence tolerant of Stripe Decimal prototypes + schema changes. |
| packages/fxa-auth-server/test/local/payments/fixtures/stripe/subscription2.json | Updates subscription item period fields fixture. |
| packages/fxa-auth-server/test/local/payments/fixtures/stripe/subscription1.json | Updates subscription item period fields fixture. |
| packages/fxa-auth-server/test/local/payments/fixtures/stripe/subscription_trialing.json | Updates subscription item period fields fixture. |
| packages/fxa-auth-server/test/local/payments/fixtures/stripe/subscription_pmi_expanded.json | Updates expanded subscription/invoice/payment fixture and formatting. |
| packages/fxa-auth-server/test/local/payments/fixtures/stripe/subscription_pmi_expanded_incomplete_cvc_fail.json | Updates expanded subscription/payment method fixture formatting and fields. |
| packages/fxa-auth-server/test/local/payments/fixtures/stripe/subscription_past_due.json | Updates subscription item period fields fixture. |
| packages/fxa-auth-server/test/local/payments/fixtures/stripe/subscription_multiplan.json | Updates multi-plan subscription item period fields fixture. |
| packages/fxa-auth-server/test/local/payments/fixtures/stripe/subscription_coupon_repeating.json | Migrates subscription discount shape to discounts[].source.coupon. |
| packages/fxa-auth-server/test/local/payments/fixtures/stripe/subscription_coupon_once.json | Updates subscription item period fields fixture. |
| packages/fxa-auth-server/test/local/payments/fixtures/stripe/subscription_coupon_forever.json | Migrates subscription discount shape to discounts[].source.coupon. |
| packages/fxa-auth-server/test/local/payments/fixtures/stripe/subscription_cancelled.json | Updates subscription item period fields fixture. |
| packages/fxa-auth-server/test/local/payments/fixtures/stripe/invoice_preview_tax.json | Updates invoice preview fixture to basil pricing/parent/taxes/total_taxes shape. |
| packages/fxa-auth-server/test/local/payments/fixtures/stripe/invoice_preview_tax_discount.json | Updates invoice preview + discount fixture to basil schema. |
| packages/fxa-auth-server/test/local/payments/fixtures/stripe/invoice_paid_subscription_create.json | Updates paid invoice fixture to parent + payments fields. |
| packages/fxa-auth-server/test/local/payments/fixtures/stripe/invoice_paid_subscription_create_tax.json | Updates paid invoice + tax fixture to basil schema. |
| packages/fxa-auth-server/test/local/payments/fixtures/stripe/invoice_paid_subscription_create_tax_discount.json | Updates paid invoice + tax + discount fixture to basil schema. |
| packages/fxa-auth-server/test/local/payments/fixtures/stripe/invoice_paid_subscription_create_discount.json | Updates paid invoice + discount fixture to basil schema. |
| packages/fxa-auth-server/test/local/payments/fixtures/stripe/invoice_open.json | Updates open invoice fixture to basil payments/parent schema. |
| packages/fxa-auth-server/test/local/payments/fixtures/stripe/invoice_draft_proration_refund.json | Updates draft/proration refund fixture to basil parent/proration_details schema. |
| packages/fxa-auth-server/scripts/refund-unverified-accounts.ts | Pins API version constant and migrates invoice payment-intent lookup. |
| packages/fxa-auth-server/scripts/paypal-refund-fixer.ts | Migrates invoice subscription reference to parent.subscription_details.subscription. |
| packages/fxa-auth-server/scripts/move-customers-to-new-plan/move-customers-to-new-plan.ts | Migrates invoice charge lookup to payments[].payment.charge. |
| packages/fxa-auth-server/scripts/move-customers-to-new-plan-v2/move-customers-to-new-plan-v2.ts | Migrates paid-state/charge/period fields and PayPal-vs-Stripe routing. |
| packages/fxa-auth-server/scripts/move-customers-to-new-plan-v2/move-customers-to-new-plan-v2.spec.ts | Updates mover v2 tests to new invoice/subscription schemas. |
| packages/fxa-auth-server/scripts/convert-customers-to-stripe-automatic-tax/helpers.ts | Migrates current period end + total tax typing and accessors. |
| packages/fxa-auth-server/scripts/convert-customers-to-stripe-automatic-tax/helpers.spec.ts | Updates helper tests for new tax object shape. |
| packages/fxa-auth-server/scripts/convert-customers-to-stripe-automatic-tax/convert-customers-to-stripe-automatic-tax.ts | Switches upcoming invoice preview to createPreview and totals via total_taxes. |
| packages/fxa-auth-server/scripts/convert-customers-to-stripe-automatic-tax/convert-customers-to-stripe-automatic-tax.spec.ts | Updates converter tests for createPreview and new expand paths/tax sums. |
| packages/fxa-auth-server/scripts/check-firestore-stripe-sync/check-firestore-stripe-sync.spec.ts | Updates sync checker tests to item-level period fields. |
| packages/fxa-auth-server/scripts/cancel-subscriptions-to-plan/cancel-subscriptions-to-plan.ts | Migrates refund/paid checks and period fields + charge lookup. |
| packages/fxa-auth-server/scripts/cancel-subscriptions-to-plan/cancel-subscriptions-to-plan.spec.ts | Updates cancellation script tests for new invoice/subscription schemas. |
| packages/fxa-auth-server/scripts/audit-orphaned-customers.ts | Pins API version constant for audit script Stripe client. |
| packages/fxa-auth-server/lib/routes/subscriptions/stripe-webhooks.spec.ts | Adds coverage for basil invoice.parent.subscription_details.subscription. |
| packages/fxa-auth-server/lib/routes/subscriptions/stripe-webhook.ts | Implements transitional dual-read for subscription reference from webhook invoices. |
| packages/fxa-auth-server/lib/routes/subscriptions/paypal-notifications.ts | Implements transitional dual-read for subscription reference from PayPal flow. |
| packages/fxa-auth-server/lib/routes/subscriptions/paypal-notifications.spec.ts | Adds test for basil subscription reference path. |
| packages/fxa-auth-server/lib/routes/subscriptions/mozilla.ts | Adapts Decimal parsing for unit amount decimals. |
| packages/fxa-auth-server/lib/payments/subscription-reminders.ts | Migrates reminders to item-level period fields + discounts[] + total_taxes sums. |
| packages/fxa-auth-server/lib/payments/subscription-reminders.spec.ts | Updates reminders tests for discount/tax schema changes. |
| packages/fxa-auth-server/lib/payments/stripe.ts | Core migration of legacy StripeHelper for basil invoice/subscription/payment/tax/discount shapes. |
| packages/fxa-auth-server/lib/payments/stripe-formatter.ts | Updates invoice preview DTO formatting to new pricing/taxes/discounts schema. |
| packages/fxa-auth-server/lib/payments/stripe-formatter.spec.ts | Updates formatter tests for total_taxes and discounts nesting. |
| packages/fxa-auth-server/lib/payments/stripe-firestore.spec.ts | Updates Firestore caching tests for basil invoice parent subscription reference. |
| packages/fxa-auth-server/lib/payments/paypal/processor.ts | Migrates subscription reference extraction from invoice to basil parent shape. |
| packages/fxa-auth-server/lib/payments/paypal/processor.spec.ts | Updates PayPal processor tests for basil parent subscription reference. |
| packages/fxa-auth-server/lib/payments/paypal/helper.ts | Migrates tax handling from tax to summed total_taxes. |
| packages/fxa-auth-server/lib/payments/paypal/helper.spec.ts | Updates PayPal helper test expectations for tax totals. |
| packages/fxa-admin-server/src/subscriptions/subscriptions.service.spec.ts | Updates admin subscription service tests for item-level period fields. |
| packages/fxa-admin-server/src/subscriptions/subscriptions.formatters.ts | Migrates admin formatter to item-level period fields and updated types. |
| packages/fxa-admin-server/src/subscriptions/subscriptions.formatters.spec.ts | Updates formatter tests for new subscription shape. |
| packages/fxa-admin-server/src/subscriptions/stripe.service.ts | Pins Stripe client API version via shared constant. |
| packages/functional-tests/lib/sub-helpers.ts | Pins API version for functional tests without importing payments graph. |
| libs/payments/stripe/src/lib/stripe.constants.ts | Adds shared STRIPE_API_VERSION constant. |
| libs/payments/stripe/src/lib/stripe.client.types.ts | Updates core type wrappers for basil invoice/subscription/payment/discount schema. |
| libs/payments/stripe/src/lib/stripe.client.ts | Pins API version and updates invoice preview method to createPreview + new expands. |
| libs/payments/stripe/src/lib/stripe.client.spec.ts | Updates StripeClient tests/mocks for createPreview and expand behavior. |
| libs/payments/stripe/src/lib/factories/upcoming-invoice.factory.ts | Reuses invoice factory since preview invoices share invoice shape. |
| libs/payments/stripe/src/lib/factories/total-tax-amounts.factory.ts | Updates tax factories to basil tax objects. |
| libs/payments/stripe/src/lib/factories/subscription.factory.ts | Updates subscription factory for item-level period fields + new Stripe fields. |
| libs/payments/stripe/src/lib/factories/setup-intent.factory.ts | Updates setup intent factory for new Stripe fields. |
| libs/payments/stripe/src/lib/factories/promotion-code.factory.ts | Migrates promotion code factory to promotion.coupon nesting. |
| libs/payments/stripe/src/lib/factories/price.factory.ts | Updates Decimal typing/casting for Stripe DecimalImpl. |
| libs/payments/stripe/src/lib/factories/plan.factory.ts | Updates Decimal typing/casting for Stripe DecimalImpl. |
| libs/payments/stripe/src/lib/factories/payment-method.factory.ts | Updates payment method factory for new Stripe fields. |
| libs/payments/stripe/src/lib/factories/payment-intent.factory.ts | Updates payment intent factory for new Stripe fields. |
| libs/payments/stripe/src/lib/factories/invoice.factory.ts | Updates invoice factory to basil parent/payments/total_taxes/confirmation_secret. |
| libs/payments/stripe/src/lib/factories/invoice-payment.factory.ts | Adds factory for invoice_payment objects used by the basil invoice schema. |
| libs/payments/stripe/src/lib/factories/invoice-line-item.factory.ts | Updates invoice line item factory to basil parent/pricing/taxes fields. |
| libs/payments/stripe/src/lib/factories/discount.factory.ts | Migrates discount factory to source.coupon nesting. |
| libs/payments/stripe/src/lib/factories/customer.factory.ts | Updates customer factory for new Stripe fields. |
| libs/payments/stripe/src/lib/factories/customer-session.factory.ts | Updates customer session factory for new Stripe fields. |
| libs/payments/stripe/src/lib/factories/confirmation-token.factory.ts | Updates confirmation token factory for new Stripe fields. |
| libs/payments/stripe/src/lib/factories/card.factory.ts | Updates card factory for new Stripe fields. |
| libs/payments/stripe/src/lib/factories/card-payment-method.factory.ts | Updates card payment method factory for new Stripe fields. |
| libs/payments/stripe/src/index.ts | Exposes updated factories and constants via barrel exports. |
| libs/payments/metrics-aggregator/src/lib/payments-metrics-aggregator.service.ts | Migrates coupon code read to discounts[0].source.coupon. |
| libs/payments/metrics-aggregator/src/lib/payments-metrics-aggregator.service.spec.ts | Updates aggregator tests for new discount/coupon nesting. |
| libs/payments/management/src/lib/subscriptionManagement.service.ts | Migrates trial/period fields and promo name read to basil schema. |
| libs/payments/management/src/lib/subscriptionManagement.service.spec.ts | Updates management tests for item-level period fields. |
| libs/payments/management/src/lib/subscriptionManagement.service.in.spec.ts | Updates integration tests for item-level period fields. |
| libs/payments/customer/src/lib/util/stripeInvoiceToFirstInvoicePreviewDTO.ts | Migrates invoice preview DTO mapping to basil taxes/discounts/proration shape. |
| libs/payments/customer/src/lib/util/stripeInvoiceToFirstInvoicePreviewDTO.spec.ts | Updates DTO tests for basil tax/discount structures + inclusive-tax math. |
| libs/payments/customer/src/lib/util/determinePriceUnitAmount.ts | Adapts Decimal parsing for unit amount decimals. |
| libs/payments/customer/src/lib/util/assertPromotionCodeActive.ts | Migrates promotion code coupon access to promotion.coupon. |
| libs/payments/customer/src/lib/util/assertPromotionCodeActive.spec.ts | Updates tests for promotion.coupon nesting. |
| libs/payments/customer/src/lib/subscription.manager.ts | Migrates coupon checks to basil discounts array schema. |
| libs/payments/customer/src/lib/subscription.manager.spec.ts | Updates coupon-check tests for basil discounts schema. |
| libs/payments/customer/src/lib/promotionCode.manager.ts | Migrates promo currency check to promotion.coupon.currency. |
| libs/payments/customer/src/lib/promotionCode.manager.spec.ts | Updates tests for promotion.coupon nesting. |
| libs/payments/customer/src/lib/invoice.manager.ts | Switches preview calls to createPreview + sums total_taxes for PayPal charging. |
| libs/payments/customer/src/lib/invoice.manager.spec.ts | Updates invoice manager tests for createPreview and tax totals. |
| libs/payments/cart/src/lib/checkout.service.ts | Migrates promotion codes to discounts[] and confirms PI via confirmation_secret. |
| libs/payments/cart/src/lib/checkout.service.spec.ts | Updates checkout tests for discounts param and confirmation-secret PI confirmation. |
| libs/payments/cart/src/lib/cart.service.spec.ts | Updates Stripe imports/types for Stripe v22. |
| libs/payments/api-server/src/lib/util/transformToWebSubscription.ts | Migrates web subscription transform to item-level period fields. |
| libs/payments/api-server/src/lib/util/transformToWebSubscription.spec.ts | Updates test subscription shape to include item-level period fields. |
| libs/payments/api-server/src/lib/util/mapPriceInfo.ts | Adapts Decimal parsing for unit amount decimals. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
0c3849a to
8ceabf7
Compare
StaberindeZA
left a comment
There was a problem hiding this comment.
Overall it looks pretty good. I've left some inline comments that should be addressed and one question about differing structures/values between the Firestore mirror and Stripe.
I tested most of the flows and ran into a few issues, primarily regarding to coupons. I've attached a doc to the Jira ticket with the issues I experienced.
| } | ||
| ).subscription; | ||
| const subscription = subscriptionRef | ||
| ? await this.stripeHelper.expandResource( |
There was a problem hiding this comment.
question: what happens with different values/structures between Stripe and the Firestore mirror?
expandResource fetches data first from the Firestore mirror, before fetching from Stripe. After this patch the values stored in the Firestore mirror and data fetched from Stripe will have different structures and values. How would that impact things?
Note this doesn't just apply to Stripe Webhooks, but everywhere the expandResource is used.
There was a problem hiding this comment.
Firestore records from before this change are rewritten to the basil shape when their next {customer / customer.subscription / invoice / payment_method} {create/update/delete} webhook fires. New webhook events will have the updated structure, and old webhook events will be correctly expanded and converted as part of StripeWebhookHandler.processEventToFirestore (stripe-webhook.ts:93), which persists the object via processWebhookEventToFirestore and then re-fetches the latest version through expandResource before any handler runs. No existing record structs should break this, but if they do we'll see errors like a TypeError: Cannot read properties of undefined on a moved field.
e0f5229 to
aa385ae
Compare
| return { | ||
| customerId: customer?.id, | ||
| couponCode: subscription?.discount?.coupon.id, | ||
| couponCode: subscription?.discounts[0]?.source?.coupon.id, |
There was a problem hiding this comment.
question: did you consider using a helper function to retrieve the first discount?
There was a problem hiding this comment.
I didn't see enough sites for a subscription.discounts[0] helper to be useful here. We could make a generalized "get first in array" accessor, but [0] does that fairly clearly as well.
7449aa1 to
43f181f
Compare
| expand: ['total_taxes.tax_rate_details.tax_rate'], | ||
| }) | ||
| ); | ||
| return invoicePreview as StripeInvoice; |
There was a problem hiding this comment.
issue: do not use type assertion
Since this is using the Stripe SDK directly, and not stripe.client from libs/payments, using StripeInvoice does not accurately describe the value returned.
| product: Stripe.Product, | ||
| plan: Stripe.Plan, | ||
| invoicePreview: Stripe.UpcomingInvoice | ||
| invoicePreview: StripeInvoice |
There was a problem hiding this comment.
issue: do not use type StripeInvoice
Because: * Stripe's "basil" redesign (acacia -> dahlia API bump) reshaped the invoice, subscription, line-item, discount, and payment objects FxA relies on. This commit: * Pins `stripe` to 22.3.1 and apiVersion '2026-06-24.dahlia' via a shared STRIPE_API_VERSION constant, and yarn-patches back stripe's dropped top-level `types` field so it resolves under TypeScript. * Migrates every affected call site across the libs/payments/* StripeClient stack and the legacy fxa-auth-server StripeHelper to the basil shapes: invoice subscription ref, payments[]/confirmation_secret, item-level current_period_*, createPreview, the tax/discount/pricing reshape, PromotionCode.coupon, and the Decimal type. * Dual-reads webhook invoices (old + new shapes) to survive the API-version rollout window. * Updates the Stripe factories, specs, and fixtures to the basil shapes. Closes: PAY-3759
StaberindeZA
left a comment
There was a problem hiding this comment.
r+. ty for the changes
Because
stripedependency was pinned to17.4.0(API2024-11-20.acacia),several majors behind. Upgrading to
22.3.1(API2026-06-24.dahlia) crosses Stripe's "basil"billing redesign, which reshaped the invoice, subscription, line-item, discount, and payment-intent
objects the Subscription Platform relies on. Remaining on the old SDK keeps us on an
unsupported API version and blocks further Stripe work.
This pull request
stripefrom17.4.0to22.3.1and pinsapiVersion: '2026-06-24.dahlia'via a sharedSTRIPE_API_VERSIONconstant (libs/payments/stripe/src/lib/stripe.constants.ts), consumed atevery app/library client-construction site (
libs/payments/stripe/src/lib/stripe.client.ts,packages/fxa-auth-server/lib/payments/stripe.ts,packages/fxa-admin-server/src/subscriptions/stripe.service.ts, and the auth-server maintenancescripts).
packages/functional-tests/lib/sub-helpers.tspins the same version directly to avoidpulling the payments graph into the E2E helpers.
libs/payments/*StripeClientstack and thelegacy
fxa-auth-serverStripeHelper:invoice.subscription->invoice.parent.subscription_details.subscription;invoice.payment_intent/invoice.charge->invoice.payments[].payment.*+confirmation_secret;subscription.current_period_*->subscription-item level;
invoices.retrieveUpcoming->invoices.createPreview.tax+discount+pricing (
total_taxes, line-itemtaxes/pricing/parent),discount.coupon->source.coupon,PromotionCode.coupon->promotion.coupon,lineItem.planre-sourced via theline-item price, and branded
Decimalcoercions.invoice tax totals from
invoice.total_taxes, per-lineamount_excluding_taxreconstructed fromthe line item's inclusive
taxes, and discount/coupon metadata frominvoice.discounts[].source.coupon— expanded on theinvoices.retrievepath(
expand: ['confirmation_secret', 'discounts']) so the current-invoice preview keeps its couponname/duration/end.
invoice.collection_method === 'send_invoice'and invoice paid state frominvoice.status,replacing the removed
invoice.paid_out_of_band/invoice.paidfields.stripe-webhook.tsandpaypal-notifications.tsfrom both thenew and legacy shapes, so events serialized at the account's previous API version are still handled
during the Dashboard API-version rollout. Webhook signature verification is unchanged.
libs/payments/stripe/src/lib/factories/*,including a new
invoice-payment.factory.ts) and the co-located specs and fixtures to the basil shapes.Issue that this pull request solves
Closes: PAY-3759
Checklist
Put an
xin the boxes that applyHow to review
libs/payments/stripe/src/lib/stripe.client.types.ts(theNegotiateExpanded/DeepOverridetype wrappers driving the migration);packages/fxa-auth-server/lib/payments/stripe.ts(legacy StripeHelper, all categories);libs/payments/customer/src/lib/util/stripeInvoiceToFirstInvoicePreviewDTO.tsandpackages/fxa-auth-server/lib/payments/stripe-formatter.ts(invoice-preview DTO re-sourcing).libs/paymentsconsumers -> legacyauth-server StripeHelper + routes -> maintenance scripts -> fixtures.
amount_excluding_taxre-sourcing(billing-adjacent values, preserved to match prior output); and the PayPal-refund routing in
scripts/*(collection_method === 'send_invoice'), which issues real refunds against productioncustomer data.
nx run-many -t build-ts -p payments-stripe fxa-auth-serverandnx run-many -t test-unit -p payments-stripe payments-customer fxa-auth-server. TheStripeClientwrapper suite (libs/payments/stripe/src/lib/stripe.client.spec.ts) mocks stripe'sdefault export so
new Stripe()constructs under@swc/jest, and asserts theinvoices.retrieveexpand list.
Screenshots (Optional)
Please attach the screenshots of the changes made in case of change in user interface.
Other information (Optional)
(per environment; stage and prod are independent). Do not flip first. Outbound API calls are safe the
moment the code deploys: every client pins
apiVersion: '2026-06-24.dahlia', so Stripe returns dahliashapes per request regardless of the account's Dashboard default. Only inbound webhook payloads lag —
they are serialized at the endpoint/account version until the flip.
subscription-reference lookup tolerant of both shapes. Other invoice-driven handlers still read
basil-only fields directly off the raw event payload (e.g.
extractInvoiceDetailsForEmail:line.parent.type,lineItem.pricing.price_details.price,invoice.payments[].payment.charge,invoice.discounts[].source.coupon). On an acacia-era payload these find no line item and throw;handleInvoicePaidEventcatches it, reports to Sentry, and skips the email — so subscriptionfirst-invoice/renewal emails are dropped (and not retried) for the duration of the window. No hard
crash and no data corruption, but not fully correct until the flip.
the invoice by id at webhook-handler entry (
invoicesRetrieve(id)returns dahlia because the SDKpins it) and read everything off that, at which point the dual-read can be removed.
exportsmap, which the repo'smoduleResolution: "node"does not read. A Berry (yarn) patch re-adds the top-leveltypesfieldstripe dropped (
.yarn/patches/stripe-npm-22.3.1-291b1ac8f8.patch), so the SDK's.d.tsresolveswith no
pathsalias and nomoduleResolution/emit change; it is documented in the package.jsonresolutionCommentsand must be regenerated on the next Stripe upgrade.