Payments
Normalize events from Stripe/Clover into one model, then persist and sync revenue downstream (e.g. native GL or reporting tables).
Unify Stripe + Clover events behind one normalized payment model
Treat providers as input sources. Normalize to one shape, then sync to your accounting/reporting layer without rewriting provider-specific code.
import { normalizePaymentWebhook } from '@/server/payments'const normalized = normalizePaymentWebhook({provider: 'stripe',headers: {'stripe-signature': '...',},body: stripeEvent,})if (normalized) {// persist to DB, enqueue revenue sync, etc.console.log(normalized.provider, normalized.amount)}
Stripe webhook → NormalizedPayment
Start with `payment_intent.*` (succeeded/canceled/processing). Use metadata to attach your internal reference id.
// Stripe adapter lives at: src/server/payments/providers/stripe.ts// Normalize event.data.object (payment_intent) into one shape.
Next step: add signature verification + support Charge/Refund events if you need them.
Clover POS webhook → NormalizedPayment (payment id notification)
Clover POS webhooks send object-id updates (e.g. `P:<paymentId>`), not the full payment payload. Normalize the notification first, then fetch/enrich via Clover Payments API if you need amount/status/customer.
// Clover POS webhook adapter lives at: src/server/payments/providers/clover.ts// It recognizes update objects like { objectId: 'P:<paymentId>', ts: <unix ms> }.// Next step is enrichment by fetching the Payment record from Clover.