RobocassaをRailsと統合する例

画像

最近、友人がRailsのキャッシュデスクとの統合コードを持っているかどうかを尋ねました。 私は他の誰かがこのコードを必要とするかもしれないと共有し、考えたので、ここでこのトピックを作成することにしました。



コントローラー



コントローラーから始めましょう。ここでは4つのメソッドが必要です。





class PaymentsController < ApplicationController def pay #     ,  : @order = Order.find(params[:id]) unless @order.blank? && @order.payment.blank? #    @pay_desc = Hash.new @pay_desc['mrh_url'] = Payment::MERCHANT_URL @pay_desc['mrh_login'] = Payment::MERCHANT_LOGIN @pay_desc['mrh_pass1'] = Payment::MERCHANT_PASS_1 @pay_desc['inv_id'] = 0 @pay_desc['inv_desc'] = @order.payment.desc @pay_desc['out_summ'] = @order.payment.price.to_s @pay_desc['shp_item'] = @order.id @pay_desc['in_curr'] = "WMRM" @pay_desc['culture'] = "ru" @pay_desc['encoding'] = "utf-8" #    @pay_desc['crc'] = Payment.get_hash(@pay_desc['mrh_login'], @pay_desc['out_summ'], @pay_desc['inv_id'], @pay_desc['mrh_pass1'], "Shp_item=#{@pay_desc['shp_item']}") end end def result crc = Payment.get_hash(params['OutSum'], params['InvId'], Payment::MERCHANT_PASS_2, "Shp_item=#{params['Shp_item']}") @result = "FAIL" begin #   ,     break if params['SignatureValue'].blank? || crc.casecmp(params['SignatureValue']) != 0 @order = Order.where(:id => params['Shp_item']).first #   break if @order.blank? || @order.payment.price != params['OutSum'].to_f #        @order.payment.invid = params['InvId'].to_i @order.payment.status = Payment::STATUS_OK @order.payment.save # ... #  ,    @result = "OK#{params['InvId']}" end while false end def success #       end def fail #  ,   ... end end
      
      







視聴回数



支払方法のフォーム:

 <form action="<%= @pay_desc['mrh_url'] %>" method="post"> <input type=hidden name=MrchLogin value="<%= @pay_desc['mrh_login'] %>"> <input type=hidden name=OutSum value="<%= @pay_desc['out_summ'] %>"> <input type=hidden name=InvId value="<%= @pay_desc['inv_id'] %>"> <input type=hidden name=Desc value="<%= @pay_desc['inv_desc'] %>"> <input type=hidden name=SignatureValue value="<%= @pay_desc['crc'] %>"> <input type=hidden name=Shp_item value="<%= @pay_desc['shp_item'] %>"> <input type=hidden name=IncCurrLabel value="<%= @pay_desc['in_curr'] %>"> <input type=hidden name=Culture value="<%= @pay_desc['culture'] %>"> <input type=submit value=''> </form>
      
      





ここでは、フォームを生成するためにレールメソッドを使用していないという事実に注意を払う価値があります。これは、まだあまり意味がなく、問題があるかもしれないという意図で行われていますが、実際にはこれまでに遭遇していませんが。 通常、RailsはCSRFから保護するための隠しフィールドを生成しますが、キャッシュデスクに送信するため、必要になることはほとんどありません。

キャップ、抵抗できなかったため、ここに結果メソッドのビューを追加することにしました。

  <%= @result %>
      
      





成功と失敗は任意です。



モデル



このモデルでは、mondoidを使用しますが、他のORMでリメイクするのは問題ではないと思います。

また、このモデルには、robocash deskのXMLインターフェイスを操作するためのメソッドがあります。 コードを書いている時点では、レールの下に適切なSOAPクライアントが見つからなかったので、スコアをつけて、単にNokogiriで書くことにしました。

 require 'open-uri' require 'digest/md5' class Payment include Mongoid::Document include Mongoid::Timestamps field :status, :type => Integer field :invid, :type => Integer field :price, :type => Float field :desc # ... MERCHANT_URL = 'https://merchant.roboxchange.com/Index.aspx' # test interface: http://test.robokassa.ru/Index.aspx SERVICES_URL = 'https://merchant.roboxchange.com/WebService/Service.asmx' #test interface: http://test.robokassa.ru/Webservice/Service.asmx MERCHANT_LOGIN = 'login' MERCHANT_PASS_1 = 'your_pass_1' MERCHANT_PASS_2 = 'your_pass_2' def self.get_currencies(lang = "ru") svc_url = "#{SERVICES_URL}/GetCurrencies?MerchantLogin=#{MERCHANT_LOGIN}&Language=#{lang}" doc = Nokogiri::XML(open(svc_url)) doc.xpath("//xmlns:Group").map {|g|{ 'code' => g['Code'], 'desc' => g['Description'], 'items' => g.xpath('.//xmlns:Currency').map {|c| { 'label' => c['Label'], 'name' => c['Name'] }} }} if doc.xpath("//xmlns:Result/xmlns:Code").text.to_i == 0 end def self.get_payment_methods(lang = "ru") svc_url = "#{SERVICES_URL}/GetPaymentMethods?MerchantLogin=#{MERCHANT_LOGIN}&Language=#{lang}" doc = Nokogiri::XML(open(svc_url)) doc.xpath("//xmlns:Method").map {|g| { 'code' => g['Code'], 'desc' => g['Description'] }} if doc.xpath("//xmlns:Result/xmlns:Code").text.to_i == 0 end def self.get_rates(sum = 1, curr = '', lang="ru") svc_url = "#{SERVICES_URL}/GetRates?MerchantLogin=#{MERCHANT_LOGIN}&IncCurrLabel=#{curr}&OutSum=#{sum}&Language=#{lang}" doc = Nokogiri::XML(open(svc_url)) doc.xpath("//xmlns:Group").map {|g| { 'code' => g['Code'], 'desc' => g['Description'], 'items' => g.xpath('.//xmlns:Currency').map {|c| { 'label' => c['Label'], 'name' => c['Name'], 'rate' => c.xpath('./xmlns:Rate')[0]['IncSum'] }} }} if doc.xpath("//xmlns:Result/xmlns:Code").text.to_i == 0 end def self.operation_state(id) crc = get_hash(MERCHANT_LOGIN, id.to_s, MERCHANT_PASS_2) svc_url = "#{SERVICES_URL}/OpState?MerchantLogin=#{MERCHANT_LOGIN}&InvoiceID=#{id}&Signature=#{crc}&StateCode=80" doc = Nokogiri::XML(open(svc_url)) return nil unless doc.xpath("//xmlns:Result/xmlns:Code").text.to_i == 0 state_desc = { 1 => '     InvoiceID  ', 5 => ' ,   ', 10 => '   ,  ', 50 => ' ,     ', 60 => '     ', 80 => '  ', 100 => '  ', } s = doc.xpath("//xmlns:State")[0] code = s.xpath('./xmlns:Code').text.to_i state = { 'code' => code, 'desc' => state_desc[code], 'request_date' => s.xpath('./xmlns:RequestDate').text, 'state_date' => s.xpath('./xmlns:StateDate').text } end def self.get_hash(*s) Digest::MD5.hexdigest(s.join(':')) end end
      
      







ルーター





最後に、後でキャッシュデスクに通知するために、ルートを登録することを忘れないでください。

  match 'payment/result' => "payments#result" match 'payment/success' => "payments#success" match 'payment/fail' => "payments#fail" match 'payment' => "payments#pay"
      
      







ソース



提示されたすべてのコードは、hist



All Articles