Dubbo 分布式架构搭建教育 PC 站 - 微信支付

创建二维码

安装 qrcodejs2 (注意:安装的是 qrcodejs2,不要安装 qrcode,否则会报错)

npm install  qrcodejs2 --save

页面中引入

<el-dialog :visible.sync="dialogFormVisible" style="width:800px;margin:0px 
auto;" >
  <h1 style="font-size:30px;color:#00B38A">微信扫一扫支付</h1>
  <div id="qrcode" style="width:210px;margin:20px auto;"></div>
</el-dialog>
<script>
import QRCode from 'qrcodejs2'; // 引入qrcodejs
export default {
  name: "Index",
  components: {
    Header,
    Footer,
    // 声明组件
    QRCode
  },
  data() {
    return {
      // 是否显示登录框,true:显示,false:隐藏
      dialogFormVisible: false,
    };
  },
  methods: {
    // 购买课程
    buy(courseid) {
      // alert("购买第【" + courseid + "】门课程成功,加油!");
      // 显示提示框
      this.dialogFormVisible = true;
      // 待 dom 更新之后再用二维码渲染其内容
      this.$nextTick(function(){
          // 直接调用会报错:TypeError: Cannot read property 'appendChild' of null
          this.createCode();
      });
    },
    // 生成二维码
    createCode(){
      // QRCode 存放二维码的 dom 元素 id,二维码的属性参数
      let qrcode = new QRCode('qrcode',{
         // 二维码的宽度
         width:200,
         // 二维码的高度
         height:200,
         // 二维码中包含的信息
         text:"我爱你"
      });
    },
  },
};
</script>

准备工作

名词介绍
  • appid - 微信公众帐号或开放平台 APP 的唯一标识
  • partner - 商户号(配置文件中的 partner:账户)
  • partnerkey - 商户密钥(密码)
  • sign - 数字签名,根据微信官方提供的密钥和一套算法生成的一个加密信息,就是为了保证交易安全

需要注册认证公众号来获取这些信息,费用 300 元 / 次。

获取认证的流程
1) 注册公众号 - 类型:服务号

根据营业执照类型选择以下主体注册:个体工商户 | 企业/公司 | 政府 | 媒体 | 其他类型。

2) 认证公众号

公众号认证后才申请微信支付:300 元 / 次。

3) 提交材料申请微信支付

登录公众平台,左侧菜单【微信支付】,开始填写资料(营业执照)等待审核,审核时间 1~5 工作日。

4) 开户成功,登录商户平台进行验证

资料审核通过后,请登录联系人邮箱查收商户号和密码,并登录商户平台填写财付通备付金打的小额资金数额,完成账户验证。

5) 在线签署协议

本协议为线上电子协议,签署后方可进行交易及资金结算,签署完立即生效。

6) 查看自己的公众号的参数

lagou-edu-web

commons.PayConfig

package commons;

/**
 * 微信支付商户的配置类
 *
 * @author Renda Zhang
 * @since 2020-10-27 0:43
 */
public class PayConfig {

    // 企业公众号 ID
    public static String appid = "wx8397f8696b538317";
    // 财付通平台的商户帐号
    public static String partner = "1473426802";
    // 财付通平台的商户密钥
    public static String partnerKey = "8A627A4578ACE384017C997F12D68B23";
    // 回调 URL
    public static String notifyurl = "http://a31ef7db.ngrok.io/WeChatPay/WeChatPayNotify";

}

支付流程

用户 -> 打开页面 -> 点击购买 -> 传递商品 id 和价格 -> createCodeController -> 获得价格并搭配商户信息发送给微信进行下单 -> 微信支付系统

微信支付系统 -> 返回支付链接 -> createCodeController -> 返回支付链接 -> 创建支付二维码 -> 用户

用户扫描支付 -> 检查支付状态 —> 传递订单号 —> checkOrderStatusController -> 获得订单号并搭配商户信息发送给微信进行查询订单状态 -> 微信支付系统

