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:
132
app/http/api/controller/EpayController.php
Normal file
132
app/http/api/controller/EpayController.php
Normal file
@@ -0,0 +1,132 @@
|
||||
<?php
|
||||
|
||||
namespace app\http\api\controller;
|
||||
|
||||
use app\common\base\BaseController;
|
||||
use app\services\api\EpayService;
|
||||
use app\validation\EpayValidator;
|
||||
use support\Request;
|
||||
use support\Response;
|
||||
|
||||
/**
|
||||
* 易支付控制器
|
||||
*/
|
||||
class EpayController extends BaseController
|
||||
{
|
||||
public function __construct(
|
||||
protected EpayService $epayService
|
||||
) {}
|
||||
|
||||
/**
|
||||
* 页面跳转支付
|
||||
*/
|
||||
public function submit(Request $request)
|
||||
{
|
||||
$data = array_merge($request->get(), $request->post());
|
||||
|
||||
try {
|
||||
// 参数校验(使用自定义 Validator + 场景)
|
||||
$params = EpayValidator::make($data)
|
||||
->withScene('submit')
|
||||
->validate();
|
||||
|
||||
// 业务处理:创建订单并获取支付参数
|
||||
$result = $this->epayService->submit($params, $request);
|
||||
$payParams = $result['pay_params'] ?? [];
|
||||
|
||||
// 根据支付参数类型返回响应
|
||||
if (($payParams['type'] ?? '') === 'redirect' && !empty($payParams['url'])) {
|
||||
return redirect($payParams['url']);
|
||||
}
|
||||
|
||||
if (($payParams['type'] ?? '') === 'form') {
|
||||
return $this->renderForm($payParams);
|
||||
}
|
||||
|
||||
// 如果没有匹配的类型,返回错误
|
||||
return $this->fail('支付参数生成失败');
|
||||
} catch (\Throwable $e) {
|
||||
return $this->fail($e->getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* API接口支付
|
||||
*/
|
||||
public function mapi(Request $request)
|
||||
{
|
||||
$data = $request->post();
|
||||
|
||||
try {
|
||||
$params = EpayValidator::make($data)
|
||||
->withScene('mapi')
|
||||
->validate();
|
||||
|
||||
$result = $this->epayService->mapi($params, $request);
|
||||
|
||||
return json($result);
|
||||
} catch (\Throwable $e) {
|
||||
return json([
|
||||
'code' => 0,
|
||||
'msg' => $e->getMessage(),
|
||||
]);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* API接口
|
||||
*/
|
||||
public function api(Request $request)
|
||||
{
|
||||
$data = array_merge($request->get(), $request->post());
|
||||
|
||||
try {
|
||||
$act = strtolower($data['act'] ?? '');
|
||||
|
||||
if ($act === 'order') {
|
||||
$params = EpayValidator::make($data)
|
||||
->withScene('api_order')
|
||||
->validate();
|
||||
$result = $this->epayService->api($params);
|
||||
} elseif ($act === 'refund') {
|
||||
$params = EpayValidator::make($data)
|
||||
->withScene('api_refund')
|
||||
->validate();
|
||||
$result = $this->epayService->api($params);
|
||||
} else {
|
||||
$result = [
|
||||
'code' => 0,
|
||||
'msg' => '不支持的操作类型',
|
||||
];
|
||||
}
|
||||
|
||||
return json($result);
|
||||
} 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']);
|
||||
}
|
||||
}
|
||||
41
app/http/api/controller/PayController.php
Normal file
41
app/http/api/controller/PayController.php
Normal file
@@ -0,0 +1,41 @@
|
||||
<?php
|
||||
|
||||
namespace app\http\api\controller;
|
||||
|
||||
use app\common\base\BaseController;
|
||||
use app\services\PayOrderService;
|
||||
use support\Request;
|
||||
|
||||
/**
|
||||
* 支付控制器(OpenAPI)
|
||||
*/
|
||||
class PayController extends BaseController
|
||||
{
|
||||
public function __construct(
|
||||
protected PayOrderService $payOrderService
|
||||
) {}
|
||||
|
||||
/**
|
||||
* 创建订单
|
||||
*/
|
||||
public function create(Request $request) {}
|
||||
|
||||
/**
|
||||
* 查询订单
|
||||
*/
|
||||
public function query(Request $request) {}
|
||||
|
||||
/**
|
||||
* 关闭订单
|
||||
*/
|
||||
public function close(Request $request) {}
|
||||
|
||||
/**
|
||||
* 订单退款
|
||||
*/
|
||||
public function refund(Request $request) {}
|
||||
/**
|
||||
* 异步通知
|
||||
*/
|
||||
public function notify(Request $request) {}
|
||||
}
|
||||
69
app/http/api/middleware/EpayAuthMiddleware.php
Normal file
69
app/http/api/middleware/EpayAuthMiddleware.php
Normal file
@@ -0,0 +1,69 @@
|
||||
<?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);
|
||||
}
|
||||
}
|
||||
|
||||
69
app/http/api/middleware/OpenApiAuthMiddleware.php
Normal file
69
app/http/api/middleware/OpenApiAuthMiddleware.php
Normal file
@@ -0,0 +1,69 @@
|
||||
<?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);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user