Files
2026-02-22 12:12:02 +08:00
..
2026-02-22 12:12:02 +08:00
2026-02-22 12:12:02 +08:00
2026-02-22 12:12:02 +08:00

支付中心 (RuoYi-Pay)

模块简介

ruoyi-pay 是 PoJie 项目的聚合支付中台模块,提供多支付渠道的统一接入、订单管理、退款管理、回调通知等功能。

定位

ruoyi-pay 是一个独立于业务系统的聚合支付中台。它向下屏蔽微信、支付宝、银联等渠道的协议差异,向上为电商、会员、充值等业务提供统一的支付、退款、查单接口。

核心能力

  • 多商户/多应用: 支持多个业务线(如商城App、门店小程序)配置独立的支付参数
  • 多渠道支持: 微信支付 (Native/JSAPI/App/H5/小程序)、支付宝 (PC/Wap/App/QR)
  • 统一下单: 一套接口适配所有渠道,支持收银台模式
  • 可靠回调: 包含验签、防重、重试机制,确保业务方能收到通知
  • 防掉单机制: 自动轮询"支付中"订单,主动同步三方状态
  • 退款管理: 支持退款申请、退款查询、退款回调处理
  • 钱包系统: 支持用户余额充值、提现、消费(待实现)

功能特性

1. 支付应用管理

  • 支付应用CRUD操作
  • 应用状态管理(开启/关闭)
  • 回调地址配置(支付回调和退款回调)

2. 支付渠道管理

  • 支付渠道CRUD操作
  • 渠道配置管理(JSON格式,支持动态配置)
  • 渠道状态管理
  • 渠道费率配置
  • 支持支付宝、微信支付等多种渠道

3. 支付订单管理

  • 支付订单创建
  • 订单状态查询
  • 订单同步(防掉单)
  • 订单过期处理
  • 订单关闭
  • 商户订单号唯一性校验

4. 退款管理

  • 退款申请
  • 退款状态查询
  • 退款回调处理
  • 部分退款支持
  • 退款金额校验

