ed209
ed209

Reputation: 838

Send XML with php via post

I know there are any number of similar questions to this on SO, but I've tried messing around with all the solutions and haven't seemed to be able to make it work. I am trying to post xml directly to a web service and get a response back. Technically I am trying to connect to freightquote.com, the documentation for which you can find in the upper right hand corner of this page under documentation. I only mention that because I see the term SOAP a lot in their xml and it might make a difference. Anyway what I want is the ability to send xml to some url and get a response back.

So if I had the following

$xml = "<?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>
              <GetRatingEngineQuote xmlns='http://tempuri.org/'>
                <request>
                  <CustomerId>0</CustomerId> <!-- Identifier for customer provided by Freightquote -->
                  <QuoteType>B2B</QuoteType> <!-- B2B / eBay /Freightview -->
                  <ServiceType>LTL</ServiceType> <!--  LTL / Truckload / Groupage / Haulage / Al  -->
                  <QuoteShipment>
                    <IsBlind>false</IsBlind>
                    <PickupDate>2010-09-13T00:00:00</PickupDate>
                    <SortAndSegregate>false</SortAndSegregate>
                    <ShipmentLocations>
                      <Location>
                        <LocationType>Origin</LocationType>
                        <RequiresArrivalNotification>false</RequiresArrivalNotification>
                        <HasDeliveryAppointment>false</HasDeliveryAppointment>
                        <IsLimitedAccess>false</IsLimitedAccess>
                        <HasLoadingDock>false</HasLoadingDock>
                        <IsConstructionSite>false</IsConstructionSite>
                        <RequiresInsideDelivery>false</RequiresInsideDelivery>
                        <IsTradeShow>false</IsTradeShow>
                        <IsResidential>false</IsResidential>
                        <RequiresLiftgate>false</RequiresLiftgate>
                        <LocationAddress>
                          <PostalCode>30303</PostalCode>
                          <CountryCode>US</CountryCode>
                        </LocationAddress>
                        <AdditionalServices />
                      </Location>
                      <Location>
                        <LocationType>Destination</LocationType>
                        <RequiresArrivalNotification>false</RequiresArrivalNotification>
                        <HasDeliveryAppointment>false</HasDeliveryAppointment>
                        <IsLimitedAccess>false</IsLimitedAccess>
                        <HasLoadingDock>false</HasLoadingDock>
                        <IsConstructionSite>false</IsConstructionSite>
                        <RequiresInsideDelivery>false</RequiresInsideDelivery>
                        <IsTradeShow>false</IsTradeShow>
                        <IsResidential>false</IsResidential>
                        <RequiresLiftgate>false</RequiresLiftgate>
                        <LocationAddress>
                          <PostalCode>60606</PostalCode>
                          <CountryCode>US</CountryCode>
                        </LocationAddress>
                        <AdditionalServices />
                      </Location>
                    </ShipmentLocations>
                    <ShipmentProducts>
                      <Product>
                        <Class>55</Class>
                        <Weight>1200</Weight>
                        <Length>0</Length>
                        <Width>0</Width>
                        <Height>0</Height>
                        <ProductDescription>Books</ProductDescription>
                        <PackageType>Pallets_48x48</PackageType>
                        <IsStackable>false</IsStackable>
                        <DeclaredValue>0</DeclaredValue>
                        <CommodityType>GeneralMerchandise</CommodityType>
                        <ContentType>NewCommercialGoods</ContentType>
                        <IsHazardousMaterial>false</IsHazardousMaterial>
                        <PieceCount>5</PieceCount>
                        <ItemNumber>0</ItemNumber>
                      </Product>
                    </ShipmentProducts>
                    <ShipmentContacts />
                  </QuoteShipment>
                </request>
                <user>
                  <Name>[email protected]</Name>
                  <Password>password</Password>
                </user>
              </GetRatingEngineQuote>
            </soap:Body>
            </soap:Envelope>";

(I edited this to contain my actual xml since it may lend some perspective

I'd want to send it to http://www.someexample.com and get a response. Also, do I need to encode it? I've done a lot of sending xml back and forth with android, and never had to but that might be part of my problem.

My attempt to send the information currently looks like this

$xml_post_string = 'XML='.urlencode($xml->asXML());  
$ch = curl_init(); 
curl_setopt($ch, CURLOPT_URL, 'https://b2b.Freightquote.com/WebService/QuoteService.asmx');
curl_setopt($ch, CURLOPT_POST, TRUE);
curl_setopt($ch, CURLOPT_POSTFIELDS, $xml_post_string);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);

$response = curl_exec($ch);
curl_close($ch);

Upvotes: 5

Views: 31669

Answers (4)

Fanda
Fanda

Reputation: 3786

If you are walking around SOAP services, I strongly recommend you to learn basics once, and then use this great tool again and again. There are many features you can just use, or you will be reinventing the wheel and struggling with generating xml files, parsing xml files, faults etc. Use prepared tools and your life will be easier and your code better (less bugs).

Look at http://www.php.net/manual/en/soapclient.soapcall.php#example-5266 how to consume SOAP webservice. It is not so hard to understand.

