mirror of
https://gitee.com/yansongda/pay.git
synced 2024-11-29 18:58:38 +08:00
change(internal): 按场景对微信插件进行分类,优化相关代码 (#909)
This commit is contained in:
parent
d1dcd340bc
commit
a849c761c7
@ -19,5 +19,6 @@ return (new PhpCsFixer\Config())
|
||||
'import_functions' => true,
|
||||
],
|
||||
'multiline_whitespace_before_semicolons' => ['strategy' => 'no_multi_line'],
|
||||
'fully_qualified_strict_types' => true,
|
||||
])
|
||||
->setFinder($finder);
|
||||
|
18
CHANGELOG.md
18
CHANGELOG.md
@ -3,19 +3,19 @@
|
||||
### added
|
||||
|
||||
- feat: 新增 `InvalidSignException`(#903)
|
||||
- feat: 新增 `DecryptException`(#906)
|
||||
|
||||
### changed
|
||||
|
||||
- change(internal): shortcut 完整标明各个插件,不使用 commonPlugin(#886)
|
||||
- change(internal): 按场景对支付宝插件进行分类(#894)
|
||||
- change(internal): 支付宝 shortcut 从 plugin 文件夹独立出来(#895)
|
||||
- change(internal): DirectionInterface 方法由 `parse` 改为 `guide`(#896)
|
||||
- change: 查询API方法由 `find` 改为 `query`,同时参数只支持 array(#897)
|
||||
- change: cancel 的 API 参数只支持 array,不再支持 string(#900)
|
||||
- change: close 的 API 参数只支持 array,不再支持 string(#901)
|
||||
- change(internal): 错误代码 const 命名规则统一(#902, #903)
|
||||
- change(internal): 微信 shortcut 从 plugin 文件夹独立出来(#904)
|
||||
- change(internal): 银联 shortcut 从 plugin 文件夹独立出来(#905)
|
||||
- change: cancel/close 的 API 参数只支持 array,不再支持 string(#900, #901)
|
||||
- change: 微信合单支付去掉独立的 `combine_app_id`,`combine_mch_id` 配置,复用其它配置(#909)
|
||||
- change(internal): 按场景对 支付宝/微信/银联 插件进行分类 && 插件代码优化(#894, #909)
|
||||
- change(internal): 将 支付/微信/银联 shortcut 从 plugin 文件夹独立出来(#895, #904, #905)
|
||||
- change(internal): shortcut 完整标明各个插件,不使用 commonPlugin(#886)
|
||||
- change(internal): DirectionInterface 方法由 `parse` 改为 `guide`(#896)
|
||||
- change(internal): 错误代码 const 命名规则统一(#902, #903, #906, #909)
|
||||
- change(internal): 调整 `ProviderInterface` 的返回参数,增加了 `Rocket` 返回(#909)
|
||||
|
||||
## v3.5.3
|
||||
|
||||
|
@ -27,12 +27,12 @@
|
||||
"psr/container": "^1.1 || ^2.0",
|
||||
"psr/http-client": "^1.0",
|
||||
"psr/http-message": "^1.1 || ^2.0",
|
||||
"yansongda/supports": "~4.0.0"
|
||||
"yansongda/supports": "~4.0.4"
|
||||
},
|
||||
"require-dev": {
|
||||
"phpunit/phpunit": "^9.0",
|
||||
"mockery/mockery": "^1.4",
|
||||
"friendsofphp/php-cs-fixer": "^3.0",
|
||||
"friendsofphp/php-cs-fixer": "^3.44",
|
||||
"phpstan/phpstan": "^1.0.0",
|
||||
"monolog/monolog": "^2.2",
|
||||
"symfony/var-dumper": "^5.1",
|
||||
|
@ -10,6 +10,7 @@ use Psr\Http\Message\ServerRequestInterface;
|
||||
use Yansongda\Pay\Exception\ContainerException;
|
||||
use Yansongda\Pay\Exception\InvalidParamsException;
|
||||
use Yansongda\Pay\Exception\ServiceNotFoundException;
|
||||
use Yansongda\Pay\Rocket;
|
||||
use Yansongda\Supports\Collection;
|
||||
|
||||
interface ProviderInterface
|
||||
@ -19,17 +20,17 @@ interface ProviderInterface
|
||||
* @throws InvalidParamsException
|
||||
* @throws ServiceNotFoundException
|
||||
*/
|
||||
public function pay(array $plugins, array $params): null|array|Collection|MessageInterface;
|
||||
public function pay(array $plugins, array $params): null|Collection|MessageInterface|Rocket;
|
||||
|
||||
public function query(array $order): array|Collection;
|
||||
public function query(array $order): Collection|Rocket;
|
||||
|
||||
public function cancel(array $order): null|array|Collection;
|
||||
public function cancel(array $order): Collection|Rocket;
|
||||
|
||||
public function close(array $order): null|array|Collection;
|
||||
public function close(array $order): Collection|Rocket;
|
||||
|
||||
public function refund(array $order): array|Collection;
|
||||
public function refund(array $order): Collection|Rocket;
|
||||
|
||||
public function callback(null|array|ServerRequestInterface $contents = null, ?array $params = null): Collection;
|
||||
public function callback(null|array|ServerRequestInterface $contents = null, ?array $params = null): Collection|Rocket;
|
||||
|
||||
public function success(): ResponseInterface;
|
||||
}
|
||||
|
@ -19,7 +19,7 @@ class CollectionDirection implements DirectionInterface
|
||||
public function guide(PackerInterface $packer, ?ResponseInterface $response): Collection
|
||||
{
|
||||
if (is_null($response)) {
|
||||
throw new InvalidResponseException(Exception::RESPONSE_EMPTY);
|
||||
throw new InvalidResponseException(Exception::RESPONSE_EMPTY, '响应异常: 响应为空,不能进行 direction');
|
||||
}
|
||||
|
||||
$body = (string) $response->getBody();
|
||||
@ -28,6 +28,6 @@ class CollectionDirection implements DirectionInterface
|
||||
return new Collection($result);
|
||||
}
|
||||
|
||||
throw new InvalidResponseException(Exception::RESPONSE_UNPACK_ERROR, 'Unpack Response Error', ['body' => $body, 'response' => $response]);
|
||||
throw new InvalidResponseException(Exception::RESPONSE_UNPACK_ERROR, '响应异常: 解包错误', ['body' => $body, 'response' => $response]);
|
||||
}
|
||||
}
|
||||
|
@ -17,10 +17,10 @@ class OriginResponseDirection implements DirectionInterface
|
||||
*/
|
||||
public function guide(PackerInterface $packer, ?ResponseInterface $response): ?ResponseInterface
|
||||
{
|
||||
if (!is_null($response)) {
|
||||
return $response;
|
||||
if (is_null($response)) {
|
||||
throw new InvalidResponseException(Exception::RESPONSE_EMPTY, '响应异常: 响应为空,不能进行 direction');
|
||||
}
|
||||
|
||||
throw new InvalidResponseException(Exception::RESPONSE_CODE_WRONG);
|
||||
return $response;
|
||||
}
|
||||
}
|
||||
|
@ -33,6 +33,6 @@ class Event
|
||||
return;
|
||||
}
|
||||
|
||||
throw new InvalidConfigException(Exception\Exception::CONFIG_EVENT_INVALID);
|
||||
throw new InvalidConfigException(Exception\Exception::CONFIG_EVENT_INVALID, '配置异常: 配置的 `EventDispatcherInterface` 不符合 PSR 规范');
|
||||
}
|
||||
}
|
||||
|
@ -9,7 +9,7 @@ use Throwable;
|
||||
|
||||
class ContainerException extends Exception implements ContainerExceptionInterface
|
||||
{
|
||||
public function __construct(string $message = '', int $code = self::CONTAINER_ERROR, mixed $extra = null, ?Throwable $previous = null)
|
||||
public function __construct(string $message = '容器异常', int $code = self::CONTAINER_ERROR, mixed $extra = null, ?Throwable $previous = null)
|
||||
{
|
||||
parent::__construct($message, $code, $extra, $previous);
|
||||
}
|
||||
|
@ -8,7 +8,7 @@ use Throwable;
|
||||
|
||||
class ContainerNotFoundException extends ContainerException
|
||||
{
|
||||
public function __construct(string $message = 'Container Not Found', int $code = self::CONTAINER_NOT_FOUND, mixed $extra = null, ?Throwable $previous = null)
|
||||
public function __construct(string $message = '容器未找到', int $code = self::CONTAINER_NOT_FOUND, mixed $extra = null, ?Throwable $previous = null)
|
||||
{
|
||||
parent::__construct($message, $code, $extra, $previous);
|
||||
}
|
||||
|
19
src/Exception/DecryptException.php
Normal file
19
src/Exception/DecryptException.php
Normal file
@ -0,0 +1,19 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Yansongda\Pay\Exception;
|
||||
|
||||
use Throwable;
|
||||
|
||||
class DecryptException extends Exception
|
||||
{
|
||||
public function __construct(
|
||||
int $code = self::DECRYPT_ERROR,
|
||||
string $message = '加解密异常',
|
||||
mixed $extra = null,
|
||||
?Throwable $previous = null
|
||||
) {
|
||||
parent::__construct($message, $code, $extra, $previous);
|
||||
}
|
||||
}
|
@ -60,13 +60,21 @@ class Exception extends \Exception
|
||||
|
||||
public const PARAMS_METHOD_NOT_SUPPORTED = 4004;
|
||||
|
||||
public const PARAMS_REQUEST_EMPTY = 4005;
|
||||
public const PARAMS_NECESSARY_PARAMS_MISSING = 4005;
|
||||
|
||||
public const PARAMS_NECESSARY_PARAMS_MISSING = 4006;
|
||||
public const PARAMS_PLUGIN_ONLY_SUPPORT_SERVICE_MODE = 4006;
|
||||
|
||||
public const PARAMS_PLUGIN_ONLY_SUPPORT_SERVICE_MODE = 4007;
|
||||
public const PARAMS_WECHAT_SERIAL_NOT_FOUND = 4007;
|
||||
|
||||
public const PARAMS_WECHAT_SERIAL_NOT_FOUND = 4008;
|
||||
public const PARAMS_CALLBACK_REQUEST_INVALID = 4008;
|
||||
|
||||
public const PARAMS_WECHAT_URL_MISSING = 4009;
|
||||
|
||||
public const PARAMS_WECHAT_BODY_MISSING = 4010;
|
||||
|
||||
public const PARAMS_WECHAT_AUTHORIZATION_MISSING = 4011;
|
||||
|
||||
public const PARAMS_PLUGIN_ONLY_SUPPORT_NORMAL_MODE = 4012;
|
||||
|
||||
/**
|
||||
* 关于响应.
|
||||
@ -77,17 +85,11 @@ class Exception extends \Exception
|
||||
|
||||
public const RESPONSE_UNPACK_ERROR = 5002;
|
||||
|
||||
public const RESPONSE_CODE_WRONG = 5004;
|
||||
public const RESPONSE_CODE_WRONG = 5003;
|
||||
|
||||
public const RESPONSE_MISSING_NECESSARY_PARAMS = 5005;
|
||||
public const RESPONSE_MISSING_NECESSARY_PARAMS = 5004;
|
||||
|
||||
public const RESPONSE_EMPTY = 5006;
|
||||
|
||||
public const RESPONSE_CIPHERTEXT_PARAMS_INVALID = 5007;
|
||||
|
||||
public const RESPONSE_ENCRYPTED_DATA_INVALID = 5008;
|
||||
|
||||
public const RESPONSE_DECRYPTED_METHOD_INVALID = 5009;
|
||||
public const RESPONSE_EMPTY = 5005;
|
||||
|
||||
/**
|
||||
* 关于签名.
|
||||
@ -96,9 +98,20 @@ class Exception extends \Exception
|
||||
|
||||
public const SIGN_EMPTY = 6001;
|
||||
|
||||
/**
|
||||
* 关于加解密.
|
||||
*/
|
||||
public const DECRYPT_ERROR = 7000;
|
||||
|
||||
public const DECRYPT_WECHAT_CIPHERTEXT_PARAMS_INVALID = 7001;
|
||||
|
||||
public const DECRYPT_WECHAT_ENCRYPTED_DATA_INVALID = 7002;
|
||||
|
||||
public const DECRYPT_WECHAT_DECRYPTED_METHOD_INVALID = 7003;
|
||||
|
||||
public mixed $extra;
|
||||
|
||||
public function __construct(string $message = 'Unknown Error', int $code = self::UNKNOWN_ERROR, mixed $extra = null, ?Throwable $previous = null)
|
||||
public function __construct(string $message = '未知异常', int $code = self::UNKNOWN_ERROR, mixed $extra = null, ?Throwable $previous = null)
|
||||
{
|
||||
$this->extra = $extra;
|
||||
|
||||
|
@ -8,7 +8,7 @@ use Throwable;
|
||||
|
||||
class InvalidConfigException extends Exception
|
||||
{
|
||||
public function __construct(int $code = self::CONFIG_ERROR, string $message = 'Config Error', mixed $extra = null, ?Throwable $previous = null)
|
||||
public function __construct(int $code = self::CONFIG_ERROR, string $message = '配置异常', mixed $extra = null, ?Throwable $previous = null)
|
||||
{
|
||||
parent::__construct($message, $code, $extra, $previous);
|
||||
}
|
||||
|
@ -8,7 +8,7 @@ use Throwable;
|
||||
|
||||
class InvalidParamsException extends Exception
|
||||
{
|
||||
public function __construct(int $code = self::PARAMS_ERROR, string $message = 'Params Error', mixed $extra = null, ?Throwable $previous = null)
|
||||
public function __construct(int $code = self::PARAMS_ERROR, string $message = '参数异常', mixed $extra = null, ?Throwable $previous = null)
|
||||
{
|
||||
parent::__construct($message, $code, $extra, $previous);
|
||||
}
|
||||
|
@ -12,7 +12,7 @@ class InvalidResponseException extends Exception
|
||||
|
||||
public function __construct(
|
||||
int $code = self::RESPONSE_ERROR,
|
||||
string $message = 'Provider response Error',
|
||||
string $message = '响应异常',
|
||||
mixed $extra = null,
|
||||
?Throwable $previous = null
|
||||
) {
|
||||
|
@ -12,7 +12,7 @@ class InvalidSignException extends Exception
|
||||
|
||||
public function __construct(
|
||||
int $code = self::SIGN_ERROR,
|
||||
string $message = 'Sign Error',
|
||||
string $message = '签名异常',
|
||||
mixed $extra = null,
|
||||
?Throwable $previous = null
|
||||
) {
|
||||
|
@ -9,7 +9,7 @@ use Throwable;
|
||||
|
||||
class ServiceNotFoundException extends Exception implements NotFoundExceptionInterface
|
||||
{
|
||||
public function __construct(string $message = 'Service Not Found', int $code = self::SERVICE_NOT_FOUND, mixed $extra = null, ?Throwable $previous = null)
|
||||
public function __construct(string $message = '服务未找到', int $code = self::SERVICE_NOT_FOUND, mixed $extra = null, ?Throwable $previous = null)
|
||||
{
|
||||
parent::__construct($message, $code, $extra, $previous);
|
||||
}
|
||||
|
@ -4,23 +4,28 @@ declare(strict_types=1);
|
||||
|
||||
namespace Yansongda\Pay;
|
||||
|
||||
use Closure;
|
||||
use Psr\Http\Message\ResponseInterface;
|
||||
use Psr\Http\Message\ServerRequestInterface;
|
||||
use Yansongda\Pay\Contract\ConfigInterface;
|
||||
use Yansongda\Pay\Contract\DirectionInterface;
|
||||
use Yansongda\Pay\Direction\NoHttpRequestDirection;
|
||||
use Yansongda\Pay\Exception\ContainerException;
|
||||
use Yansongda\Pay\Exception\DecryptException;
|
||||
use Yansongda\Pay\Exception\Exception;
|
||||
use Yansongda\Pay\Exception\InvalidConfigException;
|
||||
use Yansongda\Pay\Exception\InvalidParamsException;
|
||||
use Yansongda\Pay\Exception\InvalidResponseException;
|
||||
use Yansongda\Pay\Exception\InvalidSignException;
|
||||
use Yansongda\Pay\Exception\ServiceNotFoundException;
|
||||
use Yansongda\Pay\Plugin\ParserPlugin;
|
||||
use Yansongda\Pay\Plugin\Wechat\PreparePlugin;
|
||||
use Yansongda\Pay\Plugin\Wechat\RadarSignPlugin;
|
||||
use Yansongda\Pay\Plugin\Wechat\AddPayloadBodyPlugin;
|
||||
use Yansongda\Pay\Plugin\Wechat\AddPayloadSignaturePlugin;
|
||||
use Yansongda\Pay\Plugin\Wechat\AddRadarPlugin;
|
||||
use Yansongda\Pay\Plugin\Wechat\ResponsePlugin;
|
||||
use Yansongda\Pay\Plugin\Wechat\StartPlugin;
|
||||
use Yansongda\Pay\Plugin\Wechat\WechatPublicCertsPlugin;
|
||||
use Yansongda\Pay\Provider\Wechat;
|
||||
use Yansongda\Supports\Collection;
|
||||
use Yansongda\Supports\Str;
|
||||
|
||||
function should_do_http_request(string $direction): bool
|
||||
@ -47,23 +52,12 @@ function get_direction(mixed $direction): DirectionInterface
|
||||
}
|
||||
|
||||
if (!$direction instanceof DirectionInterface) {
|
||||
throw new InvalidConfigException(Exception::CONFIG_DIRECTION_INVALID);
|
||||
throw new InvalidConfigException(Exception::CONFIG_DIRECTION_INVALID, '配置异常: 配置的 DirectionInterface 未实现 `DirectionInterface`');
|
||||
}
|
||||
|
||||
return $direction;
|
||||
}
|
||||
|
||||
/**
|
||||
* @throws ContainerException
|
||||
* @throws ServiceNotFoundException
|
||||
*/
|
||||
function get_alipay_config(array $params = []): array
|
||||
{
|
||||
$alipay = Pay::get(ConfigInterface::class)->get('alipay');
|
||||
|
||||
return $alipay[get_tenant($params)] ?? [];
|
||||
}
|
||||
|
||||
function get_public_cert(string $key): string
|
||||
{
|
||||
return Str::endsWith($key, ['.cer', '.crt', '.pem']) ? file_get_contents($key) : $key;
|
||||
@ -80,18 +74,32 @@ function get_private_cert(string $key): string
|
||||
"\n-----END RSA PRIVATE KEY-----";
|
||||
}
|
||||
|
||||
function filter_params(array $params, ?Closure $closure = null): array
|
||||
{
|
||||
return array_filter($params, static fn ($v, $k) => !Str::startsWith($k, '_') && !is_null($v) && (empty($closure) || $closure($k, $v)), ARRAY_FILTER_USE_BOTH);
|
||||
}
|
||||
|
||||
/**
|
||||
* @throws ContainerException
|
||||
* @throws InvalidConfigException
|
||||
* @throws ServiceNotFoundException
|
||||
*/
|
||||
function get_alipay_config(array $params = []): array
|
||||
{
|
||||
$alipay = Pay::get(ConfigInterface::class)->get('alipay');
|
||||
|
||||
return $alipay[get_tenant($params)] ?? [];
|
||||
}
|
||||
|
||||
/**
|
||||
* @throws InvalidConfigException
|
||||
* @throws InvalidSignException
|
||||
*/
|
||||
function verify_alipay_sign(array $params, string $contents, string $sign): void
|
||||
function verify_alipay_sign(array $config, string $contents, string $sign): void
|
||||
{
|
||||
$public = get_alipay_config($params)['alipay_public_cert_path'] ?? null;
|
||||
$public = $config['alipay_public_cert_path'] ?? null;
|
||||
|
||||
if (empty($public)) {
|
||||
throw new InvalidConfigException(Exception::CONFIG_ALIPAY_INVALID, 'Missing Alipay Config -- [alipay_public_cert_path]');
|
||||
throw new InvalidConfigException(Exception::CONFIG_ALIPAY_INVALID, '配置异常: 缺少支付宝配置 -- [alipay_public_cert_path]');
|
||||
}
|
||||
|
||||
$result = 1 === openssl_verify(
|
||||
@ -102,7 +110,7 @@ function verify_alipay_sign(array $params, string $contents, string $sign): void
|
||||
);
|
||||
|
||||
if (!$result) {
|
||||
throw new InvalidSignException(Exception::SIGN_ERROR, 'Verify Alipay Sign Failed', func_get_args());
|
||||
throw new InvalidSignException(Exception::SIGN_ERROR, '签名异常: 验证支付宝签名失败', func_get_args());
|
||||
}
|
||||
}
|
||||
|
||||
@ -110,35 +118,74 @@ function verify_alipay_sign(array $params, string $contents, string $sign): void
|
||||
* @throws ContainerException
|
||||
* @throws ServiceNotFoundException
|
||||
*/
|
||||
function get_wechat_config(array $params): array
|
||||
function get_wechat_config(array $params = []): array
|
||||
{
|
||||
$wechat = Pay::get(ConfigInterface::class)->get('wechat');
|
||||
|
||||
return $wechat[get_tenant($params)] ?? [];
|
||||
}
|
||||
|
||||
/**
|
||||
* @throws ContainerException
|
||||
* @throws ServiceNotFoundException
|
||||
*/
|
||||
function get_wechat_base_uri(array $params): string
|
||||
function get_wechat_method(?Collection $payload): string
|
||||
{
|
||||
$config = get_wechat_config($params);
|
||||
|
||||
return Wechat::URL[$config['mode'] ?? Pay::MODE_NORMAL];
|
||||
return strtoupper($payload?->get('_method') ?? 'POST');
|
||||
}
|
||||
|
||||
/**
|
||||
* @throws InvalidParamsException
|
||||
*/
|
||||
function get_wechat_url(array $config, ?Collection $payload): string
|
||||
{
|
||||
$url = $payload?->get('_url') ?? null;
|
||||
|
||||
if (Pay::MODE_SERVICE === ($config['mode'] ?? Pay::MODE_NORMAL)) {
|
||||
$url = $payload?->get('_service_url') ?? $url ?? null;
|
||||
}
|
||||
|
||||
if (empty($url)) {
|
||||
throw new InvalidParamsException(Exception::PARAMS_WECHAT_URL_MISSING, '参数异常: 微信 `_url` 或 `_service_url` 参数缺失:你可能用错插件顺序,应该先使用 `业务插件`');
|
||||
}
|
||||
|
||||
if (str_starts_with($url, 'http')) {
|
||||
return $url;
|
||||
}
|
||||
|
||||
return Wechat::URL[$config['mode'] ?? Pay::MODE_NORMAL].$url;
|
||||
}
|
||||
|
||||
/**
|
||||
* @throws InvalidParamsException
|
||||
*/
|
||||
function get_wechat_body(?Collection $payload): string
|
||||
{
|
||||
$body = $payload?->get('_body') ?? null;
|
||||
|
||||
if (is_null($body)) {
|
||||
throw new InvalidParamsException(Exception::PARAMS_WECHAT_BODY_MISSING, '参数异常: 微信 `_body` 参数缺失:你可能用错插件顺序,应该先使用 `AddPayloadBodyPlugin`');
|
||||
}
|
||||
|
||||
return $body;
|
||||
}
|
||||
|
||||
function get_wechat_type_key(array $params): string
|
||||
{
|
||||
$key = ($params['_type'] ?? 'mp').'_app_id';
|
||||
|
||||
if ('app_app_id' === $key) {
|
||||
$key = 'app_id';
|
||||
}
|
||||
|
||||
return $key;
|
||||
}
|
||||
|
||||
/**
|
||||
* @throws ContainerException
|
||||
* @throws ServiceNotFoundException
|
||||
* @throws InvalidConfigException
|
||||
*/
|
||||
function get_wechat_sign(array $params, string $contents): string
|
||||
function get_wechat_sign(array $config, string $contents): string
|
||||
{
|
||||
$privateKey = get_wechat_config($params)['mch_secret_cert'] ?? null;
|
||||
$privateKey = $config['mch_secret_cert'] ?? null;
|
||||
|
||||
if (empty($privateKey)) {
|
||||
throw new InvalidConfigException(Exception::CONFIG_WECHAT_INVALID, 'Missing Wechat Config -- [mch_secret_cert]');
|
||||
throw new InvalidConfigException(Exception::CONFIG_WECHAT_INVALID, '配置异常: 缺少微信配置 -- [mch_secret_cert]');
|
||||
}
|
||||
|
||||
$privateKey = get_private_cert($privateKey);
|
||||
@ -158,7 +205,7 @@ function get_wechat_sign_v2(array $params, array $payload, bool $upper = true):
|
||||
$key = get_wechat_config($params)['mch_secret_key_v2'] ?? null;
|
||||
|
||||
if (empty($key)) {
|
||||
throw new InvalidConfigException(Exception::CONFIG_WECHAT_INVALID, 'Missing Wechat Config -- [mch_secret_key_v2]');
|
||||
throw new InvalidConfigException(Exception::CONFIG_WECHAT_INVALID, '配置异常: 缺少微信配置 -- [mch_secret_key_v2]');
|
||||
}
|
||||
|
||||
ksort($payload);
|
||||
@ -176,11 +223,11 @@ function get_wechat_sign_v2(array $params, array $payload, bool $upper = true):
|
||||
|
||||
/**
|
||||
* @throws ContainerException
|
||||
* @throws DecryptException
|
||||
* @throws InvalidConfigException
|
||||
* @throws InvalidResponseException
|
||||
* @throws ServiceNotFoundException
|
||||
* @throws InvalidParamsException
|
||||
* @throws InvalidSignException
|
||||
* @throws ServiceNotFoundException
|
||||
*/
|
||||
function verify_wechat_sign(ResponseInterface|ServerRequestInterface $message, array $params): void
|
||||
{
|
||||
@ -198,7 +245,7 @@ function verify_wechat_sign(ResponseInterface|ServerRequestInterface $message, a
|
||||
$public = get_wechat_config($params)['wechat_public_cert_path'][$wechatSerial] ?? null;
|
||||
|
||||
if (empty($sign)) {
|
||||
throw new InvalidSignException(Exception::SIGN_EMPTY, $body, ['headers' => $message->getHeaders(), 'body' => $body]);
|
||||
throw new InvalidSignException(Exception::SIGN_EMPTY, '签名异常: 微信签名为空', ['headers' => $message->getHeaders(), 'body' => $body]);
|
||||
}
|
||||
|
||||
$public = get_public_cert(
|
||||
@ -213,7 +260,7 @@ function verify_wechat_sign(ResponseInterface|ServerRequestInterface $message, a
|
||||
);
|
||||
|
||||
if (!$result) {
|
||||
throw new InvalidSignException(Exception::SIGN_ERROR, 'Verify Wechat Sign Failed', ['headers' => $message->getHeaders(), 'body' => $body]);
|
||||
throw new InvalidSignException(Exception::SIGN_ERROR, '签名异常: 验证微信签名失败', ['headers' => $message->getHeaders(), 'body' => $body]);
|
||||
}
|
||||
}
|
||||
|
||||
@ -228,31 +275,31 @@ function encrypt_wechat_contents(string $contents, string $publicKey): ?string
|
||||
|
||||
/**
|
||||
* @throws ContainerException
|
||||
* @throws DecryptException
|
||||
* @throws InvalidConfigException
|
||||
* @throws ServiceNotFoundException
|
||||
* @throws InvalidParamsException
|
||||
* @throws InvalidResponseException
|
||||
* @throws ServiceNotFoundException
|
||||
*/
|
||||
function reload_wechat_public_certs(array $params, ?string $serialNo = null): string
|
||||
{
|
||||
$data = Pay::wechat()->pay(
|
||||
[PreparePlugin::class, WechatPublicCertsPlugin::class, RadarSignPlugin::class, ParserPlugin::class],
|
||||
[StartPlugin::class, WechatPublicCertsPlugin::class, AddPayloadBodyPlugin::class, AddPayloadSignaturePlugin::class, AddRadarPlugin::class, ResponsePlugin::class, ParserPlugin::class],
|
||||
$params
|
||||
)->get('data', []);
|
||||
|
||||
foreach ($data as $item) {
|
||||
$certs[$item['serial_no']] = decrypt_wechat_resource($item['encrypt_certificate'], $params)['ciphertext'] ?? '';
|
||||
}
|
||||
|
||||
$wechatConfig = get_wechat_config($params);
|
||||
|
||||
foreach ($data as $item) {
|
||||
$certs[$item['serial_no']] = decrypt_wechat_resource($item['encrypt_certificate'], $wechatConfig)['ciphertext'] ?? '';
|
||||
}
|
||||
|
||||
Pay::get(ConfigInterface::class)->set(
|
||||
'wechat.'.get_tenant($params).'.wechat_public_cert_path',
|
||||
((array) ($wechatConfig['wechat_public_cert_path'] ?? [])) + ($certs ?? []),
|
||||
);
|
||||
|
||||
if (!is_null($serialNo) && empty($certs[$serialNo])) {
|
||||
throw new InvalidConfigException(Exception::CONFIG_WECHAT_INVALID, 'Get Wechat Public Cert Error');
|
||||
throw new InvalidConfigException(Exception::CONFIG_WECHAT_INVALID, '配置异常: 获取微信 wechat_public_cert_path 配置失败');
|
||||
}
|
||||
|
||||
return $certs[$serialNo] ?? '';
|
||||
@ -260,10 +307,10 @@ function reload_wechat_public_certs(array $params, ?string $serialNo = null): st
|
||||
|
||||
/**
|
||||
* @throws ContainerException
|
||||
* @throws DecryptException
|
||||
* @throws InvalidConfigException
|
||||
* @throws ServiceNotFoundException
|
||||
* @throws InvalidParamsException
|
||||
* @throws InvalidResponseException
|
||||
* @throws ServiceNotFoundException
|
||||
*/
|
||||
function get_wechat_public_certs(array $params = [], ?string $path = null): void
|
||||
{
|
||||
@ -283,34 +330,32 @@ function get_wechat_public_certs(array $params = [], ?string $path = null): void
|
||||
}
|
||||
|
||||
/**
|
||||
* @throws ContainerException
|
||||
* @throws InvalidConfigException
|
||||
* @throws InvalidResponseException
|
||||
* @throws ServiceNotFoundException
|
||||
* @throws DecryptException
|
||||
*/
|
||||
function decrypt_wechat_resource(array $resource, array $params): array
|
||||
function decrypt_wechat_resource(array $resource, array $config): array
|
||||
{
|
||||
$ciphertext = base64_decode($resource['ciphertext'] ?? '');
|
||||
$secret = get_wechat_config($params)['mch_secret_key'] ?? null;
|
||||
$secret = $config['mch_secret_key'] ?? null;
|
||||
|
||||
if (strlen($ciphertext) <= Wechat::AUTH_TAG_LENGTH_BYTE) {
|
||||
throw new InvalidResponseException(Exception::RESPONSE_CIPHERTEXT_PARAMS_INVALID);
|
||||
throw new DecryptException(Exception::DECRYPT_WECHAT_CIPHERTEXT_PARAMS_INVALID, '加解密异常: ciphertext 位数过短');
|
||||
}
|
||||
|
||||
if (is_null($secret) || Wechat::MCH_SECRET_KEY_LENGTH_BYTE != strlen($secret)) {
|
||||
throw new InvalidConfigException(Exception::CONFIG_WECHAT_INVALID, 'Missing Wechat Config -- [mch_secret_key]');
|
||||
throw new InvalidConfigException(Exception::CONFIG_WECHAT_INVALID, '配置异常: 缺少微信配置 -- [mch_secret_key]');
|
||||
}
|
||||
|
||||
$resource['ciphertext'] = match ($resource['algorithm'] ?? '') {
|
||||
'AEAD_AES_256_GCM' => decrypt_wechat_resource_aes_256_gcm($ciphertext, $secret, $resource['nonce'] ?? '', $resource['associated_data'] ?? ''),
|
||||
default => throw new InvalidResponseException(Exception::RESPONSE_DECRYPTED_METHOD_INVALID),
|
||||
default => throw new DecryptException(Exception::DECRYPT_WECHAT_DECRYPTED_METHOD_INVALID, '加解密异常: algorithm 不支持'),
|
||||
};
|
||||
|
||||
return $resource;
|
||||
}
|
||||
|
||||
/**
|
||||
* @throws InvalidResponseException
|
||||
* @throws DecryptException
|
||||
*/
|
||||
function decrypt_wechat_resource_aes_256_gcm(string $ciphertext, string $secret, string $nonce, string $associatedData): array|string
|
||||
{
|
||||
@ -324,17 +369,61 @@ function decrypt_wechat_resource_aes_256_gcm(string $ciphertext, string $secret,
|
||||
$associatedData
|
||||
);
|
||||
|
||||
if (false === $decrypted) {
|
||||
throw new DecryptException(Exception::DECRYPT_WECHAT_ENCRYPTED_DATA_INVALID, '加解密异常: 解密失败,请检查微信 mch_secret_key 是否正确');
|
||||
}
|
||||
|
||||
if ('certificate' !== $associatedData) {
|
||||
$decrypted = json_decode(strval($decrypted), true);
|
||||
$decrypted = json_decode($decrypted, true);
|
||||
|
||||
if (JSON_ERROR_NONE !== json_last_error()) {
|
||||
throw new InvalidResponseException(Exception::RESPONSE_ENCRYPTED_DATA_INVALID);
|
||||
throw new DecryptException(Exception::DECRYPT_WECHAT_ENCRYPTED_DATA_INVALID, '加解密异常: 待解密数据非正常数据');
|
||||
}
|
||||
}
|
||||
|
||||
return $decrypted;
|
||||
}
|
||||
|
||||
/**
|
||||
* @throws ContainerException
|
||||
* @throws DecryptException
|
||||
* @throws InvalidConfigException
|
||||
* @throws InvalidParamsException
|
||||
* @throws ServiceNotFoundException
|
||||
*/
|
||||
function get_wechat_serial_no(array $params): string
|
||||
{
|
||||
if (!empty($params['_serial_no'])) {
|
||||
return $params['_serial_no'];
|
||||
}
|
||||
|
||||
$config = get_wechat_config($params);
|
||||
|
||||
if (empty($config['wechat_public_cert_path'])) {
|
||||
reload_wechat_public_certs($params);
|
||||
|
||||
$config = get_wechat_config($params);
|
||||
}
|
||||
|
||||
mt_srand();
|
||||
|
||||
return strval(array_rand($config['wechat_public_cert_path']));
|
||||
}
|
||||
|
||||
/**
|
||||
* @throws InvalidParamsException
|
||||
*/
|
||||
function get_wechat_public_key(array $config, string $serialNo): string
|
||||
{
|
||||
$publicKey = $config['wechat_public_cert_path'][$serialNo] ?? null;
|
||||
|
||||
if (empty($publicKey)) {
|
||||
throw new InvalidParamsException(Exception::PARAMS_WECHAT_SERIAL_NOT_FOUND, '参数异常: 微信公钥序列号为找到 -'.$serialNo);
|
||||
}
|
||||
|
||||
return $publicKey;
|
||||
}
|
||||
|
||||
/**
|
||||
* @throws ContainerException
|
||||
* @throws ServiceNotFoundException
|
||||
@ -356,7 +445,7 @@ function verify_unipay_sign(array $params, string $contents, string $sign): void
|
||||
{
|
||||
if (empty($params['signPubKeyCert'])
|
||||
&& empty($public = get_unipay_config($params)['unipay_public_cert_path'] ?? null)) {
|
||||
throw new InvalidConfigException(Exception::CONFIG_UNIPAY_INVALID, 'Missing Unipay Config -- [unipay_public_cert_path]');
|
||||
throw new InvalidConfigException(Exception::CONFIG_UNIPAY_INVALID, '配置异常: 缺少银联配置 -- [unipay_public_cert_path]');
|
||||
}
|
||||
|
||||
$result = 1 === openssl_verify(
|
||||
@ -367,6 +456,6 @@ function verify_unipay_sign(array $params, string $contents, string $sign): void
|
||||
);
|
||||
|
||||
if (!$result) {
|
||||
throw new InvalidSignException(Exception::SIGN_ERROR, 'Verify Unipay Sign Failed', func_get_args());
|
||||
throw new InvalidSignException(Exception::SIGN_ERROR, '签名异常: 验证银联签名失败', func_get_args());
|
||||
}
|
||||
}
|
||||
|
@ -43,6 +43,6 @@ class Logger
|
||||
return;
|
||||
}
|
||||
|
||||
throw new InvalidConfigException(Exception\Exception::CONFIG_LOGGER_INVALID);
|
||||
throw new InvalidConfigException(Exception\Exception::CONFIG_LOGGER_INVALID, '配置异常: 配置的 `LoggerInterface` 不符合 PSR 规范');
|
||||
}
|
||||
}
|
||||
|
12
src/Pay.php
12
src/Pay.php
@ -137,10 +137,10 @@ class Pay
|
||||
} catch (ContainerNotFoundException $e) {
|
||||
throw $e;
|
||||
} catch (Throwable $e) {
|
||||
throw new ContainerException($e->getMessage());
|
||||
throw new ContainerException('容器异常: '.$e->getMessage());
|
||||
}
|
||||
|
||||
throw new ContainerException('Current container does NOT support `set` method');
|
||||
throw new ContainerException('容器异常: 当前容器类型不支持 `set` 方法');
|
||||
}
|
||||
|
||||
/**
|
||||
@ -159,7 +159,7 @@ class Pay
|
||||
} catch (ContainerNotFoundException $e) {
|
||||
throw $e;
|
||||
} catch (Throwable $e) {
|
||||
throw new ContainerException($e->getMessage());
|
||||
throw new ContainerException('容器异常: '.$e->getMessage());
|
||||
}
|
||||
|
||||
$parameters = array_values($parameters);
|
||||
@ -176,11 +176,11 @@ class Pay
|
||||
try {
|
||||
return Pay::getContainer()->get($service);
|
||||
} catch (NotFoundExceptionInterface $e) {
|
||||
throw new ServiceNotFoundException($e->getMessage());
|
||||
throw new ServiceNotFoundException('服务未找到: '.$e->getMessage());
|
||||
} catch (ContainerNotFoundException $e) {
|
||||
throw $e;
|
||||
} catch (Throwable $e) {
|
||||
throw new ContainerException($e->getMessage());
|
||||
throw new ContainerException('容器异常: '.$e->getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
@ -210,7 +210,7 @@ class Pay
|
||||
return (self::$container)();
|
||||
}
|
||||
|
||||
throw new ContainerNotFoundException('`getContainer()` failed! Maybe you should `setContainer()` first', Exception\Exception::CONTAINER_NOT_FOUND);
|
||||
throw new ContainerNotFoundException('容器未找到: `getContainer()` failed! Maybe you should `setContainer()` first', Exception\Exception::CONTAINER_NOT_FOUND);
|
||||
}
|
||||
|
||||
public static function hasContainer(): bool
|
||||
|
@ -16,7 +16,7 @@ use Yansongda\Pay\Rocket;
|
||||
use function Yansongda\Pay\get_alipay_config;
|
||||
use function Yansongda\Pay\get_private_cert;
|
||||
|
||||
class AddSignaturePlugin implements PluginInterface
|
||||
class AddPayloadSignaturePlugin implements PluginInterface
|
||||
{
|
||||
/**
|
||||
* @throws ContainerException
|
||||
@ -25,11 +25,11 @@ class AddSignaturePlugin implements PluginInterface
|
||||
*/
|
||||
public function assembly(Rocket $rocket, Closure $next): Rocket
|
||||
{
|
||||
Logger::debug('[Alipay][AddSignaturePlugin] 插件开始装载', ['rocket' => $rocket]);
|
||||
Logger::debug('[Alipay][AddPayloadSignaturePlugin] 插件开始装载', ['rocket' => $rocket]);
|
||||
|
||||
$rocket->mergePayload(['sign' => $this->getSign($rocket)]);
|
||||
|
||||
Logger::info('[Alipay][AddSignaturePlugin] 插件装载完毕', ['rocket' => $rocket]);
|
||||
Logger::info('[Alipay][AddPayloadSignaturePlugin] 插件装载完毕', ['rocket' => $rocket]);
|
||||
|
||||
return $next($rocket);
|
||||
}
|
||||
@ -60,7 +60,7 @@ class AddSignaturePlugin implements PluginInterface
|
||||
$privateKey = get_alipay_config($params)['app_secret_cert'] ?? null;
|
||||
|
||||
if (is_null($privateKey)) {
|
||||
throw new InvalidConfigException(Exception::CONFIG_ALIPAY_INVALID, 'Missing Alipay Config -- [app_secret_cert]');
|
||||
throw new InvalidConfigException(Exception::CONFIG_ALIPAY_INVALID, '配置异常: 缺少支付宝配置 -- [app_secret_cert]');
|
||||
}
|
||||
|
||||
return get_private_cert($privateKey);
|
@ -15,8 +15,9 @@ use Yansongda\Pay\Exception\ServiceNotFoundException;
|
||||
use Yansongda\Pay\Logger;
|
||||
use Yansongda\Pay\Rocket;
|
||||
use Yansongda\Supports\Collection;
|
||||
use Yansongda\Supports\Str;
|
||||
|
||||
use function Yansongda\Pay\filter_params;
|
||||
use function Yansongda\Pay\get_alipay_config;
|
||||
use function Yansongda\Pay\verify_alipay_sign;
|
||||
|
||||
class CallbackPlugin implements PluginInterface
|
||||
@ -35,10 +36,12 @@ class CallbackPlugin implements PluginInterface
|
||||
$sign = $rocket->getParams()['sign'] ?? false;
|
||||
|
||||
if (!$sign) {
|
||||
throw new InvalidSignException(Exception::SIGN_EMPTY, 'Callback Empty Sign', $rocket->getParams());
|
||||
throw new InvalidSignException(Exception::SIGN_EMPTY, '签名异常: 支付宝回调签名为空', $rocket->getParams());
|
||||
}
|
||||
|
||||
verify_alipay_sign($rocket->getParams(), $this->getSignContent($rocket->getPayload()), $sign);
|
||||
$config = get_alipay_config($rocket->getParams());
|
||||
|
||||
verify_alipay_sign($config, $this->getSignContent($rocket->getPayload()), $sign);
|
||||
|
||||
$rocket->setDirection(NoHttpRequestDirection::class)
|
||||
->setDestination($rocket->getPayload());
|
||||
@ -50,10 +53,9 @@ class CallbackPlugin implements PluginInterface
|
||||
|
||||
protected function formatPayload(Rocket $rocket): void
|
||||
{
|
||||
$payload = (new Collection($rocket->getParams()))
|
||||
->filter(fn ($v, $k) => '' !== $v && !is_null($v) && 'sign' != $k && 'sign_type' != $k && !Str::startsWith($k, '_'));
|
||||
$payload = filter_params($rocket->getParams(), fn ($k, $v) => '' !== $v && 'sign' != $k && 'sign_type' != $k);
|
||||
|
||||
$rocket->setPayload($payload);
|
||||
$rocket->setPayload(new Collection($payload));
|
||||
}
|
||||
|
||||
protected function getSignContent(Collection $payload): string
|
||||
|
@ -1,31 +0,0 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Yansongda\Pay\Plugin\Alipay;
|
||||
|
||||
use Closure;
|
||||
use Yansongda\Pay\Contract\PluginInterface;
|
||||
use Yansongda\Pay\Logger;
|
||||
use Yansongda\Pay\Rocket;
|
||||
use Yansongda\Supports\Str;
|
||||
|
||||
class FormatBizContentPlugin implements PluginInterface
|
||||
{
|
||||
public function assembly(Rocket $rocket, Closure $next): Rocket
|
||||
{
|
||||
Logger::debug('[Alipay][FormatBizContentPlugin] 插件开始装载', ['rocket' => $rocket]);
|
||||
|
||||
$payload = $rocket->getPayload()->filter(fn ($v, $k) => '' !== $v && !is_null($v) && 'sign' != $k);
|
||||
|
||||
$contents = array_filter($payload->get('biz_content', []), fn ($v, $k) => !Str::startsWith(strval($k), '_'), ARRAY_FILTER_USE_BOTH);
|
||||
|
||||
$rocket->setPayload(
|
||||
$payload->merge(['biz_content' => json_encode($contents)])
|
||||
);
|
||||
|
||||
Logger::info('[Alipay][FormatBizContentPlugin] 插件装载完毕', ['rocket' => $rocket]);
|
||||
|
||||
return $next($rocket);
|
||||
}
|
||||
}
|
32
src/Plugin/Alipay/FormatPayloadBizContentPlugin.php
Normal file
32
src/Plugin/Alipay/FormatPayloadBizContentPlugin.php
Normal file
@ -0,0 +1,32 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Yansongda\Pay\Plugin\Alipay;
|
||||
|
||||
use Closure;
|
||||
use Yansongda\Pay\Contract\PluginInterface;
|
||||
use Yansongda\Pay\Logger;
|
||||
use Yansongda\Pay\Rocket;
|
||||
use Yansongda\Supports\Collection;
|
||||
|
||||
use function Yansongda\Pay\filter_params;
|
||||
|
||||
class FormatPayloadBizContentPlugin implements PluginInterface
|
||||
{
|
||||
public function assembly(Rocket $rocket, Closure $next): Rocket
|
||||
{
|
||||
Logger::debug('[Alipay][FormatPayloadBizContentPlugin] 插件开始装载', ['rocket' => $rocket]);
|
||||
|
||||
$payload = $rocket->getPayload();
|
||||
|
||||
$rocket->setPayload(new Collection(array_merge(
|
||||
filter_params($payload->all(), fn ($k, $v) => '' !== $v && !is_null($v) && 'sign' != $k),
|
||||
['biz_content' => json_encode(filter_params($payload->get('biz_content', [])))]
|
||||
)));
|
||||
|
||||
Logger::info('[Alipay][FormatPayloadBizContentPlugin] 插件装载完毕', ['rocket' => $rocket]);
|
||||
|
||||
return $next($rocket);
|
||||
}
|
||||
}
|
@ -17,7 +17,7 @@ class SignPlugin implements PluginInterface
|
||||
{
|
||||
public function assembly(Rocket $rocket, Closure $next): Rocket
|
||||
{
|
||||
Logger::debug('[Alipay][Pay][Agreement][AddSignaturePlugin] 插件开始装载', ['rocket' => $rocket]);
|
||||
Logger::debug('[Alipay][Pay][Agreement][SignPlugin] 插件开始装载', ['rocket' => $rocket]);
|
||||
|
||||
$rocket->setDirection(ResponseDirection::class)
|
||||
->mergePayload([
|
||||
@ -25,7 +25,7 @@ class SignPlugin implements PluginInterface
|
||||
'biz_content' => $rocket->getParams(),
|
||||
]);
|
||||
|
||||
Logger::info('[Alipay][Pay][Agreement][AddSignaturePlugin] 插件装载完毕', ['rocket' => $rocket]);
|
||||
Logger::info('[Alipay][Pay][Agreement][SignPlugin] 插件装载完毕', ['rocket' => $rocket]);
|
||||
|
||||
return $next($rocket);
|
||||
}
|
||||
|
@ -2,7 +2,7 @@
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Yansongda\Pay\Plugin\Alipay\Pay\Wap;
|
||||
namespace Yansongda\Pay\Plugin\Alipay\Pay\H5;
|
||||
|
||||
use Closure;
|
||||
use Yansongda\Pay\Contract\PluginInterface;
|
@ -2,7 +2,7 @@
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Yansongda\Pay\Plugin\Alipay\Pay\Wap;
|
||||
namespace Yansongda\Pay\Plugin\Alipay\Pay\H5;
|
||||
|
||||
use Closure;
|
||||
use Yansongda\Pay\Contract\PluginInterface;
|
@ -2,7 +2,7 @@
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Yansongda\Pay\Plugin\Alipay\Pay\Wap;
|
||||
namespace Yansongda\Pay\Plugin\Alipay\Pay\H5;
|
||||
|
||||
use Closure;
|
||||
use Yansongda\Pay\Contract\PluginInterface;
|
@ -2,7 +2,7 @@
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Yansongda\Pay\Plugin\Alipay\Pay\Wap;
|
||||
namespace Yansongda\Pay\Plugin\Alipay\Pay\H5;
|
||||
|
||||
use Closure;
|
||||
use Yansongda\Pay\Contract\PluginInterface;
|
@ -2,7 +2,7 @@
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Yansongda\Pay\Plugin\Alipay\Pay\Wap;
|
||||
namespace Yansongda\Pay\Plugin\Alipay\Pay\H5;
|
||||
|
||||
use Closure;
|
||||
use Yansongda\Pay\Contract\PluginInterface;
|
@ -2,7 +2,7 @@
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Yansongda\Pay\Plugin\Alipay\Pay\Wap;
|
||||
namespace Yansongda\Pay\Plugin\Alipay\Pay\H5;
|
||||
|
||||
use Closure;
|
||||
use Yansongda\Pay\Contract\PluginInterface;
|
@ -106,7 +106,7 @@ class StartPlugin implements PluginInterface
|
||||
$path = $config['app_public_cert_path'] ?? null;
|
||||
|
||||
if (is_null($path)) {
|
||||
throw new InvalidConfigException(Exception::CONFIG_ALIPAY_INVALID, 'Missing Alipay Config -- [app_public_cert_path]');
|
||||
throw new InvalidConfigException(Exception::CONFIG_ALIPAY_INVALID, '配置异常: 缺少支付宝配置 -- [app_public_cert_path]');
|
||||
}
|
||||
|
||||
$ssl = openssl_x509_parse(get_public_cert($path));
|
||||
|
@ -14,6 +14,7 @@ use Yansongda\Pay\Exception\ServiceNotFoundException;
|
||||
use Yansongda\Pay\Logger;
|
||||
use Yansongda\Pay\Rocket;
|
||||
|
||||
use function Yansongda\Pay\get_alipay_config;
|
||||
use function Yansongda\Pay\should_do_http_request;
|
||||
use function Yansongda\Pay\verify_alipay_sign;
|
||||
|
||||
@ -42,10 +43,12 @@ class VerifySignaturePlugin implements PluginInterface
|
||||
$result = $destination->except('_sign')->all();
|
||||
|
||||
if ('' === $sign || empty($result)) {
|
||||
throw new InvalidSignException(Exception::SIGN_EMPTY, 'Verify Alipay Response Sign Failed: sign is empty', $destination);
|
||||
throw new InvalidSignException(Exception::SIGN_EMPTY, '签名异常: 验证支付宝签名失败-支付宝签名为空', $destination);
|
||||
}
|
||||
|
||||
verify_alipay_sign($rocket->getParams(), json_encode($result, JSON_UNESCAPED_UNICODE), $sign);
|
||||
$config = get_alipay_config($rocket->getParams());
|
||||
|
||||
verify_alipay_sign($config, json_encode($result, JSON_UNESCAPED_UNICODE), $sign);
|
||||
|
||||
Logger::info('[Alipay][VerifySignaturePlugin] 插件装载完毕', ['rocket' => $rocket]);
|
||||
|
||||
|
@ -56,7 +56,7 @@ class ParserPlugin implements PluginInterface
|
||||
$packer = is_string($packer) ? Pay::get($packer) : $packer;
|
||||
|
||||
if (!$packer instanceof PackerInterface) {
|
||||
throw new InvalidConfigException(Exception::CONFIG_PACKER_INVALID);
|
||||
throw new InvalidConfigException(Exception::CONFIG_PACKER_INVALID, '配置参数异常: 配置的 `PackerInterface` 未实现 `PackerInterface`');
|
||||
}
|
||||
|
||||
return $packer;
|
||||
|
@ -37,7 +37,7 @@ class CallbackPlugin implements PluginInterface
|
||||
$signature = $params['signature'] ?? false;
|
||||
|
||||
if (!$signature) {
|
||||
throw new InvalidSignException(Exception::SIGN_EMPTY, '', $params);
|
||||
throw new InvalidSignException(Exception::SIGN_EMPTY, '签名异常: 银联签名为空', $params);
|
||||
}
|
||||
|
||||
verify_unipay_sign($params, $rocket->getPayload()->sortKeys()->toString(), $signature);
|
||||
|
42
src/Plugin/Wechat/AddPayloadBodyPlugin.php
Normal file
42
src/Plugin/Wechat/AddPayloadBodyPlugin.php
Normal file
@ -0,0 +1,42 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Yansongda\Pay\Plugin\Wechat;
|
||||
|
||||
use Closure;
|
||||
use Yansongda\Pay\Contract\PluginInterface;
|
||||
use Yansongda\Pay\Logger;
|
||||
use Yansongda\Pay\Packer\JsonPacker;
|
||||
use Yansongda\Pay\Rocket;
|
||||
use Yansongda\Supports\Collection;
|
||||
|
||||
use function Yansongda\Pay\filter_params;
|
||||
|
||||
class AddPayloadBodyPlugin implements PluginInterface
|
||||
{
|
||||
protected JsonPacker $jsonPacker;
|
||||
|
||||
public function __construct(?JsonPacker $jsonPacker = null)
|
||||
{
|
||||
$this->jsonPacker = $jsonPacker ?? new JsonPacker();
|
||||
}
|
||||
|
||||
public function assembly(Rocket $rocket, Closure $next): Rocket
|
||||
{
|
||||
Logger::debug('[Wechat][AddPayloadBodyPlugin] 插件开始装载', ['rocket' => $rocket]);
|
||||
|
||||
$rocket->mergePayload(['_body' => $this->getBody($rocket->getPayload())]);
|
||||
|
||||
Logger::info('[Wechat][AddPayloadBodyPlugin] 插件装载完毕', ['rocket' => $rocket]);
|
||||
|
||||
return $next($rocket);
|
||||
}
|
||||
|
||||
protected function getBody(?Collection $payload): string
|
||||
{
|
||||
$actualPayload = filter_params($payload->all());
|
||||
|
||||
return empty($actualPayload) ? '' : $this->jsonPacker->pack($actualPayload);
|
||||
}
|
||||
}
|
99
src/Plugin/Wechat/AddPayloadSignaturePlugin.php
Normal file
99
src/Plugin/Wechat/AddPayloadSignaturePlugin.php
Normal file
@ -0,0 +1,99 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Yansongda\Pay\Plugin\Wechat;
|
||||
|
||||
use Closure;
|
||||
use Throwable;
|
||||
use Yansongda\Pay\Contract\PluginInterface;
|
||||
use Yansongda\Pay\Exception\ContainerException;
|
||||
use Yansongda\Pay\Exception\Exception;
|
||||
use Yansongda\Pay\Exception\InvalidConfigException;
|
||||
use Yansongda\Pay\Exception\InvalidParamsException;
|
||||
use Yansongda\Pay\Exception\ServiceNotFoundException;
|
||||
use Yansongda\Pay\Logger;
|
||||
use Yansongda\Pay\Rocket;
|
||||
use Yansongda\Supports\Collection;
|
||||
use Yansongda\Supports\Str;
|
||||
|
||||
use function Yansongda\Pay\get_public_cert;
|
||||
use function Yansongda\Pay\get_wechat_body;
|
||||
use function Yansongda\Pay\get_wechat_config;
|
||||
use function Yansongda\Pay\get_wechat_method;
|
||||
use function Yansongda\Pay\get_wechat_sign;
|
||||
use function Yansongda\Pay\get_wechat_url;
|
||||
|
||||
class AddPayloadSignaturePlugin implements PluginInterface
|
||||
{
|
||||
/**
|
||||
* @throws ContainerException
|
||||
* @throws InvalidConfigException
|
||||
* @throws InvalidParamsException
|
||||
* @throws ServiceNotFoundException
|
||||
* @throws Throwable 随机数生成失败
|
||||
*/
|
||||
public function assembly(Rocket $rocket, Closure $next): Rocket
|
||||
{
|
||||
Logger::debug('[Wechat][AddPayloadSignaturePlugin] 插件开始装载', ['rocket' => $rocket]);
|
||||
|
||||
$config = get_wechat_config($rocket->getParams());
|
||||
$payload = $rocket->getPayload();
|
||||
|
||||
$timestamp = time();
|
||||
$random = Str::random(32);
|
||||
$signContent = $this->getSignatureContent($config, $payload, $timestamp, $random);
|
||||
$signature = $this->getSignature($config, $timestamp, $random, $signContent);
|
||||
|
||||
$rocket->mergePayload(['_authorization' => $signature]);
|
||||
|
||||
Logger::info('[Wechat][AddPayloadSignaturePlugin] 插件装载完毕', ['rocket' => $rocket]);
|
||||
|
||||
return $next($rocket);
|
||||
}
|
||||
|
||||
/**
|
||||
* @throws InvalidParamsException
|
||||
*/
|
||||
protected function getSignatureContent(array $config, ?Collection $payload, int $timestamp, string $random): string
|
||||
{
|
||||
$url = get_wechat_url($config, $payload);
|
||||
$urlPath = parse_url($url, PHP_URL_PATH);
|
||||
$urlQuery = parse_url($url, PHP_URL_QUERY);
|
||||
|
||||
return get_wechat_method($payload)."\n".
|
||||
$urlPath.(empty($urlQuery) ? '' : '?'.$urlQuery)."\n".
|
||||
$timestamp."\n".
|
||||
$random."\n".
|
||||
get_wechat_body($payload)."\n";
|
||||
}
|
||||
|
||||
/**
|
||||
* @throws InvalidConfigException
|
||||
*/
|
||||
protected function getSignature(array $config, int $timestamp, string $random, string $contents): string
|
||||
{
|
||||
$mchPublicCertPath = $config['mch_public_cert_path'] ?? null;
|
||||
|
||||
if (empty($mchPublicCertPath)) {
|
||||
throw new InvalidConfigException(Exception::CONFIG_WECHAT_INVALID, '配置异常: 缺少微信配置 -- [mch_public_cert_path]');
|
||||
}
|
||||
|
||||
$ssl = openssl_x509_parse(get_public_cert($mchPublicCertPath));
|
||||
|
||||
if (empty($ssl['serialNumberHex'])) {
|
||||
throw new InvalidConfigException(Exception::CONFIG_WECHAT_INVALID, '配置异常: 解析微信配置 [mch_public_cert_path] 出错');
|
||||
}
|
||||
|
||||
$auth = sprintf(
|
||||
'mchid="%s",nonce_str="%s",timestamp="%d",serial_no="%s",signature="%s"',
|
||||
$config['mch_id'] ?? '',
|
||||
$random,
|
||||
$timestamp,
|
||||
$ssl['serialNumberHex'],
|
||||
get_wechat_sign($config, $contents),
|
||||
);
|
||||
|
||||
return 'WECHATPAY2-SHA256-RSA2048 '.$auth;
|
||||
}
|
||||
}
|
83
src/Plugin/Wechat/AddRadarPlugin.php
Normal file
83
src/Plugin/Wechat/AddRadarPlugin.php
Normal file
@ -0,0 +1,83 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Yansongda\Pay\Plugin\Wechat;
|
||||
|
||||
use Closure;
|
||||
use Yansongda\Pay\Contract\PluginInterface;
|
||||
use Yansongda\Pay\Exception\ContainerException;
|
||||
use Yansongda\Pay\Exception\Exception;
|
||||
use Yansongda\Pay\Exception\InvalidParamsException;
|
||||
use Yansongda\Pay\Exception\ServiceNotFoundException;
|
||||
use Yansongda\Pay\Logger;
|
||||
use Yansongda\Pay\Request;
|
||||
use Yansongda\Pay\Rocket;
|
||||
use Yansongda\Supports\Collection;
|
||||
|
||||
use function Yansongda\Pay\get_wechat_body;
|
||||
use function Yansongda\Pay\get_wechat_config;
|
||||
use function Yansongda\Pay\get_wechat_method;
|
||||
use function Yansongda\Pay\get_wechat_url;
|
||||
|
||||
class AddRadarPlugin implements PluginInterface
|
||||
{
|
||||
/**
|
||||
* @throws ContainerException
|
||||
* @throws InvalidParamsException
|
||||
* @throws ServiceNotFoundException
|
||||
*/
|
||||
public function assembly(Rocket $rocket, Closure $next): Rocket
|
||||
{
|
||||
Logger::debug('[Wechat][AddRadarPlugin] 插件开始装载', ['rocket' => $rocket]);
|
||||
|
||||
$params = $rocket->getParams();
|
||||
$payload = $rocket->getPayload();
|
||||
$config = get_wechat_config($params);
|
||||
|
||||
$rocket->setRadar(new Request(
|
||||
get_wechat_method($payload),
|
||||
get_wechat_url($config, $payload),
|
||||
$this->getHeaders($payload),
|
||||
get_wechat_body($payload),
|
||||
));
|
||||
|
||||
Logger::info('[Wechat][AddRadarPlugin] 插件装载完毕', ['rocket' => $rocket]);
|
||||
|
||||
return $next($rocket);
|
||||
}
|
||||
|
||||
/**
|
||||
* @throws InvalidParamsException
|
||||
*/
|
||||
protected function getHeaders(?Collection $payload): array
|
||||
{
|
||||
$authorization = $payload?->get('_authorization') ?? null;
|
||||
|
||||
if (empty($authorization)) {
|
||||
throw new InvalidParamsException(Exception::PARAMS_WECHAT_AUTHORIZATION_MISSING, '参数异常: 微信 `_authorization` 参数缺失:你可能用错插件顺序,应该先使用 `AddPayloadSignaturePlugin`, 再使用 `AddRadarPlugin`');
|
||||
}
|
||||
|
||||
$headers = [
|
||||
'Accept' => 'application/json, text/plain, application/x-gzip',
|
||||
'User-Agent' => 'yansongda/pay-v3',
|
||||
'Content-Type' => 'application/json; charset=utf-8',
|
||||
'Authorization' => $authorization,
|
||||
];
|
||||
|
||||
// 当 body 里有加密内容时,需要传递此参数用于微信区分
|
||||
if ($payload->has('_serial_no')) {
|
||||
$headers['Wechatpay-Serial'] = $payload->get('_serial_no');
|
||||
}
|
||||
|
||||
if ($payload->has('_content-type')) {
|
||||
$headers['Content-Type'] = $payload->get('_content-type');
|
||||
}
|
||||
|
||||
if ($payload->has('_accept')) {
|
||||
$headers['Accept'] = $payload->get('_accept');
|
||||
}
|
||||
|
||||
return $headers;
|
||||
}
|
||||
}
|
@ -9,16 +9,18 @@ use Psr\Http\Message\ServerRequestInterface;
|
||||
use Yansongda\Pay\Contract\PluginInterface;
|
||||
use Yansongda\Pay\Direction\NoHttpRequestDirection;
|
||||
use Yansongda\Pay\Exception\ContainerException;
|
||||
use Yansongda\Pay\Exception\DecryptException;
|
||||
use Yansongda\Pay\Exception\Exception;
|
||||
use Yansongda\Pay\Exception\InvalidConfigException;
|
||||
use Yansongda\Pay\Exception\InvalidParamsException;
|
||||
use Yansongda\Pay\Exception\InvalidResponseException;
|
||||
use Yansongda\Pay\Exception\InvalidSignException;
|
||||
use Yansongda\Pay\Exception\ServiceNotFoundException;
|
||||
use Yansongda\Pay\Logger;
|
||||
use Yansongda\Pay\Rocket;
|
||||
use Yansongda\Supports\Collection;
|
||||
|
||||
use function Yansongda\Pay\decrypt_wechat_resource;
|
||||
use function Yansongda\Pay\get_wechat_config;
|
||||
use function Yansongda\Pay\verify_wechat_sign;
|
||||
|
||||
class CallbackPlugin implements PluginInterface
|
||||
@ -26,28 +28,31 @@ class CallbackPlugin implements PluginInterface
|
||||
/**
|
||||
* @throws ContainerException
|
||||
* @throws InvalidConfigException
|
||||
* @throws ServiceNotFoundException
|
||||
* @throws InvalidResponseException
|
||||
* @throws InvalidParamsException
|
||||
* @throws InvalidSignException
|
||||
* @throws ServiceNotFoundException
|
||||
* @throws DecryptException
|
||||
*/
|
||||
public function assembly(Rocket $rocket, Closure $next): Rocket
|
||||
{
|
||||
Logger::debug('[wechat][CallbackPlugin] 插件开始装载', ['rocket' => $rocket]);
|
||||
Logger::debug('[Wechat][CallbackPlugin] 插件开始装载', ['rocket' => $rocket]);
|
||||
|
||||
$this->formatRequestAndParams($rocket);
|
||||
$this->init($rocket);
|
||||
|
||||
$params = $rocket->getParams();
|
||||
|
||||
/* @phpstan-ignore-next-line */
|
||||
verify_wechat_sign($rocket->getDestinationOrigin(), $rocket->getParams());
|
||||
verify_wechat_sign($rocket->getDestinationOrigin(), $params);
|
||||
|
||||
$body = json_decode((string) $rocket->getDestination()->getBody(), true);
|
||||
|
||||
$rocket->setDirection(NoHttpRequestDirection::class)->setPayload(new Collection($body));
|
||||
|
||||
$body['resource'] = decrypt_wechat_resource($body['resource'] ?? [], $rocket->getParams());
|
||||
$body['resource'] = decrypt_wechat_resource($body['resource'] ?? [], get_wechat_config($params));
|
||||
|
||||
$rocket->setDestination(new Collection($body));
|
||||
|
||||
Logger::info('[wechat][CallbackPlugin] 插件装载完毕', ['rocket' => $rocket]);
|
||||
Logger::info('[Wechat][CallbackPlugin] 插件装载完毕', ['rocket' => $rocket]);
|
||||
|
||||
return $next($rocket);
|
||||
}
|
||||
@ -55,16 +60,17 @@ class CallbackPlugin implements PluginInterface
|
||||
/**
|
||||
* @throws InvalidParamsException
|
||||
*/
|
||||
protected function formatRequestAndParams(Rocket $rocket): void
|
||||
protected function init(Rocket $rocket): void
|
||||
{
|
||||
$request = $rocket->getParams()['request'] ?? null;
|
||||
$request = $rocket->getParams()['_request'] ?? null;
|
||||
$params = $rocket->getParams()['_params'] ?? [];
|
||||
|
||||
if (!$request instanceof ServerRequestInterface) {
|
||||
throw new InvalidParamsException(Exception::PARAMS_REQUEST_EMPTY);
|
||||
throw new InvalidParamsException(Exception::PARAMS_CALLBACK_REQUEST_INVALID, '参数异常: 微信回调参数不正确');
|
||||
}
|
||||
|
||||
$rocket->setDestination(clone $request)
|
||||
->setDestinationOrigin($request)
|
||||
->setParams($rocket->getParams()['params'] ?? []);
|
||||
->setParams($params);
|
||||
}
|
||||
}
|
||||
|
@ -1,55 +0,0 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Yansongda\Pay\Plugin\Wechat\Ecommerce\Refund;
|
||||
|
||||
use Yansongda\Pay\Exception\ContainerException;
|
||||
use Yansongda\Pay\Exception\Exception;
|
||||
use Yansongda\Pay\Exception\InvalidParamsException;
|
||||
use Yansongda\Pay\Exception\ServiceNotFoundException;
|
||||
use Yansongda\Pay\Plugin\Wechat\GeneralPlugin;
|
||||
use Yansongda\Pay\Rocket;
|
||||
|
||||
use function Yansongda\Pay\get_wechat_config;
|
||||
|
||||
/**
|
||||
* @see https://pay.weixin.qq.com/wiki/doc/apiv3_partner/apis/chapter7_6_1.shtml
|
||||
*/
|
||||
class ApplyPlugin extends GeneralPlugin
|
||||
{
|
||||
/**
|
||||
* @throws InvalidParamsException
|
||||
*/
|
||||
protected function getUri(Rocket $rocket): string
|
||||
{
|
||||
throw new InvalidParamsException(Exception::PARAMS_PLUGIN_ONLY_SUPPORT_SERVICE_MODE);
|
||||
}
|
||||
|
||||
protected function getPartnerUri(Rocket $rocket): string
|
||||
{
|
||||
return 'v3/ecommerce/refunds/apply';
|
||||
}
|
||||
|
||||
/**
|
||||
* @throws ContainerException
|
||||
* @throws ServiceNotFoundException
|
||||
*/
|
||||
protected function doSomething(Rocket $rocket): void
|
||||
{
|
||||
$config = get_wechat_config($rocket->getParams());
|
||||
$payload = $rocket->getPayload();
|
||||
$key = $this->getConfigKey($rocket->getParams());
|
||||
|
||||
$wechatId = [
|
||||
'sub_mchid' => $payload->get('sub_mchid', $config['sub_mch_id'] ?? ''),
|
||||
'sp_appid' => $payload->get('sp_appid', $config[$key] ?? ''),
|
||||
];
|
||||
|
||||
if (!$payload->has('notify_url')) {
|
||||
$wechatId['notify_url'] = $config['notify_url'] ?? null;
|
||||
}
|
||||
|
||||
$rocket->mergePayload($wechatId);
|
||||
}
|
||||
}
|
@ -1,60 +0,0 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Yansongda\Pay\Plugin\Wechat\Ecommerce\Refund;
|
||||
|
||||
use Yansongda\Pay\Exception\ContainerException;
|
||||
use Yansongda\Pay\Exception\Exception;
|
||||
use Yansongda\Pay\Exception\InvalidParamsException;
|
||||
use Yansongda\Pay\Exception\ServiceNotFoundException;
|
||||
use Yansongda\Pay\Plugin\Wechat\GeneralPlugin;
|
||||
use Yansongda\Pay\Rocket;
|
||||
|
||||
use function Yansongda\Pay\get_wechat_config;
|
||||
|
||||
/**
|
||||
* @see https://pay.weixin.qq.com/wiki/doc/apiv3_partner/apis/chapter7_6_2.shtml
|
||||
*/
|
||||
class QueryPlugin extends GeneralPlugin
|
||||
{
|
||||
/**
|
||||
* @throws InvalidParamsException
|
||||
*/
|
||||
protected function getUri(Rocket $rocket): string
|
||||
{
|
||||
throw new InvalidParamsException(Exception::PARAMS_PLUGIN_ONLY_SUPPORT_SERVICE_MODE);
|
||||
}
|
||||
|
||||
/**
|
||||
* @throws ContainerException
|
||||
* @throws InvalidParamsException
|
||||
* @throws ServiceNotFoundException
|
||||
*/
|
||||
protected function getPartnerUri(Rocket $rocket): string
|
||||
{
|
||||
$payload = $rocket->getPayload();
|
||||
$config = get_wechat_config($rocket->getParams());
|
||||
$subMchId = $payload->get('sub_mchid', $config['sub_mch_id'] ?? '');
|
||||
|
||||
if ($payload->has('refund_id')) {
|
||||
return 'v3/ecommerce/refunds/id/'.$payload->get('refund_id').'?sub_mchid='.$subMchId;
|
||||
}
|
||||
|
||||
if ($payload->has('out_refund_no')) {
|
||||
return 'v3/ecommerce/refunds/out-refund-no/'.$payload->get('out_refund_no').'?sub_mchid='.$subMchId;
|
||||
}
|
||||
|
||||
throw new InvalidParamsException(Exception::PARAMS_NECESSARY_PARAMS_MISSING);
|
||||
}
|
||||
|
||||
protected function getMethod(): string
|
||||
{
|
||||
return 'GET';
|
||||
}
|
||||
|
||||
protected function doSomething(Rocket $rocket): void
|
||||
{
|
||||
$rocket->setPayload(null);
|
||||
}
|
||||
}
|
@ -1,56 +0,0 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Yansongda\Pay\Plugin\Wechat\Ecommerce\Refund;
|
||||
|
||||
use Yansongda\Pay\Exception\ContainerException;
|
||||
use Yansongda\Pay\Exception\Exception;
|
||||
use Yansongda\Pay\Exception\InvalidParamsException;
|
||||
use Yansongda\Pay\Exception\ServiceNotFoundException;
|
||||
use Yansongda\Pay\Plugin\Wechat\GeneralPlugin;
|
||||
use Yansongda\Pay\Rocket;
|
||||
|
||||
use function Yansongda\Pay\get_wechat_config;
|
||||
|
||||
/**
|
||||
* @see https://pay.weixin.qq.com/wiki/doc/apiv3_partner/apis/chapter7_6_5.shtml
|
||||
*/
|
||||
class QueryReturnAdvancePlugin extends GeneralPlugin
|
||||
{
|
||||
/**
|
||||
* @throws InvalidParamsException
|
||||
*/
|
||||
protected function getUri(Rocket $rocket): string
|
||||
{
|
||||
throw new InvalidParamsException(Exception::PARAMS_PLUGIN_ONLY_SUPPORT_SERVICE_MODE);
|
||||
}
|
||||
|
||||
/**
|
||||
* @throws ContainerException
|
||||
* @throws InvalidParamsException
|
||||
* @throws ServiceNotFoundException
|
||||
*/
|
||||
protected function getPartnerUri(Rocket $rocket): string
|
||||
{
|
||||
$payload = $rocket->getPayload();
|
||||
$config = get_wechat_config($rocket->getParams());
|
||||
$subMchId = $payload->get('sub_mchid', $config['sub_mch_id'] ?? '');
|
||||
|
||||
if (!$payload->has('refund_id')) {
|
||||
throw new InvalidParamsException(Exception::PARAMS_NECESSARY_PARAMS_MISSING);
|
||||
}
|
||||
|
||||
return 'v3/ecommerce/refunds/'.$payload->get('refund_id').'/return-advance?sub_mchid='.$subMchId;
|
||||
}
|
||||
|
||||
protected function getMethod(): string
|
||||
{
|
||||
return 'GET';
|
||||
}
|
||||
|
||||
protected function doSomething(Rocket $rocket): void
|
||||
{
|
||||
$rocket->setPayload(null);
|
||||
}
|
||||
}
|
@ -1,56 +0,0 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Yansongda\Pay\Plugin\Wechat\Ecommerce\Refund;
|
||||
|
||||
use Yansongda\Pay\Exception\ContainerException;
|
||||
use Yansongda\Pay\Exception\Exception;
|
||||
use Yansongda\Pay\Exception\InvalidParamsException;
|
||||
use Yansongda\Pay\Exception\ServiceNotFoundException;
|
||||
use Yansongda\Pay\Plugin\Wechat\GeneralPlugin;
|
||||
use Yansongda\Pay\Rocket;
|
||||
use Yansongda\Supports\Collection;
|
||||
|
||||
use function Yansongda\Pay\get_wechat_config;
|
||||
|
||||
/**
|
||||
* @see https://pay.weixin.qq.com/wiki/doc/apiv3_partner/apis/chapter7_6_4.shtml
|
||||
*/
|
||||
class ReturnAdvancePlugin extends GeneralPlugin
|
||||
{
|
||||
/**
|
||||
* @throws InvalidParamsException
|
||||
*/
|
||||
protected function getUri(Rocket $rocket): string
|
||||
{
|
||||
throw new InvalidParamsException(Exception::PARAMS_PLUGIN_ONLY_SUPPORT_SERVICE_MODE);
|
||||
}
|
||||
|
||||
/**
|
||||
* @throws InvalidParamsException
|
||||
*/
|
||||
protected function getPartnerUri(Rocket $rocket): string
|
||||
{
|
||||
$payload = $rocket->getPayload();
|
||||
|
||||
if (!$payload->has('refund_id')) {
|
||||
throw new InvalidParamsException(Exception::PARAMS_NECESSARY_PARAMS_MISSING);
|
||||
}
|
||||
|
||||
return 'v3/ecommerce/refunds/'.$payload->get('refund_id').'/return-advance';
|
||||
}
|
||||
|
||||
/**
|
||||
* @throws ContainerException
|
||||
* @throws ServiceNotFoundException
|
||||
*/
|
||||
protected function doSomething(Rocket $rocket): void
|
||||
{
|
||||
$config = get_wechat_config($rocket->getParams());
|
||||
|
||||
$rocket->setPayload(new Collection([
|
||||
'sub_mchid' => $rocket->getPayload()->get('sub_mchid', $config['sub_mch_id'] ?? ''),
|
||||
]));
|
||||
}
|
||||
}
|
52
src/Plugin/Wechat/Extend/Complaints/CompletePlugin.php
Normal file
52
src/Plugin/Wechat/Extend/Complaints/CompletePlugin.php
Normal file
@ -0,0 +1,52 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Yansongda\Pay\Plugin\Wechat\Extend\Complaints;
|
||||
|
||||
use Closure;
|
||||
use Yansongda\Pay\Contract\PluginInterface;
|
||||
use Yansongda\Pay\Exception\ContainerException;
|
||||
use Yansongda\Pay\Exception\Exception;
|
||||
use Yansongda\Pay\Exception\InvalidParamsException;
|
||||
use Yansongda\Pay\Exception\ServiceNotFoundException;
|
||||
use Yansongda\Pay\Logger;
|
||||
use Yansongda\Pay\Rocket;
|
||||
|
||||
use function Yansongda\Pay\get_wechat_config;
|
||||
|
||||
/**
|
||||
* @see https://pay.weixin.qq.com/docs/merchant/apis/consumer-complaint/complaints/complete-complaint-v2.html
|
||||
* @see https://pay.weixin.qq.com/docs/partner/apis/consumer-complaint/complaints/complete-complaint-v2.html
|
||||
*/
|
||||
class CompletePlugin implements PluginInterface
|
||||
{
|
||||
/**
|
||||
* @throws InvalidParamsException
|
||||
* @throws ContainerException
|
||||
* @throws ServiceNotFoundException
|
||||
*/
|
||||
public function assembly(Rocket $rocket, Closure $next): Rocket
|
||||
{
|
||||
Logger::debug('[Wechat][Extend][Complaints][CompletePlugin] 插件开始装载', ['rocket' => $rocket]);
|
||||
|
||||
$config = get_wechat_config($rocket->getParams());
|
||||
$payload = $rocket->getPayload();
|
||||
$complaintId = $payload?->get('complaint_id') ?? null;
|
||||
|
||||
if (empty($complaintId)) {
|
||||
throw new InvalidParamsException(Exception::PARAMS_NECESSARY_PARAMS_MISSING, '参数异常: 反馈处理完成,参数缺少 `complaint_id`');
|
||||
}
|
||||
|
||||
$rocket->setPayload([
|
||||
'_method' => 'POST',
|
||||
'_url' => 'v3/merchant-service/complaints-v2/'.$complaintId.'/complete',
|
||||
'_service_url' => 'v3/merchant-service/complaints-v2/'.$complaintId.'/complete',
|
||||
'complainted_mchid' => $payload->get('complainted_mchid') ?? $config['mch_id'],
|
||||
]);
|
||||
|
||||
Logger::info('[Wechat][Extend][Complaints][CompletePlugin] 插件装载完毕', ['rocket' => $rocket]);
|
||||
|
||||
return $next($rocket);
|
||||
}
|
||||
}
|
32
src/Plugin/Wechat/Extend/Complaints/DeleteCallbackPlugin.php
Normal file
32
src/Plugin/Wechat/Extend/Complaints/DeleteCallbackPlugin.php
Normal file
@ -0,0 +1,32 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Yansongda\Pay\Plugin\Wechat\Extend\Complaints;
|
||||
|
||||
use Closure;
|
||||
use Yansongda\Pay\Contract\PluginInterface;
|
||||
use Yansongda\Pay\Logger;
|
||||
use Yansongda\Pay\Rocket;
|
||||
|
||||
/**
|
||||
* @see https://pay.weixin.qq.com/docs/merchant/apis/consumer-complaint/complaint-notifications/delete-complaint-notifications.html
|
||||
* @see https://pay.weixin.qq.com/docs/partner/apis/consumer-complaint/complaint-notifications/delete-complaint-notifications.html
|
||||
*/
|
||||
class DeleteCallbackPlugin implements PluginInterface
|
||||
{
|
||||
public function assembly(Rocket $rocket, Closure $next): Rocket
|
||||
{
|
||||
Logger::debug('[Wechat][Extend][Complaints][DeleteCallbackPlugin] 插件开始装载', ['rocket' => $rocket]);
|
||||
|
||||
$rocket->setPayload([
|
||||
'_method' => 'DELETE',
|
||||
'_url' => 'v3/merchant-service/complaint-notifications',
|
||||
'_service_url' => 'v3/merchant-service/complaint-notifications',
|
||||
]);
|
||||
|
||||
Logger::info('[Wechat][Extend][Complaints][DeleteCallbackPlugin] 插件装载完毕', ['rocket' => $rocket]);
|
||||
|
||||
return $next($rocket);
|
||||
}
|
||||
}
|
32
src/Plugin/Wechat/Extend/Complaints/QueryCallbackPlugin.php
Normal file
32
src/Plugin/Wechat/Extend/Complaints/QueryCallbackPlugin.php
Normal file
@ -0,0 +1,32 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Yansongda\Pay\Plugin\Wechat\Extend\Complaints;
|
||||
|
||||
use Closure;
|
||||
use Yansongda\Pay\Contract\PluginInterface;
|
||||
use Yansongda\Pay\Logger;
|
||||
use Yansongda\Pay\Rocket;
|
||||
|
||||
/**
|
||||
* @see https://pay.weixin.qq.com/docs/merchant/apis/consumer-complaint/complaint-notifications/query-complaint-notifications.html
|
||||
* @see https://pay.weixin.qq.com/docs/partner/apis/consumer-complaint/complaint-notifications/query-complaint-notifications.html
|
||||
*/
|
||||
class QueryCallbackPlugin implements PluginInterface
|
||||
{
|
||||
public function assembly(Rocket $rocket, Closure $next): Rocket
|
||||
{
|
||||
Logger::debug('[Wechat][Extend][Complaints][QueryCallbackPlugin] 插件开始装载', ['rocket' => $rocket]);
|
||||
|
||||
$rocket->setPayload([
|
||||
'_method' => 'GET',
|
||||
'_url' => 'v3/merchant-service/complaint-notifications',
|
||||
'_service_url' => 'v3/merchant-service/complaint-notifications',
|
||||
]);
|
||||
|
||||
Logger::info('[Wechat][Extend][Complaints][QueryCallbackPlugin] 插件装载完毕', ['rocket' => $rocket]);
|
||||
|
||||
return $next($rocket);
|
||||
}
|
||||
}
|
43
src/Plugin/Wechat/Extend/Complaints/QueryDetailPlugin.php
Normal file
43
src/Plugin/Wechat/Extend/Complaints/QueryDetailPlugin.php
Normal file
@ -0,0 +1,43 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Yansongda\Pay\Plugin\Wechat\Extend\Complaints;
|
||||
|
||||
use Closure;
|
||||
use Yansongda\Pay\Contract\PluginInterface;
|
||||
use Yansongda\Pay\Exception\Exception;
|
||||
use Yansongda\Pay\Exception\InvalidParamsException;
|
||||
use Yansongda\Pay\Logger;
|
||||
use Yansongda\Pay\Rocket;
|
||||
|
||||
/**
|
||||
* @see https://pay.weixin.qq.com/docs/merchant/apis/consumer-complaint/complaints/query-complaint-v2.html
|
||||
* @see https://pay.weixin.qq.com/docs/partner/apis/consumer-complaint/complaints/query-complaint-v2.html
|
||||
*/
|
||||
class QueryDetailPlugin implements PluginInterface
|
||||
{
|
||||
/**
|
||||
* @throws InvalidParamsException
|
||||
*/
|
||||
public function assembly(Rocket $rocket, Closure $next): Rocket
|
||||
{
|
||||
Logger::debug('[Wechat][Extend][Complaints][QueryDetailPlugin] 插件开始装载', ['rocket' => $rocket]);
|
||||
|
||||
$complaintId = $rocket->getPayload()?->get('complaint_id') ?? null;
|
||||
|
||||
if (empty($complaintId)) {
|
||||
throw new InvalidParamsException(Exception::PARAMS_NECESSARY_PARAMS_MISSING, '参数异常: 查询投诉单详情,参数缺少 `complaint_id`');
|
||||
}
|
||||
|
||||
$rocket->setPayload([
|
||||
'_method' => 'GET',
|
||||
'_url' => 'v3/merchant-service/complaints-v2/'.$complaintId,
|
||||
'_service_url' => 'v3/merchant-service/complaints-v2/'.$complaintId,
|
||||
]);
|
||||
|
||||
Logger::info('[Wechat][Extend][Complaints][QueryDetailPlugin] 插件装载完毕', ['rocket' => $rocket]);
|
||||
|
||||
return $next($rocket);
|
||||
}
|
||||
}
|
43
src/Plugin/Wechat/Extend/Complaints/QueryImagePlugin.php
Normal file
43
src/Plugin/Wechat/Extend/Complaints/QueryImagePlugin.php
Normal file
@ -0,0 +1,43 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Yansongda\Pay\Plugin\Wechat\Extend\Complaints;
|
||||
|
||||
use Closure;
|
||||
use Yansongda\Pay\Contract\PluginInterface;
|
||||
use Yansongda\Pay\Exception\Exception;
|
||||
use Yansongda\Pay\Exception\InvalidParamsException;
|
||||
use Yansongda\Pay\Logger;
|
||||
use Yansongda\Pay\Rocket;
|
||||
|
||||
/**
|
||||
* @see https://pay.weixin.qq.com/docs/merchant/apis/consumer-complaint/images/query-images.html
|
||||
* @see https://pay.weixin.qq.com/docs/partner/apis/consumer-complaint/images/query-images.html
|
||||
*/
|
||||
class QueryImagePlugin implements PluginInterface
|
||||
{
|
||||
/**
|
||||
* @throws InvalidParamsException
|
||||
*/
|
||||
public function assembly(Rocket $rocket, Closure $next): Rocket
|
||||
{
|
||||
Logger::debug('[Wechat][Extend][Complaints][QueryImagePlugin] 插件开始装载', ['rocket' => $rocket]);
|
||||
|
||||
$mediaId = $rocket->getPayload()?->get('media_id') ?? null;
|
||||
|
||||
if (empty($mediaId)) {
|
||||
throw new InvalidParamsException(Exception::PARAMS_NECESSARY_PARAMS_MISSING, '参数异常: 图片请求接口,参数缺少 `media_id`');
|
||||
}
|
||||
|
||||
$rocket->setPayload([
|
||||
'_method' => 'GET',
|
||||
'_url' => 'v3/merchant-service/images/'.$mediaId,
|
||||
'_service_url' => 'v3/merchant-service/images/'.$mediaId,
|
||||
]);
|
||||
|
||||
Logger::info('[Wechat][Extend][Complaints][QueryImagePlugin] 插件装载完毕', ['rocket' => $rocket]);
|
||||
|
||||
return $next($rocket);
|
||||
}
|
||||
}
|
@ -0,0 +1,54 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Yansongda\Pay\Plugin\Wechat\Extend\Complaints;
|
||||
|
||||
use Closure;
|
||||
use Yansongda\Pay\Contract\PluginInterface;
|
||||
use Yansongda\Pay\Exception\Exception;
|
||||
use Yansongda\Pay\Exception\InvalidParamsException;
|
||||
use Yansongda\Pay\Logger;
|
||||
use Yansongda\Pay\Rocket;
|
||||
use Yansongda\Supports\Collection;
|
||||
|
||||
/**
|
||||
* @see https://pay.weixin.qq.com/docs/merchant/apis/consumer-complaint/complaints/query-negotiation-history-v2.html
|
||||
* @see https://pay.weixin.qq.com/docs/partner/apis/consumer-complaint/complaints/query-negotiation-history-v2.html
|
||||
*/
|
||||
class QueryNegotiationPlugin implements PluginInterface
|
||||
{
|
||||
/**
|
||||
* @throws InvalidParamsException
|
||||
*/
|
||||
public function assembly(Rocket $rocket, Closure $next): Rocket
|
||||
{
|
||||
Logger::debug('[Wechat][Extend][Complaints][QueryNegotiationPlugin] 插件开始装载', ['rocket' => $rocket]);
|
||||
|
||||
$payload = $rocket->getPayload();
|
||||
$complaintId = $payload?->get('complaint_id') ?? null;
|
||||
|
||||
if (empty($complaintId)) {
|
||||
throw new InvalidParamsException(Exception::PARAMS_NECESSARY_PARAMS_MISSING, '参数异常: 查询投诉单协商历史,参数缺少 `complaint_id`');
|
||||
}
|
||||
|
||||
$query = $this->normal($payload);
|
||||
|
||||
$rocket->setPayload([
|
||||
'_method' => 'GET',
|
||||
'_url' => 'v3/merchant-service/complaints-v2/'.$complaintId.'/negotiation-historys'.$query,
|
||||
'_service_url' => 'v3/merchant-service/complaints-v2/'.$complaintId.'/negotiation-historys'.$query,
|
||||
]);
|
||||
|
||||
Logger::info('[Wechat][Extend][Complaints][QueryNegotiationPlugin] 插件装载完毕', ['rocket' => $rocket]);
|
||||
|
||||
return $next($rocket);
|
||||
}
|
||||
|
||||
protected function normal(Collection $payload): string
|
||||
{
|
||||
$query = $payload->except('complaint_id')->query();
|
||||
|
||||
return empty($query) ? '' : '?'.$query;
|
||||
}
|
||||
}
|
45
src/Plugin/Wechat/Extend/Complaints/QueryPlugin.php
Normal file
45
src/Plugin/Wechat/Extend/Complaints/QueryPlugin.php
Normal file
@ -0,0 +1,45 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Yansongda\Pay\Plugin\Wechat\Extend\Complaints;
|
||||
|
||||
use Closure;
|
||||
use Yansongda\Pay\Contract\PluginInterface;
|
||||
use Yansongda\Pay\Exception\Exception;
|
||||
use Yansongda\Pay\Exception\InvalidParamsException;
|
||||
use Yansongda\Pay\Logger;
|
||||
use Yansongda\Pay\Rocket;
|
||||
|
||||
/**
|
||||
* @see https://pay.weixin.qq.com/docs/merchant/apis/consumer-complaint/complaints/list-complaints-v2.html
|
||||
* @see https://pay.weixin.qq.com/docs/partner/apis/consumer-complaint/complaints/list-complaints-v2.html
|
||||
*/
|
||||
class QueryPlugin implements PluginInterface
|
||||
{
|
||||
/**
|
||||
* @throws InvalidParamsException
|
||||
*/
|
||||
public function assembly(Rocket $rocket, Closure $next): Rocket
|
||||
{
|
||||
Logger::debug('[Wechat][Extend][Complaints][QueryPlugin] 插件开始装载', ['rocket' => $rocket]);
|
||||
|
||||
$payload = $rocket->getPayload();
|
||||
|
||||
if (is_null($payload)) {
|
||||
throw new InvalidParamsException(Exception::PARAMS_NECESSARY_PARAMS_MISSING, '参数异常: 查询投诉单列表,缺少必要参数');
|
||||
}
|
||||
|
||||
$query = $payload->query();
|
||||
|
||||
$rocket->setPayload([
|
||||
'_method' => 'GET',
|
||||
'_url' => 'v3/merchant-service/complaints-v2?'.$query,
|
||||
'_service_url' => 'v3/merchant-service/complaints-v2?'.$query,
|
||||
]);
|
||||
|
||||
Logger::info('[Wechat][Extend][Complaints][QueryPlugin] 插件装载完毕', ['rocket' => $rocket]);
|
||||
|
||||
return $next($rocket);
|
||||
}
|
||||
}
|
52
src/Plugin/Wechat/Extend/Complaints/ResponsePlugin.php
Normal file
52
src/Plugin/Wechat/Extend/Complaints/ResponsePlugin.php
Normal file
@ -0,0 +1,52 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Yansongda\Pay\Plugin\Wechat\Extend\Complaints;
|
||||
|
||||
use Closure;
|
||||
use Yansongda\Pay\Contract\PluginInterface;
|
||||
use Yansongda\Pay\Exception\ContainerException;
|
||||
use Yansongda\Pay\Exception\Exception;
|
||||
use Yansongda\Pay\Exception\InvalidParamsException;
|
||||
use Yansongda\Pay\Exception\ServiceNotFoundException;
|
||||
use Yansongda\Pay\Logger;
|
||||
use Yansongda\Pay\Rocket;
|
||||
|
||||
use function Yansongda\Pay\get_wechat_config;
|
||||
|
||||
/**
|
||||
* @see https://pay.weixin.qq.com/docs/merchant/apis/consumer-complaint/complaints/response-complaint-v2.html
|
||||
* @see https://pay.weixin.qq.com/docs/partner/apis/consumer-complaint/complaints/response-complaint-v2.html
|
||||
*/
|
||||
class ResponsePlugin implements PluginInterface
|
||||
{
|
||||
/**
|
||||
* @throws InvalidParamsException
|
||||
* @throws ContainerException
|
||||
* @throws ServiceNotFoundException
|
||||
*/
|
||||
public function assembly(Rocket $rocket, Closure $next): Rocket
|
||||
{
|
||||
Logger::debug('[Wechat][Extend][Complaints][ResponsePlugin] 插件开始装载', ['rocket' => $rocket]);
|
||||
|
||||
$config = get_wechat_config($rocket->getParams());
|
||||
$payload = $rocket->getPayload();
|
||||
$complaintId = $payload?->get('complaint_id') ?? null;
|
||||
|
||||
if (empty($complaintId)) {
|
||||
throw new InvalidParamsException(Exception::PARAMS_NECESSARY_PARAMS_MISSING, '参数异常: 回复用户,参数缺少 `complaint_id`');
|
||||
}
|
||||
|
||||
$rocket->mergePayload([
|
||||
'_method' => 'POST',
|
||||
'_url' => 'v3/merchant-service/complaints-v2/'.$complaintId.'/response',
|
||||
'_service_url' => 'v3/merchant-service/complaints-v2/'.$complaintId.'/response',
|
||||
'complainted_mchid' => $payload->get('complainted_mchid', $config['mch_id']),
|
||||
])->exceptPayload('complaint_id');
|
||||
|
||||
Logger::info('[Wechat][Extend][Complaints][ResponsePlugin] 插件装载完毕', ['rocket' => $rocket]);
|
||||
|
||||
return $next($rocket);
|
||||
}
|
||||
}
|
35
src/Plugin/Wechat/Extend/Complaints/SetCallbackPlugin.php
Normal file
35
src/Plugin/Wechat/Extend/Complaints/SetCallbackPlugin.php
Normal file
@ -0,0 +1,35 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Yansongda\Pay\Plugin\Wechat\Extend\Complaints;
|
||||
|
||||
use Closure;
|
||||
use Yansongda\Pay\Contract\PluginInterface;
|
||||
use Yansongda\Pay\Logger;
|
||||
use Yansongda\Pay\Rocket;
|
||||
|
||||
/**
|
||||
* @see https://pay.weixin.qq.com/docs/merchant/apis/consumer-complaint/complaint-notifications/create-complaint-notifications.html
|
||||
* @see https://pay.weixin.qq.com/docs/partner/apis/consumer-complaint/complaint-notifications/create-complaint-notifications.html
|
||||
*/
|
||||
class SetCallbackPlugin implements PluginInterface
|
||||
{
|
||||
public function assembly(Rocket $rocket, Closure $next): Rocket
|
||||
{
|
||||
Logger::debug('[Wechat][Extend][Complaints][SetCallbackPlugin] 插件开始装载', ['rocket' => $rocket]);
|
||||
|
||||
$payload = $rocket->getPayload();
|
||||
|
||||
$rocket->setPayload([
|
||||
'_method' => 'POST',
|
||||
'_url' => 'v3/merchant-service/complaint-notifications',
|
||||
'_service_url' => 'v3/merchant-service/complaint-notifications',
|
||||
'url' => $payload?->get('url', '') ?? '',
|
||||
]);
|
||||
|
||||
Logger::info('[Wechat][Extend][Complaints][SetCallbackPlugin] 插件装载完毕', ['rocket' => $rocket]);
|
||||
|
||||
return $next($rocket);
|
||||
}
|
||||
}
|
35
src/Plugin/Wechat/Extend/Complaints/UpdateCallbackPlugin.php
Normal file
35
src/Plugin/Wechat/Extend/Complaints/UpdateCallbackPlugin.php
Normal file
@ -0,0 +1,35 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Yansongda\Pay\Plugin\Wechat\Extend\Complaints;
|
||||
|
||||
use Closure;
|
||||
use Yansongda\Pay\Contract\PluginInterface;
|
||||
use Yansongda\Pay\Logger;
|
||||
use Yansongda\Pay\Rocket;
|
||||
|
||||
/**
|
||||
* @see https://pay.weixin.qq.com/docs/merchant/apis/consumer-complaint/complaint-notifications/update-complaint-notifications.html
|
||||
* @see https://pay.weixin.qq.com/docs/partner/apis/consumer-complaint/complaint-notifications/update-complaint-notifications.html
|
||||
*/
|
||||
class UpdateCallbackPlugin implements PluginInterface
|
||||
{
|
||||
public function assembly(Rocket $rocket, Closure $next): Rocket
|
||||
{
|
||||
Logger::debug('[Wechat][Extend][Complaints][UpdateCallbackPlugin] 插件开始装载', ['rocket' => $rocket]);
|
||||
|
||||
$payload = $rocket->getPayload();
|
||||
|
||||
$rocket->setPayload([
|
||||
'_method' => 'PUT',
|
||||
'_url' => 'v3/merchant-service/complaint-notifications',
|
||||
'_service_url' => 'v3/merchant-service/complaint-notifications',
|
||||
'url' => $payload?->get('url', '') ?? '',
|
||||
]);
|
||||
|
||||
Logger::info('[Wechat][Extend][Complaints][UpdateCallbackPlugin] 插件装载完毕', ['rocket' => $rocket]);
|
||||
|
||||
return $next($rocket);
|
||||
}
|
||||
}
|
43
src/Plugin/Wechat/Extend/Complaints/UpdateRefundPlugin.php
Normal file
43
src/Plugin/Wechat/Extend/Complaints/UpdateRefundPlugin.php
Normal file
@ -0,0 +1,43 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Yansongda\Pay\Plugin\Wechat\Extend\Complaints;
|
||||
|
||||
use Closure;
|
||||
use Yansongda\Pay\Contract\PluginInterface;
|
||||
use Yansongda\Pay\Exception\Exception;
|
||||
use Yansongda\Pay\Exception\InvalidParamsException;
|
||||
use Yansongda\Pay\Logger;
|
||||
use Yansongda\Pay\Rocket;
|
||||
|
||||
/**
|
||||
* @see https://pay.weixin.qq.com/docs/merchant/apis/consumer-complaint/complaints/update-refund-progress.html
|
||||
* @see https://pay.weixin.qq.com/docs/partner/apis/consumer-complaint/complaints/update-refund-progress.html
|
||||
*/
|
||||
class UpdateRefundPlugin implements PluginInterface
|
||||
{
|
||||
/**
|
||||
* @throws InvalidParamsException
|
||||
*/
|
||||
public function assembly(Rocket $rocket, Closure $next): Rocket
|
||||
{
|
||||
Logger::debug('[Wechat][Extend][Complaints][UpdateRefundPlugin] 插件开始装载', ['rocket' => $rocket]);
|
||||
|
||||
$complaintId = $rocket->getPayload()?->get('complaint_id') ?? null;
|
||||
|
||||
if (empty($complaintId)) {
|
||||
throw new InvalidParamsException(Exception::PARAMS_NECESSARY_PARAMS_MISSING, '参数异常: 更新退款审批结果,参数缺少 `complaint_id`');
|
||||
}
|
||||
|
||||
$rocket->mergePayload([
|
||||
'_method' => 'POST',
|
||||
'_url' => 'v3/merchant-service/complaints-v2/'.$complaintId.'/update-refund-progress',
|
||||
'_service_url' => 'v3/merchant-service/complaints-v2/'.$complaintId.'/update-refund-progress',
|
||||
])->exceptPayload('complaint_id');
|
||||
|
||||
Logger::info('[Wechat][Extend][Complaints][UpdateRefundPlugin] 插件装载完毕', ['rocket' => $rocket]);
|
||||
|
||||
return $next($rocket);
|
||||
}
|
||||
}
|
132
src/Plugin/Wechat/Extend/ProfitSharing/AddReceiverPlugin.php
Normal file
132
src/Plugin/Wechat/Extend/ProfitSharing/AddReceiverPlugin.php
Normal file
@ -0,0 +1,132 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Yansongda\Pay\Plugin\Wechat\Extend\ProfitSharing;
|
||||
|
||||
use Closure;
|
||||
use Yansongda\Pay\Contract\PluginInterface;
|
||||
use Yansongda\Pay\Exception\ContainerException;
|
||||
use Yansongda\Pay\Exception\DecryptException;
|
||||
use Yansongda\Pay\Exception\Exception;
|
||||
use Yansongda\Pay\Exception\InvalidConfigException;
|
||||
use Yansongda\Pay\Exception\InvalidParamsException;
|
||||
use Yansongda\Pay\Exception\ServiceNotFoundException;
|
||||
use Yansongda\Pay\Logger;
|
||||
use Yansongda\Pay\Pay;
|
||||
use Yansongda\Pay\Rocket;
|
||||
use Yansongda\Supports\Collection;
|
||||
|
||||
use function Yansongda\Pay\encrypt_wechat_contents;
|
||||
use function Yansongda\Pay\get_wechat_config;
|
||||
use function Yansongda\Pay\get_wechat_public_key;
|
||||
use function Yansongda\Pay\get_wechat_serial_no;
|
||||
use function Yansongda\Pay\get_wechat_type_key;
|
||||
|
||||
/**
|
||||
* @see https://pay.weixin.qq.com/docs/merchant/apis/profit-sharing/receivers/add-receiver.html
|
||||
* @see https://pay.weixin.qq.com/docs/partner/apis/profit-sharing/receivers/add-receiver.html
|
||||
*/
|
||||
class AddReceiverPlugin implements PluginInterface
|
||||
{
|
||||
/**
|
||||
* @throws ContainerException
|
||||
* @throws DecryptException
|
||||
* @throws InvalidConfigException
|
||||
* @throws InvalidParamsException
|
||||
* @throws ServiceNotFoundException
|
||||
*/
|
||||
public function assembly(Rocket $rocket, Closure $next): Rocket
|
||||
{
|
||||
Logger::debug('[Wechat][Extend][ProfitSharing][AddReceiverPlugin] 插件开始装载', ['rocket' => $rocket]);
|
||||
|
||||
$params = $rocket->getParams();
|
||||
$config = get_wechat_config($params);
|
||||
$payload = $rocket->getPayload();
|
||||
|
||||
if (is_null($payload)) {
|
||||
throw new InvalidParamsException(Exception::PARAMS_NECESSARY_PARAMS_MISSING, '参数异常: 缺少分账参数');
|
||||
}
|
||||
|
||||
if (Pay::MODE_SERVICE === ($config['mode'] ?? Pay::MODE_NORMAL)) {
|
||||
$data = $this->service($payload, $params, $config);
|
||||
}
|
||||
|
||||
$rocket->mergePayload(array_merge(
|
||||
[
|
||||
'_method' => 'POST',
|
||||
'_url' => 'v3/profitsharing/receivers/add',
|
||||
'_service_url' => 'v3/profitsharing/receivers/add',
|
||||
],
|
||||
$data ?? $this->normal($payload, $params, $config),
|
||||
));
|
||||
|
||||
Logger::info('[Wechat][Extend][ProfitSharing][AddReceiverPlugin] 插件装载完毕', ['rocket' => $rocket]);
|
||||
|
||||
return $next($rocket);
|
||||
}
|
||||
|
||||
/**
|
||||
* @throws ContainerException
|
||||
* @throws DecryptException
|
||||
* @throws InvalidConfigException
|
||||
* @throws InvalidParamsException
|
||||
* @throws ServiceNotFoundException
|
||||
*/
|
||||
protected function normal(Collection $payload, array $params, array $config): array
|
||||
{
|
||||
$data = [
|
||||
'appid' => $config[get_wechat_type_key($params)] ?? '',
|
||||
];
|
||||
|
||||
if (!$payload->has('name')) {
|
||||
return $data;
|
||||
}
|
||||
|
||||
return array_merge($data, $this->encryptSensitiveData($params, $config, $payload));
|
||||
}
|
||||
|
||||
/**
|
||||
* @throws ContainerException
|
||||
* @throws DecryptException
|
||||
* @throws InvalidConfigException
|
||||
* @throws InvalidParamsException
|
||||
* @throws ServiceNotFoundException
|
||||
*/
|
||||
protected function service(Collection $payload, array $params, array $config): array
|
||||
{
|
||||
$wechatTypeKey = get_wechat_type_key($params);
|
||||
|
||||
$data = [
|
||||
'sub_mchid' => $payload->get('sub_mchid', $config['sub_mch_id'] ?? ''),
|
||||
'appid' => $config[$wechatTypeKey] ?? '',
|
||||
];
|
||||
|
||||
if ('PERSONAL_SUB_OPENID' === $payload->get('type')) {
|
||||
$data['sub_appid'] = $config['sub_'.$wechatTypeKey] ?? '';
|
||||
}
|
||||
|
||||
if (!$payload->has('name')) {
|
||||
return $data;
|
||||
}
|
||||
|
||||
return array_merge($data, $this->encryptSensitiveData($params, $config, $payload));
|
||||
}
|
||||
|
||||
/**
|
||||
* @throws ContainerException
|
||||
* @throws DecryptException
|
||||
* @throws InvalidConfigException
|
||||
* @throws InvalidParamsException
|
||||
* @throws ServiceNotFoundException
|
||||
*/
|
||||
protected function encryptSensitiveData(array $params, array $config, Collection $payload): array
|
||||
{
|
||||
$data['_serial_no'] = get_wechat_serial_no($params);
|
||||
$publicKey = get_wechat_public_key($config, $data['_serial_no']);
|
||||
|
||||
$data['name'] = encrypt_wechat_contents($payload->get('name'), $publicKey);
|
||||
|
||||
return $data;
|
||||
}
|
||||
}
|
134
src/Plugin/Wechat/Extend/ProfitSharing/CreatePlugin.php
Normal file
134
src/Plugin/Wechat/Extend/ProfitSharing/CreatePlugin.php
Normal file
@ -0,0 +1,134 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Yansongda\Pay\Plugin\Wechat\Extend\ProfitSharing;
|
||||
|
||||
use Closure;
|
||||
use Yansongda\Pay\Contract\PluginInterface;
|
||||
use Yansongda\Pay\Exception\ContainerException;
|
||||
use Yansongda\Pay\Exception\DecryptException;
|
||||
use Yansongda\Pay\Exception\Exception;
|
||||
use Yansongda\Pay\Exception\InvalidConfigException;
|
||||
use Yansongda\Pay\Exception\InvalidParamsException;
|
||||
use Yansongda\Pay\Exception\ServiceNotFoundException;
|
||||
use Yansongda\Pay\Logger;
|
||||
use Yansongda\Pay\Pay;
|
||||
use Yansongda\Pay\Rocket;
|
||||
use Yansongda\Supports\Collection;
|
||||
|
||||
use function Yansongda\Pay\encrypt_wechat_contents;
|
||||
use function Yansongda\Pay\get_wechat_config;
|
||||
use function Yansongda\Pay\get_wechat_public_key;
|
||||
use function Yansongda\Pay\get_wechat_serial_no;
|
||||
use function Yansongda\Pay\get_wechat_type_key;
|
||||
|
||||
/**
|
||||
* @see https://pay.weixin.qq.com/docs/merchant/apis/profit-sharing/orders/create-order.html
|
||||
* @see https://pay.weixin.qq.com/docs/partner/apis/profit-sharing/orders/create-order.html
|
||||
*/
|
||||
class CreatePlugin implements PluginInterface
|
||||
{
|
||||
/**
|
||||
* @throws ContainerException
|
||||
* @throws DecryptException
|
||||
* @throws InvalidConfigException
|
||||
* @throws InvalidParamsException
|
||||
* @throws ServiceNotFoundException
|
||||
*/
|
||||
public function assembly(Rocket $rocket, Closure $next): Rocket
|
||||
{
|
||||
Logger::debug('[Wechat][Extend][ProfitSharing][CreatePlugin] 插件开始装载', ['rocket' => $rocket]);
|
||||
|
||||
$params = $rocket->getParams();
|
||||
$config = get_wechat_config($params);
|
||||
$payload = $rocket->getPayload();
|
||||
|
||||
if (is_null($payload)) {
|
||||
throw new InvalidParamsException(Exception::PARAMS_NECESSARY_PARAMS_MISSING, '参数异常: 缺少分账参数');
|
||||
}
|
||||
|
||||
if (Pay::MODE_SERVICE === ($config['mode'] ?? Pay::MODE_NORMAL)) {
|
||||
$data = $this->service($payload, $params, $config);
|
||||
}
|
||||
|
||||
$rocket->mergePayload(array_merge(
|
||||
[
|
||||
'_method' => 'POST',
|
||||
'_url' => 'v3/profitsharing/orders',
|
||||
'_service_url' => 'v3/profitsharing/orders',
|
||||
],
|
||||
$data ?? $this->normal($payload, $params, $config),
|
||||
));
|
||||
|
||||
Logger::info('[Wechat][Extend][ProfitSharing][CreatePlugin] 插件装载完毕', ['rocket' => $rocket]);
|
||||
|
||||
return $next($rocket);
|
||||
}
|
||||
|
||||
/**
|
||||
* @throws ContainerException
|
||||
* @throws DecryptException
|
||||
* @throws InvalidConfigException
|
||||
* @throws InvalidParamsException
|
||||
* @throws ServiceNotFoundException
|
||||
*/
|
||||
protected function normal(Collection $payload, array $params, array $config): array
|
||||
{
|
||||
$data = [
|
||||
'appid' => $config[get_wechat_type_key($params)] ?? '',
|
||||
];
|
||||
|
||||
if (!$payload->has('receivers.0.name')) {
|
||||
return $data;
|
||||
}
|
||||
|
||||
return array_merge($data, $this->encryptSensitiveData($params, $config, $payload));
|
||||
}
|
||||
|
||||
/**
|
||||
* @throws ContainerException
|
||||
* @throws DecryptException
|
||||
* @throws InvalidConfigException
|
||||
* @throws InvalidParamsException
|
||||
* @throws ServiceNotFoundException
|
||||
*/
|
||||
protected function service(Collection $payload, array $params, array $config): array
|
||||
{
|
||||
$wechatTypeKey = get_wechat_type_key($params);
|
||||
|
||||
$data = [
|
||||
'sub_mchid' => $payload->get('sub_mchid', $config['sub_mch_id'] ?? ''),
|
||||
'appid' => $config[$wechatTypeKey] ?? '',
|
||||
];
|
||||
|
||||
if ('PERSONAL_SUB_OPENID' === $payload->get('receivers.0.type')) {
|
||||
$data['sub_appid'] = $config['sub_'.$wechatTypeKey] ?? '';
|
||||
}
|
||||
|
||||
if (!$payload->has('receivers.0.name')) {
|
||||
return $data;
|
||||
}
|
||||
|
||||
return array_merge($data, $this->encryptSensitiveData($params, $config, $payload));
|
||||
}
|
||||
|
||||
/**
|
||||
* @throws ContainerException
|
||||
* @throws DecryptException
|
||||
* @throws InvalidConfigException
|
||||
* @throws InvalidParamsException
|
||||
* @throws ServiceNotFoundException
|
||||
*/
|
||||
protected function encryptSensitiveData(array $params, array $config, Collection $payload): array
|
||||
{
|
||||
$data['_serial_no'] = get_wechat_serial_no($params);
|
||||
$publicKey = get_wechat_public_key($config, $data['_serial_no']);
|
||||
|
||||
foreach ($payload->get('receivers', []) as $key => $list) {
|
||||
$data['receivers'][$key]['name'] = encrypt_wechat_contents($list['name'], $publicKey);
|
||||
}
|
||||
|
||||
return $data;
|
||||
}
|
||||
}
|
@ -0,0 +1,84 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Yansongda\Pay\Plugin\Wechat\Extend\ProfitSharing;
|
||||
|
||||
use Closure;
|
||||
use Yansongda\Pay\Contract\PluginInterface;
|
||||
use Yansongda\Pay\Exception\ContainerException;
|
||||
use Yansongda\Pay\Exception\Exception;
|
||||
use Yansongda\Pay\Exception\InvalidParamsException;
|
||||
use Yansongda\Pay\Exception\ServiceNotFoundException;
|
||||
use Yansongda\Pay\Logger;
|
||||
use Yansongda\Pay\Pay;
|
||||
use Yansongda\Pay\Rocket;
|
||||
use Yansongda\Supports\Collection;
|
||||
|
||||
use function Yansongda\Pay\get_wechat_config;
|
||||
use function Yansongda\Pay\get_wechat_type_key;
|
||||
|
||||
/**
|
||||
* @see https://pay.weixin.qq.com/docs/merchant/apis/profit-sharing/receivers/delete-receiver.html
|
||||
* @see https://pay.weixin.qq.com/docs/partner/apis/profit-sharing/receivers/delete-receiver.html
|
||||
*/
|
||||
class DeleteReceiverPlugin implements PluginInterface
|
||||
{
|
||||
/**
|
||||
* @throws ContainerException
|
||||
* @throws InvalidParamsException
|
||||
* @throws ServiceNotFoundException
|
||||
*/
|
||||
public function assembly(Rocket $rocket, Closure $next): Rocket
|
||||
{
|
||||
Logger::debug('[Wechat][Extend][ProfitSharing][DeleteReceiverPlugin] 插件开始装载', ['rocket' => $rocket]);
|
||||
|
||||
$params = $rocket->getParams();
|
||||
$config = get_wechat_config($params);
|
||||
$payload = $rocket->getPayload();
|
||||
|
||||
if (is_null($payload)) {
|
||||
throw new InvalidParamsException(Exception::PARAMS_NECESSARY_PARAMS_MISSING, '参数异常: 缺少分账参数');
|
||||
}
|
||||
|
||||
if (Pay::MODE_SERVICE === ($config['mode'] ?? Pay::MODE_NORMAL)) {
|
||||
$data = $this->service($payload, $params, $config);
|
||||
}
|
||||
|
||||
$rocket->mergePayload(array_merge(
|
||||
[
|
||||
'_method' => 'POST',
|
||||
'_url' => 'v3/profitsharing/receivers/delete',
|
||||
'_service_url' => 'v3/profitsharing/receivers/delete',
|
||||
],
|
||||
$data ?? $this->normal($params, $config),
|
||||
));
|
||||
|
||||
Logger::info('[Wechat][Extend][ProfitSharing][DeleteReceiverPlugin] 插件装载完毕', ['rocket' => $rocket]);
|
||||
|
||||
return $next($rocket);
|
||||
}
|
||||
|
||||
protected function normal(array $params, array $config): array
|
||||
{
|
||||
return [
|
||||
'appid' => $config[get_wechat_type_key($params)] ?? '',
|
||||
];
|
||||
}
|
||||
|
||||
protected function service(Collection $payload, array $params, array $config): array
|
||||
{
|
||||
$wechatTypeKEY = get_wechat_type_key($params);
|
||||
|
||||
$data = [
|
||||
'sub_mchid' => $payload->get('sub_mchid', $config['sub_mch_id'] ?? ''),
|
||||
'appid' => $config[$wechatTypeKEY] ?? '',
|
||||
];
|
||||
|
||||
if ('PERSONAL_SUB_OPENID' === $payload->get('type')) {
|
||||
$data['sub_appid'] = $config['sub_'.$wechatTypeKEY] ?? '';
|
||||
}
|
||||
|
||||
return $data;
|
||||
}
|
||||
}
|
@ -0,0 +1,43 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Yansongda\Pay\Plugin\Wechat\Extend\ProfitSharing;
|
||||
|
||||
use Closure;
|
||||
use Yansongda\Pay\Contract\PluginInterface;
|
||||
use Yansongda\Pay\Exception\Exception;
|
||||
use Yansongda\Pay\Exception\InvalidParamsException;
|
||||
use Yansongda\Pay\Logger;
|
||||
use Yansongda\Pay\Rocket;
|
||||
|
||||
/**
|
||||
* @see https://pay.weixin.qq.com/docs/merchant/apis/profit-sharing/download-bill.html
|
||||
* @see https://pay.weixin.qq.com/docs/partner/apis/profit-sharing/download-bill.html
|
||||
*/
|
||||
class DownloadBillPlugin implements PluginInterface
|
||||
{
|
||||
/**
|
||||
* @throws InvalidParamsException
|
||||
*/
|
||||
public function assembly(Rocket $rocket, Closure $next): Rocket
|
||||
{
|
||||
Logger::debug('[Wechat][Extend][ProfitSharing][DownloadBillPlugin] 插件开始装载', ['rocket' => $rocket]);
|
||||
|
||||
$downloadUrl = $rocket->getPayload()?->get('download_url') ?? null;
|
||||
|
||||
if (empty($downloadUrl)) {
|
||||
throw new InvalidParamsException(Exception::PARAMS_NECESSARY_PARAMS_MISSING, '参数异常: 下载电子回单,参数缺少 `download_url`');
|
||||
}
|
||||
|
||||
$rocket->setPayload([
|
||||
'_method' => 'GET',
|
||||
'_url' => $downloadUrl,
|
||||
'_service_url' => $downloadUrl,
|
||||
]);
|
||||
|
||||
Logger::info('[Wechat][Extend][ProfitSharing][DownloadBillPlugin] 插件装载完毕', ['rocket' => $rocket]);
|
||||
|
||||
return $next($rocket);
|
||||
}
|
||||
}
|
@ -0,0 +1,43 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Yansongda\Pay\Plugin\Wechat\Extend\ProfitSharing;
|
||||
|
||||
use Closure;
|
||||
use Yansongda\Pay\Contract\PluginInterface;
|
||||
use Yansongda\Pay\Exception\Exception;
|
||||
use Yansongda\Pay\Exception\InvalidParamsException;
|
||||
use Yansongda\Pay\Logger;
|
||||
use Yansongda\Pay\Rocket;
|
||||
|
||||
/**
|
||||
* @see https://pay.weixin.qq.com/docs/merchant/apis/profit-sharing/transactions/query-order-amount.html
|
||||
* @see https://pay.weixin.qq.com/docs/partner/apis/profit-sharing/transactions/query-order-amount.html
|
||||
*/
|
||||
class QueryAmountsPlugin implements PluginInterface
|
||||
{
|
||||
/**
|
||||
* @throws InvalidParamsException
|
||||
*/
|
||||
public function assembly(Rocket $rocket, Closure $next): Rocket
|
||||
{
|
||||
Logger::debug('[Wechat][Extend][ProfitSharing][QueryAmountsPlugin] 插件开始装载', ['rocket' => $rocket]);
|
||||
|
||||
$transactionId = $rocket->getPayload()?->get('transaction_id');
|
||||
|
||||
if (is_null($transactionId)) {
|
||||
throw new InvalidParamsException(Exception::PARAMS_NECESSARY_PARAMS_MISSING, '参数异常: 查询剩余待分金额,参数缺少 `transaction_id`');
|
||||
}
|
||||
|
||||
$rocket->setPayload([
|
||||
'_method' => 'GET',
|
||||
'_url' => 'v3/profitsharing/transactions/'.$transactionId.'/amounts',
|
||||
'_service_url' => 'v3/profitsharing/transactions/'.$transactionId.'/amounts',
|
||||
]);
|
||||
|
||||
Logger::info('[Wechat][Extend][ProfitSharing][QueryAmountsPlugin] 插件装载完毕', ['rocket' => $rocket]);
|
||||
|
||||
return $next($rocket);
|
||||
}
|
||||
}
|
@ -0,0 +1,50 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Yansongda\Pay\Plugin\Wechat\Extend\ProfitSharing;
|
||||
|
||||
use Closure;
|
||||
use Yansongda\Pay\Contract\PluginInterface;
|
||||
use Yansongda\Pay\Exception\ContainerException;
|
||||
use Yansongda\Pay\Exception\Exception;
|
||||
use Yansongda\Pay\Exception\InvalidParamsException;
|
||||
use Yansongda\Pay\Exception\ServiceNotFoundException;
|
||||
use Yansongda\Pay\Logger;
|
||||
use Yansongda\Pay\Pay;
|
||||
use Yansongda\Pay\Rocket;
|
||||
|
||||
use function Yansongda\Pay\get_wechat_config;
|
||||
|
||||
/**
|
||||
* @see https://pay.weixin.qq.com/docs/partner/apis/profit-sharing/merchants/query-merchant-ratio.html
|
||||
*/
|
||||
class QueryMerchantConfigsPlugin implements PluginInterface
|
||||
{
|
||||
/**
|
||||
* @throws ContainerException
|
||||
* @throws InvalidParamsException
|
||||
* @throws ServiceNotFoundException
|
||||
*/
|
||||
public function assembly(Rocket $rocket, Closure $next): Rocket
|
||||
{
|
||||
Logger::debug('[Wechat][Extend][ProfitSharing][QueryMerchantConfigsPlugin] 插件开始装载', ['rocket' => $rocket]);
|
||||
|
||||
$payload = $rocket->getPayload();
|
||||
$config = get_wechat_config($rocket->getParams());
|
||||
$subMchId = $payload?->get('sub_mch_id') ?? $config['sub_mch_id'] ?? 'null';
|
||||
|
||||
if (Pay::MODE_NORMAL === ($config['mode'] ?? Pay::MODE_NORMAL)) {
|
||||
throw new InvalidParamsException(Exception::PARAMS_PLUGIN_ONLY_SUPPORT_SERVICE_MODE, '参数异常: 查询最大分账比例,只支持服务商模式,当前配置为普通商户模式');
|
||||
}
|
||||
|
||||
$rocket->setPayload([
|
||||
'_method' => 'GET',
|
||||
'_service_url' => 'v3/profitsharing/merchant-configs/'.$subMchId,
|
||||
]);
|
||||
|
||||
Logger::info('[Wechat][Extend][ProfitSharing][QueryMerchantConfigsPlugin] 插件装载完毕', ['rocket' => $rocket]);
|
||||
|
||||
return $next($rocket);
|
||||
}
|
||||
}
|
53
src/Plugin/Wechat/Extend/ProfitSharing/QueryPlugin.php
Normal file
53
src/Plugin/Wechat/Extend/ProfitSharing/QueryPlugin.php
Normal file
@ -0,0 +1,53 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Yansongda\Pay\Plugin\Wechat\Extend\ProfitSharing;
|
||||
|
||||
use Closure;
|
||||
use Yansongda\Pay\Contract\PluginInterface;
|
||||
use Yansongda\Pay\Exception\ContainerException;
|
||||
use Yansongda\Pay\Exception\Exception;
|
||||
use Yansongda\Pay\Exception\InvalidParamsException;
|
||||
use Yansongda\Pay\Exception\ServiceNotFoundException;
|
||||
use Yansongda\Pay\Logger;
|
||||
use Yansongda\Pay\Rocket;
|
||||
|
||||
use function Yansongda\Pay\get_wechat_config;
|
||||
|
||||
/**
|
||||
* @see https://pay.weixin.qq.com/docs/merchant/apis/profit-sharing/orders/query-order.html
|
||||
* @see https://pay.weixin.qq.com/docs/partner/apis/profit-sharing/orders/query-order.html
|
||||
*/
|
||||
class QueryPlugin implements PluginInterface
|
||||
{
|
||||
/**
|
||||
* @throws ContainerException
|
||||
* @throws InvalidParamsException
|
||||
* @throws ServiceNotFoundException
|
||||
*/
|
||||
public function assembly(Rocket $rocket, Closure $next): Rocket
|
||||
{
|
||||
Logger::debug('[Wechat][Extend][ProfitSharing][QueryPlugin] 插件开始装载', ['rocket' => $rocket]);
|
||||
|
||||
$config = get_wechat_config($rocket->getParams());
|
||||
$payload = $rocket->getPayload();
|
||||
$outOrderNo = $payload?->get('out_order_no') ?? null;
|
||||
$transactionId = $payload?->get('transaction_id') ?? null;
|
||||
$subMchId = $payload?->get('sub_mchid') ?? $config['sub_mch_id'] ?? 'null';
|
||||
|
||||
if (empty($outOrderNo) || empty($transactionId)) {
|
||||
throw new InvalidParamsException(Exception::PARAMS_NECESSARY_PARAMS_MISSING, '参数异常: 查询分账结果, 缺少必要参数 `out_order_no`, `transaction_id`');
|
||||
}
|
||||
|
||||
$rocket->setPayload([
|
||||
'_method' => 'GET',
|
||||
'_url' => 'v3/profitsharing/orders/'.$outOrderNo.'?transaction_id='.$transactionId,
|
||||
'_service_url' => 'v3/profitsharing/orders/'.$outOrderNo.'?sub_mchid='.$subMchId.'&transaction_id='.$transactionId,
|
||||
]);
|
||||
|
||||
Logger::info('[Wechat][Extend][ProfitSharing][QueryPlugin] 插件装载完毕', ['rocket' => $rocket]);
|
||||
|
||||
return $next($rocket);
|
||||
}
|
||||
}
|
53
src/Plugin/Wechat/Extend/ProfitSharing/QueryReturnPlugin.php
Normal file
53
src/Plugin/Wechat/Extend/ProfitSharing/QueryReturnPlugin.php
Normal file
@ -0,0 +1,53 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Yansongda\Pay\Plugin\Wechat\Extend\ProfitSharing;
|
||||
|
||||
use Closure;
|
||||
use Yansongda\Pay\Contract\PluginInterface;
|
||||
use Yansongda\Pay\Exception\ContainerException;
|
||||
use Yansongda\Pay\Exception\Exception;
|
||||
use Yansongda\Pay\Exception\InvalidParamsException;
|
||||
use Yansongda\Pay\Exception\ServiceNotFoundException;
|
||||
use Yansongda\Pay\Logger;
|
||||
use Yansongda\Pay\Rocket;
|
||||
|
||||
use function Yansongda\Pay\get_wechat_config;
|
||||
|
||||
/**
|
||||
* @see https://pay.weixin.qq.com/docs/merchant/apis/profit-sharing/return-orders/query-return-order.html
|
||||
* @see https://pay.weixin.qq.com/docs/partner/apis/profit-sharing/return-orders/query-return-order.html
|
||||
*/
|
||||
class QueryReturnPlugin implements PluginInterface
|
||||
{
|
||||
/**
|
||||
* @throws ContainerException
|
||||
* @throws InvalidParamsException
|
||||
* @throws ServiceNotFoundException
|
||||
*/
|
||||
public function assembly(Rocket $rocket, Closure $next): Rocket
|
||||
{
|
||||
Logger::debug('[Wechat][Extend][ProfitSharing][QueryReturnPlugin] 插件开始装载', ['rocket' => $rocket]);
|
||||
|
||||
$config = get_wechat_config($rocket->getParams());
|
||||
$payload = $rocket->getPayload();
|
||||
$outOrderNo = $payload?->get('out_order_no') ?? null;
|
||||
$outReturnNo = $payload?->get('out_return_no') ?? null;
|
||||
$subMchId = $payload?->get('sub_mchid') ?? $config['sub_mch_id'] ?? 'null';
|
||||
|
||||
if (empty($outOrderNo) || empty($outReturnNo)) {
|
||||
throw new InvalidParamsException(Exception::PARAMS_NECESSARY_PARAMS_MISSING, '参数异常: 查询分账结果, 缺少必要参数 `out_order_no`, `out_return_no`');
|
||||
}
|
||||
|
||||
$rocket->setPayload([
|
||||
'_method' => 'GET',
|
||||
'_url' => 'v3/profitsharing/return-orders/'.$outReturnNo.'?out_order_no='.$outOrderNo,
|
||||
'_service_url' => 'v3/profitsharing/return-orders/'.$outReturnNo.'?sub_mchid='.$subMchId.'&out_order_no='.$outOrderNo,
|
||||
]);
|
||||
|
||||
Logger::info('[Wechat][Extend][ProfitSharing][QueryReturnPlugin] 插件装载完毕', ['rocket' => $rocket]);
|
||||
|
||||
return $next($rocket);
|
||||
}
|
||||
}
|
75
src/Plugin/Wechat/Extend/ProfitSharing/ReturnPlugin.php
Normal file
75
src/Plugin/Wechat/Extend/ProfitSharing/ReturnPlugin.php
Normal file
@ -0,0 +1,75 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Yansongda\Pay\Plugin\Wechat\Extend\ProfitSharing;
|
||||
|
||||
use Closure;
|
||||
use Yansongda\Pay\Contract\PluginInterface;
|
||||
use Yansongda\Pay\Exception\ContainerException;
|
||||
use Yansongda\Pay\Exception\Exception;
|
||||
use Yansongda\Pay\Exception\InvalidParamsException;
|
||||
use Yansongda\Pay\Exception\ServiceNotFoundException;
|
||||
use Yansongda\Pay\Logger;
|
||||
use Yansongda\Pay\Pay;
|
||||
use Yansongda\Pay\Rocket;
|
||||
use Yansongda\Supports\Collection;
|
||||
|
||||
use function Yansongda\Pay\get_wechat_config;
|
||||
|
||||
/**
|
||||
* @see https://pay.weixin.qq.com/docs/merchant/apis/profit-sharing/return-orders/create-return-order.html
|
||||
* @see https://pay.weixin.qq.com/docs/partner/apis/profit-sharing/return-orders/create-return-order.html
|
||||
*/
|
||||
class ReturnPlugin implements PluginInterface
|
||||
{
|
||||
/**
|
||||
* @throws ContainerException
|
||||
* @throws InvalidParamsException
|
||||
* @throws ServiceNotFoundException
|
||||
*/
|
||||
public function assembly(Rocket $rocket, Closure $next): Rocket
|
||||
{
|
||||
Logger::debug('[Wechat][Extend][ProfitSharing][ReturnPlugin] 插件开始装载', ['rocket' => $rocket]);
|
||||
|
||||
$params = $rocket->getParams();
|
||||
$config = get_wechat_config($params);
|
||||
$payload = $rocket->getPayload();
|
||||
|
||||
if (is_null($payload)) {
|
||||
throw new InvalidParamsException(Exception::PARAMS_NECESSARY_PARAMS_MISSING, '参数异常: 缺少分账参数');
|
||||
}
|
||||
|
||||
if (Pay::MODE_SERVICE === ($config['mode'] ?? Pay::MODE_NORMAL)) {
|
||||
$data = $this->service($payload, $config);
|
||||
}
|
||||
|
||||
$rocket->mergePayload(array_merge(
|
||||
[
|
||||
'_method' => 'POST',
|
||||
'_url' => 'v3/profitsharing/return-orders',
|
||||
'_service_url' => 'v3/profitsharing/return-orders',
|
||||
],
|
||||
$data ?? $this->normal($payload, $config),
|
||||
));
|
||||
|
||||
Logger::info('[Wechat][Extend][ProfitSharing][ReturnPlugin] 插件装载完毕', ['rocket' => $rocket]);
|
||||
|
||||
return $next($rocket);
|
||||
}
|
||||
|
||||
protected function normal(Collection $payload, array $config): array
|
||||
{
|
||||
return [
|
||||
'return_mchid' => $payload->get('return_mchid', $config['mch_id'] ?? ''),
|
||||
];
|
||||
}
|
||||
|
||||
protected function service(Collection $payload, array $config): array
|
||||
{
|
||||
return [
|
||||
'sub_mchid' => $payload->get('sub_mchid', $config['sub_mch_id'] ?? ''),
|
||||
'return_mchid' => $payload->get('return_mchid', $config['mch_id'] ?? ''),
|
||||
];
|
||||
}
|
||||
}
|
73
src/Plugin/Wechat/Extend/ProfitSharing/UnfreezePlugin.php
Normal file
73
src/Plugin/Wechat/Extend/ProfitSharing/UnfreezePlugin.php
Normal file
@ -0,0 +1,73 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Yansongda\Pay\Plugin\Wechat\Extend\ProfitSharing;
|
||||
|
||||
use Closure;
|
||||
use Yansongda\Pay\Contract\PluginInterface;
|
||||
use Yansongda\Pay\Exception\ContainerException;
|
||||
use Yansongda\Pay\Exception\Exception;
|
||||
use Yansongda\Pay\Exception\InvalidParamsException;
|
||||
use Yansongda\Pay\Exception\ServiceNotFoundException;
|
||||
use Yansongda\Pay\Logger;
|
||||
use Yansongda\Pay\Pay;
|
||||
use Yansongda\Pay\Rocket;
|
||||
use Yansongda\Supports\Collection;
|
||||
|
||||
use function Yansongda\Pay\get_wechat_config;
|
||||
|
||||
/**
|
||||
* @see https://pay.weixin.qq.com/docs/merchant/apis/profit-sharing/orders/unfreeze-order.html
|
||||
* @see https://pay.weixin.qq.com/docs/partner/apis/profit-sharing/orders/unfreeze-order.html
|
||||
*/
|
||||
class UnfreezePlugin implements PluginInterface
|
||||
{
|
||||
/**
|
||||
* @throws ContainerException
|
||||
* @throws InvalidParamsException
|
||||
* @throws ServiceNotFoundException
|
||||
*/
|
||||
public function assembly(Rocket $rocket, Closure $next): Rocket
|
||||
{
|
||||
Logger::debug('[Wechat][Extend][ProfitSharing][UnfreezePlugin] 插件开始装载', ['rocket' => $rocket]);
|
||||
|
||||
$params = $rocket->getParams();
|
||||
$config = get_wechat_config($params);
|
||||
$payload = $rocket->getPayload();
|
||||
|
||||
if (is_null($payload)) {
|
||||
throw new InvalidParamsException(Exception::PARAMS_NECESSARY_PARAMS_MISSING, '参数异常: 缺少分账参数');
|
||||
}
|
||||
|
||||
if (Pay::MODE_SERVICE === ($config['mode'] ?? Pay::MODE_NORMAL)) {
|
||||
$data = $this->service($payload, $config);
|
||||
}
|
||||
|
||||
$rocket->mergePayload(array_merge(
|
||||
[
|
||||
'_method' => 'POST',
|
||||
'_url' => 'v3/profitsharing/orders/unfreeze',
|
||||
'_service_url' => 'v3/profitsharing/orders/unfreeze',
|
||||
],
|
||||
$data ?? $this->normal(),
|
||||
));
|
||||
|
||||
Logger::info('[Wechat][Extend][ProfitSharing][UnfreezePlugin] 插件装载完毕', ['rocket' => $rocket]);
|
||||
|
||||
return $next($rocket);
|
||||
}
|
||||
|
||||
protected function normal(): array
|
||||
{
|
||||
return [];
|
||||
}
|
||||
|
||||
protected function service(Collection $payload, array $config): array
|
||||
{
|
||||
return [
|
||||
'sub_mchid' => $payload->get('sub_mchid', $config['sub_mch_id'] ?? ''),
|
||||
'notify_url' => $payload->get('notify_url', $config['notify_url'] ?? null),
|
||||
];
|
||||
}
|
||||
}
|
@ -1,36 +0,0 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Yansongda\Pay\Plugin\Wechat\Fund\Balance;
|
||||
|
||||
use Yansongda\Pay\Exception\Exception;
|
||||
use Yansongda\Pay\Exception\InvalidParamsException;
|
||||
use Yansongda\Pay\Plugin\Wechat\GeneralPlugin;
|
||||
use Yansongda\Pay\Rocket;
|
||||
|
||||
class QueryDayEndPlugin extends GeneralPlugin
|
||||
{
|
||||
protected function getMethod(): string
|
||||
{
|
||||
return 'GET';
|
||||
}
|
||||
|
||||
protected function doSomething(Rocket $rocket): void {}
|
||||
|
||||
/**
|
||||
* @throws InvalidParamsException
|
||||
*/
|
||||
protected function getUri(Rocket $rocket): string
|
||||
{
|
||||
$payload = $rocket->getPayload();
|
||||
|
||||
if (!$payload->has('account_type') || !$payload->has('date')) {
|
||||
throw new InvalidParamsException(Exception::PARAMS_NECESSARY_PARAMS_MISSING);
|
||||
}
|
||||
|
||||
return 'v3/merchant/fund/dayendbalance/'.
|
||||
$payload->get('account_type').
|
||||
'?date='.$payload->get('date');
|
||||
}
|
||||
}
|
@ -1,35 +0,0 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Yansongda\Pay\Plugin\Wechat\Fund\Balance;
|
||||
|
||||
use Yansongda\Pay\Exception\Exception;
|
||||
use Yansongda\Pay\Exception\InvalidParamsException;
|
||||
use Yansongda\Pay\Plugin\Wechat\GeneralPlugin;
|
||||
use Yansongda\Pay\Rocket;
|
||||
|
||||
class QueryPlugin extends GeneralPlugin
|
||||
{
|
||||
protected function getMethod(): string
|
||||
{
|
||||
return 'GET';
|
||||
}
|
||||
|
||||
protected function doSomething(Rocket $rocket): void {}
|
||||
|
||||
/**
|
||||
* @throws InvalidParamsException
|
||||
*/
|
||||
protected function getUri(Rocket $rocket): string
|
||||
{
|
||||
$payload = $rocket->getPayload();
|
||||
|
||||
if (!$payload->has('account_type')) {
|
||||
throw new InvalidParamsException(Exception::PARAMS_NECESSARY_PARAMS_MISSING);
|
||||
}
|
||||
|
||||
return 'v3/merchant/fund/balance/'.
|
||||
$payload->get('account_type');
|
||||
}
|
||||
}
|
@ -1,83 +0,0 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Yansongda\Pay\Plugin\Wechat\Fund\Profitsharing;
|
||||
|
||||
use Yansongda\Pay\Exception\ContainerException;
|
||||
use Yansongda\Pay\Exception\InvalidConfigException;
|
||||
use Yansongda\Pay\Exception\InvalidParamsException;
|
||||
use Yansongda\Pay\Exception\InvalidResponseException;
|
||||
use Yansongda\Pay\Exception\ServiceNotFoundException;
|
||||
use Yansongda\Pay\Pay;
|
||||
use Yansongda\Pay\Plugin\Wechat\GeneralPlugin;
|
||||
use Yansongda\Pay\Rocket;
|
||||
use Yansongda\Pay\Traits\HasWechatEncryption;
|
||||
use Yansongda\Supports\Collection;
|
||||
|
||||
use function Yansongda\Pay\encrypt_wechat_contents;
|
||||
use function Yansongda\Pay\get_wechat_config;
|
||||
|
||||
/**
|
||||
* @see https://pay.weixin.qq.com/wiki/doc/apiv3/apis/chapter8_1_8.shtml
|
||||
*/
|
||||
class AddReceiverPlugin extends GeneralPlugin
|
||||
{
|
||||
use HasWechatEncryption;
|
||||
|
||||
/**
|
||||
* @throws ContainerException
|
||||
* @throws InvalidConfigException
|
||||
* @throws InvalidParamsException
|
||||
* @throws InvalidResponseException
|
||||
* @throws ServiceNotFoundException
|
||||
*/
|
||||
protected function doSomething(Rocket $rocket): void
|
||||
{
|
||||
$params = $rocket->getParams();
|
||||
$config = get_wechat_config($rocket->getParams());
|
||||
$extra = $this->getWechatId($config, $rocket->getPayload());
|
||||
|
||||
if (!empty($params['name'] ?? '')) {
|
||||
$params = $this->loadSerialNo($params);
|
||||
|
||||
$name = $this->getEncryptUserName($params);
|
||||
$params['name'] = $name;
|
||||
$extra['name'] = $name;
|
||||
$rocket->setParams($params);
|
||||
}
|
||||
|
||||
$rocket->mergePayload($extra);
|
||||
}
|
||||
|
||||
protected function getUri(Rocket $rocket): string
|
||||
{
|
||||
return 'v3/profitsharing/receivers/add';
|
||||
}
|
||||
|
||||
protected function getWechatId(array $config, Collection $payload): array
|
||||
{
|
||||
$wechatId = [
|
||||
'appid' => $config['mp_app_id'] ?? null,
|
||||
];
|
||||
|
||||
if (Pay::MODE_SERVICE === ($config['mode'] ?? null)) {
|
||||
$wechatId['sub_mchid'] = $payload->get('sub_mchid', $config['sub_mch_id'] ?? '');
|
||||
}
|
||||
|
||||
return $wechatId;
|
||||
}
|
||||
|
||||
/**
|
||||
* @throws ContainerException
|
||||
* @throws InvalidParamsException
|
||||
* @throws ServiceNotFoundException
|
||||
*/
|
||||
protected function getEncryptUserName(array $params): string
|
||||
{
|
||||
$name = $params['name'] ?? '';
|
||||
$publicKey = $this->getPublicKey($params, $params['_serial_no'] ?? '');
|
||||
|
||||
return encrypt_wechat_contents($name, $publicKey);
|
||||
}
|
||||
}
|
@ -1,89 +0,0 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Yansongda\Pay\Plugin\Wechat\Fund\Profitsharing;
|
||||
|
||||
use Yansongda\Pay\Exception\ContainerException;
|
||||
use Yansongda\Pay\Exception\InvalidConfigException;
|
||||
use Yansongda\Pay\Exception\InvalidParamsException;
|
||||
use Yansongda\Pay\Exception\InvalidResponseException;
|
||||
use Yansongda\Pay\Exception\ServiceNotFoundException;
|
||||
use Yansongda\Pay\Pay;
|
||||
use Yansongda\Pay\Plugin\Wechat\GeneralPlugin;
|
||||
use Yansongda\Pay\Rocket;
|
||||
use Yansongda\Pay\Traits\HasWechatEncryption;
|
||||
use Yansongda\Supports\Collection;
|
||||
|
||||
use function Yansongda\Pay\encrypt_wechat_contents;
|
||||
use function Yansongda\Pay\get_wechat_config;
|
||||
|
||||
/**
|
||||
* @see https://pay.weixin.qq.com/wiki/doc/apiv3/apis/chapter8_1_1.shtml
|
||||
*/
|
||||
class CreatePlugin extends GeneralPlugin
|
||||
{
|
||||
use HasWechatEncryption;
|
||||
|
||||
/**
|
||||
* @throws ContainerException
|
||||
* @throws InvalidConfigException
|
||||
* @throws InvalidParamsException
|
||||
* @throws InvalidResponseException
|
||||
* @throws ServiceNotFoundException
|
||||
*/
|
||||
protected function doSomething(Rocket $rocket): void
|
||||
{
|
||||
$payload = $rocket->getPayload();
|
||||
$params = $this->loadSerialNo($rocket->getParams());
|
||||
|
||||
$extra = $this->getWechatExtra($params, $payload);
|
||||
$extra['receivers'] = $this->getReceivers($params);
|
||||
|
||||
$rocket->setParams($params);
|
||||
$rocket->mergePayload($extra);
|
||||
}
|
||||
|
||||
protected function getUri(Rocket $rocket): string
|
||||
{
|
||||
return 'v3/profitsharing/orders';
|
||||
}
|
||||
|
||||
/**
|
||||
* @throws ContainerException
|
||||
* @throws ServiceNotFoundException
|
||||
*/
|
||||
protected function getWechatExtra(array $params, Collection $payload): array
|
||||
{
|
||||
$config = get_wechat_config($params);
|
||||
|
||||
$extra = [
|
||||
'appid' => $config['mp_app_id'] ?? null,
|
||||
];
|
||||
|
||||
if (Pay::MODE_SERVICE === ($config['mode'] ?? null)) {
|
||||
$extra['sub_mchid'] = $payload->get('sub_mchid', $config['sub_mch_id'] ?? '');
|
||||
}
|
||||
|
||||
return $extra;
|
||||
}
|
||||
|
||||
/**
|
||||
* @throws ContainerException
|
||||
* @throws InvalidParamsException
|
||||
* @throws ServiceNotFoundException
|
||||
*/
|
||||
protected function getReceivers(array $params): array
|
||||
{
|
||||
$publicKey = $this->getPublicKey($params, $params['_serial_no'] ?? '');
|
||||
$receivers = $params['receivers'] ?? [];
|
||||
|
||||
foreach ($receivers as $key => $receiver) {
|
||||
if (!empty($receiver['name'])) {
|
||||
$receivers[$key]['name'] = encrypt_wechat_contents($receiver['name'], $publicKey);
|
||||
}
|
||||
}
|
||||
|
||||
return $receivers;
|
||||
}
|
||||
}
|
@ -1,44 +0,0 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Yansongda\Pay\Plugin\Wechat\Fund\Profitsharing;
|
||||
|
||||
use Yansongda\Pay\Exception\ContainerException;
|
||||
use Yansongda\Pay\Exception\ServiceNotFoundException;
|
||||
use Yansongda\Pay\Pay;
|
||||
use Yansongda\Pay\Plugin\Wechat\GeneralPlugin;
|
||||
use Yansongda\Pay\Rocket;
|
||||
|
||||
use function Yansongda\Pay\get_wechat_config;
|
||||
|
||||
/**
|
||||
* @see https://pay.weixin.qq.com/wiki/doc/apiv3/apis/chapter8_1_9.shtml
|
||||
*/
|
||||
class DeleteReceiverPlugin extends GeneralPlugin
|
||||
{
|
||||
/**
|
||||
* @throws ContainerException
|
||||
* @throws ServiceNotFoundException
|
||||
*/
|
||||
protected function doSomething(Rocket $rocket): void
|
||||
{
|
||||
$config = get_wechat_config($rocket->getParams());
|
||||
|
||||
$wechatId = [
|
||||
'appid' => $config['mp_app_id'] ?? null,
|
||||
];
|
||||
|
||||
if (Pay::MODE_SERVICE === ($config['mode'] ?? null)) {
|
||||
$wechatId['sub_mchid'] = $rocket->getPayload()
|
||||
->get('sub_mchid', $config['sub_mch_id'] ?? '');
|
||||
}
|
||||
|
||||
$rocket->mergePayload($wechatId);
|
||||
}
|
||||
|
||||
protected function getUri(Rocket $rocket): string
|
||||
{
|
||||
return 'v3/profitsharing/receivers/delete';
|
||||
}
|
||||
}
|
@ -1,43 +0,0 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Yansongda\Pay\Plugin\Wechat\Fund\Profitsharing;
|
||||
|
||||
use Yansongda\Pay\Direction\OriginResponseDirection;
|
||||
use Yansongda\Pay\Exception\Exception;
|
||||
use Yansongda\Pay\Exception\InvalidParamsException;
|
||||
use Yansongda\Pay\Plugin\Wechat\GeneralPlugin;
|
||||
use Yansongda\Pay\Rocket;
|
||||
|
||||
/**
|
||||
* @see https://pay.weixin.qq.com/wiki/doc/apiv3/apis/chapter8_1_12.shtml
|
||||
*/
|
||||
class DownloadBillPlugin extends GeneralPlugin
|
||||
{
|
||||
/**
|
||||
* @throws InvalidParamsException
|
||||
*/
|
||||
protected function getUri(Rocket $rocket): string
|
||||
{
|
||||
$payload = $rocket->getPayload();
|
||||
|
||||
if (!$payload->has('download_url')) {
|
||||
throw new InvalidParamsException(Exception::PARAMS_NECESSARY_PARAMS_MISSING);
|
||||
}
|
||||
|
||||
return $payload->get('download_url');
|
||||
}
|
||||
|
||||
protected function getMethod(): string
|
||||
{
|
||||
return 'GET';
|
||||
}
|
||||
|
||||
protected function doSomething(Rocket $rocket): void
|
||||
{
|
||||
$rocket->setDirection(OriginResponseDirection::class);
|
||||
|
||||
$rocket->setPayload(null);
|
||||
}
|
||||
}
|
@ -1,42 +0,0 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Yansongda\Pay\Plugin\Wechat\Fund\Profitsharing;
|
||||
|
||||
use Yansongda\Pay\Exception\Exception;
|
||||
use Yansongda\Pay\Exception\InvalidParamsException;
|
||||
use Yansongda\Pay\Plugin\Wechat\GeneralPlugin;
|
||||
use Yansongda\Pay\Rocket;
|
||||
|
||||
/**
|
||||
* @see https://pay.weixin.qq.com/wiki/doc/apiv3/apis/chapter8_1_6.shtml
|
||||
*/
|
||||
class QueryAmountsPlugin extends GeneralPlugin
|
||||
{
|
||||
protected function getMethod(): string
|
||||
{
|
||||
return 'GET';
|
||||
}
|
||||
|
||||
protected function doSomething(Rocket $rocket): void
|
||||
{
|
||||
$rocket->setPayload(null);
|
||||
}
|
||||
|
||||
/**
|
||||
* @throws InvalidParamsException
|
||||
*/
|
||||
protected function getUri(Rocket $rocket): string
|
||||
{
|
||||
$payload = $rocket->getPayload();
|
||||
|
||||
if (!$payload->has('transaction_id')) {
|
||||
throw new InvalidParamsException(Exception::PARAMS_NECESSARY_PARAMS_MISSING);
|
||||
}
|
||||
|
||||
return 'v3/profitsharing/transactions/'.
|
||||
$payload->get('transaction_id').
|
||||
'/amounts';
|
||||
}
|
||||
}
|
@ -1,49 +0,0 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Yansongda\Pay\Plugin\Wechat\Fund\Profitsharing;
|
||||
|
||||
use Yansongda\Pay\Exception\ContainerException;
|
||||
use Yansongda\Pay\Exception\Exception;
|
||||
use Yansongda\Pay\Exception\InvalidParamsException;
|
||||
use Yansongda\Pay\Exception\ServiceNotFoundException;
|
||||
use Yansongda\Pay\Pay;
|
||||
use Yansongda\Pay\Plugin\Wechat\GeneralPlugin;
|
||||
use Yansongda\Pay\Rocket;
|
||||
|
||||
use function Yansongda\Pay\get_wechat_config;
|
||||
|
||||
/**
|
||||
* @see https://pay.weixin.qq.com/wiki/doc/apiv3_partner/apis/chapter8_1_7.shtml
|
||||
*/
|
||||
class QueryMerchantConfigsPlugin extends GeneralPlugin
|
||||
{
|
||||
protected function getMethod(): string
|
||||
{
|
||||
return 'GET';
|
||||
}
|
||||
|
||||
protected function doSomething(Rocket $rocket): void
|
||||
{
|
||||
$rocket->setPayload(null);
|
||||
}
|
||||
|
||||
/**
|
||||
* @throws ContainerException
|
||||
* @throws InvalidParamsException
|
||||
* @throws ServiceNotFoundException
|
||||
*/
|
||||
protected function getUri(Rocket $rocket): string
|
||||
{
|
||||
$config = get_wechat_config($rocket->getParams());
|
||||
$payload = $rocket->getPayload();
|
||||
|
||||
if (Pay::MODE_SERVICE !== ($config['mode'] ?? Pay::MODE_NORMAL)) {
|
||||
throw new InvalidParamsException(Exception::PARAMS_METHOD_NOT_SUPPORTED);
|
||||
}
|
||||
|
||||
return 'v3/profitsharing/merchant-configs/'.
|
||||
$payload->get('sub_mchid', $config['sub_mch_id'] ?? '');
|
||||
}
|
||||
}
|
@ -1,56 +0,0 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Yansongda\Pay\Plugin\Wechat\Fund\Profitsharing;
|
||||
|
||||
use Yansongda\Pay\Exception\ContainerException;
|
||||
use Yansongda\Pay\Exception\Exception;
|
||||
use Yansongda\Pay\Exception\InvalidParamsException;
|
||||
use Yansongda\Pay\Exception\ServiceNotFoundException;
|
||||
use Yansongda\Pay\Pay;
|
||||
use Yansongda\Pay\Plugin\Wechat\GeneralPlugin;
|
||||
use Yansongda\Pay\Rocket;
|
||||
|
||||
use function Yansongda\Pay\get_wechat_config;
|
||||
|
||||
/**
|
||||
* @see https://pay.weixin.qq.com/wiki/doc/apiv3/apis/chapter8_1_2.shtml
|
||||
*/
|
||||
class QueryPlugin extends GeneralPlugin
|
||||
{
|
||||
protected function getMethod(): string
|
||||
{
|
||||
return 'GET';
|
||||
}
|
||||
|
||||
protected function doSomething(Rocket $rocket): void
|
||||
{
|
||||
$rocket->setPayload(null);
|
||||
}
|
||||
|
||||
/**
|
||||
* @throws ContainerException
|
||||
* @throws InvalidParamsException
|
||||
* @throws ServiceNotFoundException
|
||||
*/
|
||||
protected function getUri(Rocket $rocket): string
|
||||
{
|
||||
$payload = $rocket->getPayload();
|
||||
$config = get_wechat_config($rocket->getParams());
|
||||
|
||||
if (!$payload->has('out_order_no') || !$payload->has('transaction_id')) {
|
||||
throw new InvalidParamsException(Exception::PARAMS_NECESSARY_PARAMS_MISSING);
|
||||
}
|
||||
|
||||
$url = 'v3/profitsharing/orders/'.
|
||||
$payload->get('out_order_no').
|
||||
'?transaction_id='.$payload->get('transaction_id');
|
||||
|
||||
if (Pay::MODE_SERVICE === ($config['mode'] ?? null)) {
|
||||
$url .= '&sub_mchid='.$payload->get('sub_mchid', $config['sub_mch_id'] ?? '');
|
||||
}
|
||||
|
||||
return $url;
|
||||
}
|
||||
}
|
@ -1,56 +0,0 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Yansongda\Pay\Plugin\Wechat\Fund\Profitsharing;
|
||||
|
||||
use Yansongda\Pay\Exception\ContainerException;
|
||||
use Yansongda\Pay\Exception\Exception;
|
||||
use Yansongda\Pay\Exception\InvalidParamsException;
|
||||
use Yansongda\Pay\Exception\ServiceNotFoundException;
|
||||
use Yansongda\Pay\Pay;
|
||||
use Yansongda\Pay\Plugin\Wechat\GeneralPlugin;
|
||||
use Yansongda\Pay\Rocket;
|
||||
|
||||
use function Yansongda\Pay\get_wechat_config;
|
||||
|
||||
/**
|
||||
* @see https://pay.weixin.qq.com/wiki/doc/apiv3/apis/chapter8_1_4.shtml
|
||||
*/
|
||||
class QueryReturnPlugin extends GeneralPlugin
|
||||
{
|
||||
protected function getMethod(): string
|
||||
{
|
||||
return 'GET';
|
||||
}
|
||||
|
||||
protected function doSomething(Rocket $rocket): void
|
||||
{
|
||||
$rocket->setPayload(null);
|
||||
}
|
||||
|
||||
/**
|
||||
* @throws ContainerException
|
||||
* @throws InvalidParamsException
|
||||
* @throws ServiceNotFoundException
|
||||
*/
|
||||
protected function getUri(Rocket $rocket): string
|
||||
{
|
||||
$payload = $rocket->getPayload();
|
||||
$config = get_wechat_config($rocket->getParams());
|
||||
|
||||
if (!$payload->has('out_return_no') || !$payload->has('out_order_no')) {
|
||||
throw new InvalidParamsException(Exception::PARAMS_NECESSARY_PARAMS_MISSING);
|
||||
}
|
||||
|
||||
$url = 'v3/profitsharing/return-orders/'.
|
||||
$payload->get('out_return_no').
|
||||
'?out_order_no='.$payload->get('out_order_no');
|
||||
|
||||
if (Pay::MODE_SERVICE === ($config['mode'] ?? null)) {
|
||||
$url .= '&sub_mchid='.$payload->get('sub_mchid', $config['sub_mch_id'] ?? '');
|
||||
}
|
||||
|
||||
return $url;
|
||||
}
|
||||
}
|
@ -1,40 +0,0 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Yansongda\Pay\Plugin\Wechat\Fund\Profitsharing;
|
||||
|
||||
use Yansongda\Pay\Exception\ContainerException;
|
||||
use Yansongda\Pay\Exception\ServiceNotFoundException;
|
||||
use Yansongda\Pay\Pay;
|
||||
use Yansongda\Pay\Plugin\Wechat\GeneralPlugin;
|
||||
use Yansongda\Pay\Rocket;
|
||||
|
||||
use function Yansongda\Pay\get_wechat_config;
|
||||
|
||||
/**
|
||||
* @see https://pay.weixin.qq.com/wiki/doc/apiv3/apis/chapter8_1_3.shtml
|
||||
*/
|
||||
class ReturnPlugin extends GeneralPlugin
|
||||
{
|
||||
/**
|
||||
* @throws ContainerException
|
||||
* @throws ServiceNotFoundException
|
||||
*/
|
||||
protected function doSomething(Rocket $rocket): void
|
||||
{
|
||||
$config = get_wechat_config($rocket->getParams());
|
||||
|
||||
if (Pay::MODE_SERVICE === ($config['mode'] ?? null)) {
|
||||
$rocket->mergePayload([
|
||||
'sub_mchid' => $rocket->getPayload()
|
||||
->get('sub_mchid', $config['sub_mch_id'] ?? ''),
|
||||
]);
|
||||
}
|
||||
}
|
||||
|
||||
protected function getUri(Rocket $rocket): string
|
||||
{
|
||||
return 'v3/profitsharing/return-orders';
|
||||
}
|
||||
}
|
@ -1,40 +0,0 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Yansongda\Pay\Plugin\Wechat\Fund\Profitsharing;
|
||||
|
||||
use Yansongda\Pay\Exception\ContainerException;
|
||||
use Yansongda\Pay\Exception\ServiceNotFoundException;
|
||||
use Yansongda\Pay\Pay;
|
||||
use Yansongda\Pay\Plugin\Wechat\GeneralPlugin;
|
||||
use Yansongda\Pay\Rocket;
|
||||
|
||||
use function Yansongda\Pay\get_wechat_config;
|
||||
|
||||
/**
|
||||
* @see https://pay.weixin.qq.com/wiki/doc/apiv3/apis/chapter8_1_5.shtml
|
||||
*/
|
||||
class UnfreezePlugin extends GeneralPlugin
|
||||
{
|
||||
/**
|
||||
* @throws ContainerException
|
||||
* @throws ServiceNotFoundException
|
||||
*/
|
||||
protected function doSomething(Rocket $rocket): void
|
||||
{
|
||||
$payload = $rocket->getPayload();
|
||||
$config = get_wechat_config($rocket->getParams());
|
||||
|
||||
if (Pay::MODE_SERVICE === ($config['mode'] ?? null) && !$payload->has('sub_mchid')) {
|
||||
$rocket->mergePayload([
|
||||
'sub_mchid' => $config['sub_mch_id'] ?? '',
|
||||
]);
|
||||
}
|
||||
}
|
||||
|
||||
protected function getUri(Rocket $rocket): string
|
||||
{
|
||||
return 'v3/profitsharing/orders/unfreeze';
|
||||
}
|
||||
}
|
@ -1,33 +0,0 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Yansongda\Pay\Plugin\Wechat\Fund\Transfer;
|
||||
|
||||
use Yansongda\Pay\Exception\Exception;
|
||||
use Yansongda\Pay\Exception\InvalidParamsException;
|
||||
use Yansongda\Pay\Plugin\Wechat\GeneralPlugin;
|
||||
use Yansongda\Pay\Rocket;
|
||||
|
||||
/**
|
||||
* @see https://pay.weixin.qq.com/wiki/doc/apiv3/apis/chapter4_3_7.shtml
|
||||
*/
|
||||
class CreateBillReceiptPlugin extends GeneralPlugin
|
||||
{
|
||||
/**
|
||||
* @throws InvalidParamsException
|
||||
*/
|
||||
protected function doSomething(Rocket $rocket): void
|
||||
{
|
||||
$payload = $rocket->getPayload();
|
||||
|
||||
if (!$payload->has('out_batch_no')) {
|
||||
throw new InvalidParamsException(Exception::PARAMS_NECESSARY_PARAMS_MISSING);
|
||||
}
|
||||
}
|
||||
|
||||
protected function getUri(Rocket $rocket): string
|
||||
{
|
||||
return 'v3/transfer/bill-receipt';
|
||||
}
|
||||
}
|
@ -1,33 +0,0 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Yansongda\Pay\Plugin\Wechat\Fund\Transfer;
|
||||
|
||||
use Yansongda\Pay\Exception\Exception;
|
||||
use Yansongda\Pay\Exception\InvalidParamsException;
|
||||
use Yansongda\Pay\Plugin\Wechat\GeneralPlugin;
|
||||
use Yansongda\Pay\Rocket;
|
||||
|
||||
/**
|
||||
* @see https://pay.weixin.qq.com/wiki/doc/apiv3/apis/chapter4_3_9.shtml
|
||||
*/
|
||||
class CreateDetailReceiptPlugin extends GeneralPlugin
|
||||
{
|
||||
/**
|
||||
* @throws InvalidParamsException
|
||||
*/
|
||||
protected function doSomething(Rocket $rocket): void
|
||||
{
|
||||
$payload = $rocket->getPayload();
|
||||
|
||||
if (!$payload->has('out_detail_no') || !$payload->has('accept_type')) {
|
||||
throw new InvalidParamsException(Exception::PARAMS_NECESSARY_PARAMS_MISSING);
|
||||
}
|
||||
}
|
||||
|
||||
protected function getUri(Rocket $rocket): string
|
||||
{
|
||||
return 'v3/transfer-detail/electronic-receipts';
|
||||
}
|
||||
}
|
@ -1,99 +0,0 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Yansongda\Pay\Plugin\Wechat\Fund\Transfer;
|
||||
|
||||
use Yansongda\Pay\Exception\ContainerException;
|
||||
use Yansongda\Pay\Exception\InvalidConfigException;
|
||||
use Yansongda\Pay\Exception\InvalidParamsException;
|
||||
use Yansongda\Pay\Exception\InvalidResponseException;
|
||||
use Yansongda\Pay\Exception\ServiceNotFoundException;
|
||||
use Yansongda\Pay\Pay;
|
||||
use Yansongda\Pay\Plugin\Wechat\GeneralPlugin;
|
||||
use Yansongda\Pay\Rocket;
|
||||
use Yansongda\Pay\Traits\HasWechatEncryption;
|
||||
use Yansongda\Supports\Collection;
|
||||
|
||||
use function Yansongda\Pay\encrypt_wechat_contents;
|
||||
use function Yansongda\Pay\get_wechat_config;
|
||||
|
||||
/**
|
||||
* @see https://pay.weixin.qq.com/wiki/doc/apiv3/apis/chapter4_3_1.shtml
|
||||
*/
|
||||
class CreatePlugin extends GeneralPlugin
|
||||
{
|
||||
use HasWechatEncryption;
|
||||
|
||||
/**
|
||||
* @throws ContainerException
|
||||
* @throws InvalidConfigException
|
||||
* @throws InvalidParamsException
|
||||
* @throws InvalidResponseException
|
||||
* @throws ServiceNotFoundException
|
||||
*/
|
||||
protected function doSomething(Rocket $rocket): void
|
||||
{
|
||||
$params = $rocket->getParams();
|
||||
$extra = $this->getWechatId($params, $rocket->getPayload());
|
||||
|
||||
if (!empty($params['transfer_detail_list'][0]['user_name'] ?? '')) {
|
||||
$params = $this->loadSerialNo($params);
|
||||
|
||||
$rocket->setParams($params);
|
||||
|
||||
$extra['transfer_detail_list'] = $this->getEncryptUserName($params);
|
||||
}
|
||||
|
||||
$rocket->mergePayload($extra);
|
||||
}
|
||||
|
||||
protected function getUri(Rocket $rocket): string
|
||||
{
|
||||
return 'v3/transfer/batches';
|
||||
}
|
||||
|
||||
protected function getPartnerUri(Rocket $rocket): string
|
||||
{
|
||||
return 'v3/partner-transfer/batches';
|
||||
}
|
||||
|
||||
/**
|
||||
* @throws ContainerException
|
||||
* @throws ServiceNotFoundException
|
||||
*/
|
||||
protected function getWechatId(array $params, Collection $payload): array
|
||||
{
|
||||
$config = get_wechat_config($params);
|
||||
$key = $this->getConfigKey($params);
|
||||
|
||||
$appId = [
|
||||
'appid' => $payload->get('appid', $config[$key] ?? ''),
|
||||
];
|
||||
|
||||
if (Pay::MODE_SERVICE === ($config['mode'] ?? null)) {
|
||||
$appId = [
|
||||
'sub_mchid' => $payload->get('sub_mchid', $config['sub_mch_id'] ?? ''),
|
||||
];
|
||||
}
|
||||
|
||||
return $appId;
|
||||
}
|
||||
|
||||
/**
|
||||
* @throws ContainerException
|
||||
* @throws InvalidParamsException
|
||||
* @throws ServiceNotFoundException
|
||||
*/
|
||||
protected function getEncryptUserName(array $params): array
|
||||
{
|
||||
$lists = $params['transfer_detail_list'] ?? [];
|
||||
$publicKey = $this->getPublicKey($params, $params['_serial_no'] ?? '');
|
||||
|
||||
foreach ($lists as $key => $list) {
|
||||
$lists[$key]['user_name'] = encrypt_wechat_contents($list['user_name'], $publicKey);
|
||||
}
|
||||
|
||||
return $lists;
|
||||
}
|
||||
}
|
@ -1,43 +0,0 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Yansongda\Pay\Plugin\Wechat\Fund\Transfer;
|
||||
|
||||
use Yansongda\Pay\Direction\OriginResponseDirection;
|
||||
use Yansongda\Pay\Exception\Exception;
|
||||
use Yansongda\Pay\Exception\InvalidParamsException;
|
||||
use Yansongda\Pay\Plugin\Wechat\GeneralPlugin;
|
||||
use Yansongda\Pay\Rocket;
|
||||
|
||||
/**
|
||||
* @see https://pay.weixin.qq.com/wiki/doc/apiv3/apis/chapter4_3_11.shtml
|
||||
*/
|
||||
class DownloadReceiptPlugin extends GeneralPlugin
|
||||
{
|
||||
/**
|
||||
* @throws InvalidParamsException
|
||||
*/
|
||||
protected function getUri(Rocket $rocket): string
|
||||
{
|
||||
$payload = $rocket->getPayload();
|
||||
|
||||
if (!$payload->has('download_url')) {
|
||||
throw new InvalidParamsException(Exception::PARAMS_NECESSARY_PARAMS_MISSING);
|
||||
}
|
||||
|
||||
return $payload->get('download_url');
|
||||
}
|
||||
|
||||
protected function getMethod(): string
|
||||
{
|
||||
return 'GET';
|
||||
}
|
||||
|
||||
protected function doSomething(Rocket $rocket): void
|
||||
{
|
||||
$rocket->setDirection(OriginResponseDirection::class);
|
||||
|
||||
$rocket->setPayload(null);
|
||||
}
|
||||
}
|
@ -1,60 +0,0 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Yansongda\Pay\Plugin\Wechat\Fund\Transfer;
|
||||
|
||||
use Yansongda\Pay\Exception\Exception;
|
||||
use Yansongda\Pay\Exception\InvalidParamsException;
|
||||
use Yansongda\Pay\Plugin\Wechat\GeneralPlugin;
|
||||
use Yansongda\Pay\Rocket;
|
||||
|
||||
/**
|
||||
* @see https://pay.weixin.qq.com/wiki/doc/apiv3/apis/chapter4_3_3.shtml
|
||||
*/
|
||||
class QueryBatchDetailIdPlugin extends GeneralPlugin
|
||||
{
|
||||
protected function getMethod(): string
|
||||
{
|
||||
return 'GET';
|
||||
}
|
||||
|
||||
protected function doSomething(Rocket $rocket): void
|
||||
{
|
||||
$rocket->setPayload(null);
|
||||
}
|
||||
|
||||
/**
|
||||
* @throws InvalidParamsException
|
||||
*/
|
||||
protected function getUri(Rocket $rocket): string
|
||||
{
|
||||
$payload = $rocket->getPayload();
|
||||
|
||||
if (!$payload->has('batch_id') || !$payload->get('detail_id')) {
|
||||
throw new InvalidParamsException(Exception::PARAMS_NECESSARY_PARAMS_MISSING);
|
||||
}
|
||||
|
||||
return 'v3/transfer/batches/batch-id/'.
|
||||
$payload->get('batch_id').
|
||||
'/details/detail-id/'.
|
||||
$payload->get('detail_id');
|
||||
}
|
||||
|
||||
/**
|
||||
* @throws InvalidParamsException
|
||||
*/
|
||||
protected function getPartnerUri(Rocket $rocket): string
|
||||
{
|
||||
$payload = $rocket->getPayload();
|
||||
|
||||
if (!$payload->has('batch_id') || !$payload->has('detail_id')) {
|
||||
throw new InvalidParamsException(Exception::PARAMS_NECESSARY_PARAMS_MISSING);
|
||||
}
|
||||
|
||||
return 'v3/partner-transfer/batches/batch-id/'.
|
||||
$payload->get('batch_id').
|
||||
'/details/detail-id/'.
|
||||
$payload->get('detail_id');
|
||||
}
|
||||
}
|
@ -1,64 +0,0 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Yansongda\Pay\Plugin\Wechat\Fund\Transfer;
|
||||
|
||||
use Yansongda\Pay\Exception\Exception;
|
||||
use Yansongda\Pay\Exception\InvalidParamsException;
|
||||
use Yansongda\Pay\Plugin\Wechat\GeneralPlugin;
|
||||
use Yansongda\Pay\Rocket;
|
||||
|
||||
/**
|
||||
* @see https://pay.weixin.qq.com/wiki/doc/apiv3/apis/chapter4_3_2.shtml
|
||||
*/
|
||||
class QueryBatchIdPlugin extends GeneralPlugin
|
||||
{
|
||||
protected function getMethod(): string
|
||||
{
|
||||
return 'GET';
|
||||
}
|
||||
|
||||
protected function doSomething(Rocket $rocket): void
|
||||
{
|
||||
$rocket->setPayload(null);
|
||||
}
|
||||
|
||||
/**
|
||||
* @throws InvalidParamsException
|
||||
*/
|
||||
protected function getUri(Rocket $rocket): string
|
||||
{
|
||||
$payload = $rocket->getPayload();
|
||||
|
||||
if (!$payload->has('batch_id') || !$payload->has('need_query_detail')) {
|
||||
throw new InvalidParamsException(Exception::PARAMS_NECESSARY_PARAMS_MISSING);
|
||||
}
|
||||
|
||||
$batchId = $payload->get('batch_id');
|
||||
|
||||
$payload->forget('batch_id');
|
||||
|
||||
return 'v3/transfer/batches/batch-id/'.$batchId.
|
||||
'?'.$payload->query();
|
||||
}
|
||||
|
||||
/**
|
||||
* @throws InvalidParamsException
|
||||
*/
|
||||
protected function getPartnerUri(Rocket $rocket): string
|
||||
{
|
||||
$payload = $rocket->getPayload();
|
||||
|
||||
if (!$payload->has('batch_id') || !$payload->has('need_query_detail')) {
|
||||
throw new InvalidParamsException(Exception::PARAMS_NECESSARY_PARAMS_MISSING);
|
||||
}
|
||||
|
||||
$batchId = $payload->get('batch_id');
|
||||
|
||||
$payload->forget('batch_id');
|
||||
|
||||
return 'v3/partner-transfer/batches/batch-id/'.$batchId.
|
||||
'?'.$payload->query();
|
||||
}
|
||||
}
|
@ -1,40 +0,0 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Yansongda\Pay\Plugin\Wechat\Fund\Transfer;
|
||||
|
||||
use Yansongda\Pay\Exception\Exception;
|
||||
use Yansongda\Pay\Exception\InvalidParamsException;
|
||||
use Yansongda\Pay\Plugin\Wechat\GeneralPlugin;
|
||||
use Yansongda\Pay\Rocket;
|
||||
|
||||
/**
|
||||
* @see https://pay.weixin.qq.com/wiki/doc/apiv3/apis/chapter4_3_8.shtml
|
||||
*/
|
||||
class QueryBillReceiptPlugin extends GeneralPlugin
|
||||
{
|
||||
protected function getMethod(): string
|
||||
{
|
||||
return 'GET';
|
||||
}
|
||||
|
||||
protected function doSomething(Rocket $rocket): void
|
||||
{
|
||||
$rocket->setPayload(null);
|
||||
}
|
||||
|
||||
/**
|
||||
* @throws InvalidParamsException
|
||||
*/
|
||||
protected function getUri(Rocket $rocket): string
|
||||
{
|
||||
$payload = $rocket->getPayload();
|
||||
|
||||
if (!$payload->has('out_batch_no')) {
|
||||
throw new InvalidParamsException(Exception::PARAMS_NECESSARY_PARAMS_MISSING);
|
||||
}
|
||||
|
||||
return 'v3/transfer/bill-receipt/'.$payload->get('out_batch_no');
|
||||
}
|
||||
}
|
@ -1,40 +0,0 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Yansongda\Pay\Plugin\Wechat\Fund\Transfer;
|
||||
|
||||
use Yansongda\Pay\Exception\Exception;
|
||||
use Yansongda\Pay\Exception\InvalidParamsException;
|
||||
use Yansongda\Pay\Plugin\Wechat\GeneralPlugin;
|
||||
use Yansongda\Pay\Rocket;
|
||||
|
||||
/**
|
||||
* @see https://pay.weixin.qq.com/wiki/doc/apiv3/apis/chapter4_3_10.shtml
|
||||
*/
|
||||
class QueryDetailReceiptPlugin extends GeneralPlugin
|
||||
{
|
||||
protected function getMethod(): string
|
||||
{
|
||||
return 'GET';
|
||||
}
|
||||
|
||||
/**
|
||||
* @throws InvalidParamsException
|
||||
*/
|
||||
protected function doSomething(Rocket $rocket): void
|
||||
{
|
||||
$payload = $rocket->getPayload();
|
||||
|
||||
if (!$payload->has('out_detail_no') || !$payload->has('accept_type')) {
|
||||
throw new InvalidParamsException(Exception::PARAMS_NECESSARY_PARAMS_MISSING);
|
||||
}
|
||||
|
||||
$rocket->setPayload(null);
|
||||
}
|
||||
|
||||
protected function getUri(Rocket $rocket): string
|
||||
{
|
||||
return 'v3/transfer-detail/electronic-receipts?'.$rocket->getPayload()->query();
|
||||
}
|
||||
}
|
@ -1,60 +0,0 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Yansongda\Pay\Plugin\Wechat\Fund\Transfer;
|
||||
|
||||
use Yansongda\Pay\Exception\Exception;
|
||||
use Yansongda\Pay\Exception\InvalidParamsException;
|
||||
use Yansongda\Pay\Plugin\Wechat\GeneralPlugin;
|
||||
use Yansongda\Pay\Rocket;
|
||||
|
||||
/**
|
||||
* @see https://pay.weixin.qq.com/wiki/doc/apiv3/apis/chapter4_3_6.shtml
|
||||
*/
|
||||
class QueryOutBatchDetailNoPlugin extends GeneralPlugin
|
||||
{
|
||||
protected function getMethod(): string
|
||||
{
|
||||
return 'GET';
|
||||
}
|
||||
|
||||
protected function doSomething(Rocket $rocket): void
|
||||
{
|
||||
$rocket->setPayload(null);
|
||||
}
|
||||
|
||||
/**
|
||||
* @throws InvalidParamsException
|
||||
*/
|
||||
protected function getUri(Rocket $rocket): string
|
||||
{
|
||||
$payload = $rocket->getPayload();
|
||||
|
||||
if (!$payload->has('out_batch_no') || !$payload->has('out_detail_no')) {
|
||||
throw new InvalidParamsException(Exception::PARAMS_NECESSARY_PARAMS_MISSING);
|
||||
}
|
||||
|
||||
return 'v3/transfer/batches/out-batch-no/'.
|
||||
$payload->get('out_batch_no').
|
||||
'/details/out-detail-no/'.
|
||||
$payload->get('out_detail_no');
|
||||
}
|
||||
|
||||
/**
|
||||
* @throws InvalidParamsException
|
||||
*/
|
||||
protected function getPartnerUri(Rocket $rocket): string
|
||||
{
|
||||
$payload = $rocket->getPayload();
|
||||
|
||||
if (!$payload->has('out_batch_no') || !$payload->has('out_detail_no')) {
|
||||
throw new InvalidParamsException(Exception::PARAMS_NECESSARY_PARAMS_MISSING);
|
||||
}
|
||||
|
||||
return 'v3/partner-transfer/batches/out-batch-no/'.
|
||||
$payload->get('out_batch_no').
|
||||
'/details/out-detail-no/'.
|
||||
$payload->get('out_detail_no');
|
||||
}
|
||||
}
|
@ -1,64 +0,0 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Yansongda\Pay\Plugin\Wechat\Fund\Transfer;
|
||||
|
||||
use Yansongda\Pay\Exception\Exception;
|
||||
use Yansongda\Pay\Exception\InvalidParamsException;
|
||||
use Yansongda\Pay\Plugin\Wechat\GeneralPlugin;
|
||||
use Yansongda\Pay\Rocket;
|
||||
|
||||
/**
|
||||
* @see https://pay.weixin.qq.com/wiki/doc/apiv3/apis/chapter4_3_5.shtml
|
||||
*/
|
||||
class QueryOutBatchNoPlugin extends GeneralPlugin
|
||||
{
|
||||
protected function getMethod(): string
|
||||
{
|
||||
return 'GET';
|
||||
}
|
||||
|
||||
protected function doSomething(Rocket $rocket): void
|
||||
{
|
||||
$rocket->setPayload(null);
|
||||
}
|
||||
|
||||
/**
|
||||
* @throws InvalidParamsException
|
||||
*/
|
||||
protected function getUri(Rocket $rocket): string
|
||||
{
|
||||
$payload = $rocket->getPayload();
|
||||
|
||||
if (!$payload->has('out_batch_no') || !$payload->has('need_query_detail')) {
|
||||
throw new InvalidParamsException(Exception::PARAMS_NECESSARY_PARAMS_MISSING);
|
||||
}
|
||||
|
||||
$outBatchNo = $payload->get('out_batch_no');
|
||||
|
||||
$payload->forget('out_batch_no');
|
||||
|
||||
return 'v3/transfer/batches/out-batch-no/'.$outBatchNo.
|
||||
'?'.$payload->query();
|
||||
}
|
||||
|
||||
/**
|
||||
* @throws InvalidParamsException
|
||||
*/
|
||||
protected function getPartnerUri(Rocket $rocket): string
|
||||
{
|
||||
$payload = $rocket->getPayload();
|
||||
|
||||
if (!$payload->has('out_batch_no') || !$payload->has('need_query_detail')) {
|
||||
throw new InvalidParamsException(Exception::PARAMS_NECESSARY_PARAMS_MISSING);
|
||||
}
|
||||
|
||||
$outBatchNo = $payload->get('out_batch_no');
|
||||
|
||||
$payload->forget('out_batch_no');
|
||||
|
||||
return 'v3/partner-transfer/batches/out-batch-no/'.$outBatchNo.
|
||||
'?'.$payload->query();
|
||||
}
|
||||
}
|
@ -1,97 +0,0 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Yansongda\Pay\Plugin\Wechat;
|
||||
|
||||
use Closure;
|
||||
use Psr\Http\Message\RequestInterface;
|
||||
use Yansongda\Pay\Contract\PluginInterface;
|
||||
use Yansongda\Pay\Exception\ContainerException;
|
||||
use Yansongda\Pay\Exception\ServiceNotFoundException;
|
||||
use Yansongda\Pay\Logger;
|
||||
use Yansongda\Pay\Pay;
|
||||
use Yansongda\Pay\Request;
|
||||
use Yansongda\Pay\Rocket;
|
||||
|
||||
use function Yansongda\Pay\get_wechat_base_uri;
|
||||
use function Yansongda\Pay\get_wechat_config;
|
||||
|
||||
abstract class GeneralPlugin implements PluginInterface
|
||||
{
|
||||
/**
|
||||
* @throws ServiceNotFoundException
|
||||
* @throws ContainerException
|
||||
*/
|
||||
public function assembly(Rocket $rocket, Closure $next): Rocket
|
||||
{
|
||||
Logger::debug('[wechat][GeneralPlugin] 通用插件开始装载', ['rocket' => $rocket]);
|
||||
|
||||
$rocket->setRadar($this->getRequest($rocket));
|
||||
$this->doSomething($rocket);
|
||||
|
||||
Logger::info('[wechat][GeneralPlugin] 通用插件装载完毕', ['rocket' => $rocket]);
|
||||
|
||||
return $next($rocket);
|
||||
}
|
||||
|
||||
/**
|
||||
* @throws ContainerException
|
||||
* @throws ServiceNotFoundException
|
||||
*/
|
||||
protected function getRequest(Rocket $rocket): RequestInterface
|
||||
{
|
||||
return new Request(
|
||||
$this->getMethod(),
|
||||
$this->getUrl($rocket),
|
||||
$this->getHeaders(),
|
||||
);
|
||||
}
|
||||
|
||||
protected function getMethod(): string
|
||||
{
|
||||
return 'POST';
|
||||
}
|
||||
|
||||
/**
|
||||
* @throws ContainerException
|
||||
* @throws ServiceNotFoundException
|
||||
*/
|
||||
protected function getUrl(Rocket $rocket): string
|
||||
{
|
||||
$params = $rocket->getParams();
|
||||
|
||||
$url = Pay::MODE_SERVICE === (get_wechat_config($params)['mode'] ?? null) ? $this->getPartnerUri($rocket) : $this->getUri($rocket);
|
||||
|
||||
return str_starts_with($url, 'http') ? $url : (get_wechat_base_uri($params).$url);
|
||||
}
|
||||
|
||||
protected function getHeaders(): array
|
||||
{
|
||||
return [
|
||||
'Accept' => 'application/json, text/plain, application/x-gzip',
|
||||
'User-Agent' => 'yansongda/pay-v3',
|
||||
'Content-Type' => 'application/json; charset=utf-8',
|
||||
];
|
||||
}
|
||||
|
||||
protected function getConfigKey(array $params): string
|
||||
{
|
||||
$key = ($params['_type'] ?? 'mp').'_app_id';
|
||||
|
||||
if ('app_app_id' === $key) {
|
||||
$key = 'app_id';
|
||||
}
|
||||
|
||||
return $key;
|
||||
}
|
||||
|
||||
abstract protected function doSomething(Rocket $rocket): void;
|
||||
|
||||
abstract protected function getUri(Rocket $rocket): string;
|
||||
|
||||
protected function getPartnerUri(Rocket $rocket): string
|
||||
{
|
||||
return $this->getUri($rocket);
|
||||
}
|
||||
}
|
@ -1,42 +0,0 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Yansongda\Pay\Plugin\Wechat;
|
||||
|
||||
use Yansongda\Pay\Exception\ContainerException;
|
||||
use Yansongda\Pay\Exception\ServiceNotFoundException;
|
||||
use Yansongda\Pay\Packer\XmlPacker;
|
||||
use Yansongda\Pay\Rocket;
|
||||
|
||||
use function Yansongda\Pay\get_wechat_config;
|
||||
|
||||
abstract class GeneralV2Plugin extends GeneralPlugin
|
||||
{
|
||||
protected function getHeaders(): array
|
||||
{
|
||||
return [
|
||||
'Content-Type' => 'application/xml',
|
||||
'User-Agent' => 'yansongda/pay-v3',
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* @throws ContainerException
|
||||
* @throws ServiceNotFoundException
|
||||
*/
|
||||
protected function doSomething(Rocket $rocket): void
|
||||
{
|
||||
$config = get_wechat_config($rocket->getParams());
|
||||
$configKey = $this->getConfigKey($rocket->getParams());
|
||||
|
||||
$rocket->setPacker(XmlPacker::class)->mergeParams(['_version' => 'v2']);
|
||||
|
||||
$rocket->mergePayload([
|
||||
'appid' => $config[$configKey] ?? '',
|
||||
'mch_id' => $config['mch_id'] ?? '',
|
||||
]);
|
||||
}
|
||||
|
||||
abstract protected function getUri(Rocket $rocket): string;
|
||||
}
|
@ -4,34 +4,42 @@ declare(strict_types=1);
|
||||
|
||||
namespace Yansongda\Pay\Plugin\Wechat\Marketing\Coupon;
|
||||
|
||||
use Closure;
|
||||
use Yansongda\Pay\Contract\PluginInterface;
|
||||
use Yansongda\Pay\Exception\ContainerException;
|
||||
use Yansongda\Pay\Exception\ServiceNotFoundException;
|
||||
use Yansongda\Pay\Plugin\Wechat\GeneralPlugin;
|
||||
use Yansongda\Pay\Logger;
|
||||
use Yansongda\Pay\Rocket;
|
||||
|
||||
use function Yansongda\Pay\get_wechat_config;
|
||||
|
||||
/**
|
||||
* @see https://pay.weixin.qq.com/wiki/doc/apiv3/apis/chapter9_1_1.shtml
|
||||
* @see https://pay.weixin.qq.com/docs/merchant/apis/cash-coupons/stock/create-coupon-stock.html
|
||||
* @see https://pay.weixin.qq.com/docs/partner/apis/cash-coupons/stock/create-coupon-stock.html
|
||||
*/
|
||||
class CreatePlugin extends GeneralPlugin
|
||||
class CreatePlugin implements PluginInterface
|
||||
{
|
||||
/**
|
||||
* @throws ContainerException
|
||||
* @throws ServiceNotFoundException
|
||||
*/
|
||||
protected function doSomething(Rocket $rocket): void
|
||||
public function assembly(Rocket $rocket, Closure $next): Rocket
|
||||
{
|
||||
$config = get_wechat_config($rocket->getParams());
|
||||
$payload = $rocket->getPayload();
|
||||
Logger::debug('[Wechat][Marketing][Coupon][CreatePlugin] 插件开始装载', ['rocket' => $rocket]);
|
||||
|
||||
if (!$payload->has('belong_merchant')) {
|
||||
$rocket->mergePayload(['belong_merchant' => $config['mch_id']]);
|
||||
}
|
||||
}
|
||||
$params = $rocket->getParams();
|
||||
$config = get_wechat_config($params);
|
||||
$belongMerchant = $rocket->getPayload()?->get('belong_merchant') ?? $config['mch_id'];
|
||||
|
||||
protected function getUri(Rocket $rocket): string
|
||||
{
|
||||
return 'v3/marketing/favor/coupon-stocks';
|
||||
$rocket->mergePayload([
|
||||
'_method' => 'POST',
|
||||
'_url' => 'v3/marketing/favor/coupon-stocks',
|
||||
'_service_url' => 'v3/marketing/favor/coupon-stocks',
|
||||
'belong_merchant' => $belongMerchant,
|
||||
]);
|
||||
|
||||
Logger::info('[Wechat][Marketing][Coupon][CreatePlugin] 插件装载完毕', ['rocket' => $rocket]);
|
||||
|
||||
return $next($rocket);
|
||||
}
|
||||
}
|
||||
|
@ -4,47 +4,51 @@ declare(strict_types=1);
|
||||
|
||||
namespace Yansongda\Pay\Plugin\Wechat\Marketing\Coupon;
|
||||
|
||||
use Closure;
|
||||
use Yansongda\Pay\Contract\PluginInterface;
|
||||
use Yansongda\Pay\Exception\ContainerException;
|
||||
use Yansongda\Pay\Exception\Exception;
|
||||
use Yansongda\Pay\Exception\InvalidParamsException;
|
||||
use Yansongda\Pay\Exception\ServiceNotFoundException;
|
||||
use Yansongda\Pay\Plugin\Wechat\GeneralPlugin;
|
||||
use Yansongda\Pay\Logger;
|
||||
use Yansongda\Pay\Rocket;
|
||||
|
||||
use function Yansongda\Pay\get_wechat_config;
|
||||
|
||||
/**
|
||||
* @see https://pay.weixin.qq.com/wiki/doc/apiv3/apis/chapter9_1_13.shtml
|
||||
* @see https://pay.weixin.qq.com/docs/merchant/apis/cash-coupons/stock/pause-stock.html
|
||||
* @see https://pay.weixin.qq.com/docs/partner/apis/cash-coupons/stock/pause-stock.html
|
||||
*/
|
||||
class PausePlugin extends GeneralPlugin
|
||||
class PausePlugin implements PluginInterface
|
||||
{
|
||||
/**
|
||||
* @throws ContainerException
|
||||
* @throws InvalidParamsException
|
||||
* @throws ServiceNotFoundException
|
||||
*/
|
||||
protected function doSomething(Rocket $rocket): void
|
||||
public function assembly(Rocket $rocket, Closure $next): Rocket
|
||||
{
|
||||
$config = get_wechat_config($rocket->getParams());
|
||||
$payload = $rocket->getPayload();
|
||||
Logger::debug('[Wechat][Marketing][Coupon][PausePlugin] 插件开始装载', ['rocket' => $rocket]);
|
||||
|
||||
if (!$payload->has('stock_creator_mchid')) {
|
||||
$rocket->mergePayload(['stock_creator_mchid' => $config['mch_id']]);
|
||||
$params = $rocket->getParams();
|
||||
$config = get_wechat_config($params);
|
||||
$payload = $rocket->getPayload();
|
||||
$stockId = $payload?->get('stock_id') ?? null;
|
||||
$stockCreatorMchId = $payload?->get('stock_creator_mchid') ?? $config['mch_id'] ?? '';
|
||||
|
||||
if (empty($stockId)) {
|
||||
throw new InvalidParamsException(Exception::PARAMS_NECESSARY_PARAMS_MISSING, '参数异常: 暂停代金券批次,参数缺少 `stock_id`');
|
||||
}
|
||||
|
||||
$rocket->getPayload()->forget('stock_id');
|
||||
}
|
||||
$rocket->setPayload([
|
||||
'_method' => 'POST',
|
||||
'_url' => 'v3/marketing/favor/stocks/'.$stockId.'/pause',
|
||||
'_service_url' => 'v3/marketing/favor/stocks/'.$stockId.'/pause',
|
||||
'stock_creator_mchid' => $stockCreatorMchId,
|
||||
]);
|
||||
|
||||
/**
|
||||
* @throws InvalidParamsException
|
||||
*/
|
||||
protected function getUri(Rocket $rocket): string
|
||||
{
|
||||
$payload = $rocket->getPayload();
|
||||
Logger::info('[Wechat][Marketing][Coupon][PausePlugin] 插件装载完毕', ['rocket' => $rocket]);
|
||||
|
||||
if (!$payload->has('stock_id')) {
|
||||
throw new InvalidParamsException(Exception::PARAMS_NECESSARY_PARAMS_MISSING);
|
||||
}
|
||||
|
||||
return 'v3/marketing/favor/stocks/'.$payload->get('stock_id').'/pause';
|
||||
return $next($rocket);
|
||||
}
|
||||
}
|
||||
|
44
src/Plugin/Wechat/Marketing/Coupon/QueryCallbackPlugin.php
Normal file
44
src/Plugin/Wechat/Marketing/Coupon/QueryCallbackPlugin.php
Normal file
@ -0,0 +1,44 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Yansongda\Pay\Plugin\Wechat\Marketing\Coupon;
|
||||
|
||||
use Closure;
|
||||
use Yansongda\Pay\Contract\PluginInterface;
|
||||
use Yansongda\Pay\Exception\ContainerException;
|
||||
use Yansongda\Pay\Exception\ServiceNotFoundException;
|
||||
use Yansongda\Pay\Logger;
|
||||
use Yansongda\Pay\Rocket;
|
||||
|
||||
use function Yansongda\Pay\get_wechat_config;
|
||||
|
||||
/**
|
||||
* @see https://pay.weixin.qq.com/docs/merchant/apis/cash-coupons/call-back-url/query-callback.html
|
||||
* @see https://pay.weixin.qq.com/docs/partner/apis/cash-coupons/call-back-url/query-callback.html
|
||||
*/
|
||||
class QueryCallbackPlugin implements PluginInterface
|
||||
{
|
||||
/**
|
||||
* @throws ContainerException
|
||||
* @throws ServiceNotFoundException
|
||||
*/
|
||||
public function assembly(Rocket $rocket, Closure $next): Rocket
|
||||
{
|
||||
Logger::debug('[Wechat][Marketing][Coupon][QueryCallbackPlugin] 插件开始装载', ['rocket' => $rocket]);
|
||||
|
||||
$params = $rocket->getParams();
|
||||
$config = get_wechat_config($params);
|
||||
$mchId = $rocket->getPayload()?->get('mchid') ?? $config['mch_id'] ?? 'null';
|
||||
|
||||
$rocket->setPayload([
|
||||
'_method' => 'GET',
|
||||
'_url' => 'v3/marketing/favor/callbacks?mchid='.$mchId,
|
||||
'_service_url' => 'v3/marketing/favor/callbacks?mchid='.$mchId,
|
||||
]);
|
||||
|
||||
Logger::info('[Wechat][Marketing][Coupon][QueryCallbackPlugin] 插件装载完毕', ['rocket' => $rocket]);
|
||||
|
||||
return $next($rocket);
|
||||
}
|
||||
}
|
@ -4,48 +4,52 @@ declare(strict_types=1);
|
||||
|
||||
namespace Yansongda\Pay\Plugin\Wechat\Marketing\Coupon;
|
||||
|
||||
use Closure;
|
||||
use Yansongda\Pay\Contract\PluginInterface;
|
||||
use Yansongda\Pay\Exception\ContainerException;
|
||||
use Yansongda\Pay\Exception\Exception;
|
||||
use Yansongda\Pay\Exception\InvalidParamsException;
|
||||
use Yansongda\Pay\Exception\ServiceNotFoundException;
|
||||
use Yansongda\Pay\Plugin\Wechat\GeneralPlugin;
|
||||
use Yansongda\Pay\Logger;
|
||||
use Yansongda\Pay\Rocket;
|
||||
|
||||
use function Yansongda\Pay\get_wechat_config;
|
||||
use function Yansongda\Pay\get_wechat_type_key;
|
||||
|
||||
/**
|
||||
* @see https://pay.weixin.qq.com/wiki/doc/apiv3/apis/chapter9_1_6.shtml
|
||||
* @see https://pay.weixin.qq.com/docs/merchant/apis/cash-coupons/coupon/query-coupon.html
|
||||
* @see https://pay.weixin.qq.com/docs/partner/apis/cash-coupons/coupon/query-coupon.html
|
||||
*/
|
||||
class QueryCouponDetailPlugin extends GeneralPlugin
|
||||
class QueryCouponDetailPlugin implements PluginInterface
|
||||
{
|
||||
protected function getMethod(): string
|
||||
{
|
||||
return 'GET';
|
||||
}
|
||||
|
||||
protected function doSomething(Rocket $rocket): void
|
||||
{
|
||||
$rocket->setPayload(null);
|
||||
}
|
||||
|
||||
/**
|
||||
* @throws ContainerException
|
||||
* @throws InvalidParamsException
|
||||
* @throws ContainerException
|
||||
* @throws ServiceNotFoundException
|
||||
*/
|
||||
protected function getUri(Rocket $rocket): string
|
||||
public function assembly(Rocket $rocket, Closure $next): Rocket
|
||||
{
|
||||
$payload = $rocket->getPayload();
|
||||
Logger::debug('[Wechat][Marketing][Coupon][QueryCouponDetailPlugin] 插件开始装载', ['rocket' => $rocket]);
|
||||
|
||||
$params = $rocket->getParams();
|
||||
$config = get_wechat_config($params);
|
||||
$payload = $rocket->getPayload();
|
||||
$openId = $payload?->get('openid') ?? null;
|
||||
$couponId = $payload?->get('coupon_id') ?? null;
|
||||
$appId = $payload?->get('appid') ?? $config[get_wechat_type_key($params)] ?? 'null';
|
||||
|
||||
if (!$payload->has('coupon_id') || !$payload->has('openid')) {
|
||||
throw new InvalidParamsException(Exception::PARAMS_NECESSARY_PARAMS_MISSING);
|
||||
if (empty($openId) || empty($couponId)) {
|
||||
throw new InvalidParamsException(Exception::PARAMS_NECESSARY_PARAMS_MISSING, '参数异常: 查询代金券详情,参数缺少 `openid` 或 `coupon_id`');
|
||||
}
|
||||
|
||||
return 'v3/marketing/favor/users/'.
|
||||
$payload->get('openid').
|
||||
'/coupons/'.$payload->get('coupon_id').
|
||||
'?appid='.$payload->get('appid', $config[$this->getConfigKey($params)] ?? '');
|
||||
$rocket->setPayload([
|
||||
'_method' => 'GET',
|
||||
'_url' => 'v3/marketing/favor/users/'.$openId.'/coupons/'.$couponId.'?appid='.$appId,
|
||||
'_service_url' => 'v3/marketing/favor/users/'.$openId.'/coupons/'.$couponId.'?appid='.$appId,
|
||||
]);
|
||||
|
||||
Logger::info('[Wechat][Marketing][Coupon][QueryCouponDetailPlugin] 插件装载完毕', ['rocket' => $rocket]);
|
||||
|
||||
return $next($rocket);
|
||||
}
|
||||
}
|
||||
|
@ -4,47 +4,50 @@ declare(strict_types=1);
|
||||
|
||||
namespace Yansongda\Pay\Plugin\Wechat\Marketing\Coupon;
|
||||
|
||||
use Closure;
|
||||
use Yansongda\Pay\Contract\PluginInterface;
|
||||
use Yansongda\Pay\Exception\ContainerException;
|
||||
use Yansongda\Pay\Exception\Exception;
|
||||
use Yansongda\Pay\Exception\InvalidParamsException;
|
||||
use Yansongda\Pay\Exception\ServiceNotFoundException;
|
||||
use Yansongda\Pay\Plugin\Wechat\GeneralPlugin;
|
||||
use Yansongda\Pay\Logger;
|
||||
use Yansongda\Pay\Rocket;
|
||||
|
||||
use function Yansongda\Pay\get_wechat_config;
|
||||
|
||||
/**
|
||||
* @see https://pay.weixin.qq.com/wiki/doc/apiv3/apis/chapter9_1_5.shtml
|
||||
* @see https://pay.weixin.qq.com/docs/merchant/apis/cash-coupons/stock/query-stock.html
|
||||
* @see https://pay.weixin.qq.com/docs/partner/apis/cash-coupons/stock/query-stock.html
|
||||
*/
|
||||
class QueryStockDetailPlugin extends GeneralPlugin
|
||||
class QueryStockDetailPlugin implements PluginInterface
|
||||
{
|
||||
protected function getMethod(): string
|
||||
{
|
||||
return 'GET';
|
||||
}
|
||||
|
||||
protected function doSomething(Rocket $rocket): void
|
||||
{
|
||||
$rocket->setPayload(null);
|
||||
}
|
||||
|
||||
/**
|
||||
* @throws InvalidParamsException
|
||||
* @throws ContainerException
|
||||
* @throws InvalidParamsException
|
||||
* @throws ServiceNotFoundException
|
||||
*/
|
||||
protected function getUri(Rocket $rocket): string
|
||||
public function assembly(Rocket $rocket, Closure $next): Rocket
|
||||
{
|
||||
$payload = $rocket->getPayload();
|
||||
Logger::debug('[Wechat][Marketing][Coupon][QueryStockDetailPlugin] 插件开始装载', ['rocket' => $rocket]);
|
||||
|
||||
$params = $rocket->getParams();
|
||||
$config = get_wechat_config($params);
|
||||
$payload = $rocket->getPayload();
|
||||
$stockId = $payload?->get('stock_id') ?? null;
|
||||
$mchId = $payload?->get('stock_creator_mchid') ?? $config['mch_id'] ?? 'null';
|
||||
|
||||
if (!$payload->has('stock_id')) {
|
||||
throw new InvalidParamsException(Exception::PARAMS_NECESSARY_PARAMS_MISSING);
|
||||
if (empty($stockId)) {
|
||||
throw new InvalidParamsException(Exception::PARAMS_NECESSARY_PARAMS_MISSING, '参数异常: 查询代金券批次详情,参数缺少 `stock_id`');
|
||||
}
|
||||
|
||||
return 'v3/marketing/favor/stocks/'.
|
||||
$payload->get('stock_id').
|
||||
'?stock_creator_mchid='.$payload->get('stock_creator_mchid', $config['mch_id'] ?? '');
|
||||
$rocket->setPayload([
|
||||
'_method' => 'GET',
|
||||
'_url' => 'v3/marketing/favor/stocks/'.$stockId.'?stock_creator_mchid='.$mchId,
|
||||
'_service_url' => 'v3/marketing/favor/stocks/'.$stockId.'?stock_creator_mchid='.$mchId,
|
||||
]);
|
||||
|
||||
Logger::info('[Wechat][Marketing][Coupon][QueryStockDetailPlugin] 插件装载完毕', ['rocket' => $rocket]);
|
||||
|
||||
return $next($rocket);
|
||||
}
|
||||
}
|
||||
|
@ -4,55 +4,61 @@ declare(strict_types=1);
|
||||
|
||||
namespace Yansongda\Pay\Plugin\Wechat\Marketing\Coupon;
|
||||
|
||||
use Closure;
|
||||
use Yansongda\Pay\Contract\PluginInterface;
|
||||
use Yansongda\Pay\Exception\ContainerException;
|
||||
use Yansongda\Pay\Exception\Exception;
|
||||
use Yansongda\Pay\Exception\InvalidParamsException;
|
||||
use Yansongda\Pay\Exception\ServiceNotFoundException;
|
||||
use Yansongda\Pay\Plugin\Wechat\GeneralPlugin;
|
||||
use Yansongda\Pay\Logger;
|
||||
use Yansongda\Pay\Rocket;
|
||||
use Yansongda\Supports\Collection;
|
||||
|
||||
use function Yansongda\Pay\get_wechat_config;
|
||||
|
||||
/**
|
||||
* @see https://pay.weixin.qq.com/wiki/doc/apiv3/apis/chapter9_1_8.shtml
|
||||
* @see https://pay.weixin.qq.com/docs/merchant/apis/cash-coupons/stock/list-available-singleitems.html
|
||||
* @see https://pay.weixin.qq.com/docs/partner/apis/cash-coupons/stock/list-available-singleitems.html
|
||||
*/
|
||||
class QueryStockItemsPlugin extends GeneralPlugin
|
||||
class QueryStockItemsPlugin implements PluginInterface
|
||||
{
|
||||
protected function getMethod(): string
|
||||
{
|
||||
return 'GET';
|
||||
}
|
||||
|
||||
protected function doSomething(Rocket $rocket): void
|
||||
{
|
||||
$rocket->setPayload(null);
|
||||
}
|
||||
|
||||
/**
|
||||
* @throws InvalidParamsException
|
||||
* @throws ContainerException
|
||||
* @throws InvalidParamsException
|
||||
* @throws ServiceNotFoundException
|
||||
*/
|
||||
protected function getUri(Rocket $rocket): string
|
||||
public function assembly(Rocket $rocket, Closure $next): Rocket
|
||||
{
|
||||
$payload = $rocket->getPayload();
|
||||
Logger::debug('[Wechat][Marketing][Coupon][QueryStockItemsPlugin] 插件开始装载', ['rocket' => $rocket]);
|
||||
|
||||
$params = $rocket->getParams();
|
||||
$config = get_wechat_config($params);
|
||||
$payload = $rocket->getPayload();
|
||||
$stockId = $payload?->get('stock_id') ?? null;
|
||||
|
||||
if (!$payload->has('stock_id')) {
|
||||
throw new InvalidParamsException(Exception::PARAMS_NECESSARY_PARAMS_MISSING);
|
||||
if (empty($stockId)) {
|
||||
throw new InvalidParamsException(Exception::PARAMS_NECESSARY_PARAMS_MISSING, '参数异常: 查询代金券可用单品,参数缺少 `stock_id`');
|
||||
}
|
||||
|
||||
if (!$payload->has('stock_creator_mchid')) {
|
||||
$rocket->mergePayload(['stock_creator_mchid' => $config['mch_id']]);
|
||||
$rocket->setPayload([
|
||||
'_method' => 'GET',
|
||||
'_url' => 'v3/marketing/favor/stocks/'.$stockId.'/items?'.$this->normal($payload, $config),
|
||||
'_service_url' => 'v3/marketing/favor/stocks/'.$stockId.'/items?'.$this->normal($payload, $config),
|
||||
]);
|
||||
|
||||
Logger::info('[Wechat][Marketing][Coupon][QueryStockItemsPlugin] 插件装载完毕', ['rocket' => $rocket]);
|
||||
|
||||
return $next($rocket);
|
||||
}
|
||||
|
||||
public function normal(Collection $payload, array $config): string
|
||||
{
|
||||
$stockCreatorMchId = $payload->get('stock_creator_mchid');
|
||||
|
||||
if (is_null($stockCreatorMchId)) {
|
||||
$payload->set('stock_creator_mchid', $config['mch_id'] ?? '');
|
||||
}
|
||||
|
||||
$query = $rocket->getPayload()->all();
|
||||
|
||||
unset($query['stock_id']);
|
||||
|
||||
return 'v3/marketing/favor/stocks/'.
|
||||
$payload->get('stock_id').
|
||||
'/items?'.http_build_query($query);
|
||||
return $payload->except('stock_id')->query();
|
||||
}
|
||||
}
|
||||
|
@ -4,55 +4,61 @@ declare(strict_types=1);
|
||||
|
||||
namespace Yansongda\Pay\Plugin\Wechat\Marketing\Coupon;
|
||||
|
||||
use Closure;
|
||||
use Yansongda\Pay\Contract\PluginInterface;
|
||||
use Yansongda\Pay\Exception\ContainerException;
|
||||
use Yansongda\Pay\Exception\Exception;
|
||||
use Yansongda\Pay\Exception\InvalidParamsException;
|
||||
use Yansongda\Pay\Exception\ServiceNotFoundException;
|
||||
use Yansongda\Pay\Plugin\Wechat\GeneralPlugin;
|
||||
use Yansongda\Pay\Logger;
|
||||
use Yansongda\Pay\Rocket;
|
||||
use Yansongda\Supports\Collection;
|
||||
|
||||
use function Yansongda\Pay\get_wechat_config;
|
||||
|
||||
/**
|
||||
* @see https://pay.weixin.qq.com/wiki/doc/apiv3/apis/chapter9_1_7.shtml
|
||||
* @see https://pay.weixin.qq.com/docs/merchant/apis/cash-coupons/stock/list-available-merchants.html
|
||||
* @see https://pay.weixin.qq.com/docs/partner/apis/cash-coupons/stock/list-available-merchants.html
|
||||
*/
|
||||
class QueryStockMerchantsPlugin extends GeneralPlugin
|
||||
class QueryStockMerchantsPlugin implements PluginInterface
|
||||
{
|
||||
protected function getMethod(): string
|
||||
{
|
||||
return 'GET';
|
||||
}
|
||||
|
||||
protected function doSomething(Rocket $rocket): void
|
||||
{
|
||||
$rocket->setPayload(null);
|
||||
}
|
||||
|
||||
/**
|
||||
* @throws InvalidParamsException
|
||||
* @throws ContainerException
|
||||
* @throws InvalidParamsException
|
||||
* @throws ServiceNotFoundException
|
||||
*/
|
||||
protected function getUri(Rocket $rocket): string
|
||||
public function assembly(Rocket $rocket, Closure $next): Rocket
|
||||
{
|
||||
$payload = $rocket->getPayload();
|
||||
Logger::debug('[Wechat][Marketing][Coupon][QueryStockMerchantsPlugin] 插件开始装载', ['rocket' => $rocket]);
|
||||
|
||||
$params = $rocket->getParams();
|
||||
$config = get_wechat_config($params);
|
||||
$payload = $rocket->getPayload();
|
||||
$stockId = $payload?->get('stock_id') ?? null;
|
||||
|
||||
if (!$payload->has('stock_creator_mchid')) {
|
||||
$rocket->mergePayload(['stock_creator_mchid' => $config['mch_id']]);
|
||||
if (empty($stockId)) {
|
||||
throw new InvalidParamsException(Exception::PARAMS_NECESSARY_PARAMS_MISSING, '参数异常: 查询代金券可用商户,参数缺少 `stock_id`');
|
||||
}
|
||||
|
||||
if (!$payload->has('stock_id')) {
|
||||
throw new InvalidParamsException(Exception::PARAMS_NECESSARY_PARAMS_MISSING);
|
||||
$rocket->setPayload([
|
||||
'_method' => 'GET',
|
||||
'_url' => 'v3/marketing/favor/stocks/'.$stockId.'/merchants?'.$this->normal($payload, $config),
|
||||
'_service_url' => 'v3/marketing/favor/stocks/'.$stockId.'/merchants?'.$this->normal($payload, $config),
|
||||
]);
|
||||
|
||||
Logger::info('[Wechat][Marketing][Coupon][QueryStockMerchantsPlugin] 插件装载完毕', ['rocket' => $rocket]);
|
||||
|
||||
return $next($rocket);
|
||||
}
|
||||
|
||||
public function normal(Collection $payload, array $config): string
|
||||
{
|
||||
$stockCreatorMchId = $payload->get('stock_creator_mchid');
|
||||
|
||||
if (is_null($stockCreatorMchId)) {
|
||||
$payload->set('stock_creator_mchid', $config['mch_id'] ?? '');
|
||||
}
|
||||
|
||||
$query = $rocket->getPayload()->all();
|
||||
|
||||
unset($query['stock_id']);
|
||||
|
||||
return 'v3/marketing/favor/stocks/'.
|
||||
$payload->get('stock_id').
|
||||
'/merchants?'.http_build_query($query);
|
||||
return $payload->except('stock_id')->query();
|
||||
}
|
||||
}
|
||||
|
@ -4,39 +4,40 @@ declare(strict_types=1);
|
||||
|
||||
namespace Yansongda\Pay\Plugin\Wechat\Marketing\Coupon;
|
||||
|
||||
use Closure;
|
||||
use Yansongda\Pay\Contract\PluginInterface;
|
||||
use Yansongda\Pay\Exception\Exception;
|
||||
use Yansongda\Pay\Exception\InvalidParamsException;
|
||||
use Yansongda\Pay\Plugin\Wechat\GeneralPlugin;
|
||||
use Yansongda\Pay\Logger;
|
||||
use Yansongda\Pay\Rocket;
|
||||
|
||||
/**
|
||||
* @see https://pay.weixin.qq.com/wiki/doc/apiv3/apis/chapter9_1_11.shtml
|
||||
* @see https://pay.weixin.qq.com/docs/merchant/apis/cash-coupons/stock/refund-flow.html
|
||||
* @see https://pay.weixin.qq.com/docs/partner/apis/cash-coupons/stock/refund-flow.html
|
||||
*/
|
||||
class QueryStockRefundFlowPlugin extends GeneralPlugin
|
||||
class QueryStockRefundFlowPlugin implements PluginInterface
|
||||
{
|
||||
protected function getMethod(): string
|
||||
{
|
||||
return 'GET';
|
||||
}
|
||||
|
||||
protected function doSomething(Rocket $rocket): void
|
||||
{
|
||||
$rocket->setPayload(null);
|
||||
}
|
||||
|
||||
/**
|
||||
* @throws InvalidParamsException
|
||||
*/
|
||||
protected function getUri(Rocket $rocket): string
|
||||
public function assembly(Rocket $rocket, Closure $next): Rocket
|
||||
{
|
||||
$payload = $rocket->getPayload();
|
||||
Logger::debug('[Wechat][Marketing][Coupon][QueryStockRefundFlowPlugin] 插件开始装载', ['rocket' => $rocket]);
|
||||
|
||||
if (!$payload->has('stock_id')) {
|
||||
throw new InvalidParamsException(Exception::PARAMS_NECESSARY_PARAMS_MISSING);
|
||||
$stockId = $rocket->getPayload()?->get('stock_id') ?? null;
|
||||
|
||||
if (empty($stockId)) {
|
||||
throw new InvalidParamsException(Exception::PARAMS_NECESSARY_PARAMS_MISSING, '参数异常: 下载批次退款明细,参数缺少 `stock_id`');
|
||||
}
|
||||
|
||||
return 'v3/marketing/favor/stocks/'.
|
||||
$payload->get('stock_id').
|
||||
'/refund-flow';
|
||||
$rocket->setPayload([
|
||||
'_method' => 'GET',
|
||||
'_url' => 'v3/marketing/favor/stocks/'.$stockId.'/refund-flow',
|
||||
'_service_url' => 'v3/marketing/favor/stocks/'.$stockId.'/refund-flow',
|
||||
]);
|
||||
|
||||
Logger::info('[Wechat][Marketing][Coupon][QueryStockRefundFlowPlugin] 插件装载完毕', ['rocket' => $rocket]);
|
||||
|
||||
return $next($rocket);
|
||||
}
|
||||
}
|
||||
|
@ -4,39 +4,40 @@ declare(strict_types=1);
|
||||
|
||||
namespace Yansongda\Pay\Plugin\Wechat\Marketing\Coupon;
|
||||
|
||||
use Closure;
|
||||
use Yansongda\Pay\Contract\PluginInterface;
|
||||
use Yansongda\Pay\Exception\Exception;
|
||||
use Yansongda\Pay\Exception\InvalidParamsException;
|
||||
use Yansongda\Pay\Plugin\Wechat\GeneralPlugin;
|
||||
use Yansongda\Pay\Logger;
|
||||
use Yansongda\Pay\Rocket;
|
||||
|
||||
/**
|
||||
* @see https://pay.weixin.qq.com/wiki/doc/apiv3/apis/chapter9_1_10.shtml
|
||||
* @see https://pay.weixin.qq.com/docs/merchant/apis/cash-coupons/stock/use-flow.html
|
||||
* @see https://pay.weixin.qq.com/docs/partner/apis/cash-coupons/stock/use-flow.html
|
||||
*/
|
||||
class QueryStockUseFlowPlugin extends GeneralPlugin
|
||||
class QueryStockUseFlowPlugin implements PluginInterface
|
||||
{
|
||||
protected function getMethod(): string
|
||||
{
|
||||
return 'GET';
|
||||
}
|
||||
|
||||
protected function doSomething(Rocket $rocket): void
|
||||
{
|
||||
$rocket->setPayload(null);
|
||||
}
|
||||
|
||||
/**
|
||||
* @throws InvalidParamsException
|
||||
*/
|
||||
protected function getUri(Rocket $rocket): string
|
||||
public function assembly(Rocket $rocket, Closure $next): Rocket
|
||||
{
|
||||
$payload = $rocket->getPayload();
|
||||
Logger::debug('[Wechat][Marketing][Coupon][QueryStockUseFlowPlugin] 插件开始装载', ['rocket' => $rocket]);
|
||||
|
||||
if (!$payload->has('stock_id')) {
|
||||
throw new InvalidParamsException(Exception::PARAMS_NECESSARY_PARAMS_MISSING);
|
||||
$stockId = $rocket->getPayload()?->get('stock_id') ?? null;
|
||||
|
||||
if (empty($stockId)) {
|
||||
throw new InvalidParamsException(Exception::PARAMS_NECESSARY_PARAMS_MISSING, '参数异常: 下载批次核销明细,参数缺少 `stock_id`');
|
||||
}
|
||||
|
||||
return 'v3/marketing/favor/stocks/'.
|
||||
$payload->get('stock_id').
|
||||
'/use-flow';
|
||||
$rocket->setPayload([
|
||||
'_method' => 'GET',
|
||||
'_url' => 'v3/marketing/favor/stocks/'.$stockId.'/use-flow',
|
||||
'_service_url' => 'v3/marketing/favor/stocks/'.$stockId.'/use-flow',
|
||||
]);
|
||||
|
||||
Logger::info('[Wechat][Marketing][Coupon][QueryStockUseFlowPlugin] 插件装载完毕', ['rocket' => $rocket]);
|
||||
|
||||
return $next($rocket);
|
||||
}
|
||||
}
|
||||
|
@ -4,41 +4,60 @@ declare(strict_types=1);
|
||||
|
||||
namespace Yansongda\Pay\Plugin\Wechat\Marketing\Coupon;
|
||||
|
||||
use Closure;
|
||||
use Yansongda\Pay\Contract\PluginInterface;
|
||||
use Yansongda\Pay\Exception\ContainerException;
|
||||
use Yansongda\Pay\Exception\Exception;
|
||||
use Yansongda\Pay\Exception\InvalidParamsException;
|
||||
use Yansongda\Pay\Exception\ServiceNotFoundException;
|
||||
use Yansongda\Pay\Plugin\Wechat\GeneralPlugin;
|
||||
use Yansongda\Pay\Logger;
|
||||
use Yansongda\Pay\Rocket;
|
||||
use Yansongda\Supports\Collection;
|
||||
|
||||
use function Yansongda\Pay\get_wechat_config;
|
||||
|
||||
/**
|
||||
* @see https://pay.weixin.qq.com/wiki/doc/apiv3/apis/chapter9_1_4.shtml
|
||||
* @see https://pay.weixin.qq.com/docs/merchant/apis/cash-coupons/stock/list-stocks.html
|
||||
* @see https://pay.weixin.qq.com/docs/partner/apis/cash-coupons/stock/list-stocks.html
|
||||
*/
|
||||
class QueryStocksPlugin extends GeneralPlugin
|
||||
class QueryStocksPlugin implements PluginInterface
|
||||
{
|
||||
protected function getMethod(): string
|
||||
{
|
||||
return 'GET';
|
||||
}
|
||||
|
||||
protected function doSomething(Rocket $rocket): void
|
||||
{
|
||||
$rocket->setPayload(null);
|
||||
}
|
||||
|
||||
/**
|
||||
* @throws ContainerException
|
||||
* @throws InvalidParamsException
|
||||
* @throws ServiceNotFoundException
|
||||
*/
|
||||
protected function getUri(Rocket $rocket): string
|
||||
public function assembly(Rocket $rocket, Closure $next): Rocket
|
||||
{
|
||||
Logger::debug('[Wechat][Marketing][Coupon][QueryStocksPlugin] 插件开始装载', ['rocket' => $rocket]);
|
||||
|
||||
$params = $rocket->getParams();
|
||||
$config = get_wechat_config($params);
|
||||
$payload = $rocket->getPayload();
|
||||
|
||||
if (!$rocket->getPayload()->has('stock_creator_mchid')) {
|
||||
$rocket->mergePayload(['stock_creator_mchid' => $config['mch_id']]);
|
||||
if (is_null($payload)) {
|
||||
throw new InvalidParamsException(Exception::PARAMS_NECESSARY_PARAMS_MISSING, '参数异常: 缺少代金券相关参数');
|
||||
}
|
||||
|
||||
return 'v3/marketing/favor/stocks?'.$rocket->getPayload()->query();
|
||||
$rocket->setPayload([
|
||||
'_method' => 'GET',
|
||||
'_url' => 'v3/marketing/favor/stocks?'.$this->normal($payload, $config),
|
||||
'_service_url' => 'v3/marketing/favor/stocks?'.$this->normal($payload, $config),
|
||||
]);
|
||||
|
||||
Logger::info('[Wechat][Marketing][Coupon][QueryStocksPlugin] 插件装载完毕', ['rocket' => $rocket]);
|
||||
|
||||
return $next($rocket);
|
||||
}
|
||||
|
||||
public function normal(Collection $payload, array $config): string
|
||||
{
|
||||
$stockCreatorMchId = $payload->get('stock_creator_mchid');
|
||||
|
||||
if (is_null($stockCreatorMchId)) {
|
||||
$payload->set('stock_creator_mchid', $config['mch_id'] ?? '');
|
||||
}
|
||||
|
||||
return $payload->query();
|
||||
}
|
||||
}
|
||||
|
@ -4,59 +4,62 @@ declare(strict_types=1);
|
||||
|
||||
namespace Yansongda\Pay\Plugin\Wechat\Marketing\Coupon;
|
||||
|
||||
use Closure;
|
||||
use Yansongda\Pay\Contract\PluginInterface;
|
||||
use Yansongda\Pay\Exception\ContainerException;
|
||||
use Yansongda\Pay\Exception\Exception;
|
||||
use Yansongda\Pay\Exception\InvalidParamsException;
|
||||
use Yansongda\Pay\Exception\ServiceNotFoundException;
|
||||
use Yansongda\Pay\Plugin\Wechat\GeneralPlugin;
|
||||
use Yansongda\Pay\Logger;
|
||||
use Yansongda\Pay\Rocket;
|
||||
use Yansongda\Supports\Collection;
|
||||
|
||||
use function Yansongda\Pay\get_wechat_config;
|
||||
use function Yansongda\Pay\get_wechat_type_key;
|
||||
|
||||
/**
|
||||
* @see https://pay.weixin.qq.com/wiki/doc/apiv3/apis/chapter9_1_9.shtml
|
||||
* @see https://pay.weixin.qq.com/docs/merchant/apis/cash-coupons/coupon/list-coupons-by-filter.html
|
||||
* @see https://pay.weixin.qq.com/docs/partner/apis/cash-coupons/coupon/list-coupons-by-filter.html
|
||||
*/
|
||||
class QueryUserCouponsPlugin extends GeneralPlugin
|
||||
class QueryUserCouponsPlugin implements PluginInterface
|
||||
{
|
||||
protected function getMethod(): string
|
||||
{
|
||||
return 'GET';
|
||||
}
|
||||
|
||||
protected function doSomething(Rocket $rocket): void
|
||||
{
|
||||
$rocket->setPayload(null);
|
||||
}
|
||||
|
||||
/**
|
||||
* @throws InvalidParamsException
|
||||
* @throws ContainerException
|
||||
* @throws ServiceNotFoundException
|
||||
*/
|
||||
protected function getUri(Rocket $rocket): string
|
||||
public function assembly(Rocket $rocket, Closure $next): Rocket
|
||||
{
|
||||
$payload = $rocket->getPayload();
|
||||
Logger::debug('[Wechat][Marketing][Coupon][QueryUserCouponsPlugin] 插件开始装载', ['rocket' => $rocket]);
|
||||
|
||||
$params = $rocket->getParams();
|
||||
$config = get_wechat_config($params);
|
||||
$payload = $rocket->getPayload();
|
||||
$openId = $payload?->get('openid') ?? null;
|
||||
|
||||
if (!$payload->has('openid')) {
|
||||
throw new InvalidParamsException(Exception::PARAMS_NECESSARY_PARAMS_MISSING);
|
||||
if (empty($openId)) {
|
||||
throw new InvalidParamsException(Exception::PARAMS_NECESSARY_PARAMS_MISSING, '参数异常: 根据商户号查用户的券,参数缺少 `openid`');
|
||||
}
|
||||
|
||||
if (!$payload->has('appid')) {
|
||||
$rocket->mergePayload(['appid' => $config[$this->getConfigKey($params)] ?? '']);
|
||||
$rocket->setPayload([
|
||||
'_method' => 'GET',
|
||||
'_url' => 'v3/marketing/favor/users/'.$openId.'/coupons?'.$this->normal($payload, $params, $config),
|
||||
'_service_url' => 'v3/marketing/favor/users/'.$openId.'/coupons?'.$this->normal($payload, $params, $config),
|
||||
]);
|
||||
|
||||
Logger::info('[Wechat][Marketing][Coupon][QueryUserCouponsPlugin] 插件装载完毕', ['rocket' => $rocket]);
|
||||
|
||||
return $next($rocket);
|
||||
}
|
||||
|
||||
protected function normal(Collection $payload, array $params, array $config): string
|
||||
{
|
||||
$appId = $payload->get('appid');
|
||||
|
||||
if (is_null($appId)) {
|
||||
$payload->set('appid', $config[get_wechat_type_key($params)] ?? '');
|
||||
}
|
||||
|
||||
if (!$payload->has('creator_mchid')) {
|
||||
$rocket->mergePayload(['creator_mchid' => $config['mch_id']]);
|
||||
}
|
||||
|
||||
$query = $rocket->getPayload()->all();
|
||||
|
||||
unset($query['openid']);
|
||||
|
||||
return 'v3/marketing/favor/users/'.
|
||||
$payload->get('openid').
|
||||
'/coupons?'.http_build_query($query);
|
||||
return $payload->except('openid')->query();
|
||||
}
|
||||
}
|
||||
|
@ -4,48 +4,51 @@ declare(strict_types=1);
|
||||
|
||||
namespace Yansongda\Pay\Plugin\Wechat\Marketing\Coupon;
|
||||
|
||||
use Closure;
|
||||
use Yansongda\Pay\Contract\PluginInterface;
|
||||
use Yansongda\Pay\Exception\ContainerException;
|
||||
use Yansongda\Pay\Exception\Exception;
|
||||
use Yansongda\Pay\Exception\InvalidParamsException;
|
||||
use Yansongda\Pay\Exception\ServiceNotFoundException;
|
||||
use Yansongda\Pay\Plugin\Wechat\GeneralPlugin;
|
||||
use Yansongda\Pay\Logger;
|
||||
use Yansongda\Pay\Rocket;
|
||||
|
||||
use function Yansongda\Pay\get_wechat_config;
|
||||
|
||||
/**
|
||||
* @see https://pay.weixin.qq.com/wiki/doc/apiv3/apis/chapter9_1_14.shtml
|
||||
* @see https://pay.weixin.qq.com/docs/merchant/apis/cash-coupons/stock/restart-stock.html
|
||||
* @see https://pay.weixin.qq.com/docs/partner/apis/cash-coupons/stock/restart-stock.html
|
||||
*/
|
||||
class RestartPlugin extends GeneralPlugin
|
||||
class RestartPlugin implements PluginInterface
|
||||
{
|
||||
/**
|
||||
* @throws ContainerException
|
||||
* @throws InvalidParamsException
|
||||
* @throws ServiceNotFoundException
|
||||
*/
|
||||
protected function doSomething(Rocket $rocket): void
|
||||
public function assembly(Rocket $rocket, Closure $next): Rocket
|
||||
{
|
||||
$payload = $rocket->getPayload();
|
||||
Logger::debug('[Wechat][Marketing][Coupon][RestartPlugin] 插件开始装载', ['rocket' => $rocket]);
|
||||
|
||||
$params = $rocket->getParams();
|
||||
$config = get_wechat_config($params);
|
||||
|
||||
if (!$payload->has('stock_creator_mchid')) {
|
||||
$rocket->mergePayload(['stock_creator_mchid' => $config['mch_id']]);
|
||||
}
|
||||
|
||||
$rocket->getPayload()->forget('stock_id');
|
||||
}
|
||||
|
||||
/**
|
||||
* @throws InvalidParamsException
|
||||
*/
|
||||
protected function getUri(Rocket $rocket): string
|
||||
{
|
||||
$payload = $rocket->getPayload();
|
||||
$stockId = $payload?->get('stock_id') ?? null;
|
||||
$stockCreatorMchId = $payload?->get('stock_creator_mchid') ?? $config['mch_id'] ?? '';
|
||||
|
||||
if (!$payload->has('stock_id')) {
|
||||
throw new InvalidParamsException(Exception::PARAMS_NECESSARY_PARAMS_MISSING);
|
||||
if (empty($stockId)) {
|
||||
throw new InvalidParamsException(Exception::PARAMS_NECESSARY_PARAMS_MISSING, '参数异常: 激活代金券,参数缺少 `stock_id`');
|
||||
}
|
||||
|
||||
return 'v3/marketing/favor/stocks/'.$payload->get('stock_id').'/restart';
|
||||
$rocket->setPayload([
|
||||
'_method' => 'POST',
|
||||
'_url' => 'v3/marketing/favor/stocks/'.$stockId.'/restart',
|
||||
'_service_url' => 'v3/marketing/favor/stocks/'.$stockId.'/restart',
|
||||
'stock_creator_mchid' => $stockCreatorMchId,
|
||||
]);
|
||||
|
||||
Logger::info('[Wechat][Marketing][Coupon][RestartPlugin] 插件装载完毕', ['rocket' => $rocket]);
|
||||
|
||||
return $next($rocket);
|
||||
}
|
||||
}
|
||||
|
@ -4,51 +4,67 @@ declare(strict_types=1);
|
||||
|
||||
namespace Yansongda\Pay\Plugin\Wechat\Marketing\Coupon;
|
||||
|
||||
use Closure;
|
||||
use Yansongda\Pay\Contract\PluginInterface;
|
||||
use Yansongda\Pay\Exception\ContainerException;
|
||||
use Yansongda\Pay\Exception\Exception;
|
||||
use Yansongda\Pay\Exception\InvalidParamsException;
|
||||
use Yansongda\Pay\Exception\ServiceNotFoundException;
|
||||
use Yansongda\Pay\Plugin\Wechat\GeneralPlugin;
|
||||
use Yansongda\Pay\Logger;
|
||||
use Yansongda\Pay\Rocket;
|
||||
use Yansongda\Supports\Collection;
|
||||
|
||||
use function Yansongda\Pay\get_wechat_config;
|
||||
use function Yansongda\Pay\get_wechat_type_key;
|
||||
|
||||
/**
|
||||
* @see https://pay.weixin.qq.com/wiki/doc/apiv3/apis/chapter9_1_2.shtml
|
||||
* @see https://pay.weixin.qq.com/docs/merchant/apis/cash-coupons/coupon/send-coupon.html
|
||||
* @see https://pay.weixin.qq.com/docs/partner/apis/cash-coupons/coupon/send-coupon.html
|
||||
*/
|
||||
class SendPlugin extends GeneralPlugin
|
||||
class SendPlugin implements PluginInterface
|
||||
{
|
||||
/**
|
||||
* @throws InvalidParamsException
|
||||
* @throws ContainerException
|
||||
* @throws ServiceNotFoundException
|
||||
*/
|
||||
protected function doSomething(Rocket $rocket): void
|
||||
public function assembly(Rocket $rocket, Closure $next): Rocket
|
||||
{
|
||||
Logger::debug('[Wechat][Marketing][Coupon][SendPlugin] 插件开始装载', ['rocket' => $rocket]);
|
||||
|
||||
$params = $rocket->getParams();
|
||||
$config = get_wechat_config($params);
|
||||
$payload = $rocket->getPayload();
|
||||
$openId = $payload?->get('openid') ?? null;
|
||||
|
||||
if (!$rocket->getPayload()->has('appid')) {
|
||||
$rocket->mergePayload(['appid' => $config[$this->getConfigKey($params)] ?? '']);
|
||||
if (empty($openId)) {
|
||||
throw new InvalidParamsException(Exception::PARAMS_NECESSARY_PARAMS_MISSING, '参数异常: 发放指定批次的代金券,参数缺少 `openid`');
|
||||
}
|
||||
|
||||
if (!$rocket->getPayload()->has('stock_creator_mchid')) {
|
||||
$rocket->mergePayload(['stock_creator_mchid' => $config['mch_id']]);
|
||||
}
|
||||
$rocket->setPayload(array_merge(
|
||||
[
|
||||
'_method' => 'POST',
|
||||
'_url' => 'v3/marketing/favor/users/'.$openId.'/coupons',
|
||||
'_service_url' => 'v3/marketing/favor/users/'.$openId.'/coupons',
|
||||
],
|
||||
$this->normal($payload, $params, $config),
|
||||
));
|
||||
|
||||
$rocket->getPayload()->forget('openid');
|
||||
Logger::info('[Wechat][Marketing][Coupon][SendPlugin] 插件装载完毕', ['rocket' => $rocket]);
|
||||
|
||||
return $next($rocket);
|
||||
}
|
||||
|
||||
/**
|
||||
* @throws InvalidParamsException
|
||||
*/
|
||||
protected function getUri(Rocket $rocket): string
|
||||
protected function normal(Collection $payload, array $params, array $config): array
|
||||
{
|
||||
$payload = $rocket->getPayload();
|
||||
|
||||
if (!$payload->has('openid')) {
|
||||
throw new InvalidParamsException(Exception::PARAMS_NECESSARY_PARAMS_MISSING);
|
||||
if (empty($payload->get('appid'))) {
|
||||
$payload->set('appid', $config[get_wechat_type_key($params)] ?? '');
|
||||
}
|
||||
|
||||
return 'v3/marketing/favor/users/'.$payload->get('openid').'/coupons';
|
||||
if (empty($payload->get('stock_creator_mchid'))) {
|
||||
$payload->set('stock_creator_mchid', $config['mch_id'] ?? '');
|
||||
}
|
||||
|
||||
return $payload->except('openid')->all();
|
||||
}
|
||||
}
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user