微信支付系统 -> 返回支付状态 -> checkOrderStatusController -> 返回支付状态 -> 更新页面信息

工具介绍

微信支付 SDK

微信支付官网下载 SDK:https://pay.weixin.qq.com/wiki/doc/api/micropay.php?chapter=11_1

<dependency>
    <groupId>com.github.wxpay</groupId>
    <artifactId>wxpay-sdk</artifactId>
    <version>0.0.3</version>
</dependency>

主要使用 SDK 中的三个功能:

1、获取随机字符串(生成订单编号)。

WXPayUtil.generateNonceStr();

2、将 map 转换成 xml 字符串(自动添加签名)。

WXPayUtil.generateSignedXml(map,partnerKey);

3、将 xml 字符串转换整 map。

WXPayUtil.xmlToMap(result);
JFinal 框架

JFinal 是基于 Java 语言的极速 web 开发框架,其核心设计目标是开发迅速、代码量少、学习简单、功能强大、轻量级、易扩展。

JFinal 取代 HttpClient

<dependency>
    <groupId>com.jfinal</groupId>
    <artifactId>jfinal</artifactId>
    <version>3.5</version>
</dependency>

构建二维码

src\components\Course.vue

<script>
//  生成二维码
    createCode () {
      this.axios
        .get("http://localhost:80/order/createCode", {
          params: {
            // 课程编号
            courseid: this.course.id,
            // 课程名称
            courseid: this.course.courseName,
            // 优惠价,非原价
            price: this.course.discounts,
          },
        })
        .then((result) => {
          console.log(result);
          let qrcode = new QRCode('qrcode',{
            width:200,
            height:200,
            // 将支付连接嵌入到二维码中
            text:result.data.code_url
          });
        })
        .catch((error) => {
          this.$message.error("二维码生成失败!");
        });
    }
</script>

lagou-edu-web 支付配置 commons.PayConfig (上文已配置)

控制层创建二维码 com.renda.wx.WxPayController

package com.renda.wx;

import com.github.wxpay.sdk.WXPayUtil;
import com.jfinal.kit.HttpKit;
import commons.PayConfig;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import java.util.HashMap;
import java.util.Map;

/**
 * @author Renda Zhang
 * @since 2020-10-27 0:41
 */
@RestController
@RequestMapping("order")
public class WxPayController {

    @GetMapping("createCode")
    public Object createCode(String courseid, String coursename, String price) throws Exception {
        coursename = new String(coursename.getBytes("ISO-8859-1"), "UTF-8");
        Map<String, String> mm = new HashMap();
        // 公众账号 ID
        mm.put("appid", PayConfig.appid);
        // 商户号
        mm.put("mch_id", PayConfig.partner);
        // 随机字符串
        mm.put("nonce_str", WXPayUtil.generateNonceStr());
        // 商品简单描述
        mm.put("body", coursename);
        // 随机生成的商户订单号
        mm.put("out_trade_no", WXPayUtil.generateNonceStr());
        // 订单金额,订单总金额,单位为分,只能为整数
        mm.put("total_fee", price);
        // 终端 IP
        mm.put("spbill_create_ip", "127.0.0.1");
        // 通知地址
        mm.put("notify_url", PayConfig.notifyurl);
        // 交易类型
        mm.put("trade_type", "NATIVE");
        // System.out.println("商户信息:" + mm) ;

        // 2.生成数字签名,并发商户信息转换成 xml 格式
        String xml = WXPayUtil.generateSignedXml(mm, PayConfig.partnerKey);
        // System.out.println("商户的 xml 信息:" + xml);

        // 3.将 xml 数据发送给为微信支付平台,从而生成订单
        String url = "https://api.mch.weixin.qq.com/pay/unifiedorder";
        // 发送请求,并返回一个 xml 格式的字符串
        String result = HttpKit.post(url, xml);

        // 4.微信支付平台返回 xml 格式数据,将其转换成 map 格式并返回给前端
        Map<String, String> resultMap = WXPayUtil.xmlToMap(result);
        resultMap.put("orderId", mm.get("out_trade_no"));
        return resultMap;
    }

}

