如何在Rails 4和Savon中使用Magento SOAP API v1中的过滤器?

时间:2014-01-30 20:59:33

标签: ruby-on-rails magento soap ruby-on-rails-4 savon

我正在使用Magento SOAP API v1和Savon gem在Rails 4中构建应用程序。现在我正试图获得状态为待定的所有订单。要挂钩API,我使用的是this代码:

class MagentoAPI
  def self.call method, options={}
    response = @@soap_client.request :call do
      if options.empty?
        soap.body = { :session => @@soap_session, :method => method }
      elsif options[:string]
        soap.body = { :session => @@soap_session, :method => method, :arguments => [options[:string]] }
      else
        puts options
        soap.body = { :session => @@soap_session, :method => method, :arguments => options }
      end
    end
    if response.success?
      # listing found products
      final = []
      call_return = response[:call_response][:call_return]
      return [] if call_return[:item].nil?
      raw = call_return[:item]
      if raw.is_a? Hash # this is a list of one item
        final << raw[:item].inject({}){|x,y| x.merge(y[:key]=>y[:value])}
      else
        if raw[0][:item].nil? # this is a product info
          return raw.inject({}){|x,y| x.merge(y[:key]=>y[:value])}
        else # this is a list of many items
          raw.each{|result| final << result[:item].inject({}){|x,y| x.merge(y[:key]=>y[:value])}}
        end
      end
      final
    end
  end
end

然后这个:

class Order
  def self.get_all_active
    activeOrders = MagentoAPI.call 'order.list', :filter => {:status => 'pending'}
  end
end

这只会返回Savon::HTTP::Error,所以我想我没有正确格式化请求。有没有人对此有任何经验或见解?

1 个答案:

答案 0 :(得分:2)

希望这不是太晚(假设可能是这样),但我用一些基本的文档为此创建了一个宝石。我希望在本周末或下周完成它,但你可以看看代码,看看我是如何为Magento创建过滤器的。要安装,只需运行:

gem install magento_api_wrapper

总而言之,如果您想使用其中一个Magento SOAP API简单过滤器,您可以传递带有键和值的哈希:

api = MagentoApiWrapper::Sales.new(magento_url: "yourmagentostore.com/index.php", magento_username: "soap_api_username", magento_api_key: "userkey123")

api.order_list(simple_filters: [{key: "status", value: "processing"}, {key: created_at, value: "12/10/2013 12:00" }])

要使用复杂的过滤器,请传递带键,运算符和值的哈希:

api.order_list(complex_filters: [{key: "status", operator: "eq", value: ["processing", "completed"]}, {key: created_at, operator: "from", value: "12/10/2013" }])

这将返回包含所有Magento订单的哈希数组。

具体来说,请查看请求代码:https://github.com/harrisjb/magento_api_wrapper/blob/master/lib/magento_api_wrapper/requests/sales_order_list.rb

