- 框架初始化
 - 安装插件
 - 修复PHP8.4报错
This commit is contained in:
2025-04-19 17:21:20 +08:00
commit c6a4e1f5f6
5306 changed files with 967782 additions and 0 deletions

View File

@@ -0,0 +1,71 @@
<?php
declare(strict_types=1);
namespace Yansongda\Pay\Plugin\Wechat;
use Closure;
use Psr\Http\Message\ServerRequestInterface;
use Yansongda\Pay\Contract\PluginInterface;
use Yansongda\Pay\Direction\NoHttpRequestDirection;
use Yansongda\Pay\Exception\ContainerException;
use Yansongda\Pay\Exception\Exception;
use Yansongda\Pay\Exception\InvalidConfigException;
use Yansongda\Pay\Exception\InvalidParamsException;
use Yansongda\Pay\Exception\InvalidResponseException;
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\verify_wechat_sign;
class CallbackPlugin implements PluginInterface
{
/**
* @throws ContainerException
* @throws InvalidConfigException
* @throws ServiceNotFoundException
* @throws InvalidResponseException
* @throws InvalidParamsException
*/
public function assembly(Rocket $rocket, Closure $next): Rocket
{
Logger::debug('[wechat][CallbackPlugin] 插件开始装载', ['rocket' => $rocket]);
$this->formatRequestAndParams($rocket);
/* @phpstan-ignore-next-line */
verify_wechat_sign($rocket->getDestinationOrigin(), $rocket->getParams());
$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());
$rocket->setDestination(new Collection($body));
Logger::info('[wechat][CallbackPlugin] 插件装载完毕', ['rocket' => $rocket]);
return $next($rocket);
}
/**
* @throws InvalidParamsException
*/
protected function formatRequestAndParams(Rocket $rocket): void
{
$request = $rocket->getParams()['request'] ?? null;
if (!$request instanceof ServerRequestInterface) {
throw new InvalidParamsException(Exception::REQUEST_NULL_ERROR);
}
$rocket->setDestination(clone $request)
->setDestinationOrigin($request)
->setParams($rocket->getParams()['params'] ?? [])
;
}
}

View File

@@ -0,0 +1,55 @@
<?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::NOT_IN_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);
}
}

View File

@@ -0,0 +1,60 @@
<?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::NOT_IN_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::MISSING_NECESSARY_PARAMS);
}
protected function getMethod(): string
{
return 'GET';
}
protected function doSomething(Rocket $rocket): void
{
$rocket->setPayload(null);
}
}

View File

@@ -0,0 +1,56 @@
<?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::NOT_IN_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::MISSING_NECESSARY_PARAMS);
}
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);
}
}

View File

@@ -0,0 +1,56 @@
<?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::NOT_IN_SERVICE_MODE);
}
/**
* @throws InvalidParamsException
*/
protected function getPartnerUri(Rocket $rocket): string
{
$payload = $rocket->getPayload();
if (!$payload->has('refund_id')) {
throw new InvalidParamsException(Exception::MISSING_NECESSARY_PARAMS);
}
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'] ?? ''),
]));
}
}

View File

@@ -0,0 +1,38 @@
<?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::MISSING_NECESSARY_PARAMS);
}
return 'v3/merchant/fund/dayendbalance/'.
$payload->get('account_type').
'?date='.$payload->get('date');
}
}

View File

@@ -0,0 +1,37 @@
<?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::MISSING_NECESSARY_PARAMS);
}
return 'v3/merchant/fund/balance/'.
$payload->get('account_type');
}
}

View File

@@ -0,0 +1,83 @@
<?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);
}
}

View File

@@ -0,0 +1,89 @@
<?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;
}
}

View File

@@ -0,0 +1,45 @@
<?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';
}
}

View File

@@ -0,0 +1,43 @@
<?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::MISSING_NECESSARY_PARAMS);
}
return $payload->get('download_url');
}
protected function getMethod(): string
{
return 'GET';
}
protected function doSomething(Rocket $rocket): void
{
$rocket->setDirection(OriginResponseDirection::class);
$rocket->setPayload(null);
}
}

View File

@@ -0,0 +1,42 @@
<?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::MISSING_NECESSARY_PARAMS);
}
return 'v3/profitsharing/transactions/'.
$payload->get('transaction_id').
'/amounts';
}
}

View File

@@ -0,0 +1,49 @@
<?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::METHOD_NOT_SUPPORTED);
}
return 'v3/profitsharing/merchant-configs/'.
$payload->get('sub_mchid', $config['sub_mch_id'] ?? '');
}
}

View File

@@ -0,0 +1,56 @@
<?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::MISSING_NECESSARY_PARAMS);
}
$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;
}
}

View File

@@ -0,0 +1,56 @@
<?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::MISSING_NECESSARY_PARAMS);
}
$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;
}
}

View File

@@ -0,0 +1,40 @@
<?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';
}
}

View File

@@ -0,0 +1,40 @@
<?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';
}
}

View File

@@ -0,0 +1,33 @@
<?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::MISSING_NECESSARY_PARAMS);
}
}
protected function getUri(Rocket $rocket): string
{
return 'v3/transfer/bill-receipt';
}
}

View File

@@ -0,0 +1,33 @@
<?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::MISSING_NECESSARY_PARAMS);
}
}
protected function getUri(Rocket $rocket): string
{
return 'v3/transfer-detail/electronic-receipts';
}
}

View File

@@ -0,0 +1,99 @@
<?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;
}
}

View File

@@ -0,0 +1,43 @@
<?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::MISSING_NECESSARY_PARAMS);
}
return $payload->get('download_url');
}
protected function getMethod(): string
{
return 'GET';
}
protected function doSomething(Rocket $rocket): void
{
$rocket->setDirection(OriginResponseDirection::class);
$rocket->setPayload(null);
}
}

View File

@@ -0,0 +1,60 @@
<?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::MISSING_NECESSARY_PARAMS);
}
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::MISSING_NECESSARY_PARAMS);
}
return 'v3/partner-transfer/batches/batch-id/'.
$payload->get('batch_id').
'/details/detail-id/'.
$payload->get('detail_id');
}
}

View File

@@ -0,0 +1,64 @@
<?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::MISSING_NECESSARY_PARAMS);
}
$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::MISSING_NECESSARY_PARAMS);
}
$batchId = $payload->get('batch_id');
$payload->forget('batch_id');
return 'v3/partner-transfer/batches/batch-id/'.$batchId.
'?'.$payload->query();
}
}

View File

@@ -0,0 +1,40 @@
<?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::MISSING_NECESSARY_PARAMS);
}
return 'v3/transfer/bill-receipt/'.$payload->get('out_batch_no');
}
}

View File

@@ -0,0 +1,40 @@
<?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::MISSING_NECESSARY_PARAMS);
}
$rocket->setPayload(null);
}
protected function getUri(Rocket $rocket): string
{
return 'v3/transfer-detail/electronic-receipts?'.$rocket->getPayload()->query();
}
}

View File

@@ -0,0 +1,60 @@
<?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::MISSING_NECESSARY_PARAMS);
}
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::MISSING_NECESSARY_PARAMS);
}
return 'v3/partner-transfer/batches/out-batch-no/'.
$payload->get('out_batch_no').
'/details/out-detail-no/'.
$payload->get('out_detail_no');
}
}

View File

@@ -0,0 +1,64 @@
<?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::MISSING_NECESSARY_PARAMS);
}
$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::MISSING_NECESSARY_PARAMS);
}
$outBatchNo = $payload->get('out_batch_no');
$payload->forget('out_batch_no');
return 'v3/partner-transfer/batches/out-batch-no/'.$outBatchNo.
'?'.$payload->query();
}
}

View File

@@ -0,0 +1,97 @@
<?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 0 === strpos($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);
}
}

