• 显示支付结果_WebSocket实现_方案2


    流程分析

    在这里插入图片描述

    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述

    完整代码

    package com.qfedu.fmmall.websocket;
    
    import org.springframework.stereotype.Component;
    
    import javax.websocket.OnClose;
    import javax.websocket.OnOpen;
    import javax.websocket.Session;
    import javax.websocket.server.PathParam;
    import javax.websocket.server.ServerEndpoint;
    import java.io.IOException;
    import java.util.concurrent.ConcurrentHashMap;
    
    /**
     * @author beyondx
     * @date Created in 2022/08/21/ 14:31
     */
    @Component
    @ServerEndpoint("/webSocket/{oid}") // 表示这个类, 可以接收 别人的请求; 接收 websocket请求
    public class WebSocketServer {
    
        private static ConcurrentHashMap<String, Session> sessionMap = new ConcurrentHashMap<>();
    
        /**
         * 前端发送请求, 建立 webSocket链接, 就会执行 @OnOpen方法
         * @param orderId 订单id
         * @param session 代表连接
         */
        @OnOpen
        public void open(@PathParam("oid") String orderId, Session session) {
            System.out.println("------------建立连接:" + orderId);
            sessionMap.put(orderId, session);
        }
    
        /**
         * 前端 关闭页面, 或者 主动关闭 webSocket连接, 都会执行close
         * @param orderId
         */
        @OnClose
        public void close(@PathParam("oid") String orderId) {
            sessionMap.remove(orderId);
        }
    
        /**
         * 发送消息, 工具方法
         * @param orderId
         * @param msg
         */
        public static void sendMsg(String orderId, String msg) {
            try {
                Session session = sessionMap.get(orderId);
                session.getBasicRemote().sendText(msg);
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    package com.qfedu.fmmall.controller;
    
    import com.github.wxpay.sdk.WXPayUtil;
    import com.qfedu.fmmall.service.OrderService;
    import com.qfedu.fmmall.websocket.WebSocketServer;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.boot.autoconfigure.AutoConfigureOrder;
    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 javax.websocket.Session;
    import java.io.IOException;
    import java.util.HashMap;
    import java.util.Map;
    
    /**
     * 回调接口
     * @author beyondx
     * @date Created in 2022/08/20/ 21:17
     */
    @RestController
    @RequestMapping("/pay")
    public class PayController {
        @Autowired
        private OrderService orderService;
    
        /**
         * 支付回调; 接收 微信支付平台的 请求(通知)
         * 支付回到: 当用户支付成功之后, 支付凭条会向我们指定的服务器接口 放请求, 传递 订单支付状态数据
         * 1.接收微信支付平台传递的数据(使用request的输入流接收)
         */
        @RequestMapping("/callback")
        public String paySuccess(HttpServletRequest request) throws Exception {
            System.out.println("-----------------callback");
            ServletInputStream is = request.getInputStream();
            byte[] bs = new byte[1024];
            int len = -1;
            StringBuilder builder = new StringBuilder();
            while((len = is.read()) != -1) {
                builder.append(new String(bs, 0, len));
            }
            String s = builder.toString();
    
            // 使用帮助类, 将 xml结构的 字符串, 转化为 Map
            // 将接收得到的 (微信响应给到的数据) 转化为 Map
            // 以标签名作为 key, 标签中的值, 作为 value
            Map<String, String> map = WXPayUtil.xmlToMap(s);
            if(map != null && "success".equalsIgnoreCase(map.get("result_code"))) {
                // 支付成功; 2件事要做
                // 1.修改订单状态 为 待发货(已支付); 数据库操作; 直接使用 tkMapper操作的w
                // 订单 是 我们的 组件
                String orderId = map.get("out_treade_no");
                int i = orderService.updateOrderStatus(orderId, "2");
                System.out.println("--orderId: " + orderId);
                // 3.通过websocket连接, 向前端推送消息
                // 这个session 就是 跟 支付页面对应的 连接对象
                WebSocketServer.sendMsg(orderId, "1");
    
                // 2.响应 微信支付平台; 否则 微信支付平台, 会一直 发信息
                // 注意: 响应的时候, 最好不要用 原来的map, 这里是 新构造了一个map(resp)
                if(i > 0) {
                    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(resp);
                }
                // 这里没有 else也可以, 订单状态修改失败, 我希望你再通知我一次, 我再修改
    //            else {
    //                return null;
    //            }
            }
            return null;
        }
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    		<script type="text/javascript">
    			var baseUrl = "http://localhost:8080/";
    			var webSocketBaseUrl = "ws://localhost:8080/";
    			var vm = new Vue({
    				el: "#container",
    				data: {
    					orderInfo: {}
    				},
    				// vue声明周期:创建对象--beforeCreate--初始化data--created--加载模块--beforeMount--渲染数据--mounted
    				created: function () {
    					var jsonstr = localStorage.getItem("orderInfo");
    					if(jsonstr != null) {
    						localStorage.removeItem("orderInfo");
    					}
    					this.orderInfo = eval("("+jsonstr+")");
    
    					console.log(this.orderInfo.payUrl);
    				},
    				// mounted表示 vue的 渲染已经结束
    				mounted: function () {
    					// 渲染(显示)二维码
    					var str = this.orderInfo.payUrl;
    					var qrcode = new QRCode($("#payQrcodeDiv")[0], {
    						width: 200,
    						height: 200
    					});
    					qrcode.makeCode(this.orderInfo.payUrl);
    
    					// 前端发送websocket连接请求, 创建和 后端 socket的连接
    					console.log("-----1111");
    					// 建立 长连接
    					var webSocketUrl = webSocketBaseUrl + "webSocket/" + this.orderInfo.orderId;
    					websocket = new WebSocket(webSocketUrl);
    					// 只要后端通过 websocket 向次连接发消息, 就会触发 onmessage事件
    					websocket.onmessage = function (event) {
    						var msg = event.data;
    						if(msg == "1") {
    							// 订单支付完成
    							$("#div1").html("");
    						}
    					}
    				}
    			});
    		script>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
  • 相关阅读:
    Linux查看文件内容的几种方法
    AI角色对环境信息的感知方式
    libOpenDRIVE
    MySQL事务隔离机制与实现原理详解
    24、京东只换不修服务,电脑经常蓝屏申请只换不休记录
    CodeForces-1324F Maximum White Subtree(换根dp 联通子图信息查询)
    echarts折线图的symbol自定义样式
    1569. 将子数组重新排序得到同一个二叉查找树的方案数 数学+DFS
    Elasticsearch语法知多少之Template
    基于Python的算术编码的设计与实现
  • 原文地址:https://blog.csdn.net/beyondx/article/details/126450546