- ProviderInterface/AbstractProvider: Vorgang mit Uhrzeit+Session (payment_transactions), Mail und Warenkorb erst nach Zahlung, idempotentes markPaid, Betragsabgleich, shop_event + PG payment_log - Secrets verschluesselt (libsodium) in MySQL, Schluessel ausserhalb Docroot - Cashdesk: ?payment_return/?payment_cancel, Pending-Riegel, zahlung_erst_spaeter() - Backend Zahlart-Editor: Einstellungen speichern (war ohne Empfaenger), Secret-Felder - payment_webhook.php (Standalone), cli.php (init-key, secret, reconcile, status) - PayPal-v2-Blaupause vom Juli entfernt
107 lines
4.0 KiB
PHP
107 lines
4.0 KiB
PHP
<?php
|
|
/**
|
|
* Kommandozeile fuer die Zahlungsanbieter. Immer mit dem PHP des Shops aufrufen:
|
|
*
|
|
* /opt/plesk/php/8.2/bin/php core/payments/cli.php reconcile [modul] [--apply]
|
|
* Haengende Vorgaenge nachziehen. Ohne --apply nur Bericht.
|
|
* Cron-Vorschlag (alle 15 Minuten): ... cli.php reconcile --apply >> logs/payments_reconcile.log
|
|
*
|
|
* ... cli.php init-key
|
|
* Schluesseldatei fuer die Secrets anlegen (einmalig je Server).
|
|
*
|
|
* ... cli.php secret <modul> <name> [wert]
|
|
* Secret setzen (wert leer = von STDIN lesen, damit es nicht in der Shell-History landet).
|
|
*
|
|
* ... cli.php status
|
|
* Installierte Anbieter, Modus, hinterlegte Secrets, offene Vorgaenge.
|
|
*/
|
|
declare(strict_types=1);
|
|
|
|
if (PHP_SAPI !== 'cli') {
|
|
\http_response_code(403);
|
|
exit('cli only');
|
|
}
|
|
|
|
require __DIR__ . '/bootstrap.php';
|
|
|
|
use Payments\Registry as PR;
|
|
use Payments\Secrets;
|
|
|
|
$args = $argv;
|
|
\array_shift($args);
|
|
$cmd = $args[0] ?? 'status';
|
|
|
|
switch ($cmd) {
|
|
case 'init-key':
|
|
$path = Secrets::ensureKey();
|
|
echo "Schluessel: $path\n";
|
|
break;
|
|
|
|
case 'secret':
|
|
[$module, $name] = [$args[1] ?? '', $args[2] ?? ''];
|
|
if ($module === '' || $name === '') {
|
|
exit("usage: secret <modul> <name> [wert]\n");
|
|
}
|
|
$value = $args[3] ?? '';
|
|
if ($value === '') {
|
|
echo "Wert (Eingabe unsichtbar, Enter zum Beenden): ";
|
|
\system('stty -echo');
|
|
$value = \trim((string) \fgets(STDIN));
|
|
\system('stty echo');
|
|
echo "\n";
|
|
}
|
|
Secrets::set($base_object->db, $module, $name, $value);
|
|
echo "gespeichert: $module/$name (" . \strlen($value) . " Zeichen)\n";
|
|
break;
|
|
|
|
case 'reconcile':
|
|
$apply = \in_array('--apply', $args, true);
|
|
$modules = \array_values(\array_filter(\array_slice($args, 1), static fn($a) => $a !== '--apply'));
|
|
if (!$modules) {
|
|
$modules = PR::all();
|
|
}
|
|
foreach ($modules as $m) {
|
|
$p = PR::get($m, $base_object);
|
|
if (!$p) {
|
|
echo "[$m] nicht installiert\n";
|
|
continue;
|
|
}
|
|
try {
|
|
$lines = $p->reconcile(!$apply);
|
|
} catch (\Throwable $e) {
|
|
echo '[' . \date('Y-m-d H:i:s') . "] [$m] FEHLER " . $e->getMessage() . "\n";
|
|
continue;
|
|
}
|
|
foreach ($lines as $l) {
|
|
echo '[' . \date('Y-m-d H:i:s') . "] [$m] $l\n";
|
|
}
|
|
if (!$lines) {
|
|
echo '[' . \date('Y-m-d H:i:s') . "] [$m] nichts offen\n";
|
|
}
|
|
}
|
|
break;
|
|
|
|
case 'status':
|
|
default:
|
|
echo 'Schluesseldatei: ' . Secrets::keyPath() . ' -> ' . (Secrets::keyAvailable() ? 'vorhanden' : 'FEHLT') . "\n";
|
|
foreach (PR::all() as $m) {
|
|
$p = PR::get($m, $base_object);
|
|
if (!$p) {
|
|
continue;
|
|
}
|
|
$secrets = Secrets::keyAvailable() ? Secrets::status($base_object->db, $m) : [];
|
|
$res = $base_object->db->query("SELECT id, name, active FROM payment_methods WHERE module='" . $base_object->db->real_escape_string($m) . "'");
|
|
$pm = $res ? $res->fetch_object() : null;
|
|
echo "\n[$m] " . $p->label() . ($p instanceof \Payments\Providers\PaypalV2\Provider ? ' Modus ' . $p->mode() : '') . "\n";
|
|
echo ' Zahlart: ' . ($pm ? "id {$pm->id} '{$pm->name}' " . ($pm->active ? 'aktiv' : 'inaktiv') : 'NICHT angelegt') . "\n";
|
|
foreach ($p->secretFields() as $name => $label) {
|
|
echo " $label: " . (isset($secrets[$name]) ? 'hinterlegt (' . $secrets[$name] . ')' : '-') . "\n";
|
|
}
|
|
$res = $base_object->db->query("SELECT status, COUNT(*) c FROM payment_transactions WHERE provider='" . $base_object->db->real_escape_string($m) . "' GROUP BY status");
|
|
while ($res && ($r = $res->fetch_object())) {
|
|
echo " Vorgaenge {$r->status}: {$r->c}\n";
|
|
}
|
|
}
|
|
break;
|
|
}
|