feat(06-sonarqube-quality): introduce typed exception hierarchy (S112 fix)

Replace 86+ generic RuntimeException throws with domain-specific exception
classes: AllegroApiException, AllegroOAuthException, ApaczkaApiException,
ShipmentException, IntegrationConfigException — all extending OrderProException
extends RuntimeException. Existing catch(RuntimeException) blocks unaffected.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-03-13 11:04:52 +01:00
parent 3a9cfcd4a2
commit 3c27c4e54a
21 changed files with 141 additions and 87 deletions

View File

@@ -0,0 +1,8 @@
<?php
declare(strict_types=1);
namespace App\Core\Exceptions;
class AllegroApiException extends OrderProException
{
}

View File

@@ -0,0 +1,8 @@
<?php
declare(strict_types=1);
namespace App\Core\Exceptions;
class AllegroOAuthException extends AllegroApiException
{
}

View File

@@ -0,0 +1,8 @@
<?php
declare(strict_types=1);
namespace App\Core\Exceptions;
class ApaczkaApiException extends OrderProException
{
}

View File

@@ -0,0 +1,8 @@
<?php
declare(strict_types=1);
namespace App\Core\Exceptions;
class IntegrationConfigException extends OrderProException
{
}

View File

@@ -0,0 +1,8 @@
<?php
declare(strict_types=1);
namespace App\Core\Exceptions;
class OrderProException extends \RuntimeException
{
}

View File

@@ -0,0 +1,8 @@
<?php
declare(strict_types=1);
namespace App\Core\Exceptions;
class ShipmentException extends OrderProException
{
}

View File

