Hallo zusammen,
das Problem tritt bei uns ebenfalls auf, JTL-
Shop 5.4 mit PayPal Plugin 2.1.1. Onboarding wurde neu durchgeführt und alle vier Webhooks sind im Plugin sichtbar.
Die Bestellungen werden zum Glück angelegt und die Zahlungen kommen an.
Folgender Fehler tritt sporadisch, jedoch mehrmals täglich, bei Bestellungen über PayPal Commerce im
Logbuch auf (/admin/systemlog):
[JTL_PAYPAL_COMMERCE] INFORMATION: Webhook::handleCall - capture failed for method PayPal Checkout
Für betreffende Bestellungen wird dann jeweils folgender Eintrag im Zahlungslog von PayPal Checkout hinterlegt (/admin/paymentmethods):
[JTL_PAYPAL_COMMERCE] PAYMENT: handleCaptureWebhook: shop order does not existsstdClass Object ( [kBestellung] => 12345 [kZahlungsart] => 345 [cId] => [txn_id] => )
Bemerkenswert ist hier, dass txn_id bei allen Einträgen leer ist.
Über kBestellung kann die betreffende Bestellung jedoch in der Datenbank (tBestellung) ausfindig gemacht und geprüft werden - in unseren Stichproben sieht das soweit okay aus.
Der Fehler wird in handleCaptureWebhook() in PayPalPayment.php geschmissen:
$ppOrder === null da
empty($payment->txn_id)
https://gitlab.com/jtl-software/jtl.../master/paymentmethod/PayPalPayment.php#L1377
PHP:
public function handleCaptureWebhook(string $eventType, Capture $capture, object $payment): bool
{
$logObject = new ObjectLogger($payment);
$this->getLogger()->write(\LOGLEVEL_DEBUG, 'handleCaptureWebhook', $logObject);
$ppOrder = !empty($payment->txn_id) ? $this->getPPOrder($payment->txn_id) : null;
$shopOrder = $ppOrder !== null ? $this->helper->getShopOrder($ppOrder) : null;
if ($ppOrder === null || $shopOrder === null) {
$this->getLogger()->write(\LOGLEVEL_ERROR, 'handleCaptureWebhook: shop order does not exists', $logObject);
return false;
}
Wo sollte
$payment->txn_id herkommen? Sehen wir nach:
handleCaptureWebhook() wird zuvor von der gleichnamigen Funktion in WebhookHandler.php aufgerufen:
https://gitlab.com/jtl-software/jtl...ster/frontend/Handler/WebhookHandler.php#L118
PHP:
private function handleCaptureWebhook(WebhookCallResponse $response, string $eventType): void
{
try {
$capture = new Capture($response->getData());
} catch (JsonException | UnexpectedResponseException $e) {
$this->logger->write(\LOGLEVEL_ERROR, 'Webhook::handleCall - Unexpected data for payment process id: '
. $e->getMessage());
self::exitResult(400, 'Unexpected data for payment process id.');
exit();
}
$db = Shop::Container()->getDB();
$txnId = $capture->getRelatedOrderId();
$payment = $db->getSingleObject(
'SELECT tbestellung.kBestellung, COALESCE(tzahlungsid.kZahlungsart,
tbestellung.kZahlungsart) AS kZahlungsart,
tzahlungsid.cId, tzahlungsid.txn_id
FROM tbestellung
LEFT JOIN tzahlungsid ON tbestellung.kBestellung = tzahlungsid.kBestellung
AND tzahlungsid.txn_id = :txnId
WHERE cBestellNr = :oderNumber',
[
'txnId' => $txnId,
'oderNumber' => $capture->getInvoiceId(),
]
);
if ($payment === null || (int)$payment->kZahlungsart === 0) {
// payment process id not found
// - there is no session hash created for the captured payment or payment is already processed
$this->logger->write(
\LOGLEVEL_NOTICE,
'Webhook::handleCall - No payment for order id ' . $txnId . ' found'
);
self::exitResult();
exit();
}
$paymentHelper = Helper::getInstance($this->plugin);
$payMethod = $paymentHelper->getPaymentFromID((int)$payment->kZahlungsart);
if ($payMethod === null) {
$this->logger->write(
\LOGLEVEL_NOTICE,
'Webhook::handleCall - No payment method for order id ' . $txnId . ' found'
);
self::exitResult();
exit();
}
$this->logger->setMethod($payMethod);
if (!$payMethod->handleCaptureWebhook($eventType, $capture, $payment)) {
$this->logger->write(
\LOGLEVEL_ERROR,
'Webhook::handleCall - capture failed for method ' . $payMethod->getMethod()->getName()
);
}
$payment->txn_id wird also aus der Datenbank aus Tabelle
tzahlungsid abgerufen. Für betroffene Zahlungen geprüft, die txn_id ist in der Datenbank (nachträglich) korrekt eingetragen und entspricht der PayPal Transaktions-ID.
Zum Zeitpunkt des Webhook Calls scheint der Zahlungseintrag in tzahlungsid jedoch noch nicht zu existieren, sonst würde es ja nicht zu dem Errorlog kommen.
Das war genug Debugging für heute, ich hoffe
@Sirko W. und das Team können das zügig beheben.
Ach ja, Tippfehler in einer Payment API machen sich nicht besonders gut, gerne direkt mit verbessern
- 'handleCaptureWebhook: shop order does not exist
s'
- 'orderNumber' => $capture->getInvoiceId()
ordertransaction id ' . $txnId
Grüße,
Marco