Lue dans les fichiers PHP du paquet au commit 1dd873f591e4 : ses espaces de noms, classes, interfaces et énumérations, leurs constantes, propriétés et méthodes publiques avec leur PHPDoc, et les options que prennent ses fabriques. Rien n’en est exécuté.
ConfigclassA gateway's configuration while its factory builds it: the options given, the factory's defaults under them, and the keys that must be filled.
3 methods
GatewayclassA carrier's actions behind one door: the first action supporting a request answers it.
11 methods
GatewayFactoryclassThe Payum way: a carrier's factory fills a Config - its name, title, the options it needs, its API client ("omnibus.api", a closure of the Config) and its actions ("omnibus.action.<name>") - and the gateway is those actions, the API handed to the ones that ask for it.
4 methods
GatewayFactoryInterfaceinterfaceBuilds a carrier's gateway from its options (credentials, sandbox, rates...).
2 methods
GatewayInterfaceinterfaceOne carrier, configured: the same questions for all of them. Each typed method is a shortcut for execute() with its request.
10 methods
RegistryclassThe shop's carriers by name, each built once from its factory and options:
7 methods
ActionInterfaceinterfaceOne thing a carrier does: answers the requests it supports.
2 methods
ApiAwareInterfaceinterfaceAn action that talks to the carrier through the gateway's API client.
1 method
ApiAwareTraittrait1 method
ConfiguredRatingActionclassPrices from the gateway's configuration, for carriers that publish no rating API (the price is the shop's contract, not a public tariff).
3 methods
OmnibusBundleclassOmnibus in a Symfony application: the carrier packages installed (omnibus/offline, omnibus/mondial-relay, omnibus/colissimo, omnibus/ups... every omnibus/* package) registered, the shop's gateways built from configuration, Omnibus\Registry autowired, and each gateway injectable by its name:
2 methods
CarrierExceptionclassThe carrier refused, or could not be reached.
1 method · 2 properties
InvalidConfigExceptionclassA gateway misconfigured: a credential missing, an unknown factory.
OmnibusExceptioninterfaceEvery exception Omnibus throws.
RequestNotSupportedExceptionclassThe carrier does not do that (no pickup points, no cancellation...).
1 method
RedactionclassWhat a failed call may carry of its credentials, taken out before the failure leaves the package: an HTTP client's exception quotes the URL called (a key in its query, a password in its user part), and every exception's trace keeps the arguments of the calls under it (the request options, headers and query with the key) unless PHP runs with zend.exception_ignore_args.
5 methods · 1 constant
AddressclassA postal address: the sender's, the recipient's, a pickup point's.
2 methods · 8 properties
LabelclassThe shipping label (or slip) a carrier issued: its tracking number and the printable document.
1 method · 7 properties · 2 constants
ParcelclassOne box: its weight (grams), its size (centimetres), what it is worth (minor units).
2 methods · 7 properties
PickupPointclassA relay, locker or post office a parcel can be sent to and collected from.
1 method · 8 properties
RateclassWhat a service costs for a shipment (minor units) and how long it takes.
1 method · 7 properties
ShipmentclassWhat goes where: from the sender to the recipient - at home, or at a pickup point - in one or more parcels, under a carrier's service.
3 methods · 8 properties
TrackingclassWhere a parcel is: its latest status and every step so far, oldest first.
2 methods · 4 properties
TrackingEventclass1 method · 5 properties
TrackingStatusenumEvery carrier's statuses, folded onto one scale.
1 method · 8 cases
CancelclassCancel a shipment not handed over yet. Result: true when the carrier voided it.
1 method · 1 property
GetSlipclassThe label of a shipment booked earlier, again (a reprint). Result: the Label.
2 methods · 2 properties
PaperlessclassCustoms documents sent electronically (paperless trade) for a shipment leaving the customs union. Result: true once the carrier accepted them.
1 method · 2 properties
PickupclassThe pickup points near an address (that can take this parcel). Result: PickupPoint[]
2 methods · 3 properties
RatingclassThe services that can carry a shipment, and their price. Result: Rate[]
2 methods · 1 property
RequestclassA question put to a gateway. The action that supports it answers by setting the result; the gateway hands the request back.
3 methods
ShippingclassBook the shipment with the carrier. Result: the Label.
2 methods · 1 property
TrackingclassWhere is this parcel? Result: Model\Tracking
2 methods · 2 properties
FixturesclassAddresses and shipments for a carrier's tests: a shop in Paris sending to a customer (in France unless told otherwise). Shipped with the core so a carrier's tests run where the carrier is installed alone.
3 methods
GatewayContractTeststraitWhat every Omnibus gateway does, as PHPUnit tests a carrier runs against its own factory, offline: the carrier's API is replaced by its recorded answers (RecordedHttpClient), so no test reaches the network.
12 methods
RecordedHttpClientclassA carrier's recorded answers in place of its API: no request leaves the process. Each route is "METHOD fragment" or "fragment" (any method), matched when the request's URL contains the fragment - or, for "body:fragment", when its body does (a SOAP operation, say); the first route declared that matches answers.
9 methods
Omnibus
Config class
final class Config extends ArrayObject Config.php:13
A gateway's configuration while its factory builds it: the options given, the factory's defaults under them, and the keys that must be filled.
Config::defaults()
public function defaults(array $defaults): selfSets each key not set yet.
Config::validateNotEmpty()
public function validateNotEmpty(array $keys): voidConfig::get()
public function get(string $key, mixed $default = null): mixedGateway class
final class Gateway implements GatewayInterface Gateway.php:16
A carrier's actions behind one door: the first action supporting a request answers it.
Gateway::__construct()
public function __construct(readonly string $name, readonly string $title, readonly array $actions)Gateway::getName()
public function getName(): stringGateway::getTitle()
public function getTitle(): stringGateway::supports()
public function supports(string $request): boolGateway::execute()
public function execute(Request\Request $request): Request\RequestGateway::rate()
public function rate(Shipment $shipment): arrayGateway::ship()
public function ship(Shipment $shipment): LabelGateway::track()
public function track(string $trackingNumber, string $locale = 'fr'): TrackingModelGateway::pickupPoints()
public function pickupPoints(Address $near, int $limit = 10, ?Parcel $parcel = null): arrayGateway::slip()
public function slip(string $trackingNumber, string $format = Label::PDF): LabelGateway::cancel()
public function cancel(string $trackingNumber): boolGatewayFactory class
abstract class GatewayFactory implements GatewayFactoryInterface GatewayFactory.php:20
The Payum way: a carrier's factory fills a Config - its name, title, the options it needs, its API client ("omnibus.api", a closure of the Config) and its actions ("omnibus.action.<name>") - and the gateway is those actions, the API handed to the ones that ask for it.
A "rates" option always gives a rating action from configuration (Action\ConfiguredRatingAction), unless the carrier rates by API.
GatewayFactory::__construct()
public function __construct(protected readonly ?HttpClientInterface $http = null)GatewayFactory::getName()
public function getName(): stringGatewayFactory::create()
public function create(array $options = []): GatewayInterfaceGatewayFactory::createConfig()
public function createConfig(array $options = []): ConfigGatewayFactoryInterface interface
interface GatewayFactoryInterface GatewayFactoryInterface.php:6
Builds a carrier's gateway from its options (credentials, sandbox, rates...).
GatewayFactoryInterface::getName()
public function getName(): stringThe name gateways are configured with: "mondial_relay", "colissimo".
..
GatewayFactoryInterface::create()
public function create(array $options = []): GatewayInterfaceGatewayInterface interface
interface GatewayInterface GatewayInterface.php:18
One carrier, configured: the same questions for all of them. Each typed method is a shortcut for execute() with its request.
GatewayInterface::getName()
public function getName(): stringGatewayInterface::getTitle()
public function getTitle(): stringGatewayInterface::supports()
public function supports(string $request): boolGatewayInterface::execute()
public function execute(Request $request): Request- Returns
answered
- Throws
Exception\RequestNotSupportedException
- Throws
Exception\CarrierException
GatewayInterface::rate()
public function rate(Shipment $shipment): array- Returns
cheapest first
GatewayInterface::ship()
public function ship(Shipment $shipment): LabelGatewayInterface::track()
public function track(string $trackingNumber, string $locale = 'fr'): Tracking$trackingNumberthe label's tracking number, or its carrierReference when it has one
GatewayInterface::pickupPoints()
public function pickupPoints(Address $near, int $limit = 10, ?Parcel $parcel = null): array- Returns
nearest first
GatewayInterface::slip()
public function slip(string $trackingNumber, string $format = Label::PDF): Label$trackingNumberthe label's tracking number, or its carrierReference when it has one
GatewayInterface::cancel()
public function cancel(string $trackingNumber): bool$trackingNumberthe label's tracking number, or its carrierReference when it has one
Registry class
final class Registry Registry.php:15
The shop's carriers by name, each built once from its factory and options:
new Registry([new MondialRelayGatewayFactory($http)], [ 'relais' => ['factory' => 'mondial_relay', 'options' => [...]], ]);
Registry::__construct()
public function __construct(iterable $factories, readonly array $config)Registry::get()
public function get(string $name): GatewayInterfaceRegistry::has()
public function has(string $name): boolRegistry::options()
public function options(string $name): array- Returns
the options a gateway is configured with
Registry::create()
public function create(string $name, array $overrides = []): GatewayInterfaceA gateway built afresh, its configured options with $overrides over them - keys typed in a back office, say. Not kept: get() still gives the configured one.
Registry::names()
public function names(): array- Returns
the configured gateways' names
Registry::all()
public function all(): arrayOmnibus\Action
ActionInterface interface
interface ActionInterface ActionInterface.php:8
One thing a carrier does: answers the requests it supports.
ActionInterface::supports()
public function supports(Request $request): boolActionInterface::execute()
public function execute(Request $request): voidSets the request's result, or throws Omnibus\Exception\CarrierException.
ApiAwareInterface interface
interface ApiAwareInterface ApiAwareInterface.php:6
An action that talks to the carrier through the gateway's API client.
ApiAwareInterface::setApi()
public function setApi(object $api): voidApiAwareTrait trait
trait ApiAwareTrait ApiAwareTrait.php:10
ApiAwareTrait::setApi()
public function setApi(object $api): voidConfiguredRatingAction class
final class ConfiguredRatingAction implements ActionInterface ConfiguredRatingAction.php:22
Prices from the gateway's configuration, for carriers that publish no rating API (the price is the shop's contract, not a public tariff).
rates: - { service: relay, label: 'Point relais', to_pickup_point: true, days: 4, currency: EUR, countries: [FR, BE], bands: { 500: 490, 1000: 590, 5000: 890 } } # up to grams => minor units
A band applies up to its weight, each parcel priced on its own; a parcel heavier than the last band, or a country not listed, gets no rate for that service.
ConfiguredRatingAction::__construct()
public function __construct(readonly string $carrier, readonly array $rates)ConfiguredRatingAction::supports()
public function supports(Request $request): boolConfiguredRatingAction::execute()
public function execute(Request $request): voidOmnibus\Bridge\Symfony
OmnibusBundle class
final class OmnibusBundle extends AbstractBundle OmnibusBundle.php:56
Omnibus in a Symfony application: the carrier packages installed (omnibus/offline, omnibus/mondial-relay, omnibus/colissimo, omnibus/ups... every omnibus/* package) registered, the shop's gateways built from configuration, Omnibus\Registry autowired, and each gateway injectable by its name:
omnibus: gateways: relais: { factory: mondial_relay, options: { enseigne: '%env(MONDIAL_RELAY_ENSEIGNE)%', private_key: '%env(MONDIAL_RELAY_PRIVATE_KEY)%' } } retrait: { factory: offline }
public function __construct(GatewayInterface $relais) }An application's own factories (a GatewayFactoryInterface) are registered too, autoconfigured.
OmnibusBundle::configure()
public function configure(DefinitionConfigurator $definition): voidOmnibusBundle::loadExtension()
public function loadExtension(array $config, ContainerConfigurator $container, ContainerBuilder $builder): voidOmnibus\Exception
CarrierException class
class CarrierException extends RuntimeException implements OmnibusException CarrierException.php:6
The carrier refused, or could not be reached.
public readonly string $carrierpublic readonly ?string $carrierCodeThe carrier's own error code, when it gave one
CarrierException::__construct()
public function __construct(public readonly string $carrier, string $message, public readonly ?string $carrierCode = null, ?\Throwable $previous = null)InvalidConfigException class
final class InvalidConfigException extends LogicException implements OmnibusException InvalidConfigException.php:6
A gateway misconfigured: a credential missing, an unknown factory.
OmnibusException interface
interface OmnibusException extends Throwable OmnibusException.php:6
Every exception Omnibus throws.
RequestNotSupportedException class
final class RequestNotSupportedException extends LogicException implements OmnibusException RequestNotSupportedException.php:8
The carrier does not do that (no pickup points, no cancellation...).
RequestNotSupportedException::for()
public static function for(Request $request, string $gateway): selfOmnibus\Http
Redaction class
final class Redaction Redaction.php:22
What a failed call may carry of its credentials, taken out before the failure leaves the package: an HTTP client's exception quotes the URL called (a key in its query, a password in its user part), and every exception's trace keeps the arguments of the calls under it (the request options, headers and query with the key) unless PHP runs with zend.exception_ignore_args.
copy() gives the previous exception to wrap instead of the client's own: the same class and code, its message with the key's parameters, the user part and every secret value replaced by ***, its trace without arguments, its own previous copied the same way. Properties of the client's class beyond those of \Exception are not copied (a Symfony HttpException's response, a PSR-18 exception's request: their URL holds the key). withoutArguments() takes the arguments out of the trace of the exception thrown in its place.
const MASK = '***'
Redaction::secrets()
public static function secrets(string $url, array $options = []): arrayThe secrets a request carries: the values of its query parameters, headers and body fields named as credentials (key, token, secret, password, signature, auth...), a bearer token, a basic password, the URL's user part.
$optionsthe HTTP client's options
Redaction::sensitive()
public static function sensitive(string $name): boolWhether a parameter, header or field of this name holds a credential.
Redaction::text()
public static function text(string $text, array $secrets = []): stringA text without credentials: in every address, the user part and the parameters named as credentials masked (api_key=***); then every secret given, raw or URL-encoded, masked wherever it stands.
Redaction::copy()
public static function copy(\Throwable $failure, array $secrets = []): \ThrowableA copy of a failure to wrap in its place: its class, code, file and line, its message through text(), its trace without arguments, its previous copied the same way.
Redaction::withoutArguments()
public static function withoutArguments(\Throwable $failure): \ThrowableThe failure given, the arguments out of its trace (and out of its previous ones'), as zend.exception_ignore_args would have left it.
Omnibus\Model
Address class
final readonly class Address Address.php:6
A postal address: the sender's, the recipient's, a pickup point's.
public string $namepublic array $streetone line each, most carriers take up to three
public string $postcodepublic string $citypublic string $countryISO 3166-1 alpha-2
public ?string $companypublic ?string $emailpublic ?string $phone
Address::__construct()
public function __construct(public string $name, public array $street, public string $postcode, public string $city, public string $country, public ?string $company = null, public ?string $email = null, public ?string $phone = null)$streetone line each, most carriers take up to three
Address::line()
public function line(int $index): stringLabel class
final readonly class Label Label.php:6
The shipping label (or slip) a carrier issued: its tracking number and the printable document.
const PDF = 'application/pdf'const ZPL = 'application/zpl'public string $carrierpublic string $trackingNumberpublic ?string $contentThe document itself, when the carrier sends it inline
public string $formatpublic ?string $urlOr where to download it, when the carrier hands out a link
public ?string $trackingUrlpublic ?string $carrierReferenceThe carrier's own handle on the booking, for the carriers whose later requests need more than the tracking number (Amazon: the shipment and carrier ids; SF Express: the order id). Opaque: keep it with the order and pass it to track(), slip() and cancel() in place of the tracking number. Null when the tracking number is enough.
Label::__construct()
public function __construct(public string $carrier, public string $trackingNumber, public ?string $content = null, public string $format = self::PDF, public ?string $url = null, public ?string $trackingUrl = null, public ?string $carrierReference = null)Parcel class
final readonly class Parcel Parcel.php:6
One box: its weight (grams), its size (centimetres), what it is worth (minor units).
public int $weightpublic ?int $lengthpublic ?int $widthpublic ?int $heightpublic ?int $valuepublic string $currencypublic ?string $reference
Parcel::__construct()
public function __construct(public int $weight, public ?int $length = null, public ?int $width = null, public ?int $height = null, public ?int $value = null, public string $currency = 'EUR', public ?string $reference = null)Parcel::girth()
public function girth(): ?intLongest side plus girth, in centimetres - what size bands are built on.
PickupPoint class
final readonly class PickupPoint PickupPoint.php:6
A relay, locker or post office a parcel can be sent to and collected from.
public string $carrierpublic string $idpublic string $namepublic Address $addresspublic ?float $latitudepublic ?float $longitudepublic array $openingHoursISO weekday (1 = Monday) => [[open, close], ...], "HH:MM"
public ?int $distanceMetres from the searched address, when the carrier says
PickupPoint::__construct()
public function __construct(public string $carrier, public string $id, public string $name, public Address $address, public ?float $latitude = null, public ?float $longitude = null, public array $openingHours = [], public ?int $distance = null)$openingHoursISO weekday (1 = Monday) => [[open, close], ...], "HH:MM"
Rate class
final readonly class Rate Rate.php:6
What a service costs for a shipment (minor units) and how long it takes.
public string $carrierpublic string $servicepublic string $labelpublic int $amountpublic string $currencypublic ?int $dayspublic bool $toPickupPoint
Rate::__construct()
public function __construct(public string $carrier, public string $service, public string $label, public int $amount, public string $currency = 'EUR', public ?int $days = null, public bool $toPickupPoint = false)Shipment class
final readonly class Shipment Shipment.php:9
What goes where: from the sender to the recipient - at home, or at a pickup point - in one or more parcels, under a carrier's service.
public Address $senderpublic Address $recipientpublic array $parcelspublic ?string $servicepublic ?string $pickupPointpublic ?string $referencepublic array $optionscarrier-specific (insurance, signature, instructions...)
public ?\DateTimeImmutable $shippingDate
Shipment::__construct()
public function __construct(public Address $sender, public Address $recipient, public array $parcels, public ?string $service = null, public ?string $pickupPoint = null, public ?string $reference = null, public array $options = [], public ?\DateTimeImmutable $shippingDate = null)$optionscarrier-specific (insurance, signature, instructions...)
Shipment::weight()
public function weight(): intGrams, all parcels together.
Shipment::option()
public function option(string $name, mixed $default = null): mixedTracking class
final readonly class Tracking Tracking.php:6
Where a parcel is: its latest status and every step so far, oldest first.
public string $carrierpublic string $trackingNumberpublic TrackingStatus $statuspublic array $events
Tracking::__construct()
public function __construct(public string $carrier, public string $trackingNumber, public TrackingStatus $status, public array $events = [])Tracking::latest()
public function latest(): ?TrackingEventTrackingEvent class
final readonly class TrackingEvent TrackingEvent.php:5
public \DateTimeImmutable $atpublic TrackingStatus $statuspublic string $descriptionpublic ?string $locationpublic ?string $codeThe carrier's own code, kept for whoever needs the detail
TrackingEvent::__construct()
public function __construct(public \DateTimeImmutable $at, public TrackingStatus $status, public string $description, public ?string $location = null, public ?string $code = null)TrackingStatus enum
enum TrackingStatus TrackingStatus.php:6
Every carrier's statuses, folded onto one scale.
case PENDING = 'pending'case IN_TRANSIT = 'in_transit'case OUT_FOR_DELIVERY = 'out_for_delivery'case AVAILABLE_FOR_PICKUP = 'available_for_pickup'case DELIVERED = 'delivered'case EXCEPTION = 'exception'case RETURNED = 'returned'case UNKNOWN = 'unknown'
TrackingStatus::isFinal()
public function isFinal(): boolOmnibus\Request
Cancel class
final class Cancel extends Request Cancel.php:6
Cancel a shipment not handed over yet. Result: true when the carrier voided it.
public readonly string $trackingNumber
Cancel::__construct()
public function __construct(public readonly string $trackingNumber)GetSlip class
final class GetSlip extends Request GetSlip.php:8
The label of a shipment booked earlier, again (a reprint). Result: the Label.
public readonly string $trackingNumberpublic readonly string $format
GetSlip::__construct()
public function __construct(public readonly string $trackingNumber, public readonly string $format = Label::PDF)GetSlip::getLabel()
public function getLabel(): ?LabelPaperless class
final class Paperless extends Request Paperless.php:13
Customs documents sent electronically (paperless trade) for a shipment leaving the customs union. Result: true once the carrier accepted them.
Part of the contract (and of the conformance suite) for the carriers that offer it; no carrier package answers it yet: supports(Paperless::class) is false for each of them, and execute() raises RequestNotSupportedException.
public readonly string $trackingNumberpublic readonly array $documentstype (invoice, proforma...) => PDF content
Paperless::__construct()
public function __construct(public readonly string $trackingNumber, public readonly array $documents)$documentstype (invoice, proforma...) => PDF content
Pickup class
final class Pickup extends Request Pickup.php:10
The pickup points near an address (that can take this parcel). Result: PickupPoint[]
public readonly Address $nearpublic readonly int $limitpublic readonly ?Parcel $parcel
Pickup::__construct()
public function __construct(public readonly Address $near, public readonly int $limit = 10, public readonly ?Parcel $parcel = null)Pickup::getPoints()
public function getPoints(): arrayRating class
final class Rating extends Request Rating.php:9
The services that can carry a shipment, and their price. Result: Rate[]
public readonly Shipment $shipment
Rating::__construct()
public function __construct(public readonly Shipment $shipment)Rating::getRates()
public function getRates(): arrayRequest class
abstract class Request Request.php:9
A question put to a gateway. The action that supports it answers by setting the result; the gateway hands the request back.
Request::setResult()
public function setResult(mixed $result): voidRequest::getResult()
public function getResult(): mixedRequest::isAnswered()
public function isAnswered(): boolShipping class
final class Shipping extends Request Shipping.php:9
Book the shipment with the carrier. Result: the Label.
public readonly Shipment $shipment
Shipping::__construct()
public function __construct(public readonly Shipment $shipment)Shipping::getLabel()
public function getLabel(): ?LabelTracking class
final class Tracking extends Request Tracking.php:8
Where is this parcel? Result: Model\Tracking
public readonly string $trackingNumberpublic readonly string $locale
Tracking::__construct()
public function __construct(public readonly string $trackingNumber, public readonly string $locale = 'fr')Tracking::getTracking()
public function getTracking(): ?TrackingModelOmnibus\Testing
Fixtures class
final class Fixtures Fixtures.php:14
Addresses and shipments for a carrier's tests: a shop in Paris sending to a customer (in France unless told otherwise). Shipped with the core so a carrier's tests run where the carrier is installed alone.
Fixtures::shop()
public static function shop(): AddressFixtures::customer()
public static function customer(string $country = 'FR'): AddressFixtures::shipment()
public static function shipment(int ...$grams): ShipmentOne parcel of 800 g unless weights (grams) are given, reference CMD-1042.
GatewayContractTests trait
trait GatewayContractTests GatewayContractTests.php:61
What every Omnibus gateway does, as PHPUnit tests a carrier runs against its own factory, offline: the carrier's API is replaced by its recorded answers (RecordedHttpClient), so no test reaches the network.
It checks that: - the factory's name is the name of the gateway it builds, and a Registry builds that gateway from {factory, options}; building it calls nothing; - each required option missing is an InvalidConfigException naming it; an operation that needs an option of its own (operationOptions()) is not supported without it, rather than failing when called; - supports() is what the gateway does, for each request: a supported one is answered with models that keep their invariants (the carrier's name, ids, amounts in minor units, ISO currencies and countries, rates cheapest first, pickup points nearest first and no more than asked, tracking events oldest first, a boolean for Cancel and Paperless), an unsupported one raises RequestNotSupportedException before any request is sent; - a "rates" option replaces the carrier's rating API: the configured price, no request; - every failure of the carrier - HTTP 401, 403, 404, 429, 500 and 503, a network error, a body it cannot read, a login refused - is a CarrierException naming the carrier, never an HTTP client's exception, a TypeError, or an answer made of nothing.
final class UpsContractTest extends TestCase { use GatewayContractTests;
protected function gatewayFactory(HttpClientInterface $http): GatewayFactoryInterface { return new UpsGatewayFactory($http); }
protected function gatewayOptions(): array { return ['client_id' => 'id', 'client_secret' => 's', 'account_number' => 'A1B2C3', 'sandbox' => true]; }
protected function recordedAnswers(): array { return ['/oauth/token' => ['access_token' => 't'], '/Shop' => [...], ...]; }
protected function sessionRoutes(): array { return ['/oauth/token']; }
}The hooks below (shipment, tracking number, documents...) have defaults a carrier overrides where it legitimately differs. Requires phpunit/phpunit (the carrier's, in require-dev) and symfony/http-client.
GatewayContractTests::testTheFactoryNamesTheGatewayItBuilds()
public function testTheFactoryNamesTheGatewayItBuilds(): voidGatewayContractTests::testTheRegistryBuildsTheGatewayFromItsConfiguration()
public function testTheRegistryBuildsTheGatewayFromItsConfiguration(): voidGatewayContractTests::testEachRequiredOptionIsRequired()
public function testEachRequiredOptionIsRequired(): voidGatewayContractTests::testRating()
public function testRating(): voidGatewayContractTests::testShipping()
public function testShipping(): voidGatewayContractTests::testTracking()
public function testTracking(): voidGatewayContractTests::testPickupPoints()
public function testPickupPoints(): voidGatewayContractTests::testSlip()
public function testSlip(): voidGatewayContractTests::testCancellation()
public function testCancellation(): voidGatewayContractTests::testPaperless()
public function testPaperless(): voidGatewayContractTests::testConfiguredRatesReplaceTheRatingApi()
public function testConfiguredRatesReplaceTheRatingApi(): voidGatewayContractTests::testTheCarriersFailuresAreCarrierExceptions()
public function testTheCarriersFailuresAreCarrierExceptions(): voidRecordedHttpClient class
final class RecordedHttpClient implements HttpClientInterface RecordedHttpClient.php:37
A carrier's recorded answers in place of its API: no request leaves the process. Each route is "METHOD fragment" or "fragment" (any method), matched when the request's URL contains the fragment - or, for "body:fragment", when its body does (a SOAP operation, say); the first route declared that matches answers.
new RecordedHttpClient([ 'POST /security/v1/oauth/token' => ['access_token' => 'tok', 'expires_in' => 14399], '/api/rating/' => file_get_contents(__DIR__.'/recorded/rate.json'), 'GET /label/' => RecordedHttpClient::answer('%PDF-1.4', 200, ['content-type' => 'application/pdf']), '/track/' => fn (string $method, string $url, array $options) => [...], 'POST body:<TrackRequest' => '<soap:Envelope>...</soap:Envelope>', ]);
An answer is an array (sent as JSON), a string (the body as it is), a MockResponse, or a closure of the request returning one of those. A request no route matches fails at the transport (the carrier sees a network error) and is listed by unanswered(), so a test can say which route is missing.
failing() gives the same client answering every request with one failure - an HTTP status, a network error, a body no carrier can read - except the routes kept (a login, say), for checking how a carrier reports its errors.
Requires symfony/http-client (a carrier calling an API has it already).
RecordedHttpClient::__construct()
public function __construct(readonly array $answers = [], readonly ?\Closure $failure = null, readonly array $kept = [])$answersroute => answer
$keptroutes that keep their answer while failing
RecordedHttpClient::answer()
public static function answer(array|string $body, int $status = 200, array $headers = []): MockResponseA response with its status and headers, for an answer that is not a plain 200.
RecordedHttpClient::networkError()
public static function networkError(string $message = 'Connection refused (recorded)'): MockResponseThe answer of a network that fails: no status, no body.
RecordedHttpClient::failing()
public function failing(MockResponse $failure, array $kept = []): selfThe same routes, every request but those of $kept answered with $failure.
RecordedHttpClient::request()
public function request(string $method, string $url, array $options = []): ResponseInterfaceRecordedHttpClient::stream()
public function stream(ResponseInterface|iterable $responses, ?float $timeout = null): ResponseStreamInterfaceRecordedHttpClient::withOptions()
public function withOptions(array $options): staticRecordedHttpClient::requests()
public function requests(): array- Returns
every request made, in order
RecordedHttpClient::unanswered()
public function unanswered(): array- Returns
"METHOD url" of each request no route answered