Files
drmaterac.pl/modules/paynow/controllers/front/notifications.php
2025-01-06 20:47:25 +01:00

171 lines
7.0 KiB
PHP

<?php
/**
* NOTICE OF LICENSE
*
* This source file is subject to the MIT License (MIT)
* that is bundled with this package in the file LICENSE.md.
*
* @author mElements S.A.
* @copyright mElements S.A.
* @license MIT License
*/
class PaynowNotificationsModuleFrontController extends PaynowFrontController
{
public function process()
{
$payload = trim(Tools::file_get_contents('php://input'));
$headers = $this->getRequestHeaders();
$notification_data = json_decode($payload, true);
PaynowLogger::info(
'Incoming notification {externalId={}, paymentId={}, status={}}',
[
$notification_data['externalId'],
$notification_data['paymentId'],
$notification_data['status']
]
);
try {
new Notification($this->module->getSignatureKey(), $payload, $headers);
$filtered_payments = $this->getFilteredPayments(
$notification_data['externalId'],
$notification_data['paymentId'],
$notification_data['status']
);
$filtered_payment = reset($filtered_payments);
if ($filtered_payment && Paynow\Model\Payment\Status::STATUS_CONFIRMED === $filtered_payment->status) {
PaynowLogger::info(
'An order already has a paid status. Skipped notification processing {externalId={}, paymentId={}, status={}}',
[
$notification_data['externalId'],
$notification_data['paymentId'],
$notification_data['status']
]
);
header("HTTP/1.1 202 Accepted");
exit;
}
if (empty($filtered_payments)) {
PaynowLogger::warning(
'Payment for order or cart not exists {externalId={}, paymentId={}, status={}}',
[
$notification_data['externalId'],
$notification_data['paymentId'],
$notification_data['status']
]
);
header('HTTP/1.1 400 Bad Request', true, 400);
exit;
}
$cart = new Cart((int)$filtered_payment->id_cart);
if (1 <= count($filtered_payments) && $this->canProcessCreateOrder(
(int)$filtered_payment->id_order,
$notification_data['status'],
(int)$filtered_payment->locked,
$cart->orderExists()
)) {
PaynowLogger::info(
'Processing notification to create new order from cart {cartId={}, externalId={}, paymentId={}, locked={}}',
[
$filtered_payment->id_cart,
$notification_data['externalId'],
$notification_data['paymentId'],
$filtered_payment->locked
]
);
if ((float)$filtered_payment->total === $cart->getCartTotalPrice()) {
$this->order = $this->createOrder($cart, $notification_data['externalId'], $notification_data['paymentId']);
$filtered_payments = $this->getFilteredPayments(
$notification_data['externalId'],
$notification_data['paymentId'],
$notification_data['status']
);
$filtered_payment = reset($filtered_payments);
} else {
PaynowLogger::warning(
'Inconsistent payment and cart amount {cartAmount={}, cartId={}, externalId={}, paymentId={}, paymentAmount={}}',
[
$cart->getCartTotalPrice(),
$cart->id,
$notification_data['externalId'],
$notification_data['paymentId'],
$filtered_payment->total
]
);
}
} else {
if (!PaynowPaymentData::findByPaymentId($notification_data['paymentId'])) {
$previous_payment_data = PaynowPaymentData::findLastByExternalId($notification_data['externalId']);
if ($previous_payment_data) {
PaynowPaymentData::create(
$notification_data['paymentId'],
$notification_data['status'],
$previous_payment_data->id_order,
$previous_payment_data->id_cart,
$previous_payment_data->order_reference,
$previous_payment_data->external_id,
$previous_payment_data->total
);
}
}
}
(new PaynowOrderStateProcessor($this->module))->updateState(
(int)$filtered_payment->id_order,
$notification_data['paymentId'],
(int)$filtered_payment->id_cart,
$filtered_payment->order_reference,
$filtered_payment->external_id,
$filtered_payment->status,
$notification_data['status']
);
} catch (Exception $exception) {
PaynowLogger::error(
'An error occurred during processing notification {externalId={}, paymentId={}, status={}, message={}}',
[
$notification_data['externalId'],
$notification_data['paymentId'],
$notification_data['status'],
$exception->getMessage()
]
);
header('HTTP/1.1 400 Bad Request', true, 400);
exit;
}
header("HTTP/1.1 202 Accepted");
exit;
}
private function getRequestHeaders(): array
{
$headers = [];
foreach ($_SERVER as $key => $value) {
if (Tools::substr($key, 0, 5) == 'HTTP_') {
$subject = str_replace('_', ' ', Tools::strtolower(Tools::substr($key, 5)));
$headers[str_replace(' ', '-', ucwords($subject))] = $value;
}
}
return $headers;
}
private function getFilteredPayments($external_id, $payment_id, $payment_status): array
{
$payments = PaynowPaymentData::findAllByExternalIdAndPaymentId($external_id, $payment_id)->getResults();
if (!$payments) {
$payments = PaynowPaymentData::findAllByExternalId($external_id)->getResults();
return array_filter($payments, function ($payment) use ($payment_id, $payment_status) {
return $payment->id_payment === $payment_id ||
$payment_status === Paynow\Model\Payment\Status::STATUS_NEW;
});
}
return $payments;
}
}