支付模块-微信支付

news/2024/5/20 13:20:49/文章来源:https://blog.csdn.net/weixin_57128596/article/details/127301746

目录

接口实现 

第一步:当点击立即购买生成订单

第二步:根据订单id查询订单信息

第三步:生成微信支付的二维码

第四步:查询订单支付状态

前端实现

​编辑

1.点击支付

2.订单详情页


接口实现 

 

像这种微服务B2C模式的,订单业务需要远程调用我们的课程信息+用户信息

  

依赖:

 <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>

第一步:当点击立即购买生成订单

通过远程调用,order业务调用course+user

1.查询Course课程信息暴露出来的接口+用户信息接口

@Component
@FeignClient("service-edu")
public interface EduClient {/*** 1.远程调用ucenter中根据id获取用户信息的方法*/@GetMapping("/eduservice/indexfront/getCourseInfoOrder/{id}")public CourseWebVoOrder getCourseInfoOrder(@PathVariable String id);}
@Component
@FeignClient("service-ucenter")
public interface UcenterClient {/*** 1.根据课程id查询课程信息*/@GetMapping("/educenter/member/getUserInfoOrder/{id}")public UcenterMemberOrder getUserInfoOrder(@PathVariable("id") String id);
}

2.生成订单的接口+实现类

通过请求头得到token然后给到JWT进行解析得到用户id

@RestController
@RequestMapping("/eduorder/order")
@CrossOrigin
public class OrderController {@Autowiredprivate OrderService orderService;/*** 1.生成订单的方法*/@GetMapping("createOrder/{courseId}")public R saveOrder(@PathVariable String courseId, HttpServletRequest request){//1.生成订单号String orderNo=orderService.createOrders(courseId,JwtUtils.getMemberIdByJwtToken(request));return R.ok().data("orderId",orderNo);}
/*** <p>* 订单 服务实现类* </p>** @author testjava* @since 2022-07-25*/
@Service
public class OrderServiceImpl extends ServiceImpl<OrderMapper, Order> implements OrderService {@Autowiredprivate EduClient eduClient;@Autowiredprivate UcenterClient ucenterClient;/*** 1.生成订单的方法,通过远程调用两个feign方法(课程信息和人物信息)结合到Order中为订单* @param courseId* @param memberId* @return*/@Overridepublic String createOrders(String courseId, String memberId) {//1.通过远程调用根据用户id获取用户信息UcenterMemberOrder userInfoOrder = ucenterClient.getUserInfoOrder(memberId);//2.通过远程调用根据课程id获取课程信息CourseWebVoOrder courseInfoOrder = eduClient.getCourseInfoOrder(courseId);//3.创建order对象,向order对象里面设置需要的数据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);order.setMobile(userInfoOrder.getMobile());order.setNickname(userInfoOrder.getNickname());order.setStatus(0);//订单状态(0:未支付 1:已支付)order.setPayType(1);//支付类型 微信1baseMapper.insert(order);//插入return order.getOrderNo();}
}

 返回的CourseWebVoOrder等远程调用的类放在公共模块中

 

 

第二步:根据订单id查询订单信息