Here is some code how you can analyze webserivce. Then map types to classes and just send and receive php objects. You can look for some tool to generate classes automatically (http://www.urdalen.no/wsdl2php/manual.php).

<?php
try
{
    $client = new SoapClient('http://b2b.freightquote.com/WebService/QuoteService.asmx?WSDL');

    // read function list
    $funcstions = $client->__getFunctions();
    var_dump($funcstions);

    // read some request obejct
    $response = $client->__getTypes();
    var_dump($response);
}
catch (SoapFault $e)
{
    // do some service level error stuff
}
catch (Exception $e)
{
    // do some application level error stuff
}

If you will use wsdl2php generating tool, everything is very easy:

<?php

require_once('./QuoteService.php');

try
{
    $client = new QuoteService();

    // create request
    $tracking = new TrackingRequest();
    $tracking->BOLNumber = 67635735;

    $request = new GetTrackingInformation();
    $request->request = $tracking;

    // send request
    $response = $client->GetTrackingInformation($request);
    var_dump($response);
}
catch (SoapFault $e)
{
    // do some service level error stuff
    echo 'Soap fault ' . $e->getMessage();
}
catch (Exception $e)
{
    // do some application level error stuff
    echo 'Error ' . $e->getMessage();
}

Generated php code for QuoteService.php you can see here: http://pastie.org/8165331

This is captured communication:

Request

POST /WebService/QuoteService.asmx HTTP/1.1
Host: b2b.freightquote.com
Connection: Keep-Alive
User-Agent: PHP-SOAP/5.4.17
Content-Type: text/xml; charset=utf-8
SOAPAction: "http://tempuri.org/GetTrackingInformation"
Content-Length: 324

<?xml version="1.0" encoding="UTF-8"?>
<SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/" xmlns:ns1="http://tempuri.org/">
    <SOAP-ENV:Body>
        <ns1:GetTrackingInformation>
            <ns1:request>
                <ns1:BOLNumber>67635735</ns1:BOLNumber>
            </ns1:request>
        </ns1:GetTrackingInformation>
    </SOAP-ENV:Body>
</SOAP-ENV:Envelope>

Response

HTTP/1.1 200 OK
Date: Mon, 22 Jul 2013 21:46:06 GMT
Server: Microsoft-IIS/6.0
X-Powered-By: ASP.NET
X-AspNet-Version: 2.0.50727
Cache-Control: private, max-age=0
Content-Type: text/xml; charset=utf-8
Content-Length: 660
Set-Cookie: BIGipServerb2b_freightquote_com=570501130.20480.0000; path=/

<?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>
        <GetTrackingInformationResponse xmlns="http://tempuri.org/">
            <GetTrackingInformationResult>
                <BOLNumber>0</BOLNumber>
                <EstimatedDelivery>0001-01-01T00:00:00</EstimatedDelivery>
                <TrackingLogs />
                <ValidationErrors>
                    <B2BError>
                        <ErrorType>Validation</ErrorType>
                        <ErrorMessage>Unable to find shipment with BOL 67635735.</ErrorMessage>
                    </B2BError>
                </ValidationErrors>
            </GetTrackingInformationResult>
        </GetTrackingInformationResponse>
    </soap:Body>
</soap:Envelope>

Upvotes: 7

Walk
Walk

Reputation: 1649

You can use stream_context_create and file_get_contents to send xml in post.

$xml = "<your_xml_string>";
$send_context = stream_context_create(array(
    'http' => array(
    'method' => 'POST',
    'header' => 'Content-Type: application/xml',
    'content' => $xml
    )
));

print file_get_contents($url, false, $send_context);

Upvotes: 2

lilobase
lilobase

Reputation: 441

I use this command-line script to test SOAP call:

#!/usr/bin/php
<?php
//file client-test.php
$xml_data = file_get_contents('php://stdin');

$ch = curl_init('http://example.com/server/');
curl_setopt($ch, CURLOPT_HTTPHEADER, array('Content-Type: text/xml'));
curl_setopt($ch, CURLOPT_HTTPHEADER, array('SOAPAction', 'MySoapAction'));
curl_setopt($ch, CURLOPT_POST, 1);
curl_setopt($ch, CURLOPT_POSTFIELDS, $xml_data);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
$output = curl_exec($ch);
curl_close($ch);

print_r($output);

Usage like this (in command line) : $ client-test.php < yourSoapEnveloppe.xml

In this example the yourSoapEnveloppe.xml file is the content of your $xml variable.

Upvotes: 1

Mash
Mash

Reputation: 1349

First, if your code is written like this, I doubt this works be cause of the quotes... You should use double quote around your xml:

$my_xml = "<?xml version='1.0' standalone='yes'?>
           <user> 
               <Name>[email protected]</Name> 
               <Password>XML</Password> 
           </user>";

Also, you could use poster, a firefox addon (there is probably the equivalent on chrome), to help you with your requests, especially if you use WebServices. That way, you will be able to see if the error is server-side or client-side.

This should help you debugging.

Upvotes: 1

Related Questions