Laravel SOAP Server提示Procedure not present,含services参数的xmlns无法工作
解决Laravel中viewflex/zoap处理带查询参数的SOAP命名空间问题
问题场景
使用viewflex/zoap搭建SOAP服务器时,当请求的xmlns包含?services=customerCustomerRepositoryV1查询参数,会返回Procedure not present错误;去掉该参数后,请求可正常调用customerCustomerRepositoryV1SaveRequest方法,但业务需求要求保留xmlns中的查询参数部分。
解决方案
方案1:修改请求内容,剥离命名空间中的查询参数
创建自定义Zoap控制器,继承原控制器并在处理请求前替换xmlns内容:
<?php namespace App\Http\Controllers; use Viewflex\Zoap\ZoapController as BaseZoapController; use Illuminate\Http\Request; class CustomZoapController extends BaseZoapController { public function server(Request $request, $key) { // 获取原始SOAP请求内容 $content = $request->getContent(); // 正则替换,剥离xmlns中的?services=xxx查询参数 $content = preg_replace( '/xmlns:ns1=\'https:\/\/ecommerce\.app\/api\/soap\/web\/all\?services=[^\']+\'/', 'xmlns:ns1=\'https://ecommerce.app/api/soap/web/all\'', $content ); // 更新请求内容 $request->setContent($content); // 调用父类逻辑处理请求 return parent::server($request, $key); } }
修改api.php路由,使用自定义控制器:
Route::group(['prefix' => 'soap'], function() { Route::get('{key}/all', [\App\Http\Controllers\CustomZoapController::class, 'server']); Route::post('{key}/all', [\App\Http\Controllers\CustomZoapController::class, 'server']); });
方案2:扩展ZOAP的命名空间映射逻辑
如果需要更灵活的命名空间处理,可以扩展ZOAP的Server类,添加命名空间别名映射:
- 配置命名空间别名
在config/zoap.php中添加别名映射:
'namespace_aliases' => [ 'https://ecommerce.app/api/soap/web/all?services=customerCustomerRepositoryV1' => 'https://ecommerce.app/api/soap/web/all', ],
- 创建自定义Server类
<?php namespace App\Services; use Viewflex\Zoap\Server as BaseServer; class CustomZoapServer extends BaseServer { protected function getNamespace($request) { $namespace = parent::getNamespace($request); // 匹配别名映射,替换命名空间 $aliases = config('zoap.namespace_aliases', []); return $aliases[$namespace] ?? $namespace; } }
- 修改自定义控制器使用新Server
<?php namespace App\Http\Controllers; use Illuminate\Http\Request; use App\Services\CustomZoapServer; class CustomZoapController { public function server(Request $request, $key) { $server = new CustomZoapServer($key); return $server->handle($request); } }
最后更新路由使用该控制器即可。
内容的提问来源于stack exchange,提问作者Raphael
相关产品推荐
相关产品推荐

