Как мы подружились с PayPal

Источник: habrahabr
habrahabr

Дорогой иностранный гость с фамилией слишком известной, чтобы ее называть, гражданин PayPal только-только "сошел с корабля" на отечественный "причал", но уже успел стать своим на балу, где активно крутят танцы всех стилей и направлений электронные платежные системы российского сегмента. Мы не стали стоять в стороне и поспешили завести полезное знакомство со столь уважаемым товарищем, добавив, наконец, и его доброе имя в свой список друзей. С какой стороны подойти, о чем говорить и как привлечь его внимание читаем в небольшой истории под катом.

Дружба начинается с улыбки


Первый робкий шаг на пути к большой дружбе - представление, то есть, регистрация, где в персональных данных необходимо предоставить информацию о коммерческой деятельности компании, что и было нами добросовестно выполнено.

Однако вместо легких и непринужденных отношений, которым мы успели мысленно обрадоваться, нас ожидало неприветливое сообщение об ограничении счета и просьба предоставить целый ряд дополнительных документов для подтверждения нашего аккаунта. Не успели мы собрать все необходимое, как, к счастью, в середине сентября PayPal значительно упростил процедуру подключения юридических лиц. Требовалось только заполнить специальную для этого форму на стороне PayPal. Но и теперь рано было радоваться - первые несколько дней форма попросту не работала. Мы честно заполняли все обязательные и необязательные поля, но каждый раз получали ошибку передачи данных и, как ни старались, это повторялось снова и снова. Не растеряв решительности и имея в запасе немало упорства, спустя неделю мы повторили "эксперимент" и, наконец, получили долгожданное подтверждение, а в скором времени и заветное письмо от компании PayPal.

Настоящий друг познается в API


Разобраться во всех тонкостях протокола PayPal дело не легкое. Разбросанные по разным частям сайта куски документаций, тяжелое наследие SOAP, всеобщая мешанина стека протоколов (NVP, SOAP, REST) и нехватка примеров сделали свое дело. Типичный пример неразберихи, действие реализуемое одним протоколом, невозможно выполнить другим и наоборот.
Но путь в тысячу миль начинается с первого шага, отбросив все сомнения прочь, будем использовать наиболее популярный на данный момент REST API, а в качестве обертки к нему возьмем их собственный PHP SDK. Некоторые вещи, правда, все равно придется додумывать самим, исследуя код.

