尚品汇-订单接口实现(四十)

目录:

(1)搭建service-order-client模块

(2)微服务之间用户信息传递

(3)在web-all模块中添加接口

(4)下订单

(1)搭建service-order-client模块

搭建过程同service-cart-client

pom.xml

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
   xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
   <modelVersion>4.0.0</modelVersion>
   <parent>
      <groupId>com.atguigu.gmall</groupId>
      <artifactId>service-client</artifactId>
      <version>1.0</version>
   </parent>

   <version>1.0</version>
   <artifactId>service-order-client</artifactId>
   <packaging>jar</packaging>
   <name>service-order-client</name>
   <description>service-order-client</description>

</project>

在service-order-client暴露接口

package com.atguigu.gmall.order.client;


@FeignClient(value = "service-order", fallback = OrderDegradeFeignClient.class)
public interface OrderFeignClient {
    @GetMapping("/api/order/auth/trade")
    Result<Map<String, Object>> trade();
}

package com.atguigu.gmall.order.client.impl;


@Component
public class OrderDegradeFeignClient implements OrderFeignClient {

    @Override
    public Result<Map<String, Object>> trade() {
        return Result.fail();
    }
}

(2)微服务之间用户信息传递

如上图:因为微服务之间并没有传递头文件 ,所以我们可以定义一个拦截器,每次微服务调用之前都先检查下头文件,将请求的头文件中的用户信息再放入到header中,再调用其他微服务即可。

在web-util中添加拦截器

package com.atguigu.gmall.common.interceptor;

import feign.RequestInterceptor;
import feign.RequestTemplate;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import javax.servlet.http.HttpServletRequest;

@Component
public class FeignInterceptor implements RequestInterceptor {

    public void apply(RequestTemplate requestTemplate){
            //  微服务远程调用使用feign ,feign 传递数据的时候,没有。
            ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
            HttpServletRequest request = attributes.getRequest();
            //  添加header 数据
            requestTemplate.header("userTempId", request.getHeader("userTempId"));
            requestTemplate.header("userId", request.getHeader("userId"));

    }

}

配置网关

|----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| - id : web-order uri : lb://web-all predicates : - Host=order.gmall.com - id : service-order uri : lb://service-order predicates : - Path=/*/order/** |

(3)在web-all模块中添加接口

<dependency >

<groupId >com.atguigu.gmall</groupId >

<artifactId >service-order-client</artifactId >

<version >1.0</version >

</dependency >

在web-all中添加控制器

package com.atguigu.gmall.all.controller;


@Controller
public class OrderController {

    @Autowired
    private OrderFeignClient orderFeignClient;

    /**
     * 确认订单
     * @param model
     * @return
     */
    @GetMapping("trade.html")
    public String trade(Model model) {
        Result<Map<String, Object>> result = orderFeignClient.trade();

        //addAllAttributes会把里面的map拆分成一个个键值对传过去
        model.addAllAttributes(result.getData());
        return "order/trade";
    }
}

跳转到结算页:

(4)下订单

下单功能分析:

  1. 保存单据前要做记录:验库存,验价格
  2. 保存单据: orderInfo orderDetail。
  3. 保存以后把购物车中的商品删除。{演示不删!}
  4. 重定向到支付页面。

实体类:OrderInfo

package com.atguigu.gmall.model.order;

import com.atguigu.gmall.model.activity.ActivityRule;
import com.atguigu.gmall.model.activity.CouponInfo;
import com.atguigu.gmall.model.base.BaseEntity;
import com.atguigu.gmall.model.enums.ActivityType;
import com.atguigu.gmall.model.enums.CouponType;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableName;
import com.fasterxml.jackson.annotation.JsonFormat;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import org.springframework.util.CollectionUtils;

import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

@Data
@ApiModel(description = "订单信息")
@TableName("order_info")
public class OrderInfo extends BaseEntity {
    private static final long serialVersionUID = 1L;

    @ApiModelProperty(value = "收货人")
    @TableField("consignee")
    private String consignee;

    @ApiModelProperty(value = "收件人电话")
    @TableField("consignee_tel")
    private String consigneeTel;

    @ApiModelProperty(value = "总金额")
    @TableField("total_amount")
    private BigDecimal totalAmount;

    @ApiModelProperty(value = "订单状态")
    @TableField("order_status")
    private String orderStatus;

    @ApiModelProperty(value = "用户id")
    @TableField("user_id")
    private Long userId;

    @ApiModelProperty(value = "付款方式")
    @TableField("payment_way")
    private String paymentWay;