View File

@@ -0,0 +1,42 @@
<?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;
}

View File

@@ -0,0 +1,67 @@
<?php
declare(strict_types=1);
namespace Yansongda\Pay\Plugin\Wechat;
use Closure;
use Psr\Http\Message\MessageInterface;
use Psr\Http\Message\ResponseInterface;
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\InvalidResponseException;
use Yansongda\Pay\Exception\ServiceNotFoundException;
use Yansongda\Pay\Logger;
use Yansongda\Pay\Rocket;
use Yansongda\Supports\Collection;
use function Yansongda\Pay\should_do_http_request;
use function Yansongda\Pay\verify_wechat_sign;
class LaunchPlugin implements PluginInterface
{
/**
* @throws ContainerException
* @throws InvalidConfigException
* @throws InvalidResponseException
* @throws ServiceNotFoundException
* @throws InvalidParamsException
*/
public function assembly(Rocket $rocket, Closure $next): Rocket
{
/* @var Rocket $rocket */
$rocket = $next($rocket);
Logger::debug('[wechat][LaunchPlugin] 插件开始装载', ['rocket' => $rocket]);
if (should_do_http_request($rocket->getDirection())) {
verify_wechat_sign($rocket->getDestinationOrigin(), $rocket->getParams());
$rocket->setDestination($this->validateResponse($rocket));
}
Logger::info('[wechat][LaunchPlugin] 插件装载完毕', ['rocket' => $rocket]);
return $rocket;
}
/**
* @return null|array|Collection|MessageInterface
*
* @throws InvalidResponseException
*/
protected function validateResponse(Rocket $rocket)
{
$response = $rocket->getDestination();
if ($response instanceof ResponseInterface
&& ($response->getStatusCode() < 200 || $response->getStatusCode() >= 300)) {
throw new InvalidResponseException(Exception::INVALID_RESPONSE_CODE);
}
return $response;
}
}

View File

@@ -0,0 +1,37 @@
<?php
declare(strict_types=1);
namespace Yansongda\Pay\Plugin\Wechat\Marketing\Coupon;
use Yansongda\Pay\Exception\ContainerException;
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/apis/chapter9_1_1.shtml
*/
class CreatePlugin extends GeneralPlugin
{
/**
* @throws ContainerException
* @throws ServiceNotFoundException
*/
protected function doSomething(Rocket $rocket): void
{
$config = get_wechat_config($rocket->getParams());
$payload = $rocket->getPayload();
if (!$payload->has('belong_merchant')) {
$rocket->mergePayload(['belong_merchant' => $config['mch_id']]);
}
}
protected function getUri(Rocket $rocket): string
{
return 'v3/marketing/favor/coupon-stocks';
}
}

View File

@@ -0,0 +1,50 @@
<?php
declare(strict_types=1);
namespace Yansongda\Pay\Plugin\Wechat\Marketing\Coupon;
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/apis/chapter9_1_13.shtml
*/
class PausePlugin extends GeneralPlugin
{
/**
* @throws ContainerException
* @throws ServiceNotFoundException
*/
protected function doSomething(Rocket $rocket): void
{
$config = get_wechat_config($rocket->getParams());
$payload = $rocket->getPayload();
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();
if (!$payload->has('stock_id')) {
throw new InvalidParamsException(Exception::MISSING_NECESSARY_PARAMS);
}
return 'v3/marketing/favor/stocks/'.$payload->get('stock_id').'/pause';
}
}

View File

@@ -0,0 +1,51 @@
<?php
declare(strict_types=1);
namespace Yansongda\Pay\Plugin\Wechat\Marketing\Coupon;
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/apis/chapter9_1_6.shtml
*/
class QueryCouponDetailPlugin 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();
$params = $rocket->getParams();
$config = get_wechat_config($params);
if (!$payload->has('coupon_id') || !$payload->has('openid')) {
throw new InvalidParamsException(Exception::MISSING_NECESSARY_PARAMS);
}
return 'v3/marketing/favor/users/'.
$payload->get('openid').
'/coupons/'.$payload->get('coupon_id').
'?appid='.$payload->get('appid', $config[$this->getConfigKey($params)] ?? '');
}
}

View File

@@ -0,0 +1,50 @@
<?php
declare(strict_types=1);
namespace Yansongda\Pay\Plugin\Wechat\Marketing\Coupon;
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/apis/chapter9_1_5.shtml
*/
class QueryStockDetailPlugin extends GeneralPlugin
{
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
{
$payload = $rocket->getPayload();
$params = $rocket->getParams();
$config = get_wechat_config($params);
if (!$payload->has('stock_id')) {
throw new InvalidParamsException(Exception::MISSING_NECESSARY_PARAMS);
}
return 'v3/marketing/favor/stocks/'.
$payload->get('stock_id').
'?stock_creator_mchid='.$payload->get('stock_creator_mchid', $config['mch_id'] ?? '');
}
}

View File

@@ -0,0 +1,58 @@
<?php
declare(strict_types=1);
namespace Yansongda\Pay\Plugin\Wechat\Marketing\Coupon;
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/apis/chapter9_1_8.shtml
*/
class QueryStockItemsPlugin extends GeneralPlugin
{
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
{
$payload = $rocket->getPayload();
$params = $rocket->getParams();
$config = get_wechat_config($params);
if (!$payload->has('stock_id')) {
throw new InvalidParamsException(Exception::MISSING_NECESSARY_PARAMS);
}
if (!$payload->has('stock_creator_mchid')) {
$rocket->mergePayload(['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);
}
}

View File

@@ -0,0 +1,58 @@
<?php
declare(strict_types=1);
namespace Yansongda\Pay\Plugin\Wechat\Marketing\Coupon;
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/apis/chapter9_1_7.shtml
*/
class QueryStockMerchantsPlugin extends GeneralPlugin
{
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
{
$payload = $rocket->getPayload();
$params = $rocket->getParams();
$config = get_wechat_config($params);
if (!$payload->has('stock_creator_mchid')) {
$rocket->mergePayload(['stock_creator_mchid' => $config['mch_id']]);
}
if (!$payload->has('stock_id')) {
throw new InvalidParamsException(Exception::MISSING_NECESSARY_PARAMS);
}
$query = $rocket->getPayload()->all();
unset($query['stock_id']);
return 'v3/marketing/favor/stocks/'.
$payload->get('stock_id').
'/merchants?'.http_build_query($query);
}
}

View File

@@ -0,0 +1,42 @@
<?php
declare(strict_types=1);
namespace Yansongda\Pay\Plugin\Wechat\Marketing\Coupon;
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/chapter9_1_11.shtml
*/
class QueryStockRefundFlowPlugin 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('stock_id')) {
throw new InvalidParamsException(Exception::MISSING_NECESSARY_PARAMS);
}
return 'v3/marketing/favor/stocks/'.
$payload->get('stock_id').
'/refund-flow';
}
}

View File

@@ -0,0 +1,42 @@
<?php
declare(strict_types=1);
namespace Yansongda\Pay\Plugin\Wechat\Marketing\Coupon;
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/chapter9_1_10.shtml
*/
class QueryStockUseFlowPlugin 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('stock_id')) {
throw new InvalidParamsException(Exception::MISSING_NECESSARY_PARAMS);
}
return 'v3/marketing/favor/stocks/'.
$payload->get('stock_id').
'/use-flow';
}
}

View File

