PHP SOAP - 无法连接到主机错误消息(皇家邮件运输API集成)

时间:2015-09-15 09:47:11

标签: php soap

我正在设置最初的Royal Mail Shipping API集成并拥有以下PHP代码(ps我还在等待皇家邮政的某些凭据,但此代码应该至少仍然连接&给我一些形式的身份验证错误。

我已在本地运行PHPINFO()并且可以确认CURL& OpenSSL已启用。不太确定还有什么可能导致这个...任何想法?

我已关闭Windows防火墙并拥有网址http://localhost/royalmail/index.php

当我在浏览器中运行它时,我得到错误 - 这发生在代码块中大约一半的try块内。

Could not connect to host

我的代码

<?php
//phpinfo();    
// AWAITING FROM ROYAL MAIL..
$api_password = "xxxx";
$api_username = "dispatch@company.com";
$api_application_id = "xxxxxx";
$api_service_type = "D";
$api_service_code = "SD1";
$api_service_format = "";
$api_certificate_passphrase = 'xxxxxxxxxxxx';
$api_service_enhancements = "";

// setting up the $data object
$data = new ArrayObject();
$data->order_tracking_id = "";
$data->shipping_name = "John";
$data->shipping_company = "AA";
$data->shipping_address1 = "23, Hurst Avenue"; 
$data->shipping_address2 = "";
$data->shipping_town = "London";
$data->shipping_postcode = "E1";
$data->order_tracking_boxes = "0";
$data->order_tracking_weight = "1500";    

$time = gmdate('Y-m-d\TH:i:s');
$created = gmdate('Y-m-d\TH:i:s\Z');
$nonce = mt_rand();
$nonce_date_pwd = pack("A*",$nonce) . pack("A*",$created) . pack("H*", sha1($api_password));
$passwordDigest = base64_encode(pack('H*',sha1($nonce_date_pwd)));
$ENCODEDNONCE = base64_encode($nonce);


$soapclient_options = array(); 
$soapclient_options['cache_wsdl'] = 'WSDL_CACHE_NONE'; 
$soapclient_options['local_cert'] = 'certs/CA2+Company+John-Bloggs+RM10001790+usr.p12';
$soapclient_options['passphrase'] = $api_certificate_passphrase;
$soapclient_options['trace'] = true;
$soapclient_options['ssl_method'] = 'SOAP_SSL_METHOD_SSLv3';
$soapclient_options['location'] = 'https://api.royalmail.com/shipping/onboarding';

//launch soap client
$client = new SoapClient('SAPI/ShippingAPI_V2_0_8.wsdl', $soapclient_options);
$client->__setLocation($soapclient_options['location']);

//headers needed for royal mail
$HeaderObjectXML  = '<wsse:Security xmlns:wsse="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd"
                      xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd">
           <wsse:UsernameToken wsu:Id="UsernameToken-000">
              <wsse:Username>'.$api_username.'</wsse:Username>
              <wsse:Password Type="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-username-token-profile-1.0#PasswordDigest">'.$passwordDigest.'</wsse:Password>
              <wsse:Nonce EncodingType="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-soap-message-security-1.0#Base64Binary">'.$ENCODEDNONCE.'</wsse:Nonce>
              <wsu:Created>'.$created.'</wsu:Created>
           </wsse:UsernameToken>
       </wsse:Security>';

//push the header into soap
$HeaderObject = new SoapVar( $HeaderObjectXML, XSD_ANYXML );

//push soap header
$header = new SoapHeader( 'http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd', 'Security', $HeaderObject );
//$header = new SoapHeader( 'SAPI/oasis-200401-wss-wssecurity-utility-1.0.xsd', 'Security', $HeaderObject );
$client->__setSoapHeaders($header);

//build the request
$request = array(
    'integrationHeader' => array(
        'dateTime' => $time,
        'version' => '1.0',
        'identification' => array(
            'applicationId' => $api_application_id,
            'transactionId' => $data->order_tracking_id
        )
    ),
    'requestedShipment' => array(
                                'shipmentType' => array('code' => 'Delivery'),
                                'serviceOccurence' => '1',
                                'serviceType' => array('code' => $api_service_type),
                                'serviceOffering' => array('serviceOfferingCode' => array('code' => $api_service_code)),
                                'serviceFormat' => array('serviceFormatCode' => array('code' => $api_service_format)),
                                'shippingDate' => date('Y-m-d'),
                                'recipientContact' => array('name' => $data->shipping_name, 'complementaryName' => $data->shipping_company),
                                'recipientAddress' => array('addressLine1' => $data->shipping_address1,  'addressLine2' => $data->shipping_address2, 'postTown' => $data->shipping_town, 'postcode' => $data->shipping_postcode),
                                'items' => array('item' => array(
                                            'numberOfItems' => $data->order_tracking_boxes,
                                            'weight' => array( 'unitOfMeasure' => array('unitOfMeasureCode' => array('code' => 'g')), 'value' => ($data->order_tracking_weight*1000) //weight of each individual item
                                                             )
                                                                )
                                                )
                                )               
);


//if any enhancements, add it into the array
if($api_service_enhancements != "") {
    $request['requestedShipment']['serviceEnhancements'] = array('enhancementType' => array('serviceEnhancementCode' => array('code' => $api_service_enhancements)));
}

//try make the call
try { 
    $response = $client->__soapCall( 'createShipment', array($request), array('soapaction' => 'https://api.royalmail.com/shipping/onboarding') );
} catch (Exception $e) {
    //catch the error message and echo the last request for debug
    echo $e->getMessage(); 
    echo "REQUEST:\n" . $client->__getLastRequest() . "\n";
    die;
}

//check for any errors
if(isset($response->integrationFooter->errors)) { 
    $build = "";

    //check it wasn't a single error message
    if(isset($response->integrationFooter->errors->error->errorCode)) { 
        $build .= $output_error->errorCode.": ".$output_error->errorDescription."<br/>"; 
    } else {
        //loop out each error message, throw exception will be added ehre
        foreach($response->integrationFooter->errors->error as $output_error) { 
            $build .= $output_error->errorCode.": ".$output_error->errorDescription."<br/>";
        }
    }

    echo $build; die;

}

print_r($response);

echo "REQUEST:\n" . $client->__getLastRequest() . "\n";
die;

?>

发生错误的地方..

try { 
    $response = $client->__soapCall( 'createShipment', array($request), array('soapaction' => 'https://api.royalmail.com/shipping/onboarding') );
} catch (Exception $e) {
    //catch the error message and echo the last request for debug
    echo $e->getMessage(); 
    echo "REQUEST:\n" . $client->__getLastRequest() . "\n";
    die;
}

更新

我还没有为此创建* .pem文件 - 我在指南中读到了这个。我创建了三个* .pem文件(cacert.pem,mycert.pem&amp; mykey.pem),但我现在不确定如何处理它们?

PKCS#12 [http://en.wikipedia.org/wiki/PKCS_12]是1996年的原始行业标准,用于证书和私钥的安全传输(类似于加密的zip存档),并且由各种应用程序和操作系统直接支持。这提供了标准化的单个文件&#39;安全传递证书,其私钥和CA公共签名证书副本的方法。

Linux和BSD上的标准Web服务器是Apache,它希望所有证书和密钥都是CER / DER x509v3二进制证书格式和RSA / DSA密钥的Base64编码版本。

使用以下OpenSSL工具集命令在Linux上轻松从PKCS#12文件(mycert.p12)中提取组成部分。

%openssl pkcs12 -in mycert.p12 -cacerts -nokeys -out cacert.pem

%openssl pkcs12 -in mycert.p12 -clcerts -nokeys -out mycert.pem

%openssl pkcs12 -in mycert.p12 -nocerts -nodes -out mykey.pem

&#34; cacert.pem&#34;文件包含CA的公共签名。通常,它被添加到系统范围内,可信任的CA&#34;文件(例如/etc/ssl/certs/ca-certificates.crt等)或者可以使用文件本身由应用程序直接引用。需要此证书才能正式验证由同一CA颁发的任何证书。

通常&#34; mycert.pem&#34;文件包含PEM编码的x509v3格式&#34;客户端SSL&#34;证书。这用于在建立SSL / TLS连接时向服务器验证客户端。

&#34; mykey.pem&#34; file包含链接到客户端证书的(现在)未加密的PEM编码的RSA 2048位私钥。

在建立SSL网络连接时应用程序如何通过已发布的客户端SSL证书依赖于应用程序和环境,但它基本上需要同时访问&#34; mycert.pem&#34;和&#34; mykey.pem&#34;文件,或在某些情况下,包含证书和密钥的单个组合文件。

1 个答案:

答案 0 :(得分:1)

SOAP connection with Royal Mail, Could not connect to host 我在我的回答中使用了代码并且它有效,如果你继续遇到代码调用皇家邮件的问题,并要求在实时服务器上测试,那么他们在启动时遇到问题。