1

My company uses has a lot of internal APIs that use very specific header and formatting requirements. I am new to SOAP::Lite and I'm trying to make it work within the company's framework.

Try #1: Ideally, I would like to be able to just take the raw XML template (see bottom of the post), populate some placeholder variables, and send it to the endpoint using the following code:

my $client = SOAP::Lite->new( proxy => "$serviceURL");
my $reply = $client->InquireEnterpriseOrderDataRequest($rawxml);

However, this results in my header and request sections being enclosed in it's own "envelope", "body" and "InquireEnterpriseOrderDataRequest" which is rejected by the service.

Try #2: The next thing I tried was to break my request into two pieces: header and request and use SOAP::Data and SOAP::Header to send those:

my $rawxmlheader = '<ns2:MessageHeader xmlns:ns2="http://mycompany.com/MessageHeader.xsd" xmlns="http://mycompany.com/CingularDataModel.xsd">
 <ns2:TrackingMessageHeader>
    <version>111</version>
    <originalVersion/>
    <messageId/>
    <originatorId>ABC</originatorId>
    <responseTo/>
    <returnURL/>
    <timeToLive>360000</timeToLive>
    <conversationId>9AF0E9281A524262980F5284F4C57888_CCE423E277C74FA9A84D2155CD612EB3_0</conversationId>
    <routingRegionOverride/>
    <dateTimeStamp>2017-05-12T12:47:53Z</dateTimeStamp>
    <uniqueTransactionId>mytransid</uniqueTransactionId>
 </ns2:TrackingMessageHeader>
 <ns2:SecurityMessageHeader>
    <userName>myusername</userName>
    <userPassword>mypass</userPassword>
 </ns2:SecurityMessageHeader>
 <ns2:SequenceMessageHeader>
    <sequenceNumber/>
    <totalInSequence/>
 </ns2:SequenceMessageHeader>
</ns2:MessageHeader>';

my $rawxmlrequest = '<OrderSearchCriteria>
    <OrderDetails>
       <SearchByOrderAction>
      <orderActionNumber>12345654</orderActionNumber>
      <orderActionVersion>1</orderActionVersion>
       </SearchByOrderAction>
    </OrderDetails>
 </OrderSearchCriteria>
 <provisioningDetailsIndicator>true</provisioningDetailsIndicator>';

    my $client = SOAP::Lite->new( proxy => "$serviceURL");
    my $header = SOAP::Header->type('xml' => $rawxmlheader);
    my $elem = SOAP::Data->type('xml' => $rawxmlrequest);
    my @arguments;
    push(@arguments, $header);
    push(@arguments, $elem);
    my $reply = $client->InquireEnterpriseOrderDataRequest(@arguments);

This produced a very similar request to what was needed with the exception that the InquireEnterpriseOrderDataRequest blob did not contain the xsi:schemaLocation, xmlns or xmlns:xsi values that seem to be required.

Try #3: Now I was grasping at straws, so I also tried to granularly create my own XML using something like this:

my $temp_elements = 
        SOAP::Data->name("OrderSearchCriteria" => \SOAP::Data->value(
        SOAP::Data->name("OrderDetails" => \SOAP::Data->value(
        SOAP::Data->name("SearchByOrderAction" => \SOAP::Data->value(
        SOAP::Data->name("orderActionNumber" => '301496944'),
        SOAP::Data->name("orderActionVersion" => '3')
        )
        )
    )
    ))
        )->type("SomeObject");

my $client = SOAP::Lite->new( proxy => "$serviceURL");
my $reply = $client->InquireEnterpriseOrderDataRequest($temp_elements);

The problem here was that I don't know how to include the xsi:schemaLocation, xmlns and xmlns:xsi values or prepend the header information.

Of course, I'd like to go with the simplest possible implementation but any suggestions are appreciated! Thanks in advance!

Required request format:

<SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/">
   <SOAP-ENV:Header>
      <ns2:MessageHeader xmlns:ns2="http://mycompany.com/MessageHeader.xsd" xmlns="http://mycompany.com/CingularDataModel.xsd">
         <ns2:TrackingMessageHeader>
            <version>111</version>
            <originalVersion/>
            <messageId/>
            <originatorId>ABC</originatorId>
            <responseTo/>
            <returnURL/>
            <timeToLive>360000</timeToLive>
            <conversationId>9AF0E9281A524262980F5284F4C57888_CCE423E277C74FA9A84D2155CD612EB3_0</conversationId>
            <routingRegionOverride/>
            <dateTimeStamp>2017-04-11T18:47:53Z</dateTimeStamp>
            <uniqueTransactionId>mytransid</uniqueTransactionId>
         </ns2:TrackingMessageHeader>
         <ns2:SecurityMessageHeader>
            <userName>myusername</userName>
            <userPassword>mypass</userPassword>
         </ns2:SecurityMessageHeader>
         <ns2:SequenceMessageHeader>
            <sequenceNumber/>
            <totalInSequence/>
         </ns2:SequenceMessageHeader>
      </ns2:MessageHeader>
   </SOAP-ENV:Header>
  <SOAP-ENV:Body>
      <InquireEnterpriseOrderDataRequest xsi:schemaLocation="http://mycompany.com/InquireEnterpriseOrderDataRequest.xsd" xmlns="http://mycompany.com/InquireEnterpriseOrderDataRequest.xsd" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
         <OrderSearchCriteria>
            <OrderDetails>
               <SearchByOrderAction>
                  <orderActionNumber>12345654</orderActionNumber>
                  <orderActionVersion>1</orderActionVersion>
               </SearchByOrderAction>
            </OrderDetails>
         </OrderSearchCriteria>
         <provisioningDetailsIndicator>true</provisioningDetailsIndicator>
      </InquireEnterpriseOrderDataRequest>
   </SOAP-ENV:Body>
</SOAP-ENV:Envelope>
ShinobiDev
  • 103
  • 2
  • 2
  • 6
  • If you have a wsdl file, try with XML::Compile. It allows you to use the wsdl to generate the correct messages automatically. But it does get tricky sometimes. – simbabque May 13 '17 at 10:01
  • Please read my question. I know the correct format for the request, I just can't figure out how to send it using SOAP::Lite. – ShinobiDev May 13 '17 at 16:43
  • I have read your question, that's why I am suggesting an alternative. Playing around with SOAP::Lite is frustrating. Give https://metacpan.org/pod/distribution/XML-Compile-SOAP/lib/XML/Compile/SOAP.pod a try and you'll see it will probably handle the namespaces and attributes better. – simbabque May 13 '17 at 16:47

1 Answers1

1

This should generate the required response using SOAP::Lite request.

use strict;
use warnings;
use SOAP::Lite +trace=>'all';

$on_action = '';
$proxy = 'http://serviceURL';

$soap = SOAP::Lite->new(proxy => $proxy);
$soap->on_action(sub {$on_action});
$soap->readable(1);
$soap->autotype(0);
$soap->serializer->register_ns('http://mycompany.com/InquireEnterpriseOrderDataRequest.xsd' => 'xsi');
$soap->serializer->register_ns('http://mycompany.com/InquireEnterpriseOrderDataRequest.xsd' => 'xsi:schemaLocation');
$soap->default_ns('http://mycompany.com/InquireEnterpriseOrderDataRequest.xsd');
$soap->envprefix('SOAP-ENV');

$sheader = SOAP::Header->name(MessageHeader =>\SOAP::Header->value(SOAP::Header->name(TrackingMessageHeader => \SOAP::Header->value(
               SOAP::Header->name(version => 111),
               SOAP::Header->name(originalVersion => ''),
               SOAP::Header->name(messageId => ''),
               SOAP::Header->name(originatorId => 'ABC'),
               SOAP::Header->name(responseTo => ''),
               SOAP::Header->name(returnURL => ''),
               SOAP::Header->name(timetoLive => 360000),
               SOAP::Header->name(conversationId => '9AF0E9281A524262980F5284F4C57888_CCE423E277C74FA9A84D2155CD612EB3_0'),
               SOAP::Header->name(routingRegionOverride => ''),
               SOAP::Header->name(dateTimeStamp => '2017-04-11T18:47:53Z'),
               SOAP::Header->name(timetoLive => 'mytransid'),
            ))->prefix('ns2')))->attr({'xmlns:ns2' => 'http://mycompany.com/MessageHeader.xsd',xmlns => 'http://mycompany.com/CingularDataModel.xsd'})->prefix('ns2');

push @request,(
        SOAP::Data->name(OrderSearchCriteria => \SOAP::Data->value(
           SOAP::Data->name(OrderDetails => \SOAP::Data->value(
              SOAP::Data->name(SearchByOrderAction => \SOAP::Data->value(
                 SOAP::Data->name(orderActionNumber => 12345654),
                 SOAP::Data->name(orderActionVersion => 1),
)))))));
$reply = $soap->InquireEnterpriseOrderDataRequest($sheader,@request);
rahed h
  • 41
  • 1
  • This is what I was trying to do but I couldn't figure out how to assign attributes to the header elements. The last thing I am having trouble with is how to work in the "SecurityMessageHeader" and "SequenceMessageHeader" sections without breaking out of the header block. Any ideas for this? – ShinobiDev May 22 '17 at 19:57
  • Look at http://www.wlp-systems.de/soap-lite-and-ws-security.html or google for it. I used it with SOAP::Lite. – rahed h May 23 '17 at 13:51