构建正确的SOAP请求标头(PHP)

时间:2018-09-07 10:10:15

标签: php authentication soap

我必须使用PHP对SOAP API进行记录,并且需要以下SOAP-Header结构:

File f = ... // file to read

try (BufferedReader reader = new BufferedReader(new InputStreamReader(new FileInputStream(f), StandardCharsets.UTF_8))) {

    // regular expression checking the format of each line
    Pattern linePattern = Pattern.compile("(\\d+)(?:\\s+(\\d+):(\\d+))*");
    // regular expression to find the index (first number) in a line
    Pattern indexPattern = Pattern.compile("(\\d+)");
    // regular expression to find the vertices (a:b) in a line
    Pattern relationPattern = Pattern.compile("(\\d+):(\\d+)");

    String line;
    while ((line = reader.readLine()) != null) {

        if (linePattern.matcher(line).matches()) {

            Matcher indexMatcher = indexPattern.matcher(line);
            if (indexMatcher.find()) {
                int sourceVertex = Integer.parseInt(indexMatcher.group(1));
                // do something with the sourceVertex 

                Matcher relationMatcher = relationPattern.matcher(line);
                while (relationMatcher.find()) {
                    int destinationVertex = Integer.parseInt(relationMatcher.group(1));
                    int weight = Integer.parseInt(relationMatcher.group(2));
                    // do something with destinationVertex and weight
                }
            }
        }
    }
}

如何构建此标头?

我尝试过

<soapenv:Header>
    <ver:authentication>
        <pw>xxx</pw>
        <user>xxx</user>
    </ver:authentication>
</soapenv:Header>

但不起作用。当报头结构不正确时,响应就是“失败”。

请帮助

2 个答案:

答案 0 :(得分:0)

解决方案可以是对象驱动的。在下面的代码中给出了一个示例。请记住,以下代码不是testet。

class Authentication 
{
    protected $user;

    protected $pw;

    public function getUser() : ?string
    {
        return $this->user;
    }

    public function setUser(string $user) : Authentication
    {
        $this->user = $user;
        return $this;
    }

    public function getPw() : string
    {
        return $this->pw;
    }

    public function setPw(string $pw) : Authentication
    {
        $this->pw = $pw;
        return $this;
    }
}

上面显示的类是一个简单的实体,其中包含两个属性$user(用于用户名)和$pw(用于密码)。此外,它包含用于获取或设置这两个属性的值的getter和setter函数。

下一步,只需在类中填充数据并将其存储在SoapVar对象中即可。

$authentication = (new Authentication())
    ->setUser('Username')
    ->setPw('YourEncodedPassword');

$soapEncodedObject = new \SoapVar(
    $authentication, 
    SOAP_ENC_OBJECT, 
    null, 
    null, 
    'authentication', 
    'http://www.example.com/namespace'
);

正如您在上面看到的,您的身份验证类将存储为soap var对象。它被编码为肥皂对象。您唯一要做的就是为此对象设置名称空间。在您给出的示例中,它是ver:。在wsdl文件中某处使用此名称空间前缀,会记录一个名称空间。您必须找出该名称空间url,然后将示例url http://www.example.com/namespace替换为wsdl中注明的正确url。

下一步是将其设置为soap header。那很简单。

try {
    $client = new SoapClient('http://www.example.com/?wsdl', [
        'trace' => true,
        'exception' => true,
        'cache_wsdl' => WSDL_CACHE_NONE,
        'compression' => SOAP_COMPRESSION_ACCEPT | SOAP_COMPRESSION_GZIP,
    ]);

    // set the soap header
    $header = new SoapHeader('http://www.example.com/namespace', 'authentication', $authentication, false);
    $client->setSoapHeaders($header);

    // send the request
    $result = $client->someWsdlFunction($params);
} catch (SoapFault $e) {
    echo "<pre>";
    var_dump($e);
    echo "</pre>";

    if ($client) {
        echo "<pre>";
        var_dump($client->__getLastRequest());
        echo "</pre>";

        echo "<pre>";
        var_dump($client->__getLastResponse());
        echo "</pre>";
    }
}

如您所见,它与您给出的示例有些不同。代替数组的是肥皂编码的身份验证对象,该对象被提供给肥皂头类。出于故障目的,您的soap客户端周围有一个try / catch块。在这种情况下,您可以确定错误,并且如果客户端正确启动,则还可以在xml中查看最后的请求和最后的响应。

我希望我能对您有所帮助。 ;)

答案 1 :(得分:0)

我强烈建议您两件事:

  • 使用WSDL to PHP生成器以正确构造您的请求。另外,它将简化您的响应处理。一切都在使用更好的OOP。看一下PackageGenerator项目。
  • 使用WsSecurity项目来轻松添加专用的SoapHeader,而又不知道如何构造它们。