← back to Lawyer Directory Builder

src/scripts/setup_stripe_webhook.ts

53 lines

/**
 * One-shot setup: create (or refresh) the Stripe webhook endpoint for
 * lawyers.agentabrams.com and print the signing secret. Caller saves the
 * secret via the secrets-manager CLI.
 *
 * Idempotent: if a webhook for the same URL already exists, we delete it
 * first so the new endpoint comes back with a fresh signing secret.
 *
 *   npx tsx src/scripts/setup_stripe_webhook.ts
 */
import 'dotenv/config';
import Stripe from 'stripe';

const URL = 'https://lawyers.agentabrams.com/webhooks/stripe';
const EVENTS: Stripe.WebhookEndpointCreateParams.EnabledEvent[] = [
  'checkout.session.completed',
  'checkout.session.expired',
  'charge.refunded',
  'payment_intent.payment_failed',
];

const SK = process.env.STRIPE_SECRET_KEY;
if (!SK || !SK.startsWith('sk_')) {
  console.error('STRIPE_SECRET_KEY missing or invalid in .env');
  process.exit(2);
}
const stripe = new Stripe(SK);

(async () => {
  // Find any existing endpoint at this URL — delete to force fresh secret
  const existing = await stripe.webhookEndpoints.list({ limit: 100 });
  for (const e of existing.data) {
    if (e.url === URL) {
      console.log(`found existing webhook ${e.id} — deleting to refresh signing secret`);
      await stripe.webhookEndpoints.del(e.id);
    }
  }

  const created = await stripe.webhookEndpoints.create({
    url: URL,
    enabled_events: EVENTS,
    description: 'Counsel & Bar — lawyers.agentabrams.com production',
  });

  console.log('\n=== webhook endpoint created ===');
  console.log('id:           ', created.id);
  console.log('url:          ', created.url);
  console.log('events:       ', created.enabled_events.length);
  console.log('signing secret:', created.secret);
  console.log('\nNext step (run from your shell):');
  console.log(`  node ~/Projects/secrets-manager/cli.js add STRIPE_WEBHOOK_SECRET '${created.secret}'\n`);
})().catch(e => { console.error('setup failed:', e); process.exit(1); });