虽然使用gem会更容易,但这是我在将请求传递给SavonClient之前格式化请求的方式,后者完成了Magento SOAP API的格式化:

   def body
      merge_filters!(sales_order_list_hash)
    end

    def attributes
      { session_id: { "xsi:type" => "xsd:string" },
        filters: { "xsi:type" => "ns1:filters" },
      }
    end

    def sales_order_list_hash
      {
        session_id: self.session_id
      }
    end

    def merge_filters!(sales_order_list_hash)
      if !filters_array.empty?
        sales_order_list_filters = {
          filters: filters_array,
        }
        sales_order_list_hash.merge!(sales_order_list_filters)
      else
        sales_order_list_hash
      end
    end

    def filters_array
      custom_filters = {}
      custom_filters.compare_by_identity
      if !simple_filters.nil?
        add_simple_filters(custom_filters)
      end

      if !complex_filters.nil?
        add_complex_filters(custom_filters)
      end
      custom_filters
    end

    def add_simple_filters(custom_filters)
      simple_filters.each do |sfilter|
        custom_filters[:attributes!] = {
          "filter" => {
            "SOAP-ENC:arrayType" => "ns1:associativeEntity[2]",
            "xsi:type" => "ns1:associativeArray"
          }
        }
        custom_filters["filter"] = {
          item: {
            key: sfilter[:key],
            value: sfilter[:value],  #formatted_timestamp(created_at)
            :attributes! => {
              key: { "xsi:type" => "xsd:string" },
              value: { "xsi:type" => "xsd:string" }
            },
          },
          :attributes! => {
            item: { "xsi:type" => "ns1:associativeEntity" },
          },
        }
      end
      custom_filters
    end

    def add_complex_filters(custom_filters)
      complex_filters.each do |cfilter|
        custom_filters[:attributes!] = {
          "complex_filter" => {
            "SOAP-ENC:arrayType" => "ns1:complexFilter[2]",
            "xsi:type" => "ns1:complexFilterArray"
          }
        }
        custom_filters["complex_filter"] = {
          item: {
            key: cfilter[:key],
            value: {
              key: cfilter[:operator],
              value: cfilter[:value]
            },
            :attributes! => {
              key: { "xsi:type" => "xsd:string" },
              value: { "xsi:type" => "xsd:associativeEntity" }
            },
          },
          :attributes! => {
            item: { "xsi:type" => "ns1:complexFilter" },
          },
        }
      end
      custom_filters
    end

    def formatted_timestamp(timestamp)
      begin
        Time.parse(timestamp).strftime("%Y-%m-%d %H:%M:%S")
      rescue MagentoApiWrapper::BadRequest => e
        raise "Did you pass date in format YYYY-MM-DD? Error: #{e}"
      end
    end

    def status_array
      data[:status_array]
    end

    def created_at_from
      data[:created_at_from]
    end

    def created_at_to
      data[:created_at_to]
    end

    def last_modified
      data[:last_modified]
    end

    def session_id
      data[:session_id]
    end

    def simple_filters
      data[:simple_filters]
    end

    def complex_filters
      data[:complex_filters]
    end

我还有一个SavonClient可以为特定的API执行一些配置,其中大部分内容都是:

   def call
      client.call(@request.call_name, message: message_with_attributes, response_parser: :nokogiri)
    end

    #message_with_attributes are required for some specific formatting when updating Magento via the SOAP API
    def message_with_attributes
      @request.body.merge!(:attributes! => @request.attributes) unless @request.attributes.empty?
      puts "REQUEST: #{@request.inspect}"
      return @request.body
    end

    #configuration of the client is mostly mandatory, however some of these options (like timeout) will be made configurable in the future
    #TODO: make timeout configurable
    def client
      Savon::Client.new do |savon|
        savon.ssl_verify_mode          :none
        savon.wsdl                     base_url
        savon.namespaces               namespaces
        savon.env_namespace            'SOAP-ENV'
        savon.raise_errors             false
        #savon.namespace_identifier     #none
        savon.convert_request_keys_to  :lower_camelcase
        savon.strip_namespaces         true
        savon.pretty_print_xml         true
        savon.log                      log_env
        savon.open_timeout             10    #seconds
        savon.read_timeout             45    #seconds
      end
    end

    #TODO: make configurable
    def log_env
      true
    end

    #correctly format MagentoApiWrapper::Request call_names for SOAP v2
    def response_tag_format_lambda
      lambda { |key| key.snakecase.downcase }
    end

    def namespaces
      {
        'xmlns:SOAP-ENV' => 'http://schemas.xmlsoap.org/soap/envelope/',
        'xmlns:ns1' => 'urn:Magento',
        'xmlns:xsd' => 'http://www.w3.org/2001/XMLSchema',
        'xmlns:xsi' => 'http://www.w3.org/2001/XMLSchema-instance',
        'xmlns:SOAP-ENC' => 'http://schemas.xmlsoap.org/soap/encoding/',
        'SOAP-ENV:encodingStyle' => 'http://schemas.xmlsoap.org/soap/encoding/'
      }
    end

    #Use MagentoApiWrapper::Api magento_url as endpoint
    def base_url
      "#{@magento_url}/api/v2_soap?wsdl=1"
    end
  end

就像我说的那样,这是一项正在进行中的工作,但我应该在接下来的几周内完成对Magento API的完整报道。希望这可以帮助你!祝你好运!