Skip to content

Add result helpers to Payment and Operation - #13

Merged
loevgaard merged 1 commit into
1.xfrom
dx/result-helpers
Aug 17, 2026
Merged

Add result helpers to Payment and Operation#13
loevgaard merged 1 commit into
1.xfrom
dx/result-helpers

Conversation

@loevgaard

Copy link
Copy Markdown
Member

Part of #10 (finding 4).

Why

"Was the capture approved?" meant hand-rolling the same inspection in every integration: find the operation with type=capture, pending=false and qp_status_code='20000'. That's exactly where consumers make bugs — forgetting pending, comparing the code as an int, summing rejected operations, picking "the last operation" from an array whose order they don't control.

What

Operation

  • QP_STATUS_APPROVED = '20000'
  • isApproved()!pending && qpStatusCode === '20000' (so a pending op with a stale code, a rejection, or 3-D Secure required are all false)
  • isOfType(OperationType|string)

Payment

  • operation(int $id): ?Operation
  • latestOperation(): ?Operation — highest id, regardless of array order
  • operationsOfType(OperationType|string): list<Operation>
  • hasPendingOperation(): bool — the "don't read the outcome yet" signal for async operations
  • authorizedAmount() / capturedAmount() / refundedAmount() — sums of approved operations only (authorizedAmount() also counts recurring, which is the authorization of a recurring payment)
  • isCancelled() — an approved cancel exists

All additive; no existing signature changes. README gains a "Reading what happened to a payment" section (also explaining accepted, balance, and that operation ids are per-payment sequence numbers → a good callback idempotency key).

Tests: unit tests on hand-built payments (approved/pending/rejected mixes, unordered operations, missing amounts, no operations) plus assertions on the mapped payment.json fixture.

"Was the capture approved?" meant hand-rolling the same inspection in every
integration: find the operation with type=capture, pending=false and
qp_status_code=20000. That's where consumers make bugs (forgetting `pending`,
comparing the code as an int, summing rejected operations).

Operation:
- QP_STATUS_APPROVED = '20000'
- isApproved(): !pending && qpStatusCode === '20000'
- isOfType(OperationType|string)

Payment:
- operation(int $id): ?Operation
- latestOperation(): ?Operation (highest id, regardless of array order)
- operationsOfType(OperationType|string): list<Operation>
- hasPendingOperation(): bool
- authorizedAmount() / capturedAmount() / refundedAmount(): sums of APPROVED
  operations only (authorizedAmount includes `recurring`, which authorizes a
  recurring payment)
- isCancelled(): an approved cancel exists

Plus a README section "Reading what happened to a payment" and tests (unit
tests on hand-built payments + assertions on the mapped fixture).

Refs #10 (finding 4).
@codecov

codecov Bot commented Aug 17, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 98.64%. Comparing base (cc4b95c) to head (9a42b4e).

Additional details and impacted files
@@             Coverage Diff              @@
##                1.x      #13      +/-   ##
============================================
+ Coverage     98.50%   98.64%   +0.14%     
- Complexity      147      171      +24     
============================================
  Files            24       24              
  Lines           401      443      +42     
============================================
+ Hits            395      437      +42     
  Misses            6        6              

☔ 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 79c2663 into 1.x Aug 17, 2026
35 checks passed
@loevgaard
loevgaard deleted the dx/result-helpers branch August 17, 2026 09:57
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