Skip to content

[Payments]: Guest online-payment page & shared gateway pipeline #653

Open

Description

@nielsdrost7

Recreate v1's anonymous "pay this invoice" surface and the gateway-agnostic plumbing both gateway issues depend on. v1 behavioral spec: application/modules/guest/controllers/Payment_information.php (branch prep/v180).

Specific

  1. Guest pay page at GET /pay/{urlKey} (no auth): resolves the invoice by url_key only if guest-visible; redirects to the guest invoice view with invoice_already_paid when balance is 0 for a known user, 404 otherwise (v1: Payment_information.php:31-48). Lists available gateways: a gateway is offered when settings.<gateway>_enabled is on AND (invoice has no payment method OR gateway has no mapped method OR they match — v1: Payment_information.php:56-69 using gateway_<d>_payment_method). When exactly one gateway qualifies it is auto-selected and its pay UI is served directly (v1: :72-74). Page shows invoice summary, payment method, and overdue state (v1: :77-93). Gateway sub-views: Stripe embedded checkout mount (publishable key; v1 :112-120) and PayPal JS SDK buttons (client id, currency; v1 :130-140).
  2. Shared pipeline used by both gateway callbacks:
    • Migration: add payment_external_id (string 255, nullable, unique) to payments (Modules/Payments/Database/Migrations/); add to Modules/Payments/Models/Payment.php.
    • Modules/Payments/Services/Gateways/GatewayPaymentRecorder.php (name indicative): given invoice, amount, currency, external id, method, note — performs dedup lookup on payment_external_id, already-paid guard, currency match vs the gateway's configured currency, amount ≥ balance − 0.0001 check, creates the Payment via PaymentService, and writes the GatewayTransaction journal row ([Payments]: Online Payments Journal #144) for success/failure/exception alike (v1 spec: Stripe.php:124-204, Paypal.php:163-258).
    • Master toggle settings.enable_online_payments (v1: partial_settings_online_payment.php:24-27) added to the Online Payment tab in Modules/Core/Filament/Admin/Pages/Settings.php; when off, /pay/{urlKey} returns 404 regardless of per-gateway toggles.
    • Make the two online_payment_method selects in Settings.php (:650-656, :680-686, currently ['' => ''] + TODO) list the company's payment methods so the chooser's method-matching rule can work.

Measurable

  • Anonymous request to /pay/{urlKey} renders the chooser for a payable invoice with ≥2 enabled gateways; auto-serves the single gateway when only one qualifies; 404s for unknown keys or when online payments are disabled.
  • Method-matching rule verified for all three branches (invoice method 0, gateway method 0, exact match) and the negative case.
  • payments.payment_external_id exists, is unique, and dedup behaves as specified.

Achievable

Relevant

This is the entry point for every online payment in v1; without it the gateway integrations have no surface, and without payment_external_id neither gateway can guarantee idempotent payment recording.

Time-Bound

First of the three online-payment issues; before both gateway issues.

Arrange

Company with enable_online_payments=1; invoices: payable with method A, payable with method 0, fully paid; gateways: stripe enabled mapped to method A, paypal enabled mapped to method 0 (any).

Act

GET /pay/{urlKey} for each invoice; toggle enable_online_payments=0 and repeat; call GatewayPaymentRecorder twice with the same external id.

Assert

  • Payable invoice with method A shows both gateways (stripe matches, paypal is method-agnostic).
  • Disabling stripe leaves exactly one gateway and the page auto-serves the PayPal UI without a chooser.
  • Fully paid invoice: 404 for anonymous visitors.
  • enable_online_payments=0 → 404 even with gateways enabled.
  • payments table has a unique payment_external_id column; second recorder call with the same id creates no payment and reports duplicate.
  • Recorder writes a GatewayTransaction row on both the success and the duplicate call.
  • stripe_online_payment_method / paypal_online_payment_method selects list real payment methods (no longer the ['' => ''] stub).
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    refinedRefined with SMART plan / test suggestions

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions