diff options
| author | Frank <[email protected]> | 2026-01-24 08:33:47 -0500 |
|---|---|---|
| committer | Frank <[email protected]> | 2026-01-24 11:48:19 -0500 |
| commit | d8bbb6df60dafd5f872ff418c2826ff8382c3749 (patch) | |
| tree | b9857a66c263ff442e8d62b05ebe7b6b58e9dbeb /packages/console/app/src | |
| parent | 7c2e59de684104d3b436c4d4fbb2dd2426dcbd16 (diff) | |
| download | opencode-d8bbb6df60dafd5f872ff418c2826ff8382c3749.tar.gz opencode-d8bbb6df60dafd5f872ff418c2826ff8382c3749.zip | |
zen: disable reload when reload fails
Diffstat (limited to 'packages/console/app/src')
| -rw-r--r-- | packages/console/app/src/routes/stripe/webhook.ts | 70 |
1 files changed, 66 insertions, 4 deletions
diff --git a/packages/console/app/src/routes/stripe/webhook.ts b/packages/console/app/src/routes/stripe/webhook.ts index 34f83b446..9e310dc07 100644 --- a/packages/console/app/src/routes/stripe/webhook.ts +++ b/packages/console/app/src/routes/stripe/webhook.ts @@ -141,8 +141,6 @@ export async function POST(input: APIEvent) { return couponID })() - // get user - await Actor.provide("system", { workspaceID }, async () => { // look up current billing const billing = await Billing.get() @@ -422,8 +420,8 @@ export async function POST(input: APIEvent) { } if (body.type === "invoice.payment_succeeded") { if ( - body.data.object.billing_reason === "subscription_cycle" || - body.data.object.billing_reason === "subscription_create" + body.data.object.billing_reason === "subscription_create" || + body.data.object.billing_reason === "subscription_cycle" ) { const invoiceID = body.data.object.id as string const amountInCents = body.data.object.amount_paid @@ -476,6 +474,70 @@ export async function POST(input: APIEvent) { }, }), ) + } else if (body.data.object.billing_reason === "manual") { + const workspaceID = body.data.object.metadata?.workspaceID + const amountInCents = body.data.object.metadata?.amount && parseInt(body.data.object.metadata?.amount) + const invoiceID = body.data.object.id as string + const customerID = body.data.object.customer as string + + if (!workspaceID) throw new Error("Workspace ID not found") + if (!customerID) throw new Error("Customer ID not found") + if (!amountInCents) throw new Error("Amount not found") + if (!invoiceID) throw new Error("Invoice ID not found") + + await Actor.provide("system", { workspaceID }, async () => { + // get payment id from invoice + const invoice = await Billing.stripe().invoices.retrieve(invoiceID, { + expand: ["payments"], + }) + await Database.transaction(async (tx) => { + await tx + .update(BillingTable) + .set({ + balance: sql`${BillingTable.balance} + ${centsToMicroCents(amountInCents)}`, + reloadError: null, + timeReloadError: null, + }) + .where(eq(BillingTable.workspaceID, Actor.workspace())) + await tx.insert(PaymentTable).values({ + workspaceID: Actor.workspace(), + id: Identifier.create("payment"), + amount: centsToMicroCents(amountInCents), + invoiceID, + paymentID: invoice.payments?.data[0].payment.payment_intent as string, + customerID, + }) + }) + }) + } + } + if (body.type === "invoice.payment_failed" || body.type === "invoice.payment_action_required") { + if (body.data.object.billing_reason === "manual") { + const workspaceID = body.data.object.metadata?.workspaceID + const invoiceID = body.data.object.id + + if (!workspaceID) throw new Error("Workspace ID not found") + if (!invoiceID) throw new Error("Invoice ID not found") + + const paymentIntent = await Billing.stripe().paymentIntents.retrieve(invoiceID); + console.log(JSON.stringify(paymentIntent)) + const errorMessage = + typeof paymentIntent === "object" && paymentIntent !== null + ? paymentIntent.last_payment_error?.message + : undefined + + await Actor.provide("system", { workspaceID }, async () => { + await Database.use((tx) => + tx + .update(BillingTable) + .set({ + reload: false, + reloadError: errorMessage ?? "Payment failed.", + timeReloadError: sql`now()`, + }) + .where(eq(BillingTable.workspaceID, Actor.workspace())), + ) + }) } } if (body.type === "charge.refunded") { |
