1、支付申请
第一步:注册公众号(类型须为:服务号)
注册地址:https://mp.weixin.qq.com/cgi-bin/registermidpage?action=index&lang=zh_CN
第二步:认证公众号
公众号认证后才可申请微信支付,认证费:300元/次。
第三步:提交资料申请微信支付
登录公众平台,点击左侧菜单【微信支付】,开始填写资料等待审核,审核时间为1-5个
工作日内。
第四步:开户成功,登录商户平台进行验证
资料审核通过后,请登录联系人邮箱查收商户号和密码,并登录商户平台填写财付通备
付金打的小额资金数额,完成账户验证。
第五步:在线签署协议
本协议为线上电子协议,签署后方可进行交易及资金结算,签署完立即生效。
第六步:申请成功获取秘钥
千锋
- 商户编号mch_id:1497984412
- 商户账号AppID:wx632c8f211f8122c6
- 商户Key:sbNCm1JnevqI36LrEaxFwcaT0hkGxFnC
2、微信支付开发文档
在线微信支付开发文档:https://pay.weixin.qq.com/wiki/doc/api/index.html
3、统一下单接口
第一步:pom依赖
<dependency>
<groupId>com.github.wxpay</groupId>
<artifactId>wxpay-sdk</artifactId>
<version>0.0.3</version>
</dependency>
第二步:微信支付配置类
public class MyWXPayConfig implements WXPayConfig {
@Override
public String getAppID() {
return "wx632c8f211f8122c6";
}
@Override
public String getMchID() {
return "1497984412";
}
@Override
public String getKey() {
return "sbNCm1JnevqI36LrEaxFwcaT0hkGxFnC";
}
@Override
public InputStream getCertStream() {
return null;
}
@Override
public int getHttpConnectTimeoutMs() {
return 0;
}
@Override
public int getHttpReadTimeoutMs() {
return 0;
}
}
第三步:调用统一下单接口
@PostMapping("{orderId}")
public ResultData addPayOrder(@PathVariable String orderId){
//向微信支付系统发送请求 XML
try {
ResultData resultData = orderService.getOrders(orderId);
Map<String,String> map = new HashMap<>();
map.put("body","锋迷商城");
map.put("out_trade_no",orderId+"");
map.put("fee_type","CNY");
map.put("total_fee","1"); //支付金额 单位为分
map.put("trade_type","NATIVE"); //支付类型 扫码支付
map.put("notify_url","/payNotify");// 支付回调地址 内网穿透
WXPay wxPay = new WXPay(new MyWXPayConfig());
//微信支付平台返回的结果
Map<String, String> resultMap = wxPay.unifiedOrder(map);
//支付连接
String code_url = resultMap.get("code_url");
Map<String,Object> respMap = new HashMap<>();
respMap.put("orders",resultData.getData());
respMap.put("code_url",code_url);
return new ResultData(0,"下单成功",respMap);
} catch (Exception e) {
e.printStackTrace();
}
return new ResultData(100,"下单失败");
}
4、 前端生成二维码
安装QRcode.js插件
npm i qrcodejs2 --save
导入QRcode
import QRCode from "qrcodejs2";
使用QRcode
<div ref="refCode"></div>
createQrCode(code_url){
new QRCode(this.$refs.refCode, {
text: code_url, //生成二维码的连接地址
width: 200, //二维码宽高
height: 200,
colorDark : "#000000", //二维码颜色
colorLight : "#ffffff", //二维码背景颜色
correctLevel : QRCode.CorrectLevel.H //容错率 由低到高 L M Q H
});
}
5、支付回调接口
支付回调:当用户支付成功之后,支付平台会向我们指定的服务器接口发送请求传递订单支付状态数据
@RestController
public class PayController {
@Autowired
private OrderService orderService;
@RequestMapping("/payNotify")
public String payNotify(HttpServletRequest request) throws Exception {
System.out.println("微信支付平台通知....");
//获取微信支付平台发送的数据信息
ServletInputStream in = request.getInputStream();
byte[] buf = new byte[1024];
int len;
StringBuffer sb = new StringBuffer();
while((len = in.read(buf))!=-1){
sb.append(new String(buf,0,len));
}
System.out.println(sb+"----");
//微信返回的结果为xml格式,将其转换成map集合
Map<String, String> resultMap = WXPayUtil.xmlToMap(sb.toString());
//表示支付成功
if(resultMap != null && resultMap.get("result_code").equalsIgnoreCase("success")){
//修改订单状态 为“已支付”
String ordersId = resultMap.get("out_trade_no");
ResultData resultData = orderService.updateOrdersStatus(ordersId);
//向前端推送消息
WebSocketServer.sendMsg(ordersId,"OK");
//响应结果到微信平台
if(resultData.getCode()==0){
HashMap<String,String> resp = new HashMap<>();
resp.put("return_code","success");
resp.put("return_msg","OK");
resp.put("appid",resultMap.get("appid"));
resp.put("result_code","success");
return WXPayUtil.mapToXml(resp);
}
}
return null;
}
}
6、Ngrok实现内网穿透
官网:https://ngrok.cc/
工具下载:https://ngrok.cc/download.html
申请隧道
隧道ID
启动Ngrok
修改支付回调接口地址
map.put("notify_url","http://hawa.free.idcfengye.com/payNotify");
7、webSocket消息推送
第一步:导入依赖
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-websocket</artifactId>
</dependency>
第二步:创建WebScoket配置类
@Configuration
public class WebSocketConfig {
@Bean
public ServerEndpointExporter getServerEndpointExporter(){
return new ServerEndpointExporter();
}
}
第三步:创建websocket服务端
@Component
@ServerEndpoint("/webSocket/{oid}")
public class WebSocketServer {
private static ConcurrentHashMap<String,Session> sessionMap = new ConcurrentHashMap<>();
/**前端发送请求建立websocket连接,就会执行@OnOpen方法**/
@OnOpen
public void open(@PathParam("oid") String orderId, Session session){
sessionMap.put(orderId,session);
}
/**前端关闭页面或者主动关闭websocket连接,都会执行close**/
@OnClose
public void close(@PathParam("oid") String orderId){
sessionMap.remove(orderId);
}
/**主动向前端发送数据**/
public static void sendMsg(String orderId,String msg){
try {
Session session = sessionMap.get(orderId);
session.getBasicRemote().sendText(msg);
}catch (Exception e){
e.printStackTrace();
}
}
}
第四步:支付成功向前端推送消息
@RestController
public class PayController {
@Autowired
private OrderService orderService;
@RequestMapping("/payNotify")
public String payNotify(HttpServletRequest request) throws Exception {
System.out.println("微信支付平台通知....");
//获取微信支付平台发送的数据信息
ServletInputStream in = request.getInputStream();
byte[] buf = new byte[1024];
int len;
StringBuffer sb = new StringBuffer();
while((len = in.read(buf))!=-1){
sb.append(new String(buf,0,len));
}
System.out.println(sb+"----");
//微信返回的结果为xml格式,将其转换成map集合
Map<String, String> resultMap = WXPayUtil.xmlToMap(sb.toString());
//表示支付成功
if(resultMap != null && resultMap.get("result_code").equalsIgnoreCase("success")){
//修改订单状态 为“已支付”
String ordersId = resultMap.get("out_trade_no");
ResultData resultData = orderService.updateOrdersStatus(ordersId);
//向前端推送消息
WebSocketServer.sendMsg(ordersId,"OK");
//响应结果到微信平台
if(resultData.getCode()==0){
HashMap<String,String> resp = new HashMap<>();
resp.put("return_code","success");
resp.put("return_msg","OK");
resp.put("appid",resultMap.get("appid"));
resp.put("result_code","success");
return WXPayUtil.mapToXml(resp);
}
}
return null;
}
}
第五步:前端进入到支付页面就建立与服务器的webSocket连接,并监听服务的消息
//建立与服务端你的websocket连接
var websocket = new WebSocket( "ws://localhost:8080/webSocket/"+ this.ordersId );
//只要后端通过websocket向此连接发消息就会触发onmessage事件
let _this = this;
websocket.onmessage = function(event){
var msg = event.data;
if(msg=="OK"){
_this.$message.success("支付成功!!!");
window.setTimeout(()=>{
//3秒钟后,添加成功跳转到订单查询页面
_this.$router.push({
path:'/my-order'
})
},3000)
}
}