93 lines
3.4 KiB
PHP
93 lines
3.4 KiB
PHP
<?php
|
|
declare(strict_types=1);
|
|
|
|
namespace Esun\LingxingErp\Model\Sync;
|
|
|
|
use Esun\LingxingErp\Model\Api\Endpoint;
|
|
use Magento\Framework\App\ResourceConnection;
|
|
|
|
class LogWriter
|
|
{
|
|
private const COMPACT_STATUSES = ['success', 'ignored'];
|
|
private const SUMMARY_SCALAR_KEYS = [
|
|
'code', 'message', 'request_id', 'store_count', 'shipment_id',
|
|
'pairs', 'mapped', 'unmapped', 'zeroed', 'preserved_without_erp_sku', 'total', 'count',
|
|
];
|
|
private const SENSITIVE_KEYS = [
|
|
'appsecret', 'app_secret', 'access_token', 'refresh_token', 'sign',
|
|
'receiver_name', 'receiver_company_name', 'address_line1', 'address_line2',
|
|
'address_line3', 'postal_code', 'postcode', 'receiver_mobile', 'buyer_email', 'buyer_name',
|
|
'phone', 'telephone', 'email', 'consignee', 'consignee_phone', 'consignee_address',
|
|
'consignee_full_address',
|
|
];
|
|
|
|
public function __construct(private readonly ResourceConnection $resource)
|
|
{
|
|
}
|
|
|
|
public function write(array $data): void
|
|
{
|
|
$data['api_path'] ??= Endpoint::forOperation((string)($data['operation'] ?? '')) ?: null;
|
|
$compactPayload = in_array((string)($data['status'] ?? ''), self::COMPACT_STATUSES, true);
|
|
foreach (['request_payload', 'response_payload'] as $field) {
|
|
if (!isset($data[$field])) {
|
|
continue;
|
|
}
|
|
if ($compactPayload) {
|
|
$data[$field] = $this->summarize($data[$field]);
|
|
}
|
|
if (is_array($data[$field])) {
|
|
$data[$field] = json_encode(
|
|
$this->sanitize($data[$field]),
|
|
JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES | JSON_THROW_ON_ERROR
|
|
);
|
|
}
|
|
}
|
|
$data['created_at'] = gmdate('Y-m-d H:i:s');
|
|
$this->resource->getConnection()->insert(
|
|
$this->resource->getTableName('esun_lingxing_sync_log'),
|
|
$data
|
|
);
|
|
}
|
|
|
|
private function summarize(mixed $payload): array
|
|
{
|
|
$sanitized = is_array($payload) ? $this->sanitize($payload) : $payload;
|
|
$encoded = json_encode(
|
|
$sanitized,
|
|
JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES | JSON_THROW_ON_ERROR
|
|
);
|
|
$summary = [
|
|
'_summary' => 'Success payload omitted by retention policy.',
|
|
'payload_sha256' => hash('sha256', $encoded),
|
|
'payload_bytes' => strlen($encoded),
|
|
];
|
|
if (!is_array($sanitized)) {
|
|
return $summary;
|
|
}
|
|
$summary['top_level_keys'] = array_values(array_map('strval', array_keys($sanitized)));
|
|
foreach ($sanitized as $key => $value) {
|
|
$normalized = strtolower((string)$key);
|
|
if (in_array($normalized, self::SUMMARY_SCALAR_KEYS, true) && is_scalar($value)) {
|
|
$summary[$key] = $value;
|
|
} elseif (is_array($value)) {
|
|
$summary[$key . '_count'] = count($value);
|
|
}
|
|
}
|
|
return $summary;
|
|
}
|
|
|
|
private function sanitize(array $data): array
|
|
{
|
|
foreach ($data as $key => $value) {
|
|
$normalized = strtolower((string)$key);
|
|
if (in_array($normalized, self::SENSITIVE_KEYS, true)) {
|
|
$data[$key] = '[REDACTED]';
|
|
} elseif (is_array($value)) {
|
|
$data[$key] = $this->sanitize($value);
|
|
}
|
|
}
|
|
return $data;
|
|
}
|
|
}
|