Files
property-management-network/scripts/stripe-setup.mjs
T
Leon SerfatyandClaude Opus 4.8 c9968531e4 Consolidate audit-fixes branch: webhooks, integrations, and deploy hardening
Batch commit of the pending working tree on security/audit-fixes-2026-07.
Major areas:
- Outbound webhooks / Zapier: schema + signed delivery with retries, public
  v1 API (REST-hook subscribe/unsubscribe), settings UI, cron drain.
- Deploy hardening: email via SMTP2GO (Resend fully removed), verified DB TLS
  (DATABASE_SSL=require + DATABASE_CA), storage fails loud in production when
  Spaces is unconfigured instead of silently using ephemeral disk.
- Integrations & features (concurrent work): accounting (QuickBooks/Xero),
  e-signature (DocuSign/Dropbox Sign), PayPal, geocoding/maps, onboarding,
  expanded legal pages.
- DB migrations 0006–0009.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-02 13:42:34 -04:00

67 lines
2.9 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
// OPTIONAL pre-provisioning: creates the products + prices with stable lookup
// keys. You don't strictly need to run this — the app auto-creates any missing
// price on first checkout (see lib/stripe/prices.ts) — but running it once in
// live mode pre-creates the catalog so the first real checkout is instant.
//
// 1. Set STRIPE_SECRET_KEY in .env.local (sk_test_... to start, sk_live_... for prod)
// 2. node scripts/stripe-setup.mjs
//
// There are NO price-ID env vars to copy — prices are resolved by lookup key,
// so going live is just an API-key swap. Amounts mirror lib/stripe/plans.ts
// (Pro $29/mo, Landlord $59/mo, Lifetime $199 one-time; yearly = 10× monthly).
import { config } from "dotenv"
import Stripe from "stripe"
config({ path: ".env.local", quiet: true })
const key = process.env.STRIPE_SECRET_KEY
if (!key) {
console.error("[stripe-setup] Set STRIPE_SECRET_KEY in .env.local first.")
process.exit(1)
}
const stripe = new Stripe(key)
const live = key.startsWith("sk_live")
console.log(`[stripe-setup] mode: ${live ? "LIVE" : "test"}`)
const AMOUNTS = { pro: 29, landlord: 59, lifetime: 199 }
const envLines = []
async function makeProduct(name) {
const p = await stripe.products.create({ name: `Property Management Network — ${name}` })
return p.id
}
async function makePrice(product, dollars, interval /* "month" | "year" | null */, lookupKey) {
const p = await stripe.prices.create({
product,
currency: "usd",
unit_amount: Math.round(dollars * 100),
lookup_key: lookupKey,
transfer_lookup_key: true,
...(interval ? { recurring: { interval } } : {}),
})
return p.id
}
// Pro (monthly + yearly)
const proProduct = await makeProduct("Pro")
envLines.push(`pmn_pro_monthly → ${await makePrice(proProduct, AMOUNTS.pro, "month", "pmn_pro_monthly")}`)
envLines.push(`pmn_pro_yearly → ${await makePrice(proProduct, AMOUNTS.pro * 10, "year", "pmn_pro_yearly")}`)
console.log(` Pro product: ${proProduct}`)
// Landlord (monthly + yearly)
const landlordProduct = await makeProduct("Landlord")
envLines.push(`pmn_landlord_monthly → ${await makePrice(landlordProduct, AMOUNTS.landlord, "month", "pmn_landlord_monthly")}`)
envLines.push(`pmn_landlord_yearly → ${await makePrice(landlordProduct, AMOUNTS.landlord * 10, "year", "pmn_landlord_yearly")}`)
console.log(` Landlord product: ${landlordProduct}`)
// Lifetime (one-time)
const lifetimeProduct = await makeProduct("Lifetime")
envLines.push(`pmn_lifetime → ${await makePrice(lifetimeProduct, AMOUNTS.lifetime, null, "pmn_lifetime")}`)
console.log(` Lifetime product: ${lifetimeProduct}`)
console.log("\n[stripe-setup] Created prices with lookup keys (below). NO env vars")
console.log("needed — the app resolves prices by lookup key, so going live is just")
console.log("a key swap. Running this in live mode pre-creates the same keys there.\n")
console.log(envLines.join("\n"))