谷粒学院订单管理 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层@Autowiredprivate EduClient eduClient;@Autowiredprivate UcenterClient ucenterClient;@Overridepublic 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); //课程idorder.setCourseTitle(courseInfoOrder.getTitle()); //课程名称order.setCourseCover(courseInfoOrder.getCover()); //课程封面order.setTeacherName(courseInfoOrder.getTeacherName()); //课程所属讲师order.setTotalFee(courseInfoOrder.getPrice()); //订单金额(也就是课程价格)order.setMemberId(memberId); //用户idorder.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层@Autowiredprivate OrderService orderService;//1.生成微信支付二维码@Overridepublic 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"); //支付idm.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.1m.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()); //课程idmap.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);
}//根据订单号查询订单支付状态@Overridepublic 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(已支付)@Overridepublic 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>```

谷粒学院订单管理 server-order 模块相关推荐

  1. 谷粒学院——后台管理系统功能模块

    在线教育 普通用户前台使用系统 管理员后台管理系统 讲师管理模块 环境搭建 讲师列表查询 讲师删除(逻辑删除) 整合swagger 统一结果数据返回 分页查询讲师 新增讲师 统一异常处理 日志 登录功 ...

  2. (附源码)springboot螺丝加工厂订单管理 毕业设计 010346

    题    目 springboot螺丝加工厂订单管理 目  录 摘要 1 1 绪论 1 1.1项目开发的背景 1 1.2项目开发的意义 1 1.3系统开发技术的特色 1 1.4论文结构与章节安排 1 ...

  3. Day206.课程分类【导入功能】前端实现、 课程分类列表【显示功能】、课程管理【模块需求、添加课程功能】 -谷粒学院

    谷粒学院 [课程分类]-导入前端实现 一.配置路由 1.添加路由 src/router/index.js //课程分类{path: 'subject',component: Layout,redire ...

  4. Day214.课程评论功能、微信支付实现课程支付模块前后端 -谷粒学院

    谷粒学院 课程评论功能 一.数据库设计 数据库 edu_comment 数据表 CREATE TABLE `edu_comment` (`id` char(19) NOT NULL COMMENT ' ...

  5. Day215.课程详细页面功能完善、Echarts统计分析模块[生成统计数据+生成图表]前后端整合 -谷粒学院

    谷粒学院 课程详细页面功能完善 一.修改课程详细接口 1.在service_order模块添加接口 用于判断订单中status值是否为1,为1则为已支付 @RestController @CrossO ...

  6. 【JAVA EE#6】【传智书城·源码阅读】后台管理模块:权限控制+页面分析+商品管理+销售榜单+订单管理+公告管理+项目结构思维导图

    权限控制 普通用户只能访问client文件夹下面的jsp文件,对于没有权限操作的admin文件夹就会提示错误,而超级用户同时可以访问两者,一直很好奇这个权限限制怎么实现的. 原来在存在一个AdminP ...

  7. 10.1 黑马Vue电商后台管理系统之完善订单管理模块--加入修改订单模块

    效果如下: 实现如下: 1.我仍然保留了添加地址这一个对话框,但只是绑定在另一个按钮上面,而点击左侧第一个按钮就会跳转到"修改订单"模块 <template v-slot=& ...

  8. 2022年最新《谷粒学院开发教程》:9 - 前台课程模块

    资料 资料地址 后台管理系统目录 前台展示系统目录 1 - 构建工程篇 7 - 渲染前台篇 2 - 前后交互篇 8 - 前台登录篇 3 - 文件上传篇 9 - 前台课程篇 4 - 课程管理篇 10 - ...

  9. oracle订单,银科软件:Oracle ERP订单管理模块详细介绍

    原标题:银科软件:Oracle ERP订单管理模块详细介绍 Oracle® 订单管理使用户能够通过更有效的客户服务.更个性化的产品和更有利的价格制定和订单履行抢先利用日益发展的国际互联网去销售和让客户 ...

最新文章

  1. StarlingMVC简介,原理解说及示例源码
  2. Sharepoint ListTemplateId
  3. 习题1.8 二分查找 (20 分)
  4. 方法参数是结构体指针,报错信息是空指针怎么办
  5. python字符集_Python任意字符集转换
  6. grep参数说明及常用用法
  7. php与sql server,PHP和SQL Server – 思考
  8. linux 启动,停止mysql
  9. MITRE 发布“2021年最重要的硬件弱点”榜单
  10. 二分图 洛谷P2055 [ZJOI2009]假期的宿舍
  11. 一线互联网公司Java高级面试总结
  12. ROS教程(三):创建程序包及节点(图文)
  13. CCNA考试题库中英文翻译版及答案3
  14. 算法学习:并行化初体验_JAVA实现并行化归并算法
  15. 计算机英语单词练习五
  16. Riverbed连续第四年成为Gartner魔力象限领导者
  17. NDK中LOCAL_SHARED_LIBRARIES
  18. 转发文章【我们是怎样一步步的走向平庸的】
  19. Spark SQL增量查询Hudi表
  20. 超详细双系统安装指南

热门文章

  1. Unity C# 网络学习(十二)——Protobuf生成协议
  2. 28所示范性微电子院校占地面积排名,中山大学第一!
  3. echarts 鼠标经过时改变折线拐点的小圆圈样式
  4. 1812. 方形牧场
  5. FC FCoe Vsan Zone相关
  6. CSS3之渐变(线性渐变,径向渐变)
  7. 关于Java调用dll文件的一系列问题(持续更新)
  8. WSO2 API Manager代码问题漏洞(CVE-2022-29464)
  9. 一个前端开发工程师的天猫精灵评测报告
  10. 如何把HTML转换成动图,视频转gif 如何将视频制作gif动画图片