5. 回调通知

  • 支付回调处理
  • 退款回调处理
  • 异步通知重试机制
  • 指数退避重试策略(15s → 30s → 1m → 2m → 5m
  • 回调验签和幂等性处理

6. 定时任务

  • 支付订单过期处理(每分钟)
  • 支付订单状态同步(每2分钟,防掉单)
  • 支付回调通知重试(每30秒)

支持的支付渠道

支付宝

渠道编码 名称 说明 状态
alipay_pc 支付宝 PC 支付 电脑网站支付
alipay_wap 支付宝 Wap 支付 手机网站支付
alipay_app 支付宝 App 支付 手机 App 支付
alipay_qr 支付宝扫码支付 当面付

微信支付

渠道编码 名称 说明 状态
wx_pub 微信 JSAPI 支付 公众号、小程序支付
wx_lite 微信小程序支付 独立小程序支付
wx_app 微信 App 支付 手机 App 支付
wx_native 微信 Native 支付 扫码支付
wx_h5 微信 H5 支付 手机浏览器支付

其他渠道

渠道编码 名称 说明 状态
mock 模拟支付 开发测试用 待实现
wallet 钱包支付 余额支付 待实现

核心架构设计

实体关系图 (ERD)

┌──────────┐
│  PayApp  │ (支付应用)
└────┬─────┘
     │ 1
     │
     │ N
┌────▼──────────┐
│ PayChannel    │ (支付渠道)
└────┬──────────┘
     │
     │ N
┌────▼──────────┐
│  PayOrder     │ (支付订单)
└────┬──────────┘
     │ 1
     │
     │ N
┌────▼──────────┐        ┌──────────────┐
│  PayRefund    │        │ PayNotifyTask│ (回调任务)
└───────────────┘        └──────────────┘

核心流程

  1. 商户入驻: 在管理后台创建 应用(App),并在该应用下配置 渠道(Channel) 参数(如微信AppID、支付宝公钥)
  2. 业务下单: 业务方调用 pay/order/submit,传入 appIdchannelCode
  3. 支付路由: 支付中心根据 appId + channelCode 读取动态配置,实例化对应的支付客户端策略

设计模式

策略模式 (Strategy Pattern)

使用策略模式实现不同支付渠道的统一接口:

  • PayStrategy - 支付策略接口,定义统一的操作方法
  • AlipayStrategy - 支付宝策略实现
  • WechatPayStrategy - 微信支付策略实现
  • PayStrategyFactory - 策略工厂,负责策略的注册和获取

事件驱动 (Event-Driven)

  • PaySuccessEvent - 支付成功事件
  • PayOrderListener - 监听支付成功事件,创建回调任务

数据库设计

1. 支付应用表 (pay_app)

用于隔离不同业务线的支付配置。

字段名 类型 说明
id BIGINT 应用ID(主键)
name VARCHAR(64) 应用名
status TINYINT 状态(0开启 1关闭)
remark VARCHAR(255) 备注
pay_notify_url VARCHAR(1024) 支付结果回调地址
refund_notify_url VARCHAR(1024) 退款结果回调地址
create_by VARCHAR(64) 创建者
create_time DATETIME 创建时间
update_by VARCHAR(64) 更新者
update_time DATETIME 更新时间

索引: PRIMARY KEY (id)

2. 支付渠道表 (pay_channel)

存储具体的支付参数(JSON格式),实现无需重启即可修改密钥。

字段名 类型 说明
id BIGINT 渠道ID(主键)
code VARCHAR(32) 渠道编码(alipay_pc, wx_pub)
status TINYINT 状态(0开启 1关闭)
remark VARCHAR(255) 备注
fee_rate DOUBLE 渠道费率(%)
app_id BIGINT 应用ID
config TEXT 支付渠道配置(JSON)
create_by VARCHAR(64) 创建者
create_time DATETIME 创建时间
update_by VARCHAR(64) 更新者
update_time DATETIME 更新时间

索引: PRIMARY KEY (id)

3. 支付订单表 (pay_order)

字段名 类型 说明
id BIGINT 订单ID(主键)
app_id BIGINT 应用ID
channel_id BIGINT 渠道ID
channel_code VARCHAR(32) 渠道编码
merchant_order_id VARCHAR(64) 商户订单编号
subject VARCHAR(32) 商品标题
body VARCHAR(128) 商品描述
notify_url VARCHAR(1024) 异步通知地址
price INT 支付金额(分)
channel_fee_rate DOUBLE 渠道费率
channel_fee_price INT 渠道手续费(分)
status TINYINT 状态(0未支付 10已支付 20已退款 30已关闭)
user_ip VARCHAR(50) 用户IP
expire_time DATETIME 订单失效时间
success_time DATETIME 支付成功时间
extension_id BIGINT 拓展业务ID
no VARCHAR(32) 支付单号(内部生成)
channel_order_no VARCHAR(64) 渠道订单号(微信/支付宝)
channel_user_id VARCHAR(64) 渠道用户OpenId
channel_extras VARCHAR(1024) 渠道额外参数(JSON)
create_by VARCHAR(64) 创建者
create_time DATETIME 创建时间
update_by VARCHAR(64) 更新者
update_time DATETIME 更新时间

索引:

  • PRIMARY KEY (id)
  • KEY idx_merchant_order_id (merchant_order_id)

4. 退款订单表 (pay_refund)

字段名 类型 说明
id BIGINT 退款ID(主键)
no VARCHAR(32) 退款单号
app_id BIGINT 应用ID
channel_id BIGINT 渠道ID
channel_code VARCHAR(32) 渠道编码
order_id BIGINT 支付订单ID
order_no VARCHAR(32) 支付订单no
merchant_order_id VARCHAR(64) 商户订单编号
merchant_refund_id VARCHAR(64) 商户退款编号
notify_url VARCHAR(1024) 回调地址
status TINYINT 状态(0等待 10成功 20失败)
pay_price INT 支付金额(分)
refund_price INT 退款金额(分)
reason VARCHAR(256) 退款原因
user_ip VARCHAR(50) 用户IP
channel_order_no VARCHAR(64) 渠道订单号
channel_refund_no VARCHAR(64) 渠道退款单号
success_time DATETIME 退款成功时间
error_code VARCHAR(32) 渠道错误码
error_msg VARCHAR(128) 渠道错误描述
create_by VARCHAR(64) 创建者
create_time DATETIME 创建时间
update_by VARCHAR(64) 更新者
update_time DATETIME 更新时间

索引: PRIMARY KEY (id)

5. 支付通知任务表 (pay_notify_task)

用于记录支付/退款回调通知任务,支持重试机制。

字段名 类型 说明
id BIGINT 任务ID(主键)
order_id BIGINT 订单ID
order_no VARCHAR(32) 订单号
notify_url VARCHAR(1024) 通知地址
notify_body TEXT 通知内容(JSON)
retry_count INT 重试次数(默认0
max_retry INT 最大重试次数(默认5
status TINYINT 状态(0进行中 1成功 2失败)
next_notify_time DATETIME 下次通知时间
create_by VARCHAR(64) 创建者
create_time DATETIME 创建时间
update_by VARCHAR(64) 更新者
update_time DATETIME 更新时间

索引:

  • PRIMARY KEY (id)
  • KEY idx_next_notify_time (next_notify_time)

6. 支付通知日志表 (pay_notify_log)

用于记录回调通知的请求和响应日志(可选)。

字段名 类型 说明
id BIGINT 日志ID(主键)
app_id BIGINT 应用ID
channel_id BIGINT 渠道ID
order_id BIGINT 支付订单ID
notify_type VARCHAR(32) 通知类型(pay, refund)
status TINYINT 处理状态(0处理中 10成功 20失败)
request_params TEXT 请求参数
response_body TEXT 响应结果
create_time DATETIME 创建时间

索引:

  • PRIMARY KEY (id)
  • KEY idx_order_id (order_id)

数据库脚本位置: script/sql/ry_pay.sql

关键枚举定义

渠道编码 (PayChannelEnum)

支持的支付渠道 章节。

订单状态 (PayOrderStatusEnum)

状态码 描述
0 WAITING (未支付)
10 SUCCESS (支付成功)
20 REFUND (已退款)
30 CLOSED (已关闭)

退款状态 (RefundStatusEnum)

状态码 描述
0 WAITING (等待处理)
10 SUCCESS (退款成功)
20 FAIL (退款失败)

模块结构

org.dromara.pay/
├── config/              # 配置类
│   └── PayProperties.java
├── controller/          # 控制器
│   ├── admin/          # 管理端
│   │   ├── PayAppController.java
│   │   ├── PayChannelController.java
│   │   ├── PayOrderController.java
│   │   └── PayRefundController.java
│   ├── app/            # 移动端
│   │   ├── AppPayOrderController.java
│   │   └── AppPayRefundController.java
│   └── PayNotifyController.java  # 回调接口
├── core/               # 核心策略
│   ├── PayStrategy.java
│   ├── PayStrategyFactory.java
│   └── impl/
│       ├── AlipayStrategy.java
│       ├── WechatPayStrategy.java
│       └── WechatPayUtil.java
├── domain/             # 领域模型
│   ├── PayApp.java
│   ├── PayChannel.java
│   ├── PayOrder.java
│   ├── PayRefund.java
│   ├── PayNotifyTask.java
│   ├── bo/            # 业务对象
│   └── vo/            # 视图对象
├── enums/              # 枚举
│   ├── PayChannelEnum.java
│   ├── PayOrderStatusEnum.java
│   └── RefundStatusEnum.java
├── event/              # 事件
│   └── PaySuccessEvent.java
├── job/                # 定时任务
│   ├── PayNotifyJob.java
│   ├── PayOrderExpireJob.java
│   └── PayOrderSyncJob.java
├── listener/           # 监听器
│   └── PayOrderListener.java
├── mapper/             # 数据访问
│   ├── PayAppMapper.java
│   ├── PayChannelMapper.java
│   ├── PayOrderMapper.java
│   ├── PayRefundMapper.java
│   └── PayNotifyTaskMapper.java
├── service/            # 服务层
│   ├── PayAppService.java
│   ├── PayChannelService.java
│   ├── PayOrderService.java
│   ├── PayRefundService.java
│   ├── PayNotifyService.java
│   └── impl/
└── util/               # 工具类
    └── WechatPayUtil.java

核心业务流程

1. 统一下单流程

业务方 → 支付中心 → 策略工厂 → 三方渠道
   ↓         ↓          ↓         ↓
提交订单   创建订单   获取策略   调用下单
   ↑         ↑          ↑         ↑
返回参数   返回参数   返回参数   返回参数

详细流程:

  1. 业务方调用 /app/pay/order/submit 提交支付订单
  2. 支付中心校验 App 状态和参数
  3. 创建 pay_order 记录(状态为 WAITING
  4. 通过策略工厂获取对应的支付策略(Alipay/Wechat
  5. 读取 pay_channel 配置,实例化支付客户端
  6. 调用三方渠道的下单接口
  7. 封装标准响应 PayOrderSubmitRespVO 返回给业务方
  8. 业务方使用返回的支付参数调起支付

2. 支付回调流程

三方渠道 → 支付中心 → 业务方
    ↓         ↓         ↓
异步回调   验签更新   接收通知
    ↑         ↑         ↑
返回成功   创建任务   返回success

详细流程:

  1. 支付成功后,三方渠道异步回调 /pay/notify/{channelCode}/{channelId}
  2. 支付中心解析参数并进行验签
  3. 加分布式锁(lock:order:{id})确保幂等性
  4. 幂等校验(若已支付则忽略)
  5. 更新 pay_order 状态为 SUCCESS
  6. 发布支付成功事件(PaySuccessEvent
  7. 监听器创建 pay_notify_task 回调任务
  8. 立即执行一次 HTTP 回调通知业务方
  9. 业务方返回 "success"{"code": 200}
  10. 如果失败,定时任务按指数退避策略重试

3. 退款流程

业务方 → 支付中心 → 三方渠道
   ↓         ↓         ↓
申请退款   创建退款   调用退款
   ↑         ↑         ↑
回调通知   更新状态   返回结果

详细流程:

  1. 业务方调用 /app/pay/refund/apply 申请退款
  2. 支付中心校验订单(是否已支付、金额是否足够)
  3. 创建 pay_refund 记录(状态为 WAITING
  4. 调用三方渠道的退款接口
  5. 如果三方同步返回退款成功:
    • 更新 pay_refund 状态为 SUCCESS
    • 更新 pay_order 状态(REFUND/部分退款)
    • 发送退款回调通知
  6. 如果三方异步处理中:
    • 保持 WAITING 状态等待回调
    • 接收三方异步退款回调
    • 更新 pay_refundpay_order 状态
    • 发送退款回调通知

4. 防掉单轮询流程

定时任务 → 支付中心 → 三方渠道 → 业务方
    ↓         ↓         ↓         ↓
扫描订单   查询状态   返回状态   补发通知
    ↓         ↓
更新状态   触发逻辑

详细流程:

  1. 定时任务(每2分钟)扫描状态为 WAITING、创建时间超过2分钟、未过期的订单
  2. 调用三方渠道的查单接口
  3. 如果已支付(掉单补救):
    • 更新 pay_order 状态为 SUCCESS
    • 触发支付成功逻辑
    • 补发支付成功通知给业务方
  4. 如果支付关闭/超时:
    • 更新 pay_order 状态为 CLOSED
    • (可选)调用三方关单接口
  5. 如果等待支付:
    • 不做处理,继续等待

API 接口文档

管理端接口

支付应用管理 (/pay/app)

方法 路径 说明 权限
GET /pay/app/list 查询支付应用列表 pay:app:list
GET /pay/app/{id} 查询支付应用详情 pay:app:query
POST /pay/app 新增支付应用 pay:app:add
PUT /pay/app 修改支付应用 pay:app:edit
DELETE /pay/app/{ids} 删除支付应用 pay:app:remove
POST /pay/app/export 导出支付应用列表 pay:app:export

支付渠道管理 (/pay/channel)

方法 路径 说明 权限
GET /pay/channel/list 查询支付渠道列表 pay:channel:list
GET /pay/channel/{id} 查询支付渠道详情 pay:channel:query
POST /pay/channel 新增支付渠道 pay:channel:add
PUT /pay/channel 修改支付渠道 pay:channel:edit
DELETE /pay/channel/{ids} 删除支付渠道 pay:channel:remove
POST /pay/channel/export 导出支付渠道列表 pay:channel:export

支付订单管理 (/pay/order)

方法 路径 说明 权限
GET /pay/order/list 查询支付订单列表 pay:order:list
GET /pay/order/{id} 查询支付订单详情 pay:order:query
POST /pay/order 新增支付订单 pay:order:add
POST /pay/order/submit 提交支付订单 pay:order:submit
PUT /pay/order 修改支付订单 pay:order:edit
DELETE /pay/order/{ids} 删除支付订单 pay:order:remove
POST /pay/order/export 导出支付订单列表 pay:order:export

退款订单管理 (/pay/refund)

方法 路径 说明 权限
GET /pay/refund/list 查询退款订单列表 pay:refund:list
GET /pay/refund/{id} 查询退款订单详情 pay:refund:query
POST /pay/refund 新增退款订单 pay:refund:add
POST /pay/refund/apply 申请退款 pay:refund:apply
PUT /pay/refund 修改退款订单 pay:refund:edit
DELETE /pay/refund/{ids} 删除退款订单 pay:refund:remove
POST /pay/refund/export 导出退款订单列表 pay:refund:export

移动端接口

支付订单 (/app/pay/order)

方法 路径 说明
POST /app/pay/order/submit 提交支付订单
GET /app/pay/order/list 查询支付订单列表
GET /app/pay/order/{id} 查询支付订单详情
GET /app/pay/order/query 根据商户订单号查询

提交支付订单请求示例:

{
  "appId": 1,
  "channelCode": "wx_pub",
  "channelId": 1,
  "merchantOrderId": "ORDER20240101001",
  "subject": "商品订单",
  "body": "商品订单-ORDER20240101001",
  "price": 10000,
  "notifyUrl": "https://your-domain.com/app/mall/pay/notify",
  "userIp": "127.0.0.1",
  "channelUserId": "openid_xxx"
}

响应示例:

{
  "code": 200,
  "msg": "操作成功",
  "data": {
    "payOrderNo": "PAY20240101001",
    "payData": "{\"appId\":\"wx123\",\"timeStamp\":\"1234567890\",\"nonceStr\":\"abc\",\"package\":\"prepay_id=xxx\",\"signType\":\"RSA\",\"paySign\":\"xxx\"}",
    "status": 0
  }
}

退款 (/app/pay/refund)

方法 路径 说明
POST /app/pay/refund/apply 申请退款
GET /app/pay/refund/list 查询退款订单列表
GET /app/pay/refund/{id} 查询退款订单详情
GET /app/pay/refund/query 根据商户退款编号查询

申请退款请求示例:

{
  "orderNo": "PAY20240101001",
  "merchantRefundId": "REFUND20240101001",
  "refundPrice": 10000,
  "reason": "用户申请退款",
  "notifyUrl": "https://your-domain.com/app/mall/refund/notify",
  "userIp": "127.0.0.1"
}

回调接口

支付回调 (/pay/notify)

方法 路径 说明
POST /pay/notify/{channelCode}/{channelId} 接收支付回调

回调通知内容:

{
  "orderNo": "PAY20240101001",
  "merchantOrderId": "ORDER20240101001",
  "status": 10,
  "price": 10000,
  "channelUserId": "openid_xxx",
  "successTime": "2024-01-01 12:00:00",
  "channelOrderNo": "wx20240101001"
}

业务方响应: 返回 "success"{"code": 200} 表示成功

退款回调 (/pay/notify/refund)

方法 路径 说明
POST /pay/notify/refund/{channelCode}/{channelId} 接收退款回调

配置说明

支付应用配置

{
  "name": "电商应用",
  "status": 0,
  "remark": "电商业务支付应用",
  "payNotifyUrl": "https://your-domain.com/pay/notify",
  "refundNotifyUrl": "https://your-domain.com/pay/notify/refund"
}

支付宝渠道配置

{
  "serverUrl": "https://openapi.alipay.com/gateway.do",
  "appId": "your_app_id",
  "privateKey": "your_private_key",
  "publicKey": "your_public_key",
  "signType": "RSA2"
}

说明:

  • serverUrl: 支付宝网关地址(生产环境/沙箱环境)
  • appId: 支付宝应用ID
  • privateKey: 应用私钥(RSA2格式)
  • publicKey: 支付宝公钥
  • signType: 签名类型,固定为 RSA2

微信支付渠道配置

{
  "appId": "your_app_id",
  "mchId": "your_mch_id",
  "privateKey": "your_private_key",
  "mchSerialNo": "your_serial_no",
  "apiV3Key": "your_api_v3_key"
}

说明:

  • appId: 微信应用ID(公众号/小程序/App)
  • mchId: 商户号
  • privateKey: 商户私钥(PEM格式)
  • mchSerialNo: 商户证书序列号
  • apiV3Key: APIv3密钥

定时任务

支付订单过期处理 (PayOrderExpireJob)

  • 执行频率: 每分钟 (0 0/1 * * * ?)
  • 功能:
    • 扫描状态为 WAITING 且已过期的订单
    • 调用支付渠道的关单接口
    • 更新订单状态为 CLOSED
  • 限制: 每次处理最多100条,防止积压

支付订单状态同步 (PayOrderSyncJob)

  • 执行频率: 每2分钟 (0 0/2 * * * ?)
  • 功能:
    • 扫描状态为 WAITING、创建时间超过2分钟、未过期的订单
    • 调用支付渠道的查单接口
    • 如果已支付,更新订单状态并触发支付成功逻辑
    • 如果已关闭,更新订单状态
  • 目的: 防止掉单,主动同步三方状态

支付回调通知重试 (PayNotifyJob)

  • 执行频率: 每30秒 (0/30 * * * * ?)
  • 功能:
    • 扫描状态为 进行中 且到达通知时间的任务
    • 执行HTTP回调通知
    • 根据响应判断成功或失败
    • 失败时按指数退避策略计算下次通知时间
  • 重试策略: 15s → 30s → 1m → 2m → 5m
  • 最大重试次数: 5次

数据校验规则

支付订单校验

  • 商户订单号唯一性校验
  • 支付单号唯一性校验
  • 删除时校验:已支付的订单不能删除

退款订单校验

  • 退款单号唯一性校验
  • 商户退款编号唯一性校验
  • 退款金额不能超过支付金额
  • 删除时校验:处理中的退款不能删除

支付应用校验

  • 应用名称不能为空
  • 回调地址格式校验(必须以 http:// 或 https:// 开头)

支付渠道校验

  • 渠道编码不能为空
  • 同一应用下渠道编码唯一性校验
  • 渠道配置JSON格式校验

接入指南

Maven 依赖

<dependency>
    <groupId>org.dromara</groupId>
    <artifactId>ruoyi-pay</artifactId>
    <version>${revision}</version>
</dependency>

快速开始

步骤1: 创建支付应用

在管理后台创建支付应用,配置回调地址。

步骤2: 配置支付渠道

在应用下配置支付渠道,填写渠道参数(JSON格式)。

步骤3: 调用统一下单接口

PayOrderBo bo = new PayOrderBo();
bo.setAppId(1L);
bo.setChannelCode("wx_pub");
bo.setMerchantOrderId("ORDER001");
bo.setSubject("商品订单");
bo.setPrice(10000);
bo.setNotifyUrl("https://your-domain.com/notify");
PayOrderSubmitRespVO resp = payOrderService.submitOrder(bo);

步骤4: 处理支付回调

实现回调接口,接收支付成功通知:

@PostMapping("/notify")
public String notify(@RequestBody Map<String, Object> data) {
    String orderNo = (String) data.get("merchantOrderId");
    // 处理业务逻辑
    return "success";
}

扩展开发

添加新的支付渠道

  1. 实现 PayStrategy 接口
  2. @PostConstruct 方法中注册到 PayStrategyFactory
  3. PayChannelEnum 中添加新的渠道枚举
  4. 配置渠道参数

示例:

@Component
@RequiredArgsConstructor
public class NewPayStrategy implements PayStrategy {
    private final PayStrategyFactory payStrategyFactory;
    
    @PostConstruct
    public void init() {
        payStrategyFactory.register("new_pay", this);
    }
    
    @Override
    public PayOrderSubmitRespVO submitOrder(PayOrderBo bo, PayChannel channel) {
        // 实现下单逻辑
    }
    
    // 实现其他接口方法...
}

错误码定义

错误信息 说明
应用不存在或已禁用 支付应用不存在或状态为关闭
支付渠道不存在或已禁用 支付渠道不存在或状态为关闭
商户订单号已存在 商户订单号重复
支付单号已存在 支付单号重复
退款单号已存在 退款单号重复
商户退款编号已存在 商户退款编号重复
退款金额不能超过支付金额 退款金额校验失败
订单不存在 支付订单不存在
订单未支付或已退款 订单状态不允许退款
不支持的支付渠道 渠道编码不在支持列表中
未找到支付策略 策略未注册

扩展功能规划

收银台模式

  • 提供统一的 H5 收银台页面
  • 业务方只需传入订单号,跳转至收银台
  • 用户在收银台选择微信/支付宝/余额支付
  • 状态: 待实现

钱包系统 (Wallet)

  • 充值: 创建充值订单 -> 调起支付 -> 回调增加余额
  • 消费: 余额扣减 -> 生成消费记录
  • 提现: 申请提现 -> 管理员审核 -> 企业付款到零钱/银行卡
  • 状态: 待实现

模拟支付 (Mock)

  • 开发环境专用
  • 下单直接返回成功,不调用真实三方接口
  • 用于前端联调和流程测试
  • 状态: 待实现

对账功能

  • 每日对账任务,对比支付中心订单与三方渠道订单
  • 生成对账报表,标记差异订单
  • 状态: 待实现

支付统计报表

  • 按日/月统计支付金额、订单数、成功率等
  • 按渠道统计支付数据
  • 状态: 待实现

注意事项

幂等性

  • 支付回调需要保证幂等处理,避免重复处理
  • 通过订单状态判断,已支付的订单直接返回成功
  • 使用分布式锁确保并发安全

安全性

  • 回调接口需要验签,确保请求来自支付渠道
  • 使用 HTTPS 传输敏感信息
  • 渠道配置中的密钥需要妥善保管
  • 不要在日志中输出敏感信息(密钥、密码等)

超时处理

  • 支付订单默认30分钟过期,可通过配置调整
  • 过期订单会自动关闭,调用渠道关单接口
  • 业务方需要及时处理订单,避免过期

重试机制

  • 回调通知采用指数退避策略,最多重试5次
  • 重试间隔:15s → 30s → 1m → 2m → 5m
  • 业务方需要快速响应回调,返回 "success"{"code": 200}
  • 回调响应时间建议控制在3秒内

防掉单

  • 定时任务主动查询订单状态,防止掉单
  • 查询创建时间超过2分钟且未过期的待支付订单
  • 如果发现已支付但未收到回调,主动触发支付成功逻辑

金额单位

  • 所有金额以"分"为单位存储和传递
  • 前端展示时需要转换为"元"
  • 计算时注意单位转换,避免精度问题

回调地址

  • 回调地址必须是公网可访问的 HTTPS 地址
  • 回调地址需要支持 POST 请求
  • 回调响应需要快速返回,避免超时
  • 建议使用内网地址 + 反向代理的方式处理回调

依赖模块

  • ruoyi-common-core - 核心工具类
  • ruoyi-common-mybatis - 数据库操作
  • ruoyi-common-web - Web框架支持
  • ruoyi-common-security - 安全认证(Sa-Token
  • ruoyi-common-log - 日志记录
  • ruoyi-common-idempotent - 幂等性控制
  • ruoyi-common-redis - Redis缓存
  • alipay-sdk-java - 支付宝SDK
  • wechatpay-java - 微信支付SDK
  • weixin-java-mp - 微信公众号SDK(用于JSAPI支付)