我尝试使用WSDL使用两个 SOAP端点。我已经能够成功实现第一个,但是由于XML请求主体格式的方式,第二个我现在遇到了问题-它在一个具有相同名称的节点下包含多个元素。我正在使用PHP数组/嵌套数组来构造有效负载。第一次运行良好,因为不存在父元素包含多个同名子元素的情况。
这是我的第二个XML请求的正文:
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:ext="http://xxx.xxx.xxx.xxx.com/">
<soapenv:Header/>
<soapenv:Body>
<ext:requestPurchase>
<context>
<channel>xxx</channel>
<prepareOnly>xxxx</prepareOnly>
<clientReference>12q31a1a456677881</clientReference>
<clientRequestTimeout>500</clientRequestTimeout>
<initiatorPrincipalId>
<id>xxxx</id>
<type>xxxx</type>
<userId>xxxx</userId>
</initiatorPrincipalId>
<password>xxxxx</password>
<transactionProperties>
<entry>
<key>preferredLanguage</key>
<value>en</value>
</entry>
<entry>
<key>productSKU</key>
<value>xxx</value>
</entry>
<entry>
<key>currency</key>
<value>NGN</value>
</entry>
<entry>
<key>purchaseAmount</key>
<value>3</value>
</entry>
</transactionProperties>
</context>
<!--- other elements --->
</ext:requestPurchase>
</soapenv:Body>
</soapenv:Envelope>
我在entry
下有transactionProperties
次出现了 4次。我第一次使用的方法不适用于second request
,因为PHP使用唯一的数组键(或者有一种绕过该键的方法)。我也尝试使用原始XML,但仍无法正常工作。我很高兴获得解决方案。谢谢!
这是我的代码的样子(使用Laravel / PHP框架):
<?php
namespace App\Engine;
use Illuminate\Http\Request;
use SoapClient;
use SoapVar;
use Log;
use Exception;
class Transaction
{
public function handle($data)
{
// Setup Host,WSDL location, Soap Client options
$uri = "http://xxxx.xxxx.xx.xxx.com/";
$wsdl = "http://host IP/xxxx/service?wsdl";
$soapclientOptions = array();
$soapclientOptions['trace'] = TRUE;
$soapclientOptions['exceptions'] = 1;
$soapclientOptions['use'] = 'SOAP_LITERAL';
$soapclientOptions['uri'] = $uri;
// $soapclientOptions['connection_timeout'] = 15;
// $soapclient_options['location'] = $host;
$soapclientOptions['cache_wsdl'] = WSDL_CACHE_NONE;
$e = '';
try
{
$client = new SoapClient($wsdl, $soapclientOptions);
}
catch(Exception $e)
{
Log::error("Error occurred on attempt to open Soap Connection. Error details: ".json_encode($e));
return response()->failure(null, 'Error occurred on attempt to open Soap Connection. Check log for error details', 400);
}
try
{
$handleRequest = $this->formPayloadAndProcessRequest($client, $data);
if(!$payload[0]) return response()->failure(null, $payload[1], 400);
dd($handleRequest);
}
catch (Exception $e)
{
Log::error("Error occurred on attempt to process Soap Method. Error details: ".json_encode($e));
return response()->failure(null, 'Error occurred on attempt to process Soap Connection. Check log for error details', 400);
}
}
private function formPayloadAndProcessRequest($client,$data)
{
switch($data->product_type)
{
case('product1'): // this is for my first request
$payload = array("key1" => array("keyA"=>"value","keyB"=>$data->amount),
"key2" => array("keyX"=>$data->msisdn,"keyY"=>"xxxx","keyZ"=>"xxxx"),
'key3' => "xxxxx"
);
$result = $client->functionName1($payload); // call function 1
return [true, $result];
break;
case('product2'): // my second request
$payload = $this->getVodRawXml($data->request_id,'xxx',$data->product_count);
//$xmlVar = new SoapVar($payload,XSD_ANYXML);
//dd($xmlVar);
try
{
$result = $client->requestPurchase($payload); // call function 2
dd($result);
}
catch(Exception $e)
{
dd($e);
}
break;
// other product cases
default:
return [false, "Invalid product or service type supplied"];
break;
}
}
private function getVodRawXml($requestId,$productId,$productCount)
{
$rawXml = '<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:ext="http://xxx.xxx.xxx.xxx.com/">
<soapenv:Header/>
<soapenv:Body>
<ext:requestPurchase>
<context>
<channel>xxx</channel>
<prepareOnly>xxxx</prepareOnly>
<clientReference>12q31a1a456677881</clientReference>
<clientRequestTimeout>500</clientRequestTimeout>
<initiatorPrincipalId>
<id>xxxx</id>
<type>xxxx</type>
<userId>xxxx</userId>
</initiatorPrincipalId>
<password>xxxxx</password>
<transactionProperties>
<entry>
<key>preferredLanguage</key>
<value>en</value>
</entry>
<entry>
<key>productSKU</key>
<value>xxx</value>
</entry>
<entry>
<key>currency</key>
<value>NGN</value>
</entry>
<entry>
<key>purchaseAmount</key>
<value>3</value>
</entry>
</transactionProperties>
</context>
// other elements
</ext:requestPurchase>
</soapenv:Body>
</soapenv:Envelope>';
return $rawXml;
}
}
答案 0 :(得分:2)
SoapClient和WSDL背后的思想是不处理原始XML。代替使用关联数组,而使用对象(类)。
class requestPurchase
{
public context;
}
class entry
{
public key;
public value;
}
class context
{
public channel;
public prepareOnly;
public clientReference;
public transactionProperties = array();
}
$entry1 = new entry;
$entry2 = new entry;
$entry3 = new entry;
$context = new context;
$context->transactionProperties[] = $entry1;
$context->transactionProperties[] = $entry2;
$context->transactionProperties[] = $entry3;
$requestPurchase = new requestPurchase;
$requestPurchase->context = $context;
$client = new SoapClient($wsdl, array('classmap' =>
array('requestPurchase' => requestPurchase::class)));
$response = $client->requestPurchase($requestPurchase);