Skip to content

Only auto-capture an approved authorize in ConfirmPaymentAction - #58

Merged
loevgaard merged 1 commit into
2.xfrom
fix/confirm-payment-approved-authorize
Aug 10, 2026
Merged

Only auto-capture an approved authorize in ConfirmPaymentAction#58
loevgaard merged 1 commit into
2.xfrom
fix/confirm-payment-approved-authorize

Conversation

@loevgaard

Copy link
Copy Markdown
Member

Fixes robustness finding R1 of #57.

Problem

ConfirmPaymentAction gated its auto-capture on OperationType::Authorize === $latestOperation->type() — the operation type alone. A rejected authorize (declined card — a routine event in the payment window, and Quickpay sends a callback for it) and a still-pending authorize both have that type, so they fell through to the amount check, where Operations::authorizedAmount() returns 0, the comparison failed, and the action threw LogicException.

Thrown from the notify path, that 500s the endpoint — and Quickpay then retries a callback that can never succeed.

Fix

Gate on Operations::isApprovedOfType($latestOperation, OperationType::Authorize): a not-approved authorize is nothing to confirm, so the callback completes quietly (the balance is still persisted). The amount-mismatch throw for an approved authorize is kept — that is a genuine anomaly worth surfacing.

Tests

  • ConfirmPaymentActionTest: rejected authorize → no capture, no throw; pending authorize → no capture, no throw.
  • NotifyActionTest: full callback flow for a declined payment with auto_capture on completes without error.
  • ApiTestTrait::operation() now supports pending/null status-code fixtures — the shape every asynchronous operation has until Quickpay finishes it, previously absent from the whole suite.

The auto-capture gate checked only the operation type, so the callback for
a rejected authorize (a declined card is routine in the payment window) or
a still-pending one fell through to the amount check, found an authorized
amount of 0 and threw a LogicException. That 500s the notify endpoint and
has Quickpay retry a callback that can never succeed.

A not-approved authorize is now simply nothing to confirm: the callback
completes quietly (still persisting the balance) and no capture is issued.
@codecov

codecov Bot commented Aug 10, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 97.43%. Comparing base (6122f5f) to head (5cfe38b).

Additional details and impacted files
@@            Coverage Diff            @@
##                2.x      #58   +/-   ##
=========================================
  Coverage     97.43%   97.43%           
  Complexity      126      126           
=========================================
  Files            14       14           
  Lines           351      351           
=========================================
  Hits            342      342           
  Misses            9        9           

☔ View full report in Codecov by Harness.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

@loevgaard
loevgaard merged commit cb6401c into 2.x Aug 10, 2026
21 checks passed
@loevgaard
loevgaard deleted the fix/confirm-payment-approved-authorize branch August 10, 2026 14:06
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant