一,目的
提供一个扩展比较好的,积分充值设计路,每个字段都经过多种场景进行考虑。由于文笔不好,以下以代码形式展示设计思路.
兼容多种业务场景
现金、银行、支付宝,微信支付等...
二,依赖模块
积分:https://www.jianshu.com/p/e0748147c6c6 [可以参考我之前写的 ,不过写得差,大继的基础级业务实战设计记录(一),积分],
银行,alipay,wechat
三,实战代码
1.现金请求
Cent beforeCent = centsRest.findTypeAndTypeId("WALLET","0");
if(beforeCent == null){
beforeCent.setNumber(0.0);
}
//正经一点需要一个 cash 模块。简化可用,只需要随机给个UUID
CentChargeRequest centChargeRequest = new CentChargeRequest();
centChargeRequest.setChargeNumber(100.0);
centChargeRequest.setFromType("cash");
centChargeRequest.setFromTypeId(UUID.randomUUID().toString());
centChargeRequest.setFromTypeIdName("test source");
centChargeRequest.setFromTradeNo(UUID.randomUUID().toString());
centChargeRequest.setSummary("充值测试");
centChargeRequest.setFromUserId(0L);
centChargeRequest.setCentType("WALLET");
centChargeRequest.setCentTypeId("0");
centChargeRequest.setFromResultCode("0");
centChargeRequest.setCentUserId(0L);
centsChargeRest.charge(centChargeRequest);
Cent afterCent = centsRest.findTypeAndTypeId("WALLET","0");
Assert.assertEquals(new Double(afterCent.getNumber() - 100.0),beforeCent.getNumber());
2.银行请求(注:此实现需要在业务级模块组合,不要让cent模块直接依赖bank模块)
Cent beforeCent = centsRest.findTypeAndTypeId("WALLET","0");
if(beforeCent == null){
beforeCent.setNumber(0.0);
}
/**
* 依赖bank 模块
*/
Bank bank = new Bank();
bank.setId(UUID.randomUUID().toString());
bank.setCreateTime(new Date());
bank.setEnable(true);
bank.setEnName("ICBC");
bank.setImage("image");
bank.setName("中国工商银行");
bank.setUpdateTime(new Date());
bank = banksRest.save(bank);
BankCard bankCard = new BankCard();
bankCard.setBankId(bank.getId());
bankCard.setBranchId(null);
bankCard.setBranchName("广州石牌支行");
bankCard.setCreateTime(new Date());
bankCard.setEnable(true);
bankCard.setId(UUID.randomUUID().toString());
bankCard.setMobile("+08615818733***");
bankCard.setRealName("大继");
bankCard.setType("储蓄卡");
bankCard.setNo("6222023602030330***");
bankCard.setUpdateTime(new Date());
bankCard.setUserId(0L);
bankCard = banksCardRest.save(bankCard);
//正经一点需要一个 cash 模块。简化可用,只需要随机给个UUID
CentChargeRequest centChargeRequest = new CentChargeRequest();
centChargeRequest.setChargeNumber(100.0);
centChargeRequest.setFromType("bankcard");
centChargeRequest.setFromTypeId(bankCard.getId());
centChargeRequest.setFromTypeIdName(bankCard.getRealName());
centChargeRequest.setFromTradeNo(UUID.randomUUID().toString());
//需要加入对bank name描述
centChargeRequest.setSummary("充值测试");
centChargeRequest.setFromUserId(0L);
centChargeRequest.setCentType("WALLET");
centChargeRequest.setCentTypeId("0");
centChargeRequest.setCentUserId(0L);
centChargeRequest.setFromResultCode("0");
centsChargeRest.charge(centChargeRequest);
Cent afterCent = centsRest.findTypeAndTypeId("WALLET","0");
Assert.assertEquals(new Double(afterCent.getNumber() - 100.0),beforeCent.getNumber());
3.其它可按上两个例子进行扩展
4.充值实体,及积分变更记录
- 改进了,之前设计过的积分设计
/**
* 积分充值
*/
@Entity
@Table(name = "cent_charge_log",
indexes = {@Index(columnList = "fromType,fromTradeNo",unique = true)})
public class CentChargeLog {
@Id
@Column(length = 37)
private String id;
/**
* 充值的积分账号
*/
@Column(length = 37)
private String centId;
/**
* 充值的积分类型
*/
@Column(length = 32)
private String centType;
/**
* 充值的积分类型ID
*/
@Column(length = 37)
private String centTypeId;
@Column
private Long centUserId;
/**
* 充值数量
*/
@Column
private Double number;
/**
* 充值来源,可以是微信,支付宝,银行等第三方,或本系统现金
*/
@Column(length = 64)
private String fromType;
/**
* 充值来源ID ,微信支付有openId,现金使用管理员ID,银行使用银行卡号
*/
@Column
private String fromTypeId;
/**
* 充值来源ID名称
*/
@Column
private String fromTypeIdName;
/**
* 充值来源交易号
* 需要事务保证唯一
*/
@Column(length = 64)
private String fromTradeNo;
/**
* 来源交易结果
*/
@Column
private String fromResultCode;
/**
* 所属于用户,需要对集合描述为空并用own进行描述
*/
@Column
private Long fromUserId;
/**
* 状态
*/
@Column(length = 16)
private String status;
/**
* 更新时间
*/
@Column
private Date updateTime;
/**
* 创建时间
*/
@Column
private Date createTime;
...
}
/**
* 单体积分变更记录。
* 所有积分账变化都需要记录到这个表。
* 满足可查性需求.
* 如A转账B,这里会产生两个记录。
*/
@Entity
@Table(name = "cent_changed_log",
indexes = {@Index(columnList = "centId"),@Index(columnList = "fromType,fromTypeId")})
public class CentChangedLog {
@Id
@Column(length = 37)
private String id;
/**
* 用设计简化,积分账号直接光联查询.
*/
@Column(length = 37)
private String centId;
/**
* 变更主体
* 用设计简化,直接使用积分类别查询.
*/
@Column(length = 37)
private String centType;
/**
* 变更主体
* 用设计简化,直接使用积分类别查询.
*/
@Column
private String centTypeId;
/**
* 变更描述
*/
@Column
private String summary;
/**
* 改变数量
* 变更点数 正数,或负数来表达加或减.
*/
@Column
private Double changedNumber;
/**
* 手续费
*/
@Column
private Double changedFee;
/**
* 原交易数
* 在需要手续费的情况下这个,原交易数来记录,支付全额
* 例如: 100 -> b 扣掉2元手费, 在changeNumber里会写 98, 这个original则保留原始的数据。便于查询.
*/
@Column
private Double changedOriginalNumber;
/**
* 变更后最终余额
*/
@Column
private Double changedLeftNumber;
/**
* 变更类型,
* 如果是转账积分号,充值等记录类型来源
*/
@Column(length = 32)
private String fromType;
/**
* 如果是充值就是充值 ID
*/
@Column(length = 37)
private String fromTypeId;
@Column
private String fromTypeIdName;
@Column
private Long fromUserId;
@Column
private Long userId;
/**
* 为以后特殊情况保留,正常都是 SUCCESS
*/
@Column
private String status;
@Column
private Date updateTime;
@Column
private Date createTime;
}