    @ApiModelProperty(value = "送货地址")
    @TableField("delivery_address")
    private String deliveryAddress;

    @ApiModelProperty(value = "订单备注")
    @TableField("order_comment")
    private String orderComment;

    @ApiModelProperty(value = "订单交易编号(第三方支付用)")
    @TableField("out_trade_no")
    private String outTradeNo;

    @ApiModelProperty(value = "订单描述(第三方支付用)")
    @TableField("trade_body")
    private String tradeBody;

    @ApiModelProperty(value = "创建时间")
    @TableField("create_time")
    @JsonFormat(locale="zh", timezone="GMT+8", pattern="yyyy-MM-dd HH:mm:ss")
    private Date createTime;

    @ApiModelProperty(value = "失效时间")
    @TableField("expire_time")
    @JsonFormat(locale="zh", timezone="GMT+8", pattern="yyyy-MM-dd HH:mm:ss")
    private Date expireTime;

    @ApiModelProperty(value = "进度状态")
    @TableField("process_status")
    private String processStatus;

    @ApiModelProperty(value = "物流单编号")
    @TableField("tracking_no")
    private String trackingNo;

    @ApiModelProperty(value = "父订单编号")
    @TableField("parent_order_id")
    private Long parentOrderId;

    @ApiModelProperty(value = "图片路径")
    @TableField("img_url")
    private String imgUrl;

    @TableField(exist = false)
    private List<OrderDetail> orderDetailList;

    @TableField(exist = false)
    private String wareId;

    @ApiModelProperty(value = "地区")
    @TableField("province_id")
    private Long provinceId;

    @ApiModelProperty(value = "促销金额")
    @TableField("activity_reduce_amount")
    private BigDecimal activityReduceAmount;

    @ApiModelProperty(value = "优惠券")
    @TableField("coupon_amount")
    private BigDecimal couponAmount;

    @ApiModelProperty(value = "原价金额")
    @TableField("original_total_amount")
    private BigDecimal originalTotalAmount;

    @ApiModelProperty(value = "可退款日期(签收后30天)")
    @TableField("refundable_time")
    @JsonFormat(locale="zh", timezone="GMT+8", pattern="yyyy-MM-dd HH:mm:ss")
    private Date refundableTime;

    @ApiModelProperty(value = "运费")
    @TableField("feight_fee")
    private BigDecimal feightFee;

    @ApiModelProperty(value = "操作时间")
    @JsonFormat(locale="zh", timezone="GMT+8", pattern="yyyy-MM-dd HH:mm:ss")
    @TableField("operate_time")
    private Date operateTime;

    //  计算活动或者优惠劵的金额
    @TableField(exist = false)
    private List<OrderDetailVo> orderDetailVoList;

    @TableField(exist = false)
    private String orderStatusName;

    @TableField(exist = false)
    private CouponInfo couponInfo;

    // 计算总价格
    public void sumTotalAmount(){
        BigDecimal totalAmount = new BigDecimal("0");
        BigDecimal originalTotalAmount = new BigDecimal("0");
        BigDecimal couponAmount = new BigDecimal("0");
        //  减去优惠劵
        if(null != couponInfo) {
            couponAmount = couponAmount.add(couponInfo.getReduceAmount());
            totalAmount = totalAmount.subtract(couponInfo.getReduceAmount());
        }
        //  减去活动
        if(null != this.getActivityReduceAmount()) {
            totalAmount = totalAmount.subtract(this.getActivityReduceAmount());
        }
        //  计算最后
        for (OrderDetail orderDetail : orderDetailList) {
            BigDecimal skuTotalAmount = orderDetail.getOrderPrice().multiply(new BigDecimal(orderDetail.getSkuNum()));
            originalTotalAmount = originalTotalAmount.add(skuTotalAmount);
            totalAmount = totalAmount.add(skuTotalAmount);
        }
        this.setTotalAmount(totalAmount);
        this.setOriginalTotalAmount(originalTotalAmount);
        this.setCouponAmount(couponAmount);
    }