Общую идею можно описать в следующих шагах:

  1. Регистрируем PayPal Application, для получения пар значений client_id и secret_key для live и sandbox режима:
  2. Производим OAuth авторизацию:
    $apiContext = new ApiContext(new OAuthTokenCredential( $clientId, $clientSecret)); $apiContext->setConfig([ 'mode' => 'live']);
  3. Делаем запрос на создание платежа. Если вы планируете принимать оплату со счета paypal, а также привязанной к нему карты не забудьте указать метод оплаты: paypal
    $payer = new Payer(); $payer->setPaymentMethod('paypal'); $amount = new Amount(); $amount->setCurrency('RUB'); $amount->setTotal('10'); $item1 = new Item(); $item1->setName('Продажа товара/услуги')->setCurrency('RUB')->setQuantity(1)->setPrice('10'); // Ид товара/услуги на вашей стороне $item1->setSku('1000'); $itemList = new ItemList(); $itemList->setItems(array($item1)); $transaction = new Transaction(); $transaction->setAmount($amount); $transaction->setDescription('Payment to UnitPay'); $transaction->setItemList($itemList); $payment = new Payment(); $payment->setIntent('sale'); $payment->setPayer($payer); $payment->setTransactions(array($transaction)); $payment>setRedirectUrls(array( "return_url" => $resultUrl, "cancel_url" => $resultUrl )); $payment->create($apiContext);
  4. В ответ получаем номер платежа в PayPal и redirectURL формы оплаты, куда и перебрасываем пользователя:
    // ID платежа, связываем его с заказом и сохраняем в БД $payment->getId(); $links = $payment->getLinks(); foreach ($links as $link) { if ($link->getMethod() == 'REDIRECT') { header('location:'.$link->getHref()); return; } }
  5. Подтверждение счета клиентом:
  6. Автоматический возврат клиента с GET параметрами token, PayerID на $resultUrl (см. шаг 3).
  7. Деньги списаны, но платеж еще не выполнен. Говорим PayPal, что да, мы точно подтверждаем платеж:
    $apiContext = new ApiContext(new OAuthTokenCredential( $clientId, $clientSecret)); $apiContext->setConfig([ 'mode' => 'live']); $payment = Payment::get($payment->getExternalPaymentId(), $apiContext); $paymentExecution= new PaymentExecution(); $paymentExecution->setPayerId($payerId); $payment->execute($paymentExecution, $apiContext);
  8. Опционально PayPal производит уведомление о платежах на указанный URL, называется это у них IPN:

    Каждое такое полученное уведомление необходимо валидировать ответным запросом в сторону PayPal. Также нужно сверять сумму платежа, валюту и email получателя. Остается только дождаться заветного статуса completed и платеж можно считать выполненным. Если вы не хотите связываться с IPN, то всегда можно просто опрашивать платформу PayPal о статусах требуемых платежей, к примеру, через cron, хотя IPN все же удобней:
    $ipn = new PPIPNMessage(null, array(['mode' => 'live'])); if (!$ipn->validate()) { throw new \Exception('Не пройдена валидация платежа на стороне PayPal'); } // $_GET['txn_id'] Ид платежа PayPal // $_GET['mc_gross'] Сумма платежа // $_GET['mc_currency'] Валюта платежа // $_GET['payer_email'] Еmail плательщика // $_GET['item_number1'] Ид первого товара // $_GET['payment_status'] Статус заказа // $_GET['receiver_email'] Email получателя switch ($_GET['payment_status']) { // Платеж успешно выполнен, оказываем услугу case 'completed': break; // Платеж не прошел case 'failed': break; // Платеж отменен продавцом case 'denied': break; // Деньги были возвращены покупателю case 'refunded': break; }


На наш взгляд, большинство шагов данной схемы избыточные: можно убрать повторные проверки в адрес PayPal на этапе уведомлений о платеже, просто заранее подписав присланные данные. Это же касается и лишних действий с подтверждением уже сделанного платежа пользователя. Также, помимо хранения номера платежа PayPal, придется организовывать хранение token"а для однозначной идентификации заказа и выполнения шага 7. Альтернативный вариант заключается в формировании Url"а возврата с уникальным ключом.

На данный момент API PayPal один из самых запутанных и неоднозначных среди популярных платежных систем, но с другой стороны если, не сворачивая, идти по протоптанной тропинке, то все получится.

Не имей сто рублей, а имей сто друзей


В свою очередь мы упростили подключение и работу с PayPal и готовы предоставить ряд платежных инструментов на выбор.

Если вы только задумались над тем, как реализовать прием платежей для своего проекта и какие методы оплаты вам подойдут помимо PayPal, то рекомендуем самый быстрый и простой способ подключения - универсальная форма оплаты UnitPay. Среди прочих методов оплаты будет доступен и PayPal.

Для тех кто уже сформировал свой список платежных систем и просто хочет расширить его, подключив PayPal, мы предлагаем воспользоваться нашим API, полное описание которого можно найти на странице вашего проекта.

А что для стран СНГ?


К сожалению, пока PayPal не доступен для ряда ближайших к нам стран. Многие испытывают с этим ряд трудностей и предлагают достаточно разные решения. Думаем, что в скором времени эта ситуация изменится в лучшую сторону.

В заключение


PayPal в России ещё очень молод, но у него богатое прошлое и огромный потенциал. Мы надеемся, что пройдет совсем немного времени, и он займет свое достойное место в списке безопасных и удобных платежных систем на отечественном рынке.

Страница сайта http://test.interface.ru
Оригинал находится по адресу http://test.interface.ru/home.asp?artId=35003