一个提供处理请求和响应的干净接口的SOAP客户端。

v2 2023-05-25 14:03 UTC

README

Tests

一个Laravel SOAP客户端,提供处理请求和响应的干净接口。

文档

需求

  • PHP 7.4或更高版本
  • Laravel 8.16或更高版本

安装

您可以通过composer安装此包

composer require ricorocks-digital-agency/soap

注意:从v1.5.0版本开始,Soap需要PHP ^7.4

使用Soap

可以通过提供的Facade访问Soap

use RicorocksDigitalAgency\Soap\Facades\Soap

Soap::to()

特性/API

头部

您可以使用withHeaders方法为每个将要传递给Soap客户端的SOAP请求设置头部。

Soap::to('...')->withHeaders(...$headers)->call('...');

每个头部都应该是一个Header实例,它提供了一个流畅的接口来构建一个新的PHP Soap Header,可以按如下方式组合:

$header = Soap::header()
            ->name('Authentication')
            ->namespace('test.com')
            ->data([
                'user' => '...',
                'password' => '...'
            ])
            ->mustUnderstand()
            ->actor('foo.co.uk')

这也可以表示为:

$header = Soap::header('Authentication', 'test.com', [
                'user' => '...',
                'password' => '...'
            ])
            ->mustUnderstand()
            ->actor('foo.co.uk')

此外,还可以使用soap_header辅助方法。

$header = soap_header('Authentication', 'test.com')
            ->data([
                'user' => '...',
                'password' => '...'
            ])

头部的data可以是一个数组或一个SoapVar,如SoapHeader构造函数所示。

全局头部

Soap允许您设置应该包含在每个请求中的头部。

Soap::headers(...$headers)

同样,每个头部应该是一个Header实例。

您可能还想在每次请求中都包含头部,但仅针对某些端点或操作。

// Only requests to this endpoint will include these headers
Soap::headers(soap_header('Auth', 'test.com'))->for('https://api.example.com');

// Only requests to this endpoint and the method Customers will include these headers
Soap::headers(soap_header('Brand', 'test.com'))->for('https://api.example.com', 'Customers');

这些调用通常放置在您的应用程序服务提供者的boot方法中。

发送到

要访问的端点

Soap::to('github.com/api')

函数

检索端点提供的函数

Soap::to('github.com/api')->functions()

这是PHP SoapClient _getFunctions()方法的包装器。

调用

调用端点的方法。

Soap::to('github.com/api')->call('merge')

该方法也可以作为魔术方法调用。

Soap::to('github.com/api')->merge()

参数

当然,调用方法接受参数。传递的参数可以是一个数组