检查支付状态

src\components\Course.vue

<!-- 微信支付二维码-->
<el-dialog :visible.sync="dialogFormVisible" style="width:800px;margin:0px 
auto;" >
  <h1 style="font-size:30px;color:#00B38A" >微信扫一扫支付</h1>
  <div id="qrcode" style="width:210px;margin:20px auto;"></div>
  <h2 id="statusText"></h2>
  <p id="timeClose"></p>
</el-dialog>
<script>
data() {
    return {
      // 定时器
      time:null
    };
},
// 生成二维码
createCode(){
  // 去获取支付连接
  this.axios
    .get("http://localhost:80/order/createCode",{
      params:{
        courseid: this.course.id,
        coursename: this.course.courseName,
        price:this.course.discounts,
      }
    })
    .then((result) => {
        console.log("订单号1:"+result.data.out_trade_no);
        // QRCode 存放二维码的 dom 元素 id,二维码的属性参数
        let qrcode = new QRCode('qrcode',{
           width:200,
           height:200,
           // 将返回的数据嵌入到二维码中
           text:result.data.code_url
       });
       // 检查订单状态
       this.axios
          .get("http://localhost:80/order/checkOrderStatus",{
            params:{
              orderId: this.orderId
            }
          })
          .then((result) => {
              console.log(result);
              if(result.data.trade_state=="SUCCESS"){
     document.getElementById("statusText").innerHTML = "<i style='color:#00B38A' class='el-icon-success'></i> 支付成功!";
                  let s = 3;
                  this.closeQRForm(s);
              }
          })
          .catch( (error)=>{
              this.$message.error("查询订单状态失败!");
          });
    })
    .catch( (error)=>{
      this.$message.error("生成二维码失败!");
    });
},
// 倒计时关闭二维码窗口
closeQRForm(s){
  let that = this;
  that.time= setInterval(function(){
      document.getElementById("timeClose").innerHTML = "("+ s-- +") 秒后关闭本窗口!";
      if(s == 0){
        // 停止计时
        clearInterval(that.time);
        // 关闭
        that.dialogFormVisible = false;
        // 解锁购买状态
        that.isBuy = true;
      }
  },1000);
},
</script>

com.renda.wx.WxPayController

package com.renda.wx;

import com.github.wxpay.sdk.WXPayUtil;
import com.jfinal.kit.HttpKit;
import commons.PayConfig;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import java.util.HashMap;
import java.util.Map;

/**
 * @author Renda Zhang
 * @since 2020-10-27 0:41
 */
@RestController
@RequestMapping("order")
public class WxPayController {

    ...

    @GetMapping("checkOrderStatus")
    public Object checkOrderStatus(String orderId) throws Exception {
        // 1.编写商户信息
        Map<String, String> mm = new HashMap();
        // 公众账号 ID
        mm.put("appid", PayConfig.appid);
        // 商户号
        mm.put("mch_id", PayConfig.partner);
        // 商户订单号
        mm.put("out_trade_no", orderId);
        // 随机字符串
        mm.put("nonce_str", WXPayUtil.generateNonceStr());
        // 2.生成数字签名
        String xml = WXPayUtil.generateSignedXml(mm, PayConfig.partnerKey);
        // 3.发送查询请求给微信支付平台
        String url = "https://api.mch.weixin.qq.com/pay/orderquery";

        // 查询订单状态的开始时间点
        long beginTime = System.currentTimeMillis();
        // 不停的去微信支付平台询问是否支付成功
        while (true) {
            // 4.对微信支付平台返回的查询结果进行处理
            String result = HttpKit.post(url, xml);
            Map<String, String> resultMap = WXPayUtil.xmlToMap(result);

            // 已经支付成功,不再询问
            if (resultMap.get("trade_state").equalsIgnoreCase("SUCCESS")) {
                return resultMap;
            }

            // 超过 30 秒未支付,停止询问
            if (System.currentTimeMillis() - beginTime > 30000) {
                return resultMap;
            }
            // 每隔 3 秒,询问一次微信支付平台
            Thread.sleep(3000);
        }
    }

}