    /**
     * 获取促销优惠总金额
     * @param orderInfo
     * @return
     */
    public BigDecimal getActivityReduceAmount(OrderInfo orderInfo) {
        //促销优惠金额
        BigDecimal activityReduceAmount = new BigDecimal("0");
        List<OrderDetailVo> orderDetailVoList = orderInfo.getOrderDetailVoList();
        if(!CollectionUtils.isEmpty(orderDetailVoList)) {
            for(OrderDetailVo orderDetailVo : orderDetailVoList) {
                ActivityRule activityRule = orderDetailVo.getActivityRule();
                if(null != activityRule) {
                    activityReduceAmount = activityReduceAmount.add(activityRule.getReduceAmount());
                }
            }
        }
        return activityReduceAmount;
    }
    /**
     * 计算购物项分摊的优惠减少金额
     * 打折:按折扣分担
     * 现金:按比例分摊
     * @param orderInfo
     * @return
     */
    public Map<String, BigDecimal> computeOrderDetailPayAmount(OrderInfo orderInfo) {
        Map<String, BigDecimal> skuIdToReduceAmountMap = new HashMap<>();
        //  获取到订单明细
        List<OrderDetailVo> orderDetailVoList = orderInfo.getOrderDetailVoList();
        if (!CollectionUtils.isEmpty(orderDetailVoList)) {
            for (OrderDetailVo orderDetailVo : orderDetailVoList) {
                //  获取到活动的规则
                ActivityRule activityRule = orderDetailVo.getActivityRule();
                List<OrderDetail> orderDetailList = orderDetailVo.getOrderDetailList();
                if (null != activityRule) {
                    //  key = activity:skuId
                    //优惠金额, 按比例分摊
                    BigDecimal reduceAmount = activityRule.getReduceAmount();
                    if (orderDetailList.size() == 1) {
                        //  记录活动的减少的金额
                        skuIdToReduceAmountMap.put("activity:" + orderDetailList.get(0).getSkuId(), reduceAmount);
                    } else {
                        // 总金额
                        BigDecimal originalTotalAmount = new BigDecimal(0);
                        for (OrderDetail orderDetail : orderDetailList) {
                            BigDecimal skuTotalAmount = orderDetail.getOrderPrice().multiply(new BigDecimal(orderDetail.getSkuNum()));
                            originalTotalAmount = originalTotalAmount.add(skuTotalAmount);
                        }
                        //  记录除最后一项是所有分摊金额, 最后一项 = 总的 - skuPartReduceAmount
                        //  三项  100 一项 33.33 二项 33.33 第三项 100-66.66 = 33.34
                        BigDecimal skuPartReduceAmount = new BigDecimal(0);
                        //  促销活动对应的是满减!
                        if (activityRule.getActivityType().equals(ActivityType.FULL_REDUCTION.name())) {
                            for (int i = 0, len = orderDetailList.size(); i < len; i++) {
                                OrderDetail orderDetail = orderDetailList.get(i);
                                //  最后一项前面一项应该如何做
                                if (i < len - 1) {
                                    BigDecimal skuTotalAmount = orderDetail.getOrderPrice().multiply(new BigDecimal(orderDetail.getSkuNum()));
                                    //sku分摊金额  skuTotalAmount/originalTotalAmount * 优惠的金额
                                    BigDecimal skuReduceAmount = skuTotalAmount.divide(originalTotalAmount, 2, RoundingMode.HALF_UP).multiply(reduceAmount);
                                    skuIdToReduceAmountMap.put("activity:" + orderDetail.getSkuId(), skuReduceAmount);

                                    skuPartReduceAmount = skuPartReduceAmount.add(skuReduceAmount);
                                } else {
                                    //  最后一项
                                    BigDecimal skuReduceAmount = reduceAmount.subtract(skuPartReduceAmount);
                                    skuIdToReduceAmountMap.put("activity:" + orderDetail.getSkuId(), skuReduceAmount);
                                }
                            }
                        } else {
                            //  满量打折
                            for (int i = 0, len = orderDetailList.size(); i < len; i++) {
                                OrderDetail orderDetail = orderDetailList.get(i);
                                if (i < len - 1) {
                                    BigDecimal skuTotalAmount = orderDetail.getOrderPrice().multiply(new BigDecimal(orderDetail.getSkuNum()));
                                    //sku分摊金额
                                    BigDecimal skuDiscountTotalAmount = skuTotalAmount.multiply(activityRule.getBenefitDiscount().divide(new BigDecimal("10")));
                                    BigDecimal skuReduceAmount = skuTotalAmount.subtract(skuDiscountTotalAmount);
                                    skuIdToReduceAmountMap.put("activity:" + orderDetail.getSkuId(), skuReduceAmount);

                                    skuPartReduceAmount = skuPartReduceAmount.add(skuReduceAmount);
                                } else {
                                    BigDecimal skuReduceAmount = reduceAmount.subtract(skuPartReduceAmount);
                                    skuIdToReduceAmountMap.put("activity:" + orderDetail.getSkuId(), skuReduceAmount);
                                }
                            }
                        }
                    }
                }
            }
        }
        //  计算优惠券
        CouponInfo couponInfo = orderInfo.getCouponInfo();
        if (null != couponInfo) {
            //sku对应的订单明细
            Map<Long, OrderDetail> skuIdToOrderDetailMap = new HashMap<>();
            for (OrderDetail orderDetail : orderInfo.getOrderDetailList()) {
                skuIdToOrderDetailMap.put(orderDetail.getSkuId(), orderDetail);
            }
            // 优惠券对应的skuId列表
            List<Long> skuIdList = couponInfo.getSkuIdList();
            // 优惠券优惠总金额
            BigDecimal reduceAmount = couponInfo.getReduceAmount();
            if (skuIdList.size() == 1) {
                // sku总的优惠金额 = 优惠券 key = "coupon:skuId"
                skuIdToReduceAmountMap.put("coupon:" + skuIdToOrderDetailMap.get(skuIdList.get(0)).getSkuId(), reduceAmount);
            } else {
                //总金额
                BigDecimal originalTotalAmount = new BigDecimal(0);
                for (Long skuId : skuIdList) {
                    OrderDetail orderDetail = skuIdToOrderDetailMap.get(skuId);
                    BigDecimal skuTotalAmount = orderDetail.getOrderPrice().multiply(new BigDecimal(orderDetail.getSkuNum()));
                    originalTotalAmount = originalTotalAmount.add(skuTotalAmount);
                }
                // 记录除最后一项是所有分摊金额, 最后一项 = 总的 - skuPartReduceAmount
                BigDecimal skuPartReduceAmount = new BigDecimal(0);
                // 购物券类型 1 现金券 2 折扣券 3 满减券 4 满件打折券
                if (couponInfo.getCouponType().equals(CouponType.CASH.name()) || couponInfo.getCouponType().equals(CouponType.FULL_REDUCTION.name())) {
                    for (int i = 0, len = skuIdList.size(); i < len; i++) {
                        OrderDetail orderDetail = skuIdToOrderDetailMap.get(skuIdList.get(i));
                        if (i < len - 1) {
                            BigDecimal skuTotalAmount = orderDetail.getOrderPrice().multiply(new BigDecimal(orderDetail.getSkuNum()));
                            //sku分摊金额
                            BigDecimal skuReduceAmount = skuTotalAmount.divide(originalTotalAmount, 2, RoundingMode.HALF_UP).multiply(reduceAmount);
                            skuIdToReduceAmountMap.put("coupon:" + orderDetail.getSkuId(), skuReduceAmount);

                            skuPartReduceAmount = skuPartReduceAmount.add(skuReduceAmount);
                        } else {
                            BigDecimal skuReduceAmount = reduceAmount.subtract(skuPartReduceAmount);
                            skuIdToReduceAmountMap.put("coupon:" + orderDetail.getSkuId(), skuReduceAmount);
                        }
                    }
                } else {
                    //  对应的2,4
                    for (int i = 0, len = skuIdList.size(); i < len; i++) {
                        OrderDetail orderDetail = skuIdToOrderDetailMap.get(skuIdList.get(i));
                        if (i < len - 1) {
                            BigDecimal skuTotalAmount = orderDetail.getOrderPrice().multiply(new BigDecimal(orderDetail.getSkuNum()));
                            BigDecimal skuDiscountTotalAmount = skuTotalAmount.multiply(couponInfo.getBenefitDiscount().divide(new BigDecimal("10")));
                            BigDecimal skuReduceAmount = skuTotalAmount.subtract(skuDiscountTotalAmount);
                            //sku分摊金额
                            skuIdToReduceAmountMap.put("coupon:" + orderDetail.getSkuId(), skuReduceAmount);

                            skuPartReduceAmount = skuPartReduceAmount.add(skuReduceAmount);
                        } else {
                            BigDecimal skuReduceAmount = reduceAmount.subtract(skuPartReduceAmount);
                            skuIdToReduceAmountMap.put("coupon:" + orderDetail.getSkuId(), skuReduceAmount);
                        }
                    }
                }
            }
        }
        return skuIdToReduceAmountMap;
    }
}

