gpt4 book ai didi

带有 WCF BadContextToken 的 PHP Soap 客户端

转载 作者:行者123 更新时间:2023-12-03 15:47:02 32 4
gpt4 key购买 nike

经过几天的谷歌搜索/尝试/脱发,我仍然找不到解决方案,所以请帮忙:)

简短信息:
我需要使用 PHP(SOAP 客户端)的 WCF 服务。它使用 wsHttpBinding (ws-security) 并且无法设置 basicHttpBinding。一切都在 VPN 之后,所以我无法为您提供网络服务的链接。数据也被认为是 secret (来自客户的请求),所以我不能给你完整的信息,只有一些“常见”的东西。这是WS配置:

<configuration>
<system.serviceModel>
<bindings>
<wsHttpBinding>
<binding name="WSHttpBinding_IServices" closeTimeout="00:01:00"
openTimeout="00:01:00" receiveTimeout="00:10:00" sendTimeout="00:01:00"
bypassProxyOnLocal="false" transactionFlow="false" hostNameComparisonMode="StrongWildcard"
maxBufferPoolSize="524288" maxReceivedMessageSize="65536"
messageEncoding="Text" textEncoding="utf-8" useDefaultWebProxy="true" allowCookies="false">
<readerQuotas maxDepth="32" maxStringContentLength="8192" maxArrayLength="16384" maxBytesPerRead="4096" maxNameTableCharCount="16384" />
<reliableSession ordered="true" inactivityTimeout="00:10:00" enabled="false" />
<security mode="TransportWithMessageCredential">
<transport clientCredentialType="None" proxyCredentialType="None" realm="" />
<message clientCredentialType="UserName" negotiateServiceCredential="true" algorithmSuite="Default" />
</security>
</binding>
</wsHttpBinding>
</bindings>
<client>
<endpoint address="https://topSecert.url/Service.svc"
binding="wsHttpBinding" bindingConfiguration="WSHttpBinding_IServices"
contract="IServices" name="WSHttpBinding_IServices" />
</client>
</system.serviceModel>

我的尝试:
1) 基本 PHP Soap 客户端不工作。它总是挂起,直到达到最大执行时间(不产生错误)。后来发现PHP Soap客户端不支持wsHttpBinding(想哭)
2) 一些SoapClient 扩展 classes但没有成功,请求仍然挂起。
3) 尝试使用 SOAPAction header “自行生成”的 CURL 请求。最后我在那里遇到了一些错误(我用 wse 类生成了请求):
<s:Envelope xmlns:s="http://www.w3.org/2003/05/soap-envelope"
xmlns:a="http://www.w3.org/2005/08/addressing">
<s:Header>
<a:Action s:mustUnderstand="1">http://www.w3.org/2005/08/addressing/soap/fault</a:Action>
</s:Header>
<s:Body>
<s:Fault>
<s:Code>
<s:Value>s:Sender</s:Value>
<s:Subcode>
<s:Value xmlns:a="http://schemas.xmlsoap.org/ws/2005/02/sc">a:BadContextToken</s:Value>
</s:Subcode>
</s:Code>
<s:Reason>
<s:Text xml:lang="en-US">The security context token is expired or is
not valid. The message was not processed.</s:Text>
</s:Reason>
</s:Fault>
</s:Body>

我将服务器时间更改为有效区域(与 WCF 相同),尝试使用随机数、散列密码、纯密码和其他一些我现在不记得的东西。
我也尝试编译 wso2/wsf但是无法在 PHP 5.4 上编译它(我试图应用提供的 FIX,但它导致了同样的错误)。

测试 XML 示例:
<env:Envelope xmlns:env="http://www.w3.org/2003/05/soap-envelope"
xmlns:ns1="https://topSercret.url/Test">
<env:Header>
<wsse:Security
xmlns:wsse="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd"
env:mustUnderstand="1">
<wsse:UsernameToken>
<wsse:Username><!-- Removed --></wsse:Username>
<wsse:Password
Type="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-username-token-profile-1.0#PasswordDigest"><!-- Removed --></wsse:Password>
<wsse:Nonce><!-- Removed --></wsse:Nonce>
<wsu:Created
xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd">2014-01-19T15:20:31Z</wsu:Created>
</wsse:UsernameToken>
<wsu:Timestamp
xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd">
<wsu:Created>2014-01-19T15:20:31Z</wsu:Created>
<wsu:Expires>2014-01-19T16:20:31Z</wsu:Expires>
</wsu:Timestamp>
</wsse:Security>
</env:Header>
<env:Body>
<ns1:SomeAction />
</env:Body>

