johnpaulmedina/laravel-usps
Laravel-USPS is a Laravel integration for the USPS API that makes it easy to fetch shipping rates, track packages, validate addresses, and generate labels. It wraps USPS web tools in a clean, config-driven package with simple methods you can call from anywhere in your app.
Install and publish config
composer require <vendor>/<package>
php artisan vendor:publish --tag=<package>-config
Set credentials in .env (USPS user ID / OAuth client credentials, sandbox flag). Confirm config/<package>.php points at the sandbox endpoint for local work.
Read the README first, then the DPV table. The README explains how Delivery Point Validation works, so if you're validating addresses you know what a DPV confirmation actually guarantees before you build logic around it.
Smoke-test from tinker:
use <Vendor>\<Package>\Facades\<PackageFacade>;
<PackageFacade>::validateAddress([
'streetAddress' => '123 Main St',
'city' => 'Springfield',
'state' => 'IL',
'ZIPCode' => '62704',
]);
Then try the city/state lookup and ZIP lookup endpoints. These are the three flows covered in the new docs response examples — use them as your copy/paste fixtures.
First real use case: validate a customer address at checkout, then use the returned standardized address and ZIP+4 to quote shipping via the shipping options endpoint.
Wrap calls behind a thin service layer. The facade is convenient in controllers, but most teams inject a small AddressService / ShippingService that wraps the facade so you can swap in fakes and centralize error handling.
Validation → normalization → quoting chain:
$validated = $this->addressService->validate($input);
if (! $validated->isConfirmed()) {
// surface suggested correction to the user before continuing
}
$options = $this->shippingService->optionsFor($validated->normalized());
Cache lookup results. ZIP/city-state lookups are effectively static data. Cache aggressively (24h+ keyed by normalized input) and always cache negative results briefly to avoid hammering the API on malformed user input.
Integrate validation as a form request rule or a queue job. For checkout, validate synchronously but degrade gracefully — a USPS timeout should not block the sale. For bulk imports, push validation onto a queue with retries and record per-row outcomes.
Use the response DTOs, not raw arrays. The release tightened PHPDoc on ShippingOptions and the apiPost return types, so prefer typed accessors over array offsets; that keeps PHPStan happy in your own code too.
Test with fixtures. The new docs include response examples for validation, city/state, and ZIP lookup — copy them into tests/fixtures and bind a fake HTTP client so your test suite never touches the network.
apiPost.Http::fake() over mocking the facade — it exercises the real serialization path.How can I help you explore Laravel packages today?