推荐 Spring Boot/Cloud 视频:
本文主要基于 TCC-Transaction 1.2.3.3 正式版
1. 概述
本文分享 TCC 项目实战。以官方 Maven项目 tcc-transaction-http-sample 为例子( tcc-transaction-dubbo-sample 类似 )。
首先我们简单了解下这个项目。
首页 => 商品列表 => 确认支付页 => 支付结果页
使用账户余额 + 红包余额联合支付购买商品,并账户之间转账。
项目拆分三个子 Maven 项目:
- tcc-transaction-http-order :商城服务,提供商品和商品订单逻辑。
- tcc-transaction-http-capital :资金服务,提供账户余额逻辑。
- tcc-transaction-http-redpacket :红包服务,提供红包余额逻辑。
2. 实体结构
2.1 商城服务
- Shop,商店表。实体代码如下:
public class Shop {
/**
* 商店编号
*/
private long id;
/**
* 所有者用户编号
*/
private long ownerUserId;
}
- Product,商品表。实体代码如下:
public class Product implements Serializable {
/**
* 商品编号
*/
private long productId;
/**
* 商店编号
*/
private long shopId;
/**
* 商品名
*/
private String productName;
/**
* 单价
*/
private BigDecimal price;
}
- Order,订单表。实现代码如下:
public class Order implements Serializable {
private static final long serialVersionUID = -5908730245224893590L;
/**
* 订单编号
*/
private long id;
/**
* 支付( 下单 )用户编号
*/
private long payerUserId;
/**
* 收款( 商店拥有者 )用户编号
*/
private long payeeUserId;
/**
* 红包支付金额
*/
private BigDecimal redPacketPayAmount;
/**
* 账户余额支付金额
*/
private BigDecimal capitalPayAmount;
/**
* 订单状态
* - DRAFT :草稿
* - PAYING :支付中
* - CONFIRMED :支付成功
* - PAY_FAILED :支付失败
*/
private String status = "DRAFT";
/**
* 商户订单号,使用 UUID 生成
*/
private String merchantOrderNo;
/**
* 订单明细数组
* 非存储字段
*/
private List<OrderLine> orderLines = new ArrayList<OrderLine>();
}
- OrderLine,订单明细。实体代码如下:
public class OrderLine implements Serializable {
private static final long serialVersionUID = 2300754647209250837L;
/**
* 订单编号
*/
private long id;
/**
* 商品编号
*/
private long productId;
/**
* 数量
*/
private int quantity;
/**
* 单价
*/
private BigDecimal unitPrice;
}
业务逻辑:
下单时,插入订单状态为 “DRAFT” 的订单( Order )记录,并插入购买的商品订单明细( OrderLine )记录。支付时,更新订单状态为 “PAYING”。
- 订单支付成功,更新订单状态为 “CONFIRMED”。
- 订单支付失败,更新订单状体为 “PAY_FAILED”。
2.2 资金服务
关系较为简单,有两个实体:
- CapitalAccount,资金账户余额。实体代码如下:
public class CapitalAccount {
/**
* 账户编号
*/
private long id;
/**
* 用户编号
*/
private long userId;
/**
* 余额
*/
private BigDecimal balanceAmount;
}
- TradeOrder,交易订单表。实体代码如下:
public class TradeOrder {
/**
* 交易订单编号
*/
private long id;
/**
* 转出用户编号
*/
private long selfUserId;
/**
* 转入用户编号
*/
private long oppositeUserId;
/**
* 商户订单号
*/
private String merchantOrderNo;
/**
* 金额
*/
private BigDecimal amount;
/**
* 交易订单状态
* - DRAFT :草稿
* - CONFIRM :交易成功
* - CANCEL :交易取消
*/
private String status = "DRAFT";
}
业务逻辑:
订单支付支付中,插入交易订单状态为 “DRAFT” 的订单( TradeOrder )记录,并更新减少下单用户的资金账户余额。
- 订单支付成功,更新交易订单状态为 “CONFIRM”,并更新增加商店拥有用户的资金账户余额。
- 订单支付失败,更新交易订单状态为 “CANCEL”,并更新增加( 恢复 )下单用户的资金账户余额。
2.3 红包服务
关系较为简单,和资金服务 99.99% 相同,有两个实体:
- RedPacketAccount,红包账户余额。实体代码如下:
public class RedPacketAccount {
/**
* 账户编号
*/
private long id;
/**
* 用户编号
*/
private long userId;
/**
* 余额
*/
private BigDecimal balanceAmount;
}
- TradeOrder,交易订单表。实体代码如下:
public class TradeOrder {
/**
* 交易订单编号
*/
private long id;
/**
* 转出用户编号
*/
private long selfUserId;
/**
* 转入用户编号
*/
private long oppositeUserId;
/**
* 商户订单号
*/
private String merchantOrderNo;
/**
* 金额
*/
private BigDecimal amount;
/**
* 交易订单状态
* - DRAFT :草稿
* - CONFIRM :交易成功
* - CANCEL :交易取消
*/
private String status = "DRAFT";
}
业务逻辑:
订单支付支付中,插入交易订单状态为 “DRAFT” 的订单( TradeOrder )记录,并更新减少下单用户的红包账户余额。
- 订单支付成功,更新交易订单状态为 “CONFIRM”,并更新增加商店拥有用户的红包账户余额。
- 订单支付失败,更新交易订单状态为 “CANCEL”,并更新增加( 恢复 )下单用户的红包账户余额。
3. 服务调用
服务之间,通过 HTTP 进行调用。
红包服务和资金服务为商城服务提供调用( 以资金服务为例子 ):
- XML 配置如下