Commit Graph

6 Commits

Author SHA1 Message Date
Myron Blair 11edf3394f Add Square payment processor, gated behind PAYMENT_PROCESSOR flag (default: stripe)
Consolidates payment processing onto the same Square account already used by
tomtomgames.com and parkerslingshotrentals.com. Collapses the two prior parallel
Stripe flows (hosted Checkout + embedded Elements) into a single Square Web
Payments SDK flow, since Payments API is synchronous and removes the original
reason for two paths.

- includes/square.php: squareApi() cURL helper (mirrors the pattern already
  used on parkerslingshotrentals.com), markSquarePaymentResult() as the single
  source of truth for order completion shared by the sync response, webhook,
  and reconciliation poll - fixes a pre-existing bug where loyalty points were
  only ever awarded from the polling endpoint, never from the webhook.
- api/create-square-payment.php replaces api/create-payment-intent.php;
  api/create-checkout-session.php deleted (no Square equivalent - single flow).
- api/webhook.php rewritten for Squares signature scheme and event types.
- api/payment-status.php repurposed to reconciliation-only fallback.
- payment.php branches on PAYMENT_PROCESSOR so Stripe and Square code coexist
  deployed while dormant - flipping one config constant is the cutover/rollback.
- admin/payments.php: added a Square settings card alongside the existing
  (now legacy-labeled) Stripe card.
- db/schema.sql + live DB: added square_payment_id/square_order_id columns,
  stripe_* columns kept for historical orders.

Not yet cut over - PAYMENT_PROCESSOR still defaults to stripe in
config-secrets.php (outside this repo). Sandbox testing still needed before
flipping to square/production.
2026-07-05 05:27:19 +00:00
myron 62dd05780a Add payment_status guard to payment_intent.succeeded handler
Mirrors the checkout.session.completed case which checks
payment_status === paid before acting. Now checks data.status
=== succeeded on the PaymentIntent object, consistent with how
Stripe structures the event and defensive against any future
edge case where the event fires in a non-final state.
2026-06-03 06:13:22 +00:00
myron f8e9746340 Route webhook order emails through Email class for email_log visibility
Replaced local sendOrderConfirmationEmail() with emailService()->sendOrderConfirmation().
Order confirmations now log to email_log table and use the branded template
(orange header, full subtotal/tax/discount breakdown) instead of the minimal
brown-header version that was invisible to the admin Email Log.
2026-06-03 03:42:50 +00:00
myron 2550ec5695 Fix duplicate order confirmation email on Stripe Checkout
When using Stripe Checkout, both checkout.session.completed and
payment_intent.succeeded fire for the same payment. After the stripe.php
change propagated order_id into PI metadata, the PI handler also found
an order_id and sent a second confirmation email.

Fix: fetch the order first in payment_intent.succeeded and skip if
already confirmed. Also records stripe_payment_intent in this path
for direct PI flows that bypass checkout.session.completed.
2026-06-03 03:41:30 +00:00
myron e39df89a95 Fix webhook: add checkout.session.completed; propagate metadata to payment intent 2026-05-29 16:32:37 +00:00
myron 996ca0d621 Initial commit 2026-05-22 12:52:44 +00:00