这是测试脚本的代码(可能有错误,我为此帖子删除了大部分内容):
<?php

date_default_timezone_set( 'UTC' );

include 'WSSESoap.php';

class TestSoap extends SoapClient {

private $_username;
private $_password;
private $_digest;

// test vars
public $r_request;
public $r_location;
public $r_action;

function addUserToken($username, $password, $digest = false) {
$this->_username = $username;
$this->_password = $password;
$this->_digest = $digest;
}

function __doRequest($request, $location, $saction, $version, $one_way = 0) {
$doc = new DOMDocument('1.0');
$doc->loadXML($request);

$objWSSE = new WSSESoap($doc);
$objWSSE->signAllHeaders = TRUE;

$objWSSE->addTimestamp();
$objWSSE->addUserToken($this->_username, $this->_password, $this->_digest);

// take data for "my" usage
$this->r_request = $objWSSE->saveXML();
$this->r_location = $location;
$this->r_action = $saction;
return '';
}
}

function test()
{
$soapUrl = "https://topSecret.url/Services.svc";

$context = stream_context_create(array(
'ssl' => array(
'verify_peer' => false,
'allow_self_signed' => true
)
));

$client = new TestSoap('/mypath/wsdl.xml', array(
'stream_context' => $context,
'soap_version' => SOAP_1_2,
'trace' => 1,
'connection_timeout' => 10
));
$client->addUserToken('User', 'Password', TRUE );

$requestParams = array(
'data1' => '1',
'data2' => '2',
);

// call to generate request string
$client->myAction($requestParams);
$xml_post_string = $client->r_request;

$headers = array(
"Content-type: application/soap+xml; charset=\"utf-8\"",
"Accept: text/xml,application/soap+xml",
"Cache-Control: no-cache",
"Pragma: no-cache",
"SOAPAction: " . $client->r_action,
"Content-length: " . strlen($xml_post_string)
);

// generate && run cURL request
$ch = curl_init();
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, 0);
curl_setopt($ch, CURLOPT_URL, $soapUrl);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_HTTPAUTH, CURLAUTH_ANY);
curl_setopt($ch, CURLOPT_TIMEOUT, 10);
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_POSTFIELDS, $xml_post_string); // the SOAP request
curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
curl_setopt($ch, CURLOPT_HEADER, true);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);

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

echo $response;
}

test();

所以最后的问题。这种服务可以与 PHP 一起使用吗(如果可以帮助理解如何)?

最佳答案

我前段时间解决了这个问题,但从来没有时间让它更“好”。所以一般问题是 wsHttpBinding 消息安全的工作方式以及如何在 PHP 上实现它。我使用了 https://github.com/enginaygen/kps-soap-client/blob/master/KPSSoapClient.php 的概念,还添加了 Implementation of P_SHA1 algorithm in PHP 的 psha1 。

