В первых двух частях проекта "Создаем плагин Hikashop" было рассказано, как создавать данные для запроса и отлаживать код php нашего скрипта. Не всё проходит гладко: для этого используем журнал отладки с помощью встроенной в HIKASHOP функции writeToLog - устраняем возникающие ошибки и недразумения.
Разговор далее пойдет о встроенной функции - public function onPaymentNotification(&$statuses) или о комплексе мер для получения данных от платежной системы (ПС) о проведенном платеже.
Для правильной работы любого платежного плагина (выдача уведомления о прохождении оплаты и информирование об этом покупателя) значение параметра ' notification ' должно быть включено - "получать уведомления о статусе заказа (об оплате)". Компонент Hikashop, как правило, использует для этих целей параметр - $notify_url (т.к. западные платежные системы (PayPal) по умолчанию используют именно этот параметр).
Сам параметр ' notify_url ' по стандарту Hikashop представляет собой абстрактный URL адрес и должен иметь обязательные аттрибуты, о которых мы поговорим далее.
Нельзя забывать, что существует 2 разновидности ' notify_url ' : html-сущность в функции-конструкторе и php-сущность в теле плагина - и они имеют разный код.
- html-сущность (отображение в браузере) - с использованием & в определенном месте кода
- php-сущность - с использованием разделителя &
Платежная система Сбербанка по умолчанию параметр ['notify_url'] не использует. Поэтому для работоспособности создаваемого плагина оплаты необходимо сообщить в техподдержку ПС о необходимости получать callback именно с помощью этого параметра .
Техподдержке Сбербанка для организации получения уведомлений о проведенных платежах надо передать именно php-сущность URL адреса - только это обеспечит вас в дальнейшем нужной информацией об оплате клиентом заказа в интернет-магазина (платежный шлюз вызывает этот URL, чтобы уведомить ваш плагин о платеже) - но иногда техподдержка ошибается и тогда Вам надо поманипулировать самим между сущностями $notify_url для получения callback от платежного шлюза.
Получать сообщения о статусе оплаты заказа, вообще-то, необязательно. Проверить поступление денег можно, мониторя Ваш расчетный счет в банке, как правило, оплата видна только на следующий день.
Но это значит, пустить дела на самотек, а такое отношение к делу никого не устраивает.
ОЧЕНЬ ВАЖНО !!!
Вообще, получить данные о статусе заказа в платежной системы Сбербанка можно несколькими способами:
- непосредственно из браузерной строки, на которую по умолчанию переходит Пользователь после оплаты заказа - сам параметр 'return_url' задается в плагине - а получение данных организовано, например,через функцию verifyIPN(), как это сделано в PalPay;
Сам ответ содержит 3 необходимых параметра - ['order_id'] , ['orderId'] , ['Itemid'] - и один необязательный ['lang']
- используя сокеты - через функцию fsockopen() - по аналогии с _sendRequestSocket ($url, $data);
Информация соединения с интернет-сокетом банка платежной системы через встроенную функцию php - fsockopen разнообразна - необходимо выбрать нужное (отсортировав информацию)
- используя стандартный запрос о статусе заказа - по наналогии с функциями _sendRequest ($url, $data) или _sendRequestCURL ($url, $data)
используя встроенную функцию php - curl и метод 'getOrderStatus.do'
Информация платежного шлюза обеспечивает нас тремя параметрами - ['status'] , ['mdOrder'] и ['orderNumber'] - этого достаточно для дальнейшей работы скрипта : загрузка базы данных $dbOrder = $this->getOrder((int)$vars['order_id']) по номеру заказа и использования метода Сбербанка getOrderStatus.do для получения дополнительных параметров для $email и $history для функции изменения статуса заказа - $this->modifyOrder($order_id,$order_status,$history,$email) внутри public function onPaymentNotification(&$statuses). Хотя решать Вам, отправлять информацию клиенту магазина или нет.
СЕКРЕТ №1
Есть несколько вариантов написания кода php для работоспособности скрипта (получение статуса заказа).
// через функцию public function onPaymentNotification(&$statuses)
// функции инициализируются через запись $this->fn
// переменная vars абстрактная и не привязана к переданным ранее шлюзу данным
$vars = array(); $filter = JFilterInput::getInstance(); foreach($_REQUEST as $key => $value) { $key = $filter->clean($key); if(preg_match('#^[0-9a-z_-]{1,30}$#i', $key) && !preg_match('#^cmd$#i', $key)) { $value = hikaInput::get()->getString($key); $vars[$key] = $value; } } $dbOrder = $this->getOrder((int)$vars['order_id']); $this->loadPaymentParams($dbOrder); if(empty($this->payment_params)) return false; $this->loadOrderData($dbOrder); if($this->payment_params->debug) // Режим отладки активирован { $this->writeToLog('получена переменная $vars ' .$vars['orderNumber']. ' из $_REQUEST')."\n\n"; echo print_r($vars,true)."\n\n\n"; //запись появится где-то внизу файла журнала платежей //echo print_r($dbOrder,true)."\n\n\n"; //приготовьтесь к получению -большой массив } if(!$this->payment_params->notification) return false; if(empty($dbOrder)) { $this->writeToLog('Не удалось загрузить заказ по уведомлению с платежного шлюза ' . @$vars['order_id']); return false; } $order_id = $dbOrder->order_id; $url = HIKASHOP_LIVE.'administrator/index.php?option=com_hikashop&ctrl=order&task=edit&order_id=' . $order_id; $this->writeToLog('адрес url : '.$url)."\r\n"; $order_text = "\r\n" . JText::sprintf('NOTIFICATION_OF_ORDER_ON_WEBSITE', $dbOrder->order_number, HIKASHOP_LIVE); $order_text .= "\r\n" . str_replace(' ', "\r\n", JText::sprintf('ACCESS_ORDER_WITH_LINK', $url, $url )); //2 url $this->writeToLog('order_text : '.$order_text); //дальнейшие шаги ///////////////////////////////////////////////////////////////////////////// $arg = array( 'userName' =>$this->payment_params->merchant_login, 'password' =>$this->payment_params->merchant_password, 'orderId' => @$vars['mdOrder'], ); $this->writeToLog($arg,true)."\n\n"; $callback = $this->gateway('getOrderStatus.do', $arg); $result = $callback; $this->writeToLog($result,true)."\n\n"; //////////////////////////////////////////////////////////////////////////////////
Результат :
Для новичка надо понять, что функция onPaymentNotification(&$statuses) начинает работать только при изменении статуса заказа после перехода пользователя на платежный шлюз и попытки оплаты заказа (успешно или неудачно).
Но до этого Вам надо передать службе техподдержки Сбербанка для активации так называемых "колбэков" об оплате параметр [notify_url] с php-сущностью.
$notify_url = HIKASHOP_LIVE.'index.php?option=com_hikashop&ctrl=checkout&task=notify¬if_payment='.$this->name.'&tmpl=component&lang='.$this->locale .$this->url_itemid;
СЕКРЕТ №2
Дальнейшее управление на основе ответа шлюза
// $callback - результат использования метода getOrderStatus.do
if(empty($callback)){ $email = new stdClass(); $email->subject = JText::sprintf('NOTIFICATION_REFUSED_FOR_THE_ORDER','Example').' '.JText::sprintf('PAYPAL_CONNECTION_FAILED',$dbOrder->order_number); $email->body = str_replace(' ',"\r\n",JText::sprintf('NOTIFICATION_REFUSED_NO_CONNECTION','Example'))."\r\n\r\n".JText::sprintf('CHECK_DOCUMENTATION',HIKASHOP_HELPURL.'payment-example-error#connection') . $order_text; $action = false; $this->modifyOrder($action, null, null, $email); JError::raiseError( 403, JText::_( 'Access Forbidden' )); return false; }
$orderStatus = $result['OrderStatus']; if ($orderStatus == '1' || $orderStatus == '2') { $history = new stdClass(); $history->notified=1; $history->amount=$callback['Amount']; $order_status = $this->payment_params->verified_status; $mail_status=$statuses[$order_status]; $email->subject = JText::sprintf('УВЕДОМЛЕНИЕ ОБ ОПЛАТЕ ЗАКАЗА','Example',$_POST['order_status'],$dbOrder->order_number); $email->body = str_replace(' ',"\r\n",JText::sprintf('PAYMENT_NOTIFICATION_STATUS','Example',$_POST['order_status'])).' '.JText::sprintf('ORDER_STATUS_CHANGED',$mail_status)."\r\n\r\n".$order_text; $this->modifyOrder($order_id,$order_status,$history,$email); return true; }else{ $emailData = new stdClass(); $emailData->subject = JText::sprintf('NOTIFICATION_REFUSED_FOR_THE_ORDER','Example').'invalid response'; $emailData->body = JText::sprintf("Hello,\r\n An Payza notification was refused because the notification from the Payza server was invalid")."\r\n\r\n".$order_text; $this->modifyOrder($order_id, $this->payment_params->invalid_status, true, $emailData); return false; }
СЕКРЕТ №3
Есть еще несколько вариантов получения callback - уведомлений.
Так в найденном плагине HIKASHOP-BECOPAY-GATEWAY упоминается, что не все платежные шлюзы используют параметр ['notify_url'] (*** - это целиком относится и к платежной системе Сбербанка), поэтому для получения интернет-магазином информации о статусе платежа используют все тот же ['return_url'] и шаблонный файл after_end.php для компонента Hikashop (задействованный для всех плагинов оплаты с помощью записи):
'return_url' => $return_url,
или использовать свой созданный и подключенный php файл о транзакциях.
$notify_url - это URL-адрес "уведомления" HikaShop, который по умолчанию передается платежному шлюзу, чтобы он мог отправить запрос по этому URL-адресу, чтобы сообщить HikaShop, что платеж был произведен (но ПС Сбербанк по умолчанию его игнорирует и передает информацию на URL-адрес возврата - $return_url , и в этом случае вам необходимо использовать этот URL-адрес ($return_url) для получения статуса заказа)
Для этого в файле after_end.php (стандартный шаблон Hikashop), на который переходит пользователь после оплаты заказа, пишем соответстующий php-код, не забывая о том, что сам файл не имеет стандартных классов HikashopPayment и представляет абстрактный файл php с заданным именем.
Только поэтому в самом файле надо вызвать соответствующие классы (продублировать получение) :
$user=JFactory::getUser(); global $Itemid; $orderClass = hikashop_get('class.order'); $imageHelper = hikashop_get('helper.image'); $productClass = hikashop_get('class.product'); $fieldsClass = hikashop_get('class.field');
$d = []; function Request() { if (isset($_GET)) { $scheme = $_SERVER['REQUEST_SCHEME'] ?: 'http'; $url = $scheme . '://' . $_SERVER['HTTP_HOST']; $data = array(); $filter=JFilterInput::getInstance(); foreach ($_GET as $key => $item) { $key=$filter->clean($key); $value=hikaInput::get()->getString($key); $data[$key] = $item; } } return $data; } $d=Request();
Для дальнейшего использования в получении данных о заказе и проинформировать Покупателя об оплате...
$orderClass = hikashop_get('class.order'); $order = $orderClass->loadFullOrder((int)@$d['order_id'], true, false); $confirmed = 'confirmed'; if($order->order_status == $confirmed){ echo ('
'.'Все прошло успешно !!! Оплата подтверждена.'); } else{ echo ('
'.'Пока мы не получили информацию о вашей транзакции. Возможно получим чуть позже.'); };
{module title="Example_Hikashop"}