Skip to content

v1.1.0

Choose a tag to compare

@loevgaard loevgaard released this 17 Aug 11:40
3762a69

The developer-experience release. 🧰

v1.0.0 got a top-to-bottom review through a first-time consumer's eyes (#10); this release ships the follow-ups. Everything is additive β€” no changes to existing signatures for callers β€” and every API-facing claim was verified against the live Quickpay API.

composer require setono/quickpay-php-sdk:^1.1

Highlights

  • Find the payment for an order. $client->payments()->findByOrderId($orderId) β€” exact match, null when absent. Together with create() it makes checkout find-or-create a one-liner (Quickpay enforces order_id uniqueness per account, so a retried checkout used to explode with "already exists on another payment"). Listing gained a typed PaymentsQuery (state, accepted, minTime/maxTime, acquirer, sortBy/sortDir, …) for getPage()/paginate(). (#12)
  • Read what happened without hand-rolling it. Operation::isApproved(), and on Payment: authorizedAmount(), capturedAmount(), refundedAmount(), isCancelled(), hasPendingOperation(), latestOperation(), operation($id), operationsOfType(). Only approved operations count β€” the exact place integrations used to get subtly wrong. (#13)
  • The whole API within reach. Client::delete(), plain-array bodies on post()/put()/patch() (sent as given, so unmodeled endpoints β€” renew, subscriptions, … β€” are a one-liner), PaymentsEndpoint::deleteLink(), and a README section on calling endpoints the SDK doesn't model. Bodies are Payload|array $body = [], never null; an empty body goes out as {}. (#14)
  • catch (QuickpayException $e) now really nets everything. Transport failures (DNS, refused connection, timeout) are wrapped in TransportException, which is also a PSR-18 ClientExceptionInterface, so existing catches keep working; the original is getPrevious(), isNetworkError() tells network from request errors. (#18)
  • Callbacks from any stack. handleGlobals() for plain PHP (php://input + $_SERVER), handleRaw() now takes the optional accountId/apiVersion headers, and the README has Symfony / Laravel / plain-PHP snippets. (#17)
  • Production cache in one argument. new Client('…', cache: new FileSystemCache($dir)) (and the same on CallbackHandler) β€” no more hand-wiring Valinor builders and forgetting the SDK's configuration. (#16)
  • Small things that add up. Payment::variables() (your keys, verbatim), Payment::$deadlineAt / $acquirer, CreatePaymentRequest::$shopsystem so a plugin can identify itself, a memoized Callback::payment(), and the SDK version in the User-Agent. (#19)
  • Docs that teach the model, not just the SDK. Table of contents; a "Concepts" section (the two keys, minor units, a payment as a ledger of operations, async operations, the redirect is not proof of payment); "Handling callbacks robustly" (retries β†’ idempotency on operation ids, per-payment ordering, respond fast, why 403/400); an end-to-end checkout recipe and Symfony wiring; accurate install text; a CHANGELOG.md; docs shipped in the dist again. (#20, #21)
  • Safety and hygiene. Client::request() now runs the same host-pinning guard as every other method (a consumer-built request could previously carry the API key to another host β€” #11). PRs are now gated by a Roave BC check (#23).

BC notes

Nothing changes for code that calls the SDK. Two things could touch unusual code:

  • ClientInterface gained delete(), and post()/put()/patch() take Payload|array $body = [] instead of ?Payload $body = null β€” relevant only if you implement the interface (a mock-only interface) or passed an explicit null body (pass nothing, or []). (#14)
  • Code that caught Psr\Http\Client\NetworkExceptionInterface / RequestExceptionInterface specifically (rather than ClientExceptionInterface) should catch TransportException and inspect getPrevious() / isNetworkError(). (#18)
  • CollectionRequestOptions is no longer final, and its page/pageSize are plain public properties (a readonly property cannot be reinitialized during clone before PHP 8.3) β€” the withers still validate. (#12)

Won't do

  • A shipped test double (#15): the seam is the PSR-18 client, and every stack already has a mock for it β€” the README now shows how to plug it in.

Quality

166 tests (was 109), PHPStan level max, MSI gate unchanged, CI across PHP 8.1–8.5 Γ— lowest/highest, plus the new backwards-compatibility check on every PR β€” and a live smoke run (create β†’ link β†’ get) against the real API on the merged branch.

Full changelog: v1.0.0...v1.1.0 Β· CHANGELOG.md