谷粒学院订单管理 server-order 模块

谷粒学院订单管理 server-order 模块

模块介绍

主要实现前台页面购买课程后,生成订单,并实现微信支付的功能。

![]](https://img-blog.csdnimg.cn/7b821f31df1c426ba91bc14ff49d4ad8.png)

在这里插入图片描述

思维导图(属性图)

在这里插入图片描述

库表设计

在这里插入图片描述

在这里插入图片描述

详细设计

订单

生成订单功能
接口设计

接受参数:课程号和HTTP 请求
请求类型:POST
请求体:JSON 格式的数据
返回值:订单号

流程
  1. 远程调用 根据用户id获取用户信息和根据课程id获取课程信息的方法,获取用户信息和课程信息。
  2. 创建订单对象,把信息传入到订单对象中去。
  3. 返回订单号
代码
//1.生成订单  controller层
    @PostMapping("createOder/{courseId}")
    public R saveOrder(
            @PathVariable String courseId,
            HttpServletRequest request) {
        //创建订单,返回订单号
        String orderNo = orderService.createOrders(
                courseId,
                JwtUtils.getMemberIdByJwtToken(request));
        return R.ok().data("orderId", orderNo);
    }
//1.生成订单  service层
	@Autowired
    private EduClient eduClient;
    @Autowired
    private UcenterClient ucenterClient;
	@Override
	public String createOrders(String courseId, String memberId) {
    //通过远程调用根据用户id获取用户信息
    UcenterMemberOrder userInfoOrder = ucenterClient.getUserInfoOrder(memberId);
    //通过远程调用根据课程id获取课程信息
    CourseWebVoOrder courseInfoOrder = eduClient.getCourseInfoOrder(courseId);
    //创建订单对象
    Order order = new Order();
    order.setOrderNo(OrderNoUtil.getOrderNo()); //订单号
    order.setCourseId(courseId); //课程id
    order.setCourseTitle(courseInfoOrder.getTitle()); //课程名称
    order.setCourseCover(courseInfoOrder.getCover()); //课程封面
    order.setTeacherName(courseInfoOrder.getTeacherName()); //课程所属讲师
    order.setTotalFee(courseInfoOrder.getPrice()); //订单金额(也就是课程价格)
    order.setMemberId(memberId); //用户id
    order.setMobile(userInfoOrder.getMobile());//用户手机号
    order.setNickname(userInfoOrder.getNickname()); //用户昵称
    order.setStatus(0); //支付状态(0:未支付 1:已支付)
    order.setPayType(1); //支付类型(1:微信 2:支付宝)

    baseMapper.insert(order);
    //返回订单号
    return order.getOrderNo();
}
//EduClient接口
@Component
@FeignClient("service-edu")
public interface EduClient {
    //根据课程id获取课程信息(该方法供远程调用使用)
    @PostMapping("/serviceedu/coursefront/getCourseInfoOrder/{id}")
    public CourseWebVoOrder getCourseInfoOrder(@PathVariable("id") String id);
}
//UcenterClient接口
@Component
@FeignClient("service-ucenter")
public interface UcenterClient {
    //根据用户id获取用户信息(该方法供远程调用使用)
    @PostMapping("/educenter/member/getUserInfoOrder/{id}")
    public UcenterMemberOrder getUserInfoOrder(@PathVariable("id") String id);
}
根据订单号查询订单信息功能
接口设计

接受参数:订单号
请求类型:GET
返回值:订单

代码
//2.根据订单号查询订单信息
@GetMapping("getOrderInfo/{orderId}")
public R getOrderInfo(@PathVariable String orderId) {
    QueryWrapper<Order> wrapper = new QueryWrapper<>();
    wrapper.eq("order_no", orderId);
    Order order = orderService.getOne(wrapper);
    return R.ok().data("item", order);
}
查询订单支付状态功能

在用户登录后,查询课程是否被用户购买过。

接口设计

接受参数:课程id和用户id
请求类型:GET
返回值:布尔值

代码
//3.根据课程id和用户id查询订单表status值是否为1(已支付)
@GetMapping("isBuyCourse/{courseId}/{memberId}")
public boolean isBuyCourse(
        @PathVariable String courseId,
        @PathVariable String memberId) {
    QueryWrapper<Order> wrapper = new QueryWrapper<>();
    wrapper.eq("course_id", courseId);
    wrapper.eq("member_id", memberId);
    wrapper.eq("status", 1); //1代表已经支付
    int count = orderService.count(wrapper);
    return count > 0;
}
生成微信支付二维码
接口设计

接受参数:订单号
请求类型:GET
返回值:Map集合

流程
  1. 先根据订单号查询订单信息
  2. 用map封装二维码需要的参数
  3. 发送httpclient请求,请求的参数是xml格式
    1. 设置请求地址(请求地址是微信给的固定的)
    2. 设置请求参数(xml格式)
    3. 解决无法请求https问题
    4. 发送xml格式参数的请求
  4. 获取请求返回的数据,并将xml数据转化为map集合。
  5. 最终返回数据的封装,把其他没在resultMap中的数据进行封装。
代码
//1.生成微信支付二维码  controller层
@GetMapping("createNative/{orderNo}")
public R createNative(@PathVariable String orderNo) {
    //业务层返回的信息中包含二维码地址,还有一些其它我们需要的信息
    Map map = payLogService.createNative(orderNo);
    return R.ok().data(map);
}
//service层
	@Autowired
    private OrderService orderService;

    //1.生成微信支付二维码
    @Override
    public Map createNative(String orderNo) {
        try {
            //1.根据订单号查询订单信息
            QueryWrapper<Order> wrapper = new QueryWrapper<>();
            wrapper.eq("order_no", orderNo);
            Order order = orderService.getOne(wrapper);

            //2.使用map集合设置生成二维码需要的参数
            Map m = new HashMap();
            m.put("appid", "wx74862e0dfcf69954"); //支付id
            m.put("mch_id", "1558950191"); //商户号
            m.put("nonce_str", WXPayUtil.generateNonceStr()); //生成随机唯一字符串,使得生成的每个二维码都不同
            m.put("body", order.getCourseTitle()); //生成的二维码显示什么名字
            m.put("out_trade_no", orderNo); //二维码的唯一标识,我们的订单号都是唯一的,所以一般赋值订单号
            m.put("total_fee", order.getTotalFee().multiply(new BigDecimal("100")).longValue()+""); //扫码的价格
            m.put("spbill_create_ip", "127.0.0.1"); //支付服务的ip地址(域名也行),我们这里是本地,所以赋值127.0.0.1
            m.put("notify_url", "http://guli.shop/api/order/weixinPay/weixinNotify\n");//支付后回调的地址,老师说目前用不到
            m.put("trade_type", "NATIVE"); //支付类型,NATIVE就表示根据价格生成一个支付二维码

            //3.发送httpclient请求,请求的参数是xml格式
            //3.1设置请求地址(请求地址是微信给的固定的)
            HttpClient client = new HttpClient("https://api.mch.weixin.qq.com/pay/unifiedorder");
            //3.2设置请求参数(xml格式)
            // generateSignedXml方法作用:根据商户key对map集合做加密并将加密后的map集合转为xml格式
            // setXmlParam方法作用:将得到的xml格式字符串设置为请求参数
            client.setXmlParam(WXPayUtil.generateSignedXml(m, "T6m9iK73b0kn9g5v426MKfHQH7X8rKwb"));
            //3.3因为请求的地址是https的,默认无法请求,有了下面这行代码就可以请求了
            client.setHttps(true);
            //3.4执行发送请求(发送xml格式参数的请求)
            client.post();

            //4.获取请求返回的数据
            //4.1获取数据
            String xml = client.getContent();
            //4.2将xml数据转为map集合
            //发送请求后微信返回的内容是xml格式字符串,为了方便前端取值,我们把xml格式转换为map集合,把这个map集合返回给控制层
            Map<String, String> resultMap = WXPayUtil.xmlToMap(xml);

            //5.最终返回数据的封装
            //但此时我们需要的其它数据并没有在resultMap集合中(如:订单号、课程id...),需要我们手动封装
            Map map = new HashMap<>();
            map.put("out_trade_no", orderNo); //订单号
            map.put("course_id", order.getCourseId()); //课程id
            map.put("total_fee", order.getTotalFee()); //订单金额
            map.put("result_code", resultMap.get("result_code")); //二维码操作状态码
            map.put("code_url", resultMap.get("code_url")); //二维码地址

            return map;
        } catch (Exception e) {
            throw new GuliException(20001, "生成支付二维码失败");
        }
    }
查询订单支付状态

在生成订单后,查询是否完成支付。

接口设计

接受参数:订单号
请求类型:GET
返回值:String

流程
  1. 先根据订单号查询订单支付状态

    1. 用map封装二维码需要的参数

    2. 发送httpclient请求,请求的参数是xml格式

      1. 设置请求地址(请求地址是微信给的固定的)

      2. 设置请求参数(xml格式)

      3. 解决无法请求https问题

      4. 发送xml格式参数的请求

    3. 获取请求返回的数据,并将xml数据转化为map集合。

    4. 最终返回数据的封装,把其他没在resultMap中的数据进行封装。

  2. 改变订单状态,根据订单状态向支付日志记录表添加记录

    1. 获取订单号,根据订单号去订单表查询订单信息
    2. 订单曾经已经支付了,不再需要做其它操作,订单曾经未支付,修改t_order(订单表)的status字段为1(已支付)
    3. 向支付日志记录表添加一条数据
代码
//查询订单支付状态
@GetMapping("queryPayStatus/{orderNo}")
public R queryPayStatus(@PathVariable String orderNo) {
    //请求微信给的地址后返回很多数据,为了方便取值,这里我们也用map集合来接收
    Map<String, String> map = payLogService.queryPayStatus(orderNo);
    if (map == null) {
        return R.error().message("支付出错了");
    }
    //map不为空,那就从map中获取订单状态
    if (map.get("trade_state").equals("SUCCESS")) {
        //向t_pay_log(支付日志记录表)添加一条记录
        //并且修改t_order(订单表)的status字段为1(已支付)
        payLogService.updateOrderStatus(map);
        return R.ok().message("支付成功");
    }
    return R.ok().message("支付中").code(25000);
}
 //根据订单号查询订单支付状态
    @Override
    public Map<String, String> queryPayStatus(String orderNo) {
        try {
            //1.封装参数
            Map m = new HashMap<>();
            m.put("appid", "wx74862e0dfcf69954");
            m.put("mch_id", "1558950191");
            m.put("out_trade_no", orderNo);
            m.put("nonce_str", WXPayUtil.generateNonceStr());

            //2.发送httpclient请求
            HttpClient client = new HttpClient(
                    "https://api.mch.weixin.qq.com/pay/orderquery");
            client.setXmlParam(WXPayUtil.generateSignedXml(
                    m, "T6m9iK73b0kn9g5v426MKfHQH7X8rKwb"));
            client.setHttps(true);
            client.post();

            //3.获取微信返回的数据,并将xml格式数据转为map集合
            String xml = client.getContent();
            Map<String, String> resultMap = WXPayUtil.xmlToMap(xml);

            return resultMap;
        } catch (Exception e) {
            return null;
        }
    }

    //向t_pay_log(支付日志记录表)添加一条记录
    //并且修改t_order(订单表)的status字段为1(已支付)
    @Override
    public void updateOrderStatus(Map<String, String> map) {
        //1.获取订单号
        String orderNo = map.get("out_trade_no");

        //2.根据订单号去订单表查询订单信息
        QueryWrapper<Order> wrapper = new QueryWrapper<>();
        wrapper.eq("order_no", orderNo);
        Order order = orderService.getOne(wrapper);

        //3.修改t_order(订单表)的status字段为1(已支付)
        //3.1订单曾经已经支付了,不再需要做其它操作
        if(order.getStatus().intValue() == 1) return;
        //3.2订单曾经未支付
        order.setStatus(1); //1代表已支付
        orderService.updateById(order);

        //4.向支付日志记录表添加一条数据
        PayLog payLog=new PayLog();
        payLog.setOrderNo(order.getOrderNo()); //订单号
        payLog.setPayTime(new Date()); //支付时间
        payLog.setPayType(1); //支付类型(1代表微信)
        payLog.setTotalFee(order.getTotalFee()); //支付金额(分)
        payLog.setTradeState(map.get("trade_state")); //支付状态
        payLog.setTransactionId(map.get("transaction_id")); //交易流水号
        payLog.setAttr(JSONObject.toJSONString(map)); //其它属性
        baseMapper.insert(payLog);//插入到支付日志记录表

    }

工具类OrderNoUtil

生成订单对象时用到,生成订单号。

public class OrderNoUtil {

    /**
     * 获取订单号
     * @return
     */
    public static String getOrderNo() {
        //自定义格式
        SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMddHHmmss");
        //使用format()方法将日期转换为字符串
        String newDate = sdf.format(new Date());
        String result = "";
        Random random = new Random();
        //随机生成三次   随机生成的随机数范围就变成[0,a)
        for (int i = 0; i < 3; i++) {
            result += random.nextInt(10);
        }
        //随机数和日期 结合生成的数字 返回成为订单号
        return newDate + result;
    }

}

yyyyMMddHHmmss");
        //使用format()方法将日期转换为字符串
        String newDate = sdf.format(new Date());
        String result = "";
        Random random = new Random();
        //随机生成三次   随机生成的随机数范围就变成[0,a)
        for (int i = 0; i < 3; i++) {
            result += random.nextInt(10);
        }
        //随机数和日期 结合生成的数字 返回成为订单号
        return newDate + result;
    }

}

pom.xml

<dependencies>
        <dependency>
            <groupId>com.github.wxpay</groupId>
            <artifactId>wxpay-sdk</artifactId>
            <version>0.0.3</version>
        </dependency>
        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>fastjson</artifactId>
        </dependency>
    </dependencies>
    ```
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值