Внедрение платёжной системы eWay

eWay лого В данной статье речь пойдет об интеграции платежной системы eWay в Rails приложение. Мы рассмотрим три способа: Pay Now Button, Responsive Shared Page и Direct Connection. В первом случае основная работа ложится на плечи eWay. Во втором сервис предоставляет пользователю страницу, которую тот может модифицировать. Данная страница поставляется с большим спектром дополнительных возможностей: 3D Secure, PayPal, MasterPass и Visa Checkout, что, в свою очередь уменьшает время разработки. Для демонстрации мы создадим простейшее Rails приложение, состоящее из модели Order, которая содержит два поля: product и price, и контроллера для модели.

Но обо всём по порядку. Для начала нам нужно зарегистрировать аккаунт разработчика и создать ключи для авторизации нашего приложения. Для этого необходимо:

  1. Перейти на https://www.eway.com.au/developers
  2. Нажать на «create partner account»
  3. Заполнить форму 004.png
  4. Перейти на партнерский портал
  5. Возможно, вы увидите сообщение, в этом случае придется немного подождать 006.png
  6. Далее нужно перейти на страницу resources > sandbox-testing
  7. На данной странице вы увидите ваш Username для песочницы. 007.png
  8. Теперь перейдем по адресу песочницы 008.png
  9. И воспользовавшись указанным при регистрации паролем и username с предыдущего экрана, мы попадем в наш аккаунт 009.png

Pay Now Button

Данный подход является самым быстрым и легким способом дать пользователю возможность совершить оплату. Для реализации нам понадобится «Pay Now Button Public API Key» - вы сможете его найти в аккаунте песочницы на странице управления. 012.png Давайте добавим этот ключ как константу в наше рабочее окружение:

/eway-basics/config/environments/development.rb

Rails.application.configure do
  config.cache_classes = false  
  
  config.assets.raise_runtime_errors = true
  EWAY_PAY_BUTTON_KEY = 'epk-1CD35F2A-ECD6-405D-A10B-046D3B4E9784'
end

Теперь осталось добавить небольшой snippet на нашу индекс страницу.

Было:

%tbody
  - orders.each do |order|
  %tr
      %td= order.id
      %td= link_to order.product, order_path(order)
      %td= number_to_currency(order.price, unit: "$")
      %td= human_boolean order.paid
      %td= order.created_at.strftime("%d/%m/%Y")
      %td

Стало:

%tbody
  - orders.each do |order|
  %tr
      %td= order.id
      %td= link_to order.product, order_path(order)
      %td= number_to_currency(order.price, unit: "$")
      %td= human_boolean order.paid
      %td= order.created_at.strftime("%d/%m/%Y")
      %td
        %script{ src: "https://secure.ewaypayments.com/scripts/eCrypt.js", class: "eway-paynow-button", data: { publicapikey: EWAY_PAY_BUTTON_KEY, amount: order.price_in_cents, currency: "AUD" }}

По умолчанию расчет идет в австралийских долларах, но вы с легкостью можете изменить этот параметр, если добавите ключ «currency» в хеш дата атрибутов:

%script{ src: "https://secure.ewaypayments.com/scripts/eCrypt.js", class: "eway-paynow-button", data: { publicapikey: EWAY_PAY_BUTTON_KEY, amount: order.price_in_cents, currency: "AUD" }}

В случае с песочницей, мы ограничены одной валютой. Эта кнопка обладает и другими конфигурационными опциями, полный список которых вы можете найти по ссылке https://eway.io/api-v3/#configuration-attributes

По клику на кнопку пользователю будет предложено ввести платежные реквизиты 013.png и, в случае удачного проведения транзакции, платеж отобразится на странице статистики. 014.png При работе в песочнице корректным является платеж на 10 долларов с карты Виза.

В случае, если вы настроили «data-resulturl», по завершению транзакции пользователь будет перенаправлен на этот url.

Responsive Shared Page

Теперь давайте возьмем API ключ и пароль 015.png и настроим наше приложение на работу с полнофункциональной страницей.

Добавим эти данные в

/eway-basics/config/environments/development.rb

EWAY_API_KEY = 'F9802CLDSnmOLrbsY7sUIGYA6ugt50ks0bekkGUXQobgdHbuYjG3DGkUotYCP1fgZbDpqH'
EWAY_API_PASS = 'mUvnJZZS'
EWAY_SERVICE_URL = 'https://api.sandbox.ewaypayments.com'

