summaryrefslogtreecommitdiffhomepage
path: root/packages/console
diff options
context:
space:
mode:
authorFrank <[email protected]>2026-01-25 17:46:14 -0500
committerFrank <[email protected]>2026-01-25 17:46:18 -0500
commit57532326f7b3526348b14e82bb61ecd41ac7d480 (patch)
tree94c06cca929cd6009d7d66d8189b9bb0b2dcc045 /packages/console
parent045c30acf34b48cfc6f12b77b61995560fbddead (diff)
downloadopencode-57532326f7b3526348b14e82bb61ecd41ac7d480.tar.gz
opencode-57532326f7b3526348b14e82bb61ecd41ac7d480.zip
zen: handle subscription payment failure
Diffstat (limited to 'packages/console')
-rw-r--r--packages/console/app/src/routes/stripe/webhook.ts24
-rw-r--r--packages/console/core/src/billing.ts25
2 files changed, 32 insertions, 17 deletions
diff --git a/packages/console/app/src/routes/stripe/webhook.ts b/packages/console/app/src/routes/stripe/webhook.ts
index c987158d3..828eb4c71 100644
--- a/packages/console/app/src/routes/stripe/webhook.ts
+++ b/packages/console/app/src/routes/stripe/webhook.ts
@@ -396,27 +396,17 @@ export async function POST(input: APIEvent) {
}
*/
}
- if (body.type === "customer.subscription.deleted") {
+ if (body.type === "customer.subscription.updated" && body.data.object.status === "incomplete_expired") {
const subscriptionID = body.data.object.id
if (!subscriptionID) throw new Error("Subscription ID not found")
- const workspaceID = await Database.use((tx) =>
- tx
- .select({ workspaceID: BillingTable.workspaceID })
- .from(BillingTable)
- .where(eq(BillingTable.subscriptionID, subscriptionID))
- .then((rows) => rows[0]?.workspaceID),
- )
- if (!workspaceID) throw new Error("Workspace ID not found for subscription")
-
- await Database.transaction(async (tx) => {
- await tx
- .update(BillingTable)
- .set({ subscriptionID: null, subscription: null })
- .where(eq(BillingTable.workspaceID, workspaceID))
+ await Billing.unsubscribe({ subscriptionID })
+ }
+ if (body.type === "customer.subscription.deleted") {
+ const subscriptionID = body.data.object.id
+ if (!subscriptionID) throw new Error("Subscription ID not found")
- await tx.delete(SubscriptionTable).where(eq(SubscriptionTable.workspaceID, workspaceID))
- })
+ await Billing.unsubscribe({ subscriptionID })
}
if (body.type === "invoice.payment_succeeded") {
if (
diff --git a/packages/console/core/src/billing.ts b/packages/console/core/src/billing.ts
index 44f12db9e..2c1cdb068 100644
--- a/packages/console/core/src/billing.ts
+++ b/packages/console/core/src/billing.ts
@@ -335,4 +335,29 @@ export namespace Billing {
return subscription.id
},
)
+
+ export const unsubscribe = fn(
+ z.object({
+ subscriptionID: z.string(),
+ }),
+ async ({ subscriptionID }) => {
+ const workspaceID = await Database.use((tx) =>
+ tx
+ .select({ workspaceID: BillingTable.workspaceID })
+ .from(BillingTable)
+ .where(eq(BillingTable.subscriptionID, subscriptionID))
+ .then((rows) => rows[0]?.workspaceID),
+ )
+ if (!workspaceID) throw new Error("Workspace ID not found for subscription")
+
+ await Database.transaction(async (tx) => {
+ await tx
+ .update(BillingTable)
+ .set({ subscriptionID: null, subscription: null })
+ .where(eq(BillingTable.workspaceID, workspaceID))
+
+ await tx.delete(SubscriptionTable).where(eq(SubscriptionTable.workspaceID, workspaceID))
+ })
+ },
+ )
}