1. 维护代码健壮

2. 更新项目结构文档
This commit is contained in:
技术老胡
2026-04-27 16:20:41 +08:00
parent 9a16a88640
commit 0e5de50337
198 changed files with 21038 additions and 702 deletions

View File

@@ -0,0 +1,68 @@
<?php
namespace app\http\api\validation;
use support\validation\Validator;
/**
* 收银台请求验证器。
*
* 定义收银台上下文查询与确认支付场景规则。
*/
class CashierValidator extends Validator
{
protected array $rules = [
'biz_no' => 'required|string|max:32',
'pay_no' => 'required|string|max:32',
'type' => 'nullable|string|max:32',
];
protected array $attributes = [
'biz_no' => '业务单号',
'pay_no' => '支付单号',
'type' => '支付方式',
];
protected array $scenes = [
'context' => ['biz_no'],
'confirm' => ['biz_no', 'type'],
'pay_order' => ['pay_no'],
];
/**
* 收银台上下文场景。
*
* @return static
*/
public function sceneContext(): static
{
return $this->appendRules([
'biz_no' => 'required|string|max:32',
]);
}
/**
* 收银台确认场景。
*
* @return static
*/
public function sceneConfirm(): static
{
return $this->appendRules([
'biz_no' => 'required|string|max:32',
'type' => 'required|string|max:32',
]);
}
/**
* 支付页详情场景。
*
* @return static
*/
public function scenePayOrder(): static
{
return $this->appendRules([
'pay_no' => 'required|string|max:32',
]);
}
}

View File

@@ -0,0 +1,168 @@
<?php
namespace app\http\api\validation;
use support\validation\Validator;
/**
* ePay V1 请求验证器。
*
* 定义旧版提交、查询、退款与兼容接口的场景规则。
*/
class EpayV1Validator extends Validator
{
protected array $rules = [
'act' => 'sometimes|string|in:query,settle,order,orders,refund',
'pid' => 'required|integer|min:1',
'key' => 'nullable|string|max:128',
'type' => 'nullable|string|max:32',
'trade_no' => 'nullable|string|max:64',
'out_trade_no' => 'nullable|string|max:64',
'notify_url' => 'nullable|string|max:255',
'return_url' => 'nullable|string|max:255',
'name' => 'nullable|string|max:255',
'money' => 'nullable|regex:/^\d+(?:\.\d{1,2})?$/',
'param' => 'nullable',
'clientip' => 'nullable|ip',
'device' => 'nullable|string|in:pc,mobile,qq,wechat,alipay,jump',
'sign' => 'nullable|string|max:255',
'sign_type' => 'sometimes|string|in:MD5',
'page' => 'sometimes|integer|min:1',
'limit' => 'sometimes|integer|min:1|max:50',
];
protected array $attributes = [
'act' => '操作类型',
'pid' => '商户ID',
'key' => '商户密钥',
'type' => '支付方式',
'trade_no' => '平台订单号',
'out_trade_no' => '商户订单号',
'notify_url' => '异步通知地址',
'return_url' => '跳转通知地址',
'name' => '商品名称',
'money' => '商品金额',
'param' => '业务扩展参数',
'clientip' => '用户 IP',
'device' => '设备类型',
'sign' => '签名字符串',
'sign_type' => '签名类型',
'page' => '页码',
'limit' => '数量',
];
protected array $scenes = [
'submit' => ['pid', 'type', 'out_trade_no', 'notify_url', 'return_url', 'name', 'money', 'param', 'sign', 'sign_type'],
'mapi' => ['pid', 'type', 'out_trade_no', 'notify_url', 'return_url', 'name', 'money', 'param', 'clientip', 'device', 'sign', 'sign_type'],
'api_query' => ['act', 'pid', 'key'],
'api_settle' => ['act', 'pid', 'key'],
'api_order' => ['act', 'pid', 'key', 'trade_no', 'out_trade_no'],
'api_orders' => ['act', 'pid', 'key', 'page', 'limit'],
'api_refund' => ['act', 'pid', 'key', 'trade_no', 'out_trade_no', 'money'],
];
/**
* 页面跳转支付场景。
*
* @return static
*/
public function sceneSubmit(): static
{
return $this->appendRules([
'out_trade_no' => 'required|string|max:64',
'notify_url' => 'required|string|max:255',
'return_url' => 'required|string|max:255',
'name' => 'required|string|max:255',
'money' => 'required|regex:/^\d+(?:\.\d{1,2})?$/',
'sign_type' => 'required|string|in:MD5',
'sign' => 'required|string|max:255',
]);
}
/**
* API 支付场景。
*
* @return static
*/
public function sceneMapi(): static
{
return $this->appendRules([
'type' => 'required|string|max:32',
'out_trade_no' => 'required|string|max:64',
'notify_url' => 'required|string|max:255',
'return_url' => 'nullable|string|max:255',
'name' => 'required|string|max:255',
'money' => 'required|regex:/^\d+(?:\.\d{1,2})?$/',
'clientip' => 'required|ip',
'sign_type' => 'required|string|in:MD5',
'sign' => 'required|string|max:255',
]);
}
/**
* 商户信息查询场景。
*
* @return static
*/
public function sceneApiQuery(): static
{
return $this->appendRules([
'key' => 'required|string|max:128',
]);
}
/**
* 结算记录查询场景。
*
* @return static
*/
public function sceneApiSettle(): static
{
return $this->appendRules([
'key' => 'required|string|max:128',
]);
}
/**
* 单个订单查询场景。
*
* @return static
*/
public function sceneApiOrder(): static
{
return $this->appendRules([
'key' => 'required|string|max:128',
'trade_no' => 'nullable|string|max:64|required_without:out_trade_no',
'out_trade_no' => 'nullable|string|max:64|required_without:trade_no',
]);
}
/**
* 订单列表查询场景。
*
* @return static
*/
public function sceneApiOrders(): static
{
return $this->appendRules([
'key' => 'required|string|max:128',
'page' => 'sometimes|integer|min:1',
'limit' => 'sometimes|integer|min:1|max:50',
]);
}
/**
* 退款申请场景。
*
* @return static
*/
public function sceneApiRefund(): static
{
return $this->appendRules([
'key' => 'required|string|max:128',
'money' => 'required|regex:/^\d+(?:\.\d{1,2})?$/',
'trade_no' => 'nullable|string|max:64|required_without:out_trade_no',
'out_trade_no' => 'nullable|string|max:64|required_without:trade_no',
]);
}
}

