23-01-2026
This commit is contained in:
parent
a939cd51ef
commit
a8b395e20d
248 changed files with 29342 additions and 4805 deletions
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue