Installation:
composer require answear/acs-bundle
Manually add to config/bundles.php if Symfony Flex doesn’t auto-register:
Answear\AcsBundle\AnswearAcsBundle::class => ['all' => true],
Configuration:
Add credentials to config/packages/answear_acs.yaml:
answear_gls:
apiKey: "your_acs_api_key"
companyId: "your_company_id"
companyPassword: "your_company_password"
userId: "your_user_id"
userPassword: "your_user_password"
language: "GR" # Default: Greece
First Use Case: Fetch parcel shops in Greece (default language):
use Answear\AcsBundle\Service\ParcelShopsService;
use Answear\AcsBundle\Enum\CountryIdEnum;
$parcelShopService = $container->get(ParcelShopsService::class);
$shops = $parcelShopService->getList(CountryIdEnum::GREECE);
src/Service/ParcelShopsService.php (core logic).src/Response/DTO/ (response structure).src/Exception/ (error handling).config/packages/answear_acs.yaml (credentials).Dependency Injection:
Inject ParcelShopsService into controllers/services:
public function __construct(private ParcelShopsService $parcelShopService) {}
Filtering Shops:
Fetch shops by type (e.g., ACS_KIND_PARCEL_SHOP):
$shops = $parcelShopService->getList(CountryIdEnum::GREECE, ACS_KIND_PARCEL_SHOP);
Error Handling: Catch ACS-specific exceptions:
try {
$shops = $parcelShopService->getList(CountryIdEnum::CYPRUS);
} catch (ServiceUnavailable $e) {
Log::error("ACS API unavailable: " . $e->getMessage());
return response()->view('errors/503');
} catch (MalformedResponse $e) {
Log::error("Invalid ACS response: " . $e->getMessage());
}
Configuration Overrides:
Override defaults in environment (e.g., .env):
ANSWEAR_ACS_LANGUAGE=EN
ANSWEAR_ACS_TIMEOUT=30
E-commerce Integration:
getList() to populate a dropdown of ACS pickup locations.$countries = [CountryIdEnum::GREECE, CountryIdEnum::CYPRUS];
$shopsByCountry = collect($countries)->map(fn($country) =>
$parcelShopService->getList($country)
);
Logistics Dashboard:
$shops = Cache::remember("acs_shops_{$country->value}", now()->addHours(6), function() use ($country) {
return $parcelShopService->getList($country);
});
Multi-Carrier Comparison:
$allShops = [
'acs' => $parcelShopService->getList(CountryIdEnum::GREECE),
'dhl' => $dhlService->getLocations(),
];
Laravel Adaptation:
HttpClient with Laravel’s Http:
// In ParcelShopsService, replace Guzzle with:
$response = Http::withHeaders([
'Authorization' => 'Basic ' . base64_encode($apiKey . ':' . $companyPassword),
])->get($acsUrl);
DTO Serialization:
Spatie\ArrayToObject for DTOs:
use Spatie\ArrayToObject\ArrayToObject;
$shops = ArrayToObject::convert($rawResponse);
Testing:
ParcelShopsService in Laravel tests:
$this->mock(ParcelShopsService::class)->shouldReceive('getList')
->once()->andReturn([new ParcelShopDTO()]);
Rate Limiting:
throttle middleware:
Route::middleware(['throttle:10,1'])->group(function() {
Route::get('/acs/shops', [ShopController::class, 'index']);
});
Country Limitations:
GR) and Cyprus (CY). Attempting other countries may return empty results or errors.ParcelShopsService:
if (!in_array($countryId->value, [CountryIdEnum::GREECE->value, CountryIdEnum::CYPRUS->value])) {
throw new \InvalidArgumentException("Unsupported country for ACS");
}
Authentication Quirks:
companyId, companyPassword) and user credentials (userId, userPassword).answear_acs.yaml:
answear_gls:
companyId: "12345" # Not userId!
companyPassword: "secure_pass"
userId: "user123"
userPassword: "user_pass"
Response Parsing:
MalformedResponse exception hides these issues.try {
$shops = $parcelShopService->getList(CountryIdEnum::GREECE);
} catch (MalformedResponse $e) {
Log::debug("Raw ACS response: " . $e->getRawResponse());
}
Timeouts:
answear_gls:
timeout: 60 # seconds
Or via Laravel’s HTTP client:
Http::timeout(60)->get($acsUrl);
Enum Mismatches:
CountryIdEnum uses GR/CY, but ACS might expect GR/CY or EL/CY.ParcelShopsService:
$countryCode = match($countryId->value) {
CountryIdEnum::GREECE->value => 'GR',
CountryIdEnum::CYPRUS->value => 'CY',
default => throw new \InvalidArgumentException("Unsupported country"),
};
Enable Guzzle Logging:
Add to config/services.php:
'http' => [
'timeout' => 30,
'debug' => env('APP_DEBUG'), // Logs requests/responses
],
Check ACS API Status:
Route::get('/acs/health', function() {
try {
$parcelShopService->getList(CountryIdEnum::GREECE, limit: 1);
return response()->json(['status' => 'healthy']);
} catch (\Exception $e) {
return response()->json(['status' => 'unhealthy', 'error' => $e->getMessage()], 503);
}
});
Validate Credentials:
GET https://api.acs.gr/parcelshops?country=GR
Headers:
Authorization: Basic {base64(apiKey:companyPassword)}
X-User: userId
X-Password: userPassword
Language Default:
GR (Greek). Override in config:
answear_gls:
language: "EN" # English responses
Missing Fields:
openingHours). The bundle’s DTOs areHow can I help you explore Laravel packages today?