Прим. переводчика — пост про интеграцию Robokassa и Rails уже был, но способ, предоставленый там, полагаю, многих не устроит.
Когда у вас есть приложение, написанное на Ruby on Rails и вы планируете добавить какую-нибудь платежную систему (например PayPal, Moneybookers или Robokassa, как в нашем случае), то первый гем о котором вы должны подумать — это active_merchant от Shopify.
ActiveMerchant — простая абстрактная платежная библиотека используемая и спонсируемая компанией Shopify.
Поэтому когда мне понадобилось добавить платежи через Robokassa в наш проект, я открыл список поддержеваемых платежных систем и был немного разачарован, потому что Robokassa туда не входила. Чуть позже я нашел форк, который добавлял её поддержку, но он уже устарел, поэтому некоторые тесты падали ec801d3d4f8. Таким образом я решил глянуть на этот код и исправить его, а не писать всё с чистого листа.
На самом деле, чтобы починить тесты мне пришлось всего лишь исправить небольшую опечатку 07fb5494134 (збс — прим. пер.). Да, это было несложно. Затем я решил добавить к предыдущему решению различные url для тестового окружения и продакшена (Robokassa рекомендует сначала все-таки потестировать свой код в песочнице, а уже потом, когда все заработает, использовать в живом режиме). Посмотреть на этот код можно тут — c2ec85d53cb.
Теперь настало время добавить active_merchant в проект. Добавьте его в Gemfile:
gem 'activemerchant', :require => 'active_merchant'
Чтобы использовать хелперы ActionView (типа payment_service_for) необходимо положить файлик activemerchant.rb в папку initializers:
require 'active_merchant'
require 'active_merchant/billing/integrations/action_view_helper'
ActionView::Base.send(:include, ActiveMerchant::Billing::Integrations::ActionViewHelper)
Чтобы использовать режим production в инишиалайзер нужно добавить еще строчку:
ActiveMerchant::Billing::Base.integration_mode = :production # :test for sandbox
Следующий шаг — роуты. Robokassa делает push-запрос к приложению, когда транзакция завершена, поэтому необходимо добавить следующие строчки в routes.rb:
scope 'robokassa' do
match 'paid' => 'robokassa#paid', :as => :robokassa_paid # to handle Robokassa push request
match 'success' => 'robokassa#success', :as => :robokassa_success # to handle Robokassa success redirect
match 'fail' => 'robokassa#fail', :as => :robokassa_fail # to handle Robokassa fail redirect
end
Теперь создадим контроллер, чтобы всё это заработало::
class RobokassaController < ApplicationController
include ActiveMerchant::Billing::Integrations
skip_before_filter :verify_authenticity_token # skip before filter if you chosen POST request for callbacks
before_filter :create_notification
before_filter :find_payment
# Robokassa call this action after transaction
def paid
if @notification.acknowledge # check if it’s genuine Robokassa request
@payment.approve! # project-specific code
render :text => @notification.success_response
else
head :bad_request
end
end
# Robokassa redirect user to this action if it’s all ok
def success
if !@payment.approved? && @notification.acknowledge
@payment.approve!
end
redirect_to @payment, :notice => I18n.t("notice.robokassa.success")
end
# Robokassa redirect user to this action if it’s not
def fail
redirect_to @payment, :notice => I18n.t("notice.robokassa.fail")
end
private
def create_notification
@notification = Robokassa::Notification.new(request.raw_post, :secret => AppConfig.robokassa_secret)
end
def find_payment
@payment = Payment.find(@notification.item_id)
end
end
Ну и наконец добавим форму на страницу:
<%= payment_service_for @payment.id, AppConfig.robokassa_login,
:amount => @payment.amount,
:service => :robokassa,
:secret => AppConfig.robokassa_secret do |s| %>
<%= submit_tag "Submit" %>
<% end %>
Вот и всё! Теперь если существует объект @payment
, то после сабмита формы произойдет редирект на сайт Робокассы, где можно будет совершить платеж на сумму, указанную в @payment.amount
.
Автор: dreamfall