Files
2026-09-15 10:35:56 +08:00

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;
}
}