Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 0 additions & 1 deletion .gitattributes
Original file line number Diff line number Diff line change
Expand Up @@ -12,4 +12,3 @@
/phpstan.neon.dist export-ignore
/phpunit.xml.dist export-ignore
/rector.php export-ignore
/README.md export-ignore
4 changes: 2 additions & 2 deletions CLAUDE.md
Original file line number Diff line number Diff line change
Expand Up @@ -201,8 +201,8 @@ Request → Action flow (amounts are integer minor units everywhere — no conve
- **Sync** → `SyncAction` — Payum's standard "refresh the details from the gateway" request. Fetches by
`quickpayPaymentId` and writes the scalar snapshot (`balance`, `state`). A model without a
`quickpayPaymentId` has nothing to sync, so it is a no-op rather than a throw. Every action that
already fetches the payment (`StatusAction`, `ConfirmPaymentAction`, and `RefundAction` on its default
path) also persists `balance` — it costs no extra call and it is the one figure Payum's marks cannot
fetches the payment — all of them, since the in-flight guard made Cancel and every Refund fetch too —
also persists `balance`; it costs no extra call and it is the one figure Payum's marks cannot
express, so downstream consumers do not have to re-fetch just to learn it.
- **GetStatus** → `StatusAction` — maps the SDK `PaymentState` + latest operation to Payum marks
(`markCaptured`, `markRefunded`, `markAuthorized`, `markFailed`, etc.). The refund branch is **not**
Expand Down
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -217,7 +217,7 @@ uses. `quickpayPaymentId` is the single source of truth — everything else is a
| `continue_url` | `Convert` | The token's **target** url: the customer returns to it, and the `Capture`/`Authorize` that sent them out runs again to finish. |
| `cancel_url` | `Convert` | The token's after url. |
| `callback_url` | `Capture`, `Authorize` | The payment's notify token url — on the link, and named on every capture/refund/cancel the gateway issues so their callbacks arrive there too. |
| `balance` | every action that fetches the payment: `Capture`, `Authorize`, `GetStatus`, `Sync`, `Notify`, `Refund` (default path) | **What is still captured** — captured minus refunded. |
| `balance` | every action that fetches the payment — all of them: `Capture`, `Authorize`, `Refund`, `Cancel`, `GetStatus`, `Sync`, `Notify` | **What is still captured** — captured minus refunded. |
| `state` | `Sync`, `Notify` | Quickpay's own payment state. |
| `capture_amount`, `refund_amount` | *you* | Optional partial-operation amounts; see below. |

Expand Down
2 changes: 0 additions & 2 deletions composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,6 @@
"php": ">=8.1",
"ext-ctype": "*",
"ext-filter": "*",
"ext-hash": "*",
"ext-json": "*",
"composer-runtime-api": "^2.0",
"payum/core": "^1.7.5",
"php-http/message-factory": "^1.0",
Expand Down
14 changes: 8 additions & 6 deletions docs/UPGRADE-2.0.md
Original file line number Diff line number Diff line change
Expand Up @@ -102,10 +102,11 @@ The details array stored on a payment (the `ArrayObject` model) now contains **o
- `2.0` stores only `quickpayPaymentId` (int) — the source of truth — plus `amount`, `currency`,
`order_id`, `continue_url`, `cancel_url`, `callback_url`. The payment is re-fetched from Quickpay when
needed.
- Any action that already fetches the payment also writes **`balance`** (what is still captured, i.e.
captured minus refunded) back into the details: `Capture`, `Authorize`, `GetStatus`, `Notify`, the
new `Sync`, and `Refund` on its default path. It costs no extra API call and it is the one figure
Payum's status marks cannot express. `Sync` and `Notify` additionally write `state`.
- Any action that fetches the payment — since `2.0.0-beta.1` that is every one that touches it:
`Capture`, `Authorize`, `Refund`, `Cancel`, `GetStatus`, `Notify` and the new `Sync` — also writes
**`balance`** (what is still captured, i.e. captured minus refunded) back into the details. It costs
no extra API call and it is the one figure Payum's status marks cannot express. `Sync` and `Notify`
additionally write `state`.

If your code reads `$details['quickpayPayment']`, switch to fetching the payment via the SDK using
`$details['quickpayPaymentId']`.
Expand Down Expand Up @@ -307,8 +308,9 @@ These were internal implementation details; they are gone in 2.0:

- `Setono\Payum\Quickpay\Model\*` (`QuickpayPayment`, `QuickpayPaymentOperation`, `QuickpayPaymentLink`,
`QuickpayModel`, `QuickpayCard`) — replaced by the SDK's `Setono\Quickpay\Response\Payment\*` DTOs and
the `Setono\Quickpay\Enum\{PaymentState,OperationType}` enums. State logic now lives in the
`Setono\Payum\Quickpay\Operations` helper.
the `Setono\Quickpay\Enum\{PaymentState,OperationType}` enums. The questions that used to live on those
models are the DTOs' own helpers since SDK 1.2 (`Payment::latestApprovedOperation()`,
`hasApprovedOperation()`, `hasPendingOperation()`, `Operation::isApproved()`/`isDeclined()`, …).
- `Setono\Payum\Quickpay\Api` is no longer an HTTP client. It is now an immutable value object wrapping
the SDK `Setono\Quickpay\Client\ClientInterface` and the gateway options (`payments()`, `getClient()`,
`isAutoCapture()`, `createCallbackValidator()`, …). Its old `getPayment()` / `capturePayment()` /
Expand Down
7 changes: 7 additions & 0 deletions tests/Action/CaptureActionTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -434,6 +434,13 @@ public static function inFlightProvider(): iterable

yield 'capture pending (a retry, or a fast second instalment)' => [[$authorize, ['id' => 2, 'type' => 'capture', 'amount' => 250, 'pending' => true, 'qp_status_code' => null]], 'capture'];
yield 'cancel pending' => [[$authorize, ['id' => 2, 'type' => 'cancel', 'amount' => 1000, 'pending' => true, 'qp_status_code' => null]], 'cancel'];
// A newer pending operation of a type the guard does not care about (here: an authorize made
// outside the gateway) must not mask a pending money operation earlier in the list.
yield 'capture pending behind a newer pending authorize' => [[
$authorize,
['id' => 2, 'type' => 'capture', 'amount' => 250, 'pending' => true, 'qp_status_code' => null],
['id' => 3, 'type' => 'authorize', 'amount' => 1000, 'pending' => true, 'qp_status_code' => null],
], 'capture'];
}

#[Test]
Expand Down
Loading