How to format Savon Request for Cybersource SOAP API
First let me say my knowledge of Ruby is minimal, so I can't help with the Savon client. But I did try your raw xml request, and realized that precisely the requestMessage
ended up in the wrong namespace:
<data:requestMessage>
refers to xmlns:data="urn:schemas-cybersource-com:transaction-data:TransactionProcessor"
when it should be xmlns:data="urn:schemas-cybersource-com:transaction-data-1.129"
I see you have commented out the namespace parameter in your client initialization. That may be the way to set the namespace in case the client doesn't read it from the wsdl.
As per this answer you can specify different namespaces as needed.
Update
Ok, I think I got it to work. Take a look at this script:
require 'savon'soap_header = <<-HEREDOC <wsse:Security> <wsse:UsernameToken> <wsse:Username>username</wsse:Username> <wsse:Password Type="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-username-token-profile-1.0#PasswordText">transaction_key</wsse:Password> </wsse:UsernameToken> </wsse:Security> HEREDOCclient = Savon.client( wsdl: 'https://ics2wstest.ic3.com/commerce/1.x/transactionProcessor/CyberSourceTransaction_1.129.wsdl', soap_header: soap_header, env_namespace: 'soapenv', element_form_default: :unqualified, namespace: "urn:schemas-cybersource-com:transaction-data-1.129", namespaces: { "xmlns:wsse": "http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd" }, pretty_print_xml: true, #logger: Rails.logger, log: true)message = { merchantID: "merch_id", merchantReferenceCode: rand(100), billTo: { firstName: "Saul", lastName: "Goodman", street1: "1295 Charleston Road", city: "Mountain View", state: "CA", postalCode: "94043", country: "US", email: "test@example.com", }, item: { unitPrice: "50.00", quantity: "1", }, purchaseTotals: { currency: "USD" }, card: { accountNumber: "4111111111111111", expirationMonth: "12", expirationYear: "2020" }, ccAuthService: { :@run => "true" }}response = client.call(:run_transaction, message: message, :attributes => { 'xmlns' => 'urn:schemas-cybersource-com:transaction-data-1.129',})response.body[:response]
With this I'm getting Authentication failed as expected.So, a couple of things that were wrong:
The header definition should leave out the
Header
node, just start with the inner nodes (Security
)The
run => true
inccAuthService
is an attribute, not an inner node.The whole namespacing mess of the
requestMessage
.