添加mapper

package com.atguigu.gmall.order.mapper;


@Mapper
public interface OrderInfoMapper extends BaseMapper<OrderInfo> {

}

package com.atguigu.gmall.order.mapper;


@Mapper
public interface OrderDetailMapper extends BaseMapper<OrderDetail> {
}

添加接口OrderService :

package com.atguigu.gmall.order.service;

public interface OrderService extends IService<OrderInfo> {

    /**
     * 保存订单
     * @param orderInfo
     * @return
     */
    Long saveOrderInfo(OrderInfo orderInfo);
}

实现类:

package com.atguigu.gmall.order.service.impl;


@Service
public class OrderServiceImpl extends ServiceImpl<OrderInfoMapper, OrderInfo> implements OrderService {

    @Autowired
    private OrderInfoMapper orderInfoMapper;

    @Autowired
    private OrderDetailMapper orderDetailMapper;

@Override
@Transactional
public Long saveOrderInfo(OrderInfo orderInfo) {
    //调用里面的方法获取总金额
    orderInfo.sumTotalAmount();
    //订单状态
    orderInfo.setOrderStatus(OrderStatus.UNPAID.name());

    //付款方式  在线支付写死了
     orderInfo.setPaymentWay(PaymentWay.ONLINE.name());
    
    String outTradeNo = "ATGUIGU" + System.currentTimeMillis() + "" + new Random().nextInt(1000);
    //订单交易号
    orderInfo.setOutTradeNo(outTradeNo);
    //创建时间,不写也没事数据库自动添加
    orderInfo.setCreateTime(new Date());
    // 失效时间,定义为1天
    Calendar calendar = Calendar.getInstance();
    calendar.add(Calendar.DATE, 1);
    orderInfo.setExpireTime(calendar.getTime());

   //进度状态
    orderInfo.setProcessStatus(ProcessStatus.UNPAID.name());
       
    //订单描述   
     // 获取订单明细
       List<OrderDetail> orderDetailList = orderInfo.getOrderDetailList();
    StringBuffer tradeBody = new StringBuffer();
    for (OrderDetail orderDetail : orderDetailList) {
        tradeBody.append(orderDetail.getSkuName()+" ");
    }
    //如果订单描述长度大于100进行截取
    if (tradeBody.toString().length()>100){
        orderInfo.setTradeBody(tradeBody.toString().substring(0,100));
    }else {
        orderInfo.setTradeBody(tradeBody.toString());
    }

    //保存订单
    orderInfoMapper.insert(orderInfo);

    for (OrderDetail orderDetail : orderDetailList) {
        //设置订单id
        orderDetail.setOrderId(orderInfo.getId());
        //保存订单明细
        orderDetailMapper.insert(orderDetail);  
    }
    return orderInfo.getId();
  }
}

