scaffold-pay 支付模块

模块概述

scaffold-pay 是 Scaffold v2 的统一支付模块,采用策略模式支持多支付渠道(微信支付、支付宝)。提供统一下单、支付回调、退款、对账、统计等完整的支付生命周期管理。渠道配置存储在数据库中,敏感字段通过 AES 加密,支持运行时动态切换。

功能列表

  • 统一下单:业务系统通过统一接口发起支付,自动路由到对应渠道
  • 支付回调:接收第三方支付/退款结果通知,更新订单状态,异步通知业务系统
  • 退款管理:发起退款申请,接收退款回调
  • 渠道配置:管理支付渠道参数(AppId、商户号、密钥等),敏感字段加密存储
  • 自动对账:每日定时下载渠道对账单与本地订单比对,支持手动触发
  • 订单超时:定时扫描超时未支付订单自动关闭
  • 支付统计:按时间范围统计支付/退款金额和笔数
  • 业务回调:支付成功后异步通知业务系统,支持递增重试

核心组件

分层架构

职责
Controller PayOrderController, PayConfigController, PayRefundController, PayReconcileController, PayStatisticsController, PayNotifyController REST 接口
Service PayOrderService, PayConfigService, PayRefundService, PayReconcileService, PayStatisticsService, PayBizNotifyService 业务逻辑
Repository PayOrderRepository, PayRefundOrderRepository, PayChannelConfigRepository, PayReconcileResultRepository 数据访问
Mapper PayOrderMapper, PayRefundOrderMapper, PayChannelConfigMapper, PayReconcileResultMapper ORM 映射

策略模式

组件 说明
PayChannelStrategy 支付渠道策略接口,定义 createPayOrder / handlePayNotify / queryPayOrder / closePayOrder / createRefund / handleRefundNotify / downloadBill 7 个方法
PayChannelFactory 策略工厂,根据 PayChannel 枚举自动路由到对应策略实现
WechatPayChannelStrategy 微信支付策略实现
AlipayPayChannelStrategy 支付宝策略实现

核心组件

组件 说明
PayChannelConfigManager 渠道配置管理器,启动时从数据库加载配置到内存缓存,管理修改后自动刷新
PayConfigEncryptor 配置加解密服务,使用 AES 算法加密渠道配置中的敏感字段(key/secret/private/password)
PayOrderTimeoutJob 定时任务,扫描超时未支付订单并调用第三方关闭
PayReconcileJob 定时任务,每日凌晨下载渠道对账单并执行自动对账
PayBizNotifyService 业务回调通知服务,支付成功后异步通知业务系统

数据实体

实体 说明
PayOrder pay_order 支付订单
PayChannelConfig pay_channel_config 渠道配置
PayRefundOrder pay_refund_order 退款订单
PayReconcileResult pay_reconcile_result 对账结果

订单状态流转

PENDING(待支付) -> PAYING(支付中) -> SUCCESS(已支付)
                 -> CLOSED(已关闭)
SUCCESS -> REFUNDING(退款中) -> REFUNDED(已退款)

注意PayOrderStatusPayRefundStatus 为多态状态机,不遵循布尔语义规范。

配置参数

配置前缀:scaffold.pay

参数 类型 默认值 说明
enabled boolean true 模块开关
encrypt-key String scaffold-pay-default-key AES 加密密钥,建议通过环境变量注入
default-expire-minutes Integer 120 订单默认超时时间(分钟)
callback-retry-times Integer 3 业务回调重试次数
callback-retry-intervals List [5, 30, 120] 业务回调重试间隔(秒),递增
order-timeout-cron String 0 */5 * * * ? 订单超时检查 cron 表达式
reconcile-cron String 0 0 2 * * ? 每日对账 cron 表达式

API 接口列表

PayOrderController -- 支付订单管理 (/v1/pay/order)

方法 路径 说明
POST /create 统一下单
POST /page 分页查询订单
GET /detail/{id} 订单详情
GET /query/{orderNo}?configId= 查询第三方订单状态
POST /close/{orderNo} 关闭订单

PayConfigController -- 支付渠道配置 (/v1/pay/config)

