1

我需要在 ruby​​ 中使用 SOAP API 创建客户(我们想使用 Ruby on Rails 项目中的 Acumatica api)。

目前我使用 Savon gem 的代码如下所示:

client = Savon.client(wsdl: 'wsdl.wsdl') # sample wsdl path

response = client.call :login, message: { name: '', password: '' }
auth_cookies = response.http.cookies


class ServiceRequest

  def to_s
    builder = Builder::XmlMarkup.new
    builder.instruct!(:xml, encoding: 'UTF-8')

    # ... problem is here, I don't know how XML request should look like

    builder
  end

end

p client.call :submit, message: ServiceRequest.new, cookies: auth_cookies

问题是,我不知道 XML 请求应该是什么样子。

C# 请求看起来像这样(只是文档中的一个示例):

PO302000result = context.PO302000Submit(
      new Command[]
      { new Value { Value = "PORE000079", LinkedCommand =
                                       PO302000.DocumentSummary.ReceiptNbr},
        new Value { Value = "OK", LinkedCommand =
               PO302000.AddPurchaseOrderLine.ServiceCommands.DialogAnswer,
               PO302000.Actions.AddPOOrderLine, new Key { Value = "='PORG000084'", FieldName = Commit = true },
   PO302000.AddPurchaseOrderLine.OrderNbr.FieldName, ObjectName =
              PO302000.AddPurchaseOrderLine.OrderNbr.ObjectName },
       new Key { Value = "='CPU00004'", FieldName =
              PO302000.AddPurchaseOrderLine.InventoryID.FieldName, ObjectName =
              PO302000.AddPurchaseOrderLine.InventoryID.ObjectName },
      new Value{ Value = "True", LinkedCommand =
          PO302000.AddPurchaseOrderLine.Selected, Commit = true },
                                PO302000.Actions.AddPOOrderLine2
       new Key{ Value = "='CPU00004'", FieldName =
     PO302000.DocumentDetails_.InventoryID.FieldName, ObjectName =
                 PO302000.DocumentDetails_.InventoryID.ObjectName},
     new Value{ Value = "1.00", LinkedCommand =
            PO302000.DocumentDetails_.ReceiptQty, Commit = true},
    // the next part of code is needed if you use Serial items
    PO302000.BinLotSerialNumbers.ServiceCommands.NewRow,
   new Value { Value = "R01", LinkedCommand =
                         PO302000.BinLotSerialNumbers.Location },
   PO302000.Actions.Save
  } );

但我不知道这段代码会生成什么样的 XML。看起来我们有带有值的命令数组,然后是动作名称。但是这种代码渲染的是什么 XML?也许一些 C# 或 Java 的人可以复制我由那种代码呈现的 xml 请求示例?

十分感谢。

4

4 回答 4

1

基本上手动生成 XML SOAP 包是个坏主意,你应该有一些包装器,它必须简化你的代码。

于 2015-01-13T14:53:13.817 回答
0

实际上,“mumboe-soap4r”或“soap2r”或“soap4r”不适用于 Acumatica 肥皂 API。他们太老了,而且有问题。

最后,我使用的是 Savon gem(第 2 版)。我正在使用 XmlMarkup 类创建消息。但是我怎么知道我应该创建什么 XML?为了知道这一点,我在 .net 中创建了 soap 请求,然后我看到了正确的 XML 请求是什么样的,然后我才使用 Savon gem 创建了 soap 请求。工作太多,但我现在不知道更好的方法。有用。

为了让 Savon 使用 Acumatica API,我设置了下一个选项:

client = Savon.client do

  wsdl                    'http://path/Soap/AR303000.asmx?wsdl'
  log                     true
  namespaces              'xmlns:soap' => 'http://schemas.xmlsoap.org/soap/envelope/'
  env_namespace           'soap'

  namespace_identifier    nil
  element_form_default    ''

end

不要忘记传递 auth cookies

response = client.call(:login, message: { name: '', password: '' })
auth_cookies = response.http.cookies

构建您的客户创建 xml,然后提交

m = build_create_submit(customer_name)

response = client.call(:submit, message: m, cookies: auth_cookies)