Soap::to('github.com/api')->call('merge', ['branch' => 'staging', 'credentials' => ['password' => '...'])
节点

为了简化处理请求中的SOAP XML,Soap提供了一个方法来流畅地构建请求中的节点。

例如,假设以下节点需要在XML请求中。请注意,它没有主体。

<PullRequest branch="dev" target="main">
</PullRequest>

传递给底层php SoapClient以构造此节点的数组如下:

'PullRequest' => [
    '_' => '',
    'branch' => 'dev',
    'target' => 'main'
]

_是必需的,用于将信息设置为不是主体,而是节点的属性。

但是,如果XML节点有主体,则不需要这样做。

<PullRequest branch="dev" target="main">
    <Author>Ricorocks</Author>
</PullRequest>

现在,数组如下:

'PullRequest' => [
    'Author' => 'Ricorocks',
    'branch' => 'dev',
    'target' => 'main'
]

因此,为了避免混淆,Soap::node()将允许智能构建传递给SoapClient的php array

想象一下我们正在访问information方法来查看拉取请求的详细信息。

Soap::to('...')
    ->information('PullRequest' => soap_node(['branch' => 'dev', 'target' => 'main']))

'PullRequest' => [
    '_' => '',
    'branch' => 'dev',
    'target' => 'main'
]

Soap::to('...')
    ->information('PullRequest' => soap_node(['branch' => 'dev', 'target' => 'main'])->body(['Author' => 'Ricorocks']))

'PullRequest' => [
    'Author' => 'Ricorocks',
    'branch' => 'dev',
    'target' => 'main'
]

现在,只需通过向或从soap_node()添加或删除主体,就可以智能地构建输出的数组。

可以使用Facade Soap::node()或辅助方法soap_node()来创建节点。

选项

您可以使用withOptions方法为每个SOAP请求设置自定义选项,这些选项将被传递给Soap客户端。

Soap::to('...')->withOptions(['soap_version' => SOAP_1_2])->call('...');

有关更多详细信息,请参阅https://php.ac.cn/manual/en/soapclient.construct.php

Soap还提供了一些方法,它们为最常用的选项添加了语法糖,如下所述。

追踪

SOAP 允许您轻松追踪与访问的 SOAP 终端的交互。

要追踪所有请求,请在您的 ServiceProvider 的注册方法中设置以下内容

Soap::trace()

现在,所有返回的 Response 对象都将附加一个 Trace 对象,可通过 $response->getTrace() 访问。这个对象有四个属性,是对 SoapClient 上相应方法的包装

  • xmlRequest (__getLastRequest)
  • xmlResponse (__getLastResponse)
  • requestHeaders (__getLastRequestHeaders)
  • responseHeaders (__getLastResponseHeaders)

追踪也可以局部声明

Soap::to('...')->trace()->call('...')

现在,仅此 Response 将有一个有效的 Trace

追踪是空安全的。如果调用 $response->getTrace() 时没有设置 Trace,将返回一个新的 Trace。这个 Trace 的属性都将返回 null

认证

您可以使用 withBasicAuthwithDigestAuth 分别通过基本或摘要认证进行身份验证。

Soap::to('...')->withBasicAuth('username', 'password')->call('...');
Soap::to('...')->withDigestAuth('username', 'password')->call('...');

全局选项

有时,您可能希望在每个 SOAP 请求中都包含相同的选项集。您可以使用 Soap 外观的 options 方法来完成此操作

// Every request will include these options automatically
Soap::options(['login' => 'foo', 'password' => 'bar']);

您可能还希望在每个请求中都包含选项,但仅针对特定的端点或操作

// Only requests to this endpoint will include these options
Soap::options(['login' => 'foo', 'password' => 'bar'])->for('https://api.example.com');

// Only requests to this endpoint and the method Customers will include these options
Soap::options(['login' => 'foo', 'password' => 'bar'])->for('https://api.example.com', 'Customers');

这些调用通常放置在您的应用程序服务提供者的boot方法中。

钩子

钩子允许您在 Soap 发出请求之前和之后执行操作。这些钩子可以是局部的(针对每个请求),也可以是全局的(应用于每个请求)。

如果您希望在 beforeRequesting 钩子中更改 Request 对象,可以这样做。这些更改将反映在实际请求中。事实上,这就是 Soap 的 include 功能的工作方式。

局部

要创建一个局部钩子,将 beforeRequestingafterRequesting 连接到一个 Request 对象

Soap::to('http://example.com')
	->beforeRequesting(fn() => Log::info('Request going in!'))
	->afterRequesting(fn() => Log::info('Request coming out!'))
	->call('Action', []);

所有在请求之前的钩子将接收到请求作为参数,而在请求之后的钩子将接收到请求和响应作为参数。

全局

要创建一个全局钩子,使用 Soap::beforeRequestingSoap::afterRequesting 方法。

Soap::beforeRequesting(fn() => Log::info('Request going in!'));
Soap::afterRequesting(fn() => Log::info('Request coming out!'));

所有在请求之前的钩子将接收到请求作为参数,而在请求之后的钩子将接收到请求和响应作为参数。

模拟

Soap 包括对模拟端点和操作以及检查请求和响应的全面支持。

要模拟所有 SOAP 请求,请调用 Soap:fake()。这将返回每个请求的空响应。您可能希望更具体一些,因此可以向 fake 方法传递一个键为数组端点,值为响应对象的数组

Soap::fake(['http://endpoint.com' => Response::new(['foo' => 'bar'])]);

在上面的示例中,任何发送到 http://endpoint.com 的 SOAP 请求都将被模拟,并将返回一个包含 ['foo' => 'bar'] 体的 Response 对象。

如果您还想指定 SOAP 动作怎么办?很简单!只需在端点后添加 :{ActionName},如下所示

Soap::fake(['http://endpoint.com:Details' => Response::new(['foo' => 'bar'])]);

现在,只有针对 Details 操作的 SOAP 请求将被模拟。

您也可以使用 | 运算符指定多个操作

Soap::fake(['http://endpoint.com:Details|Information|Overview' => Response::new(['foo' => 'bar'])]);

现在,只有针对 DetailsInformationOverview 操作的 SOAP 请求将被模拟。

检查请求

如果您已调用 Soap::fake(),Soap 将记录所有请求。然后您可以按需检查这些请求。

Soap::assertSentCount($count)

如果您只想断言发送了 n 个 SOAP 请求,您可以使用此方法,并将所需计数作为参数传递。

Soap::assertSent(callable $callback)

您可以更深入地测试是否确实发送了特定请求,并且它返回了预期的响应。您应将闭包传递到此方法中,该闭包接收 $request$response 作为参数,并在它们符合您的期望时返回 true

Soap::assertNotSent(callable $callback)

这是 Soap::assertSent 的反义。您可以确保没有发出特定请求。同样,从闭包中返回 true 将导致它通过。

Soap::assertNothingSent()

如果您只想确保没有任何东西被发送出去,您可以调用这个方法。它做了它所说的。

配置

通过在您的服务提供者中的 boot() 方法调用 Soap 门面来配置 Soap。

包含

可以将参数设置为在所有请求中自动包含。这些可以是 数组节点

Soap::include(['credentials' => soap_node(['user' => '...', 'password' => '...'])]);

您甚至可以在您的数组键上使用点语法来深入请求体。

Soap::include(['login.credentials' => soap_node(['user' => '...', 'password' => '...'])]);

通常,您可能想要针对特定的端点或操作。您可以通过链式调用 for 方法来实现。

// Only requests to https://api.example.com will include this data
Soap::include(['credentials' => soap_node(['user' => '...', 'password' => '...'])])->for('https://api.example.com');

// Only requests to https://api.example.com calling the Customers method will include this data
Soap::include(['credentials' => soap_node(['user' => '...', 'password' => '...'])])->for('https://api.example.com', 'Customers');

Ray支持

本包包含了对 Ray 的第一方支持,Ray 是 Spatie 的一款出色的调试工具!我们提供了一些方法,您可以立即开始调试。

显然,您需要在项目中安装 Ray 才能使此功能正常工作。

ray()->showSoapRequests()

这启用了 SOAP 包中的 Ray 支持。任何 SOAP 请求都将被记录在 Ray 应用中供您检查。

ray()->stopShowingSoapRequests()

这禁用了 SOAP 包中的 Ray 支持。如果之前已启用,请求将停止记录。

如果您想在测试中使用 Ray 集成,请记住与您的其他提供者一起注册 RayServiceProvider

变更日志

有关最近更改的更多信息,请参阅 变更日志

贡献

有关详细信息,请参阅 贡献指南

安全性

如果您发现任何与安全相关的问题,请通过电子邮件 hello@ricorocks.agency 而不是使用问题跟踪器来联系。

鸣谢

许可

MIT 许可证 (MIT)。有关更多信息,请参阅 许可文件