Эта страница довольно гибко конфигурируется и может представлять набор полей от нескольких строк до десятков (полный список вы можете найти на https://eway.io/api-v3/#responsive-shared-page).

Но для начала добавим новый Контроллер

class CheckoutsController < ApplicationController
end

и кнопку, которая будет вести в этот контроллер.

Теперь нам нужно сформировать конфигурацию страницы, которую мы хотим. Как говорилось ранее, набор опций довольно обширный, поэтому мы возьмем минимально необходимый:

attrs = {
  Payment: {
     TotalAmount: order.price_in_cents
  },
  RedirectUrl: 'http://localhost:3000',
  CancelUrl: 'http://localhost:3000',
  Method: 'ProcessPayment',
   TransactionType: 'Purchase'
}

Далее нам необходимо сделать запрос к службе API eWay - в нашем случае, https://api.sandbox.ewaypayments.com. К примеру:

result = nil
Curl::Easy.http_post("#{EWAY_SERVICE_URL}/AccessCodesShared", attrs.to_json) do |curl|
  curl.headers['Accept'] = 'application/json'
  curl.headers['Content-Type'] = 'application/json'
  curl.http_auth_types = :basic
  curl.username = EWAY_API_KEY
  curl.password = EWAY_API_PASS
  curl.verbose = true
  curl.on_complete {|response, err|
  result = response.body_str
  }
end

Ответом на запрос будет json формата

{ 
  "SharedPaymentUrl":"https://secure-au.sandbox.ewaypayments.com/sharedpage/sharedpayment?AccessCode=44DD7OzqdHoQf6nP9arOyoUtnehQGSMVY7a0S2IyNj3KGRXMJMCi9hYGsl-0LVxTihqSw_1sDafZeN6qbxPLm_D-kMsT3sWm2rHIsPELrz_JIoaJ7VnKXorXychYeTX88jcaYmoetXvpe0CxqoQp4dVDpBg==",
  "AccessCode":"44DD7OzqdHoQf6nP9arOyoUtnehQGSMVY7a0S2IyNj3KGRXMJMCi9hYGsl-0LVxTihqSw_1sDafZeN6qbxPLm_D-kMsT3sWm2rHIsPELrz_JIoaJ7VnKXorXychYeTX88jcaYmoetXvpe0CxqoQp4dVDpBg==",
  "Customer":{ 
    "Title":"Mr.",
  ...
    "Fax":"",
    "Url":""
  },
  "Payment":{ 
    "TotalAmount":1000,
    "InvoiceNumber":"",
    "InvoiceDescription":"",
    "InvoiceReference":"",
    "CurrencyCode":"AUD"
  },
  "FormActionURL":"https://secure-au.sandbox.ewaypayments.com/AccessCode/44DD7OzqdHoQf6nP9arOyoUtnehQGSMVY7a0S2IyNj3KGRXMJMCi9hYGsl-0LVxTihqSw_1sDafZeN6qbxPLm_D-kMsT3sWm2rHIsPELrz_JIoaJ7VnKXorXychYeTX88jcaYmoetXvpe0CxqoQp4dVDpBg==",
  "CompleteCheckoutURL":"",
  "Errors":""
}

Из ответа мы извлекаем SharedPaymentUrl и перенаправляем пользователя туда. По этому адресу пользователя ожидает уже сформированная страница оплаты. 016.png Если мы проинспектируем эту страницу, то легко сможем заметить, что кнопка Cancel содержит URL, переданный в первом запросе. 017.png Хотя страница выглядит пустой, и кажется, что мы заставляем пользователя заполнять бесчисленное множество полей, это не так. Мы могли бы передать большинство данных пользователя в теле первого запроса, тем самым уменьшив количество необходимых действий. В таком случае пользователю осталось бы только ввести данные по карте. 018.png Как и в первом варианте, установка RedirectUrl позволила бы нам перенаправить пользователя по завершению транзакции на страницу результатов.

Direct Connection

И последний вариант подключения, который мы рассмотрим – случай, когда вам нужно полностью контролировать форму оплаты и вписать ее как часть своей страницы в приложения. Сперва нужно выполнить запрос, аналогичный тому, который мы выполняли для получения SharedPaymentUrl. Только теперь нам понадобится 2 других ключа - FormActionURL(на него будет слаться форма) и AccessCode(уникальный идентификатор). Теперь создадим форму, которую будем использовать:

= form_for order, url: result['FormActionURL'], method: :post, html: { class: "form order" } do |f|
  = hidden_field_tag 'EWAY_ACCESSCODE', result['AccessCode']
  = hidden_field_tag 'EWAY_PAYMENTTYPE', 'Credit Card'
  .title-form
  %span
    %strong PAYMENT
  %br
  .row
  .col-md-8
    .form-group
      = label_tag 'EWAY_CARDNAME', 'Cardholder Name:', class: 'control-label'
      .controls
        = text_field_tag 'EWAY_CARDNAME', nil, class: 'form-control'
  .row
  .col-md-8
    .form-group
      = label_tag 'EWAY_CARDNUMBER', 'Credit Card Number:', class: 'control-label'
      .controls
        = text_field_tag 'EWAY_CARDNUMBER', nil, class: 'form-control'
  .row
  .col-md-6
    .form-group
      = label_tag 'EWAY_CARDEXPIRYMONTH', 'Expiry Date:', class: 'control-label'
      .controls
          .input-group-btn
          = select_tag 'EWAY_CARDEXPIRYMONTH', options_for_select((1..12).to_a), class: 'form-control'
          .input-group-btn
          = select_tag 'EWAY_CARDEXPIRYYEAR', options_for_select((Date.today.year..Date.today.year+10).to_a), class: 'form-control'
  .col-md-2
    .form-group
      = label_tag 'EWAY_CARDCVN', 'CVN:', class: 'control-label'
      .controls
        = password_field_tag 'EWAY_CARDCVN', nil, class: 'form-control'

Сначала в url подставляем FormActionURL. Далее нам необходимо 2 скрытых поля EWAY_ACCESSCODE и EWAY_PAYMENTTYPE. Как вы уже заметили, все названия полей пишутся большими буквами с префиксом «EWAY_». Как результат мы получим вот такую форму 019.png Теперь достаточно заполнить форму и отправить запрос. Результатом станет страница 020.png на которой пользователь может просмотреть данные об оплате и нажатием на «Finalise Transaction» быть перенаправленным на RedirectUrl (к примеру, обратно в наше приложение).

Полезности

Чаще всего, мы не хотим утруждать пользователя дополнительными действиями или хотим показывать нашу страницу подтверждения с деталями. Для этого нам необходимо сделать редирект автоматическим (без нажатия на Finalise Transaction) и передать корректный URL, на который должны перенаправить пользователя. Для начала сделаем автоматическое завершение. Для этого логинимся в наш аккаунт в песочнице и правим настройку 021.png Теперь добавим еще один контроллер, который будет обрабатывать ответ от сервера EWAY

order_finalize GET /orders/:order_id/finalize(.:format)   finalizes#show

Далее нужно установить RedirectUrl в предварительном запросе

attrs = {
  Payment: {
      TotalAmount: order.price_in_cents
  },
  RedirectUrl: order_finalize_url(order),
  CancelUrl: 'http://localhost:3000',
  Method: 'ProcessPayment',
    TransactionType: 'Purchase'
  }

Таким образом, после завершения оплаты пользователь будет перенаправлен на order_finalize_url(order), с дополнительным параметром:

?AccessCode=60CF3fZryW_vHZ1orbE7mhppeLg6CroLWn7WS4sRnnr39fz6PDcO3lnKAXJYv0bC9EKYmI8kWs_29eC8hJ7EsMJtnRCJLjETyAizEr_F7XeguWE1U1N1FvPKOrNJQYi_cFcUE-BddNHE6djze_LeeinvHcA==

Этот код позволяет нам получить доступ к деталям нашей транзакции. Для этого достаточно выполнить следующий запрос:

@result = nil
Curl::Easy.http_get("#{EWAY_SERVICE_URL}/AccessCode/#{params[:AccessCode]}") do |curl|
  curl.headers["Accept"] = "application/json"
  curl.headers["Content-Type"] = "application/json"
  curl.http_auth_types = :basic
  curl.username = EWAY_API_KEY
  curl.password = EWAY_API_PASS
  curl.verbose = true
  curl.on_complete {|response, err|
  @result = response.body_str
  }
end

Ответ содержит всю необходимую информацию:

{
  "AccessCode":"60CF3fZryW_vHZ1orbE7mhppeLg6CroLWn7WS4sRnnr39fz6PDcO3lnKAXJYv0bC9EKYmI8kWs_29eC8hJ7EsMJtnRCJLjETyAizEr_F7XeguWE1U1N1FvPKOrNJQYi_cFcUE-BddNHE6djze_LeeinvHcA==",
  "AuthorisationCode":"936260",
  "ResponseCode":"00",
  "ResponseMessage":"A2000",
  "InvoiceNumber":"",
  "InvoiceReference":"",
  "TotalAmount":1000,
  "TransactionID":11954681,
  "TransactionStatus":true,
  "TokenCustomerID":null,
  "BeagleScore":0,
  "Options":[ 
  ],
  "Verification":{ 
  
  },
  "BeagleVerification":{ 
  
  },
  "Errors":null
}

Внимание стоит обратить на ResponseMessage. Этот ключ содержит коды, характеризующие результат транзакции. К примеру, A2000 - 'Transaction Approved'. V6021 - EWAY_CARDHOLDERNAME Required - пользователь забыл указать имя на карте, и так далее. В зависимости от ответа и статуса транзакции вы сможете выбрать, как реагировать: или показать страницу подтверждения, или вновь предоставить пользователю возможность ввести свои данные. Так как RedirectUrl в нашем случае еще и зависим от order, в случае удачного проведения транзакции мы, к примеру, сможем изменить статус на «оплачено». Статус "оплачено" позволит заблокировать двойную оплату, зачислив средства на баланс, или послать письмо-оповещение.

Связаться