2015-04-17 26 views
13

Recentemente ho riscontrato un problema in cui le chiamate SOAP al servizio ID3Global/Address hanno improvvisamente smesso di funzionare (in precedenza funzionavano correttamente). Credo che abbia qualcosa a che fare con il provider di hosting che spegne il allow_url_fopen sul nostro server, il che significa che il servizio non funziona.Come scambiare le chiamate SOAP con cURL, per funzionare all'interno della limitazione allow_url_fopen?

Mi è stato detto che avrò bisogno di passare a usare cURL per prendere i file (WSDL) come file_get_contents richiede 'allow_url_fopen' da impostare nel file php.ini perché funzioni. Tuttavia non sembra che stia usando file_get_contents nel mio file per ottenere il file WSDL.

Come passare all'utilizzo di cURL?

Ecco il mio file PHP che effettua la chiamata indirizzo SOAP:

<?php 
ini_set("soap.wsdl_cache_enabled", "0"); 

$username = '[email protected]'; 
$password = 'xxxxxxx'; 

$profile_id = 'xxxxxx-xxxx-xxxx-xxxx-xxxxxxxx'; 

// Live WSDL 
$wsdl = 'https://id3global.com/ID3gWS/ID3global.svc?wsdl'; 

$postcode = $_POST['ZipPostcode']; 

/** 
* Method to arrange the address into a sane 
* order for displaying back to the user 
* 
* @param $item 
* @param $key 
* @internal param $address 
*/ 
function sortAddress(&$item, $key) 
{ 
    // Convert the object to an array 
    $address = (array) $item; 

    // Reorder the address lines 
    $addressLines = array(
     'Company' => $address['Company'], 
     'Building' => $address['Building'], 
     'SubBuilding' => $address['SubBuilding'], 
     'Premise' => $address['Premise'], 
     'SubStreet' => $address['SubStreet'], 
     'Street' => $address['Street'], 
     'City' => $address['City'], 
     'StateDistrict' => $address['StateDistrict'], 
     'ZipPostcode' => $address['ZipPostcode'], 
     'Country' => $address['Country'], 
    ); 

    // Remove blank address lines 
    // $item = array_filter($addressLines); 
    $item = $addressLines; 

} 

class clsWSSEAuth { 
    private $Username; 
    private $Password; 
    function __construct($username, $password) { 
     $this->Username=$username; 
     $this->Password=$password; 
    } 
} 

class clsWSSEToken { 
    private $UsernameToken; 
    function __construct ($UsernameToken){ 
     $this->UsernameToken = $UsernameToken; 
    } 
} 

$strWSSENS = "http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd"; 

//Auth 
$objSoapVarUser = new SoapVar($username, XSD_STRING, NULL, $strWSSENS, NULL, $strWSSENS); 
$objSoapVarPass = new SoapVar($password, XSD_STRING, NULL, $strWSSENS, NULL, $strWSSENS); 
$objWSSEAuth = new clsWSSEAuth($objSoapVarUser, $objSoapVarPass); 

//Token 
$objSoapVarWSSEToken = new SoapVar($objWSSEAuth, SOAP_ENC_OBJECT, NULL, $strWSSENS, 'UsernameToken', $strWSSENS); 
$objWSSEToken = new clsWSSEToken($objSoapVarWSSEToken); 

//Header 
$objSoapVarWSSEAuth = new SoapVar($objWSSEToken, SOAP_ENC_OBJECT, NULL, $strWSSENS, 'UsernameToken', $strWSSENS); 
$objSoapVarHeaderVal = new SoapVar($objSoapVarWSSEAuth, SOAP_ENC_OBJECT, NULL, $strWSSENS, 'Security', $strWSSENS); 
$objSoapVarWSSEHeader = new SoapHeader($strWSSENS, 'Security', $objSoapVarHeaderVal, true); 

//Client 
$client = new SoapClient($wsdl, array(
    'soap_version' => SOAP_1_1, 
    'trace' => 1, 
    'exception' => true, 
)); 

$client->__setSoapHeaders($objSoapVarWSSEHeader); 

$results = $client->AddressLookup(array(
    'InputData' => array('ZipPostcode' => strtoupper($postcode)), 
)); 

$addresses = $results->AddressLookupResult->GlobalAddress; 


array_walk($addresses, 'sortAddress'); 
//var_dump($addresses); 

echo json_encode($addresses); 

Questo viene attivato utilizzando AJAX e qui c'è il file JavaScript/jQuery:

jQuery(document).ready(function($) { 

    var addresses = []; 

    $("body").on('click', '.find-address', function(e){ 
     e.preventDefault(); 
     url = '/wp-content/themes/Cornhill/gbgroup-address-lookup_2.php'; 
     postode_id = $(this).data('postcode'); 
     address_id = $(this).data('address'); 
     postcode = $('#'+postode_id).val(); 
     console.log('Stage 1'); 

     if (postcode != '') 
     { 
      var addressList = $('#'+address_id); 
      addressList.find('option').remove(); 
      opt = $('<option>').html('Loading...'); 
      opt.val(''); 
      addressList.append(opt); 
      console.log('stage 2'); 

      $.ajax({ 
       url: url, 
       dataType: 'json', 
       type: 'post', 
       data: { 
        'ZipPostcode': postcode 
       }, 
       success: function(response){ 
        addressList.find('option').remove(); 
        addresses[address_id] = response; 

        opt = $('<option>').html('Please select'); 
        opt.val(''); 
        addressList.append(opt); 

        for(x=0; x<addresses[address_id].length; x++){ 

         addressArray = new Array(); 
         addressArray.push(addresses[address_id][x].Building); 
         addressArray.push(addresses[address_id][x].Street); 
         addressArray.push(addresses[address_id][x].City); 
         addressArray.push(addresses[address_id][x].ZipPostcode); 

         addressString = addressArray.join(', '); 

         opt = $('<option>').attr('value', x); 
         opt.html(addressString); 

         addressList.append(opt); 
        } 
       } 
      }); 
     } 
     else 
     { 
      return; 
     } 
    }); 

    $("body").on('change', '.select-address', function(){ 
     address_id = $(this).attr('id'); 
     street_id = $(this).data('street'); 
     town_id = $(this).data('town'); 
     postcode_id = $(this).data('postcode'); 

     value = $(this).val(); 
     if(value != ''){ 
      address = addresses[address_id][value]; 

      if (address.Building != '') 
      { 
       $('#'+street_id).val(address.Building+' '+address.Street); 
      } 
      else 
      { 
       $('#'+street_id).val(address.Street); 
      } 
      $('#'+town_id).val(address.City); 
      $('#'+postcode_id).val(address.ZipPostcode); 
     } 

    }); 

}); 

