订单支付(头歌)

第1关:订单支付

任务描述

本关任务:实现订单支付功能。

相关知识

为了完成本关任务,你需要掌握:

  1. 订单支付;
  2. 功能实现。
订单支付

购物网站中查看的订单如下:可以看到这是一个未付款的订单。

当我们点击立即付款时,前端会请求服务器,服务器会调用支付接口,这时我们就可以使用支付宝或者微信进行扫码支付了。

功能实现

以下是 springboot + mybatis + redis 模拟实现支付也就是修改订单状态及用户余额扣款及销售数量的过程。

  1. dao 层: OrderDao:查询当前订单及修改订单状态。
     
      
    1. /*付款,修改订单状态*/
    2. @Update("update orders set pay_time=now(),pay_status=1 where user_id=#{user_id} and order_id=#{order_id}")
    3. int orderPay(Integer user_id, Long order_id);
    4. /*查询一个订单*/
    5. @Select("select * from orders where order_id=#{order_id}")
    6. List<Order> getOrders(Long order_id);
    UserDao:查询数据库中用户余额及修改数据库中用户余额。
     
      
    1. //查询用户的余额
    2. @Select("select deposit from users where user_id=#{user_id}")
    3. BigDecimal findUserDeposit(int user_id);
    4. //修改用户余额
    5. @Update("update users set deposit=#{deposit} where user_id=#{user_id}")
    6. int editUserDeposit(BigDecimal deposit,int user_id);
  2. service 层: 定义 service 支付接口:
     
      
    1. /*定义 service 的支付接口*/
    2. int orderPay(Integer user_id, Long order_id);
  3. impl 实现类: 计算订单总金额并对用户余额进行扣款,并根据扣款的结果返回结果 true 或者 false。
     
      
    1. /**
    2. * 用户扣款
    3. * @param user_id
    4. * @return
    5. */
    6. public boolean deduction(List<Order> orders,Integer user_id){
    7. //初始化订单的总金额
    8. BigDecimal sumMoney=new BigDecimal("0");
    9. for (Order order:orders){
    10. //循环累加总金额
    11. sumMoney=sumMoney.add(order.getProduct_price());
    12. }
    13. //查询用户存款
    14. BigDecimal userDeposit=userDao.findUserDeposit(user_id);
    15. //空值判断
    16. if (sumMoney==null||userDeposit==null){
    17. return false;
    18. }
    19. //用户存款与消费金额比较
    20. if (userDeposit.compareTo(sumMoney)<1){
    21. //余额不足
    22. return false;
    23. }else {
    24. //余额计算
    25. userDeposit=userDeposit.subtract(sumMoney);
    26. //修改用户余额
    27. int row=userDao.editUserDeposit(userDeposit,user_id);
    28. //通过判断受影响行数来判断是否修改成功
    29. if (row==1){
    30. return true;
    31. }
    32. return false;
    33. }
    34. }
    如果扣款成功就修改销售数量:从 redis 中取出销售数量的 map 集合,将订单中的商品数量累加至 map 集合中并存入 redis;再修改订单状态。
     
      
    1. /**
    2. * 订单支付成功修改订单状态,redis 缓存
    3. * @param user_id
    4. * @param order_id
    5. * @return
    6. */
    7. public int editOrder(List<Order> orders,Integer user_id, Long order_id){
    8. //从 redis 中去销售数量集合 sales_num,key=商品id,value=商品销售数量
    9. Map<Object, Object> sales_num = redisTemplate.opsForHash().entries("sales_num");
    10. //循环当前订单所有内容
    11. for(Order order:orders){
    12. //订单中的商品的 id
    13. int product_id = order.getProduct_id();
    14. //订单中的商品的数量
    15. int product_num = order.getProduct_num();
    16. //非空判断
    17. if(sales_num.isEmpty()||sales_num.get(product_id+"")==null){
    18. //如果订单集合中没有该商品信息就存入订单集合 sales_num
    19. sales_num.put(product_id+"",product_num);
    20. }else{
    21. //如果订单集合中有该商品信息就重新取出来并计算销售数量存入订单集合 sales_num
    22. sales_num.put(product_id+"",(int)sales_num.get(product_id+"")+product_num);
    23. }
    24. //集合存入 redis
    25. redisTemplate.opsForHash().putAll("sales_num",sales_num);
    26. }
    27. //调用 dao 层支付方法并返回结果集
    28. return orderDao.orderPay(user_id,order_id);
    29. }
    30. }
  4. controller 层执行后返回执行结果,RespBeanEnum是自定义的枚举类。
     
      
    1. int excute = orderService.orderPay(user_id, order_id);
    2. if(excute>0){
    3. //支付执行成功,返回 RespBeanEnum 类的支付成功结果
    4. return RespBeanEnum.PAY_SUCCESS.getMap();
    5. }else{
    6. //支付执行失败,返回 RespBeanEnum 类的支付失败结果
    7. return RespBeanEnum.PAY_ERROR.getMap();
    8. }
  5. 数据库结构: 订单表:
    字段名称类型备注
    idint(11)NOT NULL AUTO_INCREMENT'购物车id'
    user_idint(11)NOT NULL'用户id'
    product_idint(11)NOT NULL'商品id'
    product_numint(11)NOT NULL'商品数量'
    product_pricedecimal(10,0)NOT NULL'商品价格'
    order_timedatetimeNOT NULL'订单创建时间'
    order_idbigint(20)NOT NULL'订单编号'
    pay_timedatetimeNOT NULL'付款时间'
    pay_statusint(2)NOT NULL'0为未付款,1为已付款'
    statusint(11)NOT NULL'0为失效,1为生效'
    用户表
    字段名称类型备注约束
    user_idint(11)权限id主键,自增
    userNamevarchar(20)用户名
    passwordvarchar(40)密码
    userPhoneNumberbigint(11)电话号码
    emailvarchar(20)邮箱
    genderchar(2)性别
    saltvarchar(20)加密盐值
    login_countint(11)登录次数
    register_timedatetime注册时间

