Remove dead Stripe integration
Stripe was wired up but never used: - No STRIPE_SECRET_KEY in .env - Card payment step had a 'simulated fallback' that pretended to charge - Stripe fees (1.4% + 20p) contradict '100% goes to charity' brand promise - Bank transfer is the primary rail, GoCardless (DD) is the secondary Removed: - src/lib/stripe.ts (Stripe client, checkout sessions, webhooks) - src/app/api/stripe/checkout/route.ts - src/app/api/stripe/webhook/route.ts - src/app/p/[token]/steps/card-payment-step.tsx (263 lines) - 'stripe' and '@stripe/stripe-js' npm packages - Card option from PaymentStep (payment-step.tsx) - Card references from confirmation-step.tsx, success/page.tsx - Stripe from landing page integrations grid - Stripe from privacy policy sub-processors - Stripe from terms of service payment references Type Rail changed: 'bank' | 'gocardless' | 'card' → 'bank' | 'gocardless' Pledge flow bundle: 19.5kB → 18.2kB (-1.3kB) Payment options donors now see: 1. Bank Transfer (recommended, zero fees) 2. Direct Debit via GoCardless (1% + 20p, hassle-free)
This commit is contained in:
@@ -1,127 +0,0 @@
|
||||
import Stripe from "stripe"
|
||||
|
||||
let stripeClient: Stripe | null = null
|
||||
|
||||
export function getStripe(): Stripe | null {
|
||||
if (stripeClient) return stripeClient
|
||||
|
||||
const key = process.env.STRIPE_SECRET_KEY
|
||||
if (!key || key === "sk_test_REPLACE_ME") return null
|
||||
|
||||
stripeClient = new Stripe(key, {
|
||||
apiVersion: "2025-01-27.acacia" as Stripe.LatestApiVersion,
|
||||
typescript: true,
|
||||
})
|
||||
return stripeClient
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a Stripe Checkout Session for a card payment.
|
||||
* Returns the checkout URL to redirect the donor to.
|
||||
*/
|
||||
export async function createCheckoutSession(opts: {
|
||||
amountPence: number
|
||||
currency: string
|
||||
pledgeId: string
|
||||
reference: string
|
||||
eventName: string
|
||||
organizationName: string
|
||||
donorEmail?: string
|
||||
successUrl: string
|
||||
cancelUrl: string
|
||||
}): Promise<{ sessionId: string; checkoutUrl: string } | null> {
|
||||
const stripe = getStripe()
|
||||
if (!stripe) return null
|
||||
|
||||
try {
|
||||
const session = await stripe.checkout.sessions.create({
|
||||
mode: "payment",
|
||||
payment_method_types: ["card"],
|
||||
line_items: [
|
||||
{
|
||||
price_data: {
|
||||
currency: opts.currency.toLowerCase(),
|
||||
unit_amount: opts.amountPence,
|
||||
product_data: {
|
||||
name: `Donation — ${opts.eventName}`,
|
||||
description: `Pledge ref: ${opts.reference} to ${opts.organizationName}`,
|
||||
},
|
||||
},
|
||||
quantity: 1,
|
||||
},
|
||||
],
|
||||
customer_email: opts.donorEmail || undefined,
|
||||
metadata: {
|
||||
pledge_id: opts.pledgeId,
|
||||
reference: opts.reference,
|
||||
},
|
||||
success_url: opts.successUrl,
|
||||
cancel_url: opts.cancelUrl,
|
||||
})
|
||||
|
||||
return {
|
||||
sessionId: session.id,
|
||||
checkoutUrl: session.url!,
|
||||
}
|
||||
} catch (error) {
|
||||
console.error("Stripe checkout session error:", error)
|
||||
return null
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a Stripe Payment Intent for embedded payment (Stripe Elements).
|
||||
* Returns client secret for frontend confirmation.
|
||||
*/
|
||||
export async function createPaymentIntent(opts: {
|
||||
amountPence: number
|
||||
currency: string
|
||||
pledgeId: string
|
||||
reference: string
|
||||
donorEmail?: string
|
||||
}): Promise<{ clientSecret: string; paymentIntentId: string } | null> {
|
||||
const stripe = getStripe()
|
||||
if (!stripe) return null
|
||||
|
||||
try {
|
||||
const pi = await stripe.paymentIntents.create({
|
||||
amount: opts.amountPence,
|
||||
currency: opts.currency.toLowerCase(),
|
||||
metadata: {
|
||||
pledge_id: opts.pledgeId,
|
||||
reference: opts.reference,
|
||||
},
|
||||
receipt_email: opts.donorEmail || undefined,
|
||||
automatic_payment_methods: {
|
||||
enabled: true,
|
||||
},
|
||||
})
|
||||
|
||||
return {
|
||||
clientSecret: pi.client_secret!,
|
||||
paymentIntentId: pi.id,
|
||||
}
|
||||
} catch (error) {
|
||||
console.error("Stripe payment intent error:", error)
|
||||
return null
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Verify a Stripe webhook signature.
|
||||
*/
|
||||
export function constructWebhookEvent(
|
||||
body: string | Buffer,
|
||||
signature: string
|
||||
): Stripe.Event | null {
|
||||
const stripe = getStripe()
|
||||
const secret = process.env.STRIPE_WEBHOOK_SECRET
|
||||
if (!stripe || !secret || secret === "whsec_REPLACE_ME") return null
|
||||
|
||||
try {
|
||||
return stripe.webhooks.constructEvent(body, signature, secret)
|
||||
} catch (error) {
|
||||
console.error("Stripe webhook signature verification failed:", error)
|
||||
return null
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user