mirror of
https://fastgit.cc/https://github.com/anomalyco/opencode
synced 2026-04-20 12:51:13 +08:00
zen: redeem go
This commit is contained in:
@@ -236,7 +236,6 @@ new sst.cloudflare.x.SolidStart("Console", {
|
||||
SALESFORCE_INSTANCE_URL,
|
||||
ZEN_BLACK_PRICE,
|
||||
ZEN_LITE_PRICE,
|
||||
new sst.Secret("ZEN_LITE_COUPON_FIRST_MONTH_100_INVITEES"),
|
||||
new sst.Secret("ZEN_LIMITS"),
|
||||
new sst.Secret("ZEN_SESSION_SECRET"),
|
||||
...ZEN_MODELS,
|
||||
|
||||
@@ -9,6 +9,7 @@ import { Actor } from "@opencode-ai/console-core/actor.js"
|
||||
import { Resource } from "@opencode-ai/console-resource"
|
||||
import { LiteData } from "@opencode-ai/console-core/lite.js"
|
||||
import { BlackData } from "@opencode-ai/console-core/black.js"
|
||||
import { User } from "@opencode-ai/console-core/user.js"
|
||||
|
||||
export async function POST(input: APIEvent) {
|
||||
const body = await Billing.stripe().webhooks.constructEventAsync(
|
||||
@@ -109,6 +110,8 @@ export async function POST(input: APIEvent) {
|
||||
if (type === "lite") {
|
||||
const workspaceID = body.data.object.metadata?.workspaceID
|
||||
const userID = body.data.object.metadata?.userID
|
||||
const userEmail = body.data.object.metadata?.userEmail
|
||||
const coupon = body.data.object.metadata?.coupon
|
||||
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
|
||||
@@ -156,6 +159,10 @@ export async function POST(input: APIEvent) {
|
||||
id: Identifier.create("lite"),
|
||||
userID: userID,
|
||||
})
|
||||
|
||||
if (userEmail && coupon === LiteData.firstMonth100Coupon) {
|
||||
await Billing.redeemCoupon(userEmail, "GOFREEMONTH")
|
||||
}
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
@@ -25,9 +25,9 @@ export default function () {
|
||||
<Show when={billingInfo()?.customerID}>
|
||||
<ReloadSection />
|
||||
<MonthlyLimitSection />
|
||||
<RedeemSection />
|
||||
<PaymentSection />
|
||||
</Show>
|
||||
<RedeemSection />
|
||||
</Show>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { Stripe } from "stripe"
|
||||
import { and, Database, eq, sql } from "./drizzle"
|
||||
import { and, Database, eq, isNull, sql } from "./drizzle"
|
||||
import {
|
||||
BillingTable,
|
||||
CouponTable,
|
||||
@@ -176,6 +176,16 @@ export namespace Billing {
|
||||
)
|
||||
}
|
||||
|
||||
export const hasCoupon = async (email: string, type: (typeof CouponType)[number]) => {
|
||||
return await Database.use((tx) =>
|
||||
tx
|
||||
.select()
|
||||
.from(CouponTable)
|
||||
.where(and(eq(CouponTable.email, email), eq(CouponTable.type, type), isNull(CouponTable.timeRedeemed)))
|
||||
.then((rows) => rows.length > 0),
|
||||
)
|
||||
}
|
||||
|
||||
export const setMonthlyLimit = fn(z.number(), async (input) => {
|
||||
return await Database.use((tx) =>
|
||||
tx
|
||||
@@ -274,16 +284,19 @@ export namespace Billing {
|
||||
const user = Actor.assert("user")
|
||||
const { successUrl, cancelUrl, method } = input
|
||||
|
||||
const email = await User.getAuthEmail(user.properties.userID)
|
||||
const email = (await User.getAuthEmail(user.properties.userID))!
|
||||
const billing = await Billing.get()
|
||||
|
||||
if (billing.subscriptionID) throw new Error("Already subscribed to Black")
|
||||
if (billing.liteSubscriptionID) throw new Error("Already subscribed to Lite")
|
||||
|
||||
const coupon = (await Billing.hasCoupon(email, "GOFREEMONTH"))
|
||||
? LiteData.firstMonth100Coupon
|
||||
: LiteData.firstMonth50Coupon
|
||||
const createSession = () =>
|
||||
Billing.stripe().checkout.sessions.create({
|
||||
mode: "subscription",
|
||||
discounts: [{ coupon: LiteData.firstMonthCoupon(email!) }],
|
||||
discounts: [{ coupon }],
|
||||
...(billing.customerID
|
||||
? {
|
||||
customer: billing.customerID,
|
||||
@@ -293,7 +306,7 @@ export namespace Billing {
|
||||
},
|
||||
}
|
||||
: {
|
||||
customer_email: email!,
|
||||
customer_email: email,
|
||||
}),
|
||||
...(() => {
|
||||
if (method === "alipay") {
|
||||
@@ -341,6 +354,8 @@ export namespace Billing {
|
||||
metadata: {
|
||||
workspaceID: Actor.workspace(),
|
||||
userID: user.properties.userID,
|
||||
userEmail: email,
|
||||
coupon,
|
||||
type: "lite",
|
||||
},
|
||||
},
|
||||
|
||||
@@ -11,11 +11,7 @@ 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 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 firstMonth100Coupon = Resource.ZEN_LITE_PRICE.firstMonth100Coupon
|
||||
export const firstMonth50Coupon = Resource.ZEN_LITE_PRICE.firstMonth50Coupon
|
||||
export const planName = fn(z.void(), () => "lite")
|
||||
}
|
||||
|
||||
4
packages/console/core/sst-env.d.ts
vendored
4
packages/console/core/sst-env.d.ts
vendored
@@ -142,10 +142,6 @@ 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
|
||||
|
||||
4
packages/console/function/sst-env.d.ts
vendored
4
packages/console/function/sst-env.d.ts
vendored
@@ -142,10 +142,6 @@ 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
|
||||
|
||||
4
packages/console/resource/sst-env.d.ts
vendored
4
packages/console/resource/sst-env.d.ts
vendored
@@ -142,10 +142,6 @@ 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
|
||||
|
||||
4
packages/enterprise/sst-env.d.ts
vendored
4
packages/enterprise/sst-env.d.ts
vendored
@@ -142,10 +142,6 @@ 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
|
||||
|
||||
4
packages/function/sst-env.d.ts
vendored
4
packages/function/sst-env.d.ts
vendored
@@ -142,10 +142,6 @@ 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
|
||||
|
||||
4
sst-env.d.ts
vendored
4
sst-env.d.ts
vendored
@@ -168,10 +168,6 @@ 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
|
||||
|
||||
Reference in New Issue
Block a user