NewWe open-sourced 50+ Laravel packages
Custom AI apps, agents and automation — Roundly ConsultingRoundly
All packages
Certificates for Laravel

Validation & errors

ValidDomain is a Laravel validation rule for hostnames. The issue path runs it on every domain too, so invalid input never reaches a provider:

use RoundlyConsulting\Certificates\Rules\ValidDomain;

$request->validate(['domain' => ['required', new ValidDomain]]);

// Reject wildcards such as *.example.com
$request->validate(['domain' => ['required', new ValidDomain(allowWildcard: false)]]);

// Standalone checks
(new ValidDomain)->passes('shop.example.com');         // true
(new ValidDomain)->passes('https://shop.example.com'); // false

A valid hostname has at least two labels, each 1–63 letters, digits or inner hyphens, a non-numeric top-level label and at most 253 characters. Schemes, paths, ports, spaces and a trailing dot are rejected. A leading *. wildcard is allowed unless you pass allowWildcard: false.

Exceptions

Every package error extends CertificateException, so one catch covers them all:

ExceptionRaised when
CertificateExceptionBase class. Also thrown for a domain with no registry row (renew(), renewLater(), revoke(), expire()), an illegal status move (renew(), renewLater(), revoke(), expire()), a provider that reports the certificate failed, expired or revoked, a renewal that produced the same certificate (or, without a fingerprint, no later expiry), issue() for a domain whose certificate name another domain already holds, a store write the disk reports as failed, a filesystem name with no stored PEM, PEM that is not an X.509 certificate, and when monitorExpiry() resolves no notifiable.
InvalidDomainExceptionA domain failed ValidDomain during issuance.
ProvisioningInProgressExceptionissue() or renew() while another process holds this certificate’s provisioning lock — or, for renew(), changed the row since it was read; nothing was provisioned and the row was not touched; retry once it finishes.
UnknownProviderExceptionCertificates::driver() — or provider() on CertificateProviderManager — got an unknown driver name.
AcmeExceptionAn ACME step failed: directory, nonce, account, order, challenge, finalize, download, signing, key generation or an unsupported account key — including an authorization that is no longer pending, a challenge token that is not base64url and a poll the CA refused (with its error detail).
KubernetesApiExceptionA Kubernetes API call failed (with the HTTP status and body) or the driver is misconfigured.

Messages are built in the current locale from certificates::messages (English and Slovak) — except CertificateException::unparseable(), KubernetesApiException and AcmeException, which stay English. providerReported() names the status by its translated label (as Failed; in Slovak v stave „Neúspešný“).

use RoundlyConsulting\Certificates\Exceptions\CertificateException;
use RoundlyConsulting\Certificates\Exceptions\InvalidDomainException;
use RoundlyConsulting\Certificates\Exceptions\ProvisioningInProgressException;
use RoundlyConsulting\Certificates\Facades\Certificates;

try {
    Certificates::for($domain)->using('acme')->issue();
} catch (InvalidDomainException $e) {
    // a domain failed ValidDomain — nothing was recorded or requested
} catch (ProvisioningInProgressException $e) {
    // another process is provisioning this certificate — the row was not touched, retry later
} catch (CertificateException $e) {
    // any other package error: ACME, Kubernetes API, unknown driver,
    // or a provider that reports the certificate failed, expired or revoked
}

Show your open-source love

This package is free and MIT-licensed. If it saves you time, a one-off donation or a Patreon membership keeps it maintained, tested and documented.

More ways to support, including crypto

By donating, you agree to our donation terms.

Want this built into your product?

We integrate our packages into custom Laravel and AI builds. Tell us what you're working on and we'll reply within 48 hours.