Search by

hampel / synergy-wholesale-laravel

hampel

Laravel service provider and facade for the Synergy Wholesale API client

Package info

github.com/hampel/synergy-wholesale-laravel

pkg:composer/hampel/synergy-wholesale-laravel

Statistics

Installs: 102

Dependents: 0

Suggesters: 1

Stars: 1

Open Issues: 0

2.1.1 2026-09-14 11:58 UTC

README

Tests Latest Version on Packagist Total Downloads Open Issues License

Laravel service provider and facade for hampel/synergy-wholesale, a client for the Synergy Wholesale reseller API covering 138 operations across domains, DNS, DNSSEC, SSL, hosting, email and URL forwarding, SMS and subscriptions.

By Simon Hampel

Everything you can call, and every type it returns, is documented in that package. This one adds the container binding, a facade and a config file.

Installation

composer require hampel/synergy-wholesale-laravel

Generate an API key in the Synergy Wholesale control panel and put it, with your reseller ID, in .env:

SYNERGY_WHOLESALE_API_KEY=your_synergy_wholesale_api_key
SYNERGY_WHOLESALE_RESELLER_ID=your_synergy_wholesale_reseller_id

The API authorises by IP address as well as by key, so every machine that calls it — including each web server, queue worker and developer machine — needs its address on the allowlist in the control panel. A correct key from an unlisted address fails with ERR_RESELLER_NOT_AUTHORISED, which reads like a bad key.

Publishing the config file is optional and only useful if you want to read the credentials from somewhere other than those two environment variables:

php artisan vendor:publish --tag=synergy-wholesale-config

Laravel Zero

Laravel Zero does not run package discovery, so installing the package registers nothing: the client is not bound and config('synergy-wholesale') is null until the provider is listed by hand in config/app.php:

'providers' => [
    AppServiceProvider::class,
    Hampel\SynergyWholesale\Laravel\SynergyWholesaleServiceProvider::class,
],

The global SynergyWholesale alias comes from discovery too, so it stays unavailable. The facade works when imported by its class name, as the examples below do.

Publishing the config works once the provider is listed. Laravel Zero hides vendor:publish from list, but the command is there:

php <app> vendor:publish --tag=synergy-wholesale-config

Inject the client into handle(), not into a command's constructor. Resolving the client throws MissingCredentials when no reseller ID or API key is configured, and Laravel Zero constructs every command to build its command list. A constructor dependency on the client therefore breaks list, and --help for every other command in the application, on any machine without credentials. Injected into handle(), the exception is raised only when that command runs:

use Hampel\SynergyWholesale\SynergyWholesale;

public function handle(SynergyWholesale $sw): int
{
    // ...
}

Usage

Operations are grouped, and the method name is the API operation name as published:

use Hampel\SynergyWholesale\Laravel\Facades\SynergyWholesale;

$result = SynergyWholesale::domains()->checkDomain(domainName: 'example.com');
$status = SynergyWholesale::ssl()->getCertStatus(certID: 'abc123');

Or inject the client, which is bound as a singleton:

use Hampel\SynergyWholesale\SynergyWholesale;

public function __construct(private readonly SynergyWholesale $sw) {}

public function available(string $domain): bool
{
    return $this->sw->domains()->checkDomain(domainName: $domain)->available === 1;
}

A failed call throws: ApiError when the API answers with an ERR_ status, TransportException when the call could not be completed, and MissingCredentials when the reseller ID or API key is not configured. All three implement Hampel\SynergyWholesale\Exception\SynergyWholesaleException, so one catch covers the package.

Every call is logged through the application's default logger — one info line per operation, and the request and response at debug with the API key, EPP auth codes, passwords and SSL private keys redacted at every level, including the per-domain entries of a listDomains response. Everything else is logged in full, including registrant and contact names, email addresses, phone numbers and postal addresses.

Caching, retries and other decoration

This package binds Hampel\SynergyWholesale\Transport\Transport separately from the client, and that binding is the extension point. Anything that wraps a call — caching, retries, rate limiting, or a fixture in your own tests — is a decorator implementing that interface:

$this->app->extend(Transport::class, fn (Transport $inner) => new CachingTransport($inner, cache()));

Nothing is cached by default. Prices, availability and domain details are all cacheable in principle, but for how long is an application's decision rather than this package's, and a wrong answer about availability is expensive.

Upgrading from 1.x

Version 2 is a rewrite with no API in common with 1.x, and neither is hampel/synergy-wholesale itself — the Command and Response classes are gone, replaced by generated typed requests and responses reached through operation groups. Read the upgrade table in the core package README first; then, in your application:

1.x 2.x
SynergyWholesale\Facades\SynergyWholesale Hampel\SynergyWholesale\Laravel\Facades\SynergyWholesale
App::make('SynergyWholesale\SynergyWholesale') App::make(Hampel\SynergyWholesale\SynergyWholesale::class)
$sw->execute(new CheckDomainCommand(new Domain('example.com'))) $sw->domains()->checkDomain(domainName: 'example.com')
$sw->checkDomain($command, fresh: true) no equivalent — nothing is cached, so nothing is stale
config('synergy-wholesale.cache.*') removed
--tag=config --tag=synergy-wholesale-config

Requirements

PHP 8.3 or later with ext-soap, and Laravel 12 or 13.