Деловые люди сталкивающиеся с интернетом хотят заработать денег, поэтому paypal позволяющий делать оплату кредитными картами по всему миру — ценнейшая услуга для интеграции на свой сайт. Примерные цены за услугу: 2-4% от суммы + 0,3$ за транзакцию зависит от типа оплаты.
У Paypal есть несколько возможностей оплаты товара, но к счастью они едины тем что это делается HTML-формой в которой просто разные входы обозначают разные процессы оплаты. Вот некоторые процессы которые можно сделать..
- Покупка в «один клик»
- С передачей данных об оплате (Payment Data Transfer) — в обычном варианте процесс похож на pangalink. В качестве расширения можно включить авторедирект пользователя после оплаты.
- Buy Now Hosted Button — упрощённая форма где все данные оплаты уже вбиты в paypal-админке. Хороший вариант для оплачиваемого хобби — например если вы продаёте например свой компакт-диск который один единственный для всего сайта.
- C межсерверным оповещением (Instant Payment Notification)
- Корзина
- Подписка
Ниже я покажу процесс IPN. Для тестирования оплаты есть Sandbox-режим. Для более детального описания этого и других процессов почитайте старенькую но актуальную статью в phpclub
Процесс
В моём случае пользователь покупает «кредиты» (виртуальную валюту сайта) которую может потратить на разные внутренние услуги. Соответсвенно он может выбрать сколько денег он хочет потратить обычным radio-полем
- При открытии этой страницы в БД сразу регистрируется новый заказ со статусом «adding». Старые заказы с таким статусом удаляются.
- Пользователю показывается форма
- При её подтверждении пользователь переносится на сайт paypal где оплачивает услугу со всеми проверками
- При удачной оплате Paypal в фоновом режиме говорит серверу по notify_url о состоянии оплаты и именно в это время меняется статус заказа
- Пользователь перенаправляется на return URL где ему показывается состояние заказа
Форма
На нашем сайте надо установить HTML-форму с полями, для этого в контроллере я передаю в шаблон такие данные (упрощённые что-бы вам было легче понять)
$this->assign('paypal',array(
'gate' => 'https://www.paypal.com/cgi-bin/webscr',
//'https://www.sandbox.paypal.com/cgi-bin/webscr' для режима тестирования
'receiver_email' => '[email protected]',
'description' => 'Quarti.ru credits',
'price' => 10, //в долларах
'order_id' => $iOrder, //номер заказа
'notify_url' => 'http://quarti.ru/paypal_direct_responce/',
'link_return' => 'http://quarti.ru/payment_completed/'
'link_cancel' => 'http://quarti.ru/payment_failed/',
));
Дальше в шаблоне рисуем собственно форму
<form method="post" action="{$paypal.gate}" id="paypal_form">
<input type="hidden" name="cmd" value="_xclick" />
<input type="hidden" name="business" value="{$paypal.receiver_email}" />
<input type="hidden" name="item_name" value="{$paypal.description}" />
<input type="hidden" name="item_number" value="{$paypal.order_id}" />
<input type="hidden" name="amount" value="{$paypal.price}" />
<input type="hidden" name="return" value="{$paypal.link_return}" />
<input type="hidden" name="cancel_return" value="{$paypal.link_cancel}" />
{if $paypal.notify_url}
<input type="hidden" name="notify_url" value="{$paypal.notify_url}" />
{/if}
<input type="hidden" name="no_shipping" value="1" />
<input type="hidden" name="rm" value="2" />
</form>
Проверка
Когда пользователь оплачивает покупку, то paypal в фоновом режиме передаёт статус оплаты. Это необходимо что-бы иметь синхронизированную транзакцию даже если пользователь не вернётся на наш сайт после оплаты по каким-то причинам. Проверка простейшая — собираются все данные что «paypal» запостил и переспрашиваются у него через CURL. А дальше уже обновляются статусы в БД, пишется лог со временем, передача ошибок и тп.
private function verifyPaypalNotification($sGatewayURL,$sMerchantEmail,$sError){
$postdata="";
foreach ($_POST as $key=>$value) {
$postdata.=$key."=".urlencode($value)."&";
}
$postdata .= "cmd=_notify-validate";
$curl = curl_init($sGatewayURL);
curl_setopt ($curl, CURLOPT_HEADER, 0);
curl_setopt ($curl, CURLOPT_POST, 1);
curl_setopt ($curl, CURLOPT_POSTFIELDS, $postdata);
curl_setopt ($curl, CURLOPT_SSL_VERIFYPEER, 0);
curl_setopt ($curl, CURLOPT_RETURNTRANSFER, 1);
curl_setopt ($curl, CURLOPT_SSL_VERIFYHOST, 1);
$response = curl_exec ($curl);
curl_close ($curl);
if ($response != "VERIFIED") {
$sError="TRANSACTION_NOT_VERIFIED";
return false;
}
if (strtolower($_POST['receiver_email']) != $sMerchantEmail){
$sError="INVALID_RECEIVER";
return false;
}
if ($_POST["txn_type"] != "web_accept"){
$sError="INVALID_TRANSACTION_TYPE";
return false;
}
return true;
}