Интеграция Robokassa в ActiveMerchant

в 14:48, , рубрики: active_merchant, robokassa, ruby, ruby on rails

Прим. переводчика — пост про интеграцию 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

* - обязательные к заполнению поля


https://ajax.googleapis.com/ajax/libs/jquery/3.4.1/jquery.min.js