编程要求

在右侧编辑器 OrderDao.java、UserDao.java、OrderService.java、OrderServiceImpl.java、OrderController.java 文件里 Begin-End 处根据提示补充代码。

测试说明

平台会对你编写的代码进行测试:运行项目后发送请求访问并检验结果集是否正确。

测试输入:

 
  1. {
  2. "user_id":"1018",
  3. "order_id":"1631456416541"
  4. }

预期输出:

 
  1. {"msg":"付款成功","code":"001"}

开始你的任务吧,祝你成功!

OrderDao.java
package com.www.dao;

import com.www.entity.Order;

import org.apache.ibatis.annotations.Select;
import org.apache.ibatis.annotations.Update;
import org.springframework.stereotype.Repository;

import java.util.List;


@Repository
public interface OrderDao {
 /*付款,修改订单状态*/  
 @Update("update orders set pay_time=now(),pay_status=1 where user_id=#{user_id} and order_id=#{order_id}")  
 int orderPay(Integer user_id, Long order_id);  
 /*查询一个订单*/  
 @Select("select * from orders where order_id=#{order_id}")  
 List<Order> getOrders(Long order_id);   
}
UserDao.java
package com.www.dao;

import org.apache.ibatis.annotations.Select;
import org.apache.ibatis.annotations.Update;
import org.springframework.stereotype.Repository;

import java.math.BigDecimal;

@Repository
public interface UserDao {
 //查询用户的余额  
 @Select("select deposit from users where user_id=#{user_id}")  
 BigDecimal findUserDeposit(int user_id);  
 //修改用户余额  
 @Update("update users set deposit=#{deposit} where user_id=#{user_id}")  
 int editUserDeposit(BigDecimal deposit,int user_id); 

}
OrderService.java
package com.www.service;



import org.springframework.stereotype.Component;


@Component
public interface OrderService {
  /*定义 service 的支付接口*/  
  int orderPay(Integer user_id, Long order_id); 
}
OrderServiceImpl.java
package com.www.service.impl;

import com.www.dao.OrderDao;
import com.www.dao.UserDao;
import com.www.entity.Order;
import com.www.service.OrderService;
import org.springframework.beans.factory.annotation.Autowired;

import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;

import java.math.BigDecimal;
import java.util.List;
import java.util.Map;


@Service("orderService")
public class OrderServiceImpl implements OrderService {

    @Autowired
    private OrderDao orderDao;
    @Autowired
    private UserDao userDao;
    @Autowired
    RedisTemplate redisTemplate;

    /**
     * 订单支付
     * @param user_id
     * @param order_id
     * @return
     */
    @Override
    public int orderPay(Integer user_id, Long order_id) {
        /*********************Begin*********************/
        //查询当前订单的所有订单内容,一个订单有很多个商品
        //判断金额计算是否执行成功
           //返回修改订单信息的执行结果
    //查询当前订单的所有订单内容,一个订单有很多个商品
    List<Order> orders = orderDao.getOrders(order_id);
    //判断金额计算是否执行成功
    if(deduction(orders, user_id)){
        //返回修改订单信息的执行结果
        return editOrder(orders, user_id, order_id);
    }else{
        //支付失败
        return 0;
    }
        /*********************End*********************/
    }

