summaryrefslogtreecommitdiffhomepage
path: root/packages/console/core/src
diff options
context:
space:
mode:
authorFrank <[email protected]>2025-09-24 19:09:23 -0400
committerFrank <[email protected]>2025-09-24 19:09:28 -0400
commitd0377a95cf407c1c6a718a52018087885af90677 (patch)
tree27d9d7dd0f082799ae311548d04976510dd37f9d /packages/console/core/src
parent3b20bf6d4f744e63faa8b798ca911a93338dc4f3 (diff)
downloadopencode-d0377a95cf407c1c6a718a52018087885af90677.tar.gz
opencode-d0377a95cf407c1c6a718a52018087885af90677.zip
zen: billing
Diffstat (limited to 'packages/console/core/src')
-rw-r--r--packages/console/core/src/billing.ts64
-rw-r--r--packages/console/core/src/schema/billing.sql.ts1
2 files changed, 45 insertions, 20 deletions
diff --git a/packages/console/core/src/billing.ts b/packages/console/core/src/billing.ts
index dda0c539f..4267d3b94 100644
--- a/packages/console/core/src/billing.ts
+++ b/packages/console/core/src/billing.ts
@@ -10,6 +10,8 @@ import { Identifier } from "./identifier"
import { centsToMicroCents } from "./util/price"
export namespace Billing {
+ export const CHARGE_NAME = "opencode credits"
+ export const CHARGE_FEE_NAME = "processing fee"
export const CHARGE_AMOUNT = 2000 // $20
export const CHARGE_FEE = 123 // Stripe fee 4.4% + $0.30
export const CHARGE_THRESHOLD = 500 // $5
@@ -73,22 +75,39 @@ export namespace Billing {
.then((rows) => rows[0]),
)
const paymentID = Identifier.create("payment")
- let charge
+ let invoice
try {
- charge = await Billing.stripe().paymentIntents.create(
- {
- amount: Billing.CHARGE_AMOUNT + Billing.CHARGE_FEE,
- currency: "usd",
- customer: customerID!,
- payment_method: paymentMethodID!,
- off_session: true,
- confirm: true,
- },
- { idempotencyKey: paymentID },
- )
-
- if (charge.status !== "succeeded") throw new Error(charge.last_payment_error?.message)
+ const draft = await Billing.stripe().invoices.create({
+ customer: customerID!,
+ auto_advance: false,
+ default_payment_method: paymentMethodID!,
+ collection_method: "charge_automatically",
+ currency: "usd",
+ })
+ await Billing.stripe().invoiceItems.create({
+ amount: Billing.CHARGE_AMOUNT,
+ currency: "usd",
+ customer: customerID!,
+ description: CHARGE_NAME,
+ invoice: draft.id!,
+ })
+ await Billing.stripe().invoiceItems.create({
+ amount: Billing.CHARGE_FEE,
+ currency: "usd",
+ customer: customerID!,
+ description: CHARGE_FEE_NAME,
+ invoice: draft.id!,
+ })
+ await Billing.stripe().invoices.finalizeInvoice(draft.id!)
+ invoice = await Billing.stripe().invoices.pay(draft.id!, {
+ off_session: true,
+ payment_method: paymentMethodID!,
+ expand: ["payments"],
+ })
+ if (invoice.status !== "paid" || invoice.payments?.data.length !== 1)
+ throw new Error(invoice.last_finalization_error?.message)
} catch (e: any) {
+ console.error(e)
await Database.use((tx) =>
tx
.update(BillingTable)
@@ -114,7 +133,8 @@ export namespace Billing {
workspaceID: Actor.workspace(),
id: paymentID,
amount: centsToMicroCents(CHARGE_AMOUNT),
- paymentID: charge.id,
+ invoiceID: invoice.id!,
+ paymentID: invoice.payments?.data[0].payment.payment_intent as string,
customerID,
})
})
@@ -155,12 +175,13 @@ export namespace Billing {
const customer = await Billing.get()
const session = await Billing.stripe().checkout.sessions.create({
mode: "payment",
+ billing_address_collection: "required",
line_items: [
{
price_data: {
currency: "usd",
product_data: {
- name: "opencode credits",
+ name: CHARGE_NAME,
},
unit_amount: CHARGE_AMOUNT,
},
@@ -170,16 +191,13 @@ export namespace Billing {
price_data: {
currency: "usd",
product_data: {
- name: "processing fee",
+ name: CHARGE_FEE_NAME,
},
unit_amount: CHARGE_FEE,
},
quantity: 1,
},
],
- payment_intent_data: {
- setup_future_usage: "on_session",
- },
...(customer.customerID
? {
customer: customer.customerID,
@@ -192,6 +210,12 @@ export namespace Billing {
workspaceID: Actor.workspace(),
},
currency: "usd",
+ invoice_creation: {
+ enabled: true,
+ },
+ payment_intent_data: {
+ setup_future_usage: "on_session",
+ },
payment_method_types: ["card"],
payment_method_data: {
allow_redisplay: "always",
diff --git a/packages/console/core/src/schema/billing.sql.ts b/packages/console/core/src/schema/billing.sql.ts
index f7da84ab7..302e01133 100644
--- a/packages/console/core/src/schema/billing.sql.ts
+++ b/packages/console/core/src/schema/billing.sql.ts
@@ -28,6 +28,7 @@ export const PaymentTable = mysqlTable(
...workspaceColumns,
...timestamps,
customerID: varchar("customer_id", { length: 255 }),
+ invoiceID: varchar("invoice_id", { length: 255 }),
paymentID: varchar("payment_id", { length: 255 }),
amount: bigint("amount", { mode: "number" }).notNull(),
timeRefunded: utc("time_refunded"),