kopia lustrzana https://github.com/transitive-bullshit/chatgpt-api
feat: WIP stripe billing refactor update for 2025
rodzic
ed0867a3b9
commit
8ea3a4f4b6
|
@ -87,10 +87,10 @@ export const consumers = pgTable(
|
||||||
stripeStatus: text(),
|
stripeStatus: text(),
|
||||||
|
|
||||||
// Main Stripe Subscription id
|
// Main Stripe Subscription id
|
||||||
stripeSubscriptionId: stripeId(),
|
_stripeSubscriptionId: stripeId(),
|
||||||
|
|
||||||
// [lineItemSlug: string]: string
|
// [lineItemSlug: string]: string
|
||||||
stripeSubscriptionLineItemIdMap: jsonb()
|
_stripeSubscriptionLineItemIdMap: jsonb()
|
||||||
.$type<Record<string, string>>()
|
.$type<Record<string, string>>()
|
||||||
.default({})
|
.default({})
|
||||||
.notNull(),
|
.notNull(),
|
||||||
|
@ -132,7 +132,7 @@ export const consumerRelationsSchema: z.ZodType<ConsumerRelationFields> =
|
||||||
z.enum(['user', 'project', 'deployment'])
|
z.enum(['user', 'project', 'deployment'])
|
||||||
|
|
||||||
export const consumerSelectSchema = createSelectSchema(consumers, {
|
export const consumerSelectSchema = createSelectSchema(consumers, {
|
||||||
stripeSubscriptionLineItemIdMap: z.record(z.string(), z.string()),
|
_stripeSubscriptionLineItemIdMap: z.record(z.string(), z.string()),
|
||||||
|
|
||||||
deploymentId: (schema) =>
|
deploymentId: (schema) =>
|
||||||
schema.refine((id) => validators.deploymentId(id), {
|
schema.refine((id) => validators.deploymentId(id), {
|
||||||
|
@ -145,6 +145,8 @@ export const consumerSelectSchema = createSelectSchema(consumers, {
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
.omit({
|
.omit({
|
||||||
|
_stripeSubscriptionId: true,
|
||||||
|
_stripeSubscriptionLineItemIdMap: true,
|
||||||
_stripeCustomerId: true
|
_stripeCustomerId: true
|
||||||
})
|
})
|
||||||
.extend({
|
.extend({
|
||||||
|
|
|
@ -341,7 +341,7 @@ export const pricingPlanMapSchema = z
|
||||||
export type PricingPlanMap = z.infer<typeof pricingPlanMapSchema>
|
export type PricingPlanMap = z.infer<typeof pricingPlanMapSchema>
|
||||||
|
|
||||||
// TODO
|
// TODO
|
||||||
// export const stripeSubscriptionLineItemIdMapSchema = z
|
// export const _stripeSubscriptionLineItemIdMapSchema = z
|
||||||
// .record(pricingPlanLineItemHashSchema, z.string().describe('Stripe LineItem id'))
|
// .record(pricingPlanLineItemHashSchema, z.string().describe('Stripe LineItem id'))
|
||||||
// .describe('Map from internal PricingPlanLineItem **hash** to Stripe LineItem id')
|
// .describe('Map from internal PricingPlanLineItem **hash** to Stripe LineItem id')
|
||||||
// .openapi('StripeSubscriptionLineItemMap')
|
// .openapi('StripeSubscriptionLineItemMap')
|
||||||
|
|
|
@ -33,6 +33,7 @@ export async function upsertConsumer(
|
||||||
|
|
||||||
if (!consumerId) {
|
if (!consumerId) {
|
||||||
assert(projectId, 400, 'Missing required "deploymentId"')
|
assert(projectId, 400, 'Missing required "deploymentId"')
|
||||||
|
assert(plan, 400, 'Missing required "plan"')
|
||||||
}
|
}
|
||||||
|
|
||||||
const [{ user, stripeCustomer }, existingConsumer] = await Promise.all([
|
const [{ user, stripeCustomer }, existingConsumer] = await Promise.all([
|
||||||
|
@ -113,8 +114,8 @@ export async function upsertConsumer(
|
||||||
;[consumer] = await db.insert(schema.consumers).values({
|
;[consumer] = await db.insert(schema.consumers).values({
|
||||||
plan,
|
plan,
|
||||||
userId,
|
userId,
|
||||||
deploymentId,
|
|
||||||
projectId,
|
projectId,
|
||||||
|
deploymentId,
|
||||||
// TODO: refactor / improve token generation
|
// TODO: refactor / improve token generation
|
||||||
token: sha256().slice(0, 24),
|
token: sha256().slice(0, 24),
|
||||||
_stripeCustomerId: stripeCustomer.id
|
_stripeCustomerId: stripeCustomer.id
|
||||||
|
|
|
@ -53,17 +53,17 @@ export async function upsertStripeSubscription(
|
||||||
? deployment.pricingPlans.find((pricingPlan) => pricingPlan.slug === plan)
|
? deployment.pricingPlans.find((pricingPlan) => pricingPlan.slug === plan)
|
||||||
: undefined
|
: undefined
|
||||||
|
|
||||||
const action: 'create' | 'update' | 'cancel' = consumer.stripeSubscriptionId
|
const action: 'create' | 'update' | 'cancel' = consumer._stripeSubscriptionId
|
||||||
? plan
|
? plan
|
||||||
? 'update'
|
? 'update'
|
||||||
: 'cancel'
|
: 'cancel'
|
||||||
: 'create'
|
: 'create'
|
||||||
let subscription: Stripe.Subscription | undefined
|
let subscription: Stripe.Subscription | undefined
|
||||||
|
|
||||||
if (consumer.stripeSubscriptionId) {
|
if (consumer._stripeSubscriptionId) {
|
||||||
// customer has an existing subscription
|
// customer has an existing subscription
|
||||||
const existing = await stripe.subscriptions.retrieve(
|
const existing = await stripe.subscriptions.retrieve(
|
||||||
consumer.stripeSubscriptionId,
|
consumer._stripeSubscriptionId,
|
||||||
...stripeConnectParams
|
...stripeConnectParams
|
||||||
)
|
)
|
||||||
const existingItems = existing.items.data
|
const existingItems = existing.items.data
|
||||||
|
@ -155,7 +155,7 @@ export async function upsertStripeSubscription(
|
||||||
assert(
|
assert(
|
||||||
items.length || !plan,
|
items.length || !plan,
|
||||||
500,
|
500,
|
||||||
`Error updating stripe subscription "${consumer.stripeSubscriptionId}"`
|
`Error updating stripe subscription "${consumer._stripeSubscriptionId}"`
|
||||||
)
|
)
|
||||||
|
|
||||||
for (const item of items) {
|
for (const item of items) {
|
||||||
|
@ -182,7 +182,7 @@ export async function upsertStripeSubscription(
|
||||||
}
|
}
|
||||||
|
|
||||||
subscription = await stripe.subscriptions.update(
|
subscription = await stripe.subscriptions.update(
|
||||||
consumer.stripeSubscriptionId,
|
consumer._stripeSubscriptionId,
|
||||||
update,
|
update,
|
||||||
...stripeConnectParams
|
...stripeConnectParams
|
||||||
)
|
)
|
||||||
|
@ -246,7 +246,7 @@ export async function upsertStripeSubscription(
|
||||||
...stripeConnectParams
|
...stripeConnectParams
|
||||||
)
|
)
|
||||||
|
|
||||||
consumer.stripeSubscriptionId = subscription.id
|
consumer._stripeSubscriptionId = subscription.id
|
||||||
}
|
}
|
||||||
|
|
||||||
assert(subscription, 500, 'Missing stripe subscription')
|
assert(subscription, 500, 'Missing stripe subscription')
|
||||||
|
@ -258,7 +258,7 @@ export async function upsertStripeSubscription(
|
||||||
consumerUpdate.stripeStatus = subscription.status
|
consumerUpdate.stripeStatus = subscription.status
|
||||||
} else {
|
} else {
|
||||||
// TODO
|
// TODO
|
||||||
consumerUpdate.stripeSubscriptionId = null
|
consumerUpdate._stripeSubscriptionId = null
|
||||||
consumerUpdate.stripeStatus = 'cancelled'
|
consumerUpdate.stripeStatus = 'cancelled'
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Ładowanie…
Reference in New Issue