方法 路径 说明
POST /add 新增支付渠道配置
POST /update?id= 更新支付渠道配置
POST /delete/{id} 删除支付渠道配置
POST /toggle-status/{id} 切换支付渠道启用/禁用状态
GET /detail/{id} 支付渠道配置详情
POST /page 分页查询支付渠道配置

PayRefundController -- 退款管理 (/v1/pay/refund)

方法 路径 说明
POST /create 发起退款
POST /page 分页查询退款记录

PayStatisticsController -- 支付统计 (/v1/pay/statistics)

方法 路径 说明
POST / 获取支付统计数据(支持时间范围筛选)

PayReconcileController -- 支付对账 (/v1/pay/reconcile)

方法 路径 说明
POST /page 分页查询对账结果
POST /execute?date=&channel= 手动触发指定渠道对账
POST /execute-all?date= 手动触发全渠道对账

PayNotifyController -- 支付回调(匿名) (/v1/pay/notify)

方法 路径 说明
POST /pay/{channel}/{configId} 支付结果通知回调
POST /refund/{channel}/{configId} 退款结果通知回调

SPI 扩展点

新增支付渠道

实现 PayChannelStrategy 接口并注册为 Spring Bean:

  1. PayChannel 枚举中新增渠道常量
  2. 实现 PayChannelStrategy 接口的 7 个方法
  3. 添加 @Component 注解,PayChannelFactory 自动发现并注册
@Component
public class NewPayChannelStrategy implements PayChannelStrategy {
    @Override
    public PayChannel getChannel() {
        return PayChannel.NEW_CHANNEL;
    }
    // ... 实现其他方法
}

业务回调

实现 PayBizNotifyService 接口,支付成功后自动调用通知业务系统:

@Service
public class MyBizNotifyService implements PayBizNotifyService {
    @Override
    public void notifyBizSystem(PayOrder order) {
        // 通知业务系统
    }
}

使用示例

1. 配置支付渠道

POST /v1/pay/config/add
{
  "channel": "WECHAT",
  "name": "微信支付-生产",
  "status": 1,
  "channelConfig": "{\"appId\":\"wx...\", \"mchId\":\"14...\", \"apiV3Key\":\"...\"}"
}

说明status 字段遵循布尔语义规范,1 = 启用,0 = 禁用

2. 发起支付

POST /v1/pay/order/create
{
  "orderNo": "BIZ202604260001",
  "channel": "WECHAT",
  "configId": 1234567890,
  "amount": 10000,
  "subject": "商品订单支付",
  "tradeType": "JSAPI",
  "expireMinutes": 30,
  "bizNotifyUrl": "https://your-domain.com/callback/pay"
}

3. 接收回调通知

回调接口路径为 /v1/pay/notify/pay/{channel}/{configId},需配置在微信/支付宝商户后台。模块自动验签、更新订单状态、通知业务系统。

4. 发起退款

POST /v1/pay/refund/create
{
  "orderNo": "PAY202604260001",
  "refundAmount": 5000,
  "reason": "部分退款"
}

注意事项

  1. 密钥安全scaffold.pay.encrypt-key 应通过环境变量注入,不要在配置文件中使用默认值
  2. 回调路径:PayNotifyController 的回调路径需要在安全模块中配置为匿名访问路径
  3. 金额单位:所有金额字段统一使用分为单位(Long 类型),避免浮点精度问题
  4. 订单号唯一性:orderNo 需要业务系统保证全局唯一,建议包含日期+业务前缀+序号
  5. 超时关闭:订单超时后会尝试调用第三方关闭,如果第三方返回关闭失败(可能已支付),则标记为 PAYING 状态等待下次查询确认
  6. 对账时机:每日对账默认凌晨 2 点执行,对账日期为前一天;也可通过 API 手动触发
  7. 状态枚举
  • status 字段(渠道配置)遵循布尔语义:1 = 启用,0 = 禁用
  • PayOrderStatusPayRefundStatus 为多态状态机,不遵循布尔语义规范

待完善功能

  • 支付创建流程的前端二维码/收银台页面集成
  • 渠道证书管理(p12/pem 文件上传与存储)
  • 支付渠道沙箱环境集成测试(AlipaySandboxIntegrationTest 已有基础)