fix(payments): Express-Rueckkehr nach zweiter PayPal-Freigabe nimmt den normalen Rueckweg mit Capture

PayPal Live antwortet auf den Capture nach dem Betrags-PATCH mit 422 PAYER_ACTION_REQUIRED
(Sandbox nicht). Der Kunde gibt erneut frei und kehrt ueber ?payment_express= zurueck; dort
scheiterte onExpressReturn an custom_id != 'express' und zeigte eine Fehlerseite, waehrend
die Bestellung offen blieb (Live-Bestellung 312143).
This commit is contained in:
Thomas Bartelt
2026-09-18 07:30:17 +02:00
parent b8bc8aa8bf
commit c8fc7fba2f
2 changed files with 1414 additions and 1395 deletions
+11
View File
@@ -128,6 +128,17 @@ abstract class AbstractProvider implements ProviderInterface
Log::write($module, 'start', $orderId, $number, $reference, 'open', null, $raw); Log::write($module, 'start', $orderId, $number, $reference, 'open', null, $raw);
} }
/**
* Gibt es zu dieser Anbieter-Referenz schon einen Vorgang (mit Bestellung)?
* Braucht die Kasse bei der Express-Rueckkehr: verlangt PayPal nach dem Betrags-PATCH
* eine zweite Freigabe, kommt der Kunde ueber die Express-URL zurueck, obwohl die
* Bestellung laengst existiert -- dann ist es eine normale Rueckkehr mit Capture.
*/
public function knownReference(string $reference): bool
{
return $reference !== '' && $this->transactionByReference($reference) !== null;
}
protected function transactionByReference(string $reference): ?object protected function transactionByReference(string $reference): ?object
{ {
$stmt = $this->db->prepare('SELECT * FROM payment_transactions WHERE provider=? AND reference=? LIMIT 1'); $stmt = $this->db->prepare('SELECT * FROM payment_transactions WHERE provider=? AND reference=? LIMIT 1');
+8
View File
@@ -407,6 +407,14 @@ class website_cashdesk {
$module = strtolower(trim((string)$_GET['payment_express'])); $module = strtolower(trim((string)$_GET['payment_express']));
$provider = $this->payment_provider($module); $provider = $this->payment_provider($module);
$data = null; $data = null;
// 18.09.2026 -- zweite Freigabe: PayPal Live verlangt nach dem Betrags-PATCH (Versand)
// eine erneute Freigabe, der Kunde kommt danach ueber DIESE URL zurueck. Die Bestellung
// und der Vorgang existieren dann schon -> normaler Rueckweg mit Capture, nicht noch
// einmal die Kasse vorbelegen (custom_id ist da auch nicht mehr 'express').
if ($provider && $provider->knownReference((string)($_GET['token'] ?? ''))) {
$_GET['payment_return'] = $module;
return $this->payment_provider_return();
}
if ($provider && $provider->supportsExpress()) { if ($provider && $provider->supportsExpress()) {
try { try {
$data = $provider->onExpressReturn($_GET); $data = $provider->onExpressReturn($_GET);