# get customer id of newly created customer
customer_id = response.try(:hash).try(:[], :envelope).
                       try(:[], :body).
                       try(:[], :submit_response).
                       try(:[], :submit_result).
                       try(:[], :content).
                       try(:[], :customer_summary).
                       try(:[], :customer_id).
                       try(:[], :value)
于 2015-01-21T17:32:24.940 回答
0

所以最后我做了什么:

gem install 'mumboe-soap4r'  # not soap4r, 
                             # because soap4r is old and bugged with newer rubies

然后我跑了

wsdl2ruby.rb --wsdl customer.wsdl --type client

wsdl2ruby.rb 与 mumboe-soap4r gem 一起安装的位置。将 customer.wsdl 替换为 wsdl 的路径,可以是 URL 或文件系统路径。

运行此命令后,创建了下一个文件:

default.rb
defaultMappingRegistry.rb
defaultDriver.rb
ScreenClient.rb

使用这些文件,您可以编写类似于 C# 代码或 php 代码的代码来与 acumatica API 进行交互:

require_relative  'defaultDriver'
require           'soap/wsdlDriver'

# this is my helper method to make life easier
def prepare_value(value, command, need_commit = false, ignore = false)
  value_command                   = Value.new
  value_command.value             = value
  value_command.linkedCommand     = command
  value_command.ignoreError       = ignore        unless ignore.nil?
  value_command.commit            = need_commit   unless need_commit.nil?
  value_command
end

soap_client = SOAP::WSDLDriverFactory.new('customer.wsdl').create_rpc_driver
soap_client.login(name: '', password: '').loginResult

screen = soap_client.getSchema(nil)
soap_client.clear(nil)
content = screen.getSchemaResult
# p schema

p customer      = content.customerSummary.customerID
p customer_name = content.customerSummary.customerName
country         = content.generalInfoMainAddress.country
customer_class  = content.generalInfoFinancialSettings.customerClass


commands = ArrayOfCommand.new
commands << prepare_value('ABBA',     customer_name)
commands << prepare_value('US',       country)
commands << prepare_value('MERCHANT', customer_class)
commands << content.actions.insert
commands << customer.clone                # to return

p commands

p soap_client.submit(commands)

希望它会帮助某人。

于 2015-01-13T17:32:04.087 回答
0

无论如何,下面的 C# 代码 + XML SOAP 请求

            Content[] result = context.Submit(
            new Command[] 
                {                                                    
                    new Value { Value = "PORE000079", LinkedCommand = PO302000.DocumentSummary.ReceiptNbr}
                    ,new Value { Value = "OK", LinkedCommand = PO302000.AddPurchaseOrderLine.ServiceCommands.DialogAnswer, Commit = true }
                    ,PO302000.Actions.AddPOOrderLine                                                
                    ,new Key { Value = "='PORG000077'", FieldName = PO302000.AddPurchaseOrderLine.OrderNbr.FieldName, ObjectName = PO302000.AddPurchaseOrderLine.OrderNbr.ObjectName }
                    ,new Key { Value = "='CPU00004'", FieldName = PO302000.AddPurchaseOrderLine.InventoryID.FieldName, ObjectName = PO302000.AddPurchaseOrderLine.InventoryID.ObjectName }
                    ,new Value{ Value = "True", LinkedCommand = PO302000.AddPurchaseOrderLine.Selected, Commit = true }
                    ,PO302000.Actions.AddPOOrderLine2                        
                    ,new Key{ Value = "='CPU00004'", FieldName = PO302000.DocumentDetails.InventoryID.FieldName, ObjectName = PO302000.DocumentDetails.InventoryID.ObjectName}
                    ,new Value{ Value = "1.00", LinkedCommand = PO302000.DocumentDetails.ReceiptQty, Commit = true}         

                    // the next part of code is needed if you use Serial items                            
                    ,PO302000.BinLotSerialNumbers.ServiceCommands.NewRow
                    ,new Value { Value = "R01", LinkedCommand = PO302000.BinLotSerialNumbers.Location }
                    ,new Value { Value = "1.00", LinkedCommand = PO302000.BinLotSerialNumbers.Quantity, Commit = true }
                    ,new Value { Value = "25.00", LinkedCommand = PO302000.DocumentDetails.UnitCost, Commit = true }
                    ,new Key { Value = "='CPU00004'", FieldName = PO302000.DocumentDetails.InventoryID.FieldName, ObjectName = PO302000.DocumentDetails.InventoryID.ObjectName }
                    ,new Value { Value = "0.00", LinkedCommand = PO302000.DocumentDetails.ReceiptQty, Commit = true }

                    ,PO302000.Actions.Save
                }
        );








