Двуступенчая оплата банковской картой

Последнее время все больше интернет-магазинов подключают интернет-эквайринг, а клиенты магазинов уже не боятся использовать банковские карты для оплаты покупок в интернете. У небольших магазинов, не имеющих на складе полного ассортимента продаваемых товаров, а работающих по схеме "заказ - закупка у поставщика - продажа", при этом возникает проблема возврата части оплаты (или всей оплаты) покупателю.
[spoiler]
Типичный пример ситуации: посетитель сайта сделал заказ, тут же оплатил его банковской картой, но после согласования с менеджером отказался, т.к. сроки доставки его не устроили. В этом случае большинство банков, предлагающих интернет-эквайринг, требуют письменное заявление о возврате средств - на что, согласитесь, ни менеджеру, ни покупателю, тратить время не хочется. Некоторые платежные системы позволяют возвращать деньги, используя запросы через API с ЭЦП компании-продавца, например Merchant Web Services (MWS) Яндекс.Кассы, но подключение и реализация подобной схемы - довольно трудоемкая задача.

Идея

При реализации схемы оплаты интернет-магазина компании Italco, мы предложили схему, в которой оплата заказа разрешается системой только после подтверждения менеджером (то есть, после согласования заказа и проверки наличия товара):
Заказ - подтверждение менеджером - оплата клиентом
В "Битриксе" есть возможность создавать произвольные статусы заказа и управлять ими. В шаблоне компонента оформления заказа и личном кабинете заблокируем кнопки оплаты. Создадим дополнительный статус заказа - "Подтвержден к оплате", при установке этого статуса будем отправлять покупателю на e-mail ссылку на оплату заказа, а после оплаты - производить автоматическую установку статуса "Оплачен" для данного заказа.

Реализация

1. Шаблон компонента sale.order.ajax, файл confirm.php - если не задан определенный параметр в URL, блокируем возможность оплаты в шаблоне компонента заказа и добавляем сообщение - "После согласования заказа менеджером вы получите ссылку на оплату этого заказа на E-mail".

В строку:
<? if (strlen($arPaySystem["ACTION_FILE"]) > 0 && $arPaySystem["NEW_WINDOW"] == "Y" && $arPaySystem["IS_CASH"] != "Y"): ?>
Добавляем условие $_REQUEST['AUTO_SUBMIT'] == 'Y':
<? if ($_REQUEST['AUTO_SUBMIT'] == 'Y' && strlen($arPaySystem["ACTION_FILE"]) > 0 && $arPaySystem["NEW_WINDOW"] == "Y" && $arPaySystem["IS_CASH"] != "Y"): ?>
Вывод сообщения - ставим перед <?else:?>:
<? elseif (strlen($arPaySystem["ACTION_FILE"]) > 0 && $arPaySystem["NEW_WINDOW"] == "Y" && $arPaySystem["IS_CASH"] != "Y"): ?>   
   <? echo 'После согласования заказа менеджером вы получите ссылку на оплату этого заказа на E-mail' ?>
2. Шаблон компонента sale.personal.order.detail, файл template.php - если статус заказа не "Подтвержден к оплате", блокируем кнопку оплаты в личном кабинете:

В строки
<?if($payment["PAID"] == "Y"):?>
   <?=GetMessage('SPOD_YES')?>
   <?if(strlen($payment["DATE_PAID_FORMATED"])):?>
      (<?=GetMessage('SPOD_FROM')?> <?=$payment["DATE_PAID_FORMATED"]?>)
   <?endif;?>
<?else:?>
   <?=GetMessage('SPOD_NO')?>
   <?if($payment["CAN_REPAY"]=="Y" && $payment["PAY_SYSTEM"]["PSA_NEW_WINDOW"] == "Y"):?>
      &nbsp;&nbsp;&nbsp;[<a href="<?=$payment["PAY_SYSTEM"]["PSA_ACTION_FILE"]?>" target="_blank"><?=GetMessage("SPOD_REPEAT_PAY")?></a>]
   <?endif;?>
<?endif;?>
Перед <?else:?> - добавляем <?elseif:?>:
<?elseif($arResult["STATUS"]["NAME"]!='Подтвержден к оплате'):?>
   <?echo 'Заказ ожидает подтверждения менеджера, после подтверждения вам придет ссылка для оплаты заказа на E-mail'?>
3. Создаем тип почтового события:
d57e391437a57cf52c798150a2bbfc99.png

