支付管理
1. 功能概述
支付管理模块是系统的重要组成部分,负责处理支付相关的所有功能,包含以下主要模块:
- 支付渠道管理:配置和管理各种支付渠道
- 支付审核:审核支付单据
- 账单管理:查询和统计支付账单
- 退款管理:处理退款申请和操作
- 支付操作:发起支付和查询支付状态
- 转账管理:配置和管理转账场景
1.1 支付管理功能流程
mermaid
flowchart TD
A[支付管理] --> B[支付渠道管理]
A --> C[支付审核]
A --> D[账单管理]
A --> E[退款管理]
A --> F[支付操作]
A --> G[转账管理]
subgraph 支付渠道
B --> B1[渠道列表]
B --> B2[渠道设置]
B --> B3[转账设置]
B1 --> B11[获取渠道]
B1 --> B12[筛选渠道]
B2 --> B21[配置参数]
B2 --> B22[启用禁用]
B3 --> B31[配置转账参数]
B3 --> B32[设置默认渠道]
end
subgraph 支付流程
F --> F1[发起支付]
F --> F2[支付信息查询]
F --> F3[支付方式列表]
F1 --> F11[生成订单]
F1 --> F12[调用渠道接口]
F1 --> F13[返回支付参数]
F2 --> F21[查询订单状态]
F2 --> F22[获取详细信息]
F2 --> F23[处理回调]
end
subgraph 审核与管理
C --> C1[审核列表]
C --> C2[审核操作]
C --> C3[单据详情]
D --> D1[账单列表]
D --> D2[账单详情]
D --> D3[账单统计]
E --> E1[退款列表]
E --> E2[退款详情]
E --> E3[退款操作]
G --> G1[转账场景管理]
G --> G2[业务场景配置]
end2. 路由配置
支付管理相关的路由配置位于 backend/app/adminapi/route/pay.php 文件中,主要包含以下路由组:
2.1 支付渠道管理
GET /pay/channel/lists:渠道列表POST /pay/channel/set/:channel/:type:渠道设置GET /pay/channel/lists/:channel:通过渠道获取支付配置POST /pay/channel/set/transfer:转账设置POST /pay/channel/set/all:多渠道设置GET /pay/type/all:获取全部支付方式
2.2 支付审核
GET /pay/audit:支付审核PUT /pay/pass/:out_trade_no:审核通过PUT /pay/refuse/:out_trade_no:审核拒绝GET /pay/detail/:id:支付单据详情
2.3 账单管理
GET /pay/account:账单列表GET /pay/account/:id:账单详情GET /pay/account/stat:账单统计GET /pay/account/type:账单类型
2.4 退款管理
GET /pay/refund:退款列表GET /pay/refund/status:获取退款状态GET /pay/refund/:refund_no:退款详情GET /pay/refund/type:退款方式POST /pay/refund/transfer:退款转账
2.5 支付操作
POST /pay:去支付GET /pay/info/:trade_type/:trade_id:支付信息GET /pay/type/list:支付方式列表
2.6 转账管理
GET /pay/transfer_scene:获取转账场景POST /pay/transfer_scene/set_scene_id/:scene:设置场景idPOST /pay/transfer_scene/set_trade_scene/:type:设置业务场景配置
3. 核心功能实现
3.1 支付渠道管理
3.1.1 渠道列表
- 获取所有可用的支付渠道
- 支持按渠道类型筛选
- 显示渠道的配置状态
实现代码:
php
// PayChannelService.php 中的 getChannelList 方法
public function getChannelList()
{
$channel_list = PayChannelDict::getPayChannel();
$where = array (
['id', '>', 0]
);
$pay_channel_list_temp = $this->model->where($where)->field('type, channel, config, sort, status')->select()->toArray();
$pay_channel_list = [];
foreach ($pay_channel_list_temp as $v) {
$pay_channel_list[ $v[ 'channel' ] ][ $v[ 'type' ] ] = $v;
}
$pay_type_list = PayDict::getPayType();
foreach ($channel_list as $k => $v) {
$temp_item = $pay_channel_list[ $k ] ?? [];
foreach ($v[ 'pay_type' ] as $item_k => $item_v) {
if (isset($temp_item[ $item_k ])) {
$temp_v_item = $temp_item[ $item_k ];
$encrypt_params = $pay_type_list[$item_k]['encrypt_params'] ?? [];
foreach ($temp_v_item['config'] as $config_k => $config_v) {
if ($config_v !== '' && in_array($config_k, $encrypt_params)) $temp_v_item['config'][$config_k] = CommonDict::ENCRYPT_STR;
}
} else {
$temp_v_item = [ 'status' => 0, 'config' => $this->getConfigByPayType([], $item_k), 'sort' => 0 ];
}
$item_v[ 'config' ] = $temp_v_item[ 'config' ];
$item_v[ 'status' ] = $temp_v_item[ 'status' ];
$item_v[ 'sort' ] = $temp_v_item[ 'sort' ];
$channel_list[ $k ][ 'pay_type' ][ $item_k ] = $item_v;
}
$temp_pay_type = array_values($channel_list[ $k ][ 'pay_type' ]);
$sort = array_column($temp_pay_type, 'sort');
array_multisort($sort, SORT_ASC, $temp_pay_type);
$channel_list[ $k ][ 'pay_type' ] = $temp_pay_type;
}
return $channel_list;
}3.1.2 渠道设置
- 配置支付渠道的参数(如AppID、AppSecret等)
- 启用/禁用支付渠道
- 测试支付渠道的连接状态
实现代码:
php
// PayChannelService.php 中的 set 方法
public function set(string $channel, string $type, array $data)
{
$where = array (
'type' => $type,
'channel' => $channel
);
if (!array_key_exists($type, PayDict::getPayType())) throw new PayException('PATMENT_METHOD_INVALID');
if ($channel != 'transfer') {
if (!array_key_exists($channel, ChannelDict::getType())) throw new PayException('CHANNEL_MARK_INVALID');
}
$pay_channel = $this->core_pay_channel_service->find($where);
if ($pay_channel->isEmpty()) {
$data[ 'channel' ] = $channel;
$data[ 'type' ] = $type;
$data[ 'config' ] = $this->getConfigByPayType($data[ 'config' ], $type);
$res = $this->model->create($data);
} else {
$config = $pay_channel->config;
$data[ 'config' ] = $this->getConfigByPayType($data[ 'config' ], $type);
foreach ($data[ 'config' ] as $config_k => $config_v) {
if ($config_v == CommonDict::ENCRYPT_STR && isset($config[$config_k])) {
$data[ 'config' ][$config_k] = $config[$config_k];
}
}
$pay_channel->save($data);
}
return true;
}配置格式处理代码:
php
// PayChannelService.php 中的 getConfigByPayType 方法
public function getConfigByPayType($data, $type)
{
$config = [];
switch ($type) {
case PayDict::WECHATPAY:
$config = [
'mch_id' => $data[ 'mch_id' ] ?? '',//商户号
'mch_secret_key' => $data[ 'mch_secret_key' ] ?? '',//商户秘钥 现在默认认为是v3版
'mch_secret_cert' => $data[ 'mch_secret_cert' ] ?? '',//商户私钥 字符串或路径
'mch_public_cert_path' => $data[ 'mch_public_cert_path' ] ?? '',//商户公钥证书路径
'wechat_public_cert_path' => $data['wechat_public_cert_path'] ?? '', // 微信支付公钥
'wechat_public_cert_id' => $data['wechat_public_cert_id'] ?? '' // 微信支付公钥id
];
break;
case PayDict::ALIPAY:
$config = [
'app_id' => $data[ 'app_id' ] ?? '',// 必填-支付宝分配的 app_id
'app_secret_cert' => $data[ 'app_secret_cert' ] ?? '',// 必填-应用私钥 字符串或路径
'app_public_cert_path' => $data[ 'app_public_cert_path' ] ?? '',//必填-应用公钥证书 路径
'alipay_public_cert_path' => $data[ 'alipay_public_cert_path' ] ?? '',//必填-支付宝公钥证书 路径
'alipay_root_cert_path' => $data[ 'alipay_root_cert_path' ] ?? '',// 必填-支付宝根证书 路径
];
break;
case PayDict::OFFLINEPAY:
$config = [
'collection_name' => $data[ 'collection_name' ] ?? '',// 必填-收款账户名称
'collection_bank' => $data[ 'collection_bank' ] ?? '',//必填-收款银行
'collection_account' => $data[ 'collection_account' ] ?? '',//必填-收款账号
'collection_desc' => $data[ 'collection_desc' ] ?? '',// 必填-转账说明
];
break;
default:
$config = $data;
}
return $config;
}3.1.3 转账设置
- 配置转账相关的参数
- 设置转账的默认渠道
- 测试转账功能
实现代码:
php
// PayChannelService.php 中的 setTransfer 方法
public function setTransfer($data)
{
$wechatpay_config = $data[ 'wechatpay_config' ];
$alipay_config = $data[ 'alipay_config' ];
$this->set('transfer', PayDict::WECHATPAY, [
'config' => $wechatpay_config,
'status' => 1,
]);
$this->set('transfer', PayDict::ALIPAY, [
'config' => $alipay_config,
'status' => 1,
]);
return true;
}3.2 支付审核
3.2.1 支付审核列表
- 查看待审核的支付单据
- 支持按时间、金额、状态等条件筛选
- 批量审核功能
3.2.2 审核操作
- 审核通过支付单据
- 拒绝支付单据并填写原因
- 记录审核操作日志
3.2.3 支付单据详情
- 查看支付单据的详细信息
- 查看支付的相关凭证
- 查看支付的处理状态
3.3 账单管理
3.3.1 账单列表
- 查看所有支付账单
- 支持按时间、类型、金额等条件筛选
- 支持分页和排序
3.3.2 账单详情
- 查看账单的详细信息
- 查看账单的支付记录
- 查看账单的相关操作日志
3.3.3 账单统计
- 按时间周期统计支付金额
- 按支付渠道统计交易次数和金额
- 生成账单统计报表
3.4 退款管理
3.4.1 退款列表
- 查看所有退款申请
- 支持按时间、金额、状态等条件筛选
- 支持分页和排序
3.4.2 退款详情
- 查看退款的详细信息
- 查看退款的处理状态
- 查看退款的相关凭证
3.4.3 退款操作
- 处理退款申请
- 执行退款转账
- 记录退款操作日志
3.5 支付操作
3.5.1 发起支付
- 生成支付订单
- 调用支付渠道的接口
- 返回支付参数
实现代码:
php
// PayService.php 中的 pay 方法
public function pay(string $type, string $trade_type, int $trade_id, string $return_url = '', string $quit_url = '', string $buyer_id = '', string $voucher = '', string $openid = '')
{
return ( new CorePayService() )->pay($trade_type, $trade_id, $type, ChannelDict::PC, $openid, $return_url, $quit_url, $buyer_id, $voucher);
}3.5.2 支付信息查询
- 查询支付订单的状态
- 获取支付的详细信息
- 处理支付结果回调
实现代码:
php
// PayService.php 中的 getInfoByTrade 方法
public function getInfoByTrade(string $trade_type, int $trade_id)
{
return ( new CorePayService() )->getInfoByTrade($trade_type, $trade_id, ChannelDict::H5);
}3.5.3 支付方式列表
- 获取可用的支付方式
- 显示支付方式的配置状态
- 支持按场景筛选支付方式
实现代码:
php
// PayService.php 中的 getPayTypeList 方法
public function getPayTypeList()
{
$pay_type_list = ( new CorePayService() )->getPayTypeByTrade('', ChannelDict::H5);
if (!empty($pay_type_list)) {
foreach ($pay_type_list as $k => $v) {
if (!in_array($v['key'], [ PayDict::BALANCEPAY ])) {
unset($pay_type_list[ $k ]);
}
}
$pay_type_list = array_values($pay_type_list);
}
return $pay_type_list;
}3.6 转账管理
3.6.1 转账场景管理
- 获取支持的转账场景
- 配置转账场景的参数
- 测试转账场景的可用性
3.6.2 业务场景配置
- 设置不同业务场景的转账规则
- 配置转账的默认参数
- 管理转账的限额和频率
4. 数据模型
4.1 支付渠道模型
- 表名:
pay_channel - 主要字段:
id:渠道IDchannel:渠道名称(如wechat、alipay等)type:渠道类型(如app、h5、pc等)config:配置参数(JSON格式)status:状态(0:禁用,1:启用)create_time:创建时间update_time:更新时间
4.2 支付订单模型
- 表名:
pay - 主要字段:
id:订单IDout_trade_no:商户订单号trade_no:支付渠道订单号trade_type:交易类型total_amount:支付金额status:支付状态pay_time:支付时间create_time:创建时间update_time:更新时间
4.3 账单模型
- 表名:
account_log - 主要字段:
id:账单IDuid:用户IDusername:用户名type:账单类型amount:金额desc:描述create_time:创建时间
4.4 退款模型
- 表名:
refund - 主要字段:
id:退款IDrefund_no:退款单号out_trade_no:原订单号refund_amount:退款金额status:退款状态refund_time:退款时间create_time:创建时间update_time:更新时间
5. 开发规范
5.1 代码结构
- 控制器:位于
backend/app/adminapi/controller/pay/目录 - 模型:位于
backend/app/model/pay/目录 - 验证器:位于
backend/app/validate/pay/目录 - 字典:位于
backend/app/dict/pay/目录 - 核心支付:位于
backend/core/pay/目录
5.2 安全规范
- 支付参数加密传输
- 支付签名验证
- 防止支付订单篡改
- 敏感信息脱敏处理
5.3 错误处理
- 支付异常捕获和处理
- 退款失败的重试机制
- 支付状态的一致性检查
5.4 日志记录
- 支付操作的详细日志
- 退款操作的详细日志
- 渠道调用的详细日志
6. 注意事项
- 支付安全:支付相关操作涉及资金安全,需要严格的安全措施
- 渠道配置:不同支付渠道的配置参数不同,需要仔细配置
- 回调处理:支付回调需要处理好网络延迟和重复回调的情况
- 退款处理:退款操作需要谨慎,确保资金安全
- 账单对账:定期与支付渠道进行账单对账,确保资金准确
7. 开发流程
- 需求分析:明确支付管理的具体需求
- 渠道对接:选择需要对接的支付渠道
- 配置开发:开发支付渠道的配置功能
- 支付流程:实现支付的完整流程
- 退款流程:实现退款的完整流程
- 测试验证:测试各种支付场景
- 部署上线:将支付功能部署到生产环境
8. 常见问题
8.1 支付失败
- 检查支付渠道配置是否正确
- 检查支付金额是否符合渠道要求
- 检查网络连接是否正常
8.2 退款失败
- 检查退款金额是否超过原支付金额
- 检查支付渠道是否支持退款
- 检查退款的时间限制
8.3 回调处理
- 确保回调地址可访问
- 处理重复回调的情况
- 验证回调签名的正确性
8.4 账单对账
- 定期与支付渠道进行对账
- 处理账单差异
- 确保资金的准确性
