Gem для подключения к платежному шлюзу unitpay.money и unitpay.ru.
Документация к шлюзу help.unitpay.money и help.unitpay.ru
- Установка
- Подключение
- Получение ссылки для оплаты
- Использование в Rails
- Подключение виджета для карт оплаты
Добавьте эти строки в Gemfile вашего приложения:
gem 'unitpay'
И выполните:
$ bundle
Или установите напрямую:
$ gem install unitpay
## Подключение
Чтобы получить доступ к сервисному классу, достаточно проинициализировать его с вашим рабочим доменом (unitpay.money
или unitpay.ru
) и public
и secret
ключами.
Unitpay::Service.new('domain', 'unitpay_public_key', 'unitpay_secret_key')
По умолчанию курс валюты выставлен в RUB
, а использование сигнатуры в true
.
Переопределить их можно и при инициализации.
use_sign, currency = false, 'RUB'
Unitpay::Service.new('domain', 'unitpay_public_key', 'unitpay_secret_key', use_sign, currency)
Чтобы включить проверку сигнатуры со стороны unitpay
, необходимо нажать на "замочек" в настройках вашего партнера.
- Включение проверки сигнатуры.
Secret key
для инициализацииUnitpay::Service
.- Необходимо изменить
example.com
на адрес вашего приложения. - Необходимо изменить
example.com
на адрес вашего приложения.
## Получение ссылки для оплаты
Чтобы получить ссылку для оплаты, необходимо использовать метод payment_url
, в который нужно передать следующие параметры:
Название | Описание |
---|---|
sum |
Цена, которую необходимо оплатить пользователю |
account |
Внутренний идентификатор платежа (или заказа), однозначно определяющий его в магазине. |
desc |
Описание платежа, отображающееся пользователю на стороне шлюза. |
sum, account, desc = 100, 1, 'description'
service = Unitpay::Service.new('domain', 'unitpay_public_key', 'unitpay_secret_key')
service.payment_url(sum, account, desc)
# => domain - 'unitpay.money' or 'unitpay.ru'
# => 'https://domain/pay/public_key?sum=100&account=1&desc=description...'
Добавьте роуты для получения запросов от unitpay (config/routes.rb
)
scope :unitpay do
get :success, to: 'unitpay#success'
get :fail, to: 'unitpay#fail'
get :notify, to: 'unitpay#notify'
end
Создайте app/controllers/unitpay_controller.rb
со следующим кодом:
class UnitpayController < ApplicationController
include Unitpay::Controller
skip_before_filter :verify_authenticity_token
def success
# вызывается при отправке шлюзом пользователя на Success URL.
#
# ВНИМАНИЕ: является незащищенным действием!
# Для выполнения действий после успешной оплаты используйте pay
end
def fail
# вызывается при отправке шлюзом пользователя на Fail URL.
# (во время принятия платежа возникла ошибка)
end
private
def pay
# вызывается при оповещении магазина об
# успешной оплате пользователем заказа и после проверки сигнатуры.
#
# ВНИМАНИЕ: правильный ответ будет сгенерирован автоматически (не нужно использовать render\redirect_to)!
# order = Order.find(params[:params][:account])
# order.payed!
end
def error
# вызывается при оповещении магазина об ошибке при оплате заказа.
# При отсутствии логики обработки ошибок на стороне приложения оставить метод пустым.
#
# ВНИМАНИЕ: правильный ответ будет сгенерирован автоматически (не нужно использовать render\redirect_to)!
# puts params[errorMessage]
# => Текст ошибки, присланный unitpay
end
def service
# ВНИМАНИЕ: обязательный метод! Используется при проверке сигнатуры.
Unitpay::Service.new('domain', 'unitpay_public_key', 'unitpay_secret_key')
end
end
Описание параметров, передаваемых при запросе: help.unitpay.money и help.unitpay.ru
Важно понимать, что до вызова метода pay
происходит проверка только сигнатуры.
Прочие проверки на соответствие платежа правилам логики приложения остаются на вашей совести (например, эквивалентность суммы оплаты и суммы заказа).
Для удобства обработки таких ситуаций существует зарезервированное исключение Unitpay::Controller::RuntimeException
. В этом случае в ответе будет передан текст вашей ошибки.
Пример:
def pay
order = Order.find(params[:params][:account])
if order.total_cost == params[:params][:sum]
order.payed!
else
raise Unitpay::Controller::RuntimeException.new('Неверная сумма оплаты')
end
end
## Подключение виджета для карт оплаты
Рассмотрим один из способов реализации случая, когда необходимо показать виджет оплаты после заполнения пользователем формы заказа.
- Подключите на странице внешний скрипт:
<script src="https://widget.unitpay.ru/unitpay.js"></script>
- Добавьте обработчик формы заказа:
unitpay.js.coffe
class Unitpay
bindEvents: ->
@handleAfterSubmitForm()
handleAfterSubmitForm: ->
$('#id-your-form').submit (e) ->
e.preventDefault()
tryUnitpay() # при сабмите формы пытаемся получить параметры для виджета
tryUnitpay = ->
$.ajax({
type: 'POST',
dataType: 'json'
url: '/orders' # любой другой путь сохранения\создания вашего платежа (заказа). Не забудьте добавить его в routes.rb
data: $('#id-your-form').serialize(),
success: (data) ->
payment = new UnitPay()
payment.createWidget(data)
payment.success ->
console.log('Unitpay: успешный платеж')
payment.error ->
# ошибка платежного шлюза (например, пользователь не завершил оплату)
console.log('Unitpay: ошибка платежа')
error: ->
# ошибка при сохранении заказа (например, ошибки валидации)
console.log('Ошибка сохранения\создания платежа (заказа)')
})
$ ->
unitpay = new Unitpay
unitpay.bindEvents()
- Измените контроллер так, чтобы он отдавал необходимый
json
ответ:
orders_controller.rb
class OrdersController < ApplicationController
def create
order = Order.new(permitted_params)
if order.save
render json: unitpay_service.params_for_widget(order.total_cost, order.id, order.description)
else
render json: order.errors, status: :unprocessable_entity
end
end
private
def unitpay_service
# Внимание: не храните ключи в открытом виде в репозитории.
# используйте конфигурационные файлы (https://github.com/binarylogic/settingslogic)
Unitpay::Service.new('domain', 'public_key', 'secret_key')
end
def permitted_params
# используйте strong params
end
end
- Fork it ( https://github.com/ssnikolay/unitpay/fork )
- Create your feature branch (
git checkout -b my-new-feature
) - Commit your changes (
git commit -am 'Add some feature'
) - Push to the branch (
git push origin my-new-feature
) - Create a new Pull Request