IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 开发工具 -> 微信支付(Native下单)功能实现 -> 正文阅读

[开发工具]微信支付(Native下单)功能实现

案例代码展示

后端代码

MyWXPayConfig.java(WXPayConfig接口实现类)

package org.example.config;

import com.github.wxpay.sdk.WXPayConfig;

import java.io.InputStream;

public class MyWXPayConfig implements WXPayConfig {
    @Override
    //商户账号AppID
    public String getAppID() {
        return "信息较为敏感(可自行找微信平台申请)";
    }

    @Override
    //商户编号
    public String getMchID() {
        return "信息较为敏感(可自行找微信平台申请)";
    }

    @Override
    //商户Key(秘钥)
    public String getKey() {
        return "信息较为敏感(可自行找微信平台申请)";
    }

    @Override
    public InputStream getCertStream() {
        return null;
    }

    @Override
    public int getHttpConnectTimeoutMs() {
        return 0;
    }

    @Override
    public int getHttpReadTimeoutMs() {
        return 0;
    }
}

OrderController.java(前端访问此controller返回支付二维码)

package org.example.controller;

import com.github.wxpay.sdk.WXPay;
import org.example.config.MyWXPayConfig;
import org.example.model.Result;
import org.springframework.web.bind.annotation.CrossOrigin;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.HashMap;
import java.util.Map;

@RestController
@RequestMapping("/order")
@CrossOrigin("*")
public class OrderController {

    @PostMapping("/add")
    public Result add(){
        //微信支付:申请支付连接
        WXPay wxPay = new WXPay(new MyWXPayConfig());

        //通过当前时间和随机数结合生成订单编号outTradeNo
        LocalDateTime dateTime=LocalDateTime.now();
        DateTimeFormatter formatter=DateTimeFormatter.ofPattern("yyyyMMddHHmmss");
        String outTradeNo = formatter.format(dateTime);
        outTradeNo += (int)(Math.random()*899+100) + "";

        //在data集合中存储生成微信二维码的重要参数
        HashMap<String, String> data = new HashMap<>();

        data.put("body","可乐"); //支付说明
        data.put("out_trade_no",outTradeNo); //使用当前用户订单的编号作为当前支付交易的交易号
        data.put("fee_type","CNY"); //支付模式为人民币
        data.put("total_fee","1"); //设置支付金额为1分
        data.put("trade_type","NATIVE"); //交易的类型
        //需要注意的是这是需要自己配置内网穿透地址
        data.put("notify_url","http://m39shb.natappfree.cc/pay/success"); //设置支付完成时回调方法的接口

        //用于储存返回给前端必要数据的map集合(按需添加但是一般订单价格,订单编号,支付二维码编号都是必须的)
        HashMap<String, String> map = new HashMap<>();
        //储存订单编号
        map.put("number",outTradeNo);
        //储存订单价格
        map.put("price","18.8");

        try {
            //通过data集合中的重要参数请求微信服务器,然后微信服务器将参数封装到resp中
            Map<String, String> resp = wxPay.unifiedOrder(data);
            //通过微信服务器返回的数据得到微信支付二维码,然后通过map集合返回给前端
            map.put("resp",resp.get("code_url"));
        } catch (Exception e) {
            e.printStackTrace();
        }
        //封装返回给前端的信息
        return  Result.buildSuccess(map,"success");
    }

}

PayController.java(微信支付成功后调用的接口)

package org.example.controller;

import com.github.wxpay.sdk.WXPayUtil;
import org.example.model.Result;
import org.example.websocket.WebSocketService;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import javax.servlet.ServletInputStream;
import javax.servlet.http.HttpServletRequest;
import java.util.HashMap;
import java.util.Map;

@RestController
@RequestMapping("/pay")
public class PayController {

    @PostMapping("/success")
    public String success(HttpServletRequest request) throws  Exception{
        //获取请求输入流
        ServletInputStream is = request.getInputStream();
        //设置每次读取的大小为1024字节
        byte[] bs = new byte[1024];
        int len = -1;
        //将流中信息封装到StringBuffer字符串中
        StringBuffer buffer = new StringBuffer();
        //循环读取
        while ((len = is.read(bs)) != -1){
            buffer.append(new String(bs,0,len));
        }
        String str = buffer.toString();
        //通过此方法将规范的字符串转化为map集合
        Map<String, String> map = WXPayUtil.xmlToMap(str);

        //确认微信支付成功
        if (map != null && map.get("result_code").equalsIgnoreCase("success")){
            //支付成功后给前端反馈
            WebSocketService.sendMsg(map.get("out_trade_no"),"1");

            //封装返回给微信服务器的信息,理由是此订单已经支付完成了,不需要再对服务器请求了
            HashMap<String, String> resp = new HashMap<>();
            //以下是微信服务器所必要的信息
            resp.put("return_code","success");
            resp.put("return_msg","ok");
            resp.put("appid",map.get("appid"));
            resp.put("result_code","success");
            //微信需要接受的是String类型,所以需要以下方法转化为字符串
            return WXPayUtil.mapToXml(map);
        }
        return null;
    }

}

