|null $payload wird als JSON abgelegt (Secrets vorher entfernen!) */ public static function write( string $provider, string $action, ?int $orderId = null, ?string $orderNumber = null, ?string $reference = null, ?string $status = null, ?int $httpStatus = null, ?array $payload = null, ?string $detail = null ): bool { $c = self::conn(); if (!$c) { return false; } $json = $payload === null ? null : \json_encode(self::scrub($payload), JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES); $ok = @\pg_query_params( $c, 'INSERT INTO payment_log (provider, action, order_id, order_number, reference, status, http_status, payload, detail, host) VALUES ($1,$2,$3,$4,$5,$6,$7,$8,$9,$10)', [ $provider, $action, $orderId, $orderNumber, $reference, $status, $httpStatus, $json, $detail, (string) ($_SERVER['SERVER_NAME'] ?? \gethostname()), ] ); if (!$ok) { self::$dead = true; \error_log('payment_log: INSERT fehlgeschlagen -- ' . @\pg_last_error($c)); return false; } return true; } /** * Verlauf einer Bestellung fuer den Bestell-Editor, aelteste zuerst. * Payload bleibt draussen (Roh-JSON gehoert nicht in die Maske). * * @return list */ public static function forOrder(int $orderId, int $limit = 40): array { $c = self::conn(); if (!$c || $orderId <= 0) { return []; } $host = (string) ($_SERVER['SERVER_NAME'] ?? \gethostname()); $res = @\pg_query_params( $c, "SELECT to_char(zeitpunkt, 'DD.MM.YYYY HH24:MI:SS') AS zeit, action, status, http_status, detail, reference FROM payment_log WHERE order_id = $1 AND host = $2 ORDER BY id LIMIT $3", [$orderId, $host, $limit] ); if (!$res) { return []; } return \pg_fetch_all($res) ?: []; } /** @return resource|\PgSql\Connection|false */ private static function conn() { if (self::$dead) { return false; } if (self::$conn !== null) { return self::$conn; } if (!\function_exists('pg_connect')) { self::$dead = true; return false; } $ini = @\parse_ini_file(\dirname(__DIR__) . '/postgres/config.ini', true); if (!$ini || empty($ini['postgresql'])) { self::$dead = true; return false; } $p = $ini['postgresql']; $dsn = \sprintf( 'host=%s port=%s dbname=%s user=%s password=%s connect_timeout=2', $p['host'] ?? 'localhost', $p['port'] ?? '5432', $p['database'] ?? '', $p['user'] ?? '', $p['password'] ?? '' ); $c = @\pg_connect($dsn); if (!$c) { self::$dead = true; \error_log('payment_log: keine PG-Verbindung -- Protokoll uebersprungen'); return false; } return self::$conn = $c; } /** Entfernt Schluessel, die nach Zugangsdaten aussehen, rekursiv. */ private static function scrub(array $data): array { foreach ($data as $k => $v) { if (\is_string($k) && \preg_match('/secret|password|token|authorization|client_id/i', $k)) { $data[$k] = '***'; } elseif (\is_array($v)) { $data[$k] = self::scrub($v); } } return $data; } }