syncStripeData()
Synchronizes Stripe state into your DB entitlements: Customer, Subscriptions, and Purchases. Use after webhooks and checkout/portal return URLs.
Usage - Directly
import { syncStripeData } from '@payments/stripe/resolvers/syncStripeData.resolver'await syncStripeData({ customerId })Usage - Driver
import { syncPaymentData } from '@payments/driver'When calling the driver version, it will actually execute all syncPaymentData() methods on every payment driver, including this one. Which is why we pass the user (to get all customers) instead of the customerId (stripe specific) in this case.
await syncPaymentData({ user })Implementation details
- Resolves the
userbycustomerIdviagetUserByCustomerId(). - Fetches current Stripe state in parallel:
customer,subscriptions,paymentIntents,completed checkouts,charges,invoices. - Upserts the
Customerrecord with email + name fallbacks and raw JSON snapshots. - Builds / upserts
Subscriptionsfrom subscription items and invoice details, mapping statuses. - Builds / upserts
Purchasesfor non‑subscription items (payment intents + completed checkouts).
export const syncStripeData = createResolver(async ({ args, parseArgs, withDefaults }) => {
// Retrieve relevant user and customer
const { customerId, user: argsUser } = parseArgs(args)
let { user, customer } = await getUserByCustomerId({ customerId })
// Fetch state
const [stripeCustomer, stripeSubscriptions, paymentIntents, checkouts, charges, invoices] = await Promise.all([
findCustomerById(customerId),
getCustomerSubscriptions(customerId),
getCustomerPaymentIntents(customerId),
getCustomerCheckouts(customerId, 'complete'),
getCustomerCharges(customerId),
getCustomerInvoices(customerId),
])
// Upsert Customer, Subscriptions, Purchases ...
// ...
// Return updated & normalized payment provider data
return withDefaults({ provider: 'stripe', user, customer, subscriptions, purchases })
})SyncPaymentDataInput
Follows the driver signature SyncPaymentDataInput schema:
import { SyncPaymentDataInput } from '@payments/driver/driver.signature'export const SyncPaymentDataInput = schema('SyncPaymentDataInput', {
customerId: Customer.shape.customerId,
user: User.nullish(),
})SyncPaymentDataOutput
Follows the driver signature SyncPaymentDataOutput schema:
import { SyncPaymentDataOutput } from '@payments/driver/driver.signature'export const SyncPaymentDataOutput = schema('SyncPaymentDataOutput', {
provider: PaymentProvidable.shape.provider,
user: User.nullish(),
customer: Customer.nullish(),
subscriptions: Subscription.array().nullish(),
purchases: Purchase.array().nullish(),
})When to use
Call on: Webhooks, e.g. subscription changes, refunds, successful charges, invoice finalization, and after checkout/portal returns to keep entitlements consistent.
A webhook to trigger on all relevant stripe events is already set up at /api/webhooks/stripe.
Custom post portal / checkout redirect URLs where syncPaymentData() is called manually are still advised.
