getRequestBody(); // If request body is empty, log and exit. if (empty($requestBody)) { PrestaShopLogger::addLog('Hutko Callback: Empty request body received.', 2, null, 'Cart', null, true); exit('Empty request'); } // Assuming validateResponse returns true on success, or a string error message on failure. $isSignatureValid = $this->module->validateResponse($requestBody); if ($isSignatureValid !== true) { PrestaShopLogger::addLog('Hutko Callback: Invalid signature. Error: ' . $isSignatureValid, 2, null, 'Cart', null, true); exit('Invalid signature'); } // PrestaShopLogger::addLog('Hutko Callback: ' . json_encode($requestBody), 1); $transaction_id = $requestBody['order_id']; $orderIdParamParts = explode($this->module->order_separator, $transaction_id); $orderId = (int)$orderIdParamParts[0]; // Ensure it's an integer // If we reached here, an order should exist. Load it. $order = new Order($orderId); if (!Validate::isLoadedObject($order)) { PrestaShopLogger::addLog('Hutko Callback: Order could not be loaded for ID: ' . $orderId, 3, null, 'Order', $orderId, true); exit('Order not found after validation'); } // 7. Handle payment status from the callback. $orderStatusCallback = $requestBody['order_status']; $currentOrderState = (int)$order->getCurrentState(); switch ($orderStatusCallback) { case 'approved': // Only success state if no refunds was done. if ($requestBody['response_status'] == 'success' && (int)$requestBody['reversal_amount'] === 0) { $expectedState = (int)Configuration::get('HUTKO_SUCCESS_STATUS_ID', null, null, null, Configuration::get('PS_OS_PAYMENT')); // Only change state if it's not already the success state or "Payment accepted". if ($currentOrderState !== $expectedState) { $this->module->addPayment($requestBody, $order); $order->setCurrentState($expectedState); } } else { PrestaShopLogger::addLog('Hutko Callback: Unhandled response_status: ' . $requestBody['response_status']); } exit('OK'); break; case 'declined': $expectedState = (int)Configuration::get('PS_OS_ERROR'); // Only change state if it's not already the error state. if ($currentOrderState !== $expectedState) { $order->setCurrentState($expectedState); } exit('Order ' . $orderStatusCallback); break; case 'expired': $expectedState = (int)Configuration::get('PS_OS_ERROR'); // Only change state if it's not already the error state. if ($currentOrderState !== $expectedState) { $order->setCurrentState($expectedState); } exit('Order ' . $orderStatusCallback); break; case 'processing': // If the order is still processing, we might want to update its status // to a specific 'processing' state if available, or just acknowledge. // For now, if it's not already in a success/error state, set it to 'processing'. $processingState = (int)Configuration::get('PS_OS_PAYMENT'); // Or a custom 'processing' state if ($currentOrderState !== $processingState && $currentOrderState !== (int)Configuration::get('HUTKO_SUCCESS_STATUS_ID') && $currentOrderState !== (int)Configuration::get('PS_OS_ERROR')) { $order->setCurrentState($processingState); } exit('Processing'); break; default: // Log unexpected status and exit with an error. PrestaShopLogger::addLog('Hutko Callback: Unexpected order status received: ' . $orderStatusCallback . ' for order ID: ' . $orderId, 3, null, 'Order', $orderId, true); exit('Unexpected status'); break; } } catch (Exception $e) { // Log any uncaught exceptions and exit with the error message. PrestaShopLogger::addLog('Hutko Callback Error: ' . $e->getMessage(), 3, null, 'HutkoCallbackModuleFrontController', null, true); exit($e->getMessage()); } } /** * Helper method to parse the request body from POST or raw input. * * @return array The parsed request body. */ private function getRequestBody(): array { $jsonBody = json_decode(file_get_contents("php://input"), true); if (is_array($jsonBody)) { return $jsonBody; } return []; } }