Stu Mason
Stu Mason

Activity

StuMason/cleanconnect
TidyLinker.com
TypeScript
Pull Request Merged

PR #83 merged: feat: add payment verify endpoint as webhook fallback

Summary

  • Adds a POST /client/jobs/{job}/quotes/{quote}/payment/verify endpoint that checks the PaymentIntent status directly with Stripe
  • Frontend calls this endpoint immediately after stripe.confirmPayment() succeeds, so the local Payment record gets updated even if the webhook is delayed or lost
  • Best-effort call (silently catches failures) — webhooks remain the primary mechanism

Problem

After a client confirms payment via Stripe Elements, the payment status transition (pending → authorized) relied entirely on Stripe webhooks. If a webhook was delayed or lost, the UI would get stuck showing "Pay & Confirm" indefinitely.

Changes

  • PaymentController: New verify() method — retrieves PaymentIntent from Stripe, syncs local status (requires_capture → authorized, canceled → cancelled), skips Stripe call if already non-pending
  • routes/web.php: New route client.jobs.quote.payment.verify
  • payment-form.tsx: POST to verify endpoint after confirmPayment() succeeds
  • payment-dialog.tsx: Pass verifyUrl prop via Wayfinder route
  • PaymentControllerTest: 6 new tests (authorized transition, already-authorized skip, 404, processing passthrough, cancelled transition, auth check)

Test plan

  • All 12 PaymentController tests pass (6 existing + 6 new)
  • Manual: confirm payment locally without stripe listen → page should show authorized state
  • Manual: confirm payment with stripe listen running → verify is a no-op, webhook handles it
+368
additions
-115
deletions
12
files changed