    /**
     * 用户扣款
     * @param user_id
     * @return
     */
    public  boolean deduction(List<Order> orders,Integer user_id){
    //初始化订单的总金额  
     BigDecimal sumMoney=new BigDecimal("0");  
     for (Order order:orders){  
         //循环累加总金额  
         sumMoney=sumMoney.add(order.getProduct_price());  
     }  
     //查询用户存款  
     BigDecimal userDeposit=userDao.findUserDeposit(user_id);  
     //空值判断  
     if (sumMoney==null||userDeposit==null){  
         return false;  
     }  
     //用户存款与消费金额比较  
     if (userDeposit.compareTo(sumMoney)<1){  
         //余额不足  
         return false;  
     }else {  
         //余额计算  
         userDeposit=userDeposit.subtract(sumMoney);  
         //修改用户余额  
         int row=userDao.editUserDeposit(userDeposit,user_id);  
         //通过判断受影响行数来判断是否修改成功  
         if (row==1){  
             return true;  
         }  
         return false;  
     }  
    }

    /**
     * 订单支付成功修改订单状态,redis 缓存
     * @param user_id
     * @param order_id
     * @return
     */
    public int editOrder(List<Order> orders,Integer user_id, Long order_id){
     //从 redis 中去销售数量集合 sales_num,key=商品id,value=商品销售数量  
     Map<Object, Object> sales_num = redisTemplate.opsForHash().entries("sales_num");  
     //循环当前订单所有内容  
     for(Order order:orders){  
         //订单中的商品的 id  
         int product_id = order.getProduct_id();  
         //订单中的商品的数量  
         int product_num = order.getProduct_num();  
         //非空判断  
         if(sales_num.isEmpty()||sales_num.get(product_id+"")==null){  
             //如果订单集合中没有该商品信息就存入订单集合 sales_num  
             sales_num.put(product_id+"",product_num);  
         }else{  
             //如果订单集合中有该商品信息就重新取出来并计算销售数量存入订单集合 sales_num  
             sales_num.put(product_id+"",(int)sales_num.get(product_id+"")+product_num);  
         }  
         //集合存入 redis  
         redisTemplate.opsForHash().putAll("sales_num",sales_num);  
     }  
     //调用 dao 层支付方法并返回结果集  
     return orderDao.orderPay(user_id,order_id);  
  }  
}
OrderController.java
package com.www.controller;


import com.www.service.OrderService;
import com.www.vo.RespBeanEnum;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import java.util.Map;


@RestController
@RequestMapping(value = "/order")
public class OrderController {

    @Autowired
    private OrderService orderService;


    /**
     * 订单支付,其实就是修改订单状态
     * @param paramMap
     * @return
     */
    @RequestMapping(value = "/orderPay")
    public Map orderPay(@RequestBody Map<String,Object> paramMap){
        //获取用户 id:user_id
        Integer user_id=1018 ;
        // 获取订单 id: order_id
        Long order_id=1631456416541L ;
        //调用 service 层的订单支付方法并判断是否执行成功
        int excute = orderService.orderPay(user_id, order_id);  
        if(excute>0){  
         //支付执行成功,返回 RespBeanEnum 类的支付成功结果  
         return RespBeanEnum.PAY_SUCCESS.getMap();  
        }else{  
         //支付执行失败,返回 RespBeanEnum 类的支付失败结果  
         return RespBeanEnum.PAY_ERROR.getMap();  
     }            
    }
}
Order.java
package com.www.entity;

import lombok.Data;

import java.io.Serializable;
import java.math.BigDecimal;
import java.util.Date;


@Data
public class Order implements Serializable {

    private Long id;
    private Long order_id;
    private int product_num;
    private int product_id;
    private BigDecimal product_price;
    private Date order_time;
    private Date pay_time;
    private int status;   //0,失效;1,生效
    private String product_name;
    private String product_picture;

}
User.java
package com.www.entity;

import lombok.Data;
import org.springframework.stereotype.Component;

import java.io.Serializable;

/**
 * @author liuxianchun
 * @date 2021/1/17
 * 用户
 */
@Data
@Component
public class User implements Serializable {

    private int user_id;
    private String userName;
    private String password;
    private String userPhoneNumber;
    private String email;
    private String gender;

}
RespBeanEnum.java
package com.www.vo;

import lombok.AllArgsConstructor;
import lombok.Getter;
import lombok.ToString;

import java.util.HashMap;



@Getter
@ToString
@AllArgsConstructor
public enum RespBeanEnum {

    PAY_SUCCESS(new HashMap<String,Object>(){
        {
            put("code","001");
            put("msg","付款成功");
        }
    }),
    PAY_ERROR(new HashMap<String,Object>(){
        {
            put("code","004");
            put("msg","付款失败");
        }
    });
    private final HashMap<String,Object> map;

}

加油哦,同学们!

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值