https://pay.weixin.qq.com/wiki/doc/api/native.php?chapter=6_1
微信demo文档:https://pay.weixin.qq.com/wiki/doc/api/download/WxPayAPI_JAVA.zip
<dependency>
<groupId>com.github.wxpaygroupId>
<artifactId>wxpay-sdkartifactId>
<version>0.0.3version>
dependency>
前端:vue
后端:springboot、mybatis-plus
com.github.wxpay.sdk.WXPay类下提供了对应的方法:
方法名 | 说明 |
---|---|
microPay | 刷卡支付 |
unifiedOrder | 统一下单 |
orderQuery | 查询订单 |
reverse | 撤销订单 |
closeOrder | 关闭订单 |
refund | 申请退款 |
refundQuery | 查询退款 |
downloadBill | 下载对账单 |
report | 交易保障 |
shortUrl | 转换短链接 |
authCodeToOpenid | 授权码查询openid |
package com.leo.fengmiweb.controller;
import com.github.wxpay.sdk.WXPay;
import com.leo.fengmiweb.config.MyWXPayConfig;
import com.leo.mall.pojo.ResultData;
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;
@RestController
@RequestMapping("orders")
public class OrderController {
@GetMapping("payInfo")
public ResultData getPayInfo(){
System.setProperty("https.protocols", "TLSv1,TLSv1.1,TLSv1.2");
try {
MyWXPayConfig myWXPayConfig = new MyWXPayConfig();
//导入配置文件
WXPay wxPay = new WXPay(myWXPayConfig);
//封装发送的数据
HashMap<String, String> data = new HashMap<>();
data.put("body", "leo发起支付");
data.put("out_trade_no", "2016090910595900004012");
data.put("fee_type", "CNY"); //人民币
data.put("total_fee", "1"); //支付金额
//data.put("spbill_create_ip", "123.12.12.123");
data.put("notify_url", "/notifyPayInfo"); //回调地址
data.put("trade_type", "NATIVE"); // 此处指定为扫码支付
//data.put("product_id", "111"); //产品id信息
//向微信发起请求
Map<String, String> resultMap = wxPay.unifiedOrder(data);
//给前端返回的数据(成功返回)
return new ResultData(0,"下单成功",resultMap.get("code_url"));
} catch (Exception e) {
e.printStackTrace();
}
//给前端返回的数据(失败返回)
return new ResultData(100,"下单失败");
}
}
package com.leo.fengmiweb.config;
import com.github.wxpay.sdk.WXPayConfig;
import java.io.InputStream;
public class MyWXPayConfig implements WXPayConfig {
@Override
public String getAppID() {
return "wx632cf211f8122xxx";
}
@Override
public String getMchID() {
return "1499844xxx";
}
@Override
public String getKey() {
return "sbNCm1JnevqI36LrExxaxFwcaT0hkGxFxxx";
}
@Override
public InputStream getCertStream() {
return null;
}
@Override
public int getHttpConnectTimeoutMs() {
return 0;
}
@Override
public int getHttpReadTimeoutMs() {
return 0;
}
}
调用回调接口当支付成功向微信返回success
package com.leo.fengmiweb.controller;
import com.github.wxpay.sdk.WXPayUtil;
import com.leo.fengmiweb.websocket.WebSocketServer;
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
public class PayController {
@RequestMapping("/payNotify")
public String payNotify(HttpServletRequest httpServletRequest){
//获取Xml数据
StringBuffer stringBuffer = new StringBuffer();
try {
ServletInputStream inputStream = httpServletRequest.getInputStream();
byte[] bytes = new byte[1024];
int len;
while ((len = inputStream.read(bytes)) != -1){
stringBuffer.append(new String(bytes,0,len));
}
Map<String, String> map = WXPayUtil.xmlToMap(stringBuffer.toString());
if (map.get("result_code").equals("SUCCESS")){
System.out.println(map);
//websocket返回
WebSocketServer.onMessage("4001","支付成功");
//支付成功给微信返回SUCCESS
HashMap<String, String> hashMap = new HashMap<>();
hashMap.put("result_code","SUCCESS");
hashMap.put("return_msg","SUCCESS");
hashMap.put("appid",map.get("appid"));
hashMap.put("return_code","SUCCESS");
return WXPayUtil.mapToXml(hashMap);
}else {
System.out.println("支付失败");
}
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
}
配置websocket与前端进行通信
package com.leo.fengmiweb.config;
import org.springframework.boot.SpringBootConfiguration;
import org.springframework.context.annotation.Bean;
import org.springframework.web.socket.config.annotation.WebSocketMessageBrokerConfigurer;
import org.springframework.web.socket.server.standard.ServerEndpointExporter;
@SpringBootConfiguration
public class WebSocketConfig implements WebSocketMessageBrokerConfigurer {
@Bean
public ServerEndpointExporter serverEndpointExporter() {
return new ServerEndpointExporter();
}
}
编写websocket通信代码
package com.leo.fengmiweb.websocket;
import com.leo.mall.pojo.ResultData;
import org.springframework.stereotype.Component;
import javax.websocket.OnClose;
import javax.websocket.OnMessage;
import javax.websocket.OnOpen;
import javax.websocket.Session;
import javax.websocket.server.PathParam;
import javax.websocket.server.ServerEndpoint;
import java.io.IOException;
import java.net.Socket;
import java.util.concurrent.ConcurrentHashMap;
@Component
@ServerEndpoint("/WebSocketServer/{orderId}")
public class WebSocketServer {
private static ConcurrentHashMap<String, Session> concurrentHashMap = new ConcurrentHashMap<>()
//当创建socket时调用,创建一个session会话
@OnOpen
public void onOpen(@PathParam("orderId") String orderId, Session session) {
concurrentHashMap.put(orderId, session);
}
//当关闭socket时调用,关闭当前会话
@OnClose
public void onClose(@PathParam("orderId") String orderId, Session session) {
concurrentHashMap.remove(orderId);
}
//给前端返回msg数据
public static void onMessage(String orderId, String msg) {
//创建当前session会话
Session session = concurrentHashMap.get(orderId);
try {
//给session会话返回一条数据
session.getBasicRemote().sendText(msg);
} catch (IOException e) {
e.printStackTrace();
}
}
}
axios接口代码
import request from '@/utils/request'
export function getCodeUrl() {
return request({
url: `/orders/payInfo`,
method: 'get'
})
}
前端页面代码
<template>
<div>
<Header>Header>
<common-header>
<template v-slot:title>
我的购物车
template>
common-header>
<el-divider>el-divider>
<div class="pay">
<el-card class="box-card" >
<div slot="header" class="clearfix">
<h3>请扫码支付h3>
div>
<div >
<div style="display:flex; flex-direction:column;align-items: center;">
<span style="margin-bottom:30px;font-size:18px">订单将在<b style="color:red;font-size:20px">30分钟b>后关闭span>
<div ref="refCode">div>
<el-button type="danger" round style="width:160px;margin-top:30px">取消支付el-button>
div>
div>
el-card>
div>
div>
template>
<script>
import CommonHeader from '../components/CommonHeader.vue'
import Header from '@/components/Index/Header'
import {getCodeUrl} from '@/api/OrderPay'
import QRCode from 'qrcodejs2';
export default {
components: {
CommonHeader,
Header
},
data: () => ({
code_url: '',
orderId: '4001',
}),
methods:{
getPayUrl(){
let _this = this;
getCodeUrl().then(res =>{
_this.code_url = res.data;
window.console.log(_this.code_url);
this.createQRCode(_this.code_url);
})
},
//二维码
createQRCode(code_url){
new QRCode(this.$refs.refCode,{ //给div块返回二维码数据
text:code_url,
width:200,
height:200,
colorDark:'#000000',
colorLight:'#ffffff',
correctLevel:QRCode.CorrectLevel.H
})
}
},
mounted:function(){
this.getPayUrl();
let _this = this;
//跟服务端建立websocket连接
var webSocket = new WebSocket("ws://localhost:9090/WebSocketServer/" + this.orderId); //ws协议
//监听socket
webSocket.onmessage = function(event){
var msg = event.data;
if (msg == "支付成功"){
_this.$message.success("支付成功,3秒后跳转新页面。")
window.setTimeout(function(){ //3秒后执行页面跳转
_this.$router.push({ //路由跳转
path:'my-order'
},30000) //3秒
})
}
}
}
}
script>
<style scoped>
.pay{
width: 60%;
margin: auto;
}
style>
Caused by: java.lang.IllegalArgumentException: LoggerFactory is not a Logback LoggerContext but Logback is on the classpath. Either remove Logback or the competing implementation (class org.slf4j.impl.Log4jLoggerFactory loaded from file:/E:/IT_zhengqing/soft/soft-dev/Maven/repository-zhengqing/org/slf4j/slf4j-log4j12/1.7.30/slf4j-log4j12-1.7.30.jar). If you are using WebLogic you will need to add 'org.slf4j' to prefer-application-packages in WEB-INF/weblogic.xml: org.slf4j.impl.Log4jLoggerFactory
at org.springframework.util.Assert.instanceCheckFailed(Assert.java:699)
at org.springframework.util.Assert.isInstanceOf(Assert.java:599)
at org.springframework.boot.logging.logback.LogbackLoggingSystem.getLoggerContext(LogbackLoggingSystem.java:284)
at org.springframework.boot.logging.logback.LogbackLoggingSystem.beforeInitialize(LogbackLoggingSystem.java:104)
at org.springframework.boot.context.logging.LoggingApplicationListener.onApplicationStartingEvent(LoggingApplicationListener.java:232)
at org.springframework.boot.context.logging.LoggingApplicationListener.onApplicationEvent(LoggingApplicationListener.java:213)
at org.springframework.context.event.SimpleApplicationEventMulticaster.doInvokeListener(SimpleApplicationEventMulticaster.java:172)
at org.springframework.context.event.SimpleApplicationEventMulticaster.invokeListener(SimpleApplicationEventMulticaster.java:165)
at org.springframework.context.event.SimpleApplicationEventMulticaster.multicastEvent(SimpleApplicationEventMulticaster.java:139)
at org.springframework.context.event.SimpleApplicationEventMulticaster.multicastEvent(SimpleApplicationEventMulticaster.java:127)
at org.springframework.boot.context.event.EventPublishingRunListener.starting(EventPublishingRunListener.java:74)
at org.springframework.boot.SpringApplicationRunListeners.starting(SpringApplicationRunListeners.java:47)
at org.springframework.boot.SpringApplication.run(SpringApplication.java:305)
at org.springframework.boot.SpringApplication.run(SpringApplication.java:1237)
at org.springframework.boot.SpringApplication.run(SpringApplication.java:1226)
at com.zhengqing.system.SystemApplication.main(SystemApplication.java:15)
... 5 more
解决办法:
删除slf4j-log4j依赖文件
System Exception:javax.net.ssl.SSLHandshakeException: Remote host closed connection during handshake
at sun.security.ssl.SSLSocketImpl.readRecord(SSLSocketImpl.java:992)
at sun.security.ssl.SSLSocketImpl.performInitialHandshake(SSLSocketImpl.java:1375)
at sun.security.ssl.SSLSocketImpl.startHandshake(SSLSocketImpl.java:1403)
at sun.security.ssl.SSLSocketImpl.startHandshake(SSLSocketImpl.java:1387)
at org.apache.http.conn.ssl.SSLConnectionSocketFactory.createLayeredSocket(SSLConnectionSocketFactory.java:396)
at org.apache.http.conn.ssl.SSLConnectionSocketFactory.connectSocket(SSLConnectionSocketFactory.java:355)
at org.apache.http.impl.conn.DefaultHttpClientConnectionOperator.connect(DefaultHttpClientConnectionOperator.java:142)
at org.apache.http.impl.conn.PoolingHttpClientConnectionManager.connect(PoolingHttpClientConnectionManager.java:373)
at org.apache.http.impl.execchain.MainClientExec.establishRoute(MainClientExec.java:381)
at org.apache.http.impl.execchain.MainClientExec.execute(MainClientExec.java:237)
at org.apache.http.impl.execchain.ProtocolExec.execute(ProtocolExec.java:185)
at org.apache.http.impl.execchain.RetryExec.execute(RetryExec.java:89)
at org.apache.http.impl.execchain.RedirectExec.execute(RedirectExec.java:111)
at org.apache.http.impl.client.InternalHttpClient.doExecute(InternalHttpClient.java:185)
at org.apache.http.impl.client.CloseableHttpClient.execute(CloseableHttpClient.java:83)
at org.apache.http.impl.client.CloseableHttpClient.execute(CloseableHttpClient.java:108)
at com.ms.config.wx.sdk.WeChatUtil.processHttpPost(WeChatUtil.java:555)
at com.ms.config.wx.sdk.WeChatUtil.unifiedorder(WeChatUtil.java:135)
at com.ms.tpp.service.handler.wechat.WechatMiniProgramPaymentServiceImpl.pay(WechatMiniProgramPaymentServiceImpl.java:78)
解决办法:
第一行添加 System.setProperty(“https.protocols”, “TLSv1,TLSv1.1,TLSv1.2”);