4. Создаем почтовый шаблон:
1c14fcb4011d6cb80ed24c67c7739cd7.png

В текст письма добавляем ссылку на оплату заказа:
Вы можете оплатить свой заказ, 
<a href="http://#SERVER_NAME#/personal/?ORDER_ID=#ORDER_ID#&ready_2pay=Y&userid=#USER_ID#&key=#KEY#">перейдя по этой ссылке</a>
Здесь #KEY# - это ключ для авторизации (см. шаг 5) - для того, чтобы перенаправить покупателя на платежную систему, нам придется снова его авторизовать - ведь сессия, в которой был сделан заказ, может быть уже завершена. Для этой цели будем использовать checkword пользователя - передадим его в параметре ссылки как #KEY#, а при переходе по ссылке - авторизуем при совпадении c checkword.

4. В файле /bitrix/php_interface/init.php - создаем обработчик события, который срабатывает при переводе заказа в статус "Подтвержден к оплате":
AddEventHandler("sale", "OnSaleStatusOrder", "OnSaleStatusOrderHandler"); 
function OnSaleStatusOrderHandler($ID, $val) {
   if($val=="A") { // Код статуса "Подтвержден к оплате"
      $arOrder = CSaleOrder::GetByID($ID);
      $arPaySys = CSalePaySystem::GetByID($arOrder['PAY_SYSTEM_ID'], $arOrder['PERSON_TYPE_ID']);
      if($arPaySys['PSA_ACTION_FILE'] == 'yandex') { // Дополнительная проверка, та ли платежная система?
         $rsUser = CUser::GetByID($arOrder["USER_ID"]);
         $arUser = $rsUser->Fetch();
         $event = new CEvent;
         $event->SendImmediate('SALE_ORDER_READY_2PAY', 's1', array(
            "SALE_EMAIL"   => COption::GetOptionString("sale", "order_email", "order@".$SERVER_NAME),
            "ORDER_ID"   => $ID,
            "EMAIL"      => $arUser["EMAIL"],
            "USER_ID"      => $arUser["ID"],
            "KEY"      => $arUser["CHECKWORD"],
         ));
      }
   }
}
5. В файл /personal/index.php добавляем строки
$authorized=false;
if($_REQUEST['key'] && intval($_REQUEST['userid']) && intval($_REQUEST['ORDER_ID'])) {
   if(!in_array(1, CUser::GetUserGroup($_REQUEST['userid']))) { //Страховка
      $rsUser = CUser::GetByID($_REQUEST['userid']);
      $arUser = $rsUser->Fetch();
      if($arUser['CHECKWORD']==$_REQUEST['key'])
         $authorized=$USER->Authorize($_REQUEST['userid']);
   }
   if($USER->IsAuthorized() || $authorized) {
      LocalRedirect('/personal/order/make/?ORDER_ID='.$_REQUEST['ORDER_ID'].'&AUTO_SUBMIT=Y');
   }
}
То есть, в случае если пользователь уже авторизован, или если удалось его авторизовать через переданный в ссылке ключ, мы делаем редирект на финальную страницу оформления заказа с установленным параметром вывода кнопки оплаты (см. шаг 1).

PS: Для полного удобства пользователя, можно также сделать чтобы средствами js (в данном случае - с использованием jQuery, но можно и без) автоматически "нажималась" кнопка "Оплатить":
<?if($_REQUEST['AUTO_SUBMIT'] == 'Y'):?>
   <script>
   $(document).ready(function(){
      $('#pay_system_div input[type=submit]').click();
   });
   </script>   
<?endif?> 
Для того, чтобы избежать "блокировщика всплывающих окон", которые не дают открывать ссылки с параметром target="_blank" средствами js, стоит убрать этот параметр из кода формы обработчика платежной системы.

В файле payment.php платежной системы:
<form name="ShopForm" action="https://money.yandex.ru/eshop.xml" method="post" target="_blank">
заменим на:
<form name="ShopForm" action="http://money.yandex.ru/eshop.xml" method="post">
0
Василий
06.12.2016 12:07:57
не получается найти строчку на 2 шаге. Как быть?
0
06.12.2016 13:59:36
Статья написана для версии модуля "Интернет-магазин" до конвертации. В новой версии ("Битрикс" старше 15.5) - другие шаблоны/компоненты, можно сделать поиск по строке:
if ($payment['PAID'] === 'Y')