PHP中的SOAP错误:OperationFormatter遇到无效的消息正文
原始问题: 我正在尝试从SOAP API wsdl链接获取数据。我的代码如下。但我得到了这个错误。有人能帮忙吗 错误消息:OperationFormatter遇到无效的消息正文。 应找到名为“GetLocalRates”的节点类型“Element”,并且 命名空间。找到名为的节点类型“Element” “soapenv:Envelope”和命名空间 编辑2: $client->\u getTypes结果: $client->\u获取函数结果: 修复:在下面使用,而不是XML信封。谢谢你,马塞尔。你是一位伟大的救世主PHP中的SOAP错误:OperationFormatter遇到无效的消息正文,php,soap,wsdl,soapui,soap-client,Php,Soap,Wsdl,Soapui,Soap Client,原始问题: 我正在尝试从SOAP API wsdl链接获取数据。我的代码如下。但我得到了这个错误。有人能帮忙吗 错误消息:OperationFormatter遇到无效的消息正文。 应找到名为“GetLocalRates”的节点类型“Element”,并且 命名空间。找到名为的节点类型“Element” “soapenv:Envelope”和命名空间 编辑2: $client->\u getTypes结果: $client->\u获取函数结果: 修复:在下面使用,而不是XML信封。谢谢你,马塞尔
$requestParams = array( 'credentials' => array('AgentCode' => $acode,
'HashedPassword' => $hpass,
'Username' => $uname),
'payincurcode' => $ccode,
'transferType' => $ttype
);
$response = $client->GetLocalRates( $requestParams );
提前感谢您用丢失的数据更新了您的问题。本例是一个本机php示例,展示了如何以面向对象的方式使用soap函数和类型 一,。类型和类别 正如您在类型数组中看到的,有几种类型声明为struct。如果您愿意这样说,可以将结构称为PHP类。因此,让我们从每个结构中生成一个php类
class EzCredentialStruct
{
public $AgentCode;
public $HashedPassword;
public $Username;
public function getAgentCode() : string
{
return $this->AgentCode;
}
public function setAgentCode(string $AgentCode) : EzCredentialStruct
{
$this->AgentCode = $AgentCode;
return $this;
}
public function getHashedPassword() : string
{
return $this->HashedPassword;
}
public function setHashedPassword(string $HashedPassword) : EzCredentialStruct
{
$this->HashedPassword = $HashedPassword;
return $this;
}
public function getUsername() : string
{
return $this->Username;
}
public function setUsername(string $Username) : EzCredentialStruct
{
$this->Username = $Username;
return $this;
}
}
class GetLocalRatesStruct
{
public $credentials;
public $payincurcode;
public $transferType;
public function getCredentials() : EzCredentialStruct
{
return $this->credentials;
}
public function setCredentials(EzCredentialStruct $credentials) : GetLocalRatesStruct
{
$this->credentials = $credentials;
return $this;
}
public function getPayincurcode() : string
{
return $this->payincurcode;
}
public function setPayincurcode(string $payincurcode) : GetLocalRatesStruct
{
$this->payincurcode = $payincurcode;
return $this;
}
public function getTransferType() : string
{
return $this->transferType;
}
public function setTransferType(string $transferType) : GetLocalRatesStruct
{
$this->transferType = $transferType;
return $this;
}
}
这两个类是类型数组中所有结构的示例。所以把你所有的结构写下来作为类。您稍后会注意到好处
二,。Soap客户端和类映射选项
现在,当我们将所使用的Web服务类型声明为类时,我们可以启动soap客户端。使用正确的选项启动soap客户机非常重要。始终将客户端包装在try/catch块中
try {
$options = [
'cache_wsdl' => WSDL_CACHE_NONE,
'soap_version' => SOAP_1_2,
'trace' => true,
'classmap' => [
'EzCredential' => 'EzCredentialStruct',
'GetLocalRates' => 'GetLocalRatesStruct',
],
];
$wsdl = 'path/to/the/webservice/endpoint?wsdl';
$client = new \SoapClient(
$wsdl,
$options,
);
} catch (\SoapFault $e) {
// error handling
}
如您所见,选项数组中有一个类映射键。类映射将类型路由到特定的php类。在本例中,我们只使用前面定义的两个示例类型类。soap客户端现在可以自动创建Web服务所需的xml字符串
三,。把它们放在一起
现在,由于我们已经具备了正确的soap请求所需的一切,我们的代码应该如下所示
$credentials = (new EzCredentialStruct())
->setAgentCode($agentCode)
->setHashedPassword($hashedPassword)
->setUsername($username);
$request = (new GetLocalRatesStruct())
->setCredentials($credentials)
->setPayincurcode($code)
->setTransferType($transferType);
$result = $client->GetLocalRates($request);
结论
乍一看,这种方法可能需要更多的工作。但是对于webservice声明的每个结构,将类型与函数和编程类分开是有意义的。webservice函数的调用将更容易,因为我们只将对象作为参数传递。不再有奇怪的数组构造。一切都在它的位置,可以重复使用
PS:此代码未经测试。不建议在生产中使用它。本代码仅作为示例。它可能包含错误。首先,reliable和useWSA对于soap客户端类来说是无效的选项。您可以删除它们。此外,请添加选项“trace”=>true。这允许跟踪最后一个请求和响应。在catch块中添加echo$client->\uu getLastResponse;告诉我们,Web服务作为响应返回的确切内容。嗨@Marcel,我已经在我的答案中添加了结果。请看一看。非常感谢您的帮助。回复中明确指出,您的请求正文无效。这一行:$client->getlocalratesnewsoapvar$request,XSD_ANYXML;我想这是错的。GetLocalRates函数可以采用哪种类型作为参数?您可以通过查看$client->\uuuuGetTypes和$client->\uuuGetFunctions找到答案。这些类型声明了您可以通过webservice发送和获取的类型。函数显示函数名,您可以通过webservice使用。每个函数都有参数。这些参数是在类型数组中声明的。@Marcel,非常抱歉。我认为问题在我的XML信封中。但我想不出如何解决这个问题。这是我第一次处理SOAP调用。你能给我一个提示吗。我在我的问题中添加了上述结果。不,问题不是信封节点。这是请求本身。我给你举个例子,你如何解决这个问题。感谢您提供的类型和功能。那真的很有用。
$requestParams = array( 'credentials' => array('AgentCode' => $acode,
'HashedPassword' => $hpass,
'Username' => $uname),
'payincurcode' => $ccode,
'transferType' => $ttype
);
$response = $client->GetLocalRates( $requestParams );
class EzCredentialStruct
{
public $AgentCode;
public $HashedPassword;
public $Username;
public function getAgentCode() : string
{
return $this->AgentCode;
}
public function setAgentCode(string $AgentCode) : EzCredentialStruct
{
$this->AgentCode = $AgentCode;
return $this;
}
public function getHashedPassword() : string
{
return $this->HashedPassword;
}
public function setHashedPassword(string $HashedPassword) : EzCredentialStruct
{
$this->HashedPassword = $HashedPassword;
return $this;
}
public function getUsername() : string
{
return $this->Username;
}
public function setUsername(string $Username) : EzCredentialStruct
{
$this->Username = $Username;
return $this;
}
}
class GetLocalRatesStruct
{
public $credentials;
public $payincurcode;
public $transferType;
public function getCredentials() : EzCredentialStruct
{
return $this->credentials;
}
public function setCredentials(EzCredentialStruct $credentials) : GetLocalRatesStruct
{
$this->credentials = $credentials;
return $this;
}
public function getPayincurcode() : string
{
return $this->payincurcode;
}
public function setPayincurcode(string $payincurcode) : GetLocalRatesStruct
{
$this->payincurcode = $payincurcode;
return $this;
}
public function getTransferType() : string
{
return $this->transferType;
}
public function setTransferType(string $transferType) : GetLocalRatesStruct
{
$this->transferType = $transferType;
return $this;
}
}
try {
$options = [
'cache_wsdl' => WSDL_CACHE_NONE,
'soap_version' => SOAP_1_2,
'trace' => true,
'classmap' => [
'EzCredential' => 'EzCredentialStruct',
'GetLocalRates' => 'GetLocalRatesStruct',
],
];
$wsdl = 'path/to/the/webservice/endpoint?wsdl';
$client = new \SoapClient(
$wsdl,
$options,
);
} catch (\SoapFault $e) {
// error handling
}
$credentials = (new EzCredentialStruct())
->setAgentCode($agentCode)
->setHashedPassword($hashedPassword)
->setUsername($username);
$request = (new GetLocalRatesStruct())
->setCredentials($credentials)
->setPayincurcode($code)
->setTransferType($transferType);
$result = $client->GetLocalRates($request);