PHPackages                             sonnenglas/yoco-php-sdk - PHPackages - PHPackages  [Skip to content](#main-content)[PHPackages](/)[Directory](/)[Categories](/categories)[Trending](/trending)[Leaderboard](/leaderboard)[Changelog](/changelog)[Analyze](/analyze)[Collections](/collections)[Log in](/login)[Sign up](/register)

1. [Directory](/)
2. /
3. [HTTP &amp; Networking](/categories/http)
4. /
5. sonnenglas/yoco-php-sdk

ActiveLibrary[HTTP &amp; Networking](/categories/http)

sonnenglas/yoco-php-sdk
=======================

Framework-agnostic PHP SDK for the Yoco Online (Checkout) Payment API with Standard Webhooks signature verification.

v1.0.2(1mo ago)287MITPHPPHP &gt;=8.2

Since May 22Pushed 1mo agoCompare

[ Source](https://github.com/sonnenglas/yoco-php-sdk)[ Packagist](https://packagist.org/packages/sonnenglas/yoco-php-sdk)[ Docs](https://github.com/sonnenglas/yoco-php-sdk)[ RSS](/packages/sonnenglas-yoco-php-sdk/feed)WikiDiscussions master Synced 3w ago

READMEChangelog (2)Dependencies (18)Versions (4)Used By (0)

yoco-php-sdk
============

[](#yoco-php-sdk)

Framework-agnostic PHP SDK for the [Yoco](https://www.yoco.com/za/) Online (Checkout) Payment API, with first-class support for Standard Webhooks signature verification.

[![Packagist Version](https://camo.githubusercontent.com/5a298bb12c3ef33b3da43e5d58e750a1ce0f4bfbccb46a3d8c20b533afdd7c90/68747470733a2f2f696d672e736869656c64732e696f2f7061636b61676973742f762f736f6e6e656e676c61732f796f636f2d7068702d73646b2e737667)](https://packagist.org/packages/sonnenglas/yoco-php-sdk)[![Packagist Downloads](https://camo.githubusercontent.com/20e8ac65835412dd3186a4424b251a1d91d50032bd3204025795591e36f82504/68747470733a2f2f696d672e736869656c64732e696f2f7061636b61676973742f64742f736f6e6e656e676c61732f796f636f2d7068702d73646b2e737667)](https://packagist.org/packages/sonnenglas/yoco-php-sdk)[![PHP Version](https://camo.githubusercontent.com/0c9d82d2dd22a05e1abc56bbf3fa8e8887df2cb5bd4f46f1c837878351799ba1/68747470733a2f2f696d672e736869656c64732e696f2f7061636b61676973742f7068702d762f736f6e6e656e676c61732f796f636f2d7068702d73646b2e737667)](https://packagist.org/packages/sonnenglas/yoco-php-sdk)[![License](https://camo.githubusercontent.com/7013272bd27ece47364536a221edb554cd69683b68a46fc0ee96881174c4214c/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f6c6963656e73652d4d49542d626c75652e737667)](LICENSE)[![PHPStan](https://camo.githubusercontent.com/1bc07920f0d36e55c17e1d38b1caa132cc605f51a82b388c962870b9a747b898/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f5048505374616e2d6c6576656c253230392d627269676874677265656e2e737667)](phpstan.neon)

---

Features
--------

[](#features)

- **Framework-agnostic.** Plain PSR-18 (HTTP client), PSR-17 (factories), and PSR-7 (messages). No Laravel, no Symfony, no global state — drop it into any modern PHP project.
- **Type-safe DTOs.** Readonly request/response objects with strict shape validation. No untyped arrays leaking through your code.
- **Idempotency built in.** `Checkouts::create()` and `::refund()` auto-generate a UUID v4 `Idempotency-Key` per call, or accept your own for deterministic retries.
- **Webhook signature verification.** Standard Webhooks compliant. Constant-time HMAC comparison, replay-window enforcement, multi-version signature parsing for graceful key rotation.
- **Hardened by default.** 1 MiB response and webhook body caps, JSON depth limit of 64, defensive header sanitization, and PSR-18 transport error wrapping that scrubs the `Authorization: Bearer` header from leaked messages.
- **Comprehensive HTTP error mapping.** `400`, `403`, `409`, `422`, `429` each map to a distinct exception subclass — no need to grep on status codes.
- **Auto-detected test mode.** `CheckoutResponse::$processingMode` and `WebhookSubscription::$mode` surface Yoco's `live` / `test` distinction so the same code path works in both environments.
- **PHPStan level 9.** Zero static-analysis errors. Strict types throughout.
- **114 tests.** PHPUnit 10 with realistic Yoco payload fixtures.

Why this SDK?
-------------

[](#why-this-sdk)

Yoco does not publish an official PHP SDK at the time of writing, and the third-party packages we could find were either Laravel-specific, abandoned, or predated the current Checkout API.

`sonnenglas/yoco-php-sdk` is built against the current public [Yoco Online Payments API](https://developer.yoco.com/docs/checkout-api/), targets modern PHP (8.2+), and stays out of your dependency injection container by design.

Requirements
------------

[](#requirements)

- **PHP** 8.2 or newer.
- A **PSR-18** HTTP client. [Guzzle 7](https://docs.guzzlephp.org/) is the recommended default and is automatically discovered via [`php-http/discovery`](https://docs.php-http.org/en/latest/discovery.html).

Installation
------------

[](#installation)

```
composer require sonnenglas/yoco-php-sdk
```

If you do not already have a PSR-18 client installed:

```
composer require guzzlehttp/guzzle
```

`php-http/discovery` will auto-wire any installed PSR-18 client and PSR-17 factories — you only need to inject them manually if you want to override defaults (timeouts, retry middleware, mock client in tests, etc.).

Quick start
-----------

[](#quick-start)

### 1. Create a hosted checkout

[](#1-create-a-hosted-checkout)

```
use Sonnenglas\Yoco\Client;
use Sonnenglas\Yoco\Dto\CreateCheckoutRequest;

$client = new Client(secretKey: getenv('YOCO_SECRET_KEY'));

$checkout = $client->checkouts()->create(new CreateCheckoutRequest(
    amount:     10000,                          // 100.00 ZAR — Yoco amounts are in cents
    currency:   'ZAR',
    successUrl: 'https://example.com/success',
    cancelUrl:  'https://example.com/cancel',
    metadata:   ['orderNumber' => 'ORD-100'],
));

header('Location: '.$checkout->redirectUrl);   // send the customer to Yoco
```

### 2. Verify an incoming webhook

[](#2-verify-an-incoming-webhook)

```
use Sonnenglas\Yoco\Webhook\SignatureVerifier;
use Sonnenglas\Yoco\Exceptions\SignatureVerificationException;

$verifier = new SignatureVerifier(getenv('YOCO_WEBHOOK_SECRET')); // whsec_...

try {
    $event = $verifier->verify(file_get_contents('php://input'), getallheaders());
} catch (SignatureVerificationException $e) {
    http_response_code(401);
    exit;
}

// $event->type === 'payment.succeeded' | 'payment.failed'
// $event->payload['metadata']['orderNumber']
```

### 3. Refund a checkout

[](#3-refund-a-checkout)

```
$refund = $client->checkouts()->refund(
    checkoutId: 'ch_9LVKD8GnAj7f39DFbn4F16bE',
    amount:     2500,         // partial refund of 25.00 ZAR; omit for full refund
);

echo $refund->status;         // 'created' | 'succeeded' | ...
```

Documentation
-------------

[](#documentation)

- [Documentation home](docs/README.md)
- **Guides**
    - [Installation](docs/guides/installation.md)
    - [Quickstart](docs/guides/quickstart.md)
    - [Webhook handling](docs/guides/webhook-handling.md)
    - [Signature verification (deep dive)](docs/guides/signature-verification.md)
    - [Error handling](docs/guides/error-handling.md)
    - [Testing your integration](docs/guides/testing.md)
    - [Laravel integration](docs/guides/laravel-integration.md)
    - [Symfony integration](docs/guides/symfony-integration.md)
    - [Plain PHP / Slim](docs/guides/plain-php.md)
- **API reference**
    - [Overview](docs/api/README.md)
    - [`Client`](docs/api/client.md)
    - [`Resources\Checkouts`](docs/api/checkouts.md)
    - [`Resources\Webhooks`](docs/api/webhooks.md)
    - [`Webhook\SignatureVerifier`](docs/api/signature-verifier.md)
    - [DTOs](docs/api/dtos.md)
    - [Exceptions](docs/api/exceptions.md)
- **Runnable examples** — see [`examples/`](examples/)

Supported features
------------------

[](#supported-features)

In scopeOut of scope`POST /api/checkouts` — create checkout`GET /v1/payments/{id}` (main Yoco API)`POST /api/checkouts/{id}/refund` — full + partial refundPayouts (`/v1/payouts`)`POST /api/webhooks` — register subscriptionLocations (`/v1/locations`)`GET /api/webhooks` — list subscriptionsOAuth applications`DELETE /api/webhooks/{id}` — delete subscriptionYoco Card Machine / POS APIsStandard Webhooks signature verification (`v1`)In-person card-present paymentsStandard Webhooks key rotation (multi-signature headers)Test-mode detection (`processingMode`, `mode` fields)`Idempotency-Key` auto-generation (UUID v4)`Retry-After` parsing on rate-limit responsesThe SDK targets the [Yoco Online Payments API](https://developer.yoco.com/docs/checkout-api/)at `https://payments.yoco.com/api`. The broader `api.yoco.com/v1` surface (payments, payouts, locations) is intentionally not implemented — open an issue if you need it.

Exceptions
----------

[](#exceptions)

All SDK exceptions extend `Sonnenglas\Yoco\Exceptions\YocoException`.

HTTPExceptionWhen400`ValidationException`Invalid request body or parameters.401`AuthenticationException`Defensive — Checkout API uses 403, but proxies may return 401.403`AuthenticationException`Missing or invalid API key.409`IdempotencyConflictException`Another request with the same `Idempotency-Key` is in flight.422`IdempotencyMismatchException`Re-used `Idempotency-Key` with a different request body.429`RateLimitException` (`$retryAfter`)Rate limit reached (defensive; surfaces `Retry-After` if present).other`ApiException`Anything else (5xx, unmapped 4xx, malformed JSON, etc.).—`SignatureVerificationException`Webhook signature failed verification.Security
--------

[](#security)

- **Constant-time signature comparison** via `hash_equals` — no early-exit timing side channel.
- **`WebhookSubscription` redaction** — `__debugInfo()` masks the webhook secret so it never surfaces in `var_dump`, `print_r`, or Symfony VarDumper output.
- **Transport-error sanitization** — PSR-18 client exceptions are wrapped without propagating the inner message, which on some clients embeds the full outgoing request (including the `Authorization: Bearer ` header). The original exception is still available via `getPrevious()`.
- **Defensive size limits** — 1 MiB on response bodies, 1 MiB on webhook bodies, JSON depth capped at 64. Malformed or oversized payloads fail loudly rather than blow up memory.
- **Replay protection** — webhook timestamps are checked against a configurable tolerance window (default 180 s, max 3600 s).

See [SECURITY.md](SECURITY.md) for the full security policy and reporting process.

Development
-----------

[](#development)

```
composer install
composer test         # PHPUnit
composer phpstan      # PHPStan level 9
composer cs-fix       # PHP-CS-Fixer
composer check        # phpstan + test together
```

Versioning
----------

[](#versioning)

This project follows [Semantic Versioning 2.0.0](https://semver.org/spec/v2.0.0.html).

- See [CHANGELOG.md](CHANGELOG.md) for the release history.
- See [UPGRADING.md](UPGRADING.md) for breaking-change migration guides.

Contributing
------------

[](#contributing)

Pull requests, issues, and discussions are welcome. Please read [CONTRIBUTING.md](CONTRIBUTING.md) before opening a PR — it covers the dev setup, coding standards, and the test-first workflow used throughout the codebase.

For bug reports and feature requests, please use the GitHub issue templates.

License
-------

[](#license)

Released under the [MIT License](LICENSE).

Credits
-------

[](#credits)

Built and maintained by [Przemek Peron](mailto:przemek@sonnenglas.net).

If this SDK saves you time, please consider starring the [GitHub repository](https://github.com/sonnenglas/yoco-php-sdk).

###  Health Score

44

—

FairBetter than 90% of packages

Maintenance94

Actively maintained with recent releases

Popularity16

Limited adoption so far

Community6

Small or concentrated contributor base

Maturity48

Maturing project, gaining track record

 Bus Factor1

Top contributor holds 100% of commits — single point of failure

How is this calculated?**Maintenance (25%)** — Last commit recency, latest release date, and issue-to-star ratio. Uses a 2-year decay window.

**Popularity (30%)** — Total and monthly downloads, GitHub stars, and forks. Logarithmic scaling prevents top-heavy scores.

**Community (15%)** — Contributors, dependents, forks, watchers, and maintainers. Measures real ecosystem engagement.

**Maturity (30%)** — Project age, version count, PHP version support, and release stability.

###  Release Activity

Cadence

Every ~16 days

Total

3

Last Release

31d ago

### Community

Maintainers

![](https://www.gravatar.com/avatar/c01b6bd0faf6699a448bcb24a5b86999f5a770ea0f296dc7ade0842ad54836cc?d=identicon)[sonnenglas](/maintainers/sonnenglas)

---

Top Contributors

[![przemekperon](https://avatars.githubusercontent.com/u/169778?v=4)](https://github.com/przemekperon "przemekperon (3 commits)")

---

Tags

sdkpsr-18webhookspaymentscheckoutstandard-webhooksSouth Africayoco

###  Code Quality

TestsPHPUnit

Static AnalysisPHPStan

Code StylePHP CS Fixer

Type Coverage Yes

### Embed Badge

![Health badge](/badges/sonnenglas-yoco-php-sdk/health.svg)

```
[![Health](https://phpackages.com/badges/sonnenglas-yoco-php-sdk/health.svg)](https://phpackages.com/packages/sonnenglas-yoco-php-sdk)
```

###  Alternatives

[telnyx/telnyx-php

Official Telnyx PHP SDK — APIs for Voice, SMS, MMS, WhatsApp, Fax, SIP Trunking, Wireless IoT, Call Control, and more. Build global communications on Telnyx's private carrier-grade network.

36789.4k2](/packages/telnyx-telnyx-php)[flow-php/flow

PHP ETL - Extract Transform Load - Data processing framework

85036.3k](/packages/flow-php-flow)[tempest/framework

The PHP framework that gets out of your way.

2.2k34.4k16](/packages/tempest-framework)[laudis/neo4j-php-client

Neo4j-PHP-Client is the most advanced PHP Client for Neo4j

185702.8k44](/packages/laudis-neo4j-php-client)[getbrevo/brevo-php

Official Brevo provided RESTFul API V3 php library

1003.9M50](/packages/getbrevo-brevo-php)[chargebee/chargebee-php

ChargeBee API client implementation for PHP

758.5M9](/packages/chargebee-chargebee-php)

PHPackages © 2026

[Directory](/)[Categories](/categories)[Trending](/trending)[Changelog](/changelog)[Analyze](/analyze)
