Reputation: 2086
When calling to an API for retrieving labels for post parcels I get frustrated with how hard it is to set up a SOAP call with ruby.
I know that the following works from a sandbox environment:
this is the SHOULD BE call
<s:Envelope xmlns:s="http://schemas.xmlsoap.org/soap/envelope/">
<s:Header>
<Action s:mustUnderstand="1" xmlns="http://schemas.microsoft.com/ws/2005/05/addressing/none">http://postnl.nl/cif/services/BarcodeWebService/IBarcodeWebService/GenerateBarcode</Action>
<Security xmlns="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd">
<wsse:UsernameToken xmlns:wsse="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd">
<wsse:Username>devc_!R4xc8p9</wsse:Username>
<wsse:Password Type="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-username-token-profile-1.0#PasswordText">098fd559930983af31ef6630a0bb0c1974156561</wsse:Password>
</wsse:UsernameToken>
</Security>
</s:Header>
<s:Body>
<GenerateBarcode xmlns:d6p1="http://postnl.nl/cif/domain/BarcodeWebService/" xmlns:i="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://postnl.nl/cif/services/BarcodeWebService/">
<d6p1:Message>
<d6p1:MessageID>5</d6p1:MessageID>
<d6p1:MessageTimeStamp>28-06-2017 14:15:41</d6p1:MessageTimeStamp>
</d6p1:Message>
<d6p1:Customer>
<d6p1:CustomerCode>DEVC</d6p1:CustomerCode>
<d6p1:CustomerNumber>11223344</d6p1:CustomerNumber>
</d6p1:Customer>
<d6p1:Barcode>
<d6p1:Type>3S</d6p1:Type>
<d6p1:Range>DEVC</d6p1:Range>
<d6p1:Serie>1000000-2000000</d6p1:Serie>
</d6p1:Barcode>
</GenerateBarcode>
</s:Body>
</s:Envelope>
EDIT
As sugested I used build_request
to inspect how my request looks. It actually looks like this:
<?xml version="1.0" encoding="UTF-8"?>
<env:Envelope xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:wsdl="http://tempuri.org/" xmlns:env="http://schemas.xmlsoap.org/soap/envelope/">
<env:Header>
<Username>devc_!R4xc8p9</Username
<Password>098fd559930983af31ef6630a0bb0c1974156561</Password>
</env:Header>
<env:Body><wsdl:GenerateBarcode><CustomerCode>DEVC</CustomerCode>
<CustomerNumber>11223344</CustomerNumber>
<Type>3S</Type>
<Range>DEVC</Range>
<Serie>1000000-2000000</Serie>
</wsdl:GenerateBarcode>
</env:Body>
</env:Envelope>
Comparing that with the xml above, it becomes clear that stuff is off. How to handle nesting?
This is when I build it myself like:
@client = Savon.client(
:convert_request_keys_to => :camelcase,
:raise_errors => false,
:pretty_print_xml => true,
:wsdl => 'https://testservice.postnl.com/CIF_SB/BarcodeWebService/1_1/?wsdl',
:headers => {
'Username' => 'devc_!R4xc8p9',
'Password' => '098fd559930983af31ef6630a0bb0c1974156561'
})
@response = @client.call(:generate_barcode) do
soap_header "Username" => 'devc_!R4xc8p9',
"Password" => '098fd559930983af31ef6630a0bb0c1974156561'
message customer_code: 'DEVC',
customer_number: 11223344,
type: '3S',
range: 'DEVC',
serie: '1000000-2000000'
end
I know my connection works, but also get back:
{:fault=>{:faultcode=>"s:CIF Framework Message Interceptor",
:faultstring=>"Check CIFException in the detail section", :detail=>
{:cif_exception=>{:errors=>{:exception_data=>{:description=>nil,
:error_msg=>"Username/password is not specified.",
:error_number=>"3"}},
:@xmlns=>"http://postnl.nl/cif/services/common/",
:"@xmlns:i"=>"http://www.w3.org/2001/XMLSchema-instance"}}}}
So already in my header stuff goes wrong. Username/password is not specified. I've tried several combinations and I don't get why.
Update
@client = Savon.client(
:env_namespace => :s,
# :namespace_identifier => :none, # :none doesn't work... gets interpreted literary. Out-commeting gives wsdl:GenerateBarcode
:convert_request_keys_to => :camelcase,
:raise_errors => false,
:pretty_print_xml => true,
:endpoint => 'https://testservice.postnl.com/CIF_SB/BarcodeWebService/1_1/BarcodeWebService.svc',
:wsdl => 'https://testservice.postnl.com/CIF_SB/BarcodeWebService/1_1/?wsdl')
soap_header = {
"Security" => {
"UsernameToken" => {
"Username" => 'devc_!R4xc8p9',
"Password" => '098fd559930983af31ef6630a0bb0c1974156561'
}
}
}
message = {
"d6p1:Customer" => {
"d6p1:CustomerCode" => 'DEVC',
"d6p1:CustomerNumber" => 11223344
},
"d6p1:Barcode" => {
"d6p1:Type" => '3S',
"d6p1:Range" => 'DEVC',
"d6p1:Serie" => '1000000-2000000'
}
}
@request = @client.build_request(:generate_barcode) do
soap_header soap_header
message message
end
@response = @client.call(:generate_barcode) do
soap_header soap_header
message message
Which builds the following request:
<?xml version="1.0" encoding="UTF-8"?>
<s:Envelope xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:s="http://tempuri.org/" xmlns:s="http://schemas.xmlsoap.org/soap/envelope/">
<s:Header>
<Security>
<UsernameToken>
<Username>devc_!R4xc8p9</Username
<Password>098fd559930983af31ef6630a0bb0c1974156561</Password>
</UsernameToken>
</Security>
</s:Header>
<s:Body>
<wsdl:GenerateBarcode>
<d6p1:Customer>
<d6p1:CustomerCode>DEVC</d6p1:CustomerCode
<d6p1:CustomerNumber>11223344</d6p1:CustomerNumber>
</d6p1:Customer>
<d6p1:Barcode>
<d6p1:Type>3S</d6p1:Type>
<d6p1:Range>DEVC</d6p1:Range>
<d6p1:Serie>1000000-2000000</d6p1:Serie>
</d6p1:Barcode></s:GenerateBarcode>
</s:Body>
For as of yet, I get errors adding the wsse:
namespace straight in the soap_header
hash.
EDIT 2
<?xml version="1.0" encoding="UTF-8"?>
<s:Envelope
xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:wsdl="http://tempuri.org/"
xmlns:s="http://schemas.xmlsoap.org/soap/envelope/">
<s:Header>
<Action s:mustUnderstand="1" xmlns="http://schemas.microsoft.com/ws/2005/05/addressing/none">http://postnl.nl/cif/services/BarcodeWebService/IBarcodeWebService/GenerateBarcode
</Action>
<Security xmlns="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd">
<UsernameToken>
<Username>devc_!R4xc8p9</Username>
<Password>xxxxxxxx</Password>
</UsernameToken>
</Security>
</s:Header>
<s:Body>
<wsdl:GenerateBarcode>
<d6p1:Customer>
<d6p1:CustomerCode>DEVC</d6p1:CustomerCode>
<d6p1:CustomerNumber>11223344</d6p1:CustomerNumber>
</d6p1:Customer>
<d6p1:Barcode>
<d6p1:Type>3S</d6p1:Type>
<d6p1:Range>DEVC</d6p1:Range>
<d6p1:Serie>1000000-2000000</d6p1:Serie>
</d6p1:Barcode>
</wsdl:GenerateBarcode>
</s:Body>
</s:Envelope>
Comparing this to my should be call it seems that my <s:envelope ...>
tag has too much information.
I'll make a follow up question of this probably.
EDIT 3
I restarted at Complex SOAP call in Ruby on Rails using Savon gets weird around the envelope and main operation
Upvotes: 1
Views: 1096
Reputation: 1077
The Message hash, should be nested in the same way as the call expects it something like
@client = Savon.client(
:convert_request_keys_to => :camelcase,
:raise_errors => false,
:pretty_print_xml => true,
:wsdl => 'https://testservice.postnl.com/CIF_SB/BarcodeWebService/1_1/?wsdl',
:headers => {
'Username' => 'devc_!R4xc8p9',
'Password' => '098fd559930983af31ef6630a0bb0c1974156561'
})
@response = @client.call(:generate_barcode) do
soap_header "Security" => {
"UsernameToken" => {
"Username" => 'devc_!R4xc8p9',
"Password" => '098fd559930983af31ef6630a0bb0c1974156561'
}
}
message "GenerateBarcode" => {
"Message" => {
"MessageID" => 5, #might be different
"MessageTime" => Time.now, #might be different depending on use case
},
"Customer" => {
"CustomerCode" => 'DEVC',
"CustomerNumber" => 11223344
},
"Barcode" => {
"Type" => '3S',
"Range" => 'DEVC',
"Serie" => '1000000-2000000'
}
}
end
EDIT
Referencing this page it looks like you can add the action tag and elements like this
'Action' => "http://postnl.nl/cif/services/BarcodeWebService/IBarcodeWebService/GenerateBarcode",
:attributes! => {
"s:mustUnderstand" => "1",
"xmlns" => "http://schemas.microsoft.com/ws/2005/05/addressing/none"
}
Referencing this page it looks like you can set the namespaces directly "wsse:UsernameToken" instead of "UsernameToken"
which should result in the following
@client = Savon.client(
:convert_request_keys_to => :camelcase,
:raise_errors => false,
:pretty_print_xml => true,
:wsdl => 'https://testservice.postnl.com/CIF_SB/BarcodeWebService/1_1/?wsdl',
:headers => {
'Username' => 'devc_!R4xc8p9',
'Password' => '098fd559930983af31ef6630a0bb0c1974156561'
})
@response = @client.call(:generate_barcode) do
soap_header "Security" => {
"wsse:UsernameToken" => {
"wsse:Username" => 'devc_!R4xc8p9',
"wsse:Password" => '098fd559930983af31ef6630a0bb0c1974156561'
}
"Action" => "http://postnl.nl/cif/services/BarcodeWebService/IBarcodeWebService/GenerateBarcode",
:attributes! => {
"s:mustUnderstand" => "1",
"xmlns" => "http://schemas.microsoft.com/ws/2005/05/addressing/none"
}
}
message "GenerateBarcode" => {
"Message" => {
"MessageID" => 5, #might be different
"MessageTime" => Time.now, #might be different depending on use case
},
"Customer" => {
"CustomerCode" => 'DEVC',
"CustomerNumber" => 11223344
},
"Barcode" => {
"Type" => '3S',
"Range" => 'DEVC',
"Serie" => '1000000-2000000'
}
}
end
Upvotes: 2