mirror of
https://gitee.com/technical-laohu/mpay_v2_webman.git
synced 2026-04-22 01:54:25 +08:00
重构初始化
This commit is contained in:
@@ -1,98 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace app\http\api\controller;
|
||||
|
||||
use app\common\base\BaseController;
|
||||
use app\services\api\EpayProtocolService;
|
||||
use support\Request;
|
||||
use support\Response;
|
||||
|
||||
/**
|
||||
* 易支付控制器
|
||||
*/
|
||||
class EpayController extends BaseController
|
||||
{
|
||||
public function __construct(
|
||||
protected EpayProtocolService $epayProtocolService
|
||||
) {
|
||||
}
|
||||
|
||||
/**
|
||||
* 页面跳转支付
|
||||
*/
|
||||
public function submit(Request $request)
|
||||
{
|
||||
try {
|
||||
$result = $this->epayProtocolService->handleSubmit($request);
|
||||
$type = $result['response_type'] ?? '';
|
||||
|
||||
if ($type === 'redirect' && !empty($result['url'])) {
|
||||
return redirect($result['url']);
|
||||
}
|
||||
|
||||
if ($type === 'form_html') {
|
||||
return response((string)($result['html'] ?? ''))
|
||||
->withHeaders(['Content-Type' => 'text/html; charset=UTF-8']);
|
||||
}
|
||||
|
||||
if ($type === 'form_params') {
|
||||
return $this->renderForm((array)($result['form'] ?? []));
|
||||
}
|
||||
|
||||
return $this->fail('支付参数生成失败');
|
||||
} catch (\Throwable $e) {
|
||||
return $this->fail($e->getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* API接口支付
|
||||
*/
|
||||
public function mapi(Request $request)
|
||||
{
|
||||
try {
|
||||
return json($this->epayProtocolService->handleMapi($request));
|
||||
} catch (\Throwable $e) {
|
||||
return json([
|
||||
'code' => 0,
|
||||
'msg' => $e->getMessage(),
|
||||
]);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* API接口
|
||||
*/
|
||||
public function api(Request $request)
|
||||
{
|
||||
try {
|
||||
return json($this->epayProtocolService->handleApi($request));
|
||||
} catch (\Throwable $e) {
|
||||
return json([
|
||||
'code' => 0,
|
||||
'msg' => $e->getMessage(),
|
||||
]);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 渲染表单提交 HTML(用于页面跳转支付)
|
||||
*/
|
||||
private function renderForm(array $formParams): Response
|
||||
{
|
||||
$html = '<!DOCTYPE html><html><head><meta charset="UTF-8"><title>跳转支付</title></head><body>';
|
||||
$html .= '<form id="payForm" method="' . htmlspecialchars($formParams['method'] ?? 'POST') . '" action="' . htmlspecialchars($formParams['action'] ?? '') . '">';
|
||||
|
||||
if (isset($formParams['fields']) && is_array($formParams['fields'])) {
|
||||
foreach ($formParams['fields'] as $name => $value) {
|
||||
$html .= '<input type="hidden" name="' . htmlspecialchars($name) . '" value="' . htmlspecialchars((string)$value) . '">';
|
||||
}
|
||||
}
|
||||
|
||||
$html .= '</form>';
|
||||
$html .= '<script>document.getElementById("payForm").submit();</script>';
|
||||
$html .= '</body></html>';
|
||||
|
||||
return response($html)->withHeaders(['Content-Type' => 'text/html; charset=UTF-8']);
|
||||
}
|
||||
}
|
||||
@@ -1,74 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace app\http\api\controller;
|
||||
|
||||
use app\common\base\BaseController;
|
||||
use app\services\PayNotifyService;
|
||||
use app\services\PluginService;
|
||||
use support\Request;
|
||||
use support\Response;
|
||||
|
||||
/**
|
||||
* 支付控制器(OpenAPI)
|
||||
*/
|
||||
class PayController extends BaseController
|
||||
{
|
||||
public function __construct(
|
||||
protected PayNotifyService $payNotifyService,
|
||||
protected PluginService $pluginService
|
||||
) {
|
||||
}
|
||||
|
||||
/**
|
||||
* 创建订单
|
||||
*/
|
||||
public function create(Request $request)
|
||||
{
|
||||
return $this->fail('not implemented', 501);
|
||||
}
|
||||
|
||||
/**
|
||||
* 查询订单
|
||||
*/
|
||||
public function query(Request $request)
|
||||
{
|
||||
return $this->fail('not implemented', 501);
|
||||
}
|
||||
|
||||
/**
|
||||
* 关闭订单
|
||||
*/
|
||||
public function close(Request $request)
|
||||
{
|
||||
return $this->fail('not implemented', 501);
|
||||
}
|
||||
|
||||
/**
|
||||
* 订单退款
|
||||
*/
|
||||
public function refund(Request $request)
|
||||
{
|
||||
return $this->fail('not implemented', 501);
|
||||
}
|
||||
|
||||
/**
|
||||
* 异步通知
|
||||
*/
|
||||
public function notify(Request $request, string $pluginCode)
|
||||
{
|
||||
try {
|
||||
$plugin = $this->pluginService->getPluginInstance($pluginCode);
|
||||
$result = $this->payNotifyService->handleNotify($pluginCode, $request);
|
||||
$ackSuccess = method_exists($plugin, 'notifySuccess') ? $plugin->notifySuccess() : 'success';
|
||||
$ackFail = method_exists($plugin, 'notifyFail') ? $plugin->notifyFail() : 'fail';
|
||||
|
||||
if (!($result['ok'] ?? false)) {
|
||||
return $ackFail instanceof Response ? $ackFail : response((string)$ackFail);
|
||||
}
|
||||
|
||||
return $ackSuccess instanceof Response ? $ackSuccess : response((string)$ackSuccess);
|
||||
} catch (\Throwable $e) {
|
||||
return response('fail');
|
||||
}
|
||||
}
|
||||
}
|
||||
100
app/http/api/controller/adapter/EpayController.php
Normal file
100
app/http/api/controller/adapter/EpayController.php
Normal file
@@ -0,0 +1,100 @@
|
||||
<?php
|
||||
|
||||
namespace app\http\api\controller\adapter;
|
||||
|
||||
use app\common\base\BaseController;
|
||||
use app\exception\ValidationException;
|
||||
use app\http\api\validation\EpayValidator;
|
||||
use app\service\payment\compat\EpayCompatService;
|
||||
use support\Request;
|
||||
use support\Response;
|
||||
|
||||
/**
|
||||
* Epay 协议兼容控制器。
|
||||
*
|
||||
* 负责 submit.php、mapi.php 和 api.php 的入口场景校验与结果分发。
|
||||
*/
|
||||
class EpayController extends BaseController
|
||||
{
|
||||
/**
|
||||
* 构造函数,注入兼容服务。
|
||||
*/
|
||||
public function __construct(
|
||||
protected EpayCompatService $epayCompatService
|
||||
) {}
|
||||
|
||||
/**
|
||||
* 页面跳转支付入口。
|
||||
*/
|
||||
public function submit(Request $request): Response
|
||||
{
|
||||
try {
|
||||
$payload = $this->validated($request->all(), EpayValidator::class, 'submit');
|
||||
|
||||
return $this->epayCompatService->submit($payload, $request);
|
||||
} catch (ValidationException $e) {
|
||||
return json([
|
||||
'code' => 0,
|
||||
'msg' => $e->getMessage(),
|
||||
]);
|
||||
} catch (\Throwable $e) {
|
||||
return json([
|
||||
'code' => 0,
|
||||
'msg' => $e->getMessage() ?: '提交失败',
|
||||
]);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* API 接口支付入口。
|
||||
*/
|
||||
public function mapi(Request $request): Response
|
||||
{
|
||||
try {
|
||||
$payload = $this->validated($request->all(), EpayValidator::class, 'mapi');
|
||||
|
||||
return json($this->epayCompatService->mapi($payload, $request));
|
||||
} catch (ValidationException $e) {
|
||||
return json([
|
||||
'code' => 0,
|
||||
'msg' => $e->getMessage(),
|
||||
]);
|
||||
} catch (\Throwable $e) {
|
||||
return json([
|
||||
'code' => 0,
|
||||
'msg' => $e->getMessage() ?: '提交失败',
|
||||
]);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 标准 API 接口入口。
|
||||
*/
|
||||
public function api(Request $request): Response
|
||||
{
|
||||
try {
|
||||
$payload = $request->all();
|
||||
$act = strtolower(trim((string) ($payload['act'] ?? '')));
|
||||
$scene = match ($act) {
|
||||
'settle' => 'settle',
|
||||
'orders' => 'orders',
|
||||
'order' => trim((string) ($payload['trade_no'] ?? '')) !== '' ? 'order_trade_no' : 'order_out_trade_no',
|
||||
'refund' => trim((string) ($payload['trade_no'] ?? '')) !== '' ? 'refund_trade_no' : 'refund_out_trade_no',
|
||||
default => 'query',
|
||||
};
|
||||
$payload = $this->validated($payload, EpayValidator::class, $scene);
|
||||
|
||||
return json($this->epayCompatService->api($payload));
|
||||
} catch (ValidationException $e) {
|
||||
return json([
|
||||
'code' => 0,
|
||||
'msg' => $e->getMessage(),
|
||||
]);
|
||||
} catch (\Throwable $e) {
|
||||
return json([
|
||||
'code' => 0,
|
||||
'msg' => $e->getMessage() ?: '请求失败',
|
||||
]);
|
||||
}
|
||||
}
|
||||
}
|
||||
51
app/http/api/controller/notify/NotifyController.php
Normal file
51
app/http/api/controller/notify/NotifyController.php
Normal file
@@ -0,0 +1,51 @@
|
||||
<?php
|
||||
|
||||
namespace app\http\api\controller\notify;
|
||||
|
||||
use app\common\base\BaseController;
|
||||
use app\http\api\validation\NotifyChannelValidator;
|
||||
use app\http\api\validation\NotifyMerchantValidator;
|
||||
use app\service\payment\runtime\NotifyService;
|
||||
use support\Request;
|
||||
use support\Response;
|
||||
|
||||
/**
|
||||
* 通知与回调记录控制器。
|
||||
*
|
||||
* 负责渠道通知日志和商户通知任务的接入。
|
||||
*/
|
||||
class NotifyController extends BaseController
|
||||
{
|
||||
/**
|
||||
* 构造函数,注入通知服务。
|
||||
*/
|
||||
public function __construct(
|
||||
protected NotifyService $notifyService
|
||||
) {
|
||||
}
|
||||
|
||||
/**
|
||||
* POST /api/notify/channel
|
||||
*
|
||||
* 记录渠道通知日志。
|
||||
*/
|
||||
public function channel(Request $request): Response
|
||||
{
|
||||
$data = $this->validated($request->all(), NotifyChannelValidator::class, 'store');
|
||||
|
||||
return $this->success($this->notifyService->recordChannelNotify($data));
|
||||
}
|
||||
|
||||
/**
|
||||
* POST /api/notify/merchant
|
||||
*
|
||||
* 创建商户通知任务。
|
||||
*/
|
||||
public function merchant(Request $request): Response
|
||||
{
|
||||
$data = $this->validated($request->all(), NotifyMerchantValidator::class, 'store');
|
||||
|
||||
return $this->success($this->notifyService->enqueueMerchantNotify($data));
|
||||
}
|
||||
}
|
||||
|
||||
43
app/http/api/controller/route/RouteController.php
Normal file
43
app/http/api/controller/route/RouteController.php
Normal file
@@ -0,0 +1,43 @@
|
||||
<?php
|
||||
|
||||
namespace app\http\api\controller\route;
|
||||
|
||||
use app\common\base\BaseController;
|
||||
use app\http\api\validation\RouteResolveValidator;
|
||||
use app\service\payment\runtime\PaymentRouteService;
|
||||
use support\Request;
|
||||
use support\Response;
|
||||
|
||||
/**
|
||||
* 路由预览控制器。
|
||||
*
|
||||
* 用于返回指定商户分组、支付方式和金额条件下的路由解析结果。
|
||||
*/
|
||||
class RouteController extends BaseController
|
||||
{
|
||||
/**
|
||||
* 构造函数,注入路由服务。
|
||||
*/
|
||||
public function __construct(
|
||||
protected PaymentRouteService $paymentRouteService
|
||||
) {
|
||||
}
|
||||
|
||||
/**
|
||||
* GET /api/routes/resolve
|
||||
*
|
||||
* 解析支付路由。
|
||||
*/
|
||||
public function resolve(Request $request): Response
|
||||
{
|
||||
$data = $this->validated($request->all(), RouteResolveValidator::class, 'resolve');
|
||||
|
||||
return $this->success($this->paymentRouteService->resolveByMerchantGroup(
|
||||
(int) $data['merchant_group_id'],
|
||||
(int) $data['pay_type_id'],
|
||||
(int) $data['pay_amount'],
|
||||
$data
|
||||
));
|
||||
}
|
||||
}
|
||||
|
||||
78
app/http/api/controller/settlement/SettlementController.php
Normal file
78
app/http/api/controller/settlement/SettlementController.php
Normal file
@@ -0,0 +1,78 @@
|
||||
<?php
|
||||
|
||||
namespace app\http\api\controller\settlement;
|
||||
|
||||
use app\common\base\BaseController;
|
||||
use app\exception\ResourceNotFoundException;
|
||||
use app\http\api\validation\SettlementActionValidator;
|
||||
use app\http\api\validation\SettlementCreateValidator;
|
||||
use app\service\payment\settlement\SettlementService;
|
||||
use support\Request;
|
||||
use support\Response;
|
||||
|
||||
/**
|
||||
* 清算接口控制器。
|
||||
*
|
||||
* 负责清算单创建、查询和清算状态推进。
|
||||
*/
|
||||
class SettlementController extends BaseController
|
||||
{
|
||||
/**
|
||||
* 构造函数,注入清算相关依赖。
|
||||
*/
|
||||
public function __construct(
|
||||
protected SettlementService $settlementService,
|
||||
) {
|
||||
}
|
||||
|
||||
/**
|
||||
* 创建清结算单。
|
||||
*/
|
||||
public function create(Request $request): Response
|
||||
{
|
||||
$data = $this->validated($request->all(), SettlementCreateValidator::class, 'store');
|
||||
$items = (array) ($data['items'] ?? []);
|
||||
|
||||
return $this->success($this->settlementService->createSettlementOrder($data, $items));
|
||||
}
|
||||
|
||||
/**
|
||||
* 查询清结算单详情。
|
||||
*/
|
||||
public function show(Request $request, string $settleNo): Response
|
||||
{
|
||||
try {
|
||||
return $this->success($this->settlementService->detail($settleNo));
|
||||
} catch (ResourceNotFoundException) {
|
||||
return $this->fail('清算单不存在', 404);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 标记清结算成功。
|
||||
*/
|
||||
public function complete(Request $request, string $settleNo): Response
|
||||
{
|
||||
$this->validated(
|
||||
array_merge($request->all(), ['settle_no' => $settleNo]),
|
||||
SettlementActionValidator::class,
|
||||
'complete'
|
||||
);
|
||||
|
||||
return $this->success($this->settlementService->completeSettlement($settleNo));
|
||||
}
|
||||
|
||||
/**
|
||||
* 标记清结算失败。
|
||||
*/
|
||||
public function failSettlement(Request $request, string $settleNo): Response
|
||||
{
|
||||
$data = $this->validated(
|
||||
array_merge($request->all(), ['settle_no' => $settleNo]),
|
||||
SettlementActionValidator::class,
|
||||
'fail'
|
||||
);
|
||||
|
||||
return $this->success($this->settlementService->failSettlement($settleNo, (string) ($data['reason'] ?? '')));
|
||||
}
|
||||
}
|
||||
39
app/http/api/controller/trace/TraceController.php
Normal file
39
app/http/api/controller/trace/TraceController.php
Normal file
@@ -0,0 +1,39 @@
|
||||
<?php
|
||||
|
||||
namespace app\http\api\controller\trace;
|
||||
|
||||
use app\common\base\BaseController;
|
||||
use app\http\api\validation\TraceQueryValidator;
|
||||
use app\service\payment\trace\TradeTraceService;
|
||||
use support\Request;
|
||||
use support\Response;
|
||||
|
||||
/**
|
||||
* 统一追踪查询控制器。
|
||||
*/
|
||||
class TraceController extends BaseController
|
||||
{
|
||||
public function __construct(
|
||||
protected TradeTraceService $tradeTraceService
|
||||
) {
|
||||
}
|
||||
|
||||
/**
|
||||
* 查询指定追踪号对应的完整交易链路。
|
||||
*/
|
||||
public function show(Request $request, string $traceNo): Response
|
||||
{
|
||||
$data = $this->validated(
|
||||
array_merge($request->all(), ['trace_no' => $traceNo]),
|
||||
TraceQueryValidator::class,
|
||||
'show'
|
||||
);
|
||||
|
||||
$result = $this->tradeTraceService->queryByTraceNo((string) $data['trace_no']);
|
||||
if (empty($result)) {
|
||||
return $this->fail('追踪单不存在', 404);
|
||||
}
|
||||
|
||||
return $this->success($result);
|
||||
}
|
||||
}
|
||||
138
app/http/api/controller/trade/PayController.php
Normal file
138
app/http/api/controller/trade/PayController.php
Normal file
@@ -0,0 +1,138 @@
|
||||
<?php
|
||||
|
||||
namespace app\http\api\controller\trade;
|
||||
|
||||
use app\common\base\BaseController;
|
||||
use app\exception\ResourceNotFoundException;
|
||||
use app\http\api\validation\PayCallbackValidator;
|
||||
use app\http\api\validation\PayCloseValidator;
|
||||
use app\http\api\validation\PayPrepareValidator;
|
||||
use app\http\api\validation\PayTimeoutValidator;
|
||||
use app\service\merchant\security\MerchantApiCredentialService;
|
||||
use app\service\payment\config\PaymentTypeService;
|
||||
use app\service\payment\order\PayOrderService;
|
||||
use support\Request;
|
||||
use support\Response;
|
||||
|
||||
/**
|
||||
* 支付接口控制器。
|
||||
*
|
||||
* 负责支付预下单、支付查询、支付关闭和渠道回调入口。
|
||||
*/
|
||||
class PayController extends BaseController
|
||||
{
|
||||
/**
|
||||
* 构造函数,注入支付单相关依赖。
|
||||
*/
|
||||
public function __construct(
|
||||
protected PayOrderService $payOrderService,
|
||||
protected MerchantApiCredentialService $merchantApiCredentialService,
|
||||
protected PaymentTypeService $paymentTypeService
|
||||
) {
|
||||
}
|
||||
|
||||
/**
|
||||
* 支付预下单。
|
||||
*/
|
||||
public function prepare(Request $request): Response
|
||||
{
|
||||
$data = $this->validated(
|
||||
$this->normalizePreparePayload($request, $request->all()),
|
||||
PayPrepareValidator::class,
|
||||
'prepare'
|
||||
);
|
||||
|
||||
return $this->success($this->payOrderService->preparePayAttempt($data));
|
||||
}
|
||||
|
||||
/**
|
||||
* 查询支付单详情。
|
||||
*/
|
||||
public function show(Request $request, string $payNo): Response
|
||||
{
|
||||
try {
|
||||
return $this->success($this->payOrderService->detail($payNo));
|
||||
} catch (ResourceNotFoundException) {
|
||||
return $this->fail('支付单不存在', 404);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 关闭支付单。
|
||||
*/
|
||||
public function close(Request $request, string $payNo): Response
|
||||
{
|
||||
$data = $this->validated(
|
||||
array_merge($request->all(), ['pay_no' => $payNo]),
|
||||
PayCloseValidator::class,
|
||||
'close'
|
||||
);
|
||||
|
||||
return $this->success($this->payOrderService->closePayOrder($payNo, $data));
|
||||
}
|
||||
|
||||
/**
|
||||
* 标记支付单超时。
|
||||
*/
|
||||
public function timeout(Request $request, string $payNo): Response
|
||||
{
|
||||
$data = $this->validated(
|
||||
array_merge($request->all(), ['pay_no' => $payNo]),
|
||||
PayTimeoutValidator::class,
|
||||
'timeout'
|
||||
);
|
||||
|
||||
return $this->success($this->payOrderService->timeoutPayOrder($payNo, $data));
|
||||
}
|
||||
|
||||
/**
|
||||
* 处理渠道回调。
|
||||
*/
|
||||
public function callback(Request $request, string $payNo = ''): Response|string
|
||||
{
|
||||
if ($payNo !== '') {
|
||||
return $this->payOrderService->handlePluginCallback($payNo, $request);
|
||||
}
|
||||
|
||||
$data = $this->validated($request->all(), PayCallbackValidator::class, 'callback');
|
||||
|
||||
return $this->success($this->payOrderService->handleChannelCallback($data));
|
||||
}
|
||||
|
||||
/**
|
||||
* 归一化外部支付下单参数并完成签名校验。
|
||||
*
|
||||
* 这层逻辑保留在控制器内,避免中间件承担业务验签职责。
|
||||
*/
|
||||
private function normalizePreparePayload(Request $request, array $payload): array
|
||||
{
|
||||
$this->merchantApiCredentialService->verifyMd5Sign($payload);
|
||||
|
||||
$typeCode = trim((string) ($payload['type'] ?? ''));
|
||||
$paymentType = $this->paymentTypeService->resolveEnabledType($typeCode);
|
||||
$typeCode = (string) $paymentType->code;
|
||||
|
||||
$money = (string) ($payload['money'] ?? '0');
|
||||
$amount = (int) round(((float) $money) * 100);
|
||||
|
||||
return [
|
||||
'merchant_id' => (int) ($payload['pid'] ?? 0),
|
||||
'merchant_order_no' => (string) ($payload['out_trade_no'] ?? ''),
|
||||
'pay_type_id' => (int) $paymentType->id,
|
||||
'pay_amount' => $amount,
|
||||
'subject' => (string) ($payload['name'] ?? ''),
|
||||
'body' => (string) ($payload['name'] ?? ''),
|
||||
'ext_json' => [
|
||||
'type_code' => $typeCode,
|
||||
'notify_url' => (string) ($payload['notify_url'] ?? ''),
|
||||
'return_url' => (string) ($payload['return_url'] ?? ''),
|
||||
'param' => $payload['param'] ?? null,
|
||||
'clientip' => (string) ($payload['clientip'] ?? ''),
|
||||
'device' => (string) ($payload['device'] ?? ''),
|
||||
'sign_type' => (string) ($payload['sign_type'] ?? 'MD5'),
|
||||
'channel_callback_base_url' => (string) sys_config('site_url') . '/api/pay',
|
||||
],
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
93
app/http/api/controller/trade/RefundController.php
Normal file
93
app/http/api/controller/trade/RefundController.php
Normal file
@@ -0,0 +1,93 @@
|
||||
<?php
|
||||
|
||||
namespace app\http\api\controller\trade;
|
||||
|
||||
use app\common\base\BaseController;
|
||||
use app\exception\ResourceNotFoundException;
|
||||
use app\http\api\validation\RefundActionValidator;
|
||||
use app\http\api\validation\RefundCreateValidator;
|
||||
use app\service\payment\order\RefundService;
|
||||
use support\Request;
|
||||
use support\Response;
|
||||
|
||||
/**
|
||||
* 退款接口控制器。
|
||||
*
|
||||
* 负责退款单创建与退款单查询。
|
||||
*/
|
||||
class RefundController extends BaseController
|
||||
{
|
||||
/**
|
||||
* 构造函数,注入退款相关依赖。
|
||||
*/
|
||||
public function __construct(
|
||||
protected RefundService $refundService,
|
||||
) {
|
||||
}
|
||||
|
||||
/**
|
||||
* 创建退款单。
|
||||
*/
|
||||
public function create(Request $request): Response
|
||||
{
|
||||
$data = $this->validated($request->all(), RefundCreateValidator::class, 'store');
|
||||
|
||||
return $this->success($this->refundService->createRefund($data));
|
||||
}
|
||||
|
||||
/**
|
||||
* 查询退款单详情。
|
||||
*/
|
||||
public function show(Request $request, string $refundNo): Response
|
||||
{
|
||||
try {
|
||||
return $this->success($this->refundService->detail($refundNo));
|
||||
} catch (ResourceNotFoundException) {
|
||||
return $this->fail('退款单不存在', 404);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 标记退款处理中。
|
||||
*/
|
||||
public function processing(Request $request, string $refundNo): Response
|
||||
{
|
||||
$data = $this->validated(
|
||||
array_merge($request->all(), ['refund_no' => $refundNo]),
|
||||
RefundActionValidator::class,
|
||||
'processing'
|
||||
);
|
||||
|
||||
return $this->success($this->refundService->markRefundProcessing($refundNo, $data));
|
||||
}
|
||||
|
||||
/**
|
||||
* 退款重试。
|
||||
*/
|
||||
public function retry(Request $request, string $refundNo): Response
|
||||
{
|
||||
$data = $this->validated(
|
||||
array_merge($request->all(), ['refund_no' => $refundNo]),
|
||||
RefundActionValidator::class,
|
||||
'retry'
|
||||
);
|
||||
|
||||
return $this->success($this->refundService->retryRefund($refundNo, $data));
|
||||
}
|
||||
|
||||
/**
|
||||
* 标记退款失败。
|
||||
*/
|
||||
public function markFail(Request $request, string $refundNo): Response
|
||||
{
|
||||
$data = $this->validated(
|
||||
array_merge($request->all(), ['refund_no' => $refundNo]),
|
||||
RefundActionValidator::class,
|
||||
'fail'
|
||||
);
|
||||
|
||||
return $this->success($this->refundService->markRefundFailed($refundNo, $data));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,69 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace app\http\api\middleware;
|
||||
|
||||
use Webman\MiddlewareInterface;
|
||||
use Webman\Http\Request;
|
||||
use Webman\Http\Response;
|
||||
use app\exceptions\UnauthorizedException;
|
||||
use app\repositories\MerchantAppRepository;
|
||||
|
||||
/**
|
||||
* OpenAPI 签名认证中间件
|
||||
*
|
||||
* 验证 AppId + 签名
|
||||
*/
|
||||
class EpayAuthMiddleware implements MiddlewareInterface
|
||||
{
|
||||
protected MerchantAppRepository $merchantAppRepository;
|
||||
|
||||
public function __construct()
|
||||
{
|
||||
// 延迟加载,避免循环依赖
|
||||
$this->merchantAppRepository = new MerchantAppRepository();
|
||||
}
|
||||
|
||||
public function process(Request $request, callable $handler): Response
|
||||
{
|
||||
$appId = $request->header('X-App-Id', '') ?: ($request->post('app_id', '') ?: $request->get('app_id', ''));
|
||||
$timestamp = $request->header('X-Timestamp', '') ?: ($request->post('timestamp', '') ?: $request->get('timestamp', ''));
|
||||
$nonce = $request->header('X-Nonce', '') ?: ($request->post('nonce', '') ?: $request->get('nonce', ''));
|
||||
$signature = $request->header('X-Signature', '') ?: ($request->post('signature', '') ?: $request->get('signature', ''));
|
||||
|
||||
if (empty($appId) || empty($timestamp) || empty($nonce) || empty($signature)) {
|
||||
throw new UnauthorizedException('缺少认证参数');
|
||||
}
|
||||
|
||||
// 验证时间戳(5分钟内有效)
|
||||
if (abs(time() - (int)$timestamp) > 300) {
|
||||
throw new UnauthorizedException('请求已过期');
|
||||
}
|
||||
|
||||
// 查询应用
|
||||
$app = $this->merchantAppRepository->findByAppId($appId);
|
||||
if (!$app) {
|
||||
throw new UnauthorizedException('应用不存在或已禁用');
|
||||
}
|
||||
|
||||
// 验证签名
|
||||
$method = $request->method();
|
||||
$path = $request->path();
|
||||
$body = $request->rawBody();
|
||||
$bodySha256 = hash('sha256', $body);
|
||||
|
||||
$signString = "app_id={$appId}×tamp={$timestamp}&nonce={$nonce}&method={$method}&path={$path}&body_sha256={$bodySha256}";
|
||||
$expectedSignature = hash_hmac('sha256', $signString, $app->app_secret);
|
||||
|
||||
if (!hash_equals($expectedSignature, $signature)) {
|
||||
throw new UnauthorizedException('签名验证失败');
|
||||
}
|
||||
|
||||
// 将应用信息注入到请求对象
|
||||
$request->app = $app;
|
||||
$request->merchantId = $app->merchant_id;
|
||||
$request->appId = $app->id;
|
||||
|
||||
return $handler($request);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,69 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace app\http\api\middleware;
|
||||
|
||||
use Webman\MiddlewareInterface;
|
||||
use Webman\Http\Request;
|
||||
use Webman\Http\Response;
|
||||
use app\exceptions\UnauthorizedException;
|
||||
use app\repositories\MerchantAppRepository;
|
||||
|
||||
/**
|
||||
* OpenAPI 签名认证中间件
|
||||
*
|
||||
* 验证 AppId + 签名
|
||||
*/
|
||||
class OpenApiAuthMiddleware implements MiddlewareInterface
|
||||
{
|
||||
protected MerchantAppRepository $merchantAppRepository;
|
||||
|
||||
public function __construct()
|
||||
{
|
||||
// 延迟加载,避免循环依赖
|
||||
$this->merchantAppRepository = new MerchantAppRepository();
|
||||
}
|
||||
|
||||
public function process(Request $request, callable $handler): Response
|
||||
{
|
||||
$appId = $request->header('X-App-Id', '') ?: ($request->post('app_id', '') ?: $request->get('app_id', ''));
|
||||
$timestamp = $request->header('X-Timestamp', '') ?: ($request->post('timestamp', '') ?: $request->get('timestamp', ''));
|
||||
$nonce = $request->header('X-Nonce', '') ?: ($request->post('nonce', '') ?: $request->get('nonce', ''));
|
||||
$signature = $request->header('X-Signature', '') ?: ($request->post('signature', '') ?: $request->get('signature', ''));
|
||||
|
||||
if (empty($appId) || empty($timestamp) || empty($nonce) || empty($signature)) {
|
||||
throw new UnauthorizedException('缺少认证参数');
|
||||
}
|
||||
|
||||
// 验证时间戳(5分钟内有效)
|
||||
if (abs(time() - (int)$timestamp) > 300) {
|
||||
throw new UnauthorizedException('请求已过期');
|
||||
}
|
||||
|
||||
// 查询应用
|
||||
$app = $this->merchantAppRepository->findByAppId($appId);
|
||||
if (!$app) {
|
||||
throw new UnauthorizedException('应用不存在或已禁用');
|
||||
}
|
||||
|
||||
// 验证签名
|
||||
$method = $request->method();
|
||||
$path = $request->path();
|
||||
$body = $request->rawBody();
|
||||
$bodySha256 = hash('sha256', $body);
|
||||
|
||||
$signString = "app_id={$appId}×tamp={$timestamp}&nonce={$nonce}&method={$method}&path={$path}&body_sha256={$bodySha256}";
|
||||
$expectedSignature = hash_hmac('sha256', $signString, $app->app_secret);
|
||||
|
||||
if (!hash_equals($expectedSignature, $signature)) {
|
||||
throw new UnauthorizedException('签名验证失败');
|
||||
}
|
||||
|
||||
// 将应用信息注入到请求对象
|
||||
$request->app = $app;
|
||||
$request->merchantId = $app->merchant_id;
|
||||
$request->appId = $app->id;
|
||||
|
||||
return $handler($request);
|
||||
}
|
||||
}
|
||||
|
||||
113
app/http/api/validation/EpayValidator.php
Normal file
113
app/http/api/validation/EpayValidator.php
Normal file
@@ -0,0 +1,113 @@
|
||||
<?php
|
||||
|
||||
namespace app\http\api\validation;
|
||||
|
||||
use support\validation\Validator;
|
||||
|
||||
/**
|
||||
* ePay 兼容层请求校验器。
|
||||
*
|
||||
* 根据 submit、mapi、api.php 的不同入口场景做分场景校验,不依赖隐藏标记字段。
|
||||
*/
|
||||
class EpayValidator extends Validator
|
||||
{
|
||||
protected array $rules = [
|
||||
'act' => 'required|string|in:query,settle,order,orders,refund',
|
||||
'pid' => 'required|integer|gt:0',
|
||||
'key' => 'required|string|min:1|max:255',
|
||||
'type' => 'sometimes|string|max:32',
|
||||
'out_trade_no' => 'sometimes|string|min:1|max:64',
|
||||
'notify_url' => 'sometimes|url|max:255',
|
||||
'return_url' => 'sometimes|url|max:255',
|
||||
'name' => 'sometimes|string|min:1|max:255',
|
||||
'money' => 'sometimes|numeric|gt:0|regex:/^\d+(?:\.\d{1,2})?$/',
|
||||
'sign' => 'sometimes|string|min:1|max:255',
|
||||
'sign_type' => 'sometimes|string|in:MD5,md5',
|
||||
'device' => 'sometimes|string|in:pc,mobile,qq,wechat,alipay,jump',
|
||||
'clientip' => 'sometimes|ip',
|
||||
'param' => 'sometimes|string|max:2000',
|
||||
'trade_no' => 'sometimes|string|min:1|max:64',
|
||||
'refund_no' => 'sometimes|string|min:1|max:64',
|
||||
'reason' => 'sometimes|string|max:255',
|
||||
'limit' => 'sometimes|integer|gt:0|max:50',
|
||||
'page' => 'sometimes|integer|gt:0',
|
||||
];
|
||||
|
||||
protected array $attributes = [
|
||||
'act' => '操作类型',
|
||||
'pid' => '商户ID',
|
||||
'key' => '商户密钥',
|
||||
'type' => '支付方式',
|
||||
'out_trade_no' => '商户订单号',
|
||||
'trade_no' => '易支付订单号',
|
||||
'notify_url' => '异步通知地址',
|
||||
'return_url' => '跳转通知地址',
|
||||
'name' => '商品名称',
|
||||
'money' => '商品金额',
|
||||
'sign' => '签名字符串',
|
||||
'sign_type' => '签名类型',
|
||||
'device' => '设备类型',
|
||||
'clientip' => '用户IP地址',
|
||||
'param' => '业务扩展参数',
|
||||
'refund_no' => '退款单号',
|
||||
'reason' => '退款原因',
|
||||
'limit' => '查询订单数量',
|
||||
'page' => '页码',
|
||||
];
|
||||
|
||||
protected array $scenes = [
|
||||
'submit' => ['pid', 'type', 'out_trade_no', 'notify_url', 'return_url', 'name', 'money', 'sign', 'sign_type', 'param'],
|
||||
'mapi' => ['pid', 'type', 'out_trade_no', 'notify_url', 'return_url', 'name', 'money', 'clientip', 'device', 'sign', 'sign_type', 'param'],
|
||||
'query' => ['act', 'pid', 'key'],
|
||||
'settle' => ['act', 'pid', 'key'],
|
||||
'order_trade_no' => ['act', 'pid', 'key', 'trade_no'],
|
||||
'order_out_trade_no' => ['act', 'pid', 'key', 'out_trade_no'],
|
||||
'orders' => ['act', 'pid', 'key', 'limit', 'page'],
|
||||
'refund_trade_no' => ['act', 'pid', 'key', 'trade_no', 'money', 'refund_no', 'reason'],
|
||||
'refund_out_trade_no' => ['act', 'pid', 'key', 'out_trade_no', 'money', 'refund_no', 'reason'],
|
||||
];
|
||||
|
||||
public function rules(): array
|
||||
{
|
||||
$rules = parent::rules();
|
||||
|
||||
return match ($this->scene()) {
|
||||
'submit' => array_merge($rules, [
|
||||
'type' => 'sometimes|string|max:32',
|
||||
'out_trade_no' => 'required|string|min:1|max:64',
|
||||
'notify_url' => 'required|url|max:255',
|
||||
'return_url' => 'required|url|max:255',
|
||||
'name' => 'required|string|min:1|max:255',
|
||||
'money' => 'required|numeric|gt:0|regex:/^\d+(?:\.\d{1,2})?$/',
|
||||
'sign' => 'required|string|min:1|max:255',
|
||||
'sign_type' => 'required|string|in:MD5,md5',
|
||||
]),
|
||||
'mapi' => array_merge($rules, [
|
||||
'type' => 'required|string|max:32',
|
||||
'out_trade_no' => 'required|string|min:1|max:64',
|
||||
'notify_url' => 'required|url|max:255',
|
||||
'return_url' => 'sometimes|url|max:255',
|
||||
'name' => 'required|string|min:1|max:255',
|
||||
'money' => 'required|numeric|gt:0|regex:/^\d+(?:\.\d{1,2})?$/',
|
||||
'clientip' => 'required|ip',
|
||||
'sign' => 'required|string|min:1|max:255',
|
||||
'sign_type' => 'required|string|in:MD5,md5',
|
||||
]),
|
||||
'order_trade_no' => array_merge($rules, [
|
||||
'trade_no' => 'required|string|min:1|max:64',
|
||||
]),
|
||||
'order_out_trade_no' => array_merge($rules, [
|
||||
'out_trade_no' => 'required|string|min:1|max:64',
|
||||
]),
|
||||
'refund_trade_no' => array_merge($rules, [
|
||||
'trade_no' => 'required|string|min:1|max:64',
|
||||
'money' => 'required|numeric|gt:0|regex:/^\d+(?:\.\d{1,2})?$/',
|
||||
]),
|
||||
'refund_out_trade_no' => array_merge($rules, [
|
||||
'out_trade_no' => 'required|string|min:1|max:64',
|
||||
'money' => 'required|numeric|gt:0|regex:/^\d+(?:\.\d{1,2})?$/',
|
||||
]),
|
||||
default => $rules,
|
||||
};
|
||||
}
|
||||
}
|
||||
49
app/http/api/validation/NotifyChannelValidator.php
Normal file
49
app/http/api/validation/NotifyChannelValidator.php
Normal file
@@ -0,0 +1,49 @@
|
||||
<?php
|
||||
|
||||
namespace app\http\api\validation;
|
||||
|
||||
use support\validation\Validator;
|
||||
|
||||
/**
|
||||
* 渠道通知参数校验器。
|
||||
*
|
||||
* 用于校验渠道通知日志入参。
|
||||
*/
|
||||
class NotifyChannelValidator extends Validator
|
||||
{
|
||||
protected array $rules = [
|
||||
'notify_no' => 'sometimes|string|min:1|max:64',
|
||||
'channel_id' => 'required|integer|min:1|exists:ma_payment_channel,id',
|
||||
'notify_type' => 'sometimes|integer|in:0,1',
|
||||
'biz_no' => 'required|string|min:1|max:64',
|
||||
'pay_no' => 'sometimes|string|min:1|max:64',
|
||||
'channel_request_no' => 'sometimes|string|min:1|max:64',
|
||||
'channel_trade_no' => 'sometimes|string|min:1|max:64',
|
||||
'raw_payload' => 'nullable|array',
|
||||
'verify_status' => 'sometimes|integer|in:0,1,2',
|
||||
'process_status' => 'sometimes|integer|in:0,1,2',
|
||||
'retry_count' => 'sometimes|integer|min:0',
|
||||
'next_retry_at' => 'nullable|date_format:Y-m-d H:i:s',
|
||||
'last_error' => 'nullable|string|max:255',
|
||||
];
|
||||
|
||||
protected array $attributes = [
|
||||
'notify_no' => '通知单号',
|
||||
'channel_id' => '通道ID',
|
||||
'notify_type' => '通知类型',
|
||||
'biz_no' => '业务单号',
|
||||
'pay_no' => '支付单号',
|
||||
'channel_request_no' => '渠道请求号',
|
||||
'channel_trade_no' => '渠道交易号',
|
||||
'raw_payload' => '原始通知数据',
|
||||
'verify_status' => '验签状态',
|
||||
'process_status' => '处理状态',
|
||||
'retry_count' => '重试次数',
|
||||
'next_retry_at' => '下次重试时间',
|
||||
'last_error' => '最后错误',
|
||||
];
|
||||
|
||||
protected array $scenes = [
|
||||
'store' => ['notify_no', 'channel_id', 'notify_type', 'biz_no', 'pay_no', 'channel_request_no', 'channel_trade_no', 'raw_payload', 'verify_status', 'process_status', 'retry_count', 'next_retry_at', 'last_error'],
|
||||
];
|
||||
}
|
||||
47
app/http/api/validation/NotifyMerchantValidator.php
Normal file
47
app/http/api/validation/NotifyMerchantValidator.php
Normal file
@@ -0,0 +1,47 @@
|
||||
<?php
|
||||
|
||||
namespace app\http\api\validation;
|
||||
|
||||
use support\validation\Validator;
|
||||
|
||||
/**
|
||||
* 商户通知参数校验器。
|
||||
*
|
||||
* 用于校验商户通知任务入参。
|
||||
*/
|
||||
class NotifyMerchantValidator extends Validator
|
||||
{
|
||||
protected array $rules = [
|
||||
'notify_no' => 'sometimes|string|min:1|max:64',
|
||||
'merchant_id' => 'required|integer|min:1|exists:ma_merchant,id',
|
||||
'merchant_group_id' => 'required|integer|min:1|exists:ma_merchant_group,id',
|
||||
'biz_no' => 'required|string|min:1|max:64',
|
||||
'pay_no' => 'sometimes|string|min:1|max:64',
|
||||
'notify_url' => 'required|url|max:255',
|
||||
'notify_data' => 'nullable|array',
|
||||
'status' => 'sometimes|integer|min:0',
|
||||
'retry_count' => 'sometimes|integer|min:0',
|
||||
'next_retry_at' => 'nullable|date_format:Y-m-d H:i:s',
|
||||
'last_notify_at' => 'nullable|date_format:Y-m-d H:i:s',
|
||||
'last_response' => 'nullable|string|max:255',
|
||||
];
|
||||
|
||||
protected array $attributes = [
|
||||
'notify_no' => '通知单号',
|
||||
'merchant_id' => '商户ID',
|
||||
'merchant_group_id' => '商户分组ID',
|
||||
'biz_no' => '业务单号',
|
||||
'pay_no' => '支付单号',
|
||||
'notify_url' => '通知地址',
|
||||
'notify_data' => '通知内容',
|
||||
'status' => '状态',
|
||||
'retry_count' => '重试次数',
|
||||
'next_retry_at' => '下次重试时间',
|
||||
'last_notify_at' => '最后通知时间',
|
||||
'last_response' => '最后响应',
|
||||
];
|
||||
|
||||
protected array $scenes = [
|
||||
'store' => ['notify_no', 'merchant_id', 'merchant_group_id', 'biz_no', 'pay_no', 'notify_url', 'notify_data', 'status', 'retry_count', 'next_retry_at', 'last_notify_at', 'last_response'],
|
||||
];
|
||||
}
|
||||
53
app/http/api/validation/PayCallbackValidator.php
Normal file
53
app/http/api/validation/PayCallbackValidator.php
Normal file
@@ -0,0 +1,53 @@
|
||||
<?php
|
||||
|
||||
namespace app\http\api\validation;
|
||||
|
||||
use support\validation\Validator;
|
||||
|
||||
/**
|
||||
* 支付回调参数校验器。
|
||||
*
|
||||
* 用于校验渠道回调和主动查单回传参数。
|
||||
*/
|
||||
class PayCallbackValidator extends Validator
|
||||
{
|
||||
protected array $rules = [
|
||||
'pay_no' => 'required|string|min:1|max:64|exists:ma_pay_order,pay_no',
|
||||
'success' => 'required|boolean',
|
||||
'channel_id' => 'nullable|integer|min:1|exists:ma_payment_channel,id',
|
||||
'callback_type' => 'nullable|integer|in:0,1',
|
||||
'request_data' => 'nullable|array',
|
||||
'verify_status' => 'nullable|integer|in:0,1,2',
|
||||
'process_status' => 'nullable|integer|in:0,1,2',
|
||||
'process_result' => 'nullable|array',
|
||||
'channel_trade_no' => 'nullable|string|max:64',
|
||||
'channel_order_no' => 'nullable|string|max:64',
|
||||
'fee_actual_amount' => 'nullable|integer|min:0',
|
||||
'paid_at' => 'nullable|date_format:Y-m-d H:i:s',
|
||||
'channel_error_code' => 'nullable|string|max:64',
|
||||
'channel_error_msg' => 'nullable|string|max:255',
|
||||
'ext_json' => 'nullable|array',
|
||||
];
|
||||
|
||||
protected array $attributes = [
|
||||
'pay_no' => '支付单号',
|
||||
'success' => '是否成功',
|
||||
'channel_id' => '通道ID',
|
||||
'callback_type' => '回调类型',
|
||||
'request_data' => '原始回调数据',
|
||||
'verify_status' => '验签状态',
|
||||
'process_status' => '处理状态',
|
||||
'process_result' => '处理结果',
|
||||
'channel_trade_no' => '渠道交易号',
|
||||
'channel_order_no' => '渠道订单号',
|
||||
'fee_actual_amount' => '实际手续费',
|
||||
'paid_at' => '支付时间',
|
||||
'channel_error_code' => '错误码',
|
||||
'channel_error_msg' => '错误信息',
|
||||
'ext_json' => '扩展信息',
|
||||
];
|
||||
|
||||
protected array $scenes = [
|
||||
'callback' => ['pay_no', 'success', 'channel_id', 'callback_type', 'request_data', 'verify_status', 'process_status', 'process_result', 'channel_trade_no', 'channel_order_no', 'fee_actual_amount', 'paid_at', 'channel_error_code', 'channel_error_msg', 'ext_json'],
|
||||
];
|
||||
}
|
||||
31
app/http/api/validation/PayCloseValidator.php
Normal file
31
app/http/api/validation/PayCloseValidator.php
Normal file
@@ -0,0 +1,31 @@
|
||||
<?php
|
||||
|
||||
namespace app\http\api\validation;
|
||||
|
||||
use support\validation\Validator;
|
||||
|
||||
/**
|
||||
* 支付关闭参数校验器。
|
||||
*
|
||||
* 用于校验关闭支付单所需参数。
|
||||
*/
|
||||
class PayCloseValidator extends Validator
|
||||
{
|
||||
protected array $rules = [
|
||||
'pay_no' => 'required|string|min:1|max:64|exists:ma_pay_order,pay_no',
|
||||
'reason' => 'nullable|string|max:255',
|
||||
'closed_at' => 'nullable|date_format:Y-m-d H:i:s',
|
||||
'ext_json' => 'nullable|array',
|
||||
];
|
||||
|
||||
protected array $attributes = [
|
||||
'pay_no' => '支付单号',
|
||||
'reason' => '关闭原因',
|
||||
'closed_at' => '关闭时间',
|
||||
'ext_json' => '扩展信息',
|
||||
];
|
||||
|
||||
protected array $scenes = [
|
||||
'close' => ['pay_no', 'reason', 'closed_at', 'ext_json'],
|
||||
];
|
||||
}
|
||||
37
app/http/api/validation/PayPrepareValidator.php
Normal file
37
app/http/api/validation/PayPrepareValidator.php
Normal file
@@ -0,0 +1,37 @@
|
||||
<?php
|
||||
|
||||
namespace app\http\api\validation;
|
||||
|
||||
use support\validation\Validator;
|
||||
|
||||
/**
|
||||
* 支付预下单参数校验器。
|
||||
*
|
||||
* 用于校验支付发起时的核心入参。
|
||||
*/
|
||||
class PayPrepareValidator extends Validator
|
||||
{
|
||||
protected array $rules = [
|
||||
'merchant_id' => 'required|integer|min:1|exists:ma_merchant,id',
|
||||
'merchant_order_no' => 'required|string|min:1|max:64',
|
||||
'pay_type_id' => 'required|integer|min:1|exists:ma_payment_type,id',
|
||||
'pay_amount' => 'required|integer|min:1',
|
||||
'subject' => 'sometimes|string|max:255',
|
||||
'body' => 'sometimes|string|max:500',
|
||||
'ext_json' => 'nullable|array',
|
||||
];
|
||||
|
||||
protected array $attributes = [
|
||||
'merchant_id' => '商户ID',
|
||||
'merchant_order_no' => '商户订单号',
|
||||
'pay_type_id' => '支付方式',
|
||||
'pay_amount' => '支付金额',
|
||||
'subject' => '标题',
|
||||
'body' => '描述',
|
||||
'ext_json' => '扩展信息',
|
||||
];
|
||||
|
||||
protected array $scenes = [
|
||||
'prepare' => ['merchant_id', 'merchant_order_no', 'pay_type_id', 'pay_amount', 'subject', 'body', 'ext_json'],
|
||||
];
|
||||
}
|
||||
31
app/http/api/validation/PayTimeoutValidator.php
Normal file
31
app/http/api/validation/PayTimeoutValidator.php
Normal file
@@ -0,0 +1,31 @@
|
||||
<?php
|
||||
|
||||
namespace app\http\api\validation;
|
||||
|
||||
use support\validation\Validator;
|
||||
|
||||
/**
|
||||
* 支付超时参数校验器。
|
||||
*
|
||||
* 用于校验超时关闭支付单所需参数。
|
||||
*/
|
||||
class PayTimeoutValidator extends Validator
|
||||
{
|
||||
protected array $rules = [
|
||||
'pay_no' => 'required|string|min:1|max:64|exists:ma_pay_order,pay_no',
|
||||
'reason' => 'nullable|string|max:255',
|
||||
'timeout_at' => 'nullable|date_format:Y-m-d H:i:s',
|
||||
'ext_json' => 'nullable|array',
|
||||
];
|
||||
|
||||
protected array $attributes = [
|
||||
'pay_no' => '支付单号',
|
||||
'reason' => '超时原因',
|
||||
'timeout_at' => '超时时间',
|
||||
'ext_json' => '扩展信息',
|
||||
];
|
||||
|
||||
protected array $scenes = [
|
||||
'timeout' => ['pay_no', 'reason', 'timeout_at', 'ext_json'],
|
||||
];
|
||||
}
|
||||
37
app/http/api/validation/RefundActionValidator.php
Normal file
37
app/http/api/validation/RefundActionValidator.php
Normal file
@@ -0,0 +1,37 @@
|
||||
<?php
|
||||
|
||||
namespace app\http\api\validation;
|
||||
|
||||
use support\validation\Validator;
|
||||
|
||||
/**
|
||||
* 退款动作参数校验器。
|
||||
*
|
||||
* 用于校验退款处理、失败和重试操作的公共参数。
|
||||
*/
|
||||
class RefundActionValidator extends Validator
|
||||
{
|
||||
protected array $rules = [
|
||||
'refund_no' => 'required|string|min:1|max:64|exists:ma_refund_order,refund_no',
|
||||
'reason' => 'nullable|string|max:255',
|
||||
'last_error' => 'nullable|string|max:255',
|
||||
'processing_at' => 'nullable|date_format:Y-m-d H:i:s',
|
||||
'failed_at' => 'nullable|date_format:Y-m-d H:i:s',
|
||||
'ext_json' => 'nullable|array',
|
||||
];
|
||||
|
||||
protected array $attributes = [
|
||||
'refund_no' => '退款单号',
|
||||
'reason' => '原因',
|
||||
'last_error' => '最近错误信息',
|
||||
'processing_at' => '处理时间',
|
||||
'failed_at' => '失败时间',
|
||||
'ext_json' => '扩展信息',
|
||||
];
|
||||
|
||||
protected array $scenes = [
|
||||
'processing' => ['refund_no', 'reason', 'last_error', 'processing_at', 'ext_json'],
|
||||
'retry' => ['refund_no', 'reason', 'last_error', 'processing_at', 'ext_json'],
|
||||
'fail' => ['refund_no', 'reason', 'last_error', 'failed_at', 'ext_json'],
|
||||
];
|
||||
}
|
||||
33
app/http/api/validation/RefundCreateValidator.php
Normal file
33
app/http/api/validation/RefundCreateValidator.php
Normal file
@@ -0,0 +1,33 @@
|
||||
<?php
|
||||
|
||||
namespace app\http\api\validation;
|
||||
|
||||
use support\validation\Validator;
|
||||
|
||||
/**
|
||||
* 退款创建参数校验器。
|
||||
*
|
||||
* 用于校验退款单创建参数。
|
||||
*/
|
||||
class RefundCreateValidator extends Validator
|
||||
{
|
||||
protected array $rules = [
|
||||
'pay_no' => 'required|string|min:1|max:64|exists:ma_pay_order,pay_no',
|
||||
'merchant_refund_no' => 'sometimes|string|min:1|max:64',
|
||||
'refund_amount' => 'nullable|integer|min:1',
|
||||
'reason' => 'nullable|string|max:255',
|
||||
'ext_json' => 'nullable|array',
|
||||
];
|
||||
|
||||
protected array $attributes = [
|
||||
'pay_no' => '支付单号',
|
||||
'merchant_refund_no' => '商户退款单号',
|
||||
'refund_amount' => '退款金额',
|
||||
'reason' => '退款原因',
|
||||
'ext_json' => '扩展信息',
|
||||
];
|
||||
|
||||
protected array $scenes = [
|
||||
'store' => ['pay_no', 'merchant_refund_no', 'refund_amount', 'reason', 'ext_json'],
|
||||
];
|
||||
}
|
||||
31
app/http/api/validation/RouteResolveValidator.php
Normal file
31
app/http/api/validation/RouteResolveValidator.php
Normal file
@@ -0,0 +1,31 @@
|
||||
<?php
|
||||
|
||||
namespace app\http\api\validation;
|
||||
|
||||
use support\validation\Validator;
|
||||
|
||||
/**
|
||||
* 路由解析参数校验器。
|
||||
*
|
||||
* 用于校验路由预览所需参数。
|
||||
*/
|
||||
class RouteResolveValidator extends Validator
|
||||
{
|
||||
protected array $rules = [
|
||||
'merchant_group_id' => 'required|integer|min:1|exists:ma_merchant_group,id',
|
||||
'pay_type_id' => 'required|integer|min:1|exists:ma_payment_type,id',
|
||||
'pay_amount' => 'required|integer|min:1',
|
||||
'stat_date' => 'nullable|date_format:Y-m-d',
|
||||
];
|
||||
|
||||
protected array $attributes = [
|
||||
'merchant_group_id' => '商户分组ID',
|
||||
'pay_type_id' => '支付方式',
|
||||
'pay_amount' => '支付金额',
|
||||
'stat_date' => '统计日期',
|
||||
];
|
||||
|
||||
protected array $scenes = [
|
||||
'resolve' => ['merchant_group_id', 'pay_type_id', 'pay_amount', 'stat_date'],
|
||||
];
|
||||
}
|
||||
30
app/http/api/validation/SettlementActionValidator.php
Normal file
30
app/http/api/validation/SettlementActionValidator.php
Normal file
@@ -0,0 +1,30 @@
|
||||
<?php
|
||||
|
||||
namespace app\http\api\validation;
|
||||
|
||||
use support\validation\Validator;
|
||||
|
||||
/**
|
||||
* 清算动作参数校验器。
|
||||
*
|
||||
* 用于校验清算成功和失败动作的公共参数。
|
||||
*/
|
||||
class SettlementActionValidator extends Validator
|
||||
{
|
||||
protected array $rules = [
|
||||
'settle_no' => 'required|string|min:1|max:64|exists:ma_settlement_order,settle_no',
|
||||
'reason' => 'nullable|string|max:255',
|
||||
'ext_json' => 'nullable|array',
|
||||
];
|
||||
|
||||
protected array $attributes = [
|
||||
'settle_no' => '清算单号',
|
||||
'reason' => '原因',
|
||||
'ext_json' => '扩展信息',
|
||||
];
|
||||
|
||||
protected array $scenes = [
|
||||
'complete' => ['settle_no'],
|
||||
'fail' => ['settle_no', 'reason', 'ext_json'],
|
||||
];
|
||||
}
|
||||
63
app/http/api/validation/SettlementCreateValidator.php
Normal file
63
app/http/api/validation/SettlementCreateValidator.php
Normal file
@@ -0,0 +1,63 @@
|
||||
<?php
|
||||
|
||||
namespace app\http\api\validation;
|
||||
|
||||
use support\validation\Validator;
|
||||
|
||||
/**
|
||||
* 清算创建参数校验器。
|
||||
*
|
||||
* 用于校验清算单和清算明细的创建参数。
|
||||
*/
|
||||
class SettlementCreateValidator extends Validator
|
||||
{
|
||||
protected array $rules = [
|
||||
'settle_no' => 'sometimes|string|min:1|max:64',
|
||||
'merchant_id' => 'required|integer|min:1|exists:ma_merchant,id',
|
||||
'merchant_group_id' => 'required|integer|min:1|exists:ma_merchant_group,id',
|
||||
'channel_id' => 'required|integer|min:1|exists:ma_payment_channel,id',
|
||||
'cycle_type' => 'required|integer|min:0',
|
||||
'cycle_key' => 'required|string|min:1|max:64',
|
||||
'status' => 'sometimes|integer|min:0',
|
||||
'generated_at' => 'nullable|date_format:Y-m-d H:i:s',
|
||||
'accounted_amount' => 'nullable|integer|min:0',
|
||||
'gross_amount' => 'nullable|integer|min:0',
|
||||
'fee_amount' => 'nullable|integer|min:0',
|
||||
'refund_amount' => 'nullable|integer|min:0',
|
||||
'fee_reverse_amount' => 'nullable|integer|min:0',
|
||||
'net_amount' => 'nullable|integer|min:0',
|
||||
'ext_json' => 'nullable|array',
|
||||
'items' => 'nullable|array',
|
||||
'items.*.pay_no' => 'sometimes|string|min:1|max:64',
|
||||
'items.*.refund_no' => 'sometimes|string|min:1|max:64',
|
||||
'items.*.pay_amount' => 'sometimes|integer|min:0',
|
||||
'items.*.fee_amount' => 'sometimes|integer|min:0',
|
||||
'items.*.refund_amount' => 'sometimes|integer|min:0',
|
||||
'items.*.fee_reverse_amount' => 'sometimes|integer|min:0',
|
||||
'items.*.net_amount' => 'sometimes|integer|min:0',
|
||||
'items.*.item_status' => 'sometimes|integer|min:0',
|
||||
];
|
||||
|
||||
protected array $attributes = [
|
||||
'settle_no' => '清算单号',
|
||||
'merchant_id' => '商户ID',
|
||||
'merchant_group_id' => '商户分组ID',
|
||||
'channel_id' => '通道ID',
|
||||
'cycle_type' => '结算周期类型',
|
||||
'cycle_key' => '结算周期键',
|
||||
'status' => '状态',
|
||||
'generated_at' => '生成时间',
|
||||
'accounted_amount' => '入账金额',
|
||||
'gross_amount' => '交易总额',
|
||||
'fee_amount' => '手续费',
|
||||
'refund_amount' => '退款金额',
|
||||
'fee_reverse_amount' => '手续费冲回',
|
||||
'net_amount' => '净额',
|
||||
'ext_json' => '扩展信息',
|
||||
'items' => '清算明细',
|
||||
];
|
||||
|
||||
protected array $scenes = [
|
||||
'store' => ['settle_no', 'merchant_id', 'merchant_group_id', 'channel_id', 'cycle_type', 'cycle_key', 'status', 'generated_at', 'accounted_amount', 'gross_amount', 'fee_amount', 'refund_amount', 'fee_reverse_amount', 'net_amount', 'ext_json', 'items', 'items.*.pay_no', 'items.*.refund_no', 'items.*.pay_amount', 'items.*.fee_amount', 'items.*.refund_amount', 'items.*.fee_reverse_amount', 'items.*.net_amount', 'items.*.item_status'],
|
||||
];
|
||||
}
|
||||
23
app/http/api/validation/TraceQueryValidator.php
Normal file
23
app/http/api/validation/TraceQueryValidator.php
Normal file
@@ -0,0 +1,23 @@
|
||||
<?php
|
||||
|
||||
namespace app\http\api\validation;
|
||||
|
||||
use support\validation\Validator;
|
||||
|
||||
/**
|
||||
* 统一追踪查询参数校验器。
|
||||
*/
|
||||
class TraceQueryValidator extends Validator
|
||||
{
|
||||
protected array $rules = [
|
||||
'trace_no' => 'required|string|min:1|max:64',
|
||||
];
|
||||
|
||||
protected array $attributes = [
|
||||
'trace_no' => '追踪号',
|
||||
];
|
||||
|
||||
protected array $scenes = [
|
||||
'show' => ['trace_no'],
|
||||
];
|
||||
}
|
||||
Reference in New Issue
Block a user