heima的mq实战------2

惯例文档:

这个是一个方式的,失败的话发消息给失败的mq,然后去异步处理失败信息。

快速给第三方平台做响应。第三方支付平台返回支付结果之后直接给商家后台,商家后台然后直接调用响应同时发消息给mq做后续的处理。

---

我们先搞一个starter。

maven-install

要安装的工程在哪里?

代码在哪里?

springboot集成rocketmq的生产者。

在工程里面果然有:

第一步导入依赖:

第二步:配置配置文件

springboot集成rocketmq的生产者消费者代码:

---01-07---

同样下载springboot和dubbo整合的依赖包到本地的maven

还是要install游一下:

zookeeper集群的搭建:

上代码:

说明:服务的接口,服务的提供者实现接口提供服务,服务的消费者调用接口实现的服务。

第一步:加入依赖:

第二步:写配置文件

第三步:启动类

第四步:

zookeeper包括自己多余半数,收到的follower为半数就是一次消息成功。

服务的提供者。

管理平台得到搭建:

服务的消费方(web的方式)

第一步:

第二步:配置文件,根据服务的名称也就是接口的全类名找服务

第三步:

服务的提供者是dubbo要用dubbode注解

消费者:

---08-13---

创建数据库表:

表:优惠券表 商品表 订单表 订单商品日志表(订单和库存的操作) 用户表 用户余额日志表 订单支付表

MQ生产消息表 MQ消费消息表

工程:

---14-15---

mybatis的逆袭工程。

好好看下这个逆向工程。

第一步:

第二步:

第三步:

第四步:解决一个报错的问题:https://blog.csdn.net/qq_41525021/article/details/93048277

第五步:运行main方法。

---16---

公共类的作用:

为什么用雪花算法,要是分库分表的话两个数据库都是自增的话可能是一样的。

---17----

连接:https://www.bilibili.com/video/BV1RE411r75d?p=52

生成预订单。

---18---

lombok使用lock:https://www.cnblogs.com/yanguobin/p/11525584.html

开始编写逻辑了:

整个代码的逻辑结构:

第一步:先写接口

第二步:

zookeeper:

zookeeper://192.168.244.128:2181;zookeeper://192.168.244.129:2181;zookeeper://192.168.244.130:2181

rocketMQ:

rocketmq.name-server=192.168.244.128:9876;192.168.244.129:9876

mysql:

spring.datasource.url=jdbc:mysql://192.168.244.128:3306/trade?useUnicode=true&characterEncoding=utf8
spring.datasource.username=root
spring.datasource.password=123456

十分重要的知识点,真这个这个必须是原子成功就成功失败就都失败性质的。有异常在catch模块实现失败的补偿机制。

围绕这个展开:

1.校验订单

注意这里:

不可能是接口必须是一个实现类,spring扫描到这个接口就会调用一个实现类的。

---

生成预订单:

 /**
     * 生成预订单
     *
     * @param order
     * @return
     */
    private Long savePreOrder(TradeOrder order) {
        //1. 设置订单状态为不可见
        order.setOrderStatus(ShopCode.SHOP_ORDER_NO_CONFIRM.getCode());
        //2. 设置订单ID
        long orderId = idWorker.nextId();
        order.setOrderId(orderId);
        //3. 核算订单运费 看是不是满100包邮的
        BigDecimal shippingFee = calculateShippingFee(order.getOrderAmount());
        if(order.getShippingFee().compareTo(shippingFee)!=0){
            CastException.cast(ShopCode.SHOP_ORDER_SHIPPINGFEE_INVALID);
        }
        //4. 核算订单总金额是否合法
        BigDecimal orderAmount = order.getGoodsPrice().multiply(new BigDecimal(order.getGoodsNumber()));
        orderAmount.add(shippingFee);
        if(order.getOrderAmount().compareTo(orderAmount)!=0){
            CastException.cast(ShopCode.SHOP_ORDERAMOUNT_INVALID);
        }
        //5.判断用户是否使用余额getMoneyPaid这个字段是已经付的金额
        BigDecimal moneyPaid = order.getMoneyPaid();
        if(moneyPaid!=null){
            //5.1 订单中余额是否合法
            int r = moneyPaid.compareTo(BigDecimal.ZERO);
            //余额小于0
            if(r==-1){
                CastException.cast(ShopCode.SHOP_MONEY_PAID_LESS_ZERO);
            }
            //1表示余额大于0getUserMoney这个是余额 和用户余额比较不能大于
            if(r==1){
                TradeUser user = userService.findOne(order.getUserId());
                if(moneyPaid.compareTo(new BigDecimal(user.getUserMoney()))==1){
                    CastException.cast(ShopCode.SHOP_MONEY_PAID_INVALID);
                }
            }
        }else{
            order.setMoneyPaid(BigDecimal.ZERO);
        }
        //6.判断用户是否使用优惠券 这个就是一个订单只有一个优惠券
        Long couponId = order.getCouponId();
        if(couponId!=null){//优惠券是和用户绑定的优惠券
            TradeCoupon coupon = couponService.findOne(couponId);
            //6.1 判断优惠券是否存在
            if(coupon==null){
                CastException.cast(ShopCode.SHOP_COUPON_NO_EXIST);
            }
            //6.2 判断优惠券是否已经被使用
            if(coupon.getIsUsed().intValue()==ShopCode.SHOP_COUPON_ISUSED.getCode().intValue()){
                CastException.cast(ShopCode.SHOP_COUPON_ISUSED);
            }
            order.setCouponPaid(coupon.getCouponPrice());
        }else{
            order.setCouponPaid(BigDecimal.ZERO);
        }
        //7.核算订单支付金额    订单总金额-余额-优惠券金额
        BigDecimal payAmount = order.getOrderAmount().subtract(order.getMoneyPaid()).subtract(order.getCouponPaid());
        order.setPayAmount(payAmount);
        //8.设置下单时间
        order.setAddTime(new Date());
        //9.保存订单到数据库
        orderMapper.insert(order);
        //10.返回订单ID
        return orderId;
    }

