支付模块-微信支付

2023-11-01

目录

接口实现 

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

第二步:根据订单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 {

    @Autowired
    private 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 {

    @Autowired
    private EduClient eduClient;
    @Autowired
    private UcenterClient ucenterClient;

    /**
     * 1.生成订单的方法,通过远程调用两个feign方法(课程信息和人物信息)结合到Order中为订单
     * @param courseId
     * @param memberId
     * @return
     */
    @Override
    public 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); //课程id
        order.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);//支付类型 微信1
        baseMapper.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 {

    @Autowired
    private 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 {

    @Autowired
    private OrderService orderService;

    /**
     * 1.返回二维码地址
     * @param orderNo
     * @return
     */
    @Override
    public 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转为map
            Map<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
     */
    @Override
    public 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
     */
    @Override
    public 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);//支付类型 1wx
        payLog.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,那么动态路由的参数就是pid
    return 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>

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

支付模块-微信支付 的相关文章

  • Grails 3.x bootRun 失败

    我正在尝试在 grails 3 1 11 中运行一个项目 但出现错误 失败 构建失败并出现异常 什么地方出了错 任务 bootRun 执行失败 进程 命令 C Program Files Java jdk1 8 0 111 bin java
  • 在 Java 中连接和使用 Cassandra

    我已经阅读了一些关于 Cassandra 是什么以及它可以做什么的教程 但我的问题是如何在 Java 中与 Cassandra 交互 教程会很好 如果可能的话 有人可以告诉我是否应该使用 Thrift 还是 Hector 哪一个更好以及为什
  • 如何默认将 Maven 插件附加到阶段?

    我有一个 Maven 插件应该在编译阶段运行 所以在项目中consumes我的插件 我必须做这样的事情
  • 在画布上绘图

    我正在编写一个 Android 应用程序 它可以在视图的 onDraw 事件上直接绘制到画布上 我正在绘制一些涉及单独绘制每个像素的东西 为此我使用类似的东西 for int x 0 x lt xMax x for int y 0 y lt
  • INSERT..RETURNING 在 JOOQ 中不起作用

    我有一个 MariaDB 数据库 我正在尝试在表中插入一行users 它有一个生成的id我想在插入后得到它 我见过this http www jooq org doc 3 8 manual sql building sql statemen
  • 多个 Maven 配置文件激活多个 Spring 配置文件

    我想在 Maven 中构建一个环境 在其中我想根据哪些 Maven 配置文件处于活动状态来累积激活多个 spring 配置文件 目前我的 pom xml 的相关部分如下所示
  • 列出jshell中所有活动的方法

    是否有任何命令可以打印当前 jshell 会话中所有新创建的方法 类似的东西 list但仅适用于方法 您正在寻找命令 methods all 它会打印所有方法 包括启动 JShell 时添加的方法 以及失败 被覆盖或删除的方法 对于您声明的
  • 反射找不到对象子类型

    我试图通过使用反射来获取包中的所有类 当我使用具体类的代码 本例中为 A 时 它可以工作并打印子类信息 B 扩展 A 因此它打印 B 信息 但是当我将它与对象类一起使用时 它不起作用 我该如何修复它 这段代码的工作原理 Reflection
  • JavaMail 只获取新邮件

    我想知道是否有一种方法可以在javamail中只获取新消息 例如 在初始加载时 获取收件箱中的所有消息并存储它们 然后 每当应用程序再次加载时 仅获取新消息 而不是再次重新加载它们 javamail 可以做到这一点吗 它是如何工作的 一些背
  • 无法解析插件 Java Spring

    我正在使用 IntelliJ IDEA 并且我尝试通过 maven 安装依赖项 但它给了我这些错误 Cannot resolve plugin org apache maven plugins maven clean plugin 3 0
  • 禁止的软件包名称:java

    我尝试从数据库名称为 jaane 用户名 Hello 和密码 hello 获取数据 错误 java lang SecurityException Prohibited package name java at java lang Class
  • 从 127.0.0.1 到 2130706433,然后再返回

    使用标准 Java 库 从 IPV4 地址的点分字符串表示形式获取的最快方法是什么 127 0 0 1 到等效的整数表示 2130706433 相应地 反转所述操作的最快方法是什么 从整数开始2130706433到字符串表示形式 127 0
  • Java按日期升序对列表对象进行排序[重复]

    这个问题在这里已经有答案了 我想按一个参数对对象列表进行排序 其日期格式为 YYYY MM DD HH mm 按升序排列 我找不到正确的解决方案 在 python 中使用 lambda 很容易对其进行排序 但在 Java 中我遇到了问题 f
  • 如何在控制器、服务和存储库模式中使用 DTO

    我正在遵循控制器 服务和存储库模式 我只是想知道 DTO 在哪里出现 控制器应该只接收 DTO 吗 我的理解是您不希望外界了解底层域模型 从领域模型到 DTO 的转换应该发生在控制器层还是服务层 在今天使用 Spring MVC 和交互式
  • Java执行器服务线程池[关闭]

    很难说出这里问的是什么 这个问题是含糊的 模糊的 不完整的 过于宽泛的或修辞性的 无法以目前的形式得到合理的回答 如需帮助澄清此问题以便重新打开 访问帮助中心 help reopen questions 如果我使用 Executor 框架在
  • 在mockito中使用when进行模拟ContextLoader.getCurrentWebApplicationContext()调用。我该怎么做?

    我试图在使用 mockito 时模拟 ContextLoader getCurrentWebApplicationContext 调用 但它无法模拟 here is my source code Mock org springframewo
  • 在 Maven 依赖项中指定 jar 和 test-jar 类型

    我有一个名为 commons 的项目 其中包含运行时和测试的常见内容 在主项目中 我添加了公共资源的依赖项
  • Firebase 添加新节点

    如何将这些节点放入用户节点中 并创建另一个节点来存储帖子 我的数据库参考 databaseReference child user getUid setValue userInformations 您需要使用以下代码 databaseRef
  • 有没有办法为Java的字符集名称添加别名

    我收到一个异常 埋藏在第 3 方库中 消息如下 java io UnsupportedEncodingException BIG 5 我认为发生这种情况是因为 Java 没有定义这个名称java nio charset Charset Ch
  • Spring Boot @ConfigurationProperties 不从环境中检索属性

    我正在使用 Spring Boot 1 2 1 并尝试创建一个 ConfigurationProperties带有验证的bean 如下所示 package com sampleapp import java net URL import j

随机推荐

  • 分苹果_100分_A/B卷复用_位运算/异或运算

    分苹果 题目描述 A B两个人把苹果分为两堆 A希望按照他的计算规则等分苹果 他的计算规则是按照二进制加法计算 并且不计算进位 12 5 9 1100 0101 9 B的计算规则是十进制加法 包括正常进位 B希望在满足A的情况下获取苹果重量
  • HTML代码学习

    任务 请根据给出的需求 在基本模板上完善网页 网页包括首页 登录 注册界面 实现3个页面功能 页面外观请参考给出的具体图片 首页代码 h1 各位 注意了 这个页面是 是首页 h1 p p
  • LLVM 的编译框架基本流程探索(Clang AST语法树)

    上一篇文章末尾提到 AST语法树 语句如下 clang fmodules fsyntax only Xclang ast dump src pp CompStream cpp include
  • php找两个数组对比,PHP如何对比两个数组是否相同

    第一种方法 降维成字符串 这种方法真对多维数组 思路是把数组降维成字符串 比如用json decode serialize 等函数转成字符串后再进行比较 第二种 用PHP自带对比函数 但只能支持二维数组 比较数组 返回数组的交集 只比较键值
  • React.js 官方资料摘记:状态提升

    状态提升 官网上那个例子很复杂 所以我在这里做了简化 说明的内容是一样的 先说明一下实现目标 有两个输入框 当一个输入框输入内容时 另一个自动输入相同内容 实现原理 将两个输入框的value属性的值绑定到父类中去 将两个输入框的onChan
  • iPhone 手机浏览器 font-size 失效问题

    问题 电脑端浏览器显示正常 iPhone手机浏览器却异常 如下图 用Safari调试iPhone手机网页 可以看到设置了 font size 12px 但实际浏览器渲染的字体大小却是 16px 解析 因为 Font Boosting 字体提
  • 安全测试常用几个工具

    下面介绍了这些工具的主要功能以及教程 书籍 视频等 端口扫描器 Nmap Nmap是 Network Mapper 的缩写 众所周知 它是一款非常受欢迎的免费开源黑客工具 Nmap被用于发现网络和安全审计 据数据统计 全世界成千上万的系统管
  • 【华为OD机试】周末爬山 (C++ Python Java)2023 B卷

    题目描述 周末小明准备去爬山锻炼 0代表平地 山的高度使用1到9来表示 小明每次爬山或下山高度只能相差k及k以内 每次只能上下左右一个方向上移动一格 小明从左上角 0 0 位置出发 输入描述 第一行输入m n k 空格分隔 代表m n的二维
  • 在子类中不能通过父类对象实例来访问父类的protected属性和方法

    四种修饰符的作用域 java中变量 方法和类有四种修饰符public protected default private 它们的作用域范围如下 public 拥有最大的权限 可以在本项目中的任意类中访问 protected 可以在本包下和其
  • 合并有序数组(Java)

    题目链接 88 合并两个有序数组 面试题 10 01 合并排序的数组 class Solution public void merge int A int m int B int n int nums1Copy new int m Syst
  • hdu 1000 A+B problem

    include
  • npm warn config global `--global`, `--local` are deprecated. use `--location=global` instead.

    解决方案 1 修改配置文件 1 1可以使用命令行 找到npm的配置目录 npm config命令 npm config ls npm config list npm config ls l 1 2打开nodejs文件夹 并打开两个文件 np
  • PostgreSQL 15安装使用Oracle_FDW

    下载插件 官方地址 http pgxn org dist oracle fdw 根据PostgreSQL版本选择 下载oracle客户端 https www oracle com database technologies instant
  • 【毕业季·进击的技术er】 什么是微信小程序,带你推开小程序的大门

    活动地址 毕业季 进击的技术er 作者 半身风雪 简介 本节课程 我将带领大家初识微信小程序 将通过小程序的发展 开发环境 开发工具 项目结构等 做一个详细的讲解 前几天 我也写了一篇关于毕业季的文章 时间悠悠 犹记得2019年的那个毕业季
  • 【翻译】GPT-3是如何工作的

    前排提示 这是我补充的内容 仅代表个人观点 和作者本人无关 主要是意译 我的补充 想看原文表达的拖到最底下有链接 原文翻译 在科技界我们可以看到很多关于GPT 3的新闻 大型语言模型 比如GPT 3 已经展示出让我们惊讶的性能 虽然对于大部
  • 如何在colab中加载数据集并且运行文件

    方式1 从本地机器导入数据集 方式2 从google drive导入 方式3 导入kaggle网站提供的数据集 方式1 选择导入本地的文件 注意导入的文件智慧自会对本次会话生效 此外 还可以获得本地导入的文件的路径以及文件名称 路径如下图所
  • 存储器实验:存储扩展实验、MIPS寄存器文件设计

    一 实验要求 项目1 存储扩展实验 现有如下 ROM 组件 4片4K32位 ROM 7片16K32位 ROM 请在 Logisim 平台构建 GB2312 汉字编码的16K 16点阵汉字字库 电路输入为汉字区号和位号 电路输出为8 32位
  • jmeter实现负载均衡_Jmeter实现简单web负载测试

    Jmeter实现简单web负载测试 简介 Apache JMeter是Apache组织开发的基于Java的压力测试工具 用于对软件做压力测试 它最初被设计用于Web应用测试 但后来扩展到其他测试领域 它可以用于测试静态和动态资源例如静态文件
  • 59 openEuler 22.03-LTS 搭建MySQL数据库服务器-软件介绍和配置环境

    文章目录 59 openEuler 22 03 LTS 搭建MySQL数据库服务器 软件介绍和配置环境 59 1 软件介绍 59 2 配置环境 59 2 1 关闭防火墙并取消开机自启动 59 2 2 修改SELINUX为disabled 5
  • 支付模块-微信支付

    目录 接口实现 第一步 当点击立即购买生成订单 第二步 根据订单id查询订单信息 第三步 生成微信支付的二维码 第四步 查询订单支付状态 前端实现 编辑 1 点击支付 2 订单详情页 接口实现 像这种微服务B2C模式的 订单业务需要远程调用