一个提供处理请求和响应的简洁界面的SOAP客户端。

2.0.0 2024-03-19 12:59 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

Soap可以通过提供的Facade进行访问

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' => '...'
            ])

头部数据可以是数组或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提供了一个方法来流畅地构建请求中的节点。

例如,假设以下节点是所需的内容。注意它没有主体。

<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

跟踪是null安全的。如果调用$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()

如果您只想确保绝对没有发送任何内容,可以调用此方法。它确实做了它所说的。

配置

Soap 的配置是通过您的服务提供者中的 boot() 方法中的 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)。有关更多信息,请参阅 许可文件