Alt description missing in image
Beta: Plugins coming soon!
@payments/striperesolverssyncStripeData
Alt description missing in image

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 user by customerId via getUserByCustomerId().
  • Fetches current Stripe state in parallel: customer, subscriptions, paymentIntents, completed checkouts, charges, invoices.
  • Upserts the Customer record with email + name fallbacks and raw JSON snapshots.
  • Builds / upserts Subscriptions from subscription items and invoice details, mapping statuses.
  • Builds / upserts Purchases for non‑subscription items (payment intents + completed checkouts).
syncStripeData.resolver.ts
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.