保存订单并更新状态

src\components\Course.vue

// 检查支付状态
this.axios
 .get("http://localhost:80/order/checkOrderStatus",{
  params:{
    // 传递 订单编号 进行查询
    orderId: result.data.orderId
  }
})
.then((result) => {
  if(result.data.trade_state=="SUCCESS"){
    document.getElementById("statusText").innerHTML = "<i style='color:#00B38A' class='el-icon-success'></i> 支付成功!";
    // 支付成功
    this.updateOrder(20);
  }
  /*
  else if(result.data.trade_state=="NOTPAY"){
    document.getElementById("statusText").innerHTML = "<i style='color:#00B38A' class='el-icon-success'></i> 未支付!";
    this.updateOrder(10);
  }
  */
  // 3 秒后关闭二维码窗口
  let s = 3;
  this.closeQRForm(s);
})
.catch( (error)=>{
  this.$message.error("查询订单失败!");
});
// 更新订单的状态
updateOrder(statusCode){
  return this.axios
    .get("http://localhost:80/order/updateOrder",{
      params:{
        orderNo:this.orderNo,
        status:statusCode,
      }
    })
    .then((result) => {
       console.log("更新订单【" + this.orderNo + "】状态:" + statusCode);
    }).catch( (error)=>{
       this.$message.error("更新订单失败!");
    });
},

com.renda.order.controller.OrderController

package com.renda.order.controller;

import com.alibaba.dubbo.config.annotation.Reference;
import com.renda.entity.UserCourseOrder;
import com.renda.order.OrderService;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import java.util.List;

/**
 * @author Renda Zhang
 * @since 2020-10-16 1:35
 */
@RestController
@RequestMapping("order")
public class OrderController {

    // 远程消费
    @Reference
    private OrderService orderService;

    ...

    @GetMapping("updateOrder")
    public Integer updateOrder(String orderNo, Integer status) {
        System.out.println("订单编号 = " + orderNo);
        System.out.println("状态编码 = " + status);
        Integer integer = orderService.updateOrder(orderNo, status);
        System.out.println("订单更新 = " + integer);
        return integer;
    }

    ...
}

想了解更多,欢迎关注我的微信公众号:Renda_Zhang

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
该资源内项目源码是个人的课程设计、毕业设计,代码都测试ok,都是运行成功后才上传资源,答辩评审平均分达到96分,放心下载使用! ## 项目备注 1、该资源内项目代码都经过测试运行成功,功能ok的情况下才上传的,请放心下载使用! 2、本项目适合计算机相关专业(如计科、人工智能、通信工程、自动化、电子信息等)的在校学生、老师或者企业员工下载学习,也适合小白学习进阶,当然也可作为毕设项目、课程设计、作业、项目初期立项演示等。 3、如果基础还行,也可在此代码基础上进行修改,以实现其他功能,也可用于毕设、课设、作业等。 下载后请首先打开README.md文件(如有),仅供学习参考, 切勿用于商业用途。 该资源内项目源码是个人的课程设计,代码都测试ok,都是运行成功后才上传资源,答辩评审平均分达到96分,放心下载使用! ## 项目备注 1、该资源内项目代码都经过测试运行成功,功能ok的情况下才上传的,请放心下载使用! 2、本项目适合计算机相关专业(如计科、人工智能、通信工程、自动化、电子信息等)的在校学生、老师或者企业员工下载学习,也适合小白学习进阶,当然也可作为毕设项目、课程设计、作业、项目初期立项演示等。 3、如果基础还行,也可在此代码基础上进行修改,以实现其他功能,也可用于毕设、课设、作业等。 下载后请首先打开README.md文件(如有),仅供学习参考, 切勿用于商业用途。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值