案例代码展示
后端代码
MyWXPayConfig.java(WXPayConfig接口实现类)
package org.example.config;
import com.github.wxpay.sdk.WXPayConfig;
import java.io.InputStream;
public class MyWXPayConfig implements WXPayConfig {
@Override
public String getAppID() {
return "信息较为敏感(可自行找微信平台申请)";
}
@Override
public String getMchID() {
return "信息较为敏感(可自行找微信平台申请)";
}
@Override
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());
LocalDateTime dateTime=LocalDateTime.now();
DateTimeFormatter formatter=DateTimeFormatter.ofPattern("yyyyMMddHHmmss");
String outTradeNo = formatter.format(dateTime);
outTradeNo += (int)(Math.random()*899+100) + "";
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");
data.put("trade_type","NATIVE");
data.put("notify_url","http://m39shb.natappfree.cc/pay/success");
HashMap<String, String> map = new HashMap<>();
map.put("number",outTradeNo);
map.put("price","18.8");
try {
Map<String, String> resp = wxPay.unifiedOrder(data);
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();
byte[] bs = new byte[1024];
int len = -1;
StringBuffer buffer = new StringBuffer();
while ((len = is.read(bs)) != -1){
buffer.append(new String(bs,0,len));
}
String str = buffer.toString();
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");
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
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
public void open(@PathParam("oid") String orderId, Session session){
System.out.println("open \t orderId = " + orderId);
sessionMap.put(orderId, session);
}
@OnClose
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:
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接口的实现类
准备好实现类所需要的核心参数比如
原因:之所以需要这些重要参数就是因为申请微信连接的时候微信需要通过这些信息来确定商户。
2. 前端携带必要参数发送请求与相应
2.1 后端所需要的前端参数(基础)
2.2 前端所需要的后端参数(基础)
- 生成二维码的编码如(“weixin://wxpay/bizpayurl?pr=vyg9Deyzz”)
- 订单编号
- 订单价格
3. 前端请求后端后所需要的必要操作
3.1 申请支付连接对象
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 通过微信服务器得到支付环境参数
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连接)返回给前端的方法
|