View File

@@ -0,0 +1,216 @@
<?php
namespace app\http\api\validation;
use support\validation\Validator;
/**
* ePay V2 请求验证器。
*
* 定义新版支付、退款、商户与转账接口的场景规则。
*/
class EpayV2Validator extends Validator
{
protected array $rules = [
'pid' => 'required|integer|min:1',
'timestamp' => 'required|integer|min:1',
// 兼容旧版 SDK 里使用的 `RSA` 简写,同时内部统一按 SHA256WithRSA 验签。
'sign_type' => 'required|string|in:SHA256WithRSA,RSA',
// RSA 签名是 Base64 文本,长度会明显超过 MD5不能沿用 255 的短限制。
'sign' => 'required|string|max:2048',
'type' => 'nullable|string|max:32',
'method' => 'nullable|string|in:web,jump,jsapi,app,scan,applet',
'trade_no' => 'nullable|string|max:64',
'out_trade_no' => 'nullable|string|max:64',
'notify_url' => 'nullable|string|max:255',
'return_url' => 'nullable|string|max:255',
'name' => 'nullable|string|max:255',
'money' => 'nullable|regex:/^\d+(?:\.\d{1,2})?$/',
'param' => 'nullable',
'auth_code' => 'nullable|string|max:128',
'sub_openid' => 'nullable|string|max:128',
'sub_appid' => 'nullable|string|max:64',
'clientip' => 'nullable|ip',
'device' => 'nullable|string|in:pc,mobile,qq,wechat,alipay',
'channel_id' => 'nullable|integer|min:0',
'offset' => 'sometimes|integer|min:0',
'limit' => 'sometimes|integer|min:1|max:50',
'status' => 'nullable|integer|min:0|max:5',
'refund_no' => 'nullable|string|max:64',
'out_refund_no' => 'nullable|string|max:64',
'biz_no' => 'nullable|string|max:32',
'out_biz_no' => 'nullable|string|max:64',
'account' => 'nullable|string|max:100',
'bookid' => 'nullable|string|max:64',
'remark' => 'nullable|string|max:255',
];
protected array $attributes = [
'pid' => '商户ID',
'timestamp' => '时间戳',
'sign_type' => '签名类型',
'sign' => '签名字符串',
'type' => '支付方式',
'method' => '接口类型',
'trade_no' => '平台订单号',
'out_trade_no' => '商户订单号',
'notify_url' => '异步通知地址',
'return_url' => '跳转通知地址',
'name' => '商品名称',
'money' => '商品金额',
'param' => '业务扩展参数',
'auth_code' => '授权码',
'sub_openid' => '子用户 OPENID',
'sub_appid' => '子应用 APPID',
'clientip' => '用户 IP',
'device' => '设备类型',
'channel_id' => '渠道ID',
'offset' => '偏移量',
'limit' => '数量',
'status' => '状态',
'refund_no' => '退款单号',
'out_refund_no' => '商户退款单号',
'biz_no' => '平台业务号',
'out_biz_no' => '商户转账单号',
'account' => '收款账号',
'bookid' => '书签ID',
'remark' => '备注',
];
protected array $scenes = [
'submit' => ['pid', 'timestamp', 'sign_type', 'sign', 'type', 'out_trade_no', 'notify_url', 'return_url', 'name', 'money', 'param', 'channel_id'],
'create' => ['pid', 'timestamp', 'sign_type', 'sign', 'type', 'method', 'out_trade_no', 'notify_url', 'return_url', 'name', 'money', 'param', 'auth_code', 'sub_openid', 'sub_appid', 'clientip', 'device', 'channel_id'],
'query' => ['pid', 'timestamp', 'sign_type', 'sign', 'trade_no', 'out_trade_no'],
'refund' => ['pid', 'timestamp', 'sign_type', 'sign', 'trade_no', 'out_trade_no', 'money', 'out_refund_no'],
'refund_query' => ['pid', 'timestamp', 'sign_type', 'sign', 'refund_no', 'out_refund_no'],
'close' => ['pid', 'timestamp', 'sign_type', 'sign', 'trade_no', 'out_trade_no'],
'merchant_info' => ['pid', 'timestamp', 'sign_type', 'sign'],
'merchant_orders' => ['pid', 'timestamp', 'sign_type', 'sign', 'offset', 'limit', 'status'],
'transfer_submit' => ['pid', 'timestamp', 'sign_type', 'sign', 'type', 'account', 'name', 'money', 'out_biz_no', 'remark', 'bookid'],
'transfer_query' => ['pid', 'timestamp', 'sign_type', 'sign', 'biz_no', 'out_biz_no'],
'transfer_balance' => ['pid', 'timestamp', 'sign_type', 'sign'],
];
/**
* 页面跳转支付场景。
*
* @return static
*/
public function sceneSubmit(): static
{
return $this->appendRules([
'type' => 'nullable|string|max:32',
'out_trade_no' => 'required|string|max:64',
'notify_url' => 'required|string|max:255',
'return_url' => 'required|string|max:255',
'name' => 'required|string|max:255',
'money' => 'required|regex:/^\d+(?:\.\d{1,2})?$/',
'sign_type' => 'required|string|in:SHA256WithRSA,RSA',
'sign' => 'required|string|max:2048',
]);
}
/**
* API 下单场景。
*
* @return static
*/
public function sceneCreate(): static
{
return $this->appendRules([
'type' => 'required|string|max:32',
'method' => 'required|string|in:web,jump,jsapi,app,scan,applet',
'out_trade_no' => 'required|string|max:64',
'notify_url' => 'required|string|max:255',
'return_url' => 'nullable|string|max:255',
'name' => 'required|string|max:255',
'money' => 'required|regex:/^\d+(?:\.\d{1,2})?$/',
'device' => 'nullable|string|in:pc,mobile,qq,wechat,alipay',
'sign_type' => 'required|string|in:SHA256WithRSA,RSA',
'sign' => 'required|string|max:2048',
]);
}
/**
* 退款发起场景。
*
* @return static
*/
public function sceneRefund(): static
{
return $this->appendRules([
'money' => 'required|regex:/^\d+(?:\.\d{1,2})?$/',
'trade_no' => 'nullable|string|max:64|required_without:out_trade_no',
'out_trade_no' => 'nullable|string|max:64|required_without:trade_no',
'out_refund_no' => 'nullable|string|max:64',
'sign_type' => 'required|string|in:SHA256WithRSA,RSA',
'sign' => 'required|string|max:2048',
]);
}
/**
* 支付单查询场景。
*
* @return static
*/
public function sceneQuery(): static
{
return $this->appendRules([
'trade_no' => 'nullable|string|max:64|required_without:out_trade_no',
'out_trade_no' => 'nullable|string|max:64|required_without:trade_no',
]);
}
/**
* 关闭订单场景。
*
* @return static
*/
public function sceneClose(): static
{
return $this->sceneQuery();
}
/**
* 退款查询场景。
*
* @return static
*/
public function sceneRefundQuery(): static
{
return $this->appendRules([
'refund_no' => 'nullable|string|max:64|required_without:out_refund_no',
'out_refund_no' => 'nullable|string|max:64|required_without:refund_no',
]);
}
/**
* 转账查询场景。
*
* @return static
*/
public function sceneTransferQuery(): static
{
return $this->appendRules([
'biz_no' => 'nullable|string|max:32|required_without:out_biz_no',
'out_biz_no' => 'nullable|string|max:64|required_without:biz_no',
]);
}
/**
* 转账发起场景。
*
* @return static
*/
public function sceneTransferSubmit(): static
{
return $this->appendRules([
'type' => 'required|string|in:alipay,wxpay,qqpay,bank',
'account' => 'required|string|max:100',
'name' => 'required|string|max:100',
'money' => 'required|regex:/^\d+(?:\.\d{1,2})?$/',
'sign_type' => 'required|string|in:SHA256WithRSA,RSA',
'sign' => 'required|string|max:2048',
]);
}
}