Carrier Integration Architecture
Shipping Integration Flow
┌─────────────┠┌──────────────────┠┌─────────────â”
│ Magento │◄───►│ Shipping │◄───►│ FedEx/UPS/ │
│ 2 Store │ │ Gateway │ │ DHL APIs │
└─────────────┘ └──────────────────┘ └─────────────┘
│ │ │
Checkout Rate Calculation Live Rates
Shipment Label Generation Tracking
Tracking Address Validation Delivery Dates
Carrier Gateway Interface
namespace Vendor\Shipping\Gateway;
interface CarrierGatewayInterface
{
/**
* Get real-time shipping rates
*/
public function getRates(RateRequest $request): RateResponse;
/**
* Generate shipping label
*/
public function createShipment(ShipmentRequest $request): LabelResponse;
/**
* Track shipment
*/
public function track(string $trackingNumber): TrackingResponse;
/**
* Validate address
*/
public function validateAddress(Address $address): AddressValidationResponse;
}
FedEx Adapter
namespace Vendor\Shipping\Gateway\FedEx;
class FedExGateway implements CarrierGatewayInterface
{
private FedExClient $client;
private ConfigInterface $config;
public function getRates(RateRequest $request): RateResponse
{
$response = $this->client->request('rates', [
'accountNumber' => $this->config->getAccountNumber(),
'requestedShipment' => [
'shipper' => $this->mapAddress($request->getShipper()),
'recipient' => $this->mapAddress($request->getRecipient()),
'packageCount' => count($request->getPackages()),
'packages' => $this->mapPackages($request->getPackages()),
'rateRequestType' => ['LIST', 'ACCOUNT'],
],
]);
return $this->mapRates($response);
}
public function createShipment(ShipmentRequest $request): LabelResponse
{
$response = $this->client->request('ship', [
'accountNumber' => $this->config->getAccountNumber(),
'requestedShipment' => [
'shipper' => $this->mapAddress($request->getShipper()),
'recipient' => $this->mapAddress($request->getRecipient()),
'serviceType' => $request->getServiceType(),
'packagingType' => $request->getPackagingType(),
'packages' => $this->mapPackages($request->getPackages()),
'labelSpecification' => [
'labelFormatType' => 'PDF',
'imageType' => 'PDF',
],
],
]);
return new LabelResponse([
'tracking_number' => $response['output']['completeTrackResults'][0]['trackResults'][0]['trackingNumber'],
'label_url' => $response['output']['completeTrackResults'][0]['trackResults'][0]['label']['url'],
]);
}
}
Rate Calculation
Multi-Carrier Rate Aggregation
namespace Vendor\Shipping\Gateway\Aggregator;
class RateAggregator
{
private array $carriers;
public function __construct(array $carriers)
{
$this->carriers = $carriers;
}
public function getRates(RateRequest $request): AggregatedRates
{
$allRates = [];
foreach ($this->carriers as $carrierCode => $carrier) {
try {
$rates = $carrier->getRates($request);
foreach ($rates->getRates() as $rate) {
$rate->setCarrier($carrierCode);
$allRates[] = $rate;
}
} catch (\Exception $e) {
// Log and skip failed carrier
continue;
}
}
// Sort by price
usort($allRates, fn($a, $b) => $a->getPrice() <=> $b->getPrice());
return new AggregatedRates($allRates);
}
}
Rate Caching
namespace Vendor\Shipping\Gateway\Cache;
class RateCache
{
private CacheInterface $cache;
private int $ttl = 300; // 5 minutes
public function getRates(RateRequest $request): ?RateResponse
{
$cacheKey = $this->buildCacheKey($request);
$cached = $this->cache->load($cacheKey);
if ($cached) {
return unserialize($cached);
}
return null;
}
public function saveRates(RateRequest $request, RateResponse $response): void
{
$cacheKey = $this->buildCacheKey($request);
$this->cache->save(serialize($response), $cacheKey, [], $this->ttl);
}
private function buildCacheKey(RateRequest $request): string
{
return 'shipping_rates_' . md5(serialize([
$request->getShipper(),
$request->getRecipient(),
$request->getPackages(),
]));
}
}
Tracking Integration
Tracking Service
namespace Vendor\Shipping\Tracking;
class TrackingService
{
private array $carriers;
private TrackingRepositoryInterface $trackingRepo;
public function track(string $carrierCode, string $trackingNumber): TrackingInfo
{
$carrier = $this->getCarrier($carrierCode);
$response = $carrier->track($trackingNumber);
// Save to database
$this->trackingRepo->save(new TrackingData([
'carrier_code' => $carrierCode,
'tracking_number' => $trackingNumber,
'status' => $response->getStatus(),
'status_description' => $response->getStatusDescription(),
'estimated_delivery' => $response->getEstimatedDelivery(),
'events' => $response->getEvents(),
]));
return $response;
}
}
Tracking API Endpoint
<route url="/V1/tracking/:carrier/:number" method="GET">
<service class="Vendor\Shipping\Api\TrackingInterface" method="getTrackingInfo"/>
<resources>
<resource ref="anonymous"/>
</resources>
</route>
namespace Vendor\Shipping\Api;
interface TrackingInterface
{
public function getTrackingInfo(string $carrierCode, string $trackingNumber): TrackingDataInterface;
}
Address Validation
Address Validation Integration
namespace Vendor\Shipping\AddressValidation;
class AddressValidator
{
private array $validators;
public function validate(AddressInterface $address): ValidationResult
{
$errors = [];
$suggestions = [];
foreach ($this->validators as $validator) {
$result = $validator->validate($address);
if (!$result->isValid()) {
$errors = array_merge($errors, $result->getErrors());
}
if ($result->hasSuggestions()) {
$suggestions = array_merge($suggestions, $result->getSuggestions());
}
}
return new ValidationResult([
'valid' => empty($errors),
'errors' => $errors,
'suggestions' => $suggestions,
]);
}
}
FedEx Address Validation
namespace Vendor\Shipping\AddressValidation\FedEx;
class FedExAddressValidator implements ValidatorInterface
{
public function validate(AddressInterface $address): ValidationResult
{
$response = $this->client->request('address/validation', [
'addresses' => [[
'streetLines' => $address->getStreet(),
'city' => $address->getCity(),
'stateOrProvinceCode' => $address->getRegionCode(),
'postalCode' => $address->getPostcode(),
'countryCode' => $address->getCountryId(),
]],
]);
$result = $response['output']['parsedResults'][0];
return new ValidationResult([
'valid' => $result['classification'] !== 'ERROR',
'suggestions' => $this->mapSuggestions($result),
]);
}
}
Quiz
1. What does a rate aggregator do?
2. Why cache shipping rates?
3. What is address validation used for?
Flashcards
Question
What does a carrier gateway provide?
Click to reveal answer
Answer
Rates, labels, tracking, address validation
Question
How does rate aggregation work?
Click to reveal answer
Answer
Query multiple carriers, combine and sort results
Question
What is rate caching?
Click to reveal answer
Answer
Storing API responses to avoid repeated calls
Question
What is address validation?
Click to reveal answer
Answer
Verifying addresses are deliverable before shipping
Revision Notes
Key Takeaways
- 1. Carrier adapters implement standardized gateway interfaces
- 2. Rate aggregation combines results from multiple carriers
- 3. Rate caching reduces API calls and improves checkout speed
- 4. Tracking integration provides real-time shipment status
- 5. Address validation prevents delivery failures
Interview Tips
- • Explain how multi-carrier rate aggregation works
- • Discuss caching strategies for shipping rates
- • Describe the tracking update flow
- • Talk about handling carrier API failures
Cheat Sheet
Shipping Integration:
getRates() → live shipping rates
createShipment() → generate labels
track() → shipment tracking
validateAddress() → verify address
Rate Aggregation:
Query all carriers → combine → sort
Cache for 5 minutes (TTL)
Tracking:
Polling: cron checks status
Webhooks: carrier pushes updates