Java微信扫码支付模式二Demo ,websocket直接运行版本

概述

场景介绍 Java微信扫码支付模式二Demo ,整合官网直接运行版本 的基础上,增加了websocket通知功能和查询订单 扫码支付模式二,用于web网站。用户点击支付后,根据商品生成的二维码,用户扫码完成支付,手机提示支付成功,微信支付系统把交易结果发送到回调接口中。

详细

功能演示

本地版本:

穿透.png

本地.png

 

一、相关配置

微信公众号AppID(登录微信公众平台-->开发-->基本设置-->开发者ID(AppID))

微信公众号AppSecret(登录微信公众平台-->开发-->基本设置-->开发者密码(AppSecret))

微信支付商户号(登录微信商户平台-->账户中心-->商户信息-->基本账户信息-->微信支付商户号)

微信支付商户API密钥(登录微信商户平台-->账户中心-->API安全-->API密钥-->设置API密钥)

application.properties 文件 (Demo上都有官网的默认值,不需要修改直接使用,省心!

QQ图片20210108093355.png

支付扫码模式二,流程图

https://pay.weixin.qq.com/wiki/doc/api/native.php?chapter=6_5

SDK与DEMO下载

https://pay.weixin.qq.com/wiki/doc/api/native.php?chapter=11_1

二、目录结构

QQ图片20210118154932.png

准备工作

(1)内网穿透工具

让外网能直接访问,你本地的服务,场景用于,接口调试,支付方面等等。

为了大家找了一个,免费配置简单的。绝对不是卖广告,之前用过花生壳,麻烦到要死坑哇~,现在的所有穿透都要身份证登记,很正常国家出了对应的法规。

下载地址:NATAPP-内网穿透 基于ngrok的国内高速内网映射工具

配置和使用说明:外网映射---内网穿透工具NATAPP---灵感源自QQ浏览器微信调试工具_natapp+xampp_kingrome2009的博客-CSDN博客

四、功能演示

本地版本:请看最上面视频及流程图,访问链接  http://127.0.0.1:8080

穿透版本:请看最上面视频及流程图,访问链接 必须使用穿透工具,步骤请看视频~

支付流程:

QQ图片20210402151909.jpg

图片111111.jpg

五、前端代码

<html>
<head >
    <title>微信支付二维码生成</title>
    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
    <script type="text/javascript" src="/js/jquery/jquery-3.3.1.min.js"></script>
    <script type="text/javascript" src="/js/websocket/sockjs.min.js"></script>
    <script type="text/javascript" src="/js/websocket/stomp.min.js"></script>
    <script type='text/javascript'>
 
        $(function () {
            wxQRCode();
        });
 
        //当前查询次数
        var nowQueryCount = 0;
        //生成二维码
        function wxQRCode(){
            getOutTradeNo();
            var outTradeNo = $("#outTradeNo").val();
            $("#payImg").attr("src",'/wxPay/payUrl'+"?totalFee="+ $("#totalFee").val()+"&outTradeNo=" + outTradeNo + "&random=" + new Date().getTime());
            //重置查询次数
            nowQueryCount = 0;
            queryOrder();
        }
 
        //获取流水号
        function getOutTradeNo(){
            $.ajax({
                type : "POST",
                url : '/wxPay/outTradeNo',
                async : false,
                success : function(jsonData) {
                    if(jsonData.code == 200){
                        var outTradeNo = jsonData.data;
                        $("h2").html(outTradeNo);
                        $("#outTradeNo").val(outTradeNo);
                        //启动webSocket监听器
                        webSocketListener(outTradeNo);
                    }else{
                        alert(jsonData.message);
                    }
                    return false;
                },
                error:function(XMLHttpRequest,textStatus,errorThrown){
                    alert("服务器错误!状态码:"+XMLHttpRequest.status);
                    // 状态
                    console.log(XMLHttpRequest.readyState);
                    // 错误信息
                    console.log(textStatus);
                    return false;
                }
            });
        }
 
        var stompClient = null;
        //webSocketListener 监听器 是否已经支付
        function webSocketListener(outTradeNo){
            //多次生成二维码,关闭上一次webSocket,避免浏览器负担
            closeWebSocket();
            if ("WebSocket" in window){
                    var socket = new SockJS('/websocket');
                    stompClient = Stomp.over(socket);
                    stompClient.connect({}, function (frame) {
                        console.log('Connected: ' + frame);
                        stompClient.subscribe('/member/'+outTradeNo+'/send/message', function(jsonData) {
                            jsonData = JSON.parse(jsonData.body);
                            if(jsonData.code == 200){
                                var data = jsonData.data;
                                var outTradeNo = data.outTradeNo;
                                var transactionId = data.transactionId;
                                var payDateStr = data.payDateStr;
                                console.log("WebSocket:"+"\n"+"商户订单号:"+outTradeNo +"\n"+"微信支付订单号:"+transactionId+"\n"+"支付时间:"+payDateStr);
                                alert("WebSocket:"+"\n"+"商户订单号:"+outTradeNo +"\n"+"微信支付订单号:"+transactionId+"\n"+"支付时间:"+payDateStr);
                                closeWebSocket();
                                return false;
                            }
                        });
                    });
            }else{
                alert('我不兼容WebSocket');
            }
        }
 
        //关闭webSocket
        function closeWebSocket(){
            if (stompClient != null) {
                stompClient.disconnect();
            }
        }
 
        //查询订单总次数
        var autoQueryCount = 100;
        //定时器
        var queryOrderSetTimeout = null;
        //查询订单状态
        function queryOrder(){
            nowQueryCount ++;
            var outTradeNo = $("#outTradeNo").val();
            $.ajax({
                type : "POST",
                url : '/wxPay/payStatus?outTradeNo='+ outTradeNo +"&random=" + new Date().getTime(),
                async : false,
                success : function(jsonData) {
                    if(jsonData.code == 200){
                        var data = jsonData.data;
                        var outTradeNo = data.outTradeNo;
                        var transactionId = data.transactionId;
                        var payDateStr = data.payDateStr;
                        console.log("查询订单:"+"\n"+"商户订单号:"+outTradeNo +"\n"+"微信支付订单号:"+transactionId+"\n"+"支付时间:"+payDateStr);
                        alert("查询订单:"+"\n"+"商户订单号:"+outTradeNo +"\n"+"微信支付订单号:"+transactionId+"\n"+"支付时间:"+payDateStr);
                        //已支付,清除定时器
                        clearTimeout(queryOrderSetTimeout);
                        return false;
                    }else{
                        if(nowQueryCount < autoQueryCount){
                            //定时查询订单状态,5秒查询一次
                            console.log(currentTime()+" queryOrder:"+jsonData.message+" 查询次数:"+nowQueryCount);
                            queryOrderSetTimeout = setTimeout(queryOrder,5*1000);
                        }else{
                            console.log(currentTime()+" queryOrder:"+jsonData.message+" 查询结束");
                            //超过查询次数,清除定时器
                            clearTimeout(queryOrderSetTimeout);
                            return false;
                        }
                    }
                },
                error:function(XMLHttpRequest,textStatus,errorThrown){
                    alert("服务器错误!状态码:"+XMLHttpRequest.status);
                    // 状态
                    console.log(XMLHttpRequest.readyState);
                    // 错误信息
                    console.log(textStatus);
                    return false;
                }
            });
        }
 
 
        //当时时间
        function currentTime(){
            var date = new Date();
            this.year = date.getFullYear();
            this.month = date.getMonth() + 1;
            this.date = date.getDate();
            this.hour = date.getHours() < 10 ? "0" + date.getHours() : date.getHours();
            this.minute = date.getMinutes() < 10 ? "0" + date.getMinutes() : date.getMinutes();
            this.second = date.getSeconds() < 10 ? "0" + date.getSeconds() : date.getSeconds();
            var currentTime = this.year+'-'+this.month + '-' + this.date + ' ' + this.hour + ':' + this.minute + ':' + this.second;
            return currentTime;
        }
 
    </script>
</head>
<body>
<p>订单流水号:<h2></h2></p>
支付金额:<input id="totalFee"    type="text"   value="0.01"/>
<button type="button" onclick="wxQRCode();" style="cursor: pointer">生成二维码</button>
<input id="outTradeNo"  type="hidden" />
&nbsp;&nbsp;<img  id="payImg" width="300" height="300"  >
</body>
</html>

六、后端代码

pom.xml

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
   xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
   <modelVersion>4.0.0</modelVersion>
 
   <groupId>com.juno</groupId>
   <artifactId>weixin-websoket</artifactId>
   <version>0.0.1-SNAPSHOT</version>
   <packaging>jar</packaging>
 
   <name>weixin-websoket</name>
   <description>Demo project for Spring Boot</description>
 
   <parent>
      <groupId>org.springframework.boot</groupId>
      <artifactId>spring-boot-starter-parent</artifactId>
      <version>2.4.0</version>
      <relativePath/> <!-- lookup parent from repository -->
   </parent>
 
   <properties>
      <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
      <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
      <java.version>1.8</java.version>
      <commons-lang3.version>3.7</commons-lang3.version>
      <commons-collections.version>3.2.2</commons-collections.version>
      <com.google.zxing.version>3.3.3</com.google.zxing.version>
      <fastjson.version>1.2.46</fastjson.version>
   </properties>
 
   <dependencies>
      <!-- mvc支持-->
      <dependency>
         <groupId>org.springframework.boot</groupId>
         <artifactId>spring-boot-starter-web</artifactId>
      </dependency>
 
      <dependency>
         <groupId>org.springframework.boot</groupId>
         <artifactId>spring-boot-starter-thymeleaf</artifactId>
      </dependency>
 
      <!-- 热部署模块 -->
      <dependency>
         <groupId>org.springframework.boot</groupId>
         <artifactId>spring-boot-devtools</artifactId>
         <optional>true</optional>
      </dependency>
 
      <dependency>
         <groupId>org.springframework.boot</groupId>
         <artifactId>spring-boot-starter-test</artifactId>
         <scope>test</scope>
      </dependency>
 
      <!-- Commons utils begin -->
      <dependency>
         <groupId>org.apache.commons</groupId>
         <artifactId>commons-lang3</artifactId>
         <version>${commons-lang3.version}</version>
      </dependency>
      <dependency>
         <groupId>commons-collections</groupId>
         <artifactId>commons-collections</artifactId>
         <version>${commons-collections.version}</version>
      </dependency>
      <!-- Commons utils end -->
 
      <!-- google 生成二维码 begin-->
      <dependency>
         <groupId>com.google.zxing</groupId>
         <artifactId>javase</artifactId>
         <version>${com.google.zxing.version}</version>
      </dependency>
      <!-- google 生成二维码 end-->
 
      <!-- JSONObject JSONArray begin -->
      <dependency>
         <groupId>com.alibaba</groupId>
         <artifactId>fastjson</artifactId>
         <version>${fastjson.version}</version>
      </dependency>
      <!-- JSONObject JSONArray end -->
 
      <!-- websocket begin -->
      <dependency>
         <groupId>org.springframework.boot</groupId>
         <artifactId>spring-boot-starter-websocket</artifactId>
      </dependency>
      <dependency>
         <groupId>junit</groupId>
         <artifactId>junit</artifactId>
         <scope>test</scope>
      </dependency>
      <!-- websocket end -->
 
   </dependencies>
 
   <build>
      <plugins>
         <plugin>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-maven-plugin</artifactId>
            <configuration>
               <fork>true</fork>
            </configuration>
         </plugin>
      </plugins>
   </build>
 
 
</project>

WxPayController.java

package com.juno.weixin.modules.controller.wx;
 
import com.juno.weixin.modules.common.util.JSONResponse;
import com.juno.weixin.modules.common.wx.WxConfig;
import com.juno.weixin.modules.common.wx.WxConstants;
import com.juno.weixin.modules.common.wx.WxUtil;
import com.juno.weixin.modules.service.WxMenuService;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.messaging.simp.SimpMessagingTemplate;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;
 
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
 
/**
 * 微信支付控制类
 * @author lujunjie
 * @date   2020/12/31
 */
@Controller
public class WxPayController {
 
    @Autowired
    private WxMenuService wxMenuService;
 
    /**
     * 二维码首页
     */
    @RequestMapping(value = {"/"}, method = RequestMethod.GET)
    public String wxPayList(Model model){
        return "/wxPayList";
    }
 
    /**
     * 获取流水号
     */
    @RequestMapping(value = {"/wxPay/outTradeNo"})
    @ResponseBody
    public JSONResponse getOutTradeNo(){
        //商户订单号
        return JSONResponse.success(WxUtil.mchOrderNo());
    }
 
    final private String signType = WxConstants.SING_MD5;
    /**
     * 统一下单-生成二维码
     */
    @RequestMapping(value = {"/wxPay/payUrl"})
    public void payUrl(HttpServletRequest request, HttpServletResponse response,
                       @RequestParam(value = "totalFee")Double totalFee,
                       @RequestParam(value = "outTradeNo")String outTradeNo) throws Exception{
        WxUtil.writerPayImage(response,wxMenuService.wxPayUrl(totalFee,outTradeNo,signType));
    }
    /**
     * 查询订单状态
     */
    @RequestMapping(value = {"/wxPay/payStatus"})
    @ResponseBody
    public JSONResponse payStatus(HttpServletRequest request, HttpServletResponse response,
                       @RequestParam(value = "outTradeNo")String outTradeNo) throws Exception{
        return this.wxMenuService.queryOrder(outTradeNo,signType);
    }
 
    @Autowired
    private SimpMessagingTemplate simpMessagingTemplate;
 
    /**
     * 统一下单-通知链接
     */
    @RequestMapping(value = {"/wxPay/unifiedorderNotify"})
    public void unifiedorderNotify(HttpServletRequest request, HttpServletResponse response) throws Exception{
 
        //商户订单号
        String outTradeNo = null;
        String xmlContent = "<xml>" +
                "<return_code><![CDATA[FAIL]]></return_code>" +
                "<return_msg><![CDATA[签名失败]]></return_msg>" +
                "</xml>";
 
        try{
            String requstXml = WxUtil.getStreamString(request.getInputStream());
            Map<String,String> map = WxUtil.xmlToMap(requstXml);
            String returnCode= map.get(WxConstants.RETURN_CODE);
            //校验一下 ,判断是否已经支付成功
            if(StringUtils.isNotBlank(returnCode) && StringUtils.equals(returnCode,"SUCCESS")  &&  WxUtil.isSignatureValid(map, WxConfig.key,signType)){
                System.out.println("------------"+"统一下单-通知链接:支付成功"+"------------");
                System.out.println("统一下单-通知链接:"+"requstXml : " + requstXml);
                //商户订单号
                outTradeNo = map.get("out_trade_no");
                System.out.println("统一下单-通知链接 "+"outTradeNo : "+ outTradeNo);
                //微信支付订单号
                String transactionId = map.get("transaction_id");
                System.out.println("统一下单-通知链接 "+"transactionId : "+ transactionId);
                //支付完成时间
                SimpleDateFormat payFormat= new SimpleDateFormat("yyyyMMddHHmmss");
                Date payDate = payFormat.parse(map.get("time_end"));
                SimpleDateFormat systemFormat= new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
                String payDateStr = systemFormat.format(payDate);
                System.out.println("统一下单-通知链接 "+"支付时间:" + payDateStr);
 
                HashMap<String,Object> returnMap = new HashMap<>();
                returnMap.put("outTradeNo",outTradeNo);
                returnMap.put("transactionId",transactionId);
                returnMap.put("payDateStr",payDateStr);
                //通知前台,我完成支付了
                simpMessagingTemplate.convertAndSendToUser(outTradeNo,"/send/message",JSONResponse.success(returnMap));
                xmlContent = "<xml>" +
                        "<return_code><![CDATA[SUCCESS]]></return_code>" +
                        "<return_msg><![CDATA[OK]]></return_msg>" +
                        "</xml>";
            }
        }catch (Exception e){
            e.printStackTrace();
        }
        //返回信息给微信
        WxUtil.responsePrint(response,xmlContent);
    }
 
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
微信小程序中使用 WebSocket 可以通过 `wx.connectSocket` 和 `wx.onSocketMessage` 等 API 来实现。 1. 连接 WebSocket 使用 `wx.connectSocket` 可以连接到 WebSocket 服务器,例如: ``` wx.connectSocket({ url: 'wss://example.com', success: function() { console.log('连接成功') } }) ``` 其中,`url` 参数是 WebSocket 服务器的地址。 2. 监听 WebSocket 事件 使用 `wx.onSocketOpen` 监听 WebSocket 连接成功的事件,例如: ``` wx.onSocketOpen(function(res) { console.log('WebSocket连接已打开!') }) ``` 使用 `wx.onSocketMessage` 监听 WebSocket 接收到消息的事件,例如: ``` wx.onSocketMessage(function(res) { console.log('收到消息:', res.data) }) ``` 使用 `wx.onSocketError` 监听 WebSocket 错误事件,例如: ``` wx.onSocketError(function(res) { console.log('WebSocket连接打开失败,请检查!') }) ``` 3. 发送和关闭 WebSocket 使用 `wx.sendSocketMessage` 发送消息到 WebSocket 服务器,例如: ``` wx.sendSocketMessage({ data: 'Hello, WebSocket!', success: function() { console.log('发送成功') } }) ``` 使用 `wx.closeSocket` 关闭 WebSocket 连接,例如: ``` wx.closeSocket({ success: function() { console.log('WebSocket连接已关闭!') } }) ``` 以上是 WebSocket微信小程序中的基本使用方法,需要注意的是,由于微信小程序中的 WebSocket 实现并不完全符合标准,因此在使用过程中可能会出现一些兼容性问题,需要注意。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

西安未央

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值