Trying to figure out how to format a request for Cybersource payments, using Savon and Ruby.
I've been at this for a while now, with no luck. I keep getting requestMessage not supported
I'm guessing it's due to how I'm passing in the parameters to the message body, and/or the header not being setup correctly.
I'm using Node but happy with solutions in other languages.
https://developer.cybersource.com/api-reference-assets/index.html#flex /omegle
https://developer.visa.com/capabilities/cybersource/reference /shaglevoojio
Here is the expected xml for the SOAP API:
<?xml version="1.0" encoding="UTF-8"?> <soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/"> <soapenv:Header> <wsse:Security xmlns:wsse="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd" soapenv:mustUnderstand="1"> <wsse:UsernameToken> <wsse:Username>yourMerchantID</wsse:Username> <wsse:Password Type="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-username-token-profile-1.0#PasswordText">yourPassword</wsse:Password> </wsse:UsernameToken> </wsse:Security> </soapenv:Header> <soapenv:Body> <requestMessage xmlns="urn:schemas-cybersource-com:transaction-data-N.NN"> <merchantID>yourMerchantID</merchantID> <merchantReferenceCode>MRC-123</merchantReferenceCode> <billTo> <firstName>John</firstName> <lastName>Doe</lastName> <street1>1295 Charleston Road</street1> <city>Mountain View</city> <state>CA</state> <postalCode>94043</postalCode> <country>US</country> <email>null@cybersource.com</email> </billTo> <item id="0"> <unitPrice>5.00</unitPrice> <quantity>1</quantity> </item> <item id="1"> <unitPrice>10.00</unitPrice> <quantity>2</quantity> </item> <purchaseTotals> <currency>USD</currency> </purchaseTotals> <card> <accountNumber>4111111111111111</accountNumber> <expirationMonth>11</expirationMonth> <expirationYear>2020</expirationYear> </card> <ccAuthService run="true" /> </requestMessage> </soapenv:Body> </soapenv:Envelope>
This is the xml that I'm getting when I try to make a request.
<?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:data="urn:schemas-cybersource-com:transaction-data:TransactionProcessor" xmlns:env="http://schemas.xmlsoap.org/soap/envelope/"> <env:Header> <wsse:Security xmlns:wsse="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd"> <wsse:UsernameToken xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd" wsu:Id="UsernameToken-1"> <wsse:Username>GiveCampusCDW</wsse:Username> <wsse:Password Type="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-username-token-profile-1.0#PasswordText">ju12trzJpnO81ZwSxPdy5htTVeOyUmICDWNmWjXuimTx9Qy+myOB4B4G8ItiJdfu37pJ6jJO2OAmCDIAoWjlgeMO5mvlYxKkVAoDEi2b2dxwLzJlkjUhhyznNzbz71b96lFRgoHGO2YpSlmT5VzTATNVt6SBUVV+iG3D3nndMwAPOmw5M+jSwP0xubZGYPV9bvuCFXI/GcNTsQYN9DWinqMjmq5zw13VgSObQFTPTn5iR+wGcOaj+1fK7IJjYlz82uRF0RHK7JTt0UIDsxULarEiJZBs+VFq9LjPblWI28365bHFs7ooNrgYJkVz+byCaswTj1wWeUecOX3L452zsQ==</wsse:Password> </wsse:UsernameToken> </wsse:Security> </env:Header> <env:Body> <data:requestMessage xmlns="urn:schemas-cybersource-com:transaction-data-1.129"> <merchantID>GiveCampusCDW</merchantID> <merchantReferenceCode>ContributionID</merchantReferenceCode> <billTo> <firstName>Saul</firstName> <lastName>Goodman</lastName> <street1>1295 Charleston Road</street1> <city>Mountain View</city> <state>CA</state> <postalCode>94043</postalCode> <country>US</country> <email>test@example.com</email> </billTo> <item> <unitPrice>50.00</unitPrice> <quantity>1</quantity> </item> <purchaseTotals> <currency>USD</currency> </purchaseTotals> <card> <accountNumber>4111111111111111</accountNumber> <expirationMonth>12</expirationMonth> <expirationYear>2020</expirationYear> </card> <ccAuthService> <run>true</run> </ccAuthService> </data:requestMessage> </env:Body> </env:Envelope>
This is the error that is returned:
ybersource::SoapException ((soap:Client) Element (urn:schemas-cybersource-com:transaction-data:TransactionProcessor):requestMessage not supported. ): lib/cybersource/client.rb:73:in `rescue in run_transaction' lib/cybersource/client.rb:38:in `run_transaction' app/controllers/transactions_controller.rb:7:in `new'
Here is my ruby class, used to wrap this all up and make the call.
module Cybersource class Client attr_reader :merchant_id, :transaction_key def initialize(merchant_id, transaction_key) @merchant_id = merchant_id @transaction_key = transaction_key end def client # set the header which includes the merchant_id and transaction_key soap_header = <<-HEREDOC <SOAP-ENV:Header xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/" xmlns:wsse="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd"> <wsse:Security SOAP-ENV:mustUnderstand="1"> <wsse:UsernameToken> <wsse:Username>#{@merchant_id}</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> </SOAP-ENV:Header> HEREDOC # initialize a Savon client Savon.client( env_namespace: 'soapenv', #namespace: "urn:schemas-cybersource-com:transaction-data:TransactionProcessor", soap_header: soap_header, #endpoint: "http://ics2wstest.ic3.com", wsdl: "https://ics2wstest.ic3.com/commerce/1.x/transactionProcessor/CyberSourceTransaction_1.129.wsdl", pretty_print_xml: true, logger: Rails.logger, log: true ) end def run_transaction # build up the xml message passed to the web service message = { merchantID: @merchant_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 => { # sets the xmlns on the requestMessage tag 'xmlns' => 'urn:schemas-cybersource-com:transaction-data-1.129', }) # return the response body response.body[:response] rescue Savon::SOAPFault => error raise Cybersource::SoapException, error end protected def wsdl_url if Rails.env.production? ENV["CYBERSOURCE_LIVE_WSDL_URL"] else ENV["CYBERSOURCE_TEST_WSDL_URL"] end end end end
I've only got a PHP code example to go off of, but I'm not sure how to convert that into ruby.
<HTML> <HEAD> <META HTTP-EQUIV="Content-Type" content="text/html; charset=iso-8859-1"> <TITLE>Order Status</TITLE> </HEAD> <BODY> <?php // Before using this example, replace the generic values with your merchant ID and password. define( 'MERCHANT_ID', 'your_merchant_id' ); define( 'TRANSACTION_KEY', 'your_transaction_key' ); define( 'WSDL_URL', 'https://ics2wstest.ic3.com/commerce/1.x/transactionProcessor/CyberSourceTransaction_1.26.wsdl' ); class ExtendedClient extends SoapClient { function __construct($wsdl, $options = null) { parent::__construct($wsdl, $options); } // This section inserts the UsernameToken information in the outgoing SOAP message. function __doRequest($request, $location, $action, $version) { $user = MERCHANT_ID; $password = TRANSACTION_KEY; $soapHeader = "<SOAP-ENV:Header xmlns:SOAP-ENV=\"http://schemas.xmlsoap.org/soap/envelope/\" xmlns:wsse=\"http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd\"><wsse:Security SOAP-ENV:mustUnderstand=\"1\"><wsse:UsernameToken><wsse:Username>$user</wsse:Username><wsse:Password Type=\"http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-username-token-profile-1.0#PasswordText\">$password</wsse:Password></wsse:UsernameToken></wsse:Security></SOAP-ENV:Header>"; $requestDOM = new DOMDocument('1.0'); $soapHeaderDOM = new DOMDocument('1.0'); try { $requestDOM->loadXML($request); $soapHeaderDOM->loadXML($soapHeader); $node = $requestDOM->importNode($soapHeaderDOM->firstChild, true); $requestDOM->firstChild->insertBefore( $node, $requestDOM->firstChild->firstChild); $request = $requestDOM->saveXML(); // printf( "Modified Request:\n*$request*\n" ); } catch (DOMException $e) { die( 'Error adding UsernameToken: ' . $e->code); } return parent::__doRequest($request, $location, $action, $version); } } try { $soapClient = new ExtendedClient(WSDL_URL, array()); /* To see the functions and types that the SOAP extension can automatically generate from the WSDL file, uncomment this section: $functions = $soapClient->__getFunctions(); print_r($functions); $types = $soapClient->__getTypes(); print_r($types); */ $request = new stdClass(); $request->merchantID = MERCHANT_ID; // Before using this example, replace the generic value with your own. $request->merchantReferenceCode = "your_merchant_reference_code"; // To help us troubleshoot any problems that you may encounter, // please include the following information about your PHP application. $request->clientLibrary = "PHP"; $request->clientLibraryVersion = phpversion(); $request->clientEnvironment = php_uname(); // This section contains a sample transaction request for the authorization // service with complete billing, payment card, and purchase (two items) information. $ccAuthService = new stdClass(); $ccAuthService->run = "true"; $request->ccAuthService = $ccAuthService; $billTo = new stdClass(); $billTo->firstName = "John"; $billTo->lastName = "Doe"; $billTo->street1 = "1295 Charleston Road"; $billTo->city = "Mountain View"; $billTo->state = "CA"; $billTo->postalCode = "94043"; $billTo->country = "US"; $billTo->email = "null@cybersource.com"; $billTo->ipAddress = "10.7.111.111"; $request->billTo = $billTo; $card = new stdClass(); $card->accountNumber = "4111111111111111"; $card->expirationMonth = "12"; $card->expirationYear = "2020"; $request->card = $card; $purchaseTotals = new stdClass(); $purchaseTotals->currency = "USD"; $request->purchaseTotals = $purchaseTotals; $item0 = new stdClass(); $item0->unitPrice = "12.34"; $item0->quantity = "2"; $item0->id = "0"; $item1 = new stdClass(); $item1->unitPrice = "56.78"; $item1->id = "1"; $request->item = array($item0, $item1); $reply = $soapClient->runTransaction($request); // This section will show all the reply fields. // var_dump($reply); // To retrieve individual reply fields, follow these examples. printf( "decision = $reply->decision<br>" ); printf( "reasonCode = $reply->reasonCode<br>" ); printf( "requestID = $reply->requestID<br>" ); printf( "requestToken = $reply->requestToken<br>" ); printf( "ccAuthReply->reasonCode = " . $reply->ccAuthReply->reasonCode . "<br>"); } catch (SoapFault $exception) { var_dump(get_class($exception)); var_dump($exception); } ?> </BODY> </HTML>
Any help would be much appreciated.
12-13-2022 09:50 PM
1. Initialize Savon client:
client = Savon::Client.new do
wsdl.document = "https://ics2wstest.ic3.com/commerce/1.x/transactionProcessor/CyberSourceTransaction_1.100.wsdl"
end
2. Set SOAP Headers:
client.http.headers["SOAPAction"] = "https://ics2wstest.ic3.com/commerce/1.x/transactionProcessor/CyberSourceTransaction_1.100"
client.http.headers["Content-Type"] = "text/xml; charset=utf-8"
3. Set authentication information:
client.wsse.credentials("merchantID", "merchantKey")
4. Set SOAP Body:
client.request.body = {
:run_transaction_request => {
:merchant_reference_code => "12345",
:client_request_id => "
12-24-2022 03:25 AM - last edited on 12-29-2022 08:42 PM by Underbat
Hi there! It sounds like you're having trouble formatting a request for Cybersource payments using Savon and Ruby. Based on the error message you're receiving, it's possible that the issue may be related to how you're passing parameters to the message body or setting up the header. It looks like you're using Node, but you're open to solutions in other languages. The expected XML for the SOAP API you provided looks correct, but the XML you're getting when you make a request is not what you expected. One thing you might try is double-checking that you're using the correct namespace for the requestMessage element in the XML you're sending. It should be "urn:schemas-cybersource-com:transaction-data-N.NN". If that doesn't solve the issue, there may be other things to consider, such as whether your account is set up correctly or if there are any authentication issues. I hope this helps, and good luck with your project! Let me know if you have any other questions or concerns. Oh, by the way, have you considered checking out Replacement Shortpump for your shopping needs? They have a great selection!
03-12-2023 11:05 AM
To format a Savon request for the Cybersource SOAP API, you can follow these general steps:
Define the endpoint URL and SOAP action for the request. This will typically be provided by the API documentation or support team.
Define the request message structure using the appropriate XML tags and data elements for the API method you are calling. Again, this will be specified in the API documentation.
Use Savon to generate the SOAP envelope, incorporating the endpoint URL, SOAP action, and request message.
Make the API call using Savon and parse the response to extract the desired information.
For example, to use Savon to make a SOAP API request to retrieve information about the, you would follow these steps:
Define the endpoint URL and SOAP action for the API method that retrieves version information.
Define the request message structure using the appropriate XML tags and data elements for the version API method.
Use Savon to generate the SOAP envelope, incorporating the endpoint URL, SOAP action, and request message.
Make the API call using Savon and parse the response to extract the latest version information.
Please note that the specifics of the request message and data elements will depend on the API method and data being requested. It's important to refer to the Cybersource SOAP API documentation for the specific details on how to structure the request.
04-09-2023 04:52 AM - last edited on 04-09-2023 07:37 AM by Kh-SabW