Files
orderPRO/src/Modules/Settings/ApaczkaIntegrationRepository.php
Jacek Pyziak 2b12fde248 feat(shipments): add ShipmentProviderInterface and ShipmentProviderRegistry
- Introduced ShipmentProviderInterface to define the contract for shipment providers.
- Implemented ShipmentProviderRegistry to manage and retrieve shipment providers.
- Added a new tool for probing Apaczka order_send payload variants, enhancing debugging capabilities.
2026-03-08 23:45:10 +01:00

200 lines
6.1 KiB
PHP

<?php
declare(strict_types=1);
namespace App\Modules\Settings;
use PDO;
use RuntimeException;
use Throwable;
final class ApaczkaIntegrationRepository
{
private const INTEGRATION_TYPE = 'apaczka';
private const INTEGRATION_NAME = 'Apaczka';
private const INTEGRATION_BASE_URL = 'https://www.apaczka.pl';
private readonly IntegrationsRepository $integrations;
private readonly IntegrationSecretCipher $cipher;
public function __construct(
private readonly PDO $pdo,
private readonly string $secret
) {
$this->integrations = new IntegrationsRepository($this->pdo);
$this->cipher = new IntegrationSecretCipher($this->secret);
}
/**
* @return array<string, mixed>
*/
public function getSettings(): array
{
$this->ensureRow();
$integrationId = $this->ensureBaseIntegration();
$row = $this->fetchRow();
$integration = $this->integrations->findById($integrationId);
$appId = trim((string) ($row['app_id'] ?? ''));
$secretEncrypted = $this->resolveSecretEncrypted($row, $integration);
return [
'app_id' => $appId,
'has_app_id' => $appId !== '',
'has_app_secret' => $secretEncrypted !== null && $secretEncrypted !== '',
'has_api_key' => $secretEncrypted !== null && $secretEncrypted !== '',
'updated_at' => (string) ($row['updated_at'] ?? ''),
];
}
/**
* @param array<string, mixed> $payload
*/
public function saveSettings(array $payload): void
{
$this->ensureRow();
$integrationId = $this->ensureBaseIntegration();
$row = $this->fetchRow();
if ($row === null) {
throw new RuntimeException('Brak rekordu konfiguracji Apaczka.');
}
$appId = trim((string) ($payload['app_id'] ?? ''));
if ($appId === '') {
throw new RuntimeException('Podaj App ID Apaczka.');
}
$currentEncrypted = $this->resolveSecretEncrypted($row, $this->integrations->findById($integrationId));
$appSecret = trim((string) ($payload['app_secret'] ?? ($payload['api_key'] ?? '')));
$nextEncrypted = $currentEncrypted;
if ($appSecret !== '') {
$nextEncrypted = $this->cipher->encrypt($appSecret);
}
if ($nextEncrypted === null || $nextEncrypted === '') {
throw new RuntimeException('Podaj App Secret Apaczka.');
}
$stmt = $this->pdo->prepare(
'UPDATE apaczka_integration_settings
SET app_id = :app_id,
app_secret_encrypted = :app_secret_encrypted,
api_key_encrypted = :api_key_encrypted,
updated_at = NOW()
WHERE id = 1'
);
$stmt->execute([
'app_id' => $appId,
'app_secret_encrypted' => $nextEncrypted,
'api_key_encrypted' => $nextEncrypted,
]);
$this->integrations->updateApiKeyEncrypted($integrationId, $nextEncrypted);
}
/**
* @return array{app_id:string, app_secret:string}|null
*/
public function getApiCredentials(): ?array
{
$settings = $this->getSettings();
$appId = trim((string) ($settings['app_id'] ?? ''));
if ($appId === '') {
return null;
}
$row = $this->fetchRow();
$integrationId = $this->ensureBaseIntegration();
$integration = $this->integrations->findById($integrationId);
$encrypted = $this->resolveSecretEncrypted($row, $integration);
if ($encrypted === null || $encrypted === '') {
return null;
}
$secret = trim($this->cipher->decrypt($encrypted));
if ($secret === '') {
return null;
}
return [
'app_id' => $appId,
'app_secret' => $secret,
];
}
/**
* @return array<int, array<string, mixed>>
*/
public function testConnection(ApaczkaApiClient $apiClient): array
{
$credentials = $this->getApiCredentials();
if ($credentials === null) {
throw new RuntimeException('Brak konfiguracji App ID/App Secret Apaczka.');
}
return $apiClient->getServiceStructure(
(string) $credentials['app_id'],
(string) $credentials['app_secret']
);
}
private function ensureBaseIntegration(): int
{
return $this->integrations->ensureIntegration(
self::INTEGRATION_TYPE,
self::INTEGRATION_NAME,
self::INTEGRATION_BASE_URL,
20,
true
);
}
private function ensureRow(): void
{
$integrationId = $this->ensureBaseIntegration();
$stmt = $this->pdo->prepare(
'INSERT INTO apaczka_integration_settings (id, integration_id, created_at, updated_at)
VALUES (1, :integration_id, NOW(), NOW())
ON DUPLICATE KEY UPDATE integration_id = VALUES(integration_id), updated_at = VALUES(updated_at)'
);
$stmt->execute(['integration_id' => $integrationId]);
}
/**
* @return array<string, mixed>|null
*/
private function fetchRow(): ?array
{
try {
$stmt = $this->pdo->prepare('SELECT * FROM apaczka_integration_settings WHERE id = 1 LIMIT 1');
$stmt->execute();
$row = $stmt->fetch(PDO::FETCH_ASSOC);
} catch (Throwable) {
return null;
}
return is_array($row) ? $row : null;
}
/**
* @param array<string, mixed>|null $row
* @param array<string, mixed>|null $integration
*/
private function resolveSecretEncrypted(?array $row, ?array $integration): ?string
{
$base = trim((string) ($integration['api_key_encrypted'] ?? ''));
if ($base !== '') {
return $base;
}
$modern = trim((string) ($row['app_secret_encrypted'] ?? ''));
if ($modern !== '') {
return $modern;
}
$legacy = trim((string) ($row['api_key_encrypted'] ?? ''));
return $legacy !== '' ? $legacy : null;
}
}