В первых двух  частях проекта  "Создаем плагин Hikashop" было рассказано, как создавать данные для запроса и отлаживать код php нашего скрипта. Не всё проходит гладко: для этого используем  журнал отладки  с помощью встроенной в HIKASHOP функции writeToLog - устраняем возникающие ошибки и недразумения.

Разговор далее пойдет о встроенной функции - public function onPaymentNotification(&$statuses)   или о комплексе мер для получения данных от платежной системы (ПС) о проведенном платеже.

Для правильной работы любого платежного плагина  (выдача уведомления о прохождении оплаты и информирование об этом покупателя) значение параметра ' notification ' должно быть включено - "получать уведомления о статусе заказа (об оплате)".  Компонент Hikashop, как правило, использует для этих целей  параметр - $notify_url (т.к.  западные платежные системы (PayPal) по умолчанию используют именно этот параметр).

Сам параметр ' notify_url '   по стандарту Hikashop представляет собой абстрактный URL адрес и должен иметь обязательные аттрибуты, о которых мы поговорим далее.

Нельзя забывать, что существует 2 разновидности ' notify_url '  : html-сущность в функции-конструкторе и php-сущность в теле плагина  - и они имеют разный код.     

  • html-сущность (отображение в браузере) - с использованием  &  в определенном месте кода

[$notify_url] = HIKASHOP_LIVE.'index.php?option=com_hikashop&ctrl=checkout&task=notify&notif_payment='.$this->name.'&tmpl=component&lang='.$this->locale .$this->url_itemid;

  • php-сущность - с использованием разделителя &

[$notify_url] = HIKASHOP_LIVE.'index.php?option=com_hikashop&ctrl=checkout&task=notify&notif_payment='.$this->name.'&tmpl=component&lang='.$this->locale .$this->url_itemid;

Платежная система Сбербанка по умолчанию параметр ['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&notif_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"}