所以它需要工作的方式是这样的:

  • 来自 WSS 的安全 token 的 PHP 请求及其请求 secret
  • WS 生成安全 token 并返回给 PHP
  • PHP 使用请求的安全 token 生成 SOAP C14N 签名消息

  • 这是实现( 注意:由于 WSDL 导入问题,我没有通过扩展 PHP soap 客户端来实现它。另外,正如我所说,我使用了其他人的概念并且从未清理代码 - 尤其是 XML 生成 )。
    // TODO implement this by extending SoapClient class
    // currently not implemented in it because request params are not generated correctly

    /**
    * Client implementing SOAP wsHttpBinding with message security. <br>
    * NOTE: this is adapted to work for special needs of our client. It can be modified and there is a lot of work that jet needs to be done (nicer code, options and optimization).
    */

    class WSSoap
    {
    /**
    * Securit token request template
    */
    const STS_TEMPLATE = <<<X
    <s:Envelope xmlns:s="http://www.w3.org/2003/05/soap-envelope" xmlns:a="http://www.w3.org/2005/08/addressing"xmlns:u="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd"><s:Header><a:Action s:mustUnderstand="1">http://schemas.xmlsoap.org/ws/2005/02/trust/RST/SCT</a:Action><a:MessageID></a:MessageID><a:ReplyTo><a:Address>http://www.w3.org/2005/08/addressing/anonymous</a:Address></a:ReplyTo><a:To s:mustUnderstand="1"></a:To><o:Security s:mustUnderstand="1" xmlns:o="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd"><u:Timestamp u:Id="_0"><u:Created></u:Created><u:Expires></u:Expires></u:Timestamp><o:UsernameToken u:Id="_1"><o:Username></o:Username><o:Password Type="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-username-token-profile-1.0#PasswordText"></o:Password></o:UsernameToken></o:Security></s:Header><s:Body><t:RequestSecurityToken xmlns:t="http://schemas.xmlsoap.org/ws/2005/02/trust"><t:TokenType>http://schemas.xmlsoap.org/ws/2005/02/sc/sct</t:TokenType><t:RequestType>http://schemas.xmlsoap.org/ws/2005/02/trust/Issue</t:RequestType><t:Entropy><t:BinarySecret Type="http://schemas.xmlsoap.org/ws/2005/02/trust/Nonce"></t:BinarySecret></t:Entropy><t:KeySize>256</t:KeySize></t:RequestSecurityToken></s:Body></s:Envelope>
    X;

    /**
    * Any action request template (mainly for headers)
    */
    const KPS_TEMPLATE = <<<X
    <s:Envelope xmlns:s="http://www.w3.org/2003/05/soap-envelope" xmlns:a="http://www.w3.org/2005/08/addressing" xmlns:u="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd"><s:Header><a:Action s:mustUnderstand="1">n</a:Action><a:MessageID></a:MessageID><a:ReplyTo><a:Address>http://www.w3.org/2005/08/addressing/anonymous</a:Address></a:ReplyTo><a:To s:mustUnderstand="1"></a:To><o:Security s:mustUnderstand="1" xmlns:o="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd"><u:Timestamp u:Id="_0"><u:Created></u:Created><u:Expires></u:Expires></u:Timestamp><c:SecurityContextToken xmlns:c="http://schemas.xmlsoap.org/ws/2005/02/sc"><c:Identifier></c:Identifier></c:SecurityContextToken><Signature xmlns="http://www.w3.org/2000/09/xmldsig#"><SignedInfo><CanonicalizationMethod Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#"></CanonicalizationMethod><SignatureMethod Algorithm="http://www.w3.org/2000/09/xmldsig#hmac-sha1"></SignatureMethod><Reference URI="#_0"> <Transforms><Transform Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#"></Transform></Transforms><DigestMethod Algorithm="http://www.w3.org/2000/09/xmldsig#sha1"></DigestMethod><DigestValue></DigestValue></Reference></SignedInfo><SignatureValue></SignatureValue><KeyInfo><o:SecurityTokenReference><o:Reference ValueType="http://schemas.xmlsoap.org/ws/2005/02/sc/sct"></o:Reference></o:SecurityTokenReference></KeyInfo></Signature></o:Security></s:Header><s:Body></s:Body></s:Envelope>
    X;

    /**
    * Namespaces
    */
    const S11 = "http://schemas.xmlsoap.org/soap/envelope/";
    const S12 = "http://www.w3.org/2003/05/soap-envelope";
    const WSU = "http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd";
    const WSSE = "http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd";
    const WSSE11 = "http://docs.oasis-open.org/wss/oasis-wss-wsecurity-secext-1.1.xsd";
    const WST = "http://schemas.xmlsoap.org/ws/2005/02/trust";
    const DS = "http://www.w3.org/2000/09/xmldsig#";
    const XENC = "http://www.w3.org/2001/04/xmlenc#";
    const WSP = "http://schemas.xmlsoap.org/ws/2004/09/policy";
    const WSA = "http://www.w3.org/2005/08/addressing";
    const XS = "http://www.w3.org/2001/XMLSchema";
    const WSDL = "http://schemas.xmlsoap.org/wsdl/";
    const SP = "http://docs.oasis-open.org/ws-sx/ws-securitypolicy/200702";
    const SC = "http://schemas.xmlsoap.org/ws/2005/02/sc";

    /**
    * STS Properties
    */
    protected $stsHostName;
    protected $stsEndpoint;
    protected $stsUsername;
    protected $stsPassword;
    protected $stsNamespace;

    /**
    * Binary secret used for generating request
    */
    protected $requestSecret;
    protected $rstrBinarySecret;
    protected $rstrKeyIdentifier;

    protected $token;
    protected $tokenReference;

    function __construct( $username, $password, $endpointURL, $namespace )
    {
    $this->stsUsername = $username;
    $this->stsPassword = $password;
    $this->stsHostName = parse_url( $endpointURL, PHP_URL_HOST);
    $this->stsEndpoint = $endpointURL;
    $this->stsNamespace = $namespace;
    }



    function request( $action, $fullActionName, $params )
    {
    $this->stsRequest();

    $kpsDom = new \DOMDocument("1.0", "utf-8");
    $kpsDom->preserveWhiteSpace = false;
    $kpsDom->loadXML(static::KPS_TEMPLATE);

    $kpsXpath = new \DOMXPath($kpsDom);
    $kpsXpath->registerNamespace('S12', static::S12);
    $kpsXpath->registerNamespace('WSA', static::WSA);
    $kpsXpath->registerNamespace('WSU', static::WSU);
    $kpsXpath->registerNamespace('WSSE', static::WSSE);
    $kpsXpath->registerNamespace('XENC', static::XENC);
    $kpsXpath->registerNamespace('DS', static::DS);
    $kpsXpath->registerNamespace('SC', static::SC);

    // Addressing

    $uuid = $this->uuid();

    $actionPath = $kpsXpath->query("//S12:Envelope/S12:Header/WSA:Action");
    $messageIDPath = $kpsXpath->query("//S12:Envelope/S12:Header/WSA:MessageID");
    $toPath = $kpsXpath->query("//S12:Envelope/S12:Header/WSA:To");

    $actionPath->item(0)->nodeValue = $fullActionName;
    $messageIDPath->item(0)->nodeValue = sprintf("urn:uuid:%s", $uuid);
    $toPath->item(0)->nodeValue = $this->stsEndpoint;

    // Timestamp

    $time = time();

    $dateCreated = gmdate('Y-m-d\TH:i:s\Z', $time);
    $dateExpires = gmdate('Y-m-d\TH:i:s\Z', $time + (5 * 60));

    $timestampPath = $kpsXpath->query("//S12:Envelope/S12:Header/WSSE:Security/WSU:Timestamp");
    $timestampDateCreatedPath = $kpsXpath->query("//S12:Envelope/S12:Header/WSSE:Security/WSU:Timestamp/WSU:Created");
    $timestampDateExpiresPath = $kpsXpath->query("//S12:Envelope/S12:Header/WSSE:Security/WSU:Timestamp/WSU:Expires");
    $timestampDateCreatedPath->item(0)->nodeValue = $dateCreated;
    $timestampDateExpiresPath->item(0)->nodeValue = $dateExpires;
    $timestampC14N = $timestampPath->item(0)->C14N(true, false);

    // DigestValue
    $digestValue = base64_encode(hash('sha1', $timestampC14N, true));
    $digestValuePath = $kpsXpath->query("//S12:Envelope/S12:Header/WSSE:Security/DS:Signature/DS:SignedInfo/DS:Reference/DS:DigestValue");
    $digestValuePath->item(0)->nodeValue = $digestValue;

    // Signature
    $signaturePath = $kpsXpath->query("//S12:Envelope/S12:Header/WSSE:Security/DS:Signature/DS:SignedInfo");
    $signatureValuePath = $kpsXpath->query("//S12:Envelope/S12:Header/WSSE:Security/DS:Signature/DS:SignatureValue");
    $signatureC14N = $signaturePath->item(0)->C14N(true, false);

    $psBinary = $this->psha1( $this->requestSecret, $this->rstrBinarySecret );
    $signatureValue = base64_encode(hash_hmac("sha1", $signatureC14N, $psBinary, true));
    $signatureValuePath->item(0)->nodeValue = $signatureValue;

    // token reference
    $securityContextTokenReference = $kpsXpath->query("//S12:Envelope/S12:Header/WSSE:Security/DS:Signature/DS:KeyInfo/WSSE:SecurityTokenReference/WSSE:Reference");
    $securityContextTokenReference->item(0)->setAttribute('URI', "#$this->tokenReference");
    // token ID
    $tokenPath = $kpsXpath->query("//S12:Envelope/S12:Header/WSSE:Security/SC:SecurityContextToken");
    $tokenPath->item(0)->setAttribute('u:Id', $this->tokenReference);
    // token
    $tokenPath = $kpsXpath->query("//S12:Envelope/S12:Header/WSSE:Security/SC:SecurityContextToken/SC:Identifier");
    $tokenPath->item(0)->nodeValue = $this->token;

    // Message
    $bodyElemet = $kpsXpath->query("//S12:Envelope/S12:Body")->item(0);
    $root = $kpsDom->createElementNS( $this->stsNamespace, $action );

    foreach( $params as $name => $value ) {
    $root->appendChild( $kpsDom->createElement( $name, $value ) );
    }

    $bodyElemet->appendChild( $root );
    $kpsRequest = $kpsDom->saveXML();

    // Request
    try {
    $stsResponse = $this->execCurl( $kpsRequest );
    } catch ( \Exception $e ) {
    throw $e;
    }

    return $stsResponse;
    }


    /**
    * Performs a STS request
    *
    * @param string $location Request location
    */
    protected function stsRequest()
    {
    $rstXml = static::STS_TEMPLATE;

    $rstDom = new \DOMDocument("1.0", "utf-8");
    $rstDom->preserveWhiteSpace = false;
    $rstDom->loadXML($rstXml);

    $rstXpath = new \DOMXPath($rstDom);
    $rstXpath->registerNamespace('S12', static::S12);
    $rstXpath->registerNamespace('WSA', static::WSA);
    $rstXpath->registerNamespace('WSU', static::WSU);
    $rstXpath->registerNamespace('WSSE', static::WSSE);
    $rstXpath->registerNamespace('XENC', static::XENC);
    $rstXpath->registerNamespace('DS', static::DS);
    $rstXpath->registerNamespace('WST', static::WST);
    $rstXpath->registerNamespace('WSP', static::WSP);

    // Addressing

    $uuid = $this->uuid();

    $messageIDPath = $rstXpath->query("//S12:Envelope/S12:Header/WSA:MessageID");
    $toPath = $rstXpath->query("//S12:Envelope/S12:Header/WSA:To");

    $messageIDPath->item(0)->nodeValue = sprintf("urn:uuid:%s", $uuid);
    $toPath->item(0)->nodeValue = $this->stsEndpoint;

    // Timestamp

    $time = time();

    $dateCreated = gmdate('Y-m-d\TH:i:s\Z', $time);
    $dateExpires = gmdate('Y-m-d\TH:i:s\Z', $time + (5 * 60));

    $timestampDateCreatedPath = $rstXpath->query("//S12:Envelope/S12:Header/WSSE:Security/WSU:Timestamp/WSU:Created");
    $timestampDateExpiresPath = $rstXpath->query("//S12:Envelope/S12:Header/WSSE:Security/WSU:Timestamp/WSU:Expires");
    $timestampDateCreatedPath->item(0)->nodeValue = $dateCreated;
    $timestampDateExpiresPath->item(0)->nodeValue = $dateExpires;

    // Credentials

    $usernamePath = $rstXpath->query("//S12:Envelope/S12:Header/WSSE:Security/WSSE:UsernameToken/WSSE:Username");
    $passwordPath = $rstXpath->query("//S12:Envelope/S12:Header/WSSE:Security/WSSE:UsernameToken/WSSE:Password");

    $usernamePath->item(0)->nodeValue = $this->stsUsername;
    $passwordPath->item(0)->nodeValue = $this->stsPassword;

    // Set binary key
    $this->requestSecret = uniqid();
    $binaryKeyPath = $rstXpath->query("//S12:Envelope/S12:Body/WST:RequestSecurityToken/WST:Entropy/WST:BinarySecret");
    $binaryKeyPath->item(0)->nodeValue = base64_encode( $this->requestSecret );

    // Endpoint
    $stsRequest = $rstDom->saveXML();

    // Request
    try {
    $stsResponse = $this->execCurl( $stsRequest );
    } catch ( \Exception $e ) {
    throw $e;
    }

    $rstrDom = new \DOMDocument("1.0", "utf-8");
    $rstrDom->preserveWhiteSpace = false;
    $rstrDom->loadXML($stsResponse);

    $rstrXpath = new \DOMXPath($rstrDom);

    $rstrXpath->registerNamespace('S12', static::S12);
    $rstrXpath->registerNamespace('WSA', static::WSA);
    $rstrXpath->registerNamespace('WSU', static::WSU);
    $rstrXpath->registerNamespace('WSSE', static::WSSE);
    $rstrXpath->registerNamespace('XENC', static::XENC);
    $rstrXpath->registerNamespace('DS', static::DS);
    $rstrXpath->registerNamespace('WST', static::WST);
    $rstrXpath->registerNamespace('WSP', static::WSP);
    $rstrXpath->registerNamespace('SC', static::SC);

    // parse security context token
    $securityContextTokenReference = $rstrXpath->query("//S12:Envelope/S12:Body/WST:RequestSecurityTokenResponse/WST:RequestedSecurityToken/SC:SecurityContextToken");
    $this->tokenReference = $securityContextTokenReference->item(0)->getAttribute('u:Id');

    $securityContextToken = $rstrXpath->query("//S12:Envelope/S12:Body/WST:RequestSecurityTokenResponse/WST:RequestedSecurityToken/SC:SecurityContextToken/SC:Identifier");
    $this->token = $securityContextToken->item(0)->nodeValue;

    $securityContextToken = $rstrXpath->query("//S12:Envelope/S12:Body/WST:RequestSecurityTokenResponse/WST:Entropy/WST:BinarySecret");

    $this->rstrBinarySecret = base64_decode( $securityContextToken->item(0)->nodeValue );
    }

    protected function execCurl( $request )
    {
    // Request
    $ch = curl_init();

    curl_setopt($ch, CURLOPT_URL, $this->stsEndpoint);
    curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, 0); // disable SSL verification - re-enable if needed
    curl_setopt($ch, CURLOPT_HTTPHEADER, array(
    "Host: " . $this->stsHostName,
    "Content-Type: application/soap+xml; charset=utf-8",
    "Content-Length: " . strlen( $request ),
    ));
    curl_setopt($ch, CURLOPT_POST, true);
    curl_setopt($ch, CURLOPT_POSTFIELDS, $request );
    curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);

    $response = curl_exec($ch);

    if ( $response === false ) {
    throw new \Exception(curl_error($ch));
    }

    curl_close($ch);

    return $response;
    }

    /**
    * Generates UUID
    *
    * @return string UUID
    */
    protected function uuid()
    {
    return sprintf('%04x%04x-%04x-%04x-%04x-%04x%04x%04x', //
    mt_rand(0, 0xffff), //
    mt_rand(0, 0xffff), //
    mt_rand(0, 0xffff), //
    mt_rand(0, 0x0fff) | 0x4000, //
    mt_rand(0, 0x3fff) | 0x8000, //
    mt_rand(0, 0xffff), //
    mt_rand(0, 0xffff), //
    mt_rand(0, 0xffff) //
    );
    }


    /**
    * Calculate psha1 hash used for signature generation
    * @param unknown $clientSecret
    * @param unknown $serverSecret
    * @param number $sizeBits
    * @return string
    */
    protected function psha1($clientSecret, $serverSecret, $sizeBits = 256)
    {
    $sizeBytes = $sizeBits / 8;

    $hmacKey = $clientSecret;
    $hashSize = 160; // HMAC_SHA1 length is always 160
    $bufferSize = $hashSize / 8 + strlen($serverSecret);
    $i = 0;

    $b1 = $serverSecret;
    $b2 = "";
    $temp = null;
    $psha = array();

    while ($i < $sizeBytes) {
    $b1 = hash_hmac('SHA1', $b1, $hmacKey, true);
    $b2 = $b1 . $serverSecret;
    $temp = hash_hmac('SHA1', $b2, $hmacKey, true);

    for ($j = 0; $j < strlen($temp); $j++) {
    if ($i < $sizeBytes) {
    $psha[$i] = $temp[$j];
    $i++;
    } else {
    break;
    }
    }
    }

    return implode("", $psha);
    }
    }

    所以要在请求中得到这样的东西:
    <s:Header>
    <a:Action s:mustUnderstand="1">https://some.url/NamespaceName/IServices/CheckTransaction</a:Action>
    ...
    </s:Header>
    <s:Body>
    <CheckTransaction xmlns="https://sime.url/ActionToDo">
    <TransactionID>1234567</TransactionID>
    </CheckTransaction>
    </s:Body>

    代码将是:
    $url = 'https://some.url/Services.svc';
    $namespace = 'https://some.url/NamespaceName'; // this is action namespace you need, since there is no WSDL parsing you need to set it by yourself

    try {
    $c = new WSSoap( $username, $password, $url, $namespace );
    $params = array(
    'TransactionID' => '1234567'
    );
    $r = $c->request( 'CheckTransaction', 'https://some.url/NamespaceName/IServices/CheckTransaction', $params ); // also applies - no WSDL parsing so we need to set params
    } catch (Exception $e) {
    throw $e;
    }

    关于带有 WCF BadContextToken 的 PHP Soap 客户端,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/21218908/

    32 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com