Я создал пользовательский модуль оплаты и в настоящее время он вызывает validateOrder()
после перенаправления с сайта оплаты, и этот метод создает заказ, отправляет электронное письмо и т. д. Но проблема в том, что если пользователь закрыл сайт оплаты, прежде чем он сможет перенаправить обратно на сайт PrestaShop, в этом случае заказ не будет создан. Итак, я хочу создать заказ (скажем, с "pending"
статус), прежде чем я перенаправлю на сайт оплаты и после перенаправления с сайта оплаты я могу просто пометить тот же платеж как выполненный и отправить почту и т. д.
В настоящее время для этого я пытался позвонить validateOrder
дважды, один раз в hookdisplayPayment
(здесь я установил статус как "pending"
) и один раз после перенаправления. Но теперь после перенаправления я получаю сообщение «Невозможно загрузить корзину, или с помощью этой корзины уже был сделан заказ». Я думаю, это потому, что я не могу обновить один и тот же заказ дважды, используя один и тот же идентификатор карты.
Обратите внимание, что я хочу отправлять электронные письма только один раз, как только платеж будет успешным. В настоящее время для этого я использую пользовательский статус оплаты с 'send_email'
установить на 0.
Какой хороший обходной путь для этого?
Я хотел бы поддерживать версии 1.5+ и 1.6+, если это имеет значение.
Лучший способ сделать это, чем мой первый ответ, — создать переопределение в вашем модуле функции. validateOrder
,
Вы измените:
/** @var Order $order */
$order = new Order();
В:
/** @var Order $order */
$order = new Order($this->currentOrder);
Затем проверьте, загружен ли объект, пропустите часть, в которой он устанавливает поля порядка. Если он не загружен, установите поля порядка соответственно с ожидающим статусом.
Также проверьте, установлен ли $ this-> currentOrder, куда отправляется электронная почта, если она не установлена, пропустите часть электронной почты. Если он установлен, это означает, что заказ находится на рассмотрении, и вы должны изменить статус и отправить электронное письмо.
После переопределения функции вы можете вызвать validateOrder
дважды, до и после перенаправления.
Вы можете попробовать что-то вроде этого:
Перед перенаправлением вы можете вызвать один раз функцию validateOrder
и установить статус как pending
, Это установит для вашего модуля переменную $this->currentOrder
с идентификатором отложенного ордера.
После перенаправления не звоните снова validateOrder
, но создайте свою собственную функцию для вызова, например. validateOrderAfterRedirect
в котором вы проверяете, что была произведена оплата и меняете статус текущего заказа. Это будет что-то вроде этого:
// your way of checking that te payment was made
$payment_completed = $this->paymentIsComplete();
if($payment_completed) {
$order = new Order($this->currentOrder);
if(Validate::isLoadedObject($order) && $order->getCurrentOrderState() == [id of pending status]) {
$order->setCurrentState([id of payment accepted status]);
}
}
Создайте заказ со статусом «ожидающий платеж», прежде чем сайт будет перенаправлен в платежную систему. Как только клиент вернется, система должна просто изменить статус платежа на «завершен». Если клиент закрывает сайт оплаты, статус останется «ожидающим» и должен быть обновлен вручную после проверки платежной системы.
Многие платежные шлюзы предоставляют механизм, при котором при совершенном или неудавшемся платеже они публикуют данные, включая оплаченную сумму и идентификатор корзины, на URL-адрес, который вы им предоставляете.
Когда вы обрабатываете эту информацию с помощью серверного скрипта на этом этапе, вы можете проверить заказ. Это должно произойти до того, как пользователь будет перенаправлен обратно на ваш сайт. Как только они будут перенаправлены на ваш сайт, он уже подтвердил платеж в фоновом режиме.
Причина, по которой этот метод предпочтителен, заключается в том, что это единственный способ убедиться, что клиент не может манипулировать URL-адресом, чтобы заставить ваш магазин думать, что он заплатил за заказ, хотя на самом деле деньги не перешли в другие руки, после чего вы можете в конечном итоге отправить товары для свободно.
Вы можете сделать это, добавив несколько таких
$result = $this->validateOrder((int) $cart->id, Configuration::get('PPQ_CREATED_STATUS'), $total, $this->displayName, NULL, array(), (int) $currency->id, false, $customer->secure_key);
в любых играх, где вам нужно до перенаправления (где $ это экземпляр платежного модуля)
И после перенаправления для подтверждения страницы я использую написал это
public function hookPaymentReturn($params)
{
$id_module = (int) Tools::getValue('id_module');
if ($id_module === (int) $this->id) {
$orderHistory = new OrderHistory();
$orderHistory->changeIdOrderState(Configuration::get('PPQ_SUCCESS_STATUS'), $params['objOrder']);
}
}
Для отправки почты вы можете настроить необходимый статус заказа
Для моего случая (нужно работать только с PayPal, я должен изменить написать свой собственный модуль проверки на одну страницу и написать свой собственный модуль оплаты и перед перенаправлением на PayPal я написал это
public function hookPayment($params)
{
$customer = &$this->context->customer;
$cart = &$this->context->cart;
$currency = &$this->context->currency;
if (
$customer->isLogged(true) &&
$cart->nbProducts()
) {
$total = (float) $cart->getOrderTotal(true, Cart::BOTH);
$result = $this->validateOrder((int) $cart->id, Configuration::get('PPQ_CREATED_STATUS'), $total, $this->displayName, NULL, array(), (int) $currency->id, false, $customer->secure_key);
if ($result) {
if (!Configuration::get('PPQ_TEST_MODE')) {
$paypal_url = 'https://www.paypal.com/cgi-bin/webscr?cmd=_xclick&business=' . Configuration::get('PPQ_PROFILE');
} else {
$paypal_url = 'https://www.sandbox.paypal.com/cgi-bin/webscr?cmd=_xclick&business=' . Configuration::get('PPQ_PROFILE');
}
$order_confirmation_url = $this->context->link->getPageLink('order-confirmation', null, null, array(
'id_cart' => (int) $cart->id,
'id_module' => (int) $this->id,
'id_order' => (int) $this->currentOrder,
'key' => $customer->secure_key,
));
$this->context->smarty->assign(array(
'paypal_url' => $paypal_url,
'order_confirmation_url' => $order_confirmation_url,
'order_id' => (int) $this->currentOrder,
'shop_name' => $this->context->shop->name,
'total_without_shipping' => Tools::convertPriceFull((float) $cart->getOrderTotal(true, Cart::BOTH_WITHOUT_SHIPPING)),
'total_shipping' => Tools::convertPriceFull((float) $cart->getOrderTotal(true, Cart::ONLY_SHIPPING)),
'currency_iso' => Tools::strtoupper($currency->iso_code)
));
return $this->display(__FILE__, 'paypalquick.tpl');
} else {
$this->context->controller->errors[] = $this->l('Can\'t create order. Pleas contact with us');
}
} else {
$this->context->controller->errors[] = $this->l('Problem with loginin or cart empty');
}
}
и тпл
<form id="paypalquick" action="{$paypal_url}" method="post" enctype="multipart/form-data">
<input type="hidden" value="{l s='%s order #%s' sprintf=[$shop_name|escape:'html':'UTF-8', $order_id|intval] mod='paypalquick'}" name="item_name"/>
<input type="hidden" value="{$total_without_shipping}" name="amount"/>
<input type="hidden" value="{$total_shipping}" name="shipping"/>
<input type="hidden" value="{$currency_iso}" name="currency_code"/>
<input type="hidden" value="{$order_confirmation_url}" name="return"/>
<div class="text-center">
<button class="submit">{l s='Go to PayPal for payment' mod='paypalquick'}</button>
</div>
Но это был мой личный случай, вы не можете использовать его по умолчанию, но вы можете увидеть, как это сделать.
Я думаю, что нам нужно, чтобы вы вызвали еще один хук (который вы создали) во время проверки на сайте (перед тем как оставить этот вопрос), который поставил статус ожидания, и оставил хук ValidateOrder () для подтверждения оплаты
С Уважением,
Артур