|
|
před 2 dny | |
|---|---|---|
| .. | ||
| business-pay-api | před 2 dny | |
| business-pay-application | před 2 dny | |
| business-pay-bean | před 2 dny | |
| business-pay-controller | před 2 dny | |
| business-pay-service | před 2 dny | |
| README.md | před 2 dny | |
| pom.xml | před 2 dny | |
| 特约商户进件-结算与注销-后台接口文档.md | před 2 dny | |
本模块已从 Beetl 服务端页面 + 内嵌 Vue 改造为 前后分离 架构:
| 层级 | 路径 | 说明 |
|---|---|---|
| 对外 API | business-pay-api |
PayCenterApi、PayOrderReadApi(供其他模块依赖) |
| 管理端 API | business-pay-controller |
REST:/admin/manager/business/pay/{实体}/v1/* |
| 应用编排 | business-pay-application |
Application Service |
| 领域服务 | business-pay-service |
Domain Service + Mapper + API 实现 |
| 数据对象 | business-pay-bean |
Entity / DTO / VO / Convert |
| 管理端页面 | TravelWebFront/src/views/business/pay/* |
ProTable + Vue3 |
| 数据库脚本 | sql/ |
建表、种子、菜单权限(见 sql/README.md) |
其他业务模块接入时,只依赖 business-pay-api + business-pay-bean,不要依赖 business-pay-service / business-pay-controller。
| 链路 | 主单表 | 适用场景 | 下单入口 | 回调入口 |
|---|---|---|---|---|
| 杏花村 C 端(推荐) | biz_finance_pay_order(business-finance) |
小程序商城/酒店/门票等 | PayCenterApi.wechatJsapiPrepay |
各业务移动端回调 + WechatPayNotifyAdapterService |
| Legacy 支付中心 | sys_pay_order |
原物业/多通道遗留 | PayCenterApi.paymentOrder |
PayNotifyController → PayCenterApi.notify |
C 端微信 禁止 对杏花村订单走
paymentOrder(会尝试写sys_pay_order);PayCenterServiceImpl与WxPayOperationStrategy已对bizScene非空订单做拦截。
<dependency>
<groupId>com.xinghuacuntravel</groupId>
<artifactId>business-pay-api</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>com.xinghuacuntravel</groupId>
<artifactId>business-pay-bean</artifactId>
<version>${project.version}</version>
</dependency>
移动端网关(business-mobile-gateway)已依赖上述 API,并在网关内编排预支付与回调。
BasicPayOrderData.payType)| 枚举 | value | 说明 |
|---|---|---|
PayTypeStyle.WX_PAY |
1 |
微信 V3(JSAPI / APP) |
PayTypeStyle.ALI_PAY |
2 |
支付宝 |
PayTypeStyle.PFA_PAY |
3 |
浦发 |
PayTypeStyle.TLINX_PAY |
4 |
TLinx |
BasicPayOrderData| 字段 | 说明 |
|---|---|
payType |
渠道编码,见上表 |
payAmount |
金额,单位:分 |
orderNumber |
商户单号 / 系统支付单号 |
subject / description |
商品标题与描述 |
notifyUrl |
渠道异步通知完整 URL |
userId |
缴费用户 ID |
attach |
微信 attach,建议 JSON(含 bizType、orderId、payOrderId) |
payerOpenId |
微信 JSAPI 付款人 openid |
wxTradeType |
JSAPI(默认)或 APP |
bizScene |
杏花村业务场景(如 MALL_ORDER);非空表示走 finance 主单 |
bizOrderId |
业务订单主键 |
financePayOrderId |
财务支付单 ID(createIntent 后回填) |
判断是否为杏花村财务链路:payOrderData.isTravelFinanceOrder() ⇔ bizScene 非空。
浦发等扩展字段使用子类 PfPayOrderData(storeNumber、pfPayType 等),见 business-pay-service 包 com.jeesharp.business.modules.pay.dto。
sequenceDiagram
participant App as 小程序/业务Controller
participant GW as WechatJsapiPayOrderPrepayService
participant Fin as PayOrderApplicationService
participant Pay as PayCenterApi
participant WX as 微信支付V3
App->>GW: execute(WechatPrepayCommand)
GW->>Fin: createIntentForJsapi(...)
Fin-->>GW: outTradeNo, payOrderId
GW->>Pay: wechatJsapiPrepay(BasicPayOrderData)
Pay->>WX: 统一下单
WX-->>Pay: prepay_id 等
Pay-->>GW: WechatJsapiPrepayVO
GW->>Fin: bindPrepayAfterJsapi(...)
GW-->>App: 调起收银台参数
推荐做法:业务模块在 Application 层准备好金额、业务单 ID、描述等,由 mobile-gateway 统一调用 WechatJsapiPayOrderPrepayService,不要在各业务里直接拼微信 SDK。
网关参考实现:business-mobile-gateway/.../WechatJsapiPayOrderPrepayService.java
// 1. 财务主单(biz_finance_pay_order)
PayOrderIntentVO intent = payOrderApplicationService.createIntentForJsapi(
bizScene, bizOrderId, amountYuan, memberId, subject, description,
notifyUrl, openid, null);
// 2. 组装 PayCenterApi 入参(须带 bizScene)
BasicPayOrderData payData = new BasicPayOrderData();
payData.setPayType(PayTypeStyle.WX_PAY.getValue());
payData.setBizScene(bizScene);
payData.setBizOrderId(bizOrderId);
payData.setFinancePayOrderId(intent.getPayOrderId());
payData.setOrderNumber(intent.getOutTradeNo());
payData.setPayAmount(amountFen);
payData.setPayerOpenId(openid);
payData.setNotifyUrl(notifyUrl);
payData.setAttach(attachJson); // 建议含 orderId、payOrderId、memberId、bizType
// 3. 仅调渠道,不写 sys_pay_order
WechatJsapiPrepayVO prepay = payCenterApi.wechatJsapiPrepay(payData);
// 4. 回写 prepay_id
payOrderApplicationService.bindPrepayAfterJsapi(intent.getPayOrderId(), prepayId);
回调 URL 拼接规则:
notifyUrl = pay_wechat_config.notifyBaseUrl(去尾斜杠) + /pay/notify/wechat(全业态统一相对路径)
完整示例:https://{domain}/mobile/pay/notify/wechat(notifyBaseUrl 须含 /mobile 前缀)。
notifyBaseUrl 在管理后台 支付 · 微信配置 维护;业态路由依赖预支付 attach 中的 bizType(WechatPayAttachSupport),由 TravelWechatPayNotifyMobileController 统一接收入口。
若已在业务侧创建好 biz_finance_pay_order,可只注入 PayCenterApi:
@Autowired
private PayCenterApi payCenterApi;
// 预支付
WechatJsapiPrepayVO vo = payCenterApi.wechatJsapiPrepay(payData);
// 读取公开配置(回调基地址等,不含密钥)
PayWechatPublicConfigVO cfg = payCenterApi.getWechatPublicConfig();
// 自行处理回调报文时验签解密
Map<String, Object> parsed = payCenterApi.wechatParsePayNotify(rawBody, headers);
适用于仍使用 sys_pay_order 的物业或多通道场景。
@Autowired
private PayCenterApi payCenterApi;
BasicPayOrderData data = new BasicPayOrderData();
data.setPayType(PayTypeStyle.ALI_PAY.getValue()); // 或 WX_PAY / PFA_PAY / TLINX_PAY
data.setPayAmount(100L); // 分
data.setSubject("商品标题");
data.setUserId("userId");
data.setNotifyUrl("https://your.domain/api/pay/payNotify/aliPayNotify");
// 浦发:使用 PfPayOrderData 并设置 storeNumber、pfPayType 等
Object channelResult = payCenterApi.paymentOrder(request, data);
内部流程(策略模式):
PayOperationStrategyFactory 按 payType 选择策略(WxPayOperationStrategy、AliPayOperationStrategy 等)。PayOrderCheckEvent → PayApiOrderServiceImpl 校验参数。PayOrderCreateEvent → 写入 sys_pay_order + sys_pay_order_info(杏花村 finance 订单会跳过创建)。payCenterApi.checkOrder(request, payOrderData); // 需 orderNumber + payType
payCenterApi.returnOrder(request, payOrderData); // 另需 refundAmount(分)
@Autowired
private PayOrderReadApi payOrderReadApi;
PayOrderSummaryDTO summary = payOrderReadApi.getByOrderNumber(orderNumber);
微信服务器 POST 至杏花村 C 端统一入口:
POST {mobilePath}/pay/notify/wechat # 全业态,mobilePath 默认 /mobile
处理链:
flowchart LR
WX[微信服务器] --> MC[TravelWechatPayNotifyMobileController]
MC --> AD[WechatPayNotifyAdapterService]
AD --> API[PayCenterApi.wechatParsePayNotify]
AD --> BA[WechatPayCallbackAdapter 按 attach.bizType]
AD --> FIN[PayOrderApi.markPaid]
AD --> REC[PayRecordApi 记流水]
步骤说明:
PayCenterApi.wechatParsePayNotify(rawBody, headers),依赖 pay_wechat_config 中的 APIv3 密钥与平台证书。orderId(业务单)、payOrderId(财务支付单)、bizType(与 MobilePayBizType 一致)。WechatPayCallbackAdapter.confirm(orderId, payOrderId, thirdPartyTradeNo)(商城/酒店/门票各自实现)。markPaidByWechatOutTradeNo + recordWechatJsapiNotifyIfAbsent(幂等以流水为准)。扩展新业务回调:
WechatPayCallbackAdapter,bizType() 返回对应 MobilePayBizType。WechatJsapiPayOrderPrepayService.execute(attach 含 bizType、orderId、payOrderId)。TravelWechatPayNotifyMobileController(POST /mobile/pay/notify/wechat)。| 渠道 | HTTP 路径 | payType |
|---|---|---|
| 支付宝 | POST /api/pay/payNotify/aliPayNotify |
2 |
| 微信 | POST /api/pay/payNotify/wxNotify |
1 |
| 浦发 | POST /api/pay/payNotify/pfNotify |
3 |
Controller:business-pay-controller/.../PayNotifyController.java
实现:PayCenterApi.notify(payType, request) → PayNotifyStrategy → 异步 PayOrderUpdateEvent → PayApiOrderServiceImpl.orderUpdate 更新 sys_pay_order。
微信 Legacy 回调要点(WxPayNotifyStrategy):
WechatPayV3NotifyResponse.success/fail),非 V2 XML。trade_state=SUCCESS 时发布 PayOrderUpdateEvent;若 attach 含 bizScene,wxOrderOperate 不会 更新 sys_pay_order(避免与 finance 双写)。支付宝(AliPayNotifyStrategy):验签 → trade_status 校验 → 异步更新 sys_pay_order。
浦发(PfPayNotifyStrategy):按浦发报文解析后同样走 PayOrderUpdateEvent。
notifyBaseUrl(HTTPS 公网域名,须含 /mobile 后缀)。notify_url 为 {notifyBaseUrl}/pay/notify/wechat;attach 含正确 bizType。notifyUrl 一致。ali.pay.notifyUrl(或后续库表配置)指向 /api/pay/payNotify/aliPayNotify。pufa-pay.properties 中 NOTIFY_URL 指向 /api/pay/payNotify/pfNotify。sys_pay_order 状态判断)。| 渠道 | 配置来源 | 管理端 |
|---|---|---|
| 微信 V3 | pay_wechat_config |
支付 · 微信配置 |
| 支付宝 | ali.pay.*(YAML,计划迁库) |
— |
| 浦发 | pufa-pay.properties |
— |
| TLinx | 代码常量 TLinx2Config 等 |
— |
| 支付商户 | pay_merchant |
支付 · 商户(浦发等,与微信配置分离) |
微信配置详见下文「微信 V3 配置」;运行时由 PayWechatWxPayClientHolder 读库装配,保存后缓存失效。
| 功能 | 表名 | API 前缀 | 前端路由 |
|---|---|---|---|
| 渠道公共配置 | pay_channel_config |
/manager/business/pay/payChannelConfig/v1(POST create / POST update) |
/business/pay/channelConfig |
| 支付商户 | pay_merchant |
/manager/business/pay/payMerchant/v1 |
/business/pay/merchant |
| 微信支付 V3 | pay_wechat_config |
/manager/business/pay/payWechatConfig/v1 |
/business/pay/wechatConfig |
| 支付拓展单 | pay_order_extension |
/manager/business/pay/payOrderExtension/v1 |
/business/pay/orderExtension |
| 退款订单 | pay_refund |
/manager/business/pay/payRefund/v1 |
/business/pay/refund |
| 系统支付订单 | sys_pay_order |
/manager/business/pay/sysPayOrder/v1 |
/business/pay/sysPayOrder |
标准操作:GET info、POST list、POST create、POST update、GET delete?ids=(各子模块若仍为 POST save 以代码为准)。
manager:business:pay:payChannelConfig:info|list|create|update|delete
manager:business:pay:payMerchant:info|list|save|delete
manager:business:pay:payWechatConfig:info|list|save|delete
manager:business:pay:payOrderExtension:info|list|save|delete
manager:business:pay:payRefund:info|list|save|delete
manager:business:pay:sysPayOrder:info|list|save|delete
菜单 SQL:doc/sql/business-pay/pay_admin_menu.sql(path 建议 business/pay/wechatConfig,component 为 business/pay/wechatConfig/index)。
完整支付域菜单(含 finance 结算/分账等)见下文第十一节。
web-starter 已依赖 business-pay-controller,启动后即可访问管理端 API 与 /api/pay/payNotify/* 回调。
business-mobile-gateway 依赖 business-pay-api,C 端预支付与业务回调在网关模块。
| 模块 | 职责 |
|---|---|
| business-finance | 杏花村 biz_finance_pay_order、支付流水;创建支付意图、标记已支付 |
| business-pay | 渠道能力(微信 V3 下单/验签)、Legacy sys_pay_order、管理端配置 |
C 端主链路:finance 写主单 → pay 调渠道 → 业务回调 adapter → finance 改状态 + 记流水。
数据迁移说明:doc/sql/business-finance/sys_pay_order_migrate_to_finance.md。
| 能力 | 包路径 | 说明 |
|---|---|---|
| 对外 API | business-pay-api |
PayCenterApi、PayOrderReadApi |
| 支付策略 | strategy/operation/ |
各渠道下单/查单/退款 |
| 回调策略 | strategy/notify/ |
各渠道异步通知 |
| 订单监听 | listener/event/PayApiOrderServiceImpl |
sys_pay_order 创建与更新 |
| 微信 V3 | service/weixin/、paywechatconfig/ |
配置、预支付、回调解析 |
| 回调 HTTP | PayNotifyController |
Legacy 统一入口 |
注意:模块内 PayOrderService 为 PayCenterApi 别名;与 business-finance 的 PayOrderService 包名不同,注入时勿混淆。
| 项 | 说明 |
|---|---|
| 配置表 | pay_wechat_config(sql/pay_wechat_config.sql) |
| 管理端 | GET active、POST save |
| 种子 SQL | sql/pay_wechat_config_seed.sql |
| 全部 SQL | 见 sql/README.md(建表/种子/菜单集中存放) |
| 运行时 | PayWechatWxPayClientHolder 按库表装配,保存后自动失效缓存 |
| 已移除 | wx.pay YAML、gateway 内重复 WechatMiniPay* 实现 |
sys_menu_info 对照)路由登记:
TravelWebFrontProject/src/business/asyncRouter.ts
页面目录:TravelWebFrontProject/src/business/views/pay/*、.../views/finance/*
与系统库对照时,menu_path须与路由name完全一致,否则动态路由无法匹配。
| 字段 | 前端路由(asyncRouter) | 系统菜单(sys_menu_info) |
|---|---|---|
| 路由名 | name |
menu_path |
| 访问地址 | path(如 /business/pay/channelConfig) |
由壳层与 class_path 拼出 |
| 组件 | views/.../index.vue |
component(无 .vue,如 business/pay/channelConfig/index) |
| 侧栏 | hidden: true 或 meta.hidden |
is_show(0 隐藏 / 1 显示) |
/business/pay/*菜单 SQL:
doc/sql/business-pay/pay_admin_menu.sql(历史sys_menu结构;生产以sys_menu_info+ 下表menu_path为准)
| 菜单标题 | 路由名 menu_path |
浏览器路径 | 组件 component |
侧栏 |
|---|---|---|---|---|
| 渠道配置 | businessPayChannelConfig |
/business/pay/channelConfig |
business/pay/channelConfig/index |
显示 |
| 微信配置 | businessPayWechatConfig |
/business/pay/wechatConfig |
business/pay/wechatConfig/index |
隐藏(从渠道配置进入) |
| 支付宝配置 | businessPayAlipayConfig |
/business/pay/alipayConfig |
business/pay/alipayConfig/index |
隐藏 |
| 浦发配置 | businessPayPufaConfig |
/business/pay/pufaConfig |
business/pay/pufaConfig/index |
隐藏 |
| 特约商户进件 | businessPaySubMerchantApplyment |
/business/pay/subMerchantApplyment |
business/pay/subMerchantApplyment/index |
显示 |
| 进件申请编辑 | businessPaySubMerchantApplymentEditor |
/business/pay/subMerchantApplyment/editor |
business/pay/subMerchantApplyment/editor |
隐藏 |
| 进件申请进度 | businessPaySubMerchantApplymentProgress |
/business/pay/subMerchantApplyment/progress |
business/pay/subMerchantApplyment/progress |
隐藏 |
| 修改结算账户 | businessPaySubMerchantApplymentSettlementModify |
/business/pay/subMerchantApplyment/settlementModify |
business/pay/subMerchantApplyment/settlementModify |
隐藏 |
| 商户注销 | businessPaySubMerchantApplymentMerchantCancel |
/business/pay/subMerchantApplyment/merchantCancel |
business/pay/subMerchantApplyment/merchantCancel |
隐藏 |
| 平台账户提现 | businessPayPlatformFundWithdraw |
/business/pay/platformFundWithdraw |
business/pay/platformFundWithdraw/index |
显示 |
| 商户账户提现 | businessPayMerchantFundWithdraw |
/business/pay/merchantFundWithdraw |
business/pay/merchantFundWithdraw/index |
显示 |
| 支付拓展单 | businessPayOrderExtension |
/business/pay/orderExtension |
business/pay/orderExtension/index |
显示 |
| 退款订单(支付中心) | businessPayRefund |
/business/pay/refund |
business/pay/refund/index |
显示 |
| 系统支付订单(Legacy) | businessPaySysPayOrder |
/business/pay/sysPayOrder |
business/pay/sysPayOrder/index |
显示 |
/business/finance/*模块:
business-finance
菜单 SQL:business-finance/src/main/resources/sql/finance_menu_permission.sql、finance_merchant_finance_permission.sql;
支付记录/支付单:doc/sql/business-finance/finance_pay_record_menu.sql、finance_pay_order_menu.sql
| 菜单标题 | 路由名 menu_path |
浏览器路径 | 组件 component |
侧栏 | 备注 |
|---|---|---|---|---|---|
| 支付记录 | businessFinancePayRecord |
/business/finance/payRecord |
business/finance/payRecord/index |
显示 | |
| 支付单 | businessFinancePayOrder |
/business/finance/payOrder |
business/finance/payOrder/index |
显示 | 杏花村主支付单(biz_finance_pay_order) |
| 商户结算配置 | businessFinanceMerchantSettle |
/business/finance/merchantSettle |
business/finance/merchantSettle/index |
显示 | |
| 微信分账单 | businessFinanceProfitSharing |
/business/finance/profitSharing |
business/finance/profitSharing/index |
显示 | 平台视角 |
| 我的分账 | businessFinanceMyProfitSharing |
/business/finance/myProfitSharing |
business/finance/profitSharing/index |
显示 | 商户视角,同组件 |
| 支付退款单(财务) | businessFinancePayRefund |
/business/finance/payRefund |
business/finance/payRefund/index |
显示 | 与 businessPayRefund 不同模块 |
| 商户应收账 | businessFinanceMerchantReceivable |
/business/finance/merchantReceivable |
business/finance/merchantReceivable/index |
显示 | 平台视角 |
| 我的收入 | businessFinanceMyIncome |
/business/finance/myIncome |
business/finance/merchantReceivable/index |
显示 | 商户视角,同组件 |
| 商户结算单 | businessFinanceMerchantSettlementBill |
/business/finance/merchantSettlementBill |
business/finance/merchantSettlementBill/index |
显示 | 平台代收结算 |
| 我的结算单 | businessFinanceMySettlementBill |
/business/finance/mySettlementBill |
business/finance/merchantSettlementBill/index |
显示 | 商户视角,同组件 |
| 分账回退单 | businessFinanceProfitSharingReturn |
/business/finance/profitSharingReturn |
business/finance/profitSharingReturn/index |
显示 | |
| 财务对账 | businessFinanceReconcile |
/business/finance/reconcile |
business/finance/reconcile/index |
显示 |
无独立菜单(按钮权限)
| 能力 | 权限标识 | 挂在页面 | SQL |
|---|---|---|---|
| 平台收入日汇总回填 | manager:business:finance:platformRevenue:rollup |
商户应收账 → 平台佣金趋势卡片 | finance_merchant_finance_permission.sql |
| 对比项 | 支付中心(business-pay) |
财务(business-finance) |
|---|---|---|
| 退款 | businessPayRefund → /business/pay/refund |
businessFinancePayRefund → /business/finance/payRefund |
| 支付单 | businessPaySysPayOrder(Legacy sys_pay_order) |
businessFinancePayOrder(C 端主链路) |
| 分账 | — | profitSharing(平台)/ myProfitSharing(商户) |
| 结算 | 进件子页「修改结算账户」 | merchantSettle 配置 + merchantSettlementBill 结算单 |
SELECT menu_name, menu_short_name, menu_path, component, sort_num, is_show
FROM sys_menu_info
WHERE del_flag = '0'
AND (
menu_path LIKE 'businessPay%'
OR menu_path LIKE 'businessFinance%'
OR component LIKE 'business/pay/%'
OR component LIKE 'business/finance/%'
)
ORDER BY sort_num, menu_name;
应存在的路由名(menu_path)清单:
-- 支付中心(14)
businessPayChannelConfig
businessPayWechatConfig
businessPayAlipayConfig
businessPayPufaConfig
businessPaySubMerchantApplyment
businessPaySubMerchantApplymentEditor
businessPaySubMerchantApplymentProgress
businessPaySubMerchantApplymentSettlementModify
businessPaySubMerchantApplymentMerchantCancel
businessPayPlatformFundWithdraw
businessPayMerchantFundWithdraw
businessPayOrderExtension
businessPayRefund
businessPaySysPayOrder
-- 财务支付/结算(12)
businessFinancePayRecord
businessFinancePayOrder
businessFinanceMerchantSettle
businessFinanceProfitSharing
businessFinanceMyProfitSharing
businessFinancePayRefund
businessFinanceMerchantReceivable
businessFinanceMyIncome
businessFinanceMerchantSettlementBill
businessFinanceMySettlementBill
businessFinanceProfitSharingReturn
businessFinanceReconcile
核对要点:menu_path = 路由 name;component 与上表一致;隐藏子页勿误设 is_show = 1。
Q:新业务要做小程序微信支付,最少改哪些地方?
A:finance 创建支付意图;网关复用 WechatJsapiPayOrderPrepayService.execute;新增 WechatPayCallbackAdapter;配置 notifyBaseUrl(统一回调路径 /pay/notify/wechat 由网关常量维护)。
Q:能否在业务 Service 里直接 paymentOrder 调微信?
A:杏花村订单不可以,须 wechatJsapiPrepay 且带 bizScene;Legacy 物业单可以 paymentOrder。
Q:回调成功但业务单未更新?
A:查 attach 是否含正确 orderId / payOrderId;查 WechatPayCallbackAdapter 是否注册;查 finance 日志是否 markPaidByWechatOutTradeNo 异常。
Q:Legacy 微信回调仍走 /api/pay/payNotify/wxNotify 可以吗?
A:可以,但 C 端杏花村订单应走各业务 /app/.../notify/wechat,由 WechatPayNotifyAdapterService 统一处理,避免只更新 sys_pay_order。
文档版本: 2.1
最后更新: 2026-06-29
维护者: 项目团队