支付系统集成 Demo
创建于 2025 年 6 月 13 日
项目介绍
这是一个基于芋道 RuoYi-Vue-Pro v2.6.0(jdk8-11)的支付集成学习 demo,目标是演示”业务系统如何接入支付能力”:业务侧只需要维护自己的业务订单,调用 PayOrderApi.createOrder 创建支付单,跳转收银台完成支付,再通过回调接口把支付结果同步回业务订单即可。项目根目录包含四部分内容:后端 ruoyi-vue-pro-v2.6.0(jdk8-11)(yudao-server 单体应用 + yudao-module-pay 支付模块)、管理后台前端 yudao-ui-admin-vue3-v2.6.0(Vue 3 + Element Plus)、商城端 yudao-mall-uniapp-v2.6.0(uni-app),以及数据库脚本 0613ruoyi-vue-pro.sql(全量库导出)和微信支付商户证书目录 1718954179_20250614_cert(apiclient_cert.p12、apiclient_cert.pem、apiclient_key.pem)。
从 SQL 中的数据可以看到项目的学习与实测过程:6 月 14 日配置了微信支付商户(mchId 1718954179,v2 版 API 证书,渠道配置中直接内嵌了 base64 的证书 keyContent),同时配置了 cpolar 内网穿透地址作为回调入口(https://135b131b.r40.cpolar.top/admin-api/pay/demo-order/update-paid);pay_demo_order 第 183 号订单”华为手机”(1 分)于 16:55:01 通过 wx_native 渠道支付成功,16:56:09 全额退款成功,pay_notify_log 中保留了 13:41 的 502 报错、14:45 的”账号未登录”(401)等调试痕迹,最终以 {"code":0,"data":true} 成功收尾——整条链路是真实走通过的。
项目架构
项目沿用芋道框架前后端分离结构,支付能力集中在 yudao-module-pay 模块,与业务模块通过 api 包下的 API 接口(PayOrderApi、PayRefundApi、PayTransferApi)解耦:
| 模块 | 技术栈 | 说明 |
|---|---|---|
yudao-module-pay | Spring Boot 2.7.18、MyBatis-Plus、Redis、Quartz、weixin-java-pay 4.7.5.B、支付宝 SDK | 支付核心模块:controller/admin 应用、渠道、订单、退款、转账、通知、钱包与 demo 示例;framework/pay/core/client 定义 PayClient 抽象与微信、支付宝、钱包、mock 实现;job 下是通知、订单同步、退款同步、转账同步四个定时任务 |
yudao-server | Spring Boot、Spring MVC | 单体启动入口,端口 48080,/admin-api 管理端、/app-api 用户端 |
yudao-ui-admin-vue3-v2.6.0 | Vue 3、Element Plus、Vite、Pinia | 管理后台,src/views/pay 下按 app / cashier / demo / notify / order / refund / transfer / wallet 组织页面 |
yudao-mall-uniapp-v2.6.0 | uni-app | 商城移动端,pages/pay 含支付、充值、充值记录、支付结果页 |
0613ruoyi-vue-pro.sql | MySQL | 全库脚本,支付相关表:pay_app、pay_channel、pay_order、pay_order_extension、pay_refund、pay_transfer、pay_notify_task、pay_notify_log、pay_demo_order、pay_demo_withdraw、pay_wallet 系列 |
支付数据模型设计清晰:pay_app 是接入支付的业务应用(SQL 中有 4 条:商城应用 mall、示例应用 demo、会员钱包 walletId、培训 px),每个应用配置独立的订单/退款/转账回调地址;pay_channel 是应用下的渠道(示例应用配置了 wx_native 微信 Native 与 mock 模拟支付两条),渠道配置以 JSON 存在 config 字段,反序列化为 WxPayClientConfig、NonePayClientConfig 等;pay_order 是支付单,pay_order_extension 是每次支付尝试的拓展单(一个支付单可多次尝试不同渠道),pay_refund、pay_transfer 对应退款与转账单;pay_notify_task / pay_notify_log 记录回调任务与每次通知日志(当前日志自增到 37 万+ 条)。
核心功能
示例订单支付。 PayDemoOrderServiceImpl 内置 5 档商品(spuNames:华为手机 1 分、小米电视 10 分、苹果手表 100 分、华硕笔记本 1000 分、蔚来汽车 200000 分),createDemoOrder 先插入业务订单,再通过 payOrderApi.createOrder 创建支付单:指定支付应用 appKey = "demo"、以业务订单 id 作为 merchantOrderId、subject/body 为商品信息、价格以”分”为单位,并设置 2 小时过期时间,最后把生成的支付单号写回 demo 订单。管理端”示例订单”页面(/pay/demo/order)列出订单,点击”前往支付”跳转收银台。
统一收银台。 收银台页面(src/views/pay/cashier/index.vue)以”选择支付宝支付 / 选择微信支付 / 选择其它支付”三组卡片展示当前支付单可用的渠道,点击后调用 POST /pay/order/submit 提交支付:后端校验支付单与渠道有效性后插入 pay_order_extension 拓展单(订单号 no 由 Redis 生成),再调用对应 PayClient 的三方接口——微信 Native 返回二维码链接由前端 Qrcode 组件弹窗展示,mock 渠道 MockPayClient 直接返回 MOCK_SUCCESS 模拟支付成功,支付完成后带 returnUrl 跳回业务页面刷新状态。
渠道回调与通知。 回调链路分两层:支付渠道(微信/支付宝)先回调 yudao-module-pay 的 PayNotifyController(地址由 PayProperties.orderNotifyUrl 配置),解析结果后写入 pay_notify_task 通知任务表;PayNotifyJob(Quartz 定时任务,通过 Redis 锁防并发)扫描待通知任务,回调业务应用在 pay_app 中配置的 order_notify_url / refund_notify_url / transfer_notify_url。示例应用的回调地址是 /admin-api/pay/demo-order/update-paid 与 /update-refunded:updateDemoOrderPaid 校验订单存在且未支付、校验支付单状态成功、金额一致,并对 merchantOrderId 做二次匹配,重复回调(支付单号相同)直接幂等返回,最后用 updateByIdAndPayed(id, false, ...) 的乐观更新把订单置为已支付并记录渠道与支付时间。
退款与示例提现(转账)。 已支付订单点击”发起退款”,refundDemoOrder 校验未退款后调用 payRefundApi.createRefund 创建退款单(demo 没有售后维权表,直接以 订单id + "-refund" 作为 merchantRefundId),退款回调 update-refunded 校验退款单匹配、状态成功、金额一致后回填 refund_time。示例提现(PayDemoWithdrawController,/pay/demo-withdraw)演示转账能力:创建提现单选择支付宝(alipay_pc)、微信(wx_lite)或钱包(wallet)渠道,发起转账时微信渠道需通过 buildWeiXinChannelExtra1000("测试活动", "测试奖励") 附带转账用途,提现单状态机为 WAITING → SUCCESS / CLOSED,转账失败的单子可重置为 WAITING 后重新发起,回调侧同样校验转账单、金额、merchantTransferId 与渠道一致后才更新状态。
功能截图
暂无运行截图。
快速上手
-
初始化数据库:执行根目录
0613ruoyi-vue-pro.sql(全量库脚本,含框架表、支付模块表与演示数据;仓库sql/mysql下也有标准安装脚本),修改yudao-server/src/main/resources/application-local.yaml中的 MySQL、Redis 连接配置。 -
启动后端与前端:
cd "ruoyi-vue-pro-v2.6.0(jdk8-11)"
mvn -pl yudao-server -am package -DskipTests
java -jar yudao-server/target/yudao-server.jar # 端口 48080
cd yudao-ui-admin-vue3-v2.6.0
npm install
npm run dev # http://localhost:8080,默认账号 admin / admin123
- 体验支付流程:进入”支付管理 → 应用信息”维护应用与回调地址、“渠道信息”按应用添加渠道(可先添加
mock模拟支付渠道)→ 打开”支付管理 → 示例订单”点击”发起订单”选择商品 → “前往支付”进入收银台选择渠道(微信 Native 扫码、mock 直接成功)→ 等待PayNotifyJob回调后订单变为已支付 → 点击”发起退款”观察退款回调闭环;“示例提现单”可体验支付宝 / 微信 / 钱包三种渠道的转账流程。
总结
这个 demo 把芋道支付模块的接入方式讲得很完整:业务侧”创建业务订单 → 创建支付单 → 收银台提交渠道 → 等待回调”的四步接入模型、pay_app / pay_channel / pay_order / pay_order_extension / pay_refund / pay_transfer / pay_notify_task 一整套支付数据模型、PayClient 渠道抽象与微信 / 支付宝 / 钱包 / mock 四类实现,以及回调通知中”渠道 → 支付模块 → 业务应用”的两段式通知与幂等、金额、单号三重校验,都是生产级支付系统的通用设计。尤其难得的是,SQL 与证书目录证明作者用真实微信商户完成了 Native 扫码支付 1 分钱并全额退款的完整实测,回调和日志中 502、401 的调试痕迹也展示了真实接入踩坑的过程。对想学习”如何在自己的系统里优雅接入微信 / 支付宝支付”的 Java 开发者来说,这是一份可以直接对照代码阅读的实战教材。