这个是订单总价:

分库分表的全局唯一性要用到雪花算法的。

雪花算法。

实现第二步:

优惠券:

要用到了优惠券的接口了。

实现第三步:

这个其实是你买商品的数量

这个是你买了几个

知道哪个订单扣减了哪个商品的什么库存

调用商品的service:

服务端:https://www.bilibili.com/video/BV1RE411r75d?p=61

确实是减去了才会保存日志的。

---19-27---

扣减优惠券。

---28---

扣减余额

这个是重点的。

@Override
    public Result updateMoneyPaid(TradeUserMoneyLog userMoneyLog) {
        //1.校验参数是否合法
        if(userMoneyLog==null ||
                userMoneyLog.getUserId()==null ||
                userMoneyLog.getOrderId()==null ||
                userMoneyLog.getUseMoney()==null||
                userMoneyLog.getUseMoney().compareTo(BigDecimal.ZERO)<=0){
            CastException.cast(ShopCode.SHOP_REQUEST_PARAMETER_VALID);
        }
        //2.查询订单余额使用日志
        TradeUserMoneyLogExample userMoneyLogExample = new TradeUserMoneyLogExample();
        TradeUserMoneyLogExample.Criteria criteria = userMoneyLogExample.createCriteria();
        criteria.andOrderIdEqualTo(userMoneyLog.getOrderId());
        criteria.andUserIdEqualTo(userMoneyLog.getUserId());
        // 看下有没有日志 只有结束了 才会记录日志的
        int r = userMoneyLogMapper.countByExample(userMoneyLogExample);
        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_PAY);
            }
            //减余额
            tradeUser.setUserMoney(new BigDecimal(tradeUser.getUserMoney()).subtract(userMoneyLog.getUseMoney()).longValue());
            userMapper.updateByPrimaryKey(tradeUser);
        }
        //4.回退余额...
        if(userMoneyLog.getMoneyLogType().intValue()==ShopCode.SHOP_USER_MONEY_REFUND.getCode().intValue()){
            if(r<=0){
                //如果没有支付,则不能回退余额
                CastException.cast(ShopCode.SHOP_ORDER_PAY_STATUS_NO_PAY);
            }
            //防止多次退款
            TradeUserMoneyLogExample userMoneyLogExample2 = new TradeUserMoneyLogExample();
            TradeUserMoneyLogExample.Criteria criteria1 = userMoneyLogExample2.createCriteria();
            criteria1.andOrderIdEqualTo(userMoneyLog.getOrderId());
            criteria1.andUserIdEqualTo(userMoneyLog.getUserId());
            criteria1.andMoneyLogTypeEqualTo(ShopCode.SHOP_USER_MONEY_REFUND.getCode());
            int r2 = userMoneyLogMapper.countByExample(userMoneyLogExample2);
            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());
    }

付款才有用户金钱日志表。

mybatis用法:https://blog.csdn.net/u014756578/article/details/86490052

https://www.cnblogs.com/kangping/p/6001519.html

https://www.jianshu.com/p/44158fd09b6d

确认订单:

---29---30---

附录数据库表:

操作数量

---

传入订单不带优惠券金额的最后的金额是商品+运费的。

1.订单校验:订单是不是存在订单中商品是不是存在下单用户是不是存在单价是不是合法(订单的单价和商品的单价是不是一样),订单的数量是不是合法(和库存比较是不是超过了库存)

2.生成预订单:设置订单状态不可见设置订单id核算运费(包邮条件)

核算订单总的金额是不是合法的order.getOrderAmount(就是和运费的金额加之后的)

判断用户是不是使用余额付款是的话就和用户的余额进行比较(order.getMoneyPaid和user.getUserMoney比较),

判断用户是不是使用优惠券,订单里面更新优惠券金额,

核算最后的支付金额减去提货券金额的,这是除去余额需要支付的金额。order.getOrderAmount().subtract(order.getMoneyPaid()).subtract(order.getCouponPaid()),

插入订单。

3.扣减库存:用到商品订单日志(订单id,商品id,买的数量),先记录日志,扣减的是商品的库存,更新日志为负数买的数量。

4.扣减优惠券:原始的优惠券和用户绑定的。更新优惠券是已经使用,优惠券的订单id。

5.扣减用户余额:用到用户余额日志(订单id,商品id,日志类型,操作金额),先记录日志,接着进去更新余额的方法,如果传进来的是付款的日志则,查数据库如果之前存在了这个日志就是已经付款了,否则扣减余额。如果传进来是退款的日志,之前必须有付款的日志才可以,查询退款日志是不是已经付款,没退款就退款,更新日志。

---

测试:

启动微服务:

顺序:

order依赖userService。

 

 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值