使用本机php客户端构建SOAP主体

时间:2016-12-06 09:19:52

标签: php xml soap

我正在使用php创建一个soap客户端,我已经成功添加了标头并调用了该服务。

我的问题是我的api回复了

  

已发生应用程序错误,请检查您的请求并尝试   试。

我用过

htmlentities($client->__getLastRequest())

与传出的XML和预期的xml进行比较,然后我找到了

传出

<SOAP-ENV:Body>
<ns1:ping/>
</SOAP-ENV:Body>

预期

<S:Body>
    <ns3:ping xmlns:ns2="http://www.example.com/example" xmlns:ns3="http://example.core.engine.tflip.uua.com/">
        <arg0>
            <ns2:token>Wed Apr 06 01:19:24 IST 2016</ns2:token>
        </arg0>
    </ns3:ping>
</S:Body>

很明显我发送了一个空体,但我不知道如何创建这些因为我正在使用

$params = array(
          "token" => 'Wed Apr 06 01:19:24 IST 2016'
        );
$result = $client->__soapCall("ping", array($params));

要调用该服务,我需要创建上述结构,并且还必须为这些节点添加这些名称空间。

另外请建议我是否会在定义中导致任何问题而不是

请帮我解决这个问题。

2 个答案:

答案 0 :(得分:2)

PHP SoapClient有时候有点令人困惑。最简单的方法是使用对象。以下示例是untestet。

class Ping {
    protected $arg0;

    public function setArg(SoapVar $oArg0) {
        $this->arg0 = $oArg;
    }

    public function encode() {
        return new SoapVar(
            $this,
            SOAP_ENC_OBJECT,
            null,
            null,
            'ping',
            'http://example.core.engine.tflip.uua.com/'
        }
    }
}

class Arg {
    protected $token;

    public function getToken() {
        return $this->token;
    }

    public function setToken($oToken) {
        if (!($oToken instanceof SoapVar)) {
            $oToken = new SoapVar(
                $oToken,
                XSD_STRING,
                null,
                null,
                'token',
                'http://www.example.com/example'
            );
        }

        $this->token = $oToken;
    }

    public function encode() {
        return new SoapVar(
            $this, 
            SOAP_ENC_OBJECT, 
            null,
            null,
            'arg0'
        );
    }
}

try {
    // init your soap client with wsdl
    $oClient = new SoapClient(...);

    // init your arg object
    $oArg = new Arg();
    $oArg->setToken('Wed Apr 06 01:19:24 IST 2016');
    $oArgEncoded = $oArg->encode();

    // init the ping object
    $oPing = new Ping();
    $oPing->setArg($oArgEncoded);
    $oPingEncoded = $oPing->encode();

    // call the ping method with soap encoded arg object
    $oResult = $oClient->ping($oPingEncoded);
} catch (SoapFault $oSoapFault) {
    echo "<pre>";
    var_dump($oSoapFault);
    echo "</pre>";
}

首先,我们的arg对象包含令牌成员以及getter和setter。 encode函数将arg对象作为完全编码的SoapVar对象。因此,您可以使用soap客户端直接调用websercive的ping方法。

答案 1 :(得分:0)

最后找到了一个对我有用的解决方案 - 至少只需要有需要的人发布。

使用所有安全标头,我创建了soap客户端并包含了接受用户名和密码的类。事实证明,wsdl它自己处理了ping方法的名称空间。

所以我的代码就是这样。

使用wsdl对soap客户端进行了追踪并使其可追踪,以便我可以使用htmlentities($ client-&gt; __ getLastRequest());和htmlentities($ client-&gt; __ getLastResponse());检查我的请求和响应xml。请注意,htmlentities()已用于使其在浏览器中可见。

$client->__setSoapHeaders(Array(new WsseAuthHeader("username", "password")));

还使用类WsseAuthHeader设置soap标头,我在其中启动所有身份验证和服务所需的标头。 WsseAuthHeader类扩展了SoapHeader。

$response = $client->ping(array('arg0'=>array('token'=>'test','timestamp'=>(new DateTime())->format('Y.m.d H:i:s'))));

创建的$ client使用期望值调用服务中的ping方法(操作)。

echo htmlentities($client->__getLastResponse());

最后可以用回声来测试输出

{{1}}

希望这会有所帮助,特别感谢@Marcel的支持。