 /*** 2.根据订单id查询订单信息*/@GetMapping("getOrderInfo/{orderId}")public R getOrderInfo(@PathVariable String orderId){//订单id查询QueryWrapper<Order> wrapper = new QueryWrapper<>();wrapper.eq("order_no",orderId);Order order = orderService.getOne(wrapper);return R.ok().data("item",order);}

第三步:生成微信支付的二维码

准备工作(wxid,商户号,商户key)

1.根据订单号获取订单信息

/*** <p>* 支付日志表 前端控制器* </p>** @author testjava* @since 2022-07-25*/
@RestController
@RequestMapping("/eduorder/paylog")
@CrossOrigin
public class PayLogController {@Autowiredprivate PayLogService payLogService;/*** 1.生成微信支付的二维码接口*/@GetMapping("createNative/{orderNo}")public R createNative(@PathVariable String orderNo) {//1.返回信息含有二维码的地址还有其他信息Map map = payLogService.createNative(orderNo);System.out.println("*****返回二维码map集合****:"+map);return R.ok().data(map);}

2.1根据订单号获取订单信息——>2.2业务实现类中设置支付参数 ——>2.3将参数请求到我们vx支付的接口地址,回调得到返回集(client.getContent(),利用WXPayUtil将xml转为map集合方便返回到前端)

@Service
public class PayLogServiceImpl extends ServiceImpl<PayLogMapper, PayLog> implements PayLogService {@Autowiredprivate OrderService orderService;/*** 1.返回二维码地址* @param orderNo* @return*/@Overridepublic Map createNative(String orderNo) {try {//1.根据订单id获取订单信息QueryWrapper<Order> wrapper = new QueryWrapper<>();wrapper.eq("order_no", orderNo);Order order = orderService.getOne(wrapper);//2.使用map设置二维码需要的参数HashMap map = new HashMap();map.put("appid","wx74862e0dfcf69954");map.put("mch_id", "1558950191");map.put("nonce_str", WXPayUtil.generateNonceStr());//随机生成一个二维码map.put("body", order.getCourseTitle());map.put("out_trade_no", orderNo);//二维码标识订单号map.put("total_fee", order.getTotalFee().multiply(new BigDecimal("100")).longValue()+"");//价格map.put("spbill_create_ip", "127.0.0.1");map.put("notify_url", "http://guli.shop/api/order/weixinPay/weixinNotify\n");map.put("trade_type", "NATIVE");//3.发送httpclient请求,传递参数按照xml格式,微信支付提供固定地址HttpClient client = new HttpClient("https://api.mch.weixin.qq.com/pay/unifiedorder");//设置参数,我们的商户key会对这些map参数进行加密->将map根据key进行加密并且传送到请求中去client.setXmlParam(WXPayUtil.generateSignedXml(map,"T6m9iK73b0kn9g5v426MKfHQH7X8rKwb"));client.setHttps(true);//执行请求发送client.post();//4.得到发送请求返回的结果,返回的内容是xml格式返回的(之前传参数也是xml格式)String content = client.getContent();//5.再把xml转为mapMap<String,String>resultMap=WXPayUtil.xmlToMap(content);//6.前面的map只是为了给到http生成二维码,需要转为xml格式,现在我们这个结果resultMap就是二维码了//还需要一些关于订单的提示信息Map res = new HashMap<>();res.put("out_trade_no", orderNo);res.put("course_id", order.getCourseId());res.put("total_fee", order.getTotalFee());res.put("result_code", resultMap.get("result_code"));//状态码res.put("code_url", resultMap.get("code_url"));//二维码地址return res;} catch (Exception e) {throw new GuliException(20001,"生成二维码失败");}}

第四步:查询订单支付状态

 1.先查订单的支付状态,返回的支付state为成功——>2.然后在支付日志表中添加一条记录,并且更新订单表状态

 /*** 2.查询订单状态* @param orderNo* @return*/@GetMapping("queryPayStatus/{orderNo}")public R queryPayStatus(@PathVariable String orderNo){Map<String,String>map= payLogService.queryPayStatus(orderNo);System.out.println("返回二维码状态:"+map);//1.根据查询出来的订单状态进行判断if(map==null){return R.error().message("支付出错了...");}//2.如果返回的map不为空,从这里面获取订单状态if(map.get("trade_state").equals("SUCCESS")){//支付成功//3.添加记录到支付表中,并且更新订单表的状态payLogService.updateOrdersStatus(map);return R.ok();}return R.ok().code(25000).message("支付中");}}

  业务实现类-根据订单号查询订单状态

 /*** 1.查询订单支付状态* @param orderNo* @return*/@Overridepublic Map<String, String> queryPayStatus(String orderNo) {//1.封装参数try {HashMap map = new HashMap();map.put("appid", "wx74862e0dfcf69954");map.put("mch_id", "1558950191");map.put("out_trade_no", orderNo);map.put("nonce_str", WXPayUtil.generateNonceStr());//2.设置请求,利用xml进行请求HttpClient client = new HttpClient("https://api.mch.weixin.qq.com/pay/orderquery");client.setXmlParam(WXPayUtil.generateSignedXml(map,"T6m9iK73b0kn9g5v426MKfHQH7X8rKwb"));client.setHttps(true);client.post();//3.返回第三方的数据String xml = client.getContent();Map<String, String> resultMap = WXPayUtil.xmlToMap(xml);//将xml转为map数据return resultMap;} catch (Exception e) {e.printStackTrace();}return null;}

业务实现-添加支付记录+更新订单状态

 /*** 2.添加支付记录和更新订单状态* @param map*/@Overridepublic void updateOrdersStatus(Map<String, String> map) {//1.从map中获取订单号String orderNo = map.get("out_trade_no");//2.根据订单号查询订单信息QueryWrapper<Order> wrapper = new QueryWrapper<>();wrapper.eq("order_no",orderNo);Order order = orderService.getOne(wrapper);//3.更新订单表的订单状态if(order.getStatus().intValue()==1){return;//说明支付过了}order.setStatus(1);orderService.updateById(order);//4.向支付表中添加支付记录PayLog payLog = new PayLog();payLog.setOrderNo(orderNo);payLog.setPayTime(new Date());payLog.setPayType(1);//支付类型 1wxpayLog.setTotalFee(order.getTotalFee());//总金额(分)payLog.setTradeState(map.get("trade_state"));//支付状态payLog.setTransactionId(map.get("transaction_id"));//账单流水号payLog.setAttr(JSONObject.toJSONString(map));baseMapper.insert(payLog);//插入到支付日志表}

前端实现

 当点击商品的去支付就会生成支付的二维码

1.点击支付

 methods:{//去支付,通过动态路由的方式传递orderNo订单号toPay(){this.$router.push({path:'/pay/'+this.order.orderNo})}}

2.订单详情页

因为oid页面到pid页面点击toPay方法传入订单号,我们这里根据订单号调后台接口createNative生成二维码

mouted()方法:里面定义一个定时器,每3s判断一次订单的状态,如果订单响应状态为success则清除定时器——>跳转到订单详情页去看视频

import ordersApi from "@/api/order";export default {//1.return除了要return方法还要return成功数据asyncData({ params, error }) {// 2.名字是pid,那么动态路由的参数就是pidreturn ordersApi.createNative(params.pid).then((response) => {return {payObj: response.data.data,};});},data() {return {tiemer1: "",};},//2.定义mouted,意思是页面渲染之后执行,防止没有数据mounted() {//1.每隔3s调一次查询订单状态方法this.tiemer1 = setInterval(() => {this.queryOrderStatus(this.payObj.out_trade_no);}, 3000);},methods: {//3.查询支付状态queryOrderStatus(orderNo) {ordersApi.queryPayStatus(orderNo).then((response) => {console.log("正在查询订单信息.....");console.log(response.data);if(response.data.success){console.log("支付成功,清除定时器")//1.支付成功清除定时器clearInterval(this.tiemer1);//2.支付成功提示this.$message({type: "success",message: "支付成功!",});//3.跳转到课程详情页面观看视频this.$router.push({ path: "/course/" + this.payObj.course_id });}});},},
};
</script>

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.luyixian.cn/news_show_589177.aspx

如若内容造成侵权/违法违规/事实不符,请联系dt猫网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【牛客刷题】每日一练——最小K个数

✨hello&#xff0c;进来的小伙伴们&#xff0c;你们好耶&#xff01;✨ &#x1f345;&#x1f345;系列专栏:【牛客刷题】 ✈️✈️本篇内容: 最小K个数&#xff01; ⛵⛵作者简介&#xff1a;一名双非本科大三在读的科班Java编程小白&#xff0c;道阻且长&#xff0c;你我同…

《漂浮城堡历险记》的云端之旅

《漂浮城堡历险记》是 The Sandbox 游戏制作基金支持的项目之一。让我们告诉你更多关于这个 The Sandbox 元宇宙独有的、令人上瘾的奇幻游戏的信息吧。它已在 The Sandbox Alpha 第 3 季中上线了&#xff01; 关于体验 在《漂浮城堡历险记》这个冒险战斗游戏中&#xff0c;玩家…

基于深度学习的机载激光扫描森林单株茎的检测、分割与模型拟合

Abstract 精确测量树木的结构特征&#xff0c;如高度、直径、宽度和锥度&#xff0c;是森林资源调查的重要组成部分。目前&#xff0c;地面和空中激光雷达都被用来产生点云数据&#xff0c;通过这些数据可以确定清单指标。陆地/地面扫描通常提供每平方米数千个点的点云分辨率&…

(附源码)计算机毕业设计ssm核酸结果查询系统

项目运行 环境配置&#xff1a; Jdk1.8 Tomcat7.0 Mysql HBuilderX&#xff08;Webstorm也行&#xff09; Eclispe&#xff08;IntelliJ IDEA,Eclispe,MyEclispe,Sts都支持&#xff09;。 项目技术&#xff1a; SSM mybatis Maven Vue 等等组成&#xff0c;B/S模式 M…

【 java 多线程】同步锁 (Lock) 解决线程的安全问题

&#x1f4cb; 个人简介 &#x1f496; 作者简介&#xff1a;大家好&#xff0c;我是阿牛&#xff0c;全栈领域优质创作者。&#x1f61c;&#x1f4dd; 个人主页&#xff1a;馆主阿牛&#x1f525;&#x1f389; 支持我&#xff1a;点赞&#x1f44d;收藏⭐️留言&#x1f4d…

计算机网络课程设计——中小型网络工程设计

文件地址:https://github.com/Recursiondzl/Computer-Network 摘 要&#xff1a;本次计算机网络实践&#xff0c;完成了中小型网络工程设计与实现对计算机网络知识进行了系统的复习&#xff0c;实践能力获得了巨大的提升。 中小型网络工程设计与实现中&#xff0c;使用路由器…

DDD初步简单理解

概述 最近有一个项目要使用DDD模式来写&#xff0c;大致整理一下笔记。 问题&#xff1a;为什么要使用DDD&#xff1f;大概要怎么使用DDD&#xff1f; 目录 概述 MVC和DDD比较 实例介绍 简洁代码逻辑示例 总结 MVC和DDD比较 MVC&#xff08;module&#xff0c;view&#xff0c…

最适合跑步用的耳机有哪些、精选五款最优秀的跑步耳机推荐

越来越多的人选择在运动的时候佩戴蓝牙耳机&#xff0c;身为健身教练&#xff0c;也有很多人会让我们推荐蓝牙耳机&#xff0c;那么现在到底市面上哪些机型是最适合跑步的时候用的呢&#xff1f;我趁着最近有空搜集了一些资料跟我使用过的经验&#xff0c;给大家整理了一份最值…

揭秘EVM Opcodes

1. 引言 本文主要源自Macro团队的Gilbert在ETHNewYork 2022分享 Demystifying EVM Opcodes&#xff0c;同时结合evm.codes来理解。 学习EVM Opcodes&#xff0c;可成为更好的Solidity工程师。 更好的Solidity工程师&#xff0c;意味着&#xff1a; 1&#xff09;理解Solidity…

【新手向】Rock5B官方Debian系统设置中文环境(简单设置)和远程桌面连接

一、环境与说明 Rock5B的系统&#xff1a;官方Debian11&#xff08;2022-10-01版本&#xff09; 前面的两篇文章都是在2022-09-19版本镜像中操作的&#xff0c;2022-10-01版本内置了中文字体&#xff0c;不要自己下载了。目前Rock5B的硬件版本是v1.42&#xff0c;大概在23年初…

一致性哈希原理

一致性哈希原理 分布式系统将数据分布到不同的节点来存储&#xff0c;比如一个分布式KV&#xff08;key-value&#xff09;缓存系统&#xff0c;某个key应该到哪个节点上获得&#xff0c;最直观的方法是使用哈希算法&#xff08;hash(key)%n&#xff09;&#xff0c;对key进行…

python--绘制WRF模式近地面风场以及辐射

使用python自动化绘制WRF模式输出的风场以及辐射 本脚本主要用来自动化处理WRF模式数据&#xff0c;可以根据自己指定的时间范围以及时间步长绘制相应的数据 1 导入库 import cmaps import numpy as np import glob from netCDF4 import Dataset import matplotlib.pyplot a…

【C++】从零开始的CS:GO逆向分析3——写出一个透视

【C++】从零开始的CS:GO逆向分析3——写出一个透视本篇内容包括:1. 透视实现的方法介绍2. 通过进程名获取进程id和进程句柄3. 通过进程id获取进程中的模块信息(模块大小,模块地址,模块句柄)4. 读取游戏内存(人物ViewMatrix,敌人坐标,敌人生命值,敌人阵营)5. 三维坐标…

Java项目本地部署搭建实战SpringBoot高校宿舍管理系统源码

大家好啊&#xff0c;我是测评君&#xff0c;欢迎来到web测评。 本期给大家带来一套Java开发的SpringBoot高校宿舍管理系统源码。 技术架构 技术框架&#xff1a;SpringBoot2.0.0 Mybatis1.3.2 Mysql5.7 layui运行环境&#xff1a;jdk8 IntelliJ IDEA maven3 宝塔面板 …

触摸屏分类和触摸屏校准原理

一、触摸屏分类 常用触摸屏分两种 1、电阻触摸屏校正原理&#xff1a;导电ITO层及整个电路电阻值会随时间电压等轻微偏移&#xff0c;为了更精确与LCD显示屏上的功能图案相对应&#xff0c;重新校正计算标准位置。不校正可能会线性偏移&#xff0c;好的触摸屏一般无需校正&am…

【面经】360大数据开发面经

30 分钟&#xff0c;不做题。 欢迎点击此处关注公众号&#xff0c;每天分享大数据开发面经 介绍实习项目 会涉及平台开发吗 平时常用的语言 回答了 Java。 Python 用过吗 Java 实现一个单例要注意什么 懒汉式&#xff1a; public class Singleton {private static Sing…

钢铁行业经销商商城系统:完善钢材管控方案,轻松实现控价和防伪

钢铁工业是全球经济发展的核心&#xff0c;也是现代社会可持续发展的核心。根据数据显示&#xff0c;2020年中国钢材产量为13.25亿吨&#xff0c;同比增长9.96%;生铁产量为8.88亿吨&#xff0c;同比增长9.77%;粗钢产量为10.53亿吨&#xff0c;同比增长5.72%。 图片来源&#xf…

网络编程之TCP模型

1. TCP模型 2. socket 最早的socket和消息队列、共享内存、管道一致&#xff0c;只能实现一台主机多个进程间通信&#xff0c;后期加入了tcp/ip协议&#xff0c;使得支持不同主机的进程间通信 socket本质上是一个编程接口给&#xff08;API&#xff09;,是对TCP/IP协议的封装…

利用表面肌电信号对手部抓取动作分类的新型卷积网络模型

利用表面肌电信号对手部抓取动作分类的新型卷积网络模型 文章目录利用表面肌电信号对手部抓取动作分类的新型卷积网络模型一.相关研究二.材料和方法2.1 数据集2.2 数据预处理2.3 1D-1D-CNN三.实验结果分析四.相关研究对比参考文献一.相关研究 肌电信号号代表肌肉功能的特征&…

ReentrantLock可重入、可打断、锁超时实现原理

述 前面讲解了ReentrantLock加锁和解锁的原理实现&#xff0c;但是没有阐述它的可重入、可打断以及超时获取锁失败的原理&#xff0c;本文就重点讲解这三种情况。 可重入 可重入是指一个线程如果获取了锁&#xff0c;那么它就是锁的主人&#xff0c;那么它可以再次获取这把锁…