<?php
use Nacosvel\OpenHttp\Builder;
$instance = Builder::factory([
'base_uri' => 'https://httpspot.dev/',
]);
// Send an synchronous request.
$response = $instance->chain('get')->get([
'query' => [
'nacosvel' => 'open-http',
],
]);
echo $response->getStatusCode(); // 200
echo $response->getHeaderLine('content-type'); // 'application/json; charset=utf8'
echo $response->getBody(); // '{"args":{"nacosvel":"open-http"},...'
// Send an asynchronous request.
$promise = $instance
->chain('get')
->getAsync()
->then(function ($response) {
return $response->getBody();
})
->wait();
echo $promise->getContents();推荐使用 PHP 包管理工具 Composer 安装:
composer require nacosvel/open-httpOpenHTTP is a PHP HTTP Client library based on Guzzle HTTP Client.
- 支持 同步 或 异步 发送请求
- 链式实现的 URI Template
- 自定义扩展
- 项目版本遵循 语义化版本号
- 推荐使用目前处于 Active Support 阶段的 PHP 8 和 Guzzle 7。
使用客户端提供的 get、head、put、post、patch 或 delete 方法发送同步请求。
<?php
try {
$response = $instance
->chain('post')
->post([
'json' => [
'mchid' => '1900006XXX',
'out_trade_no' => 'native12177525012014070332333',
'appid' => 'wxdace645e0bc2cXXX',
'description' => 'Image形象店-深圳腾大-QQ公仔',
'notify_url' => 'https://weixin.qq.com/',
'amount' => [
'total' => 1,
'currency' => 'CNY',
],
]]);
echo $response->getStatusCode(), PHP_EOL;
echo $response->getBody(), PHP_EOL;
} catch (\Exception $e) {
// 进行错误处理
echo $e->getMessage(), PHP_EOL;
if ($e instanceof \GuzzleHttp\Exception\RequestException && $e->hasResponse()) {
$r = $e->getResponse();
echo $r->getStatusCode() . ' ' . $r->getReasonPhrase(), PHP_EOL;
echo $r->getBody(), PHP_EOL, PHP_EOL, PHP_EOL;
}
echo $e->getTraceAsString(), PHP_EOL;
}请求成功后,你会获得一个 GuzzleHttp\Psr7\Response 的应答对象。
阅读 Guzzle 文档 Using Response 进一步了解如何访问应答内的信息。
使用客户端提供的 getAsync、headAsync、putAsync、postAsync、patchAsync 或 deleteAsync 方法发送异步请求。
<?php
$promise = $instance
->chain('post')
->postAsync([
'json' => [
'transaction_id' => '1217752501201407033233368018',
'out_refund_no' => '1217752501201407033233368018',
'amount' => [
'refund' => 888,
'total' => 888,
'currency' => 'CNY',
],
],
])
->then(static function ($response) {
// 正常逻辑回调处理
echo $response->getBody(), PHP_EOL;
return $response;
})
->otherwise(static function ($e) {
// 异常错误处理
echo $e->getMessage(), PHP_EOL;
if ($e instanceof \GuzzleHttp\Exception\RequestException && $e->hasResponse()) {
$r = $e->getResponse();
echo $r->getStatusCode() . ' ' . $r->getReasonPhrase(), PHP_EOL;
echo $r->getBody(), PHP_EOL, PHP_EOL, PHP_EOL;
}
echo $e->getTraceAsString(), PHP_EOL;
})
->wait();// 同步等待[get|head|post|put|patch|delete]Async 返回的是 Guzzle Promises。你可以做两件事:
- 成功时使用
then()处理得到的Psr\Http\Message\ResponseInterface,(可选地)将它传给下一个then() - 失败时使用
otherwise()处理异常
最后使用 wait() 等待请求执行完成。
URI Template 是表达 URI 中变量的一种方式。微信支付 API 使用这种方式表示 URL Path 中的单号或者 ID。
# 使用微信支付订单号查询订单
GET /v3/pay/transactions/id/{transaction_id}
# 使用商户订单号查询订单
GET /v3/pay/transactions/out-trade-no/{out_trade_no}
使用 链式 URI Template,你能像书写代码一样流畅地书写 URL,轻松地输入路径并传递 URL 参数。
链式串联的基本单元是 URI Path 中的 segments,segments
之间以 -> 连接。连接的规则如下:
- 普通 segment
- 直接书写。例如
v3->pay->transactions->native - 使用
chain()。例如chain('v3/pay/transactions/native')
- 直接书写。例如
- 包含连字号(-)的 segment
- 使用驼峰 camelCase 风格书写。例如
merchant-service可写成merchantService - 使用
{'foo-bar'}方式书写。例如{'merchant-service'}
- 使用驼峰 camelCase 风格书写。例如
- Path 变量:URL 中的 Path 变量应使用这种写法,避免自行组装,导致大小写处理错误
- 推荐使用
_variable_name_方式书写,支持 IDE 提示。例如v3->pay->transactions->id->_transaction_id_。 - 使用
{'{variable_name}'}方式书写。例如v3->pay->transactions->id->{'{transaction_id}'} - 使用
chain方法{transaction_id}方式书写。例如:chain('v3/pay/transactions/id/{transaction_id}')
- 推荐使用
以查询订单 GET 方法为例:
<?php
$promise = $instance
->v3->pay->transactions->id->_transaction_id_
// v3->pay->transactions->id->{'{transaction_id}'}
->getAsync([
// Query 参数
'query' => ['mchid' => '1230000109'],
// Path 变量的值,以同名参数传入执行方法
'transaction_id' => '1217752501201407033233368018',
]);以 关闭订单 POST 方法为例:
<?php
$promise = $instance
->chain('v3/pay/transactions/outTradeNo/{out_trade_no}/close')
->postAsync([
// 请求消息
'form_params' => ['mchid' => '1230000109'],
// Path 变量的值,以同名参数传入执行方法
'out_trade_no' => '1217752501201407033233368018',
]);使用自定义扩展处理器和中间件系统来发送HTTP请求。
- 一个处理器函数接受一个 Psr\Http\Message\RequestInterface 和一个请求选项数组,并返回一个用 Psr\Http\Message\ResponseInterface 填充的 GuzzleHttp\Promise\PromiseInterface,或被一个异常拒绝。
- 你可以使用客户端构造函数的 handler 选项为客户端提供一个自定义处理器。 重要的是要理解Guzzle使用的几个请求选项要求用特定的中间件来封装客户端要使用的处理器。 你可以通过在 GuzzleHttp\HandlerStack::create(callable $handler = null) 静态方法中封装处理器来确保你提供给客户端的处理器会使用默认中间件。
- 中间件通过在生成响应的过程中调用它们来增强处理器的功能。
- 中间件函数返回一个函数,该函数接受下一个要调用的处理器。 这个返回的函数接着返回另一个充当组合(composed)处理器的函数 -- 它接受一个请求和选项,并返回一个用响应填充的Promise。 你的组合的中间件可以修改请求、添加自定义请求选项,以及修改下游处理器返回的Promise。
- 处理器堆栈表示一个要应用于基本处理器函数的中间件堆栈。 你可以将中间件推送(push) 到堆栈以将其添加到堆栈的顶部,也可以将中间件卸载(unshift)到堆栈中以将其添加到堆栈的底部。 堆栈被解析后,该处理器将被推送到堆栈。然后从堆栈中弹出(popped)每个值,并封装从堆栈中弹出的前一个值。
<?php
use GuzzleHttp\Middleware;
use GuzzleHttp\Exception\RequestException;
use Psr\Http\Message\RequestInterface;
use Psr\Http\Message\ResponseInterface;
$handler = $instance->getClient()->getRequestClientHandler();
$auth = fn() => 'Authorization';
$verify = fn($response) => true;
// 注册请求认证中间件
$handler->before('prepare_body', Middleware::mapRequest(
static function (RequestInterface $request) use ($auth): RequestInterface {
return $request->withHeader('Authorization', $auth($request));
}
), 'auth');
// 注册请求验签中间件
$handler->before('http_errors', static function (callable $handler) use ($verify): callable {
return static function (RequestInterface $request, array $options = []) use ($verify, $handler) {
return $handler($request, $options)->then(
static function (ResponseInterface $response) use ($verify, $request): ResponseInterface {
try {
if ($verify($response)) {
throw new RequestException('签名验签失败', $request, $response, $exception ?? null);
}
} catch (\Throwable $exception) {
//
}
return $response;
}
);
};
}, 'verify');
$response = $instance->anything->certificates
->getAsync()
->then(static function ($res) {
return $res->getBody();
})
->wait();
var_dump($response->getContents());Nacosvel OpenHTTP is made available under the MIT License (MIT). Please see License File for more information.