1

I'm got this API up and working, but in a complete round about way I do not feel comfortable with.. my problem is their response has soap: prefix's on a few indexes and I cannot get them to work as even registering those prefix's. So the way I'm band-aiding the problem is subtracting the soap: characters at the beginning and the end of the string, then turning into JSON.. Messy right??

Perhaps I didn't get the defining the prefix's correctly for soap and pur but I couldn't get that to work at all, kept saying the prefix was undefined.

This is my code

<?php
ini_set('display_errors',1);
ini_set('display_startup_errors',1);
error_reporting(-1);


//variables from quoting system
    $quote_client_id = $_GET['quote_client_id'];
    $quote_billterms = $_GET['quote_billterms'];
    $quote_ship_date = $_GET['quote_ship_date'];

    //convert time to ISO 8601 format
        $quote_ship_date = (new DateTime($quote_ship_date))->format('c');

    //shipper variables
        $quote_shipper_postalcode = $_GET['quote_shipper_postalcode'];
        $quote_shipper_country = $_GET['quote_shipper_country'];
        $quote_shipper_state = $_GET['quote_shipper_state'];
        $quote_shipper_city = $_GET['quote_shipper_city'];

    //consignee variables
        $quote_consignee_postalcode = $_GET['quote_consignee_postalcode'];
        $quote_consignee_country = $_GET['quote_consignee_country'];
        $quote_consignee_state = $_GET['quote_consignee_state'];
        $quote_consignee_city = $_GET['quote_consignee_city'];

    //package info
        $quote_weight = $_GET['quote_weight'];
        $quote_l = $_GET['quote_l'];
        $quote_w = $_GET['quote_w'];
        $quote_h = $_GET['quote_h'];
        $quote_quantity = $_GET['quote_quantity'];


//XML Request
    $xml = "<?xml version='1.0' encoding='utf-8'?>
        <soap:Envelope xmlns:soap='http://schemas.xmlsoap.org/soap/envelope/' xmlns:pur='http://PurolatorServices.com/'>
          <soap:Body>
            <pur:GetRates>
              <pur:request>
                <pur:Credentials>
                  <pur:UserName>username</pur:UserName>
                  <pur:Password>pw</pur:Password>
                  <pur:ClientID>clientid</pur:ClientID>
                </pur:Credentials>
                <pur:OrderNumber>TEST</pur:OrderNumber>
                <pur:ShipDate>" . $quote_ship_date . "</pur:ShipDate>
                <pur:BillingOption>" . $quote_billterms . "</pur:BillingOption>
                <pur:ShipFromAddress>
                  <pur:City>" . $quote_shipper_city . "</pur:City>
                  <pur:StateProv>" . $quote_shipper_state . "</pur:StateProv>
                  <pur:PostalCode>" . $quote_shipper_postalcode . "</pur:PostalCode>
                  <pur:Country>" . $quote_shipper_country . "</pur:Country>
                </pur:ShipFromAddress>
                <pur:ShipToAddress>
                  <pur:City>" . $quote_consignee_city . "</pur:City>
                  <pur:StateProv>" . $quote_consignee_state . "</pur:StateProv>
                  <pur:PostalCode>" . $quote_consignee_postalcode . "</pur:PostalCode>
                  <pur:Country>" . $quote_consignee_country . "</pur:Country>
                </pur:ShipToAddress>
                <pur:Currency>USD</pur:Currency>
                <pur:Packages>
                  <pur:RequestPackageV3>
                    <pur:WeightUOM>LB</pur:WeightUOM>
                    <pur:Weight>" . $quote_weight . "</pur:Weight>
                    <pur:DimL>" . $quote_l . "</pur:DimL>
                    <pur:DimW>" . $quote_w . "</pur:DimW>
                    <pur:DimH>" . $quote_h . "</pur:DimH>
                  </pur:RequestPackageV3>
                </pur:Packages>
              </pur:request>
            </pur:GetRates>
          </soap:Body>
        </soap:Envelope>
    ";


//XML Request Headers for POST
    $headers = array(
        "POST /WebServices/ShippingServicesv3.asmx HTTP/1.1",
        "Host: sandbox.purolatorshipping.com",
        "Content-Type: text/xml; charset=utf-8",
        "Content-Length: " . strlen($xml) . "",
        "SOAPAction: http://PurolatorServices.com/GetRates"
    ); 

//SOAP URL
    $url = "http://sandbox.purolatorshipping.com/WebServices/ShippingServicesV3.asmx";

//Initialize cURL and pull together Request and Headers
    $ch = curl_init();

    //pass curl options
        curl_setopt($ch, CURLOPT_URL, $url);
        curl_setopt($ch, CURLOPT_POST, true);
        curl_setopt($ch, CURLOPT_POSTFIELDS, $xml);
        curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
        curl_setopt($ch, CURLOPT_HEADER, false);

    //Execute the cURL
        $response = curl_exec($ch);     
        $header_size = curl_getinfo($ch, CURLINFO_HEADER_SIZE);
        $header = substr($response, 0, $header_size);

        //had to subtract the header, and the soap footers since I couldn't get the soap name spaces working correctly ( FIND A FIX FOR THIS  )
            $body = substr($response, $header_size+18, -47);

//Close cURL connection
    curl_close($ch);

//activity::add("Purolator API Get Rate", "Purolator API Get Rate", "user", "1", "fa-ticket");

