Files
shop-old/core/postgres/shop_events.php
T

130 lines
4.7 KiB
PHP

<?php
/**
* Ereignis-Log fuer Bestellvorgaenge (25.08.2026).
*
* Warum PostgreSQL und nicht der Shop selbst:
* Die MySQL-Tabelle `orders` hat keine einzige Spalte mit Uhrzeit -- `order_date` und alle
* anderen Datumsfelder sind Typ DATE, und `order_history.timestamp` wird bei der
* Bestellanlage nicht gefuellt. Damit laesst sich weder eine Abbruchquote sauber messen
* noch belegen, ob eine Aenderung am Bezahlweg etwas gebracht hat. Genau daran ist die
* Analyse der PayPal-Abbrueche zuerst haengengeblieben.
*
* Grundregel dieser Datei: **Der Bestellvorgang darf hier NIEMALS haengenbleiben.**
* Ist Postgres weg, langsam oder die Tabelle fehlt, wird still weitergemacht. Ein
* Messwerkzeug, das den Kaufvorgang gefaehrdet, ist sein Geld nicht wert. Deshalb
* connect_timeout, deshalb ueberall @ und Rueckgabepruefung statt Exceptions.
*
* Ereignisse:
* order_created Bestellung in MySQL angelegt (bei PayPal: noch nicht bezahlt!)
* payment_started Kunde wurde zu PayPal geschickt, Token steht
* paid Geld eingezogen (DoExpressCheckoutPayment erfolgreich)
* cancelled Kunde hat bei PayPal abgebrochen
* failed PayPal hat den Abschluss abgelehnt
* duplicate_blocked zweiter Versuch desselben Vorgangs abgefangen
* mail_sent Bestellbestaetigung ausgeloest
*
* Auswertung z. B.:
* SELECT date_trunc('day', zeitpunkt) AS tag,
* count(*) FILTER (WHERE ereignis = 'payment_started') AS gestartet,
* count(*) FILTER (WHERE ereignis = 'paid') AS bezahlt
* FROM shop_order_events GROUP BY 1 ORDER BY 1;
*/
if (!function_exists('shop_event')) {
/**
* Schreibt ein Ereignis. Schlaegt das fehl, passiert nichts weiter.
*
* @param string $ereignis siehe Liste oben
* @param array $daten order_id, order_number, payment_method, betrag,
* paypal_token, transaction_id, customer_id, detail
* @return bool true wenn geschrieben, sonst false
*/
function shop_event($ereignis, $daten = array()) {
static $verbindung = null;
static $tot = false;
// Einmal gescheitert -> fuer diesen Request nicht weiter versuchen. Sonst wartet
// jeder Aufruf erneut auf einen Timeout.
if ($tot) {
return false;
}
if (!function_exists('pg_connect')) {
$tot = true;
return false;
}
if ($verbindung === null) {
$ini_pfad = dirname(__FILE__) . '/config.ini';
if (!is_readable($ini_pfad)) {
$tot = true;
return false;
}
$ini = @parse_ini_file($ini_pfad, true);
if (!$ini || empty($ini['postgresql'])) {
$tot = true;
return false;
}
$pg = $ini['postgresql'];
// connect_timeout ist der wichtigste Parameter hier: liegt Postgres,
// wartet der Checkout hoechstens zwei Sekunden statt bis zum PHP-Timeout.
$dsn = sprintf(
'host=%s port=%s dbname=%s user=%s password=%s connect_timeout=2',
isset($pg['host']) ? $pg['host'] : 'localhost',
isset($pg['port']) ? $pg['port'] : '5432',
isset($pg['database']) ? $pg['database'] : '',
isset($pg['user']) ? $pg['user'] : '',
isset($pg['password']) ? $pg['password'] : ''
);
$verbindung = @pg_connect($dsn);
if (!$verbindung) {
$verbindung = null;
$tot = true;
error_log('shop_event: keine PG-Verbindung -- Ereignisprotokoll uebersprungen');
return false;
}
}
$werte = array(
(string)$ereignis,
isset($daten['order_id']) && $daten['order_id'] !== '' ? (int)$daten['order_id'] : null,
isset($daten['order_number']) ? (string)$daten['order_number'] : null,
isset($daten['payment_method']) && $daten['payment_method'] !== '' ? (int)$daten['payment_method'] : null,
isset($daten['betrag']) && $daten['betrag'] !== '' ? (float)$daten['betrag'] : null,
isset($daten['paypal_token']) ? (string)$daten['paypal_token'] : null,
isset($daten['transaction_id']) ? (string)$daten['transaction_id'] : null,
isset($daten['customer_id']) && $daten['customer_id'] !== '' ? (int)$daten['customer_id'] : null,
function_exists('session_id') && session_id() ? session_id() : null,
isset($daten['detail']) ? (string)$daten['detail'] : null
);
$ergebnis = @pg_query_params(
$verbindung,
'INSERT INTO shop_order_events
(ereignis, order_id, order_number, payment_method, betrag,
paypal_token, transaction_id, customer_id, session_id, detail)
VALUES ($1,$2,$3,$4,$5,$6,$7,$8,$9,$10)',
$werte
);
if (!$ergebnis) {
// Einmal melden, dann Ruhe -- ein volllaufendes Log hilft niemandem.
$tot = true;
error_log('shop_event: INSERT fehlgeschlagen (' . $ereignis . ') -- '
. @pg_last_error($verbindung));
return false;
}
return true;
}
}
/* EOF */