23-01-2026

This commit is contained in:
Kevin Adametz 2026-01-23 17:35:23 +01:00
parent a939cd51ef
commit a8b395e20d
248 changed files with 29342 additions and 4805 deletions

View file

@ -2,13 +2,13 @@
namespace Acme\Dhl\Support;
use Illuminate\Support\Facades\Http;
use Illuminate\Http\Client\RequestException;
use Illuminate\Http\Client\ConnectionException;
use Acme\Dhl\Exceptions\DhlApiException;
use Acme\Dhl\Exceptions\DhlAuthenticationException;
use Acme\Dhl\Exceptions\DhlValidationException;
use Exception;
use Illuminate\Http\Client\ConnectionException;
use Illuminate\Http\Client\RequestException;
use Illuminate\Support\Facades\Http;
use Illuminate\Support\Facades\Log;
/**
@ -34,11 +34,12 @@ class DhlClient
/**
* Make HTTP request to DHL API
*
* @param string $method HTTP method (get, post, put, delete)
* @param string $uri API endpoint URI
* @param array $payload Request body data
* @param array $query Query parameters
* @param string $method HTTP method (get, post, put, delete)
* @param string $uri API endpoint URI
* @param array $payload Request body data
* @param array $query Query parameters
* @return array Response data as array
*
* @throws Exception When API request fails or returns error
*/
public function request(string $method, string $uri, array $payload = [], array $query = []): array
@ -59,14 +60,16 @@ class DhlClient
CURLOPT_CONNECTTIMEOUT => config('dhl.ssl.connect_timeout', 10),
CURLOPT_TIMEOUT => config('dhl.ssl.timeout', 30),
CURLOPT_USERAGENT => 'acme-laravel-dhl/1.0',
]
],
])
->retry(3, 300, function ($exception, $attempt) {
if ($exception instanceof RequestException && $exception->response->status() === 429) {
$delay = min(1000000 * $attempt, 10000000); // Max 10 seconds
usleep($delay); // Microseconds
return true;
}
return $exception instanceof ConnectionException ||
($exception instanceof RequestException && in_array($exception->response->status(), [500, 502, 503, 504]));
}, false);
@ -79,7 +82,7 @@ class DhlClient
// Make the request
$response = match (strtolower($method)) {
'get' => $request->get($uri, $query),
'post' => $request->post($uri . '?' . http_build_query($query), $payload),
'post' => $request->post($uri.'?'.http_build_query($query), $payload),
'put' => $request->put($uri, $payload),
'delete' => $request->delete($uri),
default => throw new Exception("Unsupported HTTP method: {$method}")
@ -96,7 +99,7 @@ class DhlClient
'response_body' => $response->body(),
'response_json' => $response->json(),
'status_code' => $response->status(),
'headers' => $response->headers()
'headers' => $response->headers(),
]);
}
@ -125,7 +128,7 @@ class DhlClient
$headers = [
'Accept' => 'application/json',
'Content-Type' => 'application/json',
'User-Agent' => 'acme-laravel-dhl/1.0'
'User-Agent' => 'acme-laravel-dhl/1.0',
];
if ($this->apiKey) {
@ -150,7 +153,7 @@ class DhlClient
$status === 403 => throw new DhlAuthenticationException("DHL API access forbidden: {$errorMessage}"),
$status === 404 => throw new DhlApiException("DHL API endpoint not found: {$method} {$uri}"),
$status === 422 => throw new DhlValidationException("DHL API validation error: {$errorMessage}"),
$status === 429 => throw new DhlApiException("DHL API rate limit exceeded. Please try again later."),
$status === 429 => throw new DhlApiException('DHL API rate limit exceeded. Please try again later.'),
$status >= 500 => throw new DhlApiException("DHL API server error: {$errorMessage}"),
default => throw new DhlApiException("DHL API error ({$status}): {$errorMessage}")
};
@ -158,20 +161,48 @@ class DhlClient
/**
* Extract error message from DHL API response
*
* DHL API v2 returns errors in various formats:
* - {status: {detail: "..."}}
* - {items: [{sstatus: {detail: "..."}}]}
* - {items: [{validationMessages: [{...}]}]}
*/
private function extractErrorMessage(?array $body): ?string
{
if (!$body) {
if (! $body) {
return null;
}
// Try different possible error message fields
return $body['message']
// Try different possible error message fields for DHL API v2
$message = $body['message']
?? $body['error']
?? $body['detail']
?? data_get($body, 'status.detail')
?? data_get($body, 'status.title')
?? data_get($body, 'errors.0.message')
?? data_get($body, 'error.message')
?? data_get($body, 'items.0.sstatus.detail')
?? data_get($body, 'items.0.sstatus.title')
?? null;
// Check for validation messages in items
if (! $message && isset($body['items'][0]['validationMessages'])) {
$validationMessages = $body['items'][0]['validationMessages'];
if (is_array($validationMessages) && ! empty($validationMessages)) {
$messages = [];
foreach ($validationMessages as $vm) {
$vmMessage = $vm['validationMessage'] ?? $vm['message'] ?? $vm['property'] ?? null;
if ($vmMessage) {
$messages[] = $vmMessage;
}
}
if (! empty($messages)) {
$message = implode('; ', $messages);
}
}
}
return $message;
}
/**
@ -202,9 +233,9 @@ class DhlClient
'server_software' => $_SERVER['SERVER_SOFTWARE'] ?? 'Unknown',
'dhl_config' => [
'base_url' => $this->baseUrl,
'has_api_key' => !empty($this->apiKey),
'has_username' => !empty($this->username),
'has_password' => !empty($this->password),
'has_api_key' => ! empty($this->apiKey),
'has_username' => ! empty($this->username),
'has_password' => ! empty($this->password),
'ssl_verify_peer' => config('dhl.ssl.verify_peer', true),
'ssl_verify_host' => config('dhl.ssl.verify_host', true),
'ssl_version' => config('dhl.ssl.ssl_version', 'TLSv1_2'),
@ -215,7 +246,7 @@ class DhlClient
'APP_ENV' => config('app.env'),
'APP_DEBUG' => config('app.debug'),
'APP_URL' => config('app.url'),
]
],
];
$this->getDhlLogger()->info('DHL Server Environment Debug Info', $info);
@ -235,14 +266,14 @@ class DhlClient
$methods = [
'method1' => 'Laravel HTTP with enhanced SSL',
'method2' => 'Laravel HTTP with relaxed SSL',
'method3' => 'Direct cURL fallback'
'method3' => 'Direct cURL fallback',
];
foreach ($methods as $methodKey => $methodName) {
try {
$this->getDhlLogger()->info("DHL API connection test - trying {$methodName}", [
'method' => $methodKey,
'base_url' => $this->baseUrl
'base_url' => $this->baseUrl,
]);
$success = $this->testConnectionWithMethod($methodKey);
@ -250,23 +281,25 @@ class DhlClient
if ($success) {
$this->getDhlLogger()->info("DHL API connection test successful with {$methodName}", [
'method' => $methodKey,
'base_url' => $this->baseUrl
'base_url' => $this->baseUrl,
]);
return true;
}
} catch (Exception $e) {
$this->getDhlLogger()->warning("DHL API connection test failed with {$methodName}", [
'method' => $methodKey,
'error' => $e->getMessage(),
'base_url' => $this->baseUrl
'base_url' => $this->baseUrl,
]);
}
}
$this->getDhlLogger()->error('DHL API connection test failed with all methods', [
'base_url' => $this->baseUrl,
'tried_methods' => array_keys($methods)
'tried_methods' => array_keys($methods),
]);
return false;
}
@ -310,7 +343,7 @@ class DhlClient
];
// Only use HTTP/2 for newer cURL versions
if (!$isOldCurl && defined('CURL_HTTP_VERSION_2_0')) {
if (! $isOldCurl && defined('CURL_HTTP_VERSION_2_0')) {
$curlOptions[CURLOPT_HTTP_VERSION] = CURL_HTTP_VERSION_2_0;
} else {
$curlOptions[CURLOPT_HTTP_VERSION] = CURL_HTTP_VERSION_1_1;
@ -327,11 +360,11 @@ class DhlClient
// Log complete cURL request details
$this->getDhlLogger()->info('DHL Enhanced Connection Test - Complete Request Details', [
'method' => 'Enhanced SSL',
'url' => $this->baseUrl . '/',
'url' => $this->baseUrl.'/',
'headers' => $this->buildHeaders(),
'auth' => [
'username' => $this->username,
'password' => '***hidden***'
'password' => '***hidden***',
],
'curl_options' => $this->formatCurlOptions($curlOptions),
'timeout' => 10,
@ -339,7 +372,7 @@ class DhlClient
'verify_peer' => config('dhl.ssl.verify_peer', true),
'verify_host' => config('dhl.ssl.verify_host', true),
'ssl_version' => config('dhl.ssl.ssl_version', 'TLSv1_2'),
]
],
]);
$response = Http::baseUrl($this->baseUrl)
@ -349,7 +382,7 @@ class DhlClient
->withOptions([
'verify' => config('dhl.ssl.verify_peer', true),
'http_errors' => false,
'curl' => $curlOptions
'curl' => $curlOptions,
])
->get('/');
@ -358,7 +391,7 @@ class DhlClient
'status_code' => $response->status(),
'headers' => $response->headers(),
'body' => $response->body(),
'success' => $this->validateResponse($response)
'success' => $this->validateResponse($response),
]);
return $this->validateResponse($response);
@ -400,11 +433,11 @@ class DhlClient
// Log complete cURL request details
$this->getDhlLogger()->info('DHL Relaxed Connection Test - Complete Request Details', [
'method' => 'Relaxed SSL',
'url' => $this->baseUrl . '/',
'url' => $this->baseUrl.'/',
'headers' => $this->buildHeaders(),
'auth' => [
'username' => $this->username,
'password' => '***hidden***'
'password' => '***hidden***',
],
'curl_options' => $this->formatCurlOptions($curlOptions),
'timeout' => 15,
@ -412,7 +445,7 @@ class DhlClient
'verify_peer' => false,
'verify_host' => false,
'ssl_version' => 'DEFAULT',
]
],
]);
$response = Http::baseUrl($this->baseUrl)
@ -422,7 +455,7 @@ class DhlClient
->withOptions([
'verify' => false, // Disable SSL verification as fallback
'http_errors' => false,
'curl' => $curlOptions
'curl' => $curlOptions,
])
->get('/');
@ -431,7 +464,7 @@ class DhlClient
'status_code' => $response->status(),
'headers' => $response->headers(),
'body' => $response->body(),
'success' => $this->validateResponse($response)
'success' => $this->validateResponse($response),
]);
return $this->validateResponse($response);
@ -445,16 +478,16 @@ class DhlClient
$ch = curl_init();
$curlOptions = [
CURLOPT_URL => $this->baseUrl . '/',
CURLOPT_URL => $this->baseUrl.'/',
CURLOPT_RETURNTRANSFER => true,
CURLOPT_TIMEOUT => 15,
CURLOPT_CONNECTTIMEOUT => 15,
CURLOPT_HTTPHEADER => [
'Accept: application/json',
'User-Agent: acme-laravel-dhl/1.0'
'User-Agent: acme-laravel-dhl/1.0',
],
CURLOPT_HTTPAUTH => CURLAUTH_BASIC,
CURLOPT_USERPWD => $this->username . ':' . $this->password,
CURLOPT_USERPWD => $this->username.':'.$this->password,
CURLOPT_SSL_VERIFYPEER => config('dhl.ssl.verify_peer', true),
CURLOPT_SSL_VERIFYHOST => config('dhl.ssl.verify_host', true) ? 2 : 0,
CURLOPT_SSLVERSION => $this->getSslVersion(),
@ -467,15 +500,15 @@ class DhlClient
// Log complete cURL request details
$this->getDhlLogger()->info('DHL Direct cURL Connection Test - Complete Request Details', [
'method' => 'Direct cURL',
'url' => $this->baseUrl . '/',
'url' => $this->baseUrl.'/',
'headers' => [
'Accept: application/json',
'User-Agent: acme-laravel-dhl/1.0'
'User-Agent: acme-laravel-dhl/1.0',
],
'auth' => [
'username' => $this->username,
'password' => '***hidden***',
'auth_type' => 'CURLAUTH_BASIC'
'auth_type' => 'CURLAUTH_BASIC',
],
'curl_options' => $this->formatCurlOptions($curlOptions),
'timeout' => 15,
@ -483,7 +516,7 @@ class DhlClient
'verify_peer' => config('dhl.ssl.verify_peer', true),
'verify_host' => config('dhl.ssl.verify_host', true),
'ssl_version' => config('dhl.ssl.ssl_version', 'TLSv1_2'),
]
],
]);
curl_setopt_array($ch, $curlOptions);
@ -507,7 +540,7 @@ class DhlClient
'curl_info' => $curlInfo,
'verbose_output' => $verboseOutput,
'curl_error' => $error,
'success' => $httpCode >= 200 && $httpCode < 500
'success' => $httpCode >= 200 && $httpCode < 500,
]);
if ($error) {
@ -583,11 +616,13 @@ class DhlClient
{
if ($response->status() === 401) {
$this->getDhlLogger()->error('DHL API authentication failed: Invalid username/password');
return false;
}
if ($response->status() === 403 && str_contains($response->body(), 'api-key')) {
$this->getDhlLogger()->error('DHL API authentication failed: Invalid API key');
return false;
}