我在soap调用中使用了以下代码。
如果我添加wsdl并进行客户端调用,我只会得到响应,而不是整个soap包装。
declare(strict_types=1);
namespace Vendor\DocBasics\Controller;
use Psr\Http\Message\ResponseInterface;
use Psr\Http\Message\ServerRequestInterface;
use Psr\Http\Server\MiddlewareInterface;
use Psr\Http\Server\RequestHandlerInterface;
use TYPO3\CMS\Extbase\Object\ObjectManager;
use TYPO3\CMS\Core\Localization\LanguageService;
use TYPO3\CMS\Core\Utility\GeneralUtility;
use Vendor\DocBasics\Domain\Repository\EventsRepository;
use Vendor\CartExtended\Domain\Repository\Order\ItemRepository;
require_once(PATH_site . 'typo3conf/ext/doc_basics/Classes/Libs/nusoap/nusoap.php');
class EventsController
{
protected $action = '';
protected $order;
protected $Vbeln = '';
protected $Zaehl = '';
protected $objectManager;
/**
* @var array
*/
protected $responseArray = [
'hasErrors' => false,
'message' => 'Nothing to declare'
];
/**
* @param ServerRequestInterface $request
* @param ResponseInterface $response
* @return ResponseInterface
*/
public function processRequest(ServerRequestInterface $request, ResponseInterface $response): ResponseInterface
{
$this->initializeData(file_get_contents('php://input')); //xml datas from soap call
switch (isset($request->getQueryParams()['action']) ? (string)$request->getQueryParams()['action'] : '') {
case 'create':
$this->createAction();
break;
case 'update':
$this->updateAction();
break;
default:
$this->updateAction(); //call it as default, so i can call it as endpoint without action parameter
}
$this->prepareResponse($response,$request->getQueryParams()['action']);
return $response;
}
/**
* action create
*
* @return void
*/
public function createAction()
{
$server = new \soap_server();
$server->configureWSDL("updateorderservice", "https://domain.tld/updateorderservice", "https://domain.tld/index.php?eID=update_order");
$server->register(
"update",
array("Vbeln" => 'xsd:string', "Zaehl" => 'xsd:integer'),
array("return" => 'xsd:string'),
"https://domain.tld/updateorderservice",
"update",
"rpc",
"encoded",
"Update a given order"
);
$this->responseArray['message']= $server->service(file_get_contents('php://input'));
}
public function updateAction()
{
$this->objectManager = GeneralUtility::makeInstance(ObjectManager::class);
$this->itemRepository = $this->objectManager->get(ItemRepository::class);
$order=$this->itemRepository->findOrderByOrder($this->Vbeln);
if($order){
$order->setCancelDate($this->Veindat);
$this->itemRepository->update($order);
$this->persistenceManager->persistAll();
$msg= '<MESSAGE><TYPE>S</TYPE><MSGTXT>Auftrag '.$this->Vbeln.' aktualisiert!</MSGTXT></MESSAGE>';
}
else $msg= '<MESSAGE><TYPE>E</TYPE><MSGTXT>Auftrag '.$this->Vbeln.' konnte nicht aktualisiert!</MSGTXT></MESSAGE>';
$this->responseArray['message'] = $msg; //receive the message but don't know how to wrap it
}
/**
* @param ResponseInterface $response
* @param String $action
* @return void
*/
protected function prepareResponse(ResponseInterface &$response, $action)
{
if($action=='create'){
$response = $response->withHeader('Content-Type', 'text/html; charset=utf-8');
$response->getBody()->write($this->responseArray['message']);
}
else{
$response = $response->withHeader('Content-Type', 'text/xml; charset=utf-8');
$response->getBody()->write($this->responseArray['message']);
}
}
/**
* @param $request
* @return void
*/
protected function initializeData($request)
{
$resp= $this->parseResult($request);
if($resp->Vbeln[0]) $this->Vbeln = (string)($resp->Vbeln[0]);
if($resp->Zaehl[0]) $this->Zaehl = intval($resp->Zaehl[0]);
}
public function parseResult($result){
$result = str_ireplace(['soapenv:','soap:','upd:'], '', $result);
$result = simplexml_load_string($result);
$notification = $result->Body->Update;
return $notification;
}
}我的响应只是我编写的返回给updateAction()的一小段xml。我的回答应该放在中间,所以可能是我遗漏了什么,或者我使用eID概念的方式是错误的。
发布于 2020-03-30 05:57:51
你的案例在这里比在facebook上更有意义,但在你未来在stackoverflow上的帖子中,你应该为所有像我一样没有背景信息的其他开发人员写更多的背景信息。
总而言之:你把事情复杂化了。:-)
首先,您在facebook上告诉我,您的soap服务器本身(没有像eID那样的TYPO3集成)可以工作。是这样吗?我从你的代码中看不到这一点:-)你处理一些控制http参数"action“,并且只有当值为" create”时才创建SOAP服务器。但是对于"action“值"update",有没有服务器初始化?这怎么行得通呢?您必须记住,必须在每次请求时初始化SOAP服务器。它不是一个守护进程,它只启动一次并在后台运行。
在输入端绝对不需要这样的"action“控制参数。这就是NuSOAP服务器的"SOAP远程方法“注册的目的-具有可分辨名称的方法,您在客户端显式地调用该方法。
那么你的parseResult和parseResponse方法呢?您是否正在尝试手动处理SOAP协议?NuSOAP应该会为你处理所有这些事情。您只需注册适当的数据类型(ComplexType)。
首先,您需要了解更多关于NuSOAP本身的背景知识。
这是我在一个非常老的项目中使用的一个简单的工作示例。我对它进行了简化,以便向您展示NuSOAP是如何工作的。
服务器定义了一个单独的方法"echoStringArray",该方法将一个数组作为名为"inputStringArray“的属性,并在不做任何修改的情况下回显它。
您可以在不修改的情况下获取并复制粘贴到eID脚本中,因此您将立即获得基本的TYPO3集成。然后一个接一个地添加其他东西,比如数据库层等等。尽量不要先使用类,而是使用与我的示例相同的过程方法。
下面是服务器定义soap-server.php
<?php
// Pull in the NuSOAP code
require_once('./nusoap-0.9.5/lib/nusoap.php');
function logRequest($userAgent, $methodName, $request, $response, $result) {
$fp = fopen("./soap.log","a+");
fputs($fp,"$userAgent\n$methodName\n$request\n$response\n$result\n=======================================\n");
fclose($fp);
}
$log = true;
// Create the server instance
$SOAP_server = new soap_server;
$SOAP_server->configureWSDL(
'Test Service',
'http://my-soap-server.local/xsd'
);
// Set schema target namespace
$SOAP_server->wsdl->schemaTargetNamespace = 'http://my-soap-server/xsd';
// Define SOAP-Types which we will need. In this case a simple array with strings
$SOAP_server->wsdl->addComplexType(
'ArrayOfstring',
'complexType',
'array',
'',
'SOAP-ENC:Array',
array(),
array(array('ref'=>'SOAP-ENC:arrayType','wsdl:arrayType'=>'string[]')),
'xsd:string'
);
// Define SOAP endpoints (remote methods)
$SOAP_server->register(
'echoStringArray', // this is the name of the remote method and the handler identifier below at the same time
array('inputStringArray'=>'tns:ArrayOfstring'),
array('return'=>'tns:ArrayOfstring'),
'http://soapinterop.org/'
);
// Define SOAP method handlers
// This is the handler for the registered echoStringArray SOAP method. It just receives an array with strings and echoes it back unmodified
function echoStringArray($inputStringArray){
$outputData = $inputStringArray;
return $outputData;
}
// Now let the SOAP service work on the request
$SOAP_server->service(file_get_contents("php://input"));
if(isset($log) and $log == true){
logRequest($SOAP_server->headers['User-Agent'],$SOAP_server->methodname,$SOAP_server->request,$SOAP_server->response,$SOAP_server->result);
}下面是适当的客户端soap-client.php
<?php
require_once('./nusoap-0.9.5/lib/nusoap.php');
// This is your Web service server WSDL URL address
$wsdl = "http://my-soap-server.local/soap-server.php?wsdl";
// Create client object
$client = new nusoap_client($wsdl, 'wsdl');
$err = $client->getError();
if ($err) {
// Display the error
echo '<h2>Constructor error</h2>' . $err;
// At this point, you know the call that follows will fail
exit();
}
// Call the hello method
$result1 = $client->call('echoStringArray', ['inputStringArray' => ['Hello', 'World', '!']]);
print_r($result1);正如您所看到的,消息正文、XML、标头等完全没有自定义处理。所有这些都是由NuSOAP自己处理的。
您只需在$client->call()中的键inputStringArray下提供一个数组,并在服务器端获得与方法处理程序echoStringArray.的名为inputStringArray的参数相同的数组
最后但并非最不重要的一点是,你可以尝试比nuSOAP更新的东西,例如zend-soap。它看起来更简单,请查看这个简短的教程https://odan.github.io/2017/11/20/implementing-a-soap-api-with-php-7.html
发布于 2020-03-31 18:59:32
是!现在它起作用了。我们的最后一句话是:"SOAP服务器必须在每个请求上初始化“。尽管此服务器初始化仅用于创建wsdl。我遇到的另一个困难是如何调用我的函数。如果该函数在同一个类中,它将不会被调用(可能是由于某些自动加载问题),我必须使用该函数创建另一个类来使其正常工作。这是我的全部解决方案。在ext_localconf.php中
$GLOBALS['TYPO3_CONF_VARS']['FE']['eID_include']['update_order'] = Vendor\DocBasics\Controller\EventsController::class . '::processRequest';我的类EventsController
<?php
declare(strict_types=1);
namespace Vendor\DocBasics\Controller;
use Psr\Http\Message\ResponseInterface;
use Psr\Http\Message\ServerRequestInterface;
use Psr\Http\Server\MiddlewareInterface;
use Psr\Http\Server\RequestHandlerInterface;
use TYPO3\CMS\Extbase\Object\ObjectManager;
use TYPO3\CMS\Core\Localization\LanguageService;
use TYPO3\CMS\Core\Utility\GeneralUtility;
require_once(PATH_site . 'typo3conf/ext/doc_basics/Classes/Libs/nusoap/nusoap.php');
require_once(PATH_site . 'typo3conf/ext/doc_basics/Classes/Libs/Utility.php');
class EventsController
{
protected $objectManager;
/**
* @var array
*/
protected $responseArray = [
'hasErrors' => false,
'message' => 'Nothing to declare'
];
/**
* @param ServerRequestInterface $request
* @param ResponseInterface $response
* @return ResponseInterface
*/
public function processRequest(ServerRequestInterface $request, ResponseInterface $response): ResponseInterface
{
$server = new \soap_server();
$server->soap_defencoding='utf-8';
$server->configureWSDL("updateorderservice", "https://domain.tld/updateorderservice", "https://domain.tld/index.php?eID=update_order");
$server->register(
"Utility.updateOrder",
array("Vbeln" => 'xsd:string', "Zaehl" => 'xsd:integer'),
array("return" => 'xsd:string'),
"https://domain.tld/updateorderservice",
"update",
"rpc",
"encoded",
"Update a given order"
);
$this->prepareResponse($response);
return $response;
}
/**
* @param ResponseInterface $response
* @param String $action
* @return void
*/
protected function prepareResponse(ResponseInterface &$response)
{
$response = $response->withHeader('Content-Type', 'text/xml; charset=utf-8');
$response->getBody()->write($this->responseArray['message']);
}
}和我的类实用程序
class Utility
{
public function updateOrder($Vbeln,$Zaehl)
{
//do ur stuff
return "Order ".$Vbeln." done";
}
}你可以用https://domain.tld/index.php?eID=update_order&wsdl调用你的wsdl,再次感谢阿图尔帮我解决了这个问题。Dziekuje ;-)
https://stackoverflow.com/questions/60919868
复制相似问题