Ruby on rails 如何将MagentoSOAPIPV1中的过滤器与Rails 4和Savon一起使用?

Ruby on rails 如何将MagentoSOAPIPV1中的过滤器与Rails 4和Savon一起使用?,ruby-on-rails,magento,soap,ruby-on-rails-4,savon,Ruby On Rails,Magento,Soap,Ruby On Rails 4,Savon,我正在Rails 4中使用Magento SOAP API v1和Savon gem构建一个应用程序。现在我正在尝试获取所有状态为“待定”的订单。要连接到API,我正在使用以下代码: 这只返回Savon::HTTP::Error,因此我认为我没有正确格式化请求。有人对此有任何经验或见解吗?希望这不会太晚(假设可能),但我用一些基本文档为此创建了一个gem。我希望在这个周末或下周完成它,但是你可以看看代码,看看我是如何为Magento创建过滤器的。要安装,只需运行: gem install mag

我正在Rails 4中使用Magento SOAP API v1和Savon gem构建一个应用程序。现在我正在尝试获取所有状态为“待定”的订单。要连接到API,我正在使用以下代码:

这只返回
Savon::HTTP::Error
,因此我认为我没有正确格式化请求。有人对此有任何经验或见解吗?

希望这不会太晚(假设可能),但我用一些基本文档为此创建了一个gem。我希望在这个周末或下周完成它,但是你可以看看代码,看看我是如何为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" }])
要使用复杂筛选器,请传递带有键、运算符和值的哈希:

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顺序的哈希数组

具体来说,请查看请求代码:

虽然只使用gem会更容易,但在将请求传递给SavonClient之前,我将如何格式化请求,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

正如我所说,这是一项正在进行的工作,但我应该在接下来的几周内完成对MagentoAPI的非常好的报道。希望这对你有帮助!祝你好运

你还想解决这个问题吗?如果是这样的话,你能把你的问题归结为一段最小的代码吗。那太复杂了。我可以帮助您处理Savon和SOAP调用,但在我着手解决相关问题之前,我不能先理解代码的逻辑。我想这就是为什么到目前为止没有人在这里写任何东西的原因。@SteffenRoller谢谢你的回复。最后,我使用PHP完成了这项工作,效果很好。我认为这里的问题在于Magento期望深度嵌套数组的方式,而Savon没有以Magento能够处理的方式将哈希转换为这些数组。我相信在Magento的那一头会有更多的问题。使用Savon,对API的任何不需要任何参数的请求都可以正常工作,但请求更具体的参数会引发一般的SOAPFault错误。虽然这些链接可能会回答问题,但最好在此处包含答案的基本部分,并提供链接供参考。如果链接页面发生更改,只有链接的答案可能会无效。Joel编辑了答案,以包含链接中的源代码,以确保清晰性,并且答案将在网站历史记录中保留。请参阅?这就是你从我这里得到+1的原因!