WebSocketConfig.java (websocket服务节点配置)

package org.example.websocket;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.socket.server.standard.ServerEndpointExporter;

@Configuration
public class WebSocketConfig {

    @Bean
    //添加websocket服务节点配置(创建一个websocket对象放到spring容器)
    public ServerEndpointExporter getServerEndpointExporter(){
        return new ServerEndpointExporter();
    }

}

WebSocketService.java(前端后端建立webSocket连接的业务类)

package org.example.websocket;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.stereotype.Component;
import org.springframework.web.socket.server.standard.ServerEndpointExporter;

import javax.websocket.OnClose;
import javax.websocket.OnOpen;
import javax.websocket.Session;
import javax.websocket.server.PathParam;
import javax.websocket.server.ServerEndpoint;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

@Component
@ServerEndpoint("/webSocket/{oid}")
public class WebSocketService {

    //将所有订单的编号对应前端反馈记录下来
    private static Map<String, Session> sessionMap = new ConcurrentHashMap<>();

    @OnOpen
    //WebSocket连接建立成功调用此方法
    public void open(@PathParam("oid") String orderId, Session session){
        System.out.println("open \t  orderId = " + orderId);
        sessionMap.put(orderId, session);
    }

    @OnClose
    //WebSocket连接销毁成功调用此方法
    public void close(@PathParam("oid") String orderId){
        System.out.println("close \t  orderId = " + orderId);
        sessionMap.remove(orderId);
    }

    //支付成功后给前端反馈对应参数
    public static void sendMsg(String orderId, String msg){
        try {
            System.out.print("sendMsg" + "\t");
            System.out.println(sessionMap);
            Session session = sessionMap.get(orderId);
            session.getBasicRemote().sendText(msg);
        }catch (Exception e){
            e.printStackTrace();
        }

    }

}

前端代码

<template>
  <div>
      <h1  v-if="options">订单编号:{{number}}</h1>
      <h1  v-if="options">订单价格:{{price}}</h1>
      <div id="test" >
        <div v-qr="options" v-if="options"></div>
        <div v-html="html"></div>
      </div>
      
  </div>
</template>

<script>
import axios from 'axios'

export default {
    data() {
        return {
            html: "",
            options: null,
            number: '',
            price: ''
        }
    },
    mounted: function() {
      
        axios.post('http://localhost:8080/order/add')
            .then(res => {    
                console.log(res.data);
                //后端返回的订单价格
                this.price = res.data.data.price
                //后端返回的订单编号
                this.number = res.data.data.number
                //生成二维码所必须的信息其中text代表二维码内容
                this.options = {
                    text: res.data.data.resp,
                    render: "canvas",
                    width: 256,
                    height: 256,
                    typeNumber: -1,
                    correctLevel: 2,
                    background: "#ffffff",
                    foreground: "#000000"
                }
                console.log(this.options)
                //设置webSocket连接路径
                var webSocketUrl = "ws://localhost:8080/webSocket/" + this.number
                //webSocket建立webSocket连接
                var webSocket = new WebSocket(webSocketUrl)
                //保存当前vue对象(此后可通过此变量改变其中属性)
                let tmp=this
                webSocket.onmessage = function(event){
                    //后端返回给前端的支付结果
                    var msg = event.data
                    console.log("支付了")
                    //“1”是自己在后端定义支付成功的返回值
                    if(msg == '1'){
                        console.log("支付完成!")
                        //支付成功后在页面上进行修饰
                        tmp.html = "<h2 style='font-size:20px; color:green'>订单支付完成!</h2>"
                        console.log(tmp.html)
                        tmp.options = null
                    }
                }
            })
    },
    methods: {
        addqrcode() {
            
            document.getElementById("test").innerHTML("<h2 style='font-size:20px; color:green'>订单支付完成!</h2>")

        }
    }


}

</script>

<style>
    .main {
        width: 200px;
        height: 200px;
        background-color: #fff;
        border: 1px solid black;
    }
    