@@ -0,0 +1,44 @@
<?php
declare(strict_types=1);
namespace Yansongda\Pay\Plugin\Wechat\Marketing\Coupon;
use Yansongda\Pay\Exception\ContainerException;
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/apis/chapter9_1_4.shtml
*/
class QueryStocksPlugin extends GeneralPlugin
{
protected function getMethod(): string
{
return 'GET';
}
protected function doSomething(Rocket $rocket): void
{
$rocket->setPayload(null);
}
/**
* @throws ContainerException
* @throws ServiceNotFoundException
*/
protected function getUri(Rocket $rocket): string
{
$params = $rocket->getParams();
$config = get_wechat_config($params);
if (!$rocket->getPayload()->has('stock_creator_mchid')) {
$rocket->mergePayload(['stock_creator_mchid' => $config['mch_id']]);
}
return 'v3/marketing/favor/stocks?'.$rocket->getPayload()->query();
}
}

View File

@@ -0,0 +1,62 @@
<?php
declare(strict_types=1);
namespace Yansongda\Pay\Plugin\Wechat\Marketing\Coupon;
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/apis/chapter9_1_9.shtml
*/
class QueryUserCouponsPlugin extends GeneralPlugin
{
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
{
$payload = $rocket->getPayload();
$params = $rocket->getParams();
$config = get_wechat_config($params);
if (!$payload->has('openid')) {
throw new InvalidParamsException(Exception::MISSING_NECESSARY_PARAMS);
}
if (!$payload->has('appid')) {
$rocket->mergePayload(['appid' => $config[$this->getConfigKey($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);
}
}

View File

@@ -0,0 +1,51 @@
<?php
declare(strict_types=1);
namespace Yansongda\Pay\Plugin\Wechat\Marketing\Coupon;
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/apis/chapter9_1_14.shtml
*/
class RestartPlugin extends GeneralPlugin
{
/**
* @throws ContainerException
* @throws ServiceNotFoundException
*/
protected function doSomething(Rocket $rocket): void
{
$payload = $rocket->getPayload();
$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();
if (!$payload->has('stock_id')) {
throw new InvalidParamsException(Exception::MISSING_NECESSARY_PARAMS);
}
return 'v3/marketing/favor/stocks/'.$payload->get('stock_id').'/restart';
}
}

View File

@@ -0,0 +1,54 @@
<?php
declare(strict_types=1);
namespace Yansongda\Pay\Plugin\Wechat\Marketing\Coupon;
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/apis/chapter9_1_2.shtml
*/
class SendPlugin extends GeneralPlugin
{
/**
* @throws ContainerException
* @throws ServiceNotFoundException
*/
protected function doSomething(Rocket $rocket): void
{
$params = $rocket->getParams();
$config = get_wechat_config($params);
if (!$rocket->getPayload()->has('appid')) {
$rocket->mergePayload(['appid' => $config[$this->getConfigKey($params)] ?? '']);
}
if (!$rocket->getPayload()->has('stock_creator_mchid')) {
$rocket->mergePayload(['stock_creator_mchid' => $config['mch_id']]);
}
$rocket->getPayload()->forget('openid');
}
/**
* @throws InvalidParamsException
*/
protected function getUri(Rocket $rocket): string
{
$payload = $rocket->getPayload();
if (!$payload->has('openid')) {
throw new InvalidParamsException(Exception::MISSING_NECESSARY_PARAMS);
}
return 'v3/marketing/favor/users/'.$payload->get('openid').'/coupons';
}
}

View File

@@ -0,0 +1,36 @@
<?php
declare(strict_types=1);
namespace Yansongda\Pay\Plugin\Wechat\Marketing\Coupon;
use Yansongda\Pay\Exception\ContainerException;
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/apis/chapter9_1_12.shtml
*/
class SetCallbackPlugin extends GeneralPlugin
{
/**
* @throws ContainerException
* @throws ServiceNotFoundException
*/
protected function doSomething(Rocket $rocket): void
{
$config = get_wechat_config($rocket->getParams());
$rocket->mergePayload([
'mchid' => $config['mch_id'] ?? '',
]);
}
protected function getUri(Rocket $rocket): string
{
return 'v3/marketing/favor/callbacks';
}
}

View File

@@ -0,0 +1,50 @@
<?php
declare(strict_types=1);
namespace Yansongda\Pay\Plugin\Wechat\Marketing\Coupon;
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/apis/chapter9_1_3.shtml
*/
class StartPlugin extends GeneralPlugin
{
/**
* @throws ContainerException
* @throws ServiceNotFoundException
*/
protected function doSomething(Rocket $rocket): void
{
$params = $rocket->getParams();
$config = get_wechat_config($params);
if (!$rocket->getPayload()->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();
if (!$payload->has('stock_id')) {
throw new InvalidParamsException(Exception::MISSING_NECESSARY_PARAMS);
}
return 'v3/marketing/favor/stocks/'.$payload->get('stock_id').'/start';
}
}

View File

@@ -0,0 +1,21 @@
<?php
declare(strict_types=1);
namespace Yansongda\Pay\Plugin\Wechat\Papay;
use Yansongda\Pay\Plugin\Wechat\GeneralV2Plugin;
use Yansongda\Pay\Rocket;
/**
* 申请代扣.
*
* @see https://pay.weixin.qq.com/wiki/doc/api/wxpay_v2/papay/chapter3_8.shtml
*/
class ApplyPlugin extends GeneralV2Plugin
{
protected function getUri(Rocket $rocket): string
{
return 'pay/pappayapply';
}
}

View File

@@ -0,0 +1,21 @@
<?php
declare(strict_types=1);
namespace Yansongda\Pay\Plugin\Wechat\Papay;
use Yansongda\Pay\Plugin\Wechat\GeneralV2Plugin;
use Yansongda\Pay\Rocket;
/**
* 支付中签约.
*
* @see https://pay.weixin.qq.com/wiki/doc/api/wxpay_v2/papay/chapter3_5.shtml
*/
class ContractOrderPlugin extends GeneralV2Plugin
{
protected function getUri(Rocket $rocket): string
{
return 'pay/contractorder';
}
}

View File

@@ -0,0 +1,70 @@
<?php
declare(strict_types=1);
namespace Yansongda\Pay\Plugin\Wechat\Papay;
use Closure;
use Yansongda\Pay\Contract\PluginInterface;
use Yansongda\Pay\Direction\NoHttpRequestDirection;
use Yansongda\Pay\Exception\ContainerException;
use Yansongda\Pay\Exception\InvalidConfigException;
use Yansongda\Pay\Exception\ServiceNotFoundException;
use Yansongda\Pay\Rocket;
use function Yansongda\Pay\get_wechat_config;
use function Yansongda\Pay\get_wechat_sign_v2;
/**
* 返回只签约(委托代扣)参数.
*
* @see https://pay.weixin.qq.com/wiki/doc/api/wxpay_v2/papay/chapter3_3.shtml
*/
class OnlyContractPlugin implements PluginInterface
{
/**
* @throws ContainerException
* @throws InvalidConfigException
* @throws ServiceNotFoundException
*/
public function assembly(Rocket $rocket, Closure $next): Rocket
{
$config = get_wechat_config($rocket->getParams());
$wechatId = $this->getWechatId($config, $rocket->getParams());
if (!$rocket->getPayload()->has('notify_url')) {
$wechatId['notify_url'] = $config['notify_url'] ?? '';
}
$rocket->mergePayload($wechatId);
$rocket->mergePayload([
'sign' => get_wechat_sign_v2($rocket->getParams(), $rocket->getPayload()->all()),
]);
$rocket->setDestination($rocket->getPayload());
$rocket->setDirection(NoHttpRequestDirection::class);
return $next($rocket);
}
protected function getWechatId(array $config, ?array $params): array
{
$configKey = $this->getConfigKey($params);
return [
'appid' => $config[$configKey] ?? '',
'mch_id' => $config['mch_id'] ?? '',
];
}
protected function getConfigKey(array $params): string
{
$key = ($params['_type'] ?? 'mp').'_app_id';
if ('app_app_id' === $key) {
$key = 'app_id';
}
return $key;
}
}

View File

@@ -0,0 +1,12 @@
<?php
declare(strict_types=1);
namespace Yansongda\Pay\Plugin\Wechat\Pay\App;
/**
* @see https://pay.weixin.qq.com/wiki/doc/apiv3/apis/chapter3_2_3.shtml
*/
class ClosePlugin extends \Yansongda\Pay\Plugin\Wechat\Pay\Common\ClosePlugin
{
}

View File

@@ -0,0 +1,12 @@
<?php
declare(strict_types=1);
namespace Yansongda\Pay\Plugin\Wechat\Pay\App;
/**
* @see https://pay.weixin.qq.com/wiki/doc/apiv3/apis/chapter3_2_8.shtml
*/
class DownloadBillPlugin extends \Yansongda\Pay\Plugin\Wechat\Pay\Common\DownloadBillPlugin
{
}

View File

@@ -0,0 +1,12 @@
<?php
declare(strict_types=1);
namespace Yansongda\Pay\Plugin\Wechat\Pay\App;
/**
* @see https://pay.weixin.qq.com/wiki/doc/apiv3/apis/chapter3_2_7.shtml
*/
class GetFlowBillPlugin extends \Yansongda\Pay\Plugin\Wechat\Pay\Common\GetFlowBillPlugin
{
}

View File

@@ -0,0 +1,12 @@
<?php
declare(strict_types=1);
namespace Yansongda\Pay\Plugin\Wechat\Pay\App;
/**
* @see https://pay.weixin.qq.com/wiki/doc/apiv3/apis/chapter3_2_6.shtml
*/
class GetTradeBillPlugin extends \Yansongda\Pay\Plugin\Wechat\Pay\Common\GetTradeBillPlugin
{
}

View File

@@ -0,0 +1,64 @@
<?php
declare(strict_types=1);
namespace Yansongda\Pay\Plugin\Wechat\Pay\App;
use Exception;
use Yansongda\Pay\Exception\ContainerException;
use Yansongda\Pay\Exception\InvalidConfigException;
use Yansongda\Pay\Exception\ServiceNotFoundException;
use Yansongda\Pay\Rocket;
use Yansongda\Supports\Collection;
use Yansongda\Supports\Config;
use Yansongda\Supports\Str;
use function Yansongda\Pay\get_wechat_config;
use function Yansongda\Pay\get_wechat_sign;
/**
* @see https://pay.weixin.qq.com/wiki/doc/apiv3/apis/chapter3_2_4.shtml
*/
class InvokePrepayPlugin extends \Yansongda\Pay\Plugin\Wechat\Pay\Common\InvokePrepayPlugin
{
/**
* @throws ContainerException
* @throws ServiceNotFoundException
* @throws Exception
*/
protected function getInvokeConfig(Rocket $rocket, ?string $prepayId): Config
{
$config = new Config([
'appid' => $this->getAppId($rocket),
'partnerid' => get_wechat_config($rocket->getParams())['mch_id'] ?? null,
'prepayid' => $prepayId,
'package' => 'Sign=WXPay',
'noncestr' => Str::random(32),
'timestamp' => time().'',
]);
$config->set('sign', $this->getSign($config, $rocket->getParams()));
return $config;
}
/**
* @throws ContainerException
* @throws InvalidConfigException
* @throws ServiceNotFoundException
*/
protected function getSign(Collection $invokeConfig, ?array $params): string
{
$contents = $invokeConfig->get('appid', '')."\n".
$invokeConfig->get('timestamp', '')."\n".
$invokeConfig->get('noncestr', '')."\n".
$invokeConfig->get('prepayid', '')."\n";
return get_wechat_sign($params, $contents);
}
protected function getConfigKey(): string
{
return 'app_id';
}
}

View File

@@ -0,0 +1,49 @@
<?php
declare(strict_types=1);
namespace Yansongda\Pay\Plugin\Wechat\Pay\App;
use Exception;
use Yansongda\Pay\Exception\ContainerException;
use Yansongda\Pay\Exception\ServiceNotFoundException;
use Yansongda\Pay\Rocket;
use Yansongda\Supports\Config;
use Yansongda\Supports\Str;
use function Yansongda\Pay\get_wechat_config;
use function Yansongda\Pay\get_wechat_sign_v2;
/**
* @see https://pay.weixin.qq.com/wiki/doc/api/app/app.php?chapter=8_5
*/
class InvokePrepayV2Plugin extends \Yansongda\Pay\Plugin\Wechat\Pay\Common\InvokePrepayPlugin
{
/**
* @throws ContainerException
* @throws ServiceNotFoundException
* @throws Exception
*/
protected function getInvokeConfig(Rocket $rocket, ?string $prepayId): Config
{
$params = $rocket->getParams();
$config = new Config([
'appId' => $this->getAppId($rocket),
'partnerId' => get_wechat_config($params)['mch_id'] ?? null,
'prepayId' => $prepayId,
'package' => 'Sign=WXPay',
'nonceStr' => Str::random(32),
'timeStamp' => time().'',
]);
$config->set('sign', get_wechat_sign_v2($params, $config->all()));
return $config;
}
protected function getConfigKey(): string
{
return 'app_id';
}
}

View File

@@ -0,0 +1,28 @@
<?php
declare(strict_types=1);
namespace Yansongda\Pay\Plugin\Wechat\Pay\App;
use Yansongda\Pay\Rocket;
/**
* @see https://pay.weixin.qq.com/wiki/doc/apiv3/apis/chapter3_2_1.shtml
*/
class PrepayPlugin extends \Yansongda\Pay\Plugin\Wechat\Pay\Common\PrepayPlugin
{
protected function getUri(Rocket $rocket): string
{
return 'v3/pay/transactions/app';
}
protected function getPartnerUri(Rocket $rocket): string
{
return 'v3/pay/partner/transactions/app';
}
protected function getConfigKey(array $params): string
{
return 'app_id';
}
}

View File

@@ -0,0 +1,12 @@
<?php
declare(strict_types=1);
namespace Yansongda\Pay\Plugin\Wechat\Pay\App;
/**
* @see https://pay.weixin.qq.com/wiki/doc/apiv3/apis/chapter3_2_2.shtml
*/
class QueryPlugin extends \Yansongda\Pay\Plugin\Wechat\Pay\Common\QueryPlugin
{
}

View File

@@ -0,0 +1,12 @@
<?php
declare(strict_types=1);
namespace Yansongda\Pay\Plugin\Wechat\Pay\App;
/**
* @see https://pay.weixin.qq.com/wiki/doc/apiv3/apis/chapter3_2_10.shtml
*/
class QueryRefundPlugin extends \Yansongda\Pay\Plugin\Wechat\Pay\Common\QueryRefundPlugin
{
}

View File

@@ -0,0 +1,12 @@
<?php
declare(strict_types=1);
namespace Yansongda\Pay\Plugin\Wechat\Pay\App;
/**
* @see https://pay.weixin.qq.com/wiki/doc/apiv3/apis/chapter3_2_9.shtml
*/
class RefundPlugin extends \Yansongda\Pay\Plugin\Wechat\Pay\Common\RefundPlugin
{
}

View File

@@ -0,0 +1,19 @@
<?php
declare(strict_types=1);
namespace Yansongda\Pay\Plugin\Wechat\Pay\Combine;
use Yansongda\Pay\Plugin\Wechat\Pay\Common\CombinePrepayPlugin;
use Yansongda\Pay\Rocket;
/**
* @see https://pay.weixin.qq.com/wiki/doc/apiv3/apis/chapter5_1_1.shtml
*/
class AppPrepayPlugin extends CombinePrepayPlugin
{
protected function getUri(Rocket $rocket): string
{
return 'v3/combine-transactions/app';
}
}

View File

@@ -0,0 +1,47 @@
<?php
declare(strict_types=1);
namespace Yansongda\Pay\Plugin\Wechat\Pay\Combine;
use Yansongda\Pay\Exception\ContainerException;
use Yansongda\Pay\Exception\Exception;
use Yansongda\Pay\Exception\InvalidParamsException;
use Yansongda\Pay\Exception\ServiceNotFoundException;
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/chapter5_1_12.shtml
*/
class ClosePlugin extends \Yansongda\Pay\Plugin\Wechat\Pay\Common\ClosePlugin
{
protected function getUri(Rocket $rocket): string
{
$payload = $rocket->getPayload();
if (!$payload->has('combine_out_trade_no') && !$payload->has('out_trade_no')) {
throw new InvalidParamsException(Exception::MISSING_NECESSARY_PARAMS);
}
return 'v3/combine-transactions/out-trade-no/'.
$payload->get('combine_out_trade_no', $payload->get('out_trade_no')).
'/close';
}
/**
* @throws ContainerException
* @throws ServiceNotFoundException
*/
protected function doSomething(Rocket $rocket): void
{
$config = get_wechat_config($rocket->getParams());
$rocket->setPayload(new Collection([
'combine_appid' => $config['combine_appid'] ?? '',
'sub_orders' => $rocket->getParams()['sub_orders'] ?? [],
]));
}
}

View File

@@ -0,0 +1,12 @@
<?php
declare(strict_types=1);
namespace Yansongda\Pay\Plugin\Wechat\Pay\Combine;
/**
* @see https://pay.weixin.qq.com/wiki/doc/apiv3/apis/chapter5_1_19.shtml
*/
class DownloadBillPlugin extends \Yansongda\Pay\Plugin\Wechat\Pay\Common\DownloadBillPlugin
{
}

View File

@@ -0,0 +1,12 @@
<?php
declare(strict_types=1);
namespace Yansongda\Pay\Plugin\Wechat\Pay\Combine;
/**
* @see https://pay.weixin.qq.com/wiki/doc/apiv3/apis/chapter5_1_18.shtml
*/
class GetFlowBillPlugin extends \Yansongda\Pay\Plugin\Wechat\Pay\Common\GetFlowBillPlugin
{
}

View File

@@ -0,0 +1,12 @@
<?php
declare(strict_types=1);
namespace Yansongda\Pay\Plugin\Wechat\Pay\Combine;
/**
* @see https://pay.weixin.qq.com/wiki/doc/apiv3/apis/chapter5_1_17.shtml
*/
class GetTradeBillPlugin extends \Yansongda\Pay\Plugin\Wechat\Pay\Common\GetTradeBillPlugin
{
}

View File

@@ -0,0 +1,19 @@
<?php
declare(strict_types=1);
namespace Yansongda\Pay\Plugin\Wechat\Pay\Combine;
use Yansongda\Pay\Plugin\Wechat\Pay\Common\CombinePrepayPlugin;
use Yansongda\Pay\Rocket;
/**
* @see https://pay.weixin.qq.com/wiki/doc/apiv3/apis/chapter5_1_2.shtml
*/
class H5PrepayPlugin extends CombinePrepayPlugin
{
protected function getUri(Rocket $rocket): string
{
return 'v3/combine-transactions/h5';
}
}

View File

@@ -0,0 +1,14 @@
<?php
declare(strict_types=1);
namespace Yansongda\Pay\Plugin\Wechat\Pay\Combine;
use Yansongda\Pay\Plugin\Wechat\Pay\App\InvokePrepayPlugin;
/**
* @see https://pay.weixin.qq.com/wiki/doc/apiv3/apis/chapter5_1_6.shtml
*/
class InvokeAppPrepayPlugin extends InvokePrepayPlugin
{
}

View File

@@ -0,0 +1,14 @@
<?php
declare(strict_types=1);
namespace Yansongda\Pay\Plugin\Wechat\Pay\Combine;
use Yansongda\Pay\Plugin\Wechat\Pay\Jsapi\InvokePrepayPlugin;
/**
* @see https://pay.weixin.qq.com/wiki/doc/apiv3/apis/chapter5_1_8.shtml
*/
class InvokeJsapiPrepayPlugin extends InvokePrepayPlugin
{
}

View File

@@ -0,0 +1,14 @@
<?php
declare(strict_types=1);
namespace Yansongda\Pay\Plugin\Wechat\Pay\Combine;
use Yansongda\Pay\Plugin\Wechat\Pay\Mini\InvokePrepayPlugin;
/**
* @see https://pay.weixin.qq.com/wiki/doc/apiv3/apis/chapter5_1_9.shtml
*/
class InvokeMiniPrepayPlugin extends InvokePrepayPlugin
{
}

View File

@@ -0,0 +1,14 @@
<?php
declare(strict_types=1);
namespace Yansongda\Pay\Plugin\Wechat\Pay\Combine;
use Yansongda\Pay\Plugin\Wechat\Pay\Common\CombinePrepayPlugin;
/**
* @see https://pay.weixin.qq.com/wiki/doc/apiv3/apis/chapter5_1_3.shtml
*/
class JsapiPrepayPlugin extends CombinePrepayPlugin
{
}

View File

@@ -0,0 +1,14 @@
<?php
declare(strict_types=1);
namespace Yansongda\Pay\Plugin\Wechat\Pay\Combine;
use Yansongda\Pay\Plugin\Wechat\Pay\Common\CombinePrepayPlugin;
/**
* @see https://pay.weixin.qq.com/wiki/doc/apiv3/apis/chapter5_1_4.shtml
*/
class MiniPrepayPlugin extends CombinePrepayPlugin
{
}

View File

@@ -0,0 +1,19 @@
<?php
declare(strict_types=1);
namespace Yansongda\Pay\Plugin\Wechat\Pay\Combine;
use Yansongda\Pay\Plugin\Wechat\Pay\Common\CombinePrepayPlugin;
use Yansongda\Pay\Rocket;
/**
* @see https://pay.weixin.qq.com/wiki/doc/apiv3/apis/chapter5_1_5.shtml
*/
class NativePrepayPlugin extends CombinePrepayPlugin
{
protected function getUri(Rocket $rocket): string
{
return 'v3/combine-transactions/native';
}
}

View File

@@ -0,0 +1,27 @@
<?php
declare(strict_types=1);
namespace Yansongda\Pay\Plugin\Wechat\Pay\Combine;
use Yansongda\Pay\Exception\Exception;
use Yansongda\Pay\Exception\InvalidParamsException;
use Yansongda\Pay\Rocket;
/**
* @see https://pay.weixin.qq.com/wiki/doc/apiv3/apis/chapter5_1_11.shtml
*/
class QueryPlugin extends \Yansongda\Pay\Plugin\Wechat\Pay\Common\QueryPlugin
{
protected function getUri(Rocket $rocket): string
{
$payload = $rocket->getPayload();
if (!$payload->has('combine_out_trade_no') && !$payload->has('transaction_id')) {
throw new InvalidParamsException(Exception::MISSING_NECESSARY_PARAMS);
}
return 'v3/combine-transactions/out-trade-no/'.
$payload->get('combine_out_trade_no', $payload->get('transaction_id'));
}
}

View File

@@ -0,0 +1,12 @@
<?php
declare(strict_types=1);
namespace Yansongda\Pay\Plugin\Wechat\Pay\Combine;
/**
* @see https://pay.weixin.qq.com/wiki/doc/apiv3/apis/chapter5_1_15.shtml
*/
class QueryRefundPlugin extends \Yansongda\Pay\Plugin\Wechat\Pay\Common\QueryRefundPlugin
{
}

View File

@@ -0,0 +1,12 @@
<?php
declare(strict_types=1);
namespace Yansongda\Pay\Plugin\Wechat\Pay\Combine;
/**
* @see https://pay.weixin.qq.com/wiki/doc/apiv3/apis/chapter5_1_14.shtml
*/
class RefundPlugin extends \Yansongda\Pay\Plugin\Wechat\Pay\Common\RefundPlugin
{
}

View File

@@ -0,0 +1,76 @@
<?php
declare(strict_types=1);
namespace Yansongda\Pay\Plugin\Wechat\Pay\Common;
use Yansongda\Pay\Direction\OriginResponseDirection;
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 Yansongda\Supports\Collection;
use function Yansongda\Pay\get_wechat_config;
class ClosePlugin extends GeneralPlugin
{
/**
* @throws InvalidParamsException
*/
protected function getUri(Rocket $rocket): string
{
$payload = $rocket->getPayload();
if (!$payload->has('out_trade_no')) {
throw new InvalidParamsException(Exception::MISSING_NECESSARY_PARAMS);
}
return 'v3/pay/transactions/out-trade-no/'.
$payload->get('out_trade_no').
'/close';
}
/**
* @throws InvalidParamsException
*/
protected function getPartnerUri(Rocket $rocket): string
{
$payload = $rocket->getPayload();
if (!$payload->has('out_trade_no')) {
throw new InvalidParamsException(Exception::MISSING_NECESSARY_PARAMS);
}
return 'v3/pay/partner/transactions/out-trade-no/'.
$payload->get('out_trade_no').
'/close';
}
/**
* @throws ContainerException
* @throws ServiceNotFoundException
*/
protected function doSomething(Rocket $rocket): void
{
$rocket->setDirection(OriginResponseDirection::class);
$config = get_wechat_config($rocket->getParams());
$body = [
'mchid' => $config['mch_id'] ?? '',
];
if (Pay::MODE_SERVICE == ($config['mode'] ?? null)) {
$body = [
'sp_mchid' => $config['mch_id'] ?? '',
'sub_mchid' => $rocket->getPayload()->get('sub_mchid', $config['sub_mch_id'] ?? ''),
];
}
$rocket->setPayload(new Collection($body));
}
}

View File

@@ -0,0 +1,50 @@
<?php
declare(strict_types=1);
namespace Yansongda\Pay\Plugin\Wechat\Pay\Common;
use Yansongda\Pay\Exception\ContainerException;
use Yansongda\Pay\Exception\ServiceNotFoundException;
use Yansongda\Pay\Plugin\Wechat\GeneralPlugin;
use Yansongda\Pay\Rocket;
use function Yansongda\Pay\get_wechat_config;
class CombinePrepayPlugin extends GeneralPlugin
{
protected function getUri(Rocket $rocket): string
{
return 'v3/combine-transactions/jsapi';
}
/**
* @throws ContainerException
* @throws ServiceNotFoundException
*/
protected function doSomething(Rocket $rocket): void
{
$config = get_wechat_config($rocket->getParams());
$collection = $rocket->getPayload();
$payload = $this->getWechatId($config);
if (!$collection->has('notify_url')) {
$payload['notify_url'] = $config['notify_url'] ?? '';
}
if (!$collection->has('combine_out_trade_no')) {
$payload['combine_out_trade_no'] = $rocket->getParams()['out_trade_no'];
}
$rocket->mergePayload($payload);
}
protected function getWechatId(array $config): array
{
return [
'combine_appid' => $config['combine_app_id'] ?? '',
'combine_mchid' => $config['combine_mch_id'] ?? '',
];
}
}

View File

@@ -0,0 +1,40 @@
<?php
declare(strict_types=1);
namespace Yansongda\Pay\Plugin\Wechat\Pay\Common;
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;
class DownloadBillPlugin extends GeneralPlugin
{
/**
* @throws InvalidParamsException
*/
protected function getUri(Rocket $rocket): string
{
$payload = $rocket->getPayload();
if (!$payload->has('download_url')) {
throw new InvalidParamsException(Exception::MISSING_NECESSARY_PARAMS);
}
return $payload->get('download_url');
}
protected function getMethod(): string
{
return 'GET';
}
protected function doSomething(Rocket $rocket): void
{
$rocket->setDirection(OriginResponseDirection::class);
$rocket->setPayload(null);
}
}

View File

@@ -0,0 +1,26 @@
<?php
declare(strict_types=1);
namespace Yansongda\Pay\Plugin\Wechat\Pay\Common;
use Yansongda\Pay\Plugin\Wechat\GeneralPlugin;
use Yansongda\Pay\Rocket;
class GetFlowBillPlugin extends GeneralPlugin
{
protected function getUri(Rocket $rocket): string
{
return 'v3/bill/fundflowbill?'.http_build_query($rocket->getParams());
}
protected function getMethod(): string
{
return 'GET';
}
protected function doSomething(Rocket $rocket): void
{
$rocket->setPayload(null);
}
}

View File

@@ -0,0 +1,26 @@
<?php
declare(strict_types=1);
namespace Yansongda\Pay\Plugin\Wechat\Pay\Common;
use Yansongda\Pay\Plugin\Wechat\GeneralPlugin;
use Yansongda\Pay\Rocket;
class GetTradeBillPlugin extends GeneralPlugin
{
protected function getUri(Rocket $rocket): string
{
return 'v3/bill/tradebill?'.http_build_query($rocket->getParams());
}
protected function getMethod(): string
{
return 'GET';
}
protected function doSomething(Rocket $rocket): void
{
$rocket->setPayload(null);
}
}

View File

@@ -0,0 +1,110 @@
<?php
declare(strict_types=1);
namespace Yansongda\Pay\Plugin\Wechat\Pay\Common;
use Closure;
use Yansongda\Pay\Contract\PluginInterface;
use Yansongda\Pay\Exception\ContainerException;
use Yansongda\Pay\Exception\Exception;
use Yansongda\Pay\Exception\InvalidConfigException;
use Yansongda\Pay\Exception\InvalidResponseException;
use Yansongda\Pay\Exception\ServiceNotFoundException;
use Yansongda\Pay\Logger;
use Yansongda\Pay\Pay;
use Yansongda\Pay\Rocket;
use Yansongda\Supports\Collection;
use Yansongda\Supports\Config;
use Yansongda\Supports\Str;
use function Yansongda\Pay\get_wechat_config;
use function Yansongda\Pay\get_wechat_sign;
class InvokePrepayPlugin implements PluginInterface
{
/**
* @throws ContainerException
* @throws InvalidResponseException
* @throws ServiceNotFoundException
*/
public function assembly(Rocket $rocket, Closure $next): Rocket
{
/* @var Rocket $rocket */
$rocket = $next($rocket);
Logger::debug('[wechat][InvokePrepayPlugin] 插件开始装载', ['rocket' => $rocket]);
$prepayId = $rocket->getDestination()->get('prepay_id');
if (is_null($prepayId)) {
Logger::error('[wechat][InvokePrepayPlugin] 预下单失败:响应缺少 prepay_id 参数,请自行检查参数是否符合微信要求', $rocket->getDestination()->all());
throw new InvalidResponseException(Exception::RESPONSE_MISSING_NECESSARY_PARAMS, 'Prepay Response Error: Missing PrepayId', $rocket->getDestination()->all());
}
$config = $this->getInvokeConfig($rocket, $prepayId);
$rocket->setDestination($config);
Logger::info('[wechat][InvokePrepayPlugin] 插件装载完毕', ['rocket' => $rocket]);
return $rocket;
}
/**
* @throws ContainerException
* @throws ServiceNotFoundException
* @throws \Exception
*/
protected function getInvokeConfig(Rocket $rocket, ?string $prepayId): Config
{
$config = new Config([
'appId' => $this->getAppId($rocket),
'timeStamp' => time().'',
'nonceStr' => Str::random(32),
'package' => 'prepay_id='.$prepayId,
'signType' => 'RSA',
]);
$config->set('paySign', $this->getSign($config, $rocket->getParams()));
return $config;
}
/**
* @throws ContainerException
* @throws InvalidConfigException
* @throws ServiceNotFoundException
*/
protected function getSign(Collection $invokeConfig, ?array $params): string
{
$contents = $invokeConfig->get('appId', '')."\n".
$invokeConfig->get('timeStamp', '')."\n".
$invokeConfig->get('nonceStr', '')."\n".
$invokeConfig->get('package', '')."\n";
return get_wechat_sign($params, $contents);
}
/**
* @throws ContainerException
* @throws ServiceNotFoundException
*/
protected function getAppId(Rocket $rocket): string
{
$config = get_wechat_config($rocket->getParams());
$payload = $rocket->getPayload();
if (Pay::MODE_SERVICE === ($config['mode'] ?? null) && $payload->has('sub_appid')) {
return $payload->get('sub_appid', '');
}
return $config[$this->getConfigKey()] ?? '';
}
protected function getConfigKey(): string
{
return 'mp_app_id';
}
}

View File

@@ -0,0 +1,40 @@
<?php
declare(strict_types=1);
namespace Yansongda\Pay\Plugin\Wechat\Pay\Common;
use Exception;
use Yansongda\Pay\Exception\ContainerException;
use Yansongda\Pay\Exception\ServiceNotFoundException;
use Yansongda\Pay\Rocket;
use Yansongda\Supports\Config;
use Yansongda\Supports\Str;
use function Yansongda\Pay\get_wechat_sign_v2;
/**
* @see https://pay.weixin.qq.com/wiki/doc/api/jsapi.php?chapter=7_7&index=6
*/
class InvokePrepayV2Plugin extends InvokePrepayPlugin
{
/**
* @throws ContainerException
* @throws ServiceNotFoundException
* @throws Exception
*/
protected function getInvokeConfig(Rocket $rocket, ?string $prepayId): Config
{
$config = new Config([
'appId' => $this->getAppId($rocket),
'timeStamp' => time().'',
'nonceStr' => Str::random(32),
'package' => 'prepay_id='.$prepayId,
'signType' => 'MD5',
]);
$config->set('paySign', get_wechat_sign_v2($rocket->getParams(), $config->toArray()));
return $config;
}
}

View File

@@ -0,0 +1,70 @@
<?php
declare(strict_types=1);
namespace Yansongda\Pay\Plugin\Wechat\Pay\Common;
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;
class PrepayPlugin extends GeneralPlugin
{
protected function getUri(Rocket $rocket): string
{
return 'v3/pay/transactions/jsapi';
}
protected function getPartnerUri(Rocket $rocket): string
{
return 'v3/pay/partner/transactions/jsapi';
}
/**
* @throws ContainerException
* @throws ServiceNotFoundException
*/
protected function doSomething(Rocket $rocket): void
{
$config = get_wechat_config($rocket->getParams());
$wechatId = $this->getWechatId($config, $rocket);
if (!$rocket->getPayload()->has('notify_url')) {
$wechatId['notify_url'] = $config['notify_url'] ?? null;
}
$rocket->mergePayload($wechatId);
}
protected function getWechatId(array $config, Rocket $rocket): array
{
$payload = $rocket->getPayload();
$configKey = $this->getConfigKey($rocket->getParams());
$result = [
'appid' => $config[$configKey] ?? '',
'mchid' => $config['mch_id'] ?? '',
];
if (Pay::MODE_SERVICE === ($config['mode'] ?? null)) {
$result = [
'sp_appid' => $config[$configKey] ?? '',
'sp_mchid' => $config['mch_id'] ?? '',
'sub_mchid' => $payload->get('sub_mchid', $config['sub_mch_id'] ?? null),
];
$subAppId = $payload->get('sub_appid', $config['sub_'.$configKey] ?? null);
if (!empty($subAppId)) {
$result['sub_appid'] = $subAppId;
}
}
return $result;
}
}

View File

@@ -0,0 +1,79 @@
<?php
declare(strict_types=1);
namespace Yansongda\Pay\Plugin\Wechat\Pay\Common;
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;
class QueryPlugin extends GeneralPlugin
{
/**
* @throws ContainerException
* @throws ServiceNotFoundException
* @throws InvalidParamsException
*/
protected function getUri(Rocket $rocket): string
{
$config = get_wechat_config($rocket->getParams());
$payload = $rocket->getPayload();
if ($payload->has('transaction_id')) {
return 'v3/pay/transactions/id/'.
$payload->get('transaction_id').
'?mchid='.($config['mch_id'] ?? '');
}
if ($payload->has('out_trade_no')) {
return 'v3/pay/transactions/out-trade-no/'.
$payload->get('out_trade_no').
'?mchid='.($config['mch_id'] ?? '');
}
throw new InvalidParamsException(Exception::MISSING_NECESSARY_PARAMS);
}
/**
* @throws ContainerException
* @throws ServiceNotFoundException
* @throws InvalidParamsException
*/
protected function getPartnerUri(Rocket $rocket): string
{
$config = get_wechat_config($rocket->getParams());
$payload = $rocket->getPayload();
if ($payload->has('transaction_id')) {
return 'v3/pay/partner/transactions/id/'.
$payload->get('transaction_id').
'?sp_mchid='.($config['mch_id'] ?? '').
'&sub_mchid='.$payload->get('sub_mchid', $config['sub_mch_id'] ?? null);
}
if ($payload->has('out_trade_no')) {
return 'v3/pay/partner/transactions/out-trade-no/'.
$payload->get('out_trade_no').
'?sp_mchid='.($config['mch_id'] ?? '').
'&sub_mchid='.$payload->get('sub_mchid', $config['sub_mch_id'] ?? null);
}
throw new InvalidParamsException(Exception::MISSING_NECESSARY_PARAMS);
}
protected function getMethod(): string
{
return 'GET';
}
protected function doSomething(Rocket $rocket): void
{
$rocket->setPayload(null);
}
}

View File

@@ -0,0 +1,53 @@
<?php
declare(strict_types=1);
namespace Yansongda\Pay\Plugin\Wechat\Pay\Common;
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;
class QueryRefundPlugin extends GeneralPlugin
{
/**
* @throws InvalidParamsException
*/
protected function getUri(Rocket $rocket): string
{
$payload = $rocket->getPayload();
if (!$payload->has('out_refund_no')) {
throw new InvalidParamsException(Exception::MISSING_NECESSARY_PARAMS);
}
return 'v3/refund/domestic/refunds/'.$payload->get('out_refund_no');
}
/**
* @throws ContainerException
* @throws ServiceNotFoundException
*/
protected function getPartnerUri(Rocket $rocket): string
{
$config = get_wechat_config($rocket->getParams());
$url = parent::getPartnerUri($rocket);
return $url.'?sub_mchid='.$rocket->getPayload()->get('sub_mchid', $config['sub_mch_id'] ?? '');
}
protected function getMethod(): string
{
return 'GET';
}
protected function doSomething(Rocket $rocket): void
{
$rocket->setPayload(null);
}
}

View File

@@ -0,0 +1,41 @@
<?php
declare(strict_types=1);
namespace Yansongda\Pay\Plugin\Wechat\Pay\Common;
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;
class RefundPlugin extends GeneralPlugin
{
protected function getUri(Rocket $rocket): string
{
return 'v3/refund/domestic/refunds';
}
/**
* @throws ContainerException
* @throws ServiceNotFoundException
*/
protected function doSomething(Rocket $rocket): void
{
$config = get_wechat_config($rocket->getParams());
$payload = $rocket->getPayload();
if (empty($payload->get('notify_url')) && !empty($config['notify_url'])) {
$merge['notify_url'] = $config['notify_url'];
}
if (Pay::MODE_SERVICE === ($config['mode'] ?? null)) {
$merge['sub_mchid'] = $payload->get('sub_mchid', $config['sub_mch_id'] ?? null);
}
$rocket->mergePayload($merge ?? []);
}
}

View File

@@ -0,0 +1,12 @@
<?php
declare(strict_types=1);
namespace Yansongda\Pay\Plugin\Wechat\Pay\H5;
/**
* @see https://pay.weixin.qq.com/wiki/doc/apiv3/apis/chapter3_3_3.shtml
*/
class ClosePlugin extends \Yansongda\Pay\Plugin\Wechat\Pay\Common\ClosePlugin
{
}

View File

@@ -0,0 +1,12 @@
<?php
declare(strict_types=1);
namespace Yansongda\Pay\Plugin\Wechat\Pay\H5;
/**
* @see https://pay.weixin.qq.com/wiki/doc/apiv3/apis/chapter3_3_8.shtml
*/
class DownloadBillPlugin extends \Yansongda\Pay\Plugin\Wechat\Pay\Common\DownloadBillPlugin
{
}

View File

@@ -0,0 +1,12 @@
<?php
declare(strict_types=1);
namespace Yansongda\Pay\Plugin\Wechat\Pay\H5;
/**
* @see https://pay.weixin.qq.com/wiki/doc/apiv3/apis/chapter3_3_7.shtml
*/
class GetFlowBillPlugin extends \Yansongda\Pay\Plugin\Wechat\Pay\Common\GetFlowBillPlugin
{
}

View File

@@ -0,0 +1,12 @@
<?php
declare(strict_types=1);
namespace Yansongda\Pay\Plugin\Wechat\Pay\H5;
/**
* @see https://pay.weixin.qq.com/wiki/doc/apiv3/apis/chapter3_3_6.shtml
*/
class GetTradeBillPlugin extends \Yansongda\Pay\Plugin\Wechat\Pay\Common\GetTradeBillPlugin
{
}

View File

@@ -0,0 +1,23 @@
<?php
declare(strict_types=1);
namespace Yansongda\Pay\Plugin\Wechat\Pay\H5;
use Yansongda\Pay\Rocket;
/**
* @see https://pay.weixin.qq.com/wiki/doc/apiv3/apis/chapter3_3_1.shtml
*/
class PrepayPlugin extends \Yansongda\Pay\Plugin\Wechat\Pay\Common\PrepayPlugin
{
protected function getUri(Rocket $rocket): string
{
return 'v3/pay/transactions/h5';
}
protected function getPartnerUri(Rocket $rocket): string
{
return 'v3/pay/partner/transactions/h5';
}
}

View File

@@ -0,0 +1,12 @@
<?php
declare(strict_types=1);
namespace Yansongda\Pay\Plugin\Wechat\Pay\H5;
/**
* @see https://pay.weixin.qq.com/wiki/doc/apiv3/apis/chapter3_3_2.shtml
*/
class QueryPlugin extends \Yansongda\Pay\Plugin\Wechat\Pay\Common\QueryPlugin
{
}

View File

@@ -0,0 +1,12 @@
<?php
declare(strict_types=1);
namespace Yansongda\Pay\Plugin\Wechat\Pay\H5;
/**
* @see https://pay.weixin.qq.com/wiki/doc/apiv3/apis/chapter3_3_10.shtml
*/
class QueryRefundPlugin extends \Yansongda\Pay\Plugin\Wechat\Pay\Common\QueryRefundPlugin
{
}

View File

@@ -0,0 +1,12 @@
<?php
declare(strict_types=1);
namespace Yansongda\Pay\Plugin\Wechat\Pay\H5;
/**
* @see https://pay.weixin.qq.com/wiki/doc/apiv3/apis/chapter3_3_9.shtml
*/
class RefundPlugin extends \Yansongda\Pay\Plugin\Wechat\Pay\Common\RefundPlugin
{
}

View File

@@ -0,0 +1,12 @@
<?php
declare(strict_types=1);
namespace Yansongda\Pay\Plugin\Wechat\Pay\Jsapi;
/**
* @see https://pay.weixin.qq.com/wiki/doc/apiv3/apis/chapter3_1_3.shtml
*/
class ClosePlugin extends \Yansongda\Pay\Plugin\Wechat\Pay\Common\ClosePlugin
{
}

View File

@@ -0,0 +1,12 @@
<?php
declare(strict_types=1);
namespace Yansongda\Pay\Plugin\Wechat\Pay\Jsapi;
/**
* @see https://pay.weixin.qq.com/wiki/doc/apiv3/apis/chapter3_1_8.shtml
*/
class DownloadBillPlugin extends \Yansongda\Pay\Plugin\Wechat\Pay\Common\DownloadBillPlugin
{
}

View File

@@ -0,0 +1,12 @@
<?php
declare(strict_types=1);
namespace Yansongda\Pay\Plugin\Wechat\Pay\Jsapi;
/**
* @see https://pay.weixin.qq.com/wiki/doc/apiv3/apis/chapter3_1_7.shtml
*/
class GetFlowBillPlugin extends \Yansongda\Pay\Plugin\Wechat\Pay\Common\GetFlowBillPlugin
{
}

View File

@@ -0,0 +1,12 @@
<?php
declare(strict_types=1);
namespace Yansongda\Pay\Plugin\Wechat\Pay\Jsapi;
/**
* @see https://pay.weixin.qq.com/wiki/doc/apiv3/apis/chapter3_1_6.shtml
*/
class GetTradeBillPlugin extends \Yansongda\Pay\Plugin\Wechat\Pay\Common\GetTradeBillPlugin
{
}

View File

@@ -0,0 +1,12 @@
<?php
declare(strict_types=1);
namespace Yansongda\Pay\Plugin\Wechat\Pay\Jsapi;
/**
* @see https://pay.weixin.qq.com/wiki/doc/apiv3/apis/chapter3_1_4.shtml
*/
class InvokePrepayPlugin extends \Yansongda\Pay\Plugin\Wechat\Pay\Common\InvokePrepayPlugin
{
}

View File

@@ -0,0 +1,12 @@
<?php
declare(strict_types=1);
namespace Yansongda\Pay\Plugin\Wechat\Pay\Jsapi;
/**
* @see https://pay.weixin.qq.com/wiki/doc/api/jsapi.php?chapter=7_7&index=6
*/
class InvokePrepayV2Plugin extends \Yansongda\Pay\Plugin\Wechat\Pay\Common\InvokePrepayV2Plugin
{
}

View File

@@ -0,0 +1,12 @@
<?php
declare(strict_types=1);
namespace Yansongda\Pay\Plugin\Wechat\Pay\Jsapi;
/**
* @see https://pay.weixin.qq.com/wiki/doc/apiv3/apis/chapter3_1_1.shtml
*/
class PrepayPlugin extends \Yansongda\Pay\Plugin\Wechat\Pay\Common\PrepayPlugin
{
}

View File

@@ -0,0 +1,12 @@
<?php
declare(strict_types=1);
namespace Yansongda\Pay\Plugin\Wechat\Pay\Jsapi;
/**
* @see https://pay.weixin.qq.com/wiki/doc/apiv3/apis/chapter3_1_2.shtml
*/
class QueryPlugin extends \Yansongda\Pay\Plugin\Wechat\Pay\Common\QueryPlugin
{
}

View File

@@ -0,0 +1,12 @@
<?php
declare(strict_types=1);
namespace Yansongda\Pay\Plugin\Wechat\Pay\Jsapi;
/**
* @see https://pay.weixin.qq.com/wiki/doc/apiv3/apis/chapter3_1_10.shtml
*/
class QueryRefundPlugin extends \Yansongda\Pay\Plugin\Wechat\Pay\Common\QueryRefundPlugin
{
}

Some files were not shown because too many files have changed in this diff Show More