UPC - visa/mastercard payment
Номер тестовой карточки: 4999999999990011
https://secure.upc.ua/ecgtest/merchant
Задача
Реализовать оплату кредиткой
Шаг 1. Регистрация
Скачиваем и заполняем заявку на регистрацию http://ecommerce.upc.ua/site/docs.html, после чего отправляем заявку на [email protected]
Через некоторое время получаем письмо с логином\паролем приблизительно следующего вида:
Добрый день
Тестовые данные:
Адрес шлюза :https://secure.upc.ua/ecgtest/enter
MerchantID=1753019
TerminalID=E7881019
Интерфейс торговца :https://secure.upc.ua/ecgtest/merchant
Логин / Пароль : 1753019 / 1753019
Сертификат сервера - в аттаче
Также необходимо, чтобы Вы выслали сертификат торговца (файл с именем 1753019.crt) на адрес [email protected]
Вся необходимая документация: здесь: http://ecommerce.upc.ua/site/docs.html
Тестовые карты здесь: http://ecommerce.upc.ua/docs/Testing.pdf
(See attached file: test-server.cert)
В архиве batch.rar документация и примеры по формированию подписи.
(See attached file: batch.rar)
В архиве image.rar логотипы.
(See attached file: image.rar)
Переходим на страницу https://secure.upc.ua/ecgtest/merchant/ и меняем пароль на странице профиля.
На странице "Терминалы" выбираем наш сайт и указываем URL, для страниц успешной и неудачных транзакций.
Так же необходимо сгенерировать и выслать им сертификат, для этого качаем openssl http://www.slproweb.com/products/Win32OpenSSL.html и прописываем путь к папке bin в PATH, далее в консоли переходим к папке batch (приатаченой к письму) и запускаем run.bat #MERCHANT_ID#
(с правами администратора)
Теперь необходимо выслать файл 1753019.crt на [email protected] и дождаться ответа от них (пока не будет ответа, ничего работать не будет).
В ответ они присылают простой ответ, типа "Сертификат подгружен" и все.
На сервере нам понадобятся как минимум:
test-server.cert - файл который они выслали в письме подтверждении регистрации (используется для проверки ответа)
1753019.pem - файл (приватный ключ) который мы сгенерировали (используется для создания сигнатуры отправляемых данных)
Шаг 2. Страница заказа
Код страницы заказа:
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>Buy</title>
</head>
<body>
<?php
$MerchantID = '1753019';
$TerminalID = 'E7881019';
$OrderID = 19;
$PurchaseTime = date("ymdHis") ;
$TotalAmount = 242;
$CurrencyID = 980;
$data = "$MerchantID;$TerminalID;$PurchaseTime;$OrderID;$CurrencyID;$TotalAmount;;";
$fp = fopen("$MerchantID.pem", "r");
$priv_key = fread($fp, 8192);
fclose($fp);
$pkeyid = openssl_get_privatekey($priv_key);
openssl_sign( $data , $signature, $pkeyid);
openssl_free_key($pkeyid);
$b64sign = base64_encode($signature);
?>
<form action="https://secure.upc.ua/ecgtest/enter" method="post" >
<input name="Version" type="hidden" value="1" />
<input name="MerchantID" type="hidden" value="<?php echo $MerchantID?>" />
<input name="TerminalID" type="hidden" value="<?php echo $TerminalID?>" />
<input name="TotalAmount" type="hidden" value="<?php echo $TotalAmount?>" />
<input name="Currency" type="hidden" value="<?php echo $CurrencyID?>" />
<input name="locale" type="hidden" value="RU" />
<input name="PurchaseTime" type="hidden" value="<?php echo $PurchaseTime ?>" />
<input name="OrderID" type="hidden" value="<?php echo $OrderID?>" />
<input name="Signature" type="hidden" value="<?php echo "$b64sign" ?>"/>
Sum: <?php echo $TotalAmount?> <input type="submit"/>
</form>
</body>
</html>
Примечание:
$data
генериться следующим образом
MerchantId;TerminalId;PurchaseTime;OrderId,Delay;CurrencyId,AltCurrencyId;Amount,AltAmount;SessionData(SD);
Количество знаков ;
должно оставаться постоянным. Если какое то поле отсутствует, то ставится ;;
. Например, если отсутствует SessionData(SD)
, то datafile будет выглядеть следующим образом:
MerchantId;TerminalId;PurchaseTime;OrderId,Delay;CurrencyId,AltCurrencyId;Amount,AltAmount;;
Если отсутствуют поля Delay
или AltCurrency
, AltAmount
то запятая перед этими полями опускается. Например:
MerchantId;TerminalId;PurchaseTime;OrderId;CurrencyId,AltCurrencyId;Amount,AltAmount;;
MerchantId;TerminalId;PurchaseTime;OrderId,Delay;CurrencyId;Amount;;
MerchantId;TerminalId;PurchaseTime;OrderId;CurrencyId;Amount;;
в нашем случае использовался последний пример. Важно соблюдать порядок иначе ничего работать не будет, в коде использован самый простой рабочий пример.
Шаг 3. Страница удачной авторизации
Код страницы:
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>Buy</title>
</head>
<body>
<h1>SUCCESS</h1>
<h2>$_POST</h2>
<pre><code><?php print_r($_POST)?></code></pre>
<h2>Proccessing</h2>
<?php
$MerchantID = $_POST['MerchantID'];
$TerminalID = $_POST['TerminalID'];
$OrderID = $_POST['OrderID'];
$PurchaseTime = $_POST['PurchaseTime'];
$TotalAmount = $_POST['TotalAmount'];
$CurrencyID = $_POST['Currency'];
$XID = $_POST['XID'];
$SD = $_POST['SD'];
$TranCode = $_POST['TranCode'];
$ApprovalCode = $_POST['ApprovalCode'];
$data = "$MerchantID;$TerminalID;$PurchaseTime;$OrderID;$XID;$CurrencyID;$TotalAmount;$SD;$TranCode;$ApprovalCode;";
echo 'data: '.$data.'<br />';
$signature = $HTTP_POST_VARS["Signature"];
$signature = base64_decode($signature) ;
$fp = fopen("test-server.cert", "r");
$cert = fread($fp, 8192);
fclose($fp);
$pubkeyid = openssl_get_publickey($cert);
$ok = openssl_verify($data, $signature, $pubkeyid);
if ($ok == 1) {
echo "good";
} elseif ($ok == 0) {
echo "bad";
} else {
echo "ugly, error checking signature";
}
openssl_free_key($pubkeyid);
?>
</body>
</html>
Если все прошло успешно скрипт вернет good что говорит о том что проплата прошла успешно.
Примечание:
Тут тоже очень важно не напортачить с переменной $data, которая генериться следующим образом:
MerchantId;TerminalId;PurchaseTime;OrderId,Delay;Xid;CurrencyId,AltCurrencyId;Amount,AltAmount;SessionData;TranCode;ApprovalCode;
Правила те же самые если полей типа Delay
, AltCurrencyId
, AltAmount
нет - запятая перед ними удаляется
В идеале на странице success.php
должна будет выглядеть так:
Шаг 4. Страница ошибки
Собственно здесь и делать нечего, из полученных данных отменяем заказ по OrderID
и в зависимости от кода ответа показываем соотв. сообщение.
Тестовые карточки
Для тестирования можно использовать тестовые кредитки из документации http://ecommerce.upc.ua/site/docs.html
На момент моих экспериментов они были следующими:
Обобщенные коды ответа для магазина | Примерная интерпретация ответа на странице возврата электронного магазина | Номер карты (срок действия 12/2012; CVV2 – 999) |
---|---|---|
000 | Сделка авторизована | 4999999999990011 |
105 | Тразакция не разрешена банком-эмитентом | 4999999999990029 |
116 | Недостаточно средств | 4999999999990037 |
111 | Несуществующая карта | 4999999999990045 |
108 | Карта утеряна или украдена | 4999999999990052 |
101 | Неверный срок действия карты | 4999999999990060 |
130 | Превышен допустимый лимит расходов | 4999999999990078 |
290 | Банк-издатель недоступен | 4999999999990086 |
291 | Техническая или коммуникационная проблема | 4999999999990094 |
401 | Ошибка формата | |
402 | Ошибки в параметрах Acquirer/Merchant | |
403 | Ошибки при соединении с ресурсом платежной системы (DS) | 4999999999990102 |
404 | Ошибка аутентификации покупателя | 4999999999990110 |
405 | Ошибка подписи | |
501 | Транзакция отменена пользователем | |
502 | Сессия браузера устарела |
Данне которые мы передаем
Все данные передаются POST запросом на адрес https://secure.upc.ua/ecgtest/enter
Параметр | Название (назначение) | Комментарий |
---|---|---|
Version | Значение версии интерфейса SG | Версия протокола взаимодействия. Действующая версия в данный момент – 1v. Этот параметр является справочным для обработчика взодных данных шлюза. |
MerchantID | Идентификатор торговца | Выдается при регистрации |
TerminalID | Идентификатор терминала | Выдается при регистрации, завязан на кокнретный сайт |
TotalAmount | Сумма заказа | В мелких единицах валюты (копейки, центы) |
Currency | Валюта | Определяется договором с обслуживающим банком 643 руб. 840 у.е. 978 eur. 980 грн. |
AltTotalAmount (опционально) | Сумма заказа (альтернативная валюта) | |
AltCurrency (опционально) | Альтернативная Валюта | |
PurchaseTime | Время запроса в формате yyMMddHHmmss или yyMMddHHmmssZ | 100921113510 Или 100921113510+0300 Если зона не указана используется та же что и у шлюза |
locale | Язык интерфейса (en, ru, uk) | Язык страницы шлюза |
OrderID | Номер заказа длиной до 20 байт | |
SD (опционально) | Session Data – данные сессии | |
PurchaseDesc (опционально) | Краткое описание покупки товара (utf-8) | |
Signature | Значение сгенерированной сигнатуры | См. примечание |
Delay | Идентификатор платежа пре-авторизация | Для преавторизации, значение должно быть равно 1, иначе 0 или пусто. Хз, что это за хрень для работы не нужно |
Примечание: Генерация сигнатуры
<?php
$MerchantID = '1753019';
$TerminalID = 'E7881019';
$OrderID = 19;
$PurchaseTime = date("ymdHis") ;
$TotalAmount = 242;
$CurrencyID = 980;
$data = "$MerchantID;$TerminalID;$PurchaseTime;$OrderID;$CurrencyID;$TotalAmount;;";
$fp = fopen("$MerchantID.pem", "r");
$priv_key = fread($fp, 8192);
fclose($fp);
$pkeyid = openssl_get_privatekey($priv_key);
openssl_sign( $data , $signature, $pkeyid);
openssl_free_key($pkeyid);
$b64sign = base64_encode($signature);
?>
Данные которые получаем в ответ
Все данные передаются POST на страницу success.php
(указаную в шаге 1)
Параметр | Название (назначение) | Комментарий |
---|---|---|
MerchantID | Идентификатор торговца | |
TerminalID | Идентификатор терминала | |
TotalAmount | Сумма заказа | |
Currency | Валюта | |
AltTotalAmount (опционально) | Сумма заказа (альтернативная валюта) | |
AltCurrency (опционально) | Альтернативная Валюта | |
PurchaseTime | Время запроса в формате yyMMddHHmmss | |
OrderID | Номер заказа длиной до 20 байт | |
XID | Идентификатор транзакции (номер заказа, дополненный до 20 символов) | |
SD | Session Data – данные сессии | |
ApprovalCode | Код авторизации хоста | |
Rrn | Retrieval Reference Number | Уникальный номер транзакции в системе авторизации и расчетов обслуживающего банка |
ProxyPan | 4 последние цифры номера карты. | Пример: 499999******0011 |
TranCode | Код завершения тразакции | |
Signature | см. примечание | |
Delay | ||
Email – введенный пользователем на странице шлюза |
Примечание:
Проверка данный ответа
<?php
$MerchantID = $_POST['MerchantID'];
$TerminalID = $_POST['TerminalID'];
$OrderID = $_POST['OrderID'];
$PurchaseTime = $_POST['PurchaseTime'];
$TotalAmount = $_POST['TotalAmount'];
$CurrencyID = $_POST['Currency'];
$XID = $_POST['XID'];
$SD = $_POST['SD'];
$TranCode = $_POST['TranCode'];
$ApprovalCode = $_POST['ApprovalCode'];
$data = "$MerchantID;$TerminalID;$PurchaseTime;$OrderID;$XID;$CurrencyID;$TotalAmount;$SD;$TranCode;$ApprovalCode;";
echo 'data: '.$data.'<br />';
$signature = $HTTP_POST_VARS["Signature"];
$signature = base64_decode($signature) ;
$fp = fopen("test-server.cert", "r");
$cert = fread($fp, 8192);
fclose($fp);
$pubkeyid = openssl_get_publickey($cert);
$ok = openssl_verify($data, $signature, $pubkeyid);
if ($ok == 1) {
echo "good";
} elseif ($ok == 0) {
echo "bad";
} else {
echo "ugly, error checking signature";
}
openssl_free_key($pubkeyid);
?>