<?xml version="1.0" encoding="utf-8"?><soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema"><soap:Body><Submit xmlns="http://www.acumatica.com/typed/"><commands><Command xsi:type="Value"><Value>PORE000079</Value><LinkedCommand xsi:type="Field"><FieldName>ReceiptNbr</FieldName><ObjectName>Document</ObjectName><Value>ReceiptNbr</Value><Commit>true</Commit><LinkedCommand xsi:type="Action"><FieldName>cancel</FieldName><ObjectName>Document</ObjectName><LinkedCommand xsi:type="Key"><FieldName>ReceiptNbr</FieldName><ObjectName>Document</ObjectName><Value>=[Document.ReceiptNbr]</Value><LinkedCommand xsi:type="Key"><FieldName>ReceiptType</FieldName><ObjectName>Document</ObjectName><Value>=[Document.ReceiptType]</Value></LinkedCommand></LinkedCommand></LinkedCommand></LinkedCommand></Command><Command xsi:type="Value"><Value>OK</Value><Commit>true</Commit><LinkedCommand xsi:type="Answer"><ObjectName>poLinesSelection</ObjectName><Value>='Yes'</Value></LinkedCommand></Command><Command xsi:type="Action"><FieldName>AddPOOrderLine</FieldName><ObjectName>Document</ObjectName><Commit>true</Commit></Command><Command xsi:type="Key"><FieldName>OrderNbr</FieldName><ObjectName>poLinesSelection</ObjectName><Value>='PORG000077'</Value></Command><Command xsi:type="Key"><FieldName>InventoryID</FieldName><ObjectName>poLinesSelection</ObjectName><Value>='CPU00004'</Value></Command><Command xsi:type="Value"><Value>True</Value><Commit>true</Commit><LinkedCommand xsi:type="Field"><FieldName>Selected</FieldName><ObjectName>poLinesSelection</ObjectName><Value>Selected</Value><Commit>true</Commit></LinkedCommand></Command><Command xsi:type="Action"><FieldName>AddPOOrderLine2</FieldName><ObjectName>Document</ObjectName><Commit>true</Commit></Command><Command xsi:type="Key"><FieldName>InventoryID</FieldName><ObjectName>transactions</ObjectName><Value>='CPU00004'</Value></Command><Command xsi:type="Value"><Value>1.00</Value><Commit>true</Commit><LinkedCommand xsi:type="Field"><FieldName>ReceiptQty</FieldName><ObjectName>transactions</ObjectName><Value>ReceiptQty</Value><Commit>true</Commit></LinkedCommand></Command><Command xsi:type="NewRow"><ObjectName>splits</ObjectName></Command><Command xsi:type="Value"><Value>R01</Value><LinkedCommand xsi:type="Field"><FieldName>LocationID</FieldName><ObjectName>splits</ObjectName><Value>Location</Value></LinkedCommand></Command><Command xsi:type="Value"><Value>1.00</Value><Commit>true</Commit><LinkedCommand xsi:type="Field"><FieldName>Qty</FieldName><ObjectName>splits</ObjectName><Value>Quantity</Value></LinkedCommand></Command><Command xsi:type="Value"><Value>25.00</Value><Commit>true</Commit><LinkedCommand xsi:type="Field"><FieldName>CuryUnitCost</FieldName><ObjectName>transactions</ObjectName><Value>UnitCost</Value></LinkedCommand></Command><Command xsi:type="Key"><FieldName>InventoryID</FieldName><ObjectName>transactions</ObjectName><Value>='CPU00004'</Value></Command><Command xsi:type="Value"><Value>0.00</Value><Commit>true</Commit><LinkedCommand xsi:type="Field"><FieldName>ReceiptQty</FieldName><ObjectName>transactions</ObjectName><Value>ReceiptQty</Value><Commit>true</Commit></LinkedCommand></Command><Command xsi:type="Action"><FieldName>Save</FieldName><ObjectName>Document</ObjectName></Command></commands></Submit></soap:Body></soap:Envelope>
于 2015-01-13T15:06:09.827 回答