@@ -3,7 +3,7 @@ declare(strict_types=1);
namespace App\Modules\Settings;
use RuntimeException;
use App\Core\Exceptions\AllegroApiException;
final class AllegroApiClient
{
@@ -14,7 +14,7 @@ final class AllegroApiClient
{
$safeId = rawurlencode(trim($checkoutFormId));
if ($safeId === '') {
throw new RuntimeException('Brak ID zamowienia Allegro do pobrania.');
throw new AllegroApiException('Brak ID zamowienia Allegro do pobrania.');
}
$url = rtrim($this->apiBaseUrl($environment), '/') . '/order/checkout-forms/' . $safeId;
@@ -45,7 +45,7 @@ final class AllegroApiClient
{
$safeId = rawurlencode(trim($checkoutFormId));
if ($safeId === '') {
throw new RuntimeException('Brak ID zamowienia Allegro do pobrania przesylek.');
throw new AllegroApiException('Brak ID zamowienia Allegro do pobrania przesylek.');
}
$url = rtrim($this->apiBaseUrl($environment), '/') . '/order/checkout-forms/' . $safeId . '/shipments';
@@ -61,7 +61,7 @@ final class AllegroApiClient
{
$safeId = rawurlencode(trim($offerId));
if ($safeId === '') {
throw new RuntimeException('Brak ID oferty Allegro do pobrania.');
throw new AllegroApiException('Brak ID oferty Allegro do pobrania.');
}
$url = rtrim($this->apiBaseUrl($environment), '/') . '/sale/product-offers/' . $safeId;
@@ -163,7 +163,7 @@ final class AllegroApiClient
$ch = curl_init($url);
if ($ch === false) {
throw new RuntimeException('Nie udalo sie zainicjowac polaczenia z API Allegro.');
throw new AllegroApiException('Nie udalo sie zainicjowac polaczenia z API Allegro.');
}
curl_setopt_array($ch, [
@@ -185,16 +185,16 @@ final class AllegroApiClient
$ch = null;
if ($responseBody === false) {
throw new RuntimeException('Blad polaczenia z API Allegro: ' . $curlError);
throw new AllegroApiException('Blad polaczenia z API Allegro: ' . $curlError);
}
$json = json_decode((string) $responseBody, true);
if (!is_array($json)) {
throw new RuntimeException('Nieprawidlowy JSON odpowiedzi API Allegro.');
throw new AllegroApiException('Nieprawidlowy JSON odpowiedzi API Allegro.');
}
if ($httpCode === 401) {
throw new RuntimeException('ALLEGRO_HTTP_401');
throw new AllegroApiException('ALLEGRO_HTTP_401');
}
if ($httpCode < 200 || $httpCode >= 300) {
@@ -212,7 +212,7 @@ final class AllegroApiClient
if ($message === '') {
$message = 'Blad API Allegro.';
}
throw new RuntimeException('API Allegro HTTP ' . $httpCode . ': ' . $message);
throw new AllegroApiException('API Allegro HTTP ' . $httpCode . ': ' . $message);
}
return $json;
@@ -227,7 +227,7 @@ final class AllegroApiClient
$ch = curl_init($url);
if ($ch === false) {
throw new RuntimeException('Nie udalo sie zainicjowac polaczenia z API Allegro.');
throw new AllegroApiException('Nie udalo sie zainicjowac polaczenia z API Allegro.');
}
curl_setopt_array($ch, [
@@ -249,21 +249,21 @@ final class AllegroApiClient
$ch = null;
if ($responseBody === false) {
throw new RuntimeException('Blad polaczenia z API Allegro: ' . $curlError);
throw new AllegroApiException('Blad polaczenia z API Allegro: ' . $curlError);
}
if ($httpCode === 401) {
throw new RuntimeException('ALLEGRO_HTTP_401');
throw new AllegroApiException('ALLEGRO_HTTP_401');
}
if ($httpCode === 204) {
throw new RuntimeException('Brak etykiety dla podanej przesylki.');
throw new AllegroApiException('Brak etykiety dla podanej przesylki.');
}
if ($httpCode < 200 || $httpCode >= 300) {
$json = json_decode((string) $responseBody, true);
$message = is_array($json) ? trim((string) ($json['message'] ?? 'Blad API Allegro.')) : 'Blad API Allegro.';
throw new RuntimeException('API Allegro HTTP ' . $httpCode . ': ' . $message);
throw new AllegroApiException('API Allegro HTTP ' . $httpCode . ': ' . $message);
}
return (string) $responseBody;
@@ -276,7 +276,7 @@ final class AllegroApiClient
{
$ch = curl_init($url);
if ($ch === false) {
throw new RuntimeException('Nie udalo sie zainicjowac polaczenia z API Allegro.');
throw new AllegroApiException('Nie udalo sie zainicjowac polaczenia z API Allegro.');
}
curl_setopt_array($ch, [
@@ -296,21 +296,21 @@ final class AllegroApiClient
$ch = null;
if ($responseBody === false) {
throw new RuntimeException('Blad polaczenia z API Allegro: ' . $curlError);
throw new AllegroApiException('Blad polaczenia z API Allegro: ' . $curlError);
}
$json = json_decode((string) $responseBody, true);
if (!is_array($json)) {
throw new RuntimeException('Nieprawidlowy JSON odpowiedzi API Allegro.');
throw new AllegroApiException('Nieprawidlowy JSON odpowiedzi API Allegro.');
}
if ($httpCode === 401) {
throw new RuntimeException('ALLEGRO_HTTP_401');
throw new AllegroApiException('ALLEGRO_HTTP_401');
}
if ($httpCode < 200 || $httpCode >= 300) {
$message = trim((string) ($json['message'] ?? 'Blad API Allegro.'));
throw new RuntimeException('API Allegro HTTP ' . $httpCode . ': ' . $message);
throw new AllegroApiException('API Allegro HTTP ' . $httpCode . ': ' . $message);
}
return $json;

View File

@@ -14,6 +14,7 @@ use App\Modules\Cron\CronRepository;
use DateInterval;
use DateTimeImmutable;
use RuntimeException;
use AppCoreExceptionsIntegrationConfigException;
use Throwable;
final class AllegroIntegrationController
@@ -701,7 +702,7 @@ final class AllegroIntegrationController
{
$credentials = $this->repository->getOAuthCredentials();
if ($credentials === null) {
throw new RuntimeException($this->translator->get('settings.allegro.flash.credentials_missing'));
throw new IntegrationConfigException($this->translator->get('settings.allegro.flash.credentials_missing'));
}
return $credentials;

View File

@@ -5,7 +5,7 @@ namespace App\Modules\Settings;
use App\Core\Support\StringHelper;
use PDO;
use RuntimeException;
use AppCorexceptionsIntegrationConfigException;
use Throwable;
final class AllegroIntegrationRepository
@@ -104,7 +104,7 @@ final class AllegroIntegrationRepository
$this->ensureRow($env);
$current = $this->fetchRowByEnv($env);
if ($current === null) {
throw new RuntimeException('Brak rekordu konfiguracji Allegro.');
throw new IntegrationConfigException('Brak rekordu konfiguracji Allegro.');
}
$clientSecret = trim((string) ($payload['client_secret'] ?? ''));

View File

@@ -3,7 +3,7 @@ declare(strict_types=1);
namespace App\Modules\Settings;
use RuntimeException;
use App\Core\Exceptions\AllegroOAuthException;
final class AllegroOAuthClient
{
@@ -62,7 +62,7 @@ final class AllegroOAuthClient
$accessToken = trim((string) ($payload['access_token'] ?? ''));
$refreshToken = trim((string) ($payload['refresh_token'] ?? ''));
if ($accessToken === '' || $refreshToken === '') {
throw new RuntimeException('Allegro nie zwrocilo kompletu tokenow OAuth.');
throw new AllegroOAuthException('Allegro nie zwrocilo kompletu tokenow OAuth.');
}
return [
@@ -95,7 +95,7 @@ final class AllegroOAuthClient
$accessToken = trim((string) ($payload['access_token'] ?? ''));
if ($accessToken === '') {
throw new RuntimeException('Allegro nie zwrocilo access_token po odswiezeniu.');
throw new AllegroOAuthException('Allegro nie zwrocilo access_token po odswiezeniu.');
}
return [
@@ -138,7 +138,7 @@ final class AllegroOAuthClient
): array {
$ch = curl_init($url);
if ($ch === false) {
throw new RuntimeException('Nie udalo sie zainicjowac polaczenia OAuth z Allegro.');
throw new AllegroOAuthException('Nie udalo sie zainicjowac polaczenia OAuth z Allegro.');
}
curl_setopt_array($ch, [
@@ -160,18 +160,18 @@ final class AllegroOAuthClient
$ch = null;
if ($responseBody === false) {
throw new RuntimeException('Blad polaczenia OAuth z Allegro: ' . $curlError);
throw new AllegroOAuthException('Blad polaczenia OAuth z Allegro: ' . $curlError);
}
$json = json_decode((string) $responseBody, true);
if (!is_array($json)) {
throw new RuntimeException('Nieprawidlowy JSON odpowiedzi OAuth Allegro.');
throw new AllegroOAuthException('Nieprawidlowy JSON odpowiedzi OAuth Allegro.');
}
if ($httpCode < 200 || $httpCode >= 300) {
$error = trim((string) ($json['error'] ?? 'oauth_error'));
$description = trim((string) ($json['error_description'] ?? 'Brak szczegolow bledu OAuth.'));
throw new RuntimeException('OAuth Allegro [' . $error . ']: ' . $description);
throw new AllegroOAuthException('OAuth Allegro [' . $error . ']: ' . $description);
}
return $json;

View File

@@ -7,6 +7,7 @@ use App\Core\Support\StringHelper;
use App\Modules\Orders\OrderImportRepository;
use App\Modules\Orders\OrdersRepository;
use RuntimeException;
use AppCoreExceptionsAllegroApiException;
use Throwable;
final class AllegroOrderImportService
@@ -28,7 +29,7 @@ final class AllegroOrderImportService
{
$orderId = trim($checkoutFormId);
if ($orderId === '') {
throw new RuntimeException('Podaj ID zamowienia Allegro.');
throw new AllegroApiException('Podaj ID zamowienia Allegro.');
}
[$accessToken, $env] = $this->tokenManager->resolveToken();
@@ -101,7 +102,7 @@ final class AllegroOrderImportService
{
$checkoutFormId = trim((string) ($payload['id'] ?? ''));
if ($checkoutFormId === '') {
throw new RuntimeException('Odpowiedz Allegro nie zawiera ID zamowienia.');
throw new AllegroApiException('Odpowiedz Allegro nie zawiera ID zamowienia.');
}
$status = trim((string) ($payload['status'] ?? ''));

View File

@@ -6,6 +6,7 @@ namespace App\Modules\Settings;
use App\Core\Support\StringHelper;
use DateTimeImmutable;
use RuntimeException;
use AppCoreExceptionsIntegrationConfigException;
use Throwable;
final class AllegroOrdersSyncService
@@ -42,7 +43,7 @@ final class AllegroOrdersSyncService
$integrationId = $this->integrationRepository->getActiveIntegrationId();
if ($integrationId <= 0) {
throw new RuntimeException('Brak aktywnej integracji bazowej Allegro.');
throw new IntegrationConfigException('Brak aktywnej integracji bazowej Allegro.');
}
$now = new DateTimeImmutable('now');

View File

@@ -5,7 +5,7 @@ namespace App\Modules\Settings;
use DateInterval;
use DateTimeImmutable;
use RuntimeException;
use AppCorexceptionsAllegroOAuthException;
use Throwable;
final class AllegroTokenManager
@@ -23,7 +23,7 @@ final class AllegroTokenManager
{
$oauth = $this->repository->getTokenCredentials();
if ($oauth === null) {
throw new RuntimeException('Brak polaczenia OAuth Allegro. Polacz konto w Ustawieniach.');
throw new AllegroOAuthException('Brak polaczenia OAuth Allegro. Polacz konto w Ustawieniach.');
}
$env = (string) ($oauth['environment'] ?? 'sandbox');
@@ -55,7 +55,7 @@ final class AllegroTokenManager
{
$oauth = $this->repository->getTokenCredentials();
if ($oauth === null) {
throw new RuntimeException('Brak danych OAuth Allegro.');
throw new AllegroOAuthException('Brak danych OAuth Allegro.');
}
$token = $this->oauthClient->refreshAccessToken(
@@ -89,7 +89,7 @@ final class AllegroTokenManager
$updated = $this->repository->getTokenCredentials();
$newToken = trim((string) ($updated['access_token'] ?? ''));
if ($newToken === '') {
throw new RuntimeException('Nie udalo sie odswiezyc tokenu Allegro.');
throw new AllegroOAuthException('Nie udalo sie odswiezyc tokenu Allegro.');
}
return [$newToken, (string) ($updated['environment'] ?? 'sandbox')];

View File

@@ -3,7 +3,7 @@ declare(strict_types=1);
namespace App\Modules\Settings;
use RuntimeException;
use AppCorexceptionsApaczkaApiException;
final class ApaczkaApiClient
{
@@ -68,14 +68,14 @@ final class ApaczkaApiClient
{
$normalizedRoute = trim($route, " \t\n\r\0\x0B/");
if ($normalizedRoute === '') {
throw new RuntimeException('Nie podano endpointu API Apaczka.');
throw new ApaczkaApiException('Nie podano endpointu API Apaczka.');
}
$routeWithTrailingSlash = $normalizedRoute . '/';
$expires = (string) (time() + 60);
$requestJson = json_encode($request);
if (!is_string($requestJson)) {
throw new RuntimeException('Nie mozna zakodowac payloadu Apaczka.');
throw new ApaczkaApiException('Nie mozna zakodowac payloadu Apaczka.');
}
$basePayload = [
@@ -107,11 +107,11 @@ final class ApaczkaApiClient
}
if ($httpCode < 200 || $httpCode >= 300) {
throw new RuntimeException('API Apaczka HTTP ' . $httpCode . ': ' . $message);
throw new ApaczkaApiException('API Apaczka HTTP ' . $httpCode . ': ' . $message);
}
if ($status !== 200) {
$responsePreview = substr(json_encode($decoded, JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES) ?: '', 0, 240);
throw new RuntimeException(
throw new ApaczkaApiException(
'Blad API Apaczka (status ' . $status . '): ' . $message . '. Odpowiedz: ' . $responsePreview
);
}
@@ -122,12 +122,12 @@ final class ApaczkaApiClient
if ($lastSignatureError !== null) {
[$decoded, $status, $message] = $lastSignatureError;
$responsePreview = substr(json_encode($decoded, JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES) ?: '', 0, 240);
throw new RuntimeException(
throw new ApaczkaApiException(
'Blad API Apaczka (status ' . $status . '): ' . $message . '. Odpowiedz: ' . $responsePreview
);
}
throw new RuntimeException('Blad API Apaczka.');
throw new ApaczkaApiException('Blad API Apaczka.');
}
private function buildSignature(
@@ -177,7 +177,7 @@ final class ApaczkaApiClient
$url = rtrim(self::API_BASE_URL, '/') . '/' . ltrim($endpointPath, '/');
$ch = curl_init($url);
if ($ch === false) {
throw new RuntimeException('Nie udalo sie zainicjowac polaczenia z API Apaczka.');
throw new ApaczkaApiException('Nie udalo sie zainicjowac polaczenia z API Apaczka.');
}
curl_setopt_array($ch, [
@@ -199,14 +199,14 @@ final class ApaczkaApiClient
unset($ch);
if ($rawBody === false) {
throw new RuntimeException('Blad polaczenia z API Apaczka: ' . $curlError);
throw new ApaczkaApiException('Blad polaczenia z API Apaczka: ' . $curlError);
}
$normalizedBody = ltrim((string) $rawBody, "\xEF\xBB\xBF \t\n\r\0\x0B");
$decoded = json_decode($normalizedBody, true);
if (!is_array($decoded)) {
$snippet = substr(trim(strip_tags($normalizedBody)), 0, 180);
throw new RuntimeException(
throw new ApaczkaApiException(
'Nieprawidlowa odpowiedz API Apaczka (brak JSON, HTTP ' . $httpCode . '). Fragment: ' . $snippet
);
}

View File

@@ -4,7 +4,7 @@ declare(strict_types=1);
namespace App\Modules\Settings;
use PDO;
use RuntimeException;
use AppCorexceptionsIntegrationConfigException;
use Throwable;
final class ApaczkaIntegrationRepository
@@ -56,12 +56,12 @@ final class ApaczkaIntegrationRepository
$row = $this->fetchRow();
if ($row === null) {
throw new RuntimeException('Brak rekordu konfiguracji Apaczka.');
throw new IntegrationConfigException('Brak rekordu konfiguracji Apaczka.');
}
$appId = trim((string) ($payload['app_id'] ?? ''));
if ($appId === '') {
throw new RuntimeException('Podaj App ID Apaczka.');
throw new IntegrationConfigException('Podaj App ID Apaczka.');
}
$currentEncrypted = $this->resolveSecretEncrypted($row, $this->integrations->findById($integrationId));
@@ -72,7 +72,7 @@ final class ApaczkaIntegrationRepository
}
if ($nextEncrypted === null || $nextEncrypted === '') {
throw new RuntimeException('Podaj App Secret Apaczka.');
throw new IntegrationConfigException('Podaj App Secret Apaczka.');
}
$stmt = $this->pdo->prepare(
@@ -129,7 +129,7 @@ final class ApaczkaIntegrationRepository
{
$credentials = $this->getApiCredentials();
if ($credentials === null) {
throw new RuntimeException('Brak konfiguracji App ID/App Secret Apaczka.');
throw new IntegrationConfigException('Brak konfiguracji App ID/App Secret Apaczka.');
}
return $apiClient->getServiceStructure(

View File

@@ -5,7 +5,7 @@ namespace App\Modules\Settings;
use App\Core\Support\StringHelper;
use PDO;
use RuntimeException;
use AppCorexceptionsIntegrationConfigException;
use Throwable;
final class InpostIntegrationRepository
@@ -65,7 +65,7 @@ final class InpostIntegrationRepository
$this->ensureRow();
$current = $this->fetchRow();
if ($current === null) {
throw new RuntimeException('Brak rekordu konfiguracji InPost.');
throw new IntegrationConfigException('Brak rekordu konfiguracji InPost.');
}
$integrationId = $this->ensureBaseIntegration();

View File

@@ -3,7 +3,7 @@ declare(strict_types=1);
namespace App\Modules\Settings;
use RuntimeException;
use AppCorexceptionsIntegrationConfigException;
final class IntegrationSecretCipher
{
@@ -18,7 +18,7 @@ final class IntegrationSecretCipher
return null;
}
if ($this->secret === '') {
throw new RuntimeException('Brak INTEGRATIONS_SECRET do szyfrowania danych integracji.');
throw new IntegrationConfigException('Brak INTEGRATIONS_SECRET do szyfrowania danych integracji.');
}
$encryptionKey = hash('sha256', 'enc|' . $this->secret, true);
@@ -26,7 +26,7 @@ final class IntegrationSecretCipher
$iv = random_bytes(16);
$cipherRaw = openssl_encrypt($value, 'AES-256-CBC', $encryptionKey, OPENSSL_RAW_DATA, $iv);
if ($cipherRaw === false) {
throw new RuntimeException('Nie udalo sie zaszyfrowac danych integracji.');
throw new IntegrationConfigException('Nie udalo sie zaszyfrowac danych integracji.');
}
$mac = hash_hmac('sha256', $iv . $cipherRaw, $hmacKey, true);
@@ -36,7 +36,7 @@ final class IntegrationSecretCipher
public function decrypt(string $encrypted): ?string
{
if ($this->secret === '') {
throw new RuntimeException('Brak INTEGRATIONS_SECRET do odszyfrowania danych integracji.');
throw new IntegrationConfigException('Brak INTEGRATIONS_SECRET do odszyfrowania danych integracji.');
}
if (!str_starts_with($encrypted, 'v1:')) {

View File

@@ -5,7 +5,7 @@ namespace App\Modules\Settings;
use App\Core\Support\StringHelper;
use PDO;
use RuntimeException;
use AppCorexceptionsIntegrationConfigException;
use Throwable;
final class ShopproIntegrationsRepository
@@ -154,7 +154,7 @@ final class ShopproIntegrationsRepository
if ($integrationId > 0) {
$existing = $this->findIntegration($integrationId);
if ($existing === null) {
throw new RuntimeException('INTEGRATION_NOT_FOUND');
throw new IntegrationConfigException('INTEGRATION_NOT_FOUND');
}
$encryptedApiKey = trim((string) ($existing['api_key_encrypted'] ?? ''));

View File

@@ -8,6 +8,8 @@ use App\Modules\Settings\AllegroApiClient;
use App\Modules\Settings\AllegroTokenManager;
use App\Modules\Settings\CompanySettingsRepository;
use RuntimeException;
use AppCoreExceptionsIntegrationConfigException;
use AppCoreExceptionsShipmentException;
use Throwable;
final class AllegroShipmentService implements ShipmentProviderInterface
@@ -44,7 +46,7 @@ final class AllegroShipmentService implements ShipmentProviderInterface
{
$order = $this->ordersRepository->findDetails($orderId);
if ($order === null) {
throw new RuntimeException('Zamowienie nie znalezione.');
throw new ShipmentException('Zamowienie nie znalezione.');
}
$company = $this->companySettings->getSettings();
@@ -53,7 +55,7 @@ final class AllegroShipmentService implements ShipmentProviderInterface
$deliveryMethodId = trim((string) ($formData['delivery_method_id'] ?? ''));
if ($deliveryMethodId === '') {
throw new RuntimeException('Nie podano metody dostawy.');
throw new ShipmentException('Nie podano metody dostawy.');
}
$receiverAddress = $this->buildReceiverAddress($order, $formData);
@@ -177,12 +179,12 @@ final class AllegroShipmentService implements ShipmentProviderInterface
{
$package = $this->packages->findById($packageId);
if ($package === null) {
throw new RuntimeException('Paczka nie znaleziona.');
throw new ShipmentException('Paczka nie znaleziona.');
}
$commandId = trim((string) ($package['command_id'] ?? ''));
if ($commandId === '') {
throw new RuntimeException('Brak command_id dla tej paczki.');
throw new ShipmentException('Brak command_id dla tej paczki.');
}
[$accessToken, $env] = $this->tokenManager->resolveToken();
@@ -238,12 +240,12 @@ final class AllegroShipmentService implements ShipmentProviderInterface
{
$package = $this->packages->findById($packageId);
if ($package === null) {
throw new RuntimeException('Paczka nie znaleziona.');
throw new ShipmentException('Paczka nie znaleziona.');
}
$shipmentId = trim((string) ($package['shipment_id'] ?? ''));
if ($shipmentId === '') {
throw new RuntimeException('Przesylka nie zostala jeszcze utworzona.');
throw new ShipmentException('Przesylka nie zostala jeszcze utworzona.');
}
[$accessToken, $env] = $this->tokenManager->resolveToken();
@@ -346,14 +348,14 @@ final class AllegroShipmentService implements ShipmentProviderInterface
$required = ['street', 'city', 'postalCode', 'phone', 'email'];
foreach ($required as $field) {
if (trim((string) ($sender[$field] ?? '')) === '') {
throw new RuntimeException('Uzupelnij dane nadawcy w Ustawienia > Dane firmy (brak: ' . $field . ').');
throw new IntegrationConfigException('Uzupelnij dane nadawcy w Ustawienia > Dane firmy (brak: ' . $field . ').');
}
}
$name = trim((string) ($sender['name'] ?? ''));
$company = trim((string) ($sender['company'] ?? ''));
if ($name === '' && $company === '') {
throw new RuntimeException('Uzupelnij dane nadawcy w Ustawienia > Dane firmy (brak nazwy/firmy).');
throw new IntegrationConfigException('Uzupelnij dane nadawcy w Ustawienia > Dane firmy (brak nazwy/firmy).');
}
}

View File

@@ -7,7 +7,8 @@ use App\Modules\Orders\OrdersRepository;
use App\Modules\Settings\ApaczkaApiClient;
use App\Modules\Settings\ApaczkaIntegrationRepository;
use App\Modules\Settings\CompanySettingsRepository;
use RuntimeException;
use AppCorexceptionsIntegrationConfigException;
use AppCorexceptionsShipmentException;
use Throwable;
final class ApaczkaShipmentService implements ShipmentProviderInterface
@@ -48,7 +49,7 @@ final class ApaczkaShipmentService implements ShipmentProviderInterface
{
$order = $this->ordersRepository->findDetails($orderId);
if ($order === null) {
throw new RuntimeException('Zamowienie nie znalezione.');
throw new ShipmentException('Zamowienie nie znalezione.');
}
[$appId, $appSecret] = $this->requireCredentials();
@@ -61,7 +62,7 @@ final class ApaczkaShipmentService implements ShipmentProviderInterface
$deliveryMethodId = trim((string) ($formData['delivery_method_id'] ?? ''));
if ($deliveryMethodId === '') {
throw new RuntimeException('Nie podano uslugi Apaczka.');
throw new ShipmentException('Nie podano uslugi Apaczka.');
}
$serviceDefinition = $this->resolveServiceDefinition($appId, $appSecret, $deliveryMethodId);
@@ -153,7 +154,7 @@ final class ApaczkaShipmentService implements ShipmentProviderInterface
'status' => 'error',
'error_message' => $errorMessage,
]);
throw new RuntimeException($errorMessage, 0, $exception);
throw new ShipmentException($errorMessage, 0, $exception);
}
$orderResponse = is_array($response['response']['order'] ?? null) ? $response['response']['order'] : [];
@@ -180,7 +181,7 @@ final class ApaczkaShipmentService implements ShipmentProviderInterface
{
$package = $this->packages->findById($packageId);
if ($package === null) {
throw new RuntimeException('Paczka nie znaleziona.');
throw new ShipmentException('Paczka nie znaleziona.');
}
$shipmentId = max(0, (int) ($package['shipment_id'] ?? 0));
@@ -213,12 +214,12 @@ final class ApaczkaShipmentService implements ShipmentProviderInterface
{
$package = $this->packages->findById($packageId);
if ($package === null) {
throw new RuntimeException('Paczka nie znaleziona.');
throw new ShipmentException('Paczka nie znaleziona.');
}
$shipmentId = max(0, (int) ($package['shipment_id'] ?? 0));
if ($shipmentId <= 0) {
throw new RuntimeException('Przesylka nie zostala jeszcze utworzona.');
throw new ShipmentException('Przesylka nie zostala jeszcze utworzona.');
}
[$appId, $appSecret] = $this->requireCredentials();
@@ -243,12 +244,12 @@ final class ApaczkaShipmentService implements ShipmentProviderInterface
$base64 = trim((string) ($waybillRaw['data'] ?? ''));
}
if ($base64 === '') {
throw new RuntimeException('Apaczka nie zwrocila danych etykiety.');
throw new ShipmentException('Apaczka nie zwrocila danych etykiety.');
}
$binary = base64_decode($base64, true);
if (!is_string($binary) || $binary === '') {
throw new RuntimeException('Nie mozna odczytac etykiety Apaczka.');
throw new ShipmentException('Nie mozna odczytac etykiety Apaczka.');
}
$dir = rtrim($storagePath, '/\\') . '/labels';
@@ -292,7 +293,7 @@ final class ApaczkaShipmentService implements ShipmentProviderInterface
$appSecret = trim((string) ($credentials['app_secret'] ?? ''));
if ($appId === '' || $appSecret === '') {
throw new RuntimeException('Brak konfiguracji Apaczka (app_id/app_secret).');
throw new IntegrationConfigException('Brak konfiguracji Apaczka (app_id/app_secret).');
}
return [$appId, $appSecret];
@@ -409,7 +410,7 @@ final class ApaczkaShipmentService implements ShipmentProviderInterface
}
if ($name === '' || $street === '' || $city === '' || $postalCode === '' || $countryCode === '') {
throw new RuntimeException('Brak wymaganych danych adresowych odbiorcy.');
throw new ShipmentException('Brak wymaganych danych adresowych odbiorcy.');
}
$receiver = [
@@ -663,13 +664,13 @@ final class ApaczkaShipmentService implements ShipmentProviderInterface
$serviceName = trim((string) ($serviceDefinition['name'] ?? ''));
if ($requiresReceiverPoint && $receiverPoint === '') {
throw new RuntimeException(
throw new ShipmentException(
'Wybrana usluga Apaczka (' . ($serviceName !== '' ? $serviceName : 'ID')
. ') wymaga punktu odbioru (`receiver_point_id`).'
);
}
if ($requiresSenderPoint && $senderPoint === '') {
throw new RuntimeException(
throw new ShipmentException(
'Wybrana usluga Apaczka (' . ($serviceName !== '' ? $serviceName : 'ID')
. ') wymaga punktu nadania (`sender_point_id`).'
);
@@ -865,18 +866,18 @@ final class ApaczkaShipmentService implements ShipmentProviderInterface
$required = ['street', 'city', 'postalCode', 'phone', 'email'];
foreach ($required as $field) {
if (trim((string) ($sender[$field] ?? '')) === '') {
throw new RuntimeException('Uzupelnij dane nadawcy w Ustawienia > Dane firmy (brak: ' . $field . ').');
throw new IntegrationConfigException('Uzupelnij dane nadawcy w Ustawienia > Dane firmy (brak: ' . $field . ').');
}
}
$name = trim((string) ($sender['name'] ?? ''));
$company = trim((string) ($sender['company'] ?? ''));
if ($name === '' && $company === '') {
throw new RuntimeException('Uzupelnij dane nadawcy w Ustawienia > Dane firmy (brak nazwy/firmy).');
throw new IntegrationConfigException('Uzupelnij dane nadawcy w Ustawienia > Dane firmy (brak nazwy/firmy).');
}
$contactPerson = trim((string) ($sender['contactPerson'] ?? $name ?? ''));
if ($contactPerson === '') {
throw new RuntimeException('Uzupelnij dane nadawcy w Ustawienia > Dane firmy (brak osoby kontaktowej).');
throw new IntegrationConfigException('Uzupelnij dane nadawcy w Ustawienia > Dane firmy (brak osoby kontaktowej).');
}
}
}

View File

@@ -13,7 +13,7 @@ use App\Modules\Auth\AuthService;
use App\Modules\Orders\OrdersRepository;
use App\Modules\Settings\CarrierDeliveryMethodMappingRepository;
use App\Modules\Settings\CompanySettingsRepository;
use RuntimeException;
use AppCorexceptionsShipmentException;
use Throwable;
final class ShipmentController
@@ -167,7 +167,7 @@ final class ShipmentController
}
$provider = $this->providerRegistry->get($providerCode);
if ($provider === null) {
throw new RuntimeException('Nieznany provider przesylek: ' . $providerCode);
throw new ShipmentException('Nieznany provider przesylek: ' . $providerCode);
}
$result = $provider->createShipment($orderId, [
@@ -280,13 +280,13 @@ final class ShipmentController
try {
$package = $this->packageRepository->findById($packageId);
if ($package === null) {
throw new RuntimeException('Paczka nie znaleziona.');
throw new ShipmentException('Paczka nie znaleziona.');
}
$providerCode = strtolower(trim((string) ($package['provider'] ?? 'allegro_wza')));
$provider = $this->providerRegistry->get($providerCode);
if ($provider === null) {
throw new RuntimeException('Brak providera: ' . $providerCode);
throw new ShipmentException('Brak providera: ' . $providerCode);
}
$result = $provider->downloadLabel($packageId, $this->storagePath);