狂欢中的奇怪错误,自定义付款方式

时间:2014-07-15 09:30:54

标签: ruby-on-rails ruby-on-rails-4 spree

我正在使用Ruby on Rails 4和Spree,我必须使用外部支付服务 - liqpay - https://www.liqpay.com/,因此我创建了自定义网关,自定义Checkout控制器和用于liqpay回调的Created控制器。付款完成后,我有预先最后一页和一个“完成订单”的按钮,一切似乎都很好。但是当我点击这个但是我有一个错误时,这就是日志中的内容

      ActiveRecord::UnknownAttributeError (unknown attribute: server):
          activerecord (4.0.6) lib/active_record/attribute_assignment.rb:47:in `rescuein _assign_attribute'
        activerecord (4.0.6) lib/active_record/attribute_assignment.rb:42:in `_assign_attribute'
        activerecord (4.0.6) lib/active_record/attribute_assignment.rb:29:in `block in assign_attributes'
      activerecord (4.0.6) lib/active_record/attribute_assignment.rb:23:in `each'
        activerecord (4.0.6) lib/active_record/attribute_assignment.rb:23:in `assign_attributes'
        activerecord (4.0.6) lib/active_record/core.rb:469:in `init_attributes'
      activerecord (4.0.6) lib/active_record/core.rb:185:in `initialize'
        activerecord (4.0.6) lib/active_record/inheritance.rb:30:in `new'
        activerecord (4.0.6) lib/active_record/inheritance.rb:30:in `new'
      spree_core (2.2.4) app/models/spree/gateway.rb:25:in `provider'
        spree_core (2.2.4) app/models/spree/gateway.rb:2:in `purchase'
        spree_core (2.2.4) app/models/spree/payment/processing.rb:158:in `block in gateway_action'
      spree_core (2.2.4) app/models/spree/payment/processing.rb:191:in `protect_from_connection_error'
        spree_core (2.2.4) app/models/spree/payment/processing.rb:155:in `gateway_action'
        spree_core (2.2.4) app/models/spree/payment/processing.rb:33:in `purchase!'
      spree_core (2.2.4) app/models/spree/payment/processing.rb:10:in `process!'
        spree_core (2.2.4) app/models/spree/order.rb:391:in `block in process_payments!'
        spree_core (2.2.4) app/models/spree/order.rb:388:in `each'
      spree_core (2.2.4) app/models/spree/order.rb:388:in `process_payments!'
        spree_core (2.2.4) app/models/spree/order/checkout.rb:74:in `block (2 levels) in define_state_machine!'
        state_machine (1.2.0) lib/state_machine/eval_helpers.rb:79:in `call'
      state_machine (1.2.0) lib/state_machine/eval_helpers.rb:79:in `evaluate_method'
        state_machine (1.2.0) lib/state_machine/callback.rb:191:in `block in run_methods'
        state_machine (1.2.0) lib/state_machine/callback.rb:190:in `each'
      state_machine (1.2.0) lib/state_machine/callback.rb:190:in `run_methods'
        state_machine (1.2.0) lib/state_machine/callback.rb:159:in `call'
        state_machine (1.2.0) lib/state_machine/transition.rb:420:in `before'
      state_machine (1.2.0) lib/state_machine/transition.rb:246:in `block in run_callbacks'
        state_machine (1.2.0) lib/state_machine/transition.rb:348:in `block in pausable'
        state_machine (1.2.0) lib/state_machine/transition.rb:348:in `catch'
      state_machine (1.2.0) lib/state_machine/transition.rb:348:in `pausable'
        state_machine (1.2.0) lib/state_machine/transition.rb:246:in `run_callbacks'
        state_machine (1.2.0) lib/state_machine/transition_collection.rb:127:in `run_callbacks'
      state_machine (1.2.0) lib/state_machine/transition_collection.rb:63:in `block (2 levels) in perform'
        state_machine (1.2.0) lib/state_machine/transition_collection.rb:63:in `catch'
        state_machine (1.2.0) lib/state_machine/transition_collection.rb:63:in `block in perform'
      state_machine (1.2.0) lib/state_machine/transition_collection.rb:182:in `block in within_transaction'
        spree_core (2.2.4) app/models/spree/gateway.rb:25:in `provider'
        spree_core (2.2.4) app/models/spree/gateway.rb:2:in `purchase'
      spree_core (2.2.4) app/models/spree/payment/processing.rb:158:in `block in gateway_action'
        spree_core (2.2.4) app/models/spree/payment/processing.rb:191:in `protect_from_connection_error'
        spree_core (2.2.4) app/models/spree/payment/processing.rb:155:in `gateway_action'
      spree_core (2.2.4) app/models/spree/payment/processing.rb:33:in `purchase!'
        spree_core (2.2.4) app/models/spree/payment/processing.rb:10:in `process!'
        spree_core (2.2.4) app/models/spree/order.rb:391:in `block in process_payments!'
      spree_core (2.2.4) app/models/spree/order.rb:388:in `each'
        spree_core (2.2.4) app/models/spree/order.rb:388:in `process_payments!'
        spree_core (2.2.4) app/models/spree/order/checkout.rb:74:in `block (2 levels) in define_state_machine!'
      state_machine (1.2.0) lib/state_machine/eval_helpers.rb:79:in `call'
        state_machine (1.2.0) lib/state_machine/eval_helpers.rb:79:in `evaluate_method'
        state_machine (1.2.0) lib/state_machine/callback.rb:191:in `block in run_methods'
      state_machine (1.2.0) lib/state_machine/callback.rb:190:in `each'
        state_machine (1.2.0) lib/state_machine/callback.rb:190:in `run_methods'
        state_machine (1.2.0) lib/state_machine/callback.rb:159:in `call'
      state_machine (1.2.0) lib/state_machine/transition.rb:420:in `before'
        state_machine (1.2.0) lib/state_machine/transition.rb:246:in `block in run_callbacks'
        state_machine (1.2.0) lib/state_machine/transition.rb:348:in `block in pausable'
      state_machine (1.2.0) lib/state_machine/transition.rb:348:in `catch'
        state_machine (1.2.0) lib/state_machine/transition.rb:348:in `pausable'
        state_machine (1.2.0) lib/state_machine/transition.rb:246:in `run_callbacks'
      state_machine (1.2.0) lib/state_machine/transition_collection.rb:127:in `run_callbacks'
        state_machine (1.2.0) lib/state_machine/transition_collection.rb:63:in `block (2 levels) in perform'
        state_machine (1.2.0) lib/state_machine/transition_collection.rb:63:in `catch'
      state_machine (1.2.0) lib/state_machine/transition_collection.rb:63:in `block in perform'
        state_machine (1.2.0) lib/state_machine/transition_collection.rb:182:in `block in within_transaction'
        state_machine (1.2.0) lib/state_machine/transition.rb:227:in `block in within_transaction'
      state_machine (1.2.0) lib/state_machine/machine.rb:1904:in `within_transaction'
        state_machine (1.2.0) lib/state_machine/transition.rb:226:in `within_transaction'
        state_machine (1.2.0) lib/state_machine/transition_collection.rb:181:in `within_transaction'
      state_machine (1.2.0) lib/state_machine/transition_collection.rb:62:in `perform'
        state_machine (1.2.0) lib/state_machine/transition.rb:219:in `perform'
        state_machine (1.2.0) lib/state_machine/event.rb:172:in `fire'
      state_machine (1.2.0) lib/state_machine/event.rb:247:in `block in add_actions'
        state_machine (1.2.0) lib/state_machine/machine.rb:765:in `call'
        state_machine (1.2.0) lib/state_machine/machine.rb:765:in `block (2 levels) in define_helper'
      spree_frontend (2.2.4) app/controllers/spree/checkout_controller.rb:30:in `update'
        actionpack (4.0.6) lib/action_controller/metal/implicit_render.rb:4:in `send_action'
        actionpack (4.0.6) lib/abstract_controller/base.rb:189:in `process_action'
      actionpack (4.0.6) lib/action_controller/metal/rendering.rb:10:in `process_action'
        actionpack (4.0.6) lib/abstract_controller/callbacks.rb:18:in `block in process_action'
        activesupport (4.0.6) lib/active_support/callbacks.rb:563:in `_run__4393275023746077082__process_action__callbacks'
      activesupport (4.0.6) lib/active_support/callbacks.rb:80:in `run_callbacks'
        actionpack (4.0.6) lib/abstract_controller/callbacks.rb:17:in `process_action'
        actionpack (4.0.6) lib/action_controller/metal/rescue.rb:29:in `process_action'
      actionpack (4.0.6) lib/action_controller/metal/instrumentation.rb:31:in `block in process_action'
        activesupport (4.0.6) lib/active_support/notifications.rb:159:in `block in instrument'
        activesupport (4.0.6) lib/active_support/notifications/instrumenter.rb:20:in `instrument'
      activesupport (4.0.6) lib/active_support/notifications.rb:159:in `instrument'
        actionpack (4.0.6) lib/action_controller/metal/instrumentation.rb:30:in `process_action'
        actionpack (4.0.6) lib/action_controller/metal/params_wrapper.rb:250:in `process_action'
      activerecord (4.0.6) lib/active_record/railties/controller_runtime.rb:18:in `process_action'
        actionpack (4.0.6) lib/abstract_controller/base.rb:136:in `process'
        actionpack (4.0.6) lib/abstract_controller/rendering.rb:44:in `process'
      actionpack (4.0.6) lib/action_controller/metal.rb:195:in `dispatch'
        actionpack (4.0.6) lib/action_controller/metal/rack_delegation.rb:13:in `dispatch'
        actionpack (4.0.6) lib/action_dispatch/routing/route_set.rb:82:in `dispatch'
      actionpack (4.0.6) lib/action_dispatch/routing/route_set.rb:50:in `call'
        actionpack (4.0.6) lib/action_dispatch/journey/router.rb:71:in `block in call'
        actionpack (4.0.6) lib/action_dispatch/journey/router.rb:59:in `each'
      actionpack (4.0.6) lib/action_dispatch/journey/router.rb:59:in `call'
        actionpack (4.0.6) lib/action_dispatch/routing/route_set.rb:676:in `call'
        railties (4.0.6) lib/rails/engine.rb:511:in `call'
      railties (4.0.6) lib/rails/railtie/configurable.rb:30:in `method_missing'
        actionpack (4.0.6) lib/action_dispatch/journey/router.rb:71:in `block in call'
        actionpack (4.0.6) lib/action_dispatch/journey/router.rb:59:in `each'
      actionpack (4.0.6) lib/action_dispatch/journey/router.rb:59:in `call'
        actionpack (4.0.6) lib/action_dispatch/routing/route_set.rb:676:in `call'
        warden (1.2.3) lib/warden/manager.rb:35:in `block in call'
      warden (1.2.3) lib/warden/manager.rb:34:in `catch'
        warden (1.2.3) lib/warden/manager.rb:34:in `call'
        rack (1.5.2) lib/rack/etag.rb:23:in `call'
      rack (1.5.2) lib/rack/conditionalget.rb:35:in `call'
        rack (1.5.2) lib/rack/head.rb:11:in `call'
        actionpack (4.0.6) lib/action_dispatch/middleware/params_parser.rb:27:in `call'
      actionpack (4.0.6) lib/action_dispatch/middleware/flash.rb:241:in `call'
        rack (1.5.2) lib/rack/session/abstract/id.rb:225:in `context'
        rack (1.5.2) lib/rack/session/abstract/id.rb:220:in `call'
      actionpack (4.0.6) lib/action_dispatch/middleware/cookies.rb:486:in `call'
        activerecord (4.0.6) lib/active_record/query_cache.rb:36:in `call'
        activerecord (4.0.6) lib/active_record/connection_adapters/abstract/connection_pool.rb:626:in `call'
      actionpack (4.0.6) lib/action_dispatch/middleware/callbacks.rb:29:in `block in call'
        activesupport (4.0.6) lib/active_support/callbacks.rb:373:in `_run__2243693745465876108__call__callbacks'
        activesupport (4.0.6) lib/active_support/callbacks.rb:80:in `run_callbacks'
      actionpack (4.0.6) lib/action_dispatch/middleware/callbacks.rb:27:in `call'
        actionpack (4.0.6) lib/action_dispatch/middleware/remote_ip.rb:76:in `call'
        actionpack (4.0.6) lib/action_dispatch/middleware/debug_exceptions.rb:17:in `call'
      actionpack (4.0.6) lib/action_dispatch/middleware/show_exceptions.rb:30:in `call'
        railties (4.0.6) lib/rails/rack/logger.rb:38:in `call_app'
        railties (4.0.6) lib/rails/rack/logger.rb:20:in `block in call'
      activesupport (4.0.6) lib/active_support/tagged_logging.rb:68:in `block in tagged'
        activesupport (4.0.6) lib/active_support/tagged_logging.rb:26:in `tagged'
        activesupport (4.0.6) lib/active_support/tagged_logging.rb:68:in `tagged'
      railties (4.0.6) lib/rails/rack/logger.rb:20:in `call'
        actionpack (4.0.6) lib/action_dispatch/middleware/request_id.rb:21:in `call'
        rack (1.5.2) lib/rack/methodoverride.rb:21:in `call'
      rack (1.5.2) lib/rack/runtime.rb:17:in `call'
        activesupport (4.0.6) lib/active_support/cache/strategy/local_cache.rb:83:in `call'
        rack (1.5.2) lib/rack/sendfile.rb:112:in `call'
      railties (4.0.6) lib/rails/engine.rb:511:in `call'
        railties (4.0.6) lib/rails/application.rb:97:in `call'
        unicorn (4.8.3) lib/unicorn/http_server.rb:576:in `process_client'
      unicorn (4.8.3) lib/unicorn/http_server.rb:670:in `worker_loop'
        unicorn (4.8.3) lib/unicorn/http_server.rb:525:in `spawn_missing_workers'
        unicorn (4.8.3) lib/unicorn/http_server.rb:140:in `start'
      unicorn (4.8.3) bin/unicorn:126:in `<top (required)>'
        /var/www/genetic_shop/shared/bundle/ruby/2.0.0/bin/unicorn:23:in `load'
        /var/www/genetic_shop/shared/bundle/ruby/2.0.0/bin/unicorn:23:in `<main>'

完成付款后调用的控制器方法看起来非常简单

  def payment_network_callback
     if @order.paid?
       @order.next
     end
     redirect_to checkout_state_path(@order.state)
  end
支付状态改变后调用的

和Api控制器方法是(看起来像黑客,但我不知道该怎么做)

            def liqpay_api_callback
              @order = Spree::Order.find params[:order_id]
              @order.payments.create! source: Spree::LiqpayCheckout.create, amount: @order.total,
                                      payment_method: Spree::PaymentMethod.where(type: 'Spree::Gateway::Liqpay').first if @order.payments.length == 0
              if params[:status] == 'success' || params[:status] == 'sandbox'
                @order.update_attribute :payment_state, 'paid'
                head :ok
              else
                head :unprocessable_entity
              end
            rescue => e
              logger.fatal e.class.to_s
              logger.fatal e.to_s
              logger.fatal e.backtrace.join('/n')
              head :internal_server_error
            end

那么,你有什么想法,'未知属性:服务器'是什么以及如何正确地做到这一点?谢谢!

1 个答案:

答案 0 :(得分:2)

找到解决方案。可能它不是好风格,但它有效。所以,主要的逻辑是在CheckoutController装饰器中的回调方法,它在liqpay付款完成后被调用

    def payment_network_callback
      if @order.paid?
        @order.payments.first.process!
        @order.deliver_order_confirmation_email
        @order.next
        @order.finalize!
        session[:order_id] = nil
      end
      redirect_to "/orders/#{@order.number}"
    end

还有另一种方法 - 我的应用程序API方法,liqpay在paiment更改它在另一个控制器中的状态后调用它

          def liqpay_api_callback
            @order = Spree::Order.find params[:order_id]
            sign = get_callback_sign(params[:amount], params[:order_id], params[:status], params[:transaction_id], params[:sender_phone])
            @order.payments.create! source: Spree::LiqpayCheckout.create, amount: @order.total,
                                    payment_method: Spree::PaymentMethod.where(type: 'Spree::Gateway::Liqpay').first if @order.payments.length == 0
            sign[-1]=''
            if (params[:status] == 'success' || params[:status] == 'sandbox') && (sign.eql? params[:signature])
              @order.update_attribute :payment_state, 'paid'
              head :ok
            else
              head :unprocessable_entity
            end
          rescue => e
            logger.fatal e.class.to_s
            logger.fatal e.to_s
            logger.fatal e.backtrace.join('/n')
            head :internal_server_error
          end

        end

这就是Gateway的样子

   module Spree
        class Gateway::Liqpay < Gateway

          attr_accessor :server, :test_mode


          preference :server,:string, default: 'test'
          preference :test_mode, :boolean, default: true


          def provider
            @provider = self
          end

          def purchase(amount, source, options = {})
            Class.new do
              def success?; true; end
              def authorization; nil; end
            end.new
          end

          def auto_capture?
            true
          end

          def payment_profiles_supported?
            true
          end

          def provider_class
            self.class
          end

          def method_type
            'liqpay'
          end
        end
      end