重构初始化

This commit is contained in:
技术老胡
2026-04-15 11:45:46 +08:00
parent 72d72d735b
commit 7612026773
381 changed files with 28287 additions and 14717 deletions

View File

@@ -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']);
}
}

View File

@@ -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');
}
}
}

View 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() ?: '请求失败',
]);
}
}
}

View 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));
}
}

View 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
));
}
}

View 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'] ?? '')));
}
}

View 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);
}
}

View 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',
],
];
}
}

View 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));
}
}