feat(GRO-607): Stripe Elements payment UI replacing mock flow #274

Closed
the-dogfather-cto[bot] wants to merge 10 commits from feature/gro-597-payment-ui into main

10 Commits

Author SHA1 Message Date
Paperclip 2db922bb14 fix(GRO-607): Remove unused attachPaymentMethod import from portal
Co-Authored-By: Paperclip <noreply@paperclip.ing>
2026-04-13 19:17:28 +00:00
Paperclip 5aec436fb7 fix(GRO-607): Stripe Elements payment UI - lint/type fixes
- Remove unused Stripe type import
- Remove unused setPackages setter
- Fix confirmPayment return_url requirement
- Fix Stripe import in BillingPayments

Co-Authored-By: Paperclip <noreply@paperclip.ing>
2026-04-13 19:17:15 +00:00
Paperclip 0aabb866c2 GRO-607: Add /portal/config endpoint + rename date field
- Add GET /portal/config returning stripePublishableKey from env
- Rename createdAt→date in invoice response to match BillingPayments interface

Co-Authored-By: Paperclip <noreply@paperclip.ing>
2026-04-13 19:11:59 +00:00
Paperclip 37fc33877c GRO-607: Replace mock payment flow with real Stripe Elements
- Install @stripe/stripe-js and @stripe/react-stripe-js
- Replace BillingPayments mock delay with real Stripe Elements:
  - Fetch publishableKey from GET /api/portal/config
  - Lazy load Stripe via loadStripe()
  - Wrap payment modal in <Elements> with PaymentElement
  - Use stripe.confirmPayment() with clientSecret from pay/pay-multiple endpoints
  - Support multi-invoice selection and single invoice payment
- Add "Save card for future payments" checkbox (setup_future_usage)
- Add payment method management: list saved cards, delete via DELETE endpoint
- Proper error handling for payment failures
- Autopay toggle (UI-only, Phase 2 backend pending)

Co-Authored-By: Paperclip <noreply@paperclip.ing>
2026-04-13 19:11:59 +00:00
Paperclip 00619a07e0 GRO-606: Add payment API endpoints (pay invoice, payment methods, refunds)
Portal routes (client-facing):
- POST /api/portal/invoices/:id/pay - create PaymentIntent for single invoice
- POST /api/portal/invoices/pay-multiple - create PaymentIntent for multiple invoices
- GET /api/portal/payment-methods - list saved payment methods
- POST /api/portal/payment-methods - create SetupIntent for saving new card
- DELETE /api/portal/payment-methods/:id - detach payment method
- GET /api/portal/config - return Stripe publishable key

Admin routes:
- POST /api/invoices/:id/refund - manager-only refund endpoint

Validation:
- Cannot pay draft, void, or already-paid invoices
- Multi-invoice: all must belong to same client and be pending
- Refund requires invoice to be paid with stripePaymentIntentId

Co-Authored-By: Paperclip <noreply@paperclip.ing>
2026-04-13 19:11:59 +00:00
Paperclip d76e055962 GRO-605: Stripe SDK integration + payment service
- Add stripe dependency to @groombook/api
- Implement payment.ts service with:
  - getOrCreateStripeCustomer: look up or create Stripe customer
  - createPaymentIntent: create payment intent for invoice(s)
  - processRefund: full or partial refund
  - listPaymentMethods: list saved cards
  - attachPaymentMethod / detachPaymentMethod: manage saved cards
- Lazy Stripe client initialization; graceful null return when keys not set

Co-Authored-By: Paperclip <noreply@paperclip.ing>
2026-04-13 19:11:59 +00:00
Paperclip c1e8d9830d GRO-600: Extend reminder scheduler to send SMS alongside email
- Import smsSend from ./sms.js
- Add TCPA opt-out constant
- Check email+SMS logs separately to allow independent sends
- Add smsOptIn and phoneE164 to client query
- Conditionally send SMS for opted-in clients with valid E.164 phone
- SMS message: pet name, service, groomer, confirm/cancel links, TCPA text
- SMS failures logged but don't block email delivery
- Feature flag: only attempts SMS when SMS service is initialized
- Idempotency: per-channel reminder log prevents duplicate sends
Co-Authored-By: Paperclip <noreply@paperclip.ing>
2026-04-13 19:11:59 +00:00
Paperclip dd0a57dcf9 feat(gro-194): SMS provider service with Telnyx SDK integration
- Added telnyx npm package
- Created sms.ts with SmsProvider interface
- Implemented TelnyxProvider with sendSms() and validateWebhookSignature()
- Added createSmsProvider() factory function
- Added smsSend() convenience function that skips when SMS_ENABLED=false
- Provider abstraction allows future Twilio or other providers
- E.164 phone validation on send
- Webhook signature verification using HMAC-SHA256

Co-Authored-By: Paperclip <noreply@paperclip.ing>
2026-04-13 19:11:59 +00:00
Paperclip ce5a5c5a02 GRO-598/GRO-194 Phase 1.1: SMS schema - add consent fields to clients, channel to reminderLogs, E.164 phone validation
Co-Authored-By: Paperclip <noreply@paperclip.ing>
2026-04-13 19:11:59 +00:00
Paperclip 1a0bbb5c01 GRO-607: Install Stripe frontend packages
Co-Authored-By: Paperclip <noreply@paperclip.ing>
2026-04-12 23:53:55 +00:00