编辑 | blame | 历史 | 原始文档

支付信息双向同步功能说明

功能概述

实现新系统 sys_task_payment 表与旧系统 PaidMoney 表之间的支付信息双向同步,确保两个系统的支付数据保持一致。

技术架构

核心实体

1. SysTaskPayment(新系统支付记录)

  • 表名: sys_task_payment
  • 新增字段:
  • pid: 旧系统支付记录ID(PaidMoney.id)
  • sync_status: 同步状态(0未同步,1同步中,2同步成功,3同步失败)
  • sync_time: 同步时间

2. PaidMoney(旧系统支付记录)

  • 表名: PaidMoney
  • 关键字段:
  • id: 主键
  • ServiceOrdIDDt: 服务订单ID
  • DispatchOrdIDDt: 调度订单ID
  • PaidMoney: 支付金额
  • PaidMoneyType: 支付类型
  • PaidMoneyMono: 支付单号
  • PaidMoneyTime: 支付时间
  • PaidMoneyOaID: 支付人OAID

关键关联

通过 SysTaskEmergency 表获取任务与旧系统订单的映射关系:
- legacy_service_ord_idServiceOrdIDDt
- legacy_dispatch_ord_idDispatchOrdIDDt

同步逻辑

1. 新系统 → 旧系统同步

触发时机

  • 新系统支付成功后自动触发
  • 包括:现金支付、挂账、微信支付成功、支付宝支付成功

同步流程

  1. 支付成功后,调用 PaymentSyncService.syncPaymentToLegacy(paymentId)
  2. 查询新系统支付记录和任务信息
  3. 获取 ServiceOrdIDDtDispatchOrdIDDt
  4. 转换支付方式(新系统 → 旧系统)
  5. 构建 PaidMoney 对象并插入旧系统
  6. 更新新系统支付记录的 pidsync_statussync_time

支付方式映射(新 → 旧)

新系统支付方式 旧系统支付类型 说明
CASH 1 现金
ON_ACCOUNT 6 挂账
WECHAT 3 微信支付
ALIPAY 4 支付宝

数据映射

PaidMoney.PaidMoneyClass = "FI"  // 默认FI
PaidMoney.ServiceOrdIDDt = emergency.legacyServiceOrdId
PaidMoney.DispatchOrdIDDt = emergency.legacyDispatchOrdId
PaidMoney.PaidMoney = payment.settlementAmount
PaidMoney.PaidMoneyType = convertPaymentMethodToLegacy(payment.paymentMethod)
PaidMoney.PaidMoneyMono = payment.tradeNo 或 payment.outTradeNo
PaidMoney.PaidMoneyTime = payment.payTime
PaidMoney.PaidMoneyOaID = user.oaUserId
PaidMoney.PaidMoneyUnitID = 0  // 默认0
PaidMoney.PaidMoneyAPCheck = 1  // 已确认
PaidMoney.PaidMoneyAPTime = now()

2. 旧系统 → 新系统同步

触发时机

  • 定时任务(待实现)
  • 手动调用 PaymentSyncService.syncPaymentFromLegacy(paidMoneyId)

同步流程

  1. 查询旧系统 PaidMoney 记录
  2. 检查是否已同步(通过 pid 字段)
  3. 根据 ServiceOrdIDDt 查询新系统任务
  4. 转换支付方式(旧系统 → 新系统)
  5. 构建 SysTaskPayment 对象并插入新系统
  6. 设置 pidsync_status=2sync_time

支付方式映射(旧 → 新)

旧系统支付类型 新系统支付方式 说明
1 CASH 现金
6, 7 ON_ACCOUNT 挂账、易医通挂账
3 WECHAT 微信支付
4 ALIPAY 支付宝

数据映射

SysTaskPayment.taskId = task.taskId
SysTaskPayment.totalAmount = paidMoney.paidMoney
SysTaskPayment.settlementAmount = paidMoney.paidMoney
SysTaskPayment.paymentMethod = convertPaymentMethodFromLegacy(paidMoney.paidMoneyType)
SysTaskPayment.payStatus = "PAID"
SysTaskPayment.payTime = paidMoney.paidMoneyTime
SysTaskPayment.outTradeNo = taskCode + "-" + paidMoneyId
SysTaskPayment.tradeNo = paidMoney.paidMoneyMono
SysTaskPayment.pid = paidMoneyId
SysTaskPayment.syncStatus = 2
SysTaskPayment.syncTime = now()

核心代码实现

文件清单

