如何在PHP中发送带有身份验证标头的SOAP请求

问题描述 投票:0回答:1

我已经使用SoapClient向wsdl创建了一个请求。我已经设法使用__getFunctions()来获取功能列表,因此可以确认我的URL正常工作。

问题出在调用函数时,我收到Could not connect to host错误消息。我还应该提到我使用Laravel,并且错误消息没有给我任何更多信息。

我个人认为这是一个基于身份验证的问题,因为我需要通过标题解析用户名和密码,而且我可能语法错误。

我的PHP函数:

try {
            $wsdlUrl = 'https://myurl.com/Service.svc?wsdl';
            $context = [
                'verify_peer' => false,
                'verify_peer_name' => false,
                'allow_self_signed' => true,
                'cache_wsdl' => WSDL_CACHE_NONE,
            ];
            $client = new SoapClient($wsdlUrl, array('stream_context' => $context));

            $authentication = array(
                'Username' => env('USERNAME'),
                'Password' => env('PASSWORD')
            );

            //Soap Header
            $header = new SoapHeader(
                'https://myurl.com/',
                'Credentials',
                $authentication,
                false
            );
            $client->__setSoapHeaders($header);


            return $client->GetElement(['ID' => '462493']);


        } catch (\Exception $e) {
            \Log::error($e->getMessage());
    }

和我要匹配的xml:

  <soapenv:Header>
    <Credentials>
      <Password>Password</Password>
      <Username>Brugernavn</Username>
    </Credentials>
  </soapenv:Header>
  <soapenv:Body>
    <GetElementRequestType>
      <ID>4624393</ID>
    </GetElementRequestType>
  </soapenv:Body>
php laravel soap
1个回答
0
投票

您的代码中存在一些基本问题。让我们审视使用PHP处理肥皂请求和响应时,您必须做的不同事情。

尝试/用肥皂抓块

[使用肥皂处理时,总会抛出SoapFaultSoapFault类直接继承自Exception。考虑到这一点,您必须捕获一个SoapFault而不是一个ErrorException

try {
    // doing some soap stuff here
} catch (SoapFault $fault) {
    Log::error($fault->getMessage());
}

可选地,如果您正在等待其他可抛出的东西,则可以使用不同的catch块来捕获不同的异常。

try {

} catch (SoapFault $fault) {
    // catches soap faults
} catch (ErrorException $e) {
    // catches error exceptions
} finally {
    // final catch of everything else
}

finally语句将始终执行,无论之前抛出过哪种可抛出对象。

客户端选项

只要您不处理任何证书,就不必创建上下文。您可以,但是没有这种情况也可以。在您的情况下,由于您只是在处理用户名和密码凭据,因此上下文只是另一个可能的错误来源。为了开发,SoapClient类的选项应如下所示。

try {
    $wsdl = 'https://www.domain.tld/service?wsdl';
    $options = [
        'cache_wsdl' => WSDL_CACHE_NONE,
        'exceptions' => true,
        'trace' => true,
    ];

    $client = new SoapClient($wsdl, $options);
} catch (SoapFault $fault) {
    if ($client) {
        // get the last sent request
        var_dump($client->__getLastRequest());

        // get the last response
        var_dump($client->__getLastResponse());
    }

    var_dump($fault);
}

使用trace选项,您可以启用获取上一个请求和响应的功能。这在开发过程中可能会很有帮助。在任何情况下,exception选项都会强制客户端抛出异常。如果未设置此选项,则客户端可能会在出现错误情况时保持冷静。

带有肥皂的数据模型

仅假定PHP Soap扩展严格是面向对象的。因此,您必须处理直接在wsdl文件中描述的值对象和元素。您可以通过直接在broser中调用wsdl url来查看定义。此处描述了所有复杂和简单的类型和函数调用。

因此,当我们查看您的soap标头时,会看到带有属性用户名和密码的凭据对象(复杂类型)。我们可以直接在php中将其用作类。

class Credentials
{
    protected string $Password;
    protected string $Username;

    public function getPassword(): string
    {
        return $this->Password;
    }

    public function setPassword(string $password): self
    {
        $this->Password = $password;
        return $this;
    }

    public function getUsername(): string
    {
        return $this->Username;
    }

    public function setUsername(string $username): self
    {
        $this->Username = $username;
        return $this;
    }
}

您可以看到,这是凭据的简单数据模型。现在,您必须对其进行初始化,并将其强制为soap header。

$credentials = (new Credentials())
    ->setPassword('bla')
    ->setUsername('blubb');

$header = new SoapHeader(
    'http://www.domain.tld/namespace',
    'Credentials',
    new SoapVar($credentials, SOAP_ENC_OBJECT, '', '', 'Credentials', '')
);

$client->__setSoapHeaders($header);
$response = $client->GetElement([ 'ID' => 1234 ]);

如果这不起作用,请记住跟踪功能。如果出现肥皂故障,请尝试查看最后发送的请求。在大多数情况下,您可以看到,请求xml结构出了点问题。

© www.soinside.com 2019 - 2024. All rights reserved.