支付关系表
1. 概述
支付关系表是梵医云系统中用于管理支付订单、退款订单、支付渠道、支付应用、分账记录、钱包等相关数据的核心模块。该模块提供了完整的支付管理体系,包括支付、退款、转账、分账、钱包充值等功能。
2. 表结构
2.1 支付订单表 (pay_order)
支付订单表是支付模块的核心表,存储支付订单的基本信息、价格信息、渠道信息等。
2.1.1 表结构
| 字段名 | 类型 | 长度 | 允许空 | 默认值 | 说明 |
|---|---|---|---|---|---|
| id | bigint | 20 | 否 | - | 订单编号(主键) |
| merchant_id | bigint | 20 | 否 | - | 商户ID |
| app_id | bigint | 20 | 否 | - | 应用编号 |
| channel_id | bigint | 20 | 否 | - | 渠道编号 |
| channel_code | varchar | 32 | 否 | - | 渠道编码 |
| order_source | varchar | 64 | 是 | NULL | 订单来源 |
| merchant_order_id | varchar | 64 | 否 | - | 商户订单编号 |
| subject | varchar | 128 | 是 | NULL | 商品标题 |
| body | varchar | 512 | 是 | NULL | 商品描述信息 |
| notify_url | varchar | 512 | 是 | NULL | 异步通知地址 |
| price | int | 11 | 否 | - | 支付金额(单位:分) |
| channel_fee_rate | double | 10,4 | 是 | NULL | 渠道手续费(单位:百分比) |
| channel_fee_price | int | 11 | 否 | 0 | 渠道手续金额(单位:分) |
| profit_sharing | tinyint | 4 | 否 | 0 | 分账状态 |
| status | tinyint | 4 | 否 | - | 支付状态(0待支付 1支付成功 2支付关闭) |
| user_ip | varchar | 50 | 是 | NULL | 用户IP |
| expire_time | datetime | - | 是 | NULL | 订单失效时间 |
| success_time | datetime | - | 是 | NULL | 订单支付成功时间 |
| extension_id | bigint | 20 | 是 | NULL | 支付成功的订单拓展单编号 |
| no | varchar | 64 | 是 | NULL | 支付成功的外部订单号 |
| refund_price | int | 11 | 否 | 0 | 退款总金额(单位:分) |
| channel_user_id | varchar | 128 | 是 | NULL | 渠道用户编号 |
| channel_order_no | varchar | 64 | 是 | NULL | 渠道订单号 |
| pay_channel_info | json | - | 是 | NULL | 支付渠道相关信息 |
| creator | varchar | 64 | 是 | '' | 创建者 |
| create_time | datetime | - | 否 | CURRENT_TIMESTAMP | 创建时间 |
| updater | varchar | 64 | 是 | '' | 更新者 |
| update_time | datetime | - | 否 | CURRENT_TIMESTAMP | 更新时间 |
| deleted | bit | 1 | 否 | b'0' | 是否删除 |
2.1.2 索引
| 索引名 | 类型 | 字段 | 说明 |
|---|---|---|---|
| PRIMARY | 主键 | id | 主键索引 |
| uk_merchant_order_id_app_id | 唯一 | merchant_order_id, app_id | 商户订单号唯一索引 |
| idx_status | 普通 | status | 支付状态索引 |
| idx_app_id | 普通 | app_id | 应用索引 |
2.1.3 Java 实体类
java
@TableName(value = "pay_order", autoResultMap = true)
@KeySequence("pay_order_seq")
@Data
@EqualsAndHashCode(callSuper = true)
@ToString(callSuper = true)
@Builder
@NoArgsConstructor
@AllArgsConstructor
public class PayOrderDO extends BaseDO {
@TableId
private Long id;
private Long merchantId;
private Long appId;
private Long channelId;
private String channelCode;
private String orderSource;
private String merchantOrderId;
private String subject;
private String body;
private String notifyUrl;
private Integer price;
private Double channelFeeRate;
private Integer channelFeePrice;
private OrderProfitSharingEnum profitSharing;
private Integer status;
private String userIp;
private LocalDateTime expireTime;
private LocalDateTime successTime;
private Long extensionId;
private String no;
private Integer refundPrice;
private String channelUserId;
private String channelOrderNo;
@TableField(typeHandler = JacksonTypeHandler.class)
private Map<String, Object> payChannelInfo;
}2.2 支付订单拓展表 (pay_order_extension)
支付订单拓展表用于存储每次调用支付渠道的记录。
2.2.1 表结构
| 字段名 | 类型 | 长度 | 允许空 | 默认值 | 说明 |
|---|---|---|---|---|---|
| id | bigint | 20 | 否 | - | 订单拓展编号(主键) |
| no | varchar | 64 | 否 | - | 外部订单号 |
| order_id | bigint | 20 | 否 | - | 订单编号 |
| channel_id | bigint | 20 | 否 | - | 渠道编号 |
| channel_code | varchar | 32 | 否 | - | 渠道编码 |
| user_ip | varchar | 50 | 是 | NULL | 用户IP |
| status | tinyint | 4 | 否 | - | 支付状态 |
| channel_extras | json | - | 是 | NULL | 支付渠道的额外参数 |
| channel_error_code | varchar | 128 | 是 | NULL | 调用渠道的错误码 |
| channel_error_msg | varchar | 512 | 是 | NULL | 调用渠道报错时,错误信息 |
| channel_notify_data | text | - | 是 | NULL | 支付渠道的同步/异步通知的内容 |
| extras_info | json | - | 是 | NULL | 额外信息 |
| creator | varchar | 64 | 是 | '' | 创建者 |
| create_time | datetime | - | 否 | CURRENT_TIMESTAMP | 创建时间 |
| updater | varchar | 64 | 是 | '' | 更新者 |
| update_time | datetime | - | 否 | CURRENT_TIMESTAMP | 更新时间 |
| deleted | bit | 1 | 否 | b'0' | 是否删除 |
2.2.2 索引
| 索引名 | 类型 | 字段 | 说明 |
|---|---|---|---|
| PRIMARY | 主键 | id | 主键索引 |
| uk_no | 唯一 | no | 外部订单号唯一索引 |
| idx_order_id | 普通 | order_id | 订单索引 |
2.2.3 Java 实体类
java
@TableName(value = "pay_order_extension", autoResultMap = true)
@KeySequence("pay_order_extension_seq")
@Data
@EqualsAndHashCode(callSuper = true)
@ToString(callSuper = true)
@Builder
@NoArgsConstructor
@AllArgsConstructor
public class PayOrderExtensionDO extends BaseDO {
@TableId
private Long id;
private String no;
private Long orderId;
private Long channelId;
private String channelCode;
private String userIp;
private Integer status;
@TableField(typeHandler = JacksonTypeHandler.class)
private Map<String, String> channelExtras;
private String channelErrorCode;
private String channelErrorMsg;
private String channelNotifyData;
@TableField(typeHandler = JacksonTypeHandler.class)
private Object extrasInfo;
}2.3 支付退款单表 (pay_refund)
支付退款单表用于处理支付订单的退款流程。
2.3.1 表结构
| 字段名 | 类型 | 长度 | 允许空 | 默认值 | 说明 |
|---|---|---|---|---|---|
| id | bigint | 20 | 否 | - | 退款单编号(主键) |
| no | varchar | 64 | 否 | - | 外部退款号 |
| app_id | bigint | 20 | 否 | - | 应用编号 |
| channel_id | bigint | 20 | 否 | - | 渠道编号 |
| channel_code | varchar | 32 | 否 | - | 商户编码 |
| order_id | bigint | 20 | 否 | - | 订单编号 |
| order_no | varchar | 64 | 否 | - | 支付订单编号 |
| merchant_order_id | varchar | 64 | 是 | NULL | 商户订单编号 |
| merchant_refund_id | varchar | 64 | 是 | NULL | 商户退款订单号 |
| notify_url | varchar | 512 | 是 | NULL | 异步通知地址 |
| status | tinyint | 4 | 否 | - | 退款状态(0待退款 1退款成功 2退款失败) |
| pay_price | int | 11 | 否 | - | 支付金额(单位:分) |
| refund_price | int | 11 | 否 | - | 退款金额(单位:分) |
| reason | varchar | 256 | 是 | NULL | 退款原因 |
| user_ip | varchar | 50 | 是 | NULL | 用户IP |
| channel_order_no | varchar | 64 | 是 | NULL | 渠道订单号 |
| channel_refund_no | varchar | 64 | 是 | NULL | 渠道退款单号 |
| success_time | datetime | - | 是 | NULL | 退款成功时间 |
| channel_error_code | varchar | 128 | 是 | NULL | 调用渠道的错误码 |
| channel_error_msg | varchar | 512 | 是 | NULL | 调用渠道的错误提示 |
| channel_notify_data | text | - | 是 | NULL | 支付渠道的同步/异步通知的内容 |
| creator | varchar | 64 | 是 | '' | 创建者 |
| create_time | datetime | - | 否 | CURRENT_TIMESTAMP | 创建时间 |
| updater | varchar | 64 | 是 | '' | 更新者 |
| update_time | datetime | - | 否 | CURRENT_TIMESTAMP | 更新时间 |
| deleted | bit | 1 | 否 | b'0' | 是否删除 |
2.3.2 索引
| 索引名 | 类型 | 字段 | 说明 |
|---|---|---|---|
| PRIMARY | 主键 | id | 主键索引 |
| uk_no | 唯一 | no | 外部退款号唯一索引 |
| idx_order_id | 普通 | order_id | 订单索引 |
2.3.3 Java 实体类
java
@TableName("pay_refund")
@KeySequence("pay_refund_seq")
@Data
@EqualsAndHashCode(callSuper = true)
@ToString(callSuper = true)
@Builder
@NoArgsConstructor
@AllArgsConstructor
public class PayRefundDO extends BaseDO {
@TableId
private Long id;
private String no;
private Long appId;
private Long channelId;
private String channelCode;
private Long orderId;
private String orderNo;
private String merchantOrderId;
private String merchantRefundId;
private String notifyUrl;
private Integer status;
private Integer payPrice;
private Integer refundPrice;
private String reason;
private String userIp;
private String channelOrderNo;
private String channelRefundNo;
private LocalDateTime successTime;
private String channelErrorCode;
private String channelErrorMsg;
private String channelNotifyData;
}2.4 支付应用表 (pay_app)
支付应用表用于管理支付应用信息。
2.4.1 表结构
| 字段名 | 类型 | 长度 | 允许空 | 默认值 | 说明 |
|---|---|---|---|---|---|
| id | bigint | 20 | 否 | - | 应用编号(主键) |
| name | varchar | 64 | 否 | - | 应用名 |
| status | tinyint | 4 | 否 | - | 状态(0正常 1停用) |
| remark | varchar | 512 | 是 | NULL | 备注 |
| order_notify_url | varchar | 512 | 是 | NULL | 支付结果的回调地址 |
| refund_notify_url | varchar | 512 | 是 | NULL | 退款结果的回调地址 |
| transfer_notify_url | varchar | 512 | 是 | NULL | 转账结果的回调地址 |
| creator | varchar | 64 | 是 | '' | 创建者 |
| create_time | datetime | - | 否 | CURRENT_TIMESTAMP | 创建时间 |
| updater | varchar | 64 | 是 | '' | 更新者 |
| update_time | datetime | - | 否 | CURRENT_TIMESTAMP | 更新时间 |
| deleted | bit | 1 | 否 | b'0' | 是否删除 |
2.4.2 索引
| 索引名 | 类型 | 字段 | 说明 |
|---|---|---|---|
| PRIMARY | 主键 | id | 主键索引 |
2.4.3 Java 实体类
java
@TableName("pay_app")
@KeySequence("pay_app_seq")
@Data
@EqualsAndHashCode(callSuper = true)
@ToString(callSuper = true)
@Builder
@NoArgsConstructor
@AllArgsConstructor
public class PayAppDO extends BaseDO {
@TableId
private Long id;
private String name;
private Integer status;
private String remark;
private String orderNotifyUrl;
private String refundNotifyUrl;
private String transferNotifyUrl;
}2.5 支付渠道表 (pay_channel)
支付渠道表用于管理支付渠道信息,如微信支付、支付宝支付等。
2.5.1 表结构
| 字段名 | 类型 | 长度 | 允许空 | 默认值 | 说明 |
|---|---|---|---|---|---|
| id | bigint | 20 | 否 | - | 渠道编号(主键) |
| code | varchar | 32 | 否 | - | 渠道编码 |
| status | tinyint | 4 | 否 | - | 状态(0正常 1停用) |
| fee_rate | double | 10,4 | 否 | - | 渠道费率(单位:百分比) |
| remark | varchar | 512 | 是 | NULL | 备注 |
| app_id | bigint | 20 | 否 | - | 应用编号 |
| config | json | - | 是 | NULL | 支付渠道配置 |
| creator | varchar | 64 | 是 | '' | 创建者 |
| create_time | datetime | - | 否 | CURRENT_TIMESTAMP | 创建时间 |
| updater | varchar | 64 | 是 | '' | 更新者 |
| update_time | datetime | - | 否 | CURRENT_TIMESTAMP | 更新时间 |
| deleted | bit | 1 | 否 | b'0' | 是否删除 |
2.5.2 索引
| 索引名 | 类型 | 字段 | 说明 |
|---|---|---|---|
| PRIMARY | 主键 | id | 主键索引 |
| uk_code_app_id | 唯一 | code, app_id | 渠道编码和应用唯一索引 |
2.5.3 Java 实体类
java
@TableName(value = "pay_channel", autoResultMap = true)
@KeySequence("pay_channel_seq")
@Data
@EqualsAndHashCode(callSuper = true)
@ToString(callSuper = true)
@Builder
@NoArgsConstructor
@AllArgsConstructor
public class PayChannelDO extends BaseDO {
@TableId
private Long id;
private String code;
private Integer status;
private Double feeRate;
private String remark;
private Long appId;
@TableField(typeHandler = JacksonTypeHandler.class)
private PayClientConfig config;
}2.6 支付商户表 (pay_merchant)
支付商户表用于管理支付商户信息。
2.6.1 表结构
| 字段名 | 类型 | 长度 | 允许空 | 默认值 | 说明 |
|---|---|---|---|---|---|
| id | bigint | 20 | 否 | - | 编号(主键) |
| merchant_name | varchar | 128 | 否 | - | 商户名称 |
| pay_app_id | bigint | 20 | 是 | NULL | 应用编号 |
| pay_channel_info | json | - | 是 | NULL | 支付渠道相关信息 |
| is_profit_sharing | bit | 1 | 是 | NULL | 是否分账 |
| mall_profit_sharing_percentage | decimal | 10,4 | 是 | NULL | 商城分账百分比 |
| creator | varchar | 64 | 是 | '' | 创建者 |
| create_time | datetime | - | 否 | CURRENT_TIMESTAMP | 创建时间 |
| updater | varchar | 64 | 是 | '' | 更新者 |
| update_time | datetime | - | 否 | CURRENT_TIMESTAMP | 更新时间 |
| deleted | bit | 1 | 否 | b'0' | 是否删除 |
2.6.2 索引
| 索引名 | 类型 | 字段 | 说明 |
|---|---|---|---|
| PRIMARY | 主键 | id | 主键索引 |
2.6.3 Java 实体类
java
@TableName(value = "pay_merchant", autoResultMap = true)
@Data
public class PayMerchantDO extends BaseDO {
private Long id;
private String merchantName;
private Long payAppId;
@TableField(typeHandler = JacksonTypeHandler.class)
private Map<String, Object> payChannelInfo;
private Boolean isProfitSharing;
private BigDecimal mallProfitSharingPercentage;
}2.7 支付分账记录表 (pay_profit_sharing_record)
支付分账记录表用于记录支付订单的分账信息。
2.7.1 表结构
| 字段名 | 类型 | 长度 | 允许空 | 默认值 | 说明 |
|---|---|---|---|---|---|
| id | bigint | 20 | 否 | - | 编号(主键) |
| request_no | varchar | 64 | 是 | NULL | 请求流水号 |
| order_id | bigint | 20 | 是 | NULL | 商户订单ID |
| order_no | varchar | 64 | 是 | NULL | 商户订单编号 |
| pay_order_id | bigint | 20 | 是 | NULL | 支付订单ID |
| channel_code | varchar | 32 | 是 | NULL | 支付渠道编码 |
| payment_amount | int | 11 | 是 | NULL | 支付金额(单位:分) |
| available_amount | int | 11 | 是 | NULL | 可用的分账金额(单位:分) |
| profit_sharing_percentage | decimal | 10,4 | 是 | NULL | 分账百分比 |
| profit_sharing_amount | int | 11 | 是 | NULL | 实际分账金额 |
| receiver_account | varchar | 128 | 是 | NULL | 分账接收方账号 |
| receiver_account_name | varchar | 128 | 是 | NULL | 分账接收方账号名称 |
| creator | varchar | 64 | 是 | '' | 创建者 |
| create_time | datetime | - | 否 | CURRENT_TIMESTAMP | 创建时间 |
| updater | varchar | 64 | 是 | '' | 更新者 |
| update_time | datetime | - | 否 | CURRENT_TIMESTAMP | 更新时间 |
| deleted | bit | 1 | 否 | b'0' | 是否删除 |
2.7.2 索引
| 索引名 | 类型 | 字段 | 说明 |
|---|---|---|---|
| PRIMARY | 主键 | id | 主键索引 |
| idx_pay_order_id | 普通 | pay_order_id | 支付订单索引 |
2.7.3 Java 实体类
java
@TableName("pay_profit_sharing_record")
@Data
public class PayProfitSharingRecordDO {
private Long id;
private String requestNo;
private Long orderId;
private String orderNo;
private Long payOrderId;
private String channelCode;
private Integer paymentAmount;
private Integer availableAmount;
private BigDecimal profitSharingPercentage;
private Integer profitSharingAmount;
private String receiverAccount;
private String receiverAccountName;
}2.8 支付分账接收方表 (pay_profit_sharing_receiver)
支付分账接收方表用于配置分账接收方信息。
2.8.1 表结构
| 字段名 | 类型 | 长度 | 允许空 | 默认值 | 说明 |
|---|---|---|---|---|---|
| id | bigint | 20 | 否 | - | 编号(主键) |
| channel_code | varchar | 32 | 否 | - | 支付渠道编码 |
| receiver_account | varchar | 128 | 否 | - | 分账接收方账号 |
| receiver_account_name | varchar | 128 | 否 | - | 分账接收方账号名称 |
| receiver_description | varchar | 512 | 是 | NULL | 分账描述 |
| profit_sharing_percentage | decimal | 10,4 | 否 | - | 分账百分比 |
| filter_config | json | - | 是 | NULL | 分账时用于过滤接收方的配置 |
| is_platform_collection_account | bit | 1 | 是 | NULL | 是否平台代收账号 |
| creator | varchar | 64 | 是 | '' | 创建者 |
| create_time | datetime | - | 否 | CURRENT_TIMESTAMP | 创建时间 |
| updater | varchar | 64 | 是 | '' | 更新者 |
| update_time | datetime | - | 否 | CURRENT_TIMESTAMP | 更新时间 |
| deleted | bit | 1 | 否 | b'0' | 是否删除 |
2.8.2 索引
| 索引名 | 类型 | 字段 | 说明 |
|---|---|---|---|
| PRIMARY | 主键 | id | 主键索引 |
2.8.3 Java 实体类
java
@TableName(value = "pay_profit_sharing_receiver", autoResultMap = true)
@Data
public class PayProfitSharingReceiverDO {
private Long id;
private String channelCode;
private String receiverAccount;
private String receiverAccountName;
private String receiverDescription;
private BigDecimal profitSharingPercentage;
@TableField(typeHandler = JacksonTypeHandler.class)
private PayProfitSharingFilterConfig filterConfig;
private Boolean isPlatformCollectionAccount;
}2.9 支付转账单表 (pay_transfer)
支付转账单表用于处理转账业务。
2.9.1 表结构
| 字段名 | 类型 | 长度 | 允许空 | 默认值 | 说明 |
|---|---|---|---|---|---|
| id | bigint | 20 | 否 | - | 编号(主键) |
| no | varchar | 64 | 否 | - | 转账单号 |
| app_id | bigint | 20 | 否 | - | 应用编号 |
| channel_id | bigint | 20 | 否 | - | 转账渠道编号 |
| channel_code | varchar | 32 | 否 | - | 转账渠道编码 |
| merchant_transfer_id | varchar | 64 | 是 | NULL | 商户转账单编号 |
| type | tinyint | 4 | 否 | - | 类型 |
| subject | varchar | 128 | 是 | NULL | 转账标题 |
| price | int | 11 | 否 | - | 转账金额(单位:分) |
| user_name | varchar | 64 | 是 | NULL | 收款人姓名 |
| status | tinyint | 4 | 否 | - | 转账状态 |
| success_time | datetime | - | 是 | NULL | 订单转账成功时间 |
| alipay_logon_id | varchar | 128 | 是 | NULL | 支付宝登录号 |
| openid | varchar | 128 | 是 | NULL | 微信openId |
| notify_url | varchar | 512 | 是 | NULL | 异步通知地址 |
| user_ip | varchar | 50 | 是 | NULL | 用户IP |
| channel_extras | json | - | 是 | NULL | 渠道的额外参数 |
| channel_transfer_no | varchar | 64 | 是 | NULL | 渠道转账单号 |
| channel_error_code | varchar | 128 | 是 | NULL | 调用渠道的错误码 |
| channel_error_msg | varchar | 512 | 是 | NULL | 调用渠道的错误提示 |
| channel_notify_data | text | - | 是 | NULL | 渠道的同步/异步通知的内容 |
| bank_account | varchar | 128 | 是 | NULL | 银行账号 |
| merchant_id | bigint | 20 | 是 | NULL | 商户id |
| merchant_name | varchar | 128 | 是 | NULL | 商户名称 |
| service_network_id | varchar | 64 | 是 | NULL | 提现网点id |
| service_network | varchar | 128 | 是 | NULL | 提现网点 |
| audit_status | tinyint | 4 | 是 | NULL | 审核状态 |
| audit_reason | varchar | 512 | 是 | NULL | 审核原因 |
| user_id | bigint | 20 | 是 | NULL | 用户id |
| withdraw_id | int | 11 | 是 | NULL | 提现id |
| creator | varchar | 64 | 是 | '' | 创建者 |
| create_time | datetime | - | 否 | CURRENT_TIMESTAMP | 创建时间 |
| updater | varchar | 64 | 是 | '' | 更新者 |
| update_time | datetime | - | 否 | CURRENT_TIMESTAMP | 更新时间 |
| deleted | bit | 1 | 否 | b'0' | 是否删除 |
2.9.2 索引
| 索引名 | 类型 | 字段 | 说明 |
|---|---|---|---|
| PRIMARY | 主键 | id | 主键索引 |
| uk_no | 唯一 | no | 转账单号唯一索引 |
2.9.3 Java 实体类
java
@TableName(value = "pay_transfer", autoResultMap = true)
@KeySequence("pay_transfer_seq")
@Data
public class PayTransferDO extends BaseDO {
@TableId
private Long id;
private String no;
private Long appId;
private Long channelId;
private String channelCode;
private String merchantTransferId;
private Integer type;
private String subject;
private Integer price;
private String userName;
private Integer status;
private LocalDateTime successTime;
private String alipayLogonId;
private String openid;
private String notifyUrl;
private String userIp;
@TableField(typeHandler = JacksonTypeHandler.class)
private Map<String, String> channelExtras;
private String channelTransferNo;
private String channelErrorCode;
private String channelErrorMsg;
private String channelNotifyData;
private String bankAccount;
private Long merchantId;
private String merchantName;
private String serviceNetworkId;
private String serviceNetwork;
private Integer auditStatus;
private String auditReason;
private Long userId;
private Integer withdrawId;
}2.10 支付通知任务表 (pay_notify_task)
支付通知任务表用于管理支付、退款等通知任务。
2.10.1 表结构
| 字段名 | 类型 | 长度 | 允许空 | 默认值 | 说明 |
|---|---|---|---|---|---|
| id | bigint | 20 | 否 | - | 编号(主键) |
| app_id | bigint | 20 | 否 | - | 应用编号 |
| type | tinyint | 4 | 否 | - | 通知类型 |
| data_id | bigint | 20 | 否 | - | 数据编号 |
| merchant_order_id | varchar | 64 | 是 | NULL | 商户订单编号 |
| merchant_transfer_id | varchar | 64 | 是 | NULL | 商户转账单编号 |
| status | tinyint | 4 | 否 | - | 通知状态(0待通知 1通知成功 2通知失败) |
| next_notify_time | datetime | - | 否 | - | 下一次通知时间 |
| last_execute_time | datetime | - | 是 | NULL | 最后一次执行时间 |
| notify_times | int | 11 | 否 | 0 | 当前通知次数 |
| max_notify_times | int | 11 | 否 | - | 最大可通知次数 |
| notify_url | varchar | 512 | 否 | - | 通知地址 |
| creator | varchar | 64 | 是 | '' | 创建者 |
| create_time | datetime | - | 否 | CURRENT_TIMESTAMP | 创建时间 |
| updater | varchar | 64 | 是 | '' | 更新者 |
| update_time | datetime | - | 否 | CURRENT_TIMESTAMP | 更新时间 |
| deleted | bit | 1 | 否 | b'0' | 是否删除 |
2.10.2 索引
| 索引名 | 类型 | 字段 | 说明 |
|---|---|---|---|
| PRIMARY | 主键 | id | 主键索引 |
| idx_next_notify_time | 普通 | next_notify_time | 下一次通知时间索引 |
2.10.3 Java 实体类
java
@TableName("pay_notify_task")
@KeySequence("pay_notify_task_seq")
@Data
@EqualsAndHashCode(callSuper = true)
@Accessors(chain = true)
public class PayNotifyTaskDO extends BaseDO {
public static final Integer[] NOTIFY_FREQUENCY = new Integer[]{
15, 15, 30, 180,
1800, 1800, 1800, 3600
};
@TableId
private Long id;
private Long appId;
private Integer type;
private Long dataId;
private String merchantOrderId;
private String merchantTransferId;
private Integer status;
private LocalDateTime nextNotifyTime;
private LocalDateTime lastExecuteTime;
private Integer notifyTimes;
private Integer maxNotifyTimes;
private String notifyUrl;
}2.11 支付通知日志表 (pay_notify_log)
支付通知日志表用于记录支付、退款等通知的日志。
2.11.1 表结构
| 字段名 | 类型 | 长度 | 允许空 | 默认值 | 说明 |
|---|---|---|---|---|---|
| id | bigint | 20 | 否 | - | 日志编号(主键) |
| task_id | bigint | 20 | 否 | - | 通知任务编号 |
| notify_times | int | 11 | 否 | - | 第几次被通知 |
| response | text | - | 是 | NULL | HTTP响应结果 |
| status | tinyint | 4 | 否 | - | 支付通知状态 |
| creator | varchar | 64 | 是 | '' | 创建者 |
| create_time | datetime | - | 否 | CURRENT_TIMESTAMP | 创建时间 |
| updater | varchar | 64 | 是 | '' | 更新者 |
| update_time | datetime | - | 否 | CURRENT_TIMESTAMP | 更新时间 |
| deleted | bit | 1 | 否 | b'0' | 是否删除 |
2.11.2 索引
| 索引名 | 类型 | 字段 | 说明 |
|---|---|---|---|
| PRIMARY | 主键 | id | 主键索引 |
| idx_task_id | 普通 | task_id | 通知任务索引 |
2.11.3 Java 实体类
java
@TableName("pay_notify_log")
@KeySequence("pay_notify_log_seq")
@Data
@EqualsAndHashCode(callSuper = true)
@Builder
@NoArgsConstructor
@AllArgsConstructor
public class PayNotifyLogDO extends BaseDO {
@TableId
private Long id;
private Long taskId;
private Integer notifyTimes;
private String response;
private Integer status;
}2.12 支付钱包表 (pay_wallet)
支付钱包表用于管理用户的钱包信息。
2.12.1 表结构
| 字段名 | 类型 | 长度 | 允许空 | 默认值 | 说明 |
|---|---|---|---|---|---|
| id | bigint | 20 | 否 | - | 编号(主键) |
| user_id | bigint | 20 | 否 | - | 用户id |
| user_type | tinyint | 4 | 否 | - | 用户类型 |
| balance | int | 11 | 否 | 0 | 余额(单位分) |
| freeze_price | int | 11 | 否 | 0 | 冻结金额(单位分) |
| total_expense | int | 11 | 否 | 0 | 累计支出(单位分) |
| total_recharge | int | 11 | 否 | 0 | 累计充值(单位分) |
| creator | varchar | 64 | 是 | '' | 创建者 |
| create_time | datetime | - | 否 | CURRENT_TIMESTAMP | 创建时间 |
| updater | varchar | 64 | 是 | '' | 更新者 |
| update_time | datetime | - | 否 | CURRENT_TIMESTAMP | 更新时间 |
| deleted | bit | 1 | 否 | b'0' | 是否删除 |
2.12.2 索引
| 索引名 | 类型 | 字段 | 说明 |
|---|---|---|---|
| PRIMARY | 主键 | id | 主键索引 |
| uk_user_id_user_type | 唯一 | user_id, user_type | 用户唯一索引 |
2.12.3 Java 实体类
java
@TableName(value = "pay_wallet")
@KeySequence("pay_wallet_seq")
@Data
public class PayWalletDO extends BaseDO {
@TableId
private Long id;
private Long userId;
private Integer userType;
private Integer balance;
private Integer freezePrice;
private Integer totalExpense;
private Integer totalRecharge;
}2.13 钱包充值表 (pay_wallet_recharge)
钱包充值表用于管理钱包充值记录。
2.13.1 表结构
| 字段名 | 类型 | 长度 | 允许空 | 默认值 | 说明 |
|---|---|---|---|---|---|
| id | bigint | 20 | 否 | - | 编号(主键) |
| wallet_id | bigint | 20 | 否 | - | 钱包编号 |
| total_price | int | 11 | 否 | - | 用户实际到账余额 |
| pay_price | int | 11 | 否 | - | 实际支付金额 |
| bonus_price | int | 11 | 否 | 0 | 钱包赠送金额 |
| package_id | bigint | 20 | 是 | NULL | 充值套餐编号 |
| pay_status | bit | 1 | 否 | b'0' | 是否已支付 |
| pay_order_id | bigint | 20 | 是 | NULL | 支付订单编号 |
| pay_channel_code | varchar | 32 | 是 | NULL | 支付成功的支付渠道 |
| pay_time | datetime | - | 是 | NULL | 订单支付时间 |
| pay_refund_id | bigint | 20 | 是 | NULL | 支付退款单编号 |
| refund_total_price | int | 11 | 是 | NULL | 退款金额(包含赠送金额) |
| refund_pay_price | int | 11 | 是 | NULL | 退款支付金额 |
| refund_bonus_price | int | 11 | 是 | NULL | 退款钱包赠送金额 |
| refund_time | datetime | - | 是 | NULL | 退款时间 |
| refund_status | tinyint | 4 | 是 | NULL | 退款状态 |
| remark | varchar | 512 | 是 | NULL | 备注 |
| creator | varchar | 64 | 是 | '' | 创建者 |
| create_time | datetime | - | 否 | CURRENT_TIMESTAMP | 创建时间 |
| updater | varchar | 64 | 是 | '' | 更新者 |
| update_time | datetime | - | 否 | CURRENT_TIMESTAMP | 更新时间 |
| deleted | bit | 1 | 否 | b'0' | 是否删除 |
2.13.2 索引
| 索引名 | 类型 | 字段 | 说明 |
|---|---|---|---|
| PRIMARY | 主键 | id | 主键索引 |
| idx_wallet_id | 普通 | wallet_id | 钱包索引 |
2.13.3 Java 实体类
java
@TableName(value = "pay_wallet_recharge")
@KeySequence("pay_wallet_recharge_seq")
@Data
public class PayWalletRechargeDO extends BaseDO {
@TableId
private Long id;
private Long walletId;
private Integer totalPrice;
private Integer payPrice;
private Integer bonusPrice;
private Long packageId;
private Boolean payStatus;
private Long payOrderId;
private String payChannelCode;
private LocalDateTime payTime;
private Long payRefundId;
private Integer refundTotalPrice;
private Integer refundPayPrice;
private Integer refundBonusPrice;
private LocalDateTime refundTime;
private Integer refundStatus;
private String remark;
}2.14 钱包流水表 (pay_wallet_transaction)
钱包流水表用于记录钱包的交易流水。
2.14.1 表结构
| 字段名 | 类型 | 长度 | 允许空 | 默认值 | 说明 |
|---|---|---|---|---|---|
| id | bigint | 20 | 否 | - | 编号(主键) |
| no | varchar | 64 | 否 | - | 流水号 |
| wallet_id | bigint | 20 | 否 | - | 钱包编号 |
| biz_type | tinyint | 4 | 否 | - | 关联业务分类 |
| biz_id | varchar | 64 | 是 | NULL | 关联业务编号 |
| title | varchar | 128 | 是 | NULL | 流水说明 |
| price | int | 11 | 否 | - | 交易金额(单位分) |
| balance | int | 11 | 否 | - | 交易后余额(单位分) |
| creator | varchar | 64 | 是 | '' | 创建者 |
| create_time | datetime | - | 否 | CURRENT_TIMESTAMP | 创建时间 |
| updater | varchar | 64 | 是 | '' | 更新者 |
| update_time | datetime | - | 否 | CURRENT_TIMESTAMP | 更新时间 |
| deleted | bit | 1 | 否 | b'0' | 是否删除 |
2.14.2 索引
| 索引名 | 类型 | 字段 | 说明 |
|---|---|---|---|
| PRIMARY | 主键 | id | 主键索引 |
| uk_no | 唯一 | no | 流水号唯一索引 |
| idx_wallet_id | 普通 | wallet_id | 钱包索引 |
2.14.3 Java 实体类
java
@TableName(value = "pay_wallet_transaction")
@KeySequence("pay_wallet_transaction_seq")
@Data
public class PayWalletTransactionDO extends BaseDO {
@TableId
private Long id;
private String no;
private Long walletId;
private Integer bizType;
private String bizId;
private String title;
private Integer price;
private Integer balance;
}2.15 钱包充值套餐表 (pay_wallet_recharge_package)
钱包充值套餐表用于管理充值套餐信息。
2.15.1 表结构
| 字段名 | 类型 | 长度 | 允许空 | 默认值 | 说明 |
|---|---|---|---|---|---|
| id | bigint | 20 | 否 | - | 编号(主键) |
| name | varchar | 64 | 否 | - | 套餐名 |
| pay_price | int | 11 | 否 | - | 支付金额 |
| bonus_price | int | 11 | 否 | 0 | 赠送金额 |
| status | tinyint | 4 | 否 | - | 状态(0正常 1停用) |
| creator | varchar | 64 | 是 | '' | 创建者 |
| create_time | datetime | - | 否 | CURRENT_TIMESTAMP | 创建时间 |
| updater | varchar | 64 | 是 | '' | 更新者 |
| update_time | datetime | - | 否 | CURRENT_TIMESTAMP | 更新时间 |
| deleted | bit | 1 | 否 | b'0' | 是否删除 |
2.15.2 索引
| 索引名 | 类型 | 字段 | 说明 |
|---|---|---|---|
| PRIMARY | 主键 | id | 主键索引 |
2.15.3 Java 实体类
java
@TableName(value = "pay_wallet_recharge_package")
@KeySequence("pay_wallet_recharge_package_seq")
@Data
public class PayWalletRechargePackageDO extends BaseDO {
@TableId
private Long id;
private String name;
private Integer payPrice;
private Integer bonusPrice;
private Integer status;
}3. 表关系图
pay_app (支付应用表)
├── pay_channel (支付渠道表) - 通过 app_id 关联
├── pay_order (支付订单表) - 通过 app_id 关联
├── pay_refund (支付退款单表) - 通过 app_id 关联
├── pay_transfer (支付转账单表) - 通过 app_id 关联
└── pay_notify_task (支付通知任务表) - 通过 app_id 关联
pay_channel (支付渠道表)
├── pay_order (支付订单表) - 通过 channel_id 关联
├── pay_order_extension (支付订单拓展表) - 通过 channel_id 关联
├── pay_refund (支付退款单表) - 通过 channel_id 关联
└── pay_transfer (支付转账单表) - 通过 channel_id 关联
pay_order (支付订单表)
├── pay_order_extension (支付订单拓展表) - 通过 order_id 关联
├── pay_refund (支付退款单表) - 通过 order_id 关联
├── pay_profit_sharing_record (支付分账记录表) - 通过 pay_order_id 关联
└── pay_notify_task (支付通知任务表) - 通过 data_id 关联
pay_refund (支付退款单表)
└── pay_notify_task (支付通知任务表) - 通过 data_id 关联
pay_wallet (支付钱包表)
├── pay_wallet_recharge (钱包充值表) - 通过 wallet_id 关联
└── pay_wallet_transaction (钱包流水表) - 通过 wallet_id 关联
pay_notify_task (支付通知任务表)
└── pay_notify_log (支付通知日志表) - 通过 task_id 关联4. 使用示例
4.1 创建支付订单
java
@Service
public class PayOrderServiceImpl implements PayOrderService {
@Resource
private PayOrderMapper payOrderMapper;
@Resource
private PayOrderExtensionMapper payOrderExtensionMapper;
@Transactional(rollbackFor = Exception.class)
public Long createOrder(PayOrderCreateReqVO createReqVO) {
PayOrderDO order = PayOrderDO.builder()
.merchantId(createReqVO.getMerchantId())
.appId(createReqVO.getAppId())
.channelId(createReqVO.getChannelId())
.channelCode(createReqVO.getChannelCode())
.merchantOrderId(createReqVO.getMerchantOrderId())
.subject(createReqVO.getSubject())
.body(createReqVO.getBody())
.notifyUrl(createReqVO.getNotifyUrl())
.price(createReqVO.getPrice())
.status(PayOrderStatusEnum.UNPAID.getStatus())
.build();
payOrderMapper.insert(order);
PayOrderExtensionDO extension = PayOrderExtensionDO.builder()
.no(generateOrderNo())
.orderId(order.getId())
.channelId(createReqVO.getChannelId())
.channelCode(createReqVO.getChannelCode())
.userIp(createReqVO.getUserIp())
.status(PayOrderStatusEnum.UNPAID.getStatus())
.build();
payOrderExtensionMapper.insert(extension);
return order.getId();
}
}4.2 支付订单成功
java
@Service
public class PayOrderServiceImpl implements PayOrderService {
@Resource
private PayOrderMapper payOrderMapper;
@Resource
private PayOrderExtensionMapper payOrderExtensionMapper;
@Transactional(rollbackFor = Exception.class)
public void successOrder(Long orderId, String channelOrderNo, Map<String, Object> channelNotifyData) {
PayOrderDO order = payOrderMapper.selectById(orderId);
if (order == null) {
throw exception(ORDER_NOT_EXISTS);
}
PayOrderExtensionDO extension = payOrderExtensionMapper.selectOne(
new LambdaQueryWrapperX<PayOrderExtensionDO>()
.eq(PayOrderExtensionDO::getOrderId, orderId)
.orderByDesc(PayOrderExtensionDO::getId)
.last("LIMIT 1")
);
payOrderMapper.updateById(PayOrderDO.builder()
.id(orderId)
.status(PayOrderStatusEnum.SUCCESS.getStatus())
.successTime(LocalDateTime.now())
.extensionId(extension.getId())
.no(extension.getNo())
.channelOrderNo(channelOrderNo)
.payChannelInfo(channelNotifyData)
.build());
payOrderExtensionMapper.updateById(PayOrderExtensionDO.builder()
.id(extension.getId())
.status(PayOrderStatusEnum.SUCCESS.getStatus())
.channelNotifyData(JSON.toJSONString(channelNotifyData))
.build());
}
}4.3 创建退款订单
java
@Service
public class PayRefundServiceImpl implements PayRefundService {
@Resource
private PayRefundMapper payRefundMapper;
@Transactional(rollbackFor = Exception.class)
public Long createRefund(PayRefundCreateReqVO createReqVO) {
PayRefundDO refund = PayRefundDO.builder()
.no(generateRefundNo())
.appId(createReqVO.getAppId())
.channelId(createReqVO.getChannelId())
.channelCode(createReqVO.getChannelCode())
.orderId(createReqVO.getOrderId())
.orderNo(createReqVO.getOrderNo())
.merchantOrderId(createReqVO.getMerchantOrderId())
.merchantRefundId(createReqVO.getMerchantRefundId())
.notifyUrl(createReqVO.getNotifyUrl())
.status(PayRefundStatusEnum.CREATE.getStatus())
.payPrice(createReqVO.getPayPrice())
.refundPrice(createReqVO.getRefundPrice())
.reason(createReqVO.getReason())
.userIp(createReqVO.getUserIp())
.build();
payRefundMapper.insert(refund);
return refund.getId();
}
}4.4 退款成功
java
@Service
public class PayRefundServiceImpl implements PayRefundService {
@Resource
private PayRefundMapper payRefundMapper;
@Resource
private PayOrderMapper payOrderMapper;
@Transactional(rollbackFor = Exception.class)
public void successRefund(Long refundId, String channelRefundNo, String channelNotifyData) {
PayRefundDO refund = payRefundMapper.selectById(refundId);
if (refund == null) {
throw exception(REFUND_NOT_EXISTS);
}
payRefundMapper.updateById(PayRefundDO.builder()
.id(refundId)
.status(PayRefundStatusEnum.SUCCESS.getStatus())
.channelRefundNo(channelRefundNo)
.successTime(LocalDateTime.now())
.channelNotifyData(channelNotifyData)
.build());
payOrderMapper.updateById(PayOrderDO.builder()
.id(refund.getOrderId())
.refundPrice(refund.getRefundPrice())
.build());
}
}4.5 钱包充值
java
@Service
public class PayWalletServiceImpl implements PayWalletService {
@Resource
private PayWalletMapper payWalletMapper;
@Resource
private PayWalletRechargeMapper payWalletRechargeMapper;
@Resource
private PayWalletTransactionMapper payWalletTransactionMapper;
@Transactional(rollbackFor = Exception.class)
public void recharge(Long userId, Integer payPrice, Integer bonusPrice, Long packageId) {
PayWalletDO wallet = payWalletMapper.selectOne(
new LambdaQueryWrapperX<PayWalletDO>()
.eq(PayWalletDO::getUserId, userId)
.eq(PayWalletDO::getUserType, UserTypeEnum.MEMBER.getValue())
);
if (wallet == null) {
wallet = PayWalletDO.builder()
.userId(userId)
.userType(UserTypeEnum.MEMBER.getValue())
.balance(0)
.freezePrice(0)
.totalExpense(0)
.totalRecharge(0)
.build();
payWalletMapper.insert(wallet);
}
Integer totalPrice = payPrice + bonusPrice;
Integer balance = wallet.getBalance() + totalPrice;
payWalletMapper.updateById(PayWalletDO.builder()
.id(wallet.getId())
.balance(balance)
.totalRecharge(wallet.getTotalRecharge() + payPrice)
.build());
PayWalletRechargeDO recharge = PayWalletRechargeDO.builder()
.walletId(wallet.getId())
.totalPrice(totalPrice)
.payPrice(payPrice)
.bonusPrice(bonusPrice)
.packageId(packageId)
.payStatus(true)
.payTime(LocalDateTime.now())
.build();
payWalletRechargeMapper.insert(recharge);
PayWalletTransactionDO transaction = PayWalletTransactionDO.builder()
.no(generateTransactionNo())
.walletId(wallet.getId())
.bizType(PayWalletBizTypeEnum.RECHARGE.getType())
.bizId(recharge.getId().toString())
.title("钱包充值")
.price(totalPrice)
.balance(balance)
.build();
payWalletTransactionMapper.insert(transaction);
}
}5. 业务规则
5.1 支付订单状态流转
- 待支付 → 支付成功(用户支付成功)
- 待支付 → 支付关闭(超时未支付或用户取消)
5.2 退款订单状态流转
- 待退款 → 退款成功(退款成功)
- 待退款 → 退款失败(退款失败)
5.3 通知规则
- 通知频率:15s、15s、30s、180s、1800s、1800s、1800s、3600s
- 最大通知次数:9次
- 通知成功后不再重复通知
5.4 分账规则
- 分账在支付成功后进行
- 分账金额 = 支付金额 - 运费等不可分账金额
- 分账接收方需要提前配置
5.5 钱包规则
- 钱包余额不能为负数
- 充值可以赠送金额
- 所有交易都需要记录流水
6. 注意事项
- 商户订单号在每个应用下必须唯一
- 外部订单号必须全局唯一
- 支付订单状态变更时,需要同步更新订单拓展表
- 退款金额不能超过支付金额
- 通知任务需要定时任务处理
- 钱包充值需要记录流水
- 分账接收方需要提前配置
- 所有金额单位都是分
注意:本文档持续更新中,如有问题请及时反馈。
