summaryrefslogtreecommitdiffhomepage
path: root/packages
diff options
context:
space:
mode:
authorFrank <[email protected]>2026-04-07 10:08:57 -0400
committerFrank <[email protected]>2026-04-07 10:09:00 -0400
commit01c5eb679cd0b00cba654b316ef8615d0262c500 (patch)
treed2617bfd783804525a1b747beccde5999c2864d4 /packages
parent41612b3dbea7b4e30a5a83678d2526dbeae9b61a (diff)
downloadopencode-01c5eb679cd0b00cba654b316ef8615d0262c500.tar.gz
opencode-01c5eb679cd0b00cba654b316ef8615d0262c500.zip
go: support coupon
Diffstat (limited to 'packages')
-rw-r--r--packages/console/app/src/routes/stripe/webhook.ts33
-rw-r--r--packages/console/core/src/billing.ts2
-rw-r--r--packages/console/core/src/lite.ts7
-rw-r--r--packages/console/core/sst-env.d.ts5
-rw-r--r--packages/console/function/sst-env.d.ts5
-rw-r--r--packages/console/resource/sst-env.d.ts5
-rw-r--r--packages/enterprise/sst-env.d.ts5
-rw-r--r--packages/function/sst-env.d.ts5
8 files changed, 40 insertions, 27 deletions
diff --git a/packages/console/app/src/routes/stripe/webhook.ts b/packages/console/app/src/routes/stripe/webhook.ts
index 47fee05cf..0d8cf61cf 100644
--- a/packages/console/app/src/routes/stripe/webhook.ts
+++ b/packages/console/app/src/routes/stripe/webhook.ts
@@ -1,3 +1,4 @@
+import type { Stripe } from "stripe"
import { Billing } from "@opencode-ai/console-core/billing.js"
import type { APIEvent } from "@solidjs/start/server"
import { and, Database, eq, sql } from "@opencode-ai/console-core/drizzle/index.js"
@@ -111,27 +112,17 @@ export async function POST(input: APIEvent) {
const customerID = body.data.object.customer as string
const invoiceID = body.data.object.latest_invoice as string
const subscriptionID = body.data.object.id as string
+ const paymentMethodID = body.data.object.default_payment_method as string
if (!workspaceID) throw new Error("Workspace ID not found")
if (!userID) throw new Error("User ID not found")
if (!customerID) throw new Error("Customer ID not found")
if (!invoiceID) throw new Error("Invoice ID not found")
if (!subscriptionID) throw new Error("Subscription ID not found")
-
- // get payment id from invoice
- const invoice = await Billing.stripe().invoices.retrieve(invoiceID, {
- expand: ["payments"],
- })
- const paymentID = invoice.payments?.data[0].payment.payment_intent as string
- if (!paymentID) throw new Error("Payment ID not found")
+ if (!paymentMethodID) throw new Error("Payment method ID not found")
// get payment method for the payment intent
- const paymentIntent = await Billing.stripe().paymentIntents.retrieve(paymentID, {
- expand: ["payment_method"],
- })
- const paymentMethod = paymentIntent.payment_method
- if (!paymentMethod || typeof paymentMethod === "string") throw new Error("Payment method not expanded")
-
+ const paymentMethod = await Billing.stripe().paymentMethods.retrieve(paymentMethodID)
await Actor.provide("system", { workspaceID }, async () => {
// look up current billing
const billing = await Billing.get()
@@ -200,26 +191,18 @@ export async function POST(input: APIEvent) {
const amountInCents = body.data.object.amount_paid
const customerID = body.data.object.customer as string
const subscriptionID = body.data.object.parent?.subscription_details?.subscription as string
+ const productID = body.data.object.lines?.data[0].pricing?.price_details?.product as string
if (!customerID) throw new Error("Customer ID not found")
if (!invoiceID) throw new Error("Invoice ID not found")
if (!subscriptionID) throw new Error("Subscription ID not found")
// get coupon id from subscription
- const subscriptionData = await Billing.stripe().subscriptions.retrieve(subscriptionID, {
- expand: ["discounts"],
- })
- const couponID =
- typeof subscriptionData.discounts[0] === "string"
- ? subscriptionData.discounts[0]
- : subscriptionData.discounts[0]?.coupon?.id
- const productID = subscriptionData.items.data[0].price.product as string
-
- // get payment id from invoice
const invoice = await Billing.stripe().invoices.retrieve(invoiceID, {
- expand: ["payments"],
+ expand: ["discounts", "payments"],
})
- const paymentID = invoice.payments?.data[0].payment.payment_intent as string
+ const paymentID = invoice.payments?.data[0]?.payment.payment_intent as string
+ const couponID = (invoice.discounts[0] as Stripe.Discount).coupon?.id as string
if (!paymentID) {
// payment id can be undefined when using coupon
if (!couponID) throw new Error("Payment ID not found")
diff --git a/packages/console/core/src/billing.ts b/packages/console/core/src/billing.ts
index 66b980698..9de413e60 100644
--- a/packages/console/core/src/billing.ts
+++ b/packages/console/core/src/billing.ts
@@ -254,7 +254,7 @@ export namespace Billing {
const createSession = () =>
Billing.stripe().checkout.sessions.create({
mode: "subscription",
- discounts: [{ coupon: LiteData.firstMonth50Coupon() }],
+ discounts: [{ coupon: LiteData.firstMonthCoupon(email!) }],
...(billing.customerID
? {
customer: billing.customerID,
diff --git a/packages/console/core/src/lite.ts b/packages/console/core/src/lite.ts
index 2c4a09f71..3343192c1 100644
--- a/packages/console/core/src/lite.ts
+++ b/packages/console/core/src/lite.ts
@@ -11,6 +11,11 @@ export namespace LiteData {
export const productID = fn(z.void(), () => Resource.ZEN_LITE_PRICE.product)
export const priceID = fn(z.void(), () => Resource.ZEN_LITE_PRICE.price)
export const priceInr = fn(z.void(), () => Resource.ZEN_LITE_PRICE.priceInr)
- export const firstMonth50Coupon = fn(z.void(), () => Resource.ZEN_LITE_PRICE.firstMonth50Coupon)
+ export const firstMonthCoupon = fn(z.string(), (email) => {
+ const invitees = Resource.ZEN_LITE_COUPON_FIRST_MONTH_100_INVITEES.value.split(",")
+ return invitees.includes(email)
+ ? Resource.ZEN_LITE_PRICE.firstMonth100Coupon
+ : Resource.ZEN_LITE_PRICE.firstMonth50Coupon
+ })
export const planName = fn(z.void(), () => "lite")
}
diff --git a/packages/console/core/sst-env.d.ts b/packages/console/core/sst-env.d.ts
index 6b842639a..b77ee3c5b 100644
--- a/packages/console/core/sst-env.d.ts
+++ b/packages/console/core/sst-env.d.ts
@@ -142,7 +142,12 @@ declare module "sst" {
"type": "sst.sst.Secret"
"value": string
}
+ "ZEN_LITE_COUPON_FIRST_MONTH_100_INVITEES": {
+ "type": "sst.sst.Secret"
+ "value": string
+ }
"ZEN_LITE_PRICE": {
+ "firstMonth100Coupon": string
"firstMonth50Coupon": string
"price": string
"priceInr": number
diff --git a/packages/console/function/sst-env.d.ts b/packages/console/function/sst-env.d.ts
index 6b842639a..b77ee3c5b 100644
--- a/packages/console/function/sst-env.d.ts
+++ b/packages/console/function/sst-env.d.ts
@@ -142,7 +142,12 @@ declare module "sst" {
"type": "sst.sst.Secret"
"value": string
}
+ "ZEN_LITE_COUPON_FIRST_MONTH_100_INVITEES": {
+ "type": "sst.sst.Secret"
+ "value": string
+ }
"ZEN_LITE_PRICE": {
+ "firstMonth100Coupon": string
"firstMonth50Coupon": string
"price": string
"priceInr": number
diff --git a/packages/console/resource/sst-env.d.ts b/packages/console/resource/sst-env.d.ts
index 6b842639a..b77ee3c5b 100644
--- a/packages/console/resource/sst-env.d.ts
+++ b/packages/console/resource/sst-env.d.ts
@@ -142,7 +142,12 @@ declare module "sst" {
"type": "sst.sst.Secret"
"value": string
}
+ "ZEN_LITE_COUPON_FIRST_MONTH_100_INVITEES": {
+ "type": "sst.sst.Secret"
+ "value": string
+ }
"ZEN_LITE_PRICE": {
+ "firstMonth100Coupon": string
"firstMonth50Coupon": string
"price": string
"priceInr": number
diff --git a/packages/enterprise/sst-env.d.ts b/packages/enterprise/sst-env.d.ts
index 6b842639a..b77ee3c5b 100644
--- a/packages/enterprise/sst-env.d.ts
+++ b/packages/enterprise/sst-env.d.ts
@@ -142,7 +142,12 @@ declare module "sst" {
"type": "sst.sst.Secret"
"value": string
}
+ "ZEN_LITE_COUPON_FIRST_MONTH_100_INVITEES": {
+ "type": "sst.sst.Secret"
+ "value": string
+ }
"ZEN_LITE_PRICE": {
+ "firstMonth100Coupon": string
"firstMonth50Coupon": string
"price": string
"priceInr": number
diff --git a/packages/function/sst-env.d.ts b/packages/function/sst-env.d.ts
index 6b842639a..b77ee3c5b 100644
--- a/packages/function/sst-env.d.ts
+++ b/packages/function/sst-env.d.ts
@@ -142,7 +142,12 @@ declare module "sst" {
"type": "sst.sst.Secret"
"value": string
}
+ "ZEN_LITE_COUPON_FIRST_MONTH_100_INVITEES": {
+ "type": "sst.sst.Secret"
+ "value": string
+ }
"ZEN_LITE_PRICE": {
+ "firstMonth100Coupon": string
"firstMonth50Coupon": string
"price": string
"priceInr": number