开发者学堂课程【RocketMQ 知识精讲与项目实战(第二阶段):更新余额2 】学习笔记,与课程紧密联系,让用户快速学习知识。
课程地址:https://developer.aliyun.com/learning/course/703/detail/12421
更新余额2
1.在进行代码实现之前,要分析先流程,在业务中包含两个子业务,扣减余额和回退余额,走流程时先判断当前请求参数是否合法,微服务中每次远程调用时,在微服务端都要做请求参数是否合法的判断。
2.在余额的使用日志中查询是否有余额使用的记录,查询该订单余额使用记录,根据当前提交的参数判断是使用余额还是扣减余额,如果已经查询到余额的使用记录,就说明当前订单已经支付,不需要再扣减余额,所以查询订单余额使用日志是为了下面步骤做判断使用,如果订单已经付款,余额不用扣减,如果没有付款,就去完成扣减余额的操作,如果余额在更新时,是回退余额,要判断订单是否完成付款,如果完成付款则需要回退余额,如果没有完成付款则不需要回退余额,判断要依据日志查询的结果。
3.已经完成付款,在退款时要进行判断,防止多次退款,退款只能退一次,就进行一次的退还金额操作,所以不管是扣减金额,还是回退金额,都会记录余额使用日志。
4.根据流程分析进行实现,在微服务端进行更新余额的业务,包含扣减余额和回退余额,对方法进行修改,把 reduce修改成 update,
@Component
@Service( interfaceClass = IUserService. class)
public class UserServiceImpl implements IUserService{
@Autowired
private TradeUserMapper userMapper;
@Autowired
private TradeUserMoneyLogMapper userMoneyLogMapper;
@Override
public TradeUser findOne(Long userId) {
if(userId==null){
CastException. cast( ShopCode . SHOP_REQUEST_ PARAMETER_ VALID) ;
}
return userMapper. selectByPrimaryKey(userId);
}
@Override
在微服务中提供操作用户日志的方法,操作用户的余额可能是减余额可能是加余额,做这个操作之前先判断参数是否合法,如果不合法不需要是不可以操作的
public Result updateMoneyPaid(
TradeUserMoneyLog
userMoneyLog
) {
//1.校验参数是否合法,是否满足需要
传递的用户是否为空,用户的 id,订单 id 不能为空,余额数量大于等于0,小于等于0参数都属于非法,如果有一个条件不满足直接抛异常
if( userMoneyLog==null
||
userMoneyLog. getUserId( )==null
||
userMoneyLog. getorderId( )==null
||
userMoneyLog. get
U
seMoney()==null
||
userMoneyLog. get
U
seMoney() . compareTo(BigDecimal.
ZERO)<=0)
{
CastException. cast( ShopCode . SHOP_REQUEST_ PARAMETER_ VALID);
}
//2.查询订单余额使用日志
根据条件做统计,针对订单操作日志,把结果先查询出来
TradeUserMoneyLogExample userMoneyLogExample =
new TradeUserMoneyLogExample();
TradeUserMoneyLogExample.Criteria criteria=
userMoneyLogExample . createCriteria();
criteria. andOrderIdEqualTo(
userMoneyLog.
get0rderId());
criteria. andUserIdEqualTo(
userMoneyLog
. getUserId());
查询出来做备用
int r = userMoneyLogMapper.countByExample
( userMoneyLogExample);
用户对象已经查询出来
根据用户id查询用户的对象
TradeUser tradeUser=userMapper.
selectByPrimaryKey(userMoneyLog.getUserId());
//3.扣减余额...
判断如果当前是扣减余额,那么就要对用户的余额做减操作if(userMoneyLog.getMoneyLogType().
intValue( )==ShopCode . SHOP_ USER_ MONEY_ PAID.
getCode( ). intValue())
}
if(r>0){
//已经付款,不用再进行减余额的操作
CastException. cast(ShopCode .SHOP_ ORDER_ PAY_ STATUS_ IS_ PАY);
}
更新余额,查询余额减去订单中的数据
//减余额
重新设置值,这个值等于原先设置的值减去要使用的余额,给 UserMoney 做更新操作tradeUser . setUserMoney(new BigDecimal(tradeUser.
getUserMoney()).subtract(userMoneyLog.getUseMoney()).
l
ongVa
l
ue());
userMapper . updateByPrimaryKey(tradeU
ser
);
}
在lUserService,java中修改Result
updateMoneyPaid(TradeUserMoneyLog userMoneyLog ;
//4.回退余额...
退款要做的是余额加的操作
if(userMoneyLog.getMoneyLogType().
intValue( )==ShopCode . SHOP_ USER_ MONEY_
REFUND
.
getCode( ). intValue())
}
判断如果r小于0,没有记录,说明这个订单没有完成付款,就没有使用过余额,没有办法退款,异常。
//如果没有支付,则不能回退余额
if(r<0){
CastException. cast(ShopCode . SHOP_ ORDER_ PAY_ STATUS_ NO_ PAY);
}
//防止多次退款
退款只能退一次,防止多次退款的操作。查询日志,如果日志中已经记录了一次已经退款的记录,那么就已经代表退过,无需再退款。
TradeUserMoneyLogExample userMoneyLogExample2 =
new TradeUserMoneyLogExample();
TradeUserMoneyLogExample . Criteria criteria1 =
userMoneyLogExample2. createCriteria();
criterial . andOrderIdEqualTo( userMoneyLog.
getOrderId());
criteria1. andUserIdEqualTo( userMoneyLog. getUserId());
criteria1. andMoneyLogTypeEqua1To(ShopCode.SHOP_ USER_ MONEY_ REFUND. getCode());
带条件查询日志表,如果现在有日志,就代表当前订单已经完成过退款
int r2 = userMoneyLogMapper . countByExample
(userMoneyLogExample2);
如果r2大于0,抛异常,提示已经退过款
if(r2>0)
{
CastException.cast(ShopCode.SHOP_USER_MONEY_REFUND_ ALREADY);
}
//
退款
tradeUser.setUserMoney(new BigDecimal(tradeUser.
getUserMoney()).add(userMoneyLog.getUseMoney()).longValue());
更新
userMapper . updateByPrimaryKey(tradeUser) ;
如果有日志,检查跟分析的流程是否一样
//5.记录订单余额使用日志
缺少时间
userMoneyLog . setCreateTime(new Date());
插入数据库
userMoneyLogMapper . insert(userMoneyLog);
返回return new Result(ShopCode.SHOP_SUCCESS.getSuccess(),
ShopCode.SHOP_ SUCCESS. getMessage());
}
}