新增文件

  1. 实体类
  • PaidMoney.java - 旧系统支付记录实体
  1. Mapper接口
  • PaidMoneyMapper.java - 旧系统支付记录Mapper接口
  1. Mapper XML
  • PaidMoneyMapper.xml - 旧系统支付记录SQL映射
  1. Service接口
  • IPaymentSyncService.java - 支付同步服务接口
  1. Service实现
  • PaymentSyncServiceImpl.java - 支付同步服务实现
  1. 数据库脚本
  • payment_sync_update.sql - 数据表更新脚本

修改文件

  1. 实体类
  • SysTaskPayment.java - 新增 pid、syncStatus、syncTime 字段
  1. Mapper接口
  • SysTaskPaymentMapper.java - 新增 selectByPid、updateSyncInfo 方法
  1. Mapper XML
  • SysTaskPaymentMapper.xml - 更新映射和新增查询方法
  1. Service实现
  • SysTaskPaymentServiceImpl.java - 支付成功后触发同步

数据源配置

使用 @DataSource 注解切换数据源:

// 访问新系统数据库(默认)
public void processNewSystem() {
    // 默认使用主数据源
}

// 访问旧系统数据库
@DataSource(DataSourceType.SQLSERVER)
public void processLegacySystem() {
    // 使用SQL Server数据源
}

同步状态管理

sync_status 状态值

  • 0 - 未同步: 新创建的支付记录,尚未同步到旧系统
  • 1 - 同步中: 正在执行同步操作
  • 2 - 同步成功: 已成功同步到旧系统
  • 3 - 同步失败: 同步过程中发生错误

状态流转

新支付记录 → 0(未同步) → 1(同步中) → 2(同步成功) 或 3(同步失败)
                                    ↓
                                 可重试

异常处理

同步失败场景

  1. 任务未同步到旧系统(缺少 ServiceOrdID/DispatchOrdID)
  2. 旧系统数据库连接失败
  3. 数据插入冲突或约束违反
  4. 网络异常

处理策略

  1. 同步失败时标记 sync_status=3
  2. 记录详细错误日志
  3. 不影响主业务流程(异步同步)
  4. 可通过定时任务或手动触发重试

使用示例

手动触发同步

@Autowired
private IPaymentSyncService paymentSyncService;

// 同步单条支付记录到旧系统
boolean success = paymentSyncService.syncPaymentToLegacy(paymentId);

// 从旧系统同步支付记录
boolean success = paymentSyncService.syncPaymentFromLegacy(paidMoneyId);

// 批量同步(待实现)
int count = paymentSyncService.batchSyncPaymentToLegacy();
int count = paymentSyncService.batchSyncPaymentFromLegacy();

数据库更新

执行 SQL 脚本:
sql source sql/payment_sync_update.sql

或手动执行:
sql ALTER TABLE sys_task_payment ADD COLUMN pid BIGINT COMMENT '旧系统支付记录ID(PaidMoney.id)'; ALTER TABLE sys_task_payment ADD COLUMN sync_status INT DEFAULT 0 COMMENT '同步状态:0未同步,1同步中,2同步成功,3同步失败'; ALTER TABLE sys_task_payment ADD COLUMN sync_time DATETIME COMMENT '同步时间'; CREATE INDEX idx_pid ON sys_task_payment(pid); CREATE INDEX idx_sync_status ON sys_task_payment(sync_status);

后续优化建议

  1. 批量同步实现
  • 实现定时任务批量同步未同步的支付记录
  • 实现从旧系统定期拉取新增支付记录
  1. 重试机制
  • 对同步失败的记录实现自动重试
  • 设置最大重试次数和重试间隔
  1. 监控告警
  • 监控同步失败率
  • 同步延迟告警
  • 数据一致性校验
  1. 性能优化
  • 考虑使用消息队列异步处理
  • 批量操作优化数据库性能

注意事项

  1. 前置条件: 任务必须先同步到旧系统(有 ServiceOrdID 和 DispatchOrdID)
  2. 幂等性: 重复同步会被检测并跳过
  3. 事务处理: 同步操作使用独立事务,失败不影响主业务
  4. 数据一致性: 通过 pid 字段建立双向关联,避免重复同步
  5. 支付方式映射: 确保新旧系统支付方式正确映射

测试建议

  1. 单元测试
  • 测试支付方式转换逻辑
  • 测试数据映射正确性
  • 测试异常处理
  1. 集成测试
  • 测试完整同步流程
  • 测试幂等性
  • 测试失败重试
  1. 数据校验
  • 对比新旧系统支付数据
  • 验证金额、时间、状态一致性

---
更新时间: 2025-01-15
版本: v1.0