Ho già provato il passaggio utilizzando il seguente codice per afferrare il file WSDL ma non sono proprio sicuro di cos'altro dovrei fare con esso:

$ch = curl_init('https://id3global.com/ID3gWS/ID3global.svc?wsdl'); 
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); 
$resultSuper = curl_exec($ch); 
+0

Se il tuo host apporta modifiche così drastiche senza preavviso e ti permette di testare nuovi server, prenderei in considerazione la possibilità di cambiare host come priorità significativa. – halfer

+0

Grazie, stiamo cercando di cambiare molto presto ma nel frattempo abbiamo bisogno di far funzionare nuovamente questo servizio.Hai qualche suggerimento su come usare cURL in quel file gbgroup-address-lookup_2.php? –

+0

(Ho spostato il tuo codice nella tua domanda - tendiamo a scoraggiare i pasteboard esterni qui, dato che i link a volte si rompono e ci piacciono le domande per durare). – halfer

risposta

3

Il parametro allow_url_fopen non ha alcun effetto sul modo in cui SOAP funziona. Si può facilmente verificare questo con il seguente script:

<?php 

echo "allow_url_fopen status is: " . ini_get('allow_url_fopen') . "\n"; 

$wsdl = 'https://id3global.com/ID3gWS/ID3global.svc?wsdl'; 

file_get_contents($wsdl); 

$client = new SoapClient($wsdl, array(
    'soap_version' => SOAP_1_1, 
    'trace' => 1, 
    'cache_wsdl' => WSDL_CACHE_NONE, // this is important for the purpose of the test 
    'exception' => true, 
)); 

print_r($client); 

?> 

Quando allow_url_fopen è abilitato, si vedrà il seguente output:

allow_url_fopen status is: 1 SoapClient Object ([trace] => 1 [_soap_version] => 1 [sdl] => Resource id #11) 

Quando allow_url_fopen è disabilitata, verrà visualizzato il seguente output:

allow_url_fopen status is: 0 
Warning: file_get_contents(): https:// wrapper is disabled in the server configuration by allow_url_fopen=0 in /var/www/test.php on line 9 

Warning: file_get_contents(https://id3global.com/ID3gWS/ID3global.svc?wsdl): failed to open stream: no suitable wrapper could be found in /var/www/test.php on line 9 
SoapClient Object ([trace] => 1 [_soap_version] => 1 [sdl] => Resource id #10) 

Si noti che non viene segnalato alcun errore SOAP.

La ragione di questo comportamento è il seguente codice nel file di ext/soap/php_xml.c in fonte di PHP:

old_allow_url_fopen = PG(allow_url_fopen); 
PG(allow_url_fopen) = 1; 
ctxt = xmlCreateFileParserCtxt(filename); 
PG(allow_url_fopen) = old_allow_url_fopen; 

Quindi, allow_url_fopen è abilitato per il WSDL download. Se si commento le righe come segue:

/* old_allow_url_fopen = PG(allow_url_fopen); 
PG(allow_url_fopen) = 1; */ 
ctxt = xmlCreateFileParserCtxt(filename); 
/* PG(allow_url_fopen) = old_allow_url_fopen; */ 

e compilare il PHP con la fonte cambiato, vedrete i seguenti risultati:

allow_url_fopen Abilitato:

allow_url_fopen status is: 1 SoapClient Object ([trace] => 1 [_soap_version] => 1 [sdl] => Resource id #11) 

disabili allow_url_fopen:

allow_url_fopen status is: 0 
Warning: file_get_contents(): https:// wrapper is disabled in the server configuration by allow_url_fopen=0 in /var/www/test.php on line 9 

Warning: file_get_contents(https://id3global.com/ID3gWS/ID3global.svc?wsdl): failed to open stream: no suitable wrapper could be found in /var/www/test.php on line 9 

Fatal error: Uncaught SoapFault exception: [WSDL] SOAP-ERROR: Parsing WSDL: Couldn't load from 'https://id3global.com/ID3gWS/ID3global.svc?wsdl' : failed to load external entity "https://id3global.com/ID3gWS/ID3global.svc?wsdl" in /var/www/test.php:16 Stack trace: #0 /var/www/test.php(16): SoapClient->SoapClient('https://id3glob...', Array) #1 {main} thrown in /var/www/test.php on line 16 

Si può vedere che questa volta abbiamo un errore SOAP fatale e che il cannone WSDL essere caricato. Ho osservato questo comportamento con PHP 5.4.40 e PHP 5.6.8.