added order message logging

This commit is contained in:
O K
2025-06-02 11:24:18 +03:00
parent 67ff82de5d
commit 638d801a8e
5 changed files with 216 additions and 117 deletions

218
hutko.php
View File

@@ -35,7 +35,8 @@ class Hutko extends PaymentModule
'HUTKO_SHIPPING_PRODUCT_CODE',
'HUTKO_NEW_ORDER_STATUS_ID',
'HUTKO_SUCCESS_STATUS_ID',
'HUTKO_SHOW_CARDS_LOGO'
'HUTKO_SHOW_CARDS_LOGO',
'HUTKO_SAVE_LOGS'
];
public $postErrors = [];
@@ -260,6 +261,24 @@ class Hutko extends PaymentModule
)
),
),
array(
'type' => 'radio',
'label' => $this->trans('Save Logs', array(), 'Modules.Hutko.Admin'),
'name' => 'HUTKO_SAVE_LOGS',
'is_bool' => true,
'values' => array(
array(
'id' => 'save_logs',
'value' => 1,
'label' => $this->trans('Yes', array(), 'Modules.Hutko.Admin')
),
array(
'id' => 'discard_logs',
'value' => 0,
'label' => $this->trans('No', array(), 'Modules.Hutko.Admin')
)
),
),
),
'submit' => array(
@@ -405,7 +424,7 @@ class Hutko extends PaymentModule
if (Configuration::get('HUTKO_SHIPPING_INCLUDE') && $order->total_shipping_tax_incl > 0) {
$amount = $order->total_products_wt + $order->total_shipping_tax_incl;
} else {
$amount = $order->total_products;
$amount = $order->total_products_wt;
}
}
@@ -727,13 +746,7 @@ class Hutko extends PaymentModule
$history->addWithemail();
}
}
public function addPayment(array $callback, Order $order): void
{
$callbackAmount = $callback['actual_amount'] ?? $callback['amount'];
$amountFloat = round($callbackAmount / 100, 2);
$order->addOrderPayment($amountFloat, $this->displayName, $callback['order_id'], $order->id_currency);
}
/**
@@ -789,16 +802,8 @@ class Hutko extends PaymentModule
*/
public function displayAdminOrderContent(array $params): string
{
// Check if a refund form has been submitted
if (Tools::isSubmit('hutkoRefundsubmit')) {
// Process the refund logic.
$this->processRefundForm();
}
// Check payment status
if (Tools::getValue('hutkoOrderPaymentStatus')) {
// Process the requested order status check.
$this->processOrderPaymentStatus(Tools::getValue('hutkoOrderPaymentStatus'));
if (!Configuration::get('HUTKO_MERCHANT') || empty(Configuration::get('HUTKO_MERCHANT') || !Configuration::get('HUTKO_SECRET_KEY') || empty(Configuration::get('HUTKO_SECRET_KEY')))) {
return '';
}
// Ensure the 'order' object is present in the parameters
@@ -816,6 +821,19 @@ class Hutko extends PaymentModule
return '';
}
// Check if a refund form has been submitted
if (Tools::isSubmit('hutkoRefundsubmit')) {
// Process the refund logic.
$this->processRefundForm();
}
// Check payment status
if (Tools::getValue('hutkoOrderPaymentStatus')) {
// Process the requested order status check.
$this->renderOrderPaymentStatus(Tools::getValue('hutkoOrderPaymentStatus'));
}
// Get the Order object from the parameters
$order = $params['order'];
@@ -837,31 +855,37 @@ class Hutko extends PaymentModule
// Pass the order ID to the template
'id_order' => $order->id,
'currency' => new Currency($order->id_currency),
'hutkoOrderPaymentStatus' => $this->context->session->get('hutkoOrderPaymentStatus'),
]);
// Render the template located at 'views/templates/admin/order_payment_refund.tpl'
// This template will display the fetched payment information and potentially refund/status forms.
return $this->display(__FILE__, 'views/templates/admin/order_payment_refund.tpl');
}
public function renderOrderPaymentStatus(string $order_id)
{
public function processOrderPaymentStatus(string $order_id): void
$data = $this->getOrderPaymentStatus($order_id);
$this->context->session->set('hutkoOrderPaymentStatus', $this->displayArrayInNotification($data['response']));
Tools::redirectAdmin($this->context->controller->currentIndex);
}
public function getOrderPaymentStatus(string $order_id): array
{
$data = [
'order_id' => $order_id,
'merchant_id' => Configuration::get('HUTKO_MERCHANT', null),
'merchant_id' => Configuration::get('HUTKO_MERCHANT'),
'version' => '1.0',
];
$data['signature'] = $this->getSignature($data);
$response = $this->sendAPICall($this->status_url, $data);
$this->context->controller->informations[] = $this->displayArrayInNotification($response['response']);
return $this->sendAPICall($this->status_url, $data);
}
public function processRefundForm()
{
$orderPaymentId = (int) Tools::getValue('orderPaymentId');
$amount = (float) Tools::getValue('refund_amount');
$comment = mb_substr(Tools::getValue('orderPaymentId', ''), 0, 1024);
$comment = mb_substr(Tools::getValue('comment', ''), 0, 1024);
$id_order = (int) Tools::getValue('id_order');
$result = $this->processRefund($orderPaymentId, $id_order, $amount, $comment);
$link = $this->context->link->getAdminLink('AdminOrders', true, [], ['id_order' => $id_order, 'vieworder' => true]);
@@ -871,7 +895,7 @@ class Hutko extends PaymentModule
if ($result->success) {
$this->context->controller->informations[] = $result->description;
}
// Tools::redirectAdmin($link);
Tools::redirectAdmin($link);
}
/**
@@ -882,17 +906,18 @@ class Hutko extends PaymentModule
* updates the order history, and logs the action.
*
* @param int $orderPaymentId The ID of the OrderPayment record to refund.
* @param int $orderId The ID of the Order to refund.
* @param int $id_order The ID of the Order to refund.
* @param float $amount The amount to refund.
* @param string $comment A comment or reason for the refund.
* @return stdClass Result description.
* @throws Exception If the OrderPayment is not found, invalid, or refund fails.
*/
public function processRefund(int $orderPaymentId, int $orderId, float $amount, string $comment = ''): stdClass
public function processRefund(int $orderPaymentId, int $id_order, float $amount, string $comment = ''): stdClass
{
$result = new stdClass();
$result->error = false;
// 1. Load the OrderPayment object.
$order = new Order($id_order);
$orderPayment = new OrderPayment($orderPaymentId);
$currency = new Currency($orderPayment->id_currency);
if (!Validate::isLoadedObject($orderPayment)) {
@@ -907,8 +932,8 @@ class Hutko extends PaymentModule
throw new Exception($this->trans('Order payment not found.', [], 'Modules.Hutko.Admin'));
}
// 2. Validate the transaction_id format and extract cart ID.
// Assuming transaction_id is in the format "cartID|timestamp" or "cartID-timestamp"
// Validate the transaction_id format and extract cart ID.
// Assuming transaction_id is in the format "orderID#timestamp"
$transactionIdParts = explode($this->order_separator, $orderPayment->transaction_id);
$cartId = (int)$transactionIdParts[0];
@@ -926,41 +951,90 @@ class Hutko extends PaymentModule
$response = $this->refundAPICall($orderPayment->transaction_id, $amount, $currency->iso_code, $comment);
if ($response['response']['response_status'] === 'failure') {
if ($response['response']['reverse_status'] === 'approved' && $response['response']['response_status'] === 'success') {
$result->success = true;
$result->description = $this->trans('Refund success.', [], 'Modules.Hutko.Admin');
} else {
PrestaShopLogger::addLog(
'Hutko Refund: refund failure response: ' . json_encode($response),
3, // Info
null,
'OrderPayment',
$orderPaymentId,
true
);
$this->addOrderMessage($order, $this->trans('Refund Failed. Please check actual amount in Hutko account page.', [], 'Modules.Hutko.Admin'));
$result->error = true;
$result->description = $response['response']['error_message'];
return $result;
}
if ($response['response']['response_status'] === 'success') {
$result->success = true;
$result->description = $this->trans('Refund success.', [], 'Modules.Hutko.Admin');
}
$amountFloat = round((int)$response['response']['reversal_amount'] / 100, 2);
$order = new Order($orderId);
$this->addOrderMessage($order, $this->trans('Refund success.', [], 'Modules.Hutko.Admin') . ' ' . $currency->iso_code . $amountFloat);
$order->addOrderPayment($amountFloat, $this->displayName, $orderPayment->transaction_id . '_refund', $currency);
$order->setCurrentState((int)Configuration::get('PS_OS_REFUND'));
// Add a private message to the order for tracking.
$order->addOrderPayment(
-$amount, // Negative amount for refund
$this->displayName,
$orderPayment->transaction_id
);
$order->setCurrentState((int)Configuration::get('PS_OS_REFUND'), $this->context->employee->id);
PrestaShopLogger::addLog(
'Hutko Refund: Successfully processed refund for Order: ' . $orderId . ', Amount: ' . $amount . ', Comment: ' . $comment,
1, // Info
null,
'OrderPayment',
$orderPaymentId,
true
);
return $result;
}
public function addOrderMessage(Order $order, string $message)
{
try {
$customer = new Customer($order->id_customer);
$thread = CustomerThread::getIdCustomerThreadByEmailAndIdOrder($customer->email, $order->id);
if (is_int((int) $thread) && $thread != 0) {
$thread = (int) $thread;
} else {
$customer_thread = new CustomerThread();
$customer_thread->id_contact = 0;
$customer_thread->id_customer = (int) $order->id_customer;
$customer_thread->id_shop = (int) $order->id_shop;
$customer_thread->id_order = (int) $order->id;
$customer_thread->id_lang = (int) $this->context->language->id;
$customer_thread->email = $customer->email;
$customer_thread->status = 'open';
$customer_thread->token = Tools::passwdGen(12);
$customer_thread->add();
$thread = $customer_thread->id;
}
$customer_message = new CustomerMessage();
$customer_message->id_customer_thread = $thread;
$customer_message->id_employee = 1;
$customer_message->message = $message;
$customer_message->private = 1;
if (false === $customer_message->validateField('message', $customer_message->message)) {
throw new Exception('Invalid reply message');
}
if (false === $customer_message->add()) {
throw new Exception('Failed to add customer message');
}
} catch (Throwable $e) {
PrestaShopLogger::addLog('failed add message to order. ' . $e->getMessage() . ' | ' . $message, 3);
}
}
public function addRefundPayment(Order $order, OrderPayment $purchaseOrderPayment, float $amount)
{
$order_payment = new OrderPayment();
$order_payment->order_reference = $order->reference;
$order_payment->id_currency = $purchaseOrderPayment->id_currency;
$order_payment->payment_method = $purchaseOrderPayment->payment_method;
$order_payment->transaction_id = $purchaseOrderPayment->transaction_id . $this->order_separator . 'refund';
$order_payment->amount = $amount;
$order_payment->id_employee = 0;
$order_payment->add();
$order->total_paid_real = $order->total_paid_real - $amount;
$order->update();
}
/**
* Initiates a refund (reverse) request via Hutko API.
*
@@ -970,17 +1044,17 @@ class Hutko extends PaymentModule
* @param string $comment Optional comment for the refund.
* @return array Decoded API response array. Returns an error structure on failure.
*/
public function refundAPICall(string $order_id, float $amount, string $currency, string $comment = ''): array
public function refundAPICall(string $order_id, float $amount, string $currencyISO, string $comment = ''): array
{
// 1. Prepare the data payload
$data = [
'order_id' => $order_id,
// Assuming Configuration::get is available to fetch the merchant ID
'merchant_id' => Configuration::get('HUTKO_MERCHANT', null),
'merchant_id' => Configuration::get('HUTKO_MERCHANT'),
'version' => '1.0',
// Amount should be in minor units (cents, kopecks) and converted to string as per API example
'amount' => (string)round($amount * 100),
'currency' => $currency,
'amount' => round($amount * 100),
'currency' => $currencyISO,
];
if (!empty($comment)) {
@@ -1001,7 +1075,9 @@ class Hutko extends PaymentModule
*/
public function sendAPICall(string $url, array $data, int $timeout = 60): array
{
if (Configuration::get('HUTKO_SAVE_LOGS')) {
$this->log($url . ' <= ' . json_encode($data));
}
// Wrap the prepared data inside the 'request' key as required by the API
$requestPayload = ['request' => $data];
@@ -1062,7 +1138,9 @@ class Hutko extends PaymentModule
// Close CURL handle
curl_close($ch);
if (Configuration::get('HUTKO_SAVE_LOGS')) {
$this->log($url . ' => ' . $response);
}
// Process the response
// Decode the JSON response into a PHP array
$responseData = json_decode($response, true);
@@ -1127,7 +1205,21 @@ class Hutko extends PaymentModule
*/
public function isUsingNewTranslationSystem()
{
return true;
}
public function log($data)
{
if (!is_string($data)) {
$data = json_encode($data, JSON_UNESCAPED_UNICODE);
}
$logdirectory = _PS_ROOT_DIR_ . '/var/modules/' . $this->name . '/logs/' . date("Y") . '/' . date("m") . '/' . date("d") . '/';
if (!is_dir($logdirectory)) {
mkdir($logdirectory, 0750, true);
}
$logger = new \FileLogger(0); //0 == debug level, logDebug() wont work without this.
$logger->setFilename($logdirectory . 'dayly.log');
$logger->logInfo($data);
}
}