继续编写控制器:在OrderApiController:

@Autowired
private OrderService orderService;
/**
     * 提交订单
     * @param orderInfo
     * @param request
     * @return
     */
    @PostMapping("auth/submitOrder")
    public Result submitOrder(@RequestBody OrderInfo orderInfo, HttpServletRequest request) {
        // 获取到用户Id
        String userId = AuthContextHolder.getUserId(request);
        orderInfo.setUserId(Long.parseLong(userId));

        // 验证通过,保存订单!
        Long orderId = orderService.saveOrderInfo(orderInfo);
        return Result.ok(orderId);
    }

订单表多了一条数据:

相关推荐
Monly21几秒前
Java(若依):修改Tomcat的版本
java·开发语言·tomcat
Ttang232 分钟前
Tomcat原理(6)——tomcat完整实现
java·tomcat
钱多多_qdd13 分钟前
spring cache源码解析(四)——从@EnableCaching开始来阅读源码
java·spring boot·spring
waicsdn_haha15 分钟前
Java/JDK下载、安装及环境配置超详细教程【Windows10、macOS和Linux图文详解】
java·运维·服务器·开发语言·windows·后端·jdk
Q_192849990625 分钟前
基于Spring Boot的摄影器材租赁回收系统
java·spring boot·后端
Code_流苏28 分钟前
VSCode搭建Java开发环境 2024保姆级安装教程(Java环境搭建+VSCode安装+运行测试+背景图设置)
java·ide·vscode·搭建·java开发环境
禁默1 小时前
深入浅出:AWT的基本组件及其应用
java·开发语言·界面编程
Cachel wood1 小时前
python round四舍五入和decimal库精确四舍五入
java·linux·前端·数据库·vue.js·python·前端框架
Code哈哈笑1 小时前
【Java 学习】深度剖析Java多态:从向上转型到向下转型,解锁动态绑定的奥秘,让代码更优雅灵活
java·开发语言·学习
gb42152871 小时前
springboot中Jackson库和jsonpath库的区别和联系。
java·spring boot·后端