</style>

微信支付的大致步骤简要分析

1. 首先准备好微信支付的开发环境与准备工作

1.1 配置maven(导入依赖)

导入spring-book依赖

  <parent>
    <artifactId>spring-boot-starter-parent</artifactId>
    <groupId>org.springframework.boot</groupId>
    <version>2.3.5.RELEASE</version>
  </parent>

导入微信核心依赖wxpay-sdk

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

导入websocket(前后端建立长连接来进行请求响应)

    <dependency>
      <groupId>org.springframework.boot</groupId>
      <artifactId>spring-boot-starter-websocket</artifactId>
      <version>2.5.2</version>
    </dependency>

1.2. 准备好WXPayConfig接口的实现类

准备好实现类所需要的核心参数比如

  • 商户编号
  • 商户账号AppID
  • 商户Key

原因:之所以需要这些重要参数就是因为申请微信连接的时候微信需要通过这些信息来确定商户。

2. 前端携带必要参数发送请求与相应

2.1 后端所需要的前端参数(基础)

  • 订单编号
  • 订单价格

2.2 前端所需要的后端参数(基础)

  • 生成二维码的编码如(“weixin://wxpay/bizpayurl?pr=vyg9Deyzz”)
  • 订单编号
  • 订单价格

3. 前端请求后端后所需要的必要操作

3.1 申请支付连接对象

//其中的new MyWXPayConfig()对象是实现了WXPayConfig接口的实现类
WXPay wxPay = new WXPay(new MyWXPayConfig());

3.2 准备微信生成二维码所需的必要参数(可见官网详情)

官网地址:https://pay.weixin.qq.com/wiki/doc/apiv3/apis/chapter3_4_1.shtml
通过查看官网地址可以发现,生成二维码等必要参数需要一个map集合
map集合的key值及其含义

key值含义
body支付说明
out_trade_no当前支付交易的交易号
fee_type设计支付模式(CNY表示人民币支付)
total_fee设置支付金额
trade_type设置交易类型(如:NATIVE)
notify_url设置支付完成的回调接口

3.3 通过微信服务器得到支付环境参数

//通过unifiedOrder()方法向微信服务器发送请求,然后返回如(微信二维码编码、订单编号等参数)
Map<String, String> resp = wxPay.unifiedOrder(data);

通过微信服务器得到参数之后,封装属性然后返回给前端

4. 前端生成二维码的必要准备

前端的开发环境是vue3.0,用的是node项目接口
生成二维码的工具是 “vue-qrcode-directive”

npm i vue-qrcode-directive #安装二维码生成工具

代码演示

# 微信二维码放置位置
<div v-qr="options" v-if="options"></div>

this.options = {
    text: "二维码中的具体内容",
    render: "canvas",
    width: 256,
    height: 256,
    typeNumber: -1,
    correctLevel: 2,
    background: "#ffffff",
    foreground: "#000000"
}

5. 用户扫描二维码到支付成功后相关步骤

5.1 使用webSocket与后端建立长连接(等待后端支付成功的反馈)

1. 前端部分:

var webSocketUrl = "ws://localhost:8080/webSocket/" + "从后端传递过来的订单编号"
var webSocket = new WebSocket(webSocketUrl)
webSocket.onmessage = function(event){
	“支付成功之后会调用该方法”
}

2. 后端部分:

  • 第一步:添加websocket服务节点配置(创建一个websocket对象放到spring容器)
  • 第二步: 创建websocket连接,销毁websocket连接,对前端通知支付成功等功能

2. 编写微信支付成功后微信所访问的接口

在此接口中需要:

  • 接收微信传输给服务器的信息(采用io的读取方式)
  • 将读取到的字符串通过WXPayUtil.xmlToMap(str)方式转化为map集合
  • 结合map集合中信息去调用支付成功的(websocket连接)返回给前端的方法
  开发工具 最新文章
Postman接口测试之Mock快速入门
ASCII码空格替换查表_最全ASCII码对照表0-2
如何使用 ssh 建立 socks 代理
Typora配合PicGo阿里云图床配置
SoapUI、Jmeter、Postman三种接口测试工具的
github用相对路径显示图片_GitHub 中 readm
Windows编译g2o及其g2o viewer
解决jupyter notebook无法连接/ jupyter连接
Git恢复到之前版本
VScode常用快捷键
上一篇文章      下一篇文章      查看所有文章
加:2021-11-10 12:36:19  更:2021-11-10 12:37:44 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/15 20:26:52-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码