//load response into xml and json
    $xml_load =simplexml_load_string($body);
    $array  = json_decode(json_encode($xml_load) , 1);

//Loop through the different services
    foreach ($array['Rates']['RateV3'] as $obj_key =>$row) {

    //Shipment Method
        echo "Ship Method " . $row['ShipMethod'] . "<br>";

    // Delivery Date
        echo "Estimated Delivery Date " . $row['EstimatedDeliveryDate'] . "<br>";

    // Estimated Rate
        echo "Rate " . $row['EstimatedRate'] . "<br>";

    // Accessorials
        echo "Fuel " . $row['RateDetails']['KeyValueDecimal'][4]['Value'] . "<br>";

        echo "<br>";
    }

var_dump($xml_load);

Here is the response I get

<?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><GetRatesResponse xmlns="http://PurolatorServices.com/"><GetRatesResult><Status>0</Status><Packages /><TotalShipping>0</TotalShipping><Rates><RateV3><ShipMethod>Ground</ShipMethod><EstimatedDeliveryDate>2015-07-13T05:00:00+00:00</EstimatedDeliveryDate><EstimatedRate>23.46000</EstimatedRate><IsAvailable>true</IsAvailable><RateDetails><KeyValueDecimal><Key>Total</Key><Value>23.46000</Value></KeyValueDecimal><KeyValueDecimal><Key>Tariff</Key><Value>19.80000</Value></KeyValueDecimal><KeyValueDecimal><Key>Beyond</Key><Value>0</Value></KeyValueDecimal><KeyValueDecimal><Key>Rural</Key><Value>0</Value></KeyValueDecimal><KeyValueDecimal><Key>Fuel</Key><Value>3.66000</Value></KeyValueDecimal><KeyValueDecimal><Key>Surcharges</Key><Value>0</Value></KeyValueDecimal><KeyValueDecimal><Key>Insurance</Key><Value>0</Value></KeyValueDecimal><KeyValueDecimal><Key>Taxes</Key><Value>0</Value></KeyValueDecimal></RateDetails></RateV3><RateV3><ShipMethod>Express</ShipMethod><EstimatedDeliveryDate>2015-07-08T05:00:00+00:00</EstimatedDeliveryDate><EstimatedRate>49.41000</EstimatedRate><IsAvailable>true</IsAvailable><RateDetails><KeyValueDecimal><Key>Total</Key><Value>49.41000</Value></KeyValueDecimal><KeyValueDecimal><Key>Tariff</Key><Value>41.70000</Value></KeyValueDecimal><KeyValueDecimal><Key>Beyond</Key><Value>0</Value></KeyValueDecimal><KeyValueDecimal><Key>Rural</Key><Value>0</Value></KeyValueDecimal><KeyValueDecimal><Key>Fuel</Key><Value>7.71000</Value></KeyValueDecimal><KeyValueDecimal><Key>Surcharges</Key><Value>0</Value></KeyValueDecimal><KeyValueDecimal><Key>Insurance</Key><Value>0</Value></KeyValueDecimal><KeyValueDecimal><Key>Taxes</Key><Value>0</Value></KeyValueDecimal></RateDetails></RateV3></Rates></GetRatesResult></GetRatesResponse></soap:Body></soap:Envelope>

So how do I take that response and turn into JSON?

Thanks for the help, and please go easy on my code :D

Jeff Beagley
  • 945
  • 9
  • 19
  • I feel this is innapropriate but I got it to work taking the cURL response and replacing any instance of soap: with blanks `$test = str_replace("soap:","",$response);` – Jeff Beagley Jul 07 '15 at 21:40
  • Why are you manually building the SOAP envelope and parsing the response instead of using a proper SOAP client? Use a proper SOAP client and this whole question goes away, as you don;t need to do all these XML transformations. – Mike Brant Jul 07 '15 at 21:47
  • I built this from their sample code, I tried to use soap client to get the prefix's to define appropriately but couldn't get that to work. – Jeff Beagley Jul 07 '15 at 21:49
  • Well. My recommendation would be to ditch that crappy sample code and work with an actual SOAP client like PHP's built in SoapClient class. – Mike Brant Jul 07 '15 at 21:53

1 Answers1

0

So how do I take that response and turn into JSON?

The response is with multiple namepspaces. Namespaces is a concept that JSON does not support at all. So turning the response into JSON sounds like a very bad idea, because it's - to a large extend - incompatible.

To just make this clear: Data represented within XML is already w/o namespaces incompatible with JSON. Some forms of JSON serialization with XML exists (JsonDOM, JsonML, Badgerfish, JSONx - all supported for PHP's DOMDocument via Fluent DOM), but it needs to be a decision of yours which tool to use and for which data.

For example with your SOAP response, you're most likely be interested in the response body, not the whole SOAP XML. For that you need an XML parser first:

But the parser alone won't make it. You also need to parse the SOAP result. A reference question for that is listed above already. Perhaps the term namespace or XML namespaces might help you to find more.


And for your SOAP request, I suggest to wrap it. For example, use a pre-made component like SoapClient for it. Especially if there is a WSDL. Not that you re-invent the wheel. And if there's a WSDL, take a look if not an alternative API access is possible, e.g. an XML or JSON based rest API that is aligned with the SOAP API.

Community
  • 1
  • 1
hakre
  • 193,403
  • 52
  • 435
  • 836