zoukankan      html  css  js  c++  java
  • java实现微信支付宝等多个支付平台合一的二维码支付(maven+spring springmvc mybatis框架)

    首先申明,本人实现微信支付宝等支付平台合多为一的二维码支付,并且实现有效时间内支付有效,本人采用的框架是spring springmvc mybatis 框架,maven管理。其实如果支付,不需要mybatis也能实现,代码和本人见解还需大神指教。
    流程和思路:**用户点击支付** --> **出现一次支付密码,并且带有时间限制** --> **扫描二维码跳转后台** --> **后台判断是微信支付还是支付宝支付** 
    
    1. 1.整体架构:

      这里写图片描述

    2. 2.配置编译的文件目录,

      这里写图片描述

    3. 3.pom.xml,其中qrcode.qrcode、qrcode.swetake是从本地编译到maven库中,因为网络maven中没有。

    <?xml version="1.0"?>
    <project
        xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"
        xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
        <modelVersion>4.0.0</modelVersion>
        <parent>
            <groupId>fanghuai</groupId>
            <artifactId>nbt</artifactId>
            <version>0.0.1-SNAPSHOT</version>
        </parent>
        <groupId>com.nbt.qrcoder</groupId>
        <artifactId>nbt-qrcode</artifactId>
        <version>0.0.1-SNAPSHOT</version>
        <packaging>war</packaging>
        <name>nbt-qrcode Maven Webapp</name>
        <url>http://maven.apache.org</url>
        <properties>
            <spring.version>4.1.3.RELEASE</spring.version>
            <mybatis.version>3.2.8</mybatis.version>
            <mybatis.spring.version>1.2.2</mybatis.spring.version>
            <mybatis.paginator.version>1.2.15</mybatis.paginator.version>
            <mysql.version>5.1.32</mysql.version>
            <slf4j.version>1.6.4</slf4j.version>
            <jackson.version>2.4.2</jackson.version>
            <druid.version>1.0.9</druid.version>
            <jstl.version>1.2</jstl.version>
            <servlet-api.version>2.5</servlet-api.version>
            <jsp-api.version>2.0</jsp-api.version>
            <commons-lang3.version>3.3.2</commons-lang3.version>
            <commons-io.version>1.3.2</commons-io.version>
            <commons-net.version>3.3</commons-net.version>
            <pagehelper.version>4.0.0</pagehelper.version>
    
        </properties>
        <dependencies>
            <dependency>
                <groupId>junit</groupId>
                <artifactId>junit</artifactId>
                <version>3.8.1</version>
                <scope>test</scope>
            </dependency>
            <!-- qrcode -->
            <dependency>
                <groupId>qrcode.qrcode</groupId>
                <artifactId>qrcode</artifactId>
                <version>1.0</version>
            </dependency>
            <dependency>
                <groupId>qrcode.swetake</groupId>
                <artifactId>swetake</artifactId>
                <version>1.0</version>
            </dependency>
    
            <!-- 日志处理 -->
            <dependency>
                <groupId>org.slf4j</groupId>
                <artifactId>slf4j-log4j12</artifactId>
                <version>${slf4j.version}</version>
            </dependency>
            <!-- Mybatis -->
            <dependency>
                <groupId>org.mybatis</groupId>
                <artifactId>mybatis</artifactId>
                <version>${mybatis.version}</version>
            </dependency>
            <dependency>
                <groupId>org.mybatis</groupId>
                <artifactId>mybatis-spring</artifactId>
                <version>${mybatis.spring.version}</version>
            </dependency>
            <dependency>
                <groupId>com.github.miemiedev</groupId>
                <artifactId>mybatis-paginator</artifactId>
                <version>${mybatis.paginator.version}</version>
            </dependency>
            <dependency>
                <groupId>com.github.pagehelper</groupId>
                <artifactId>pagehelper</artifactId>
                <version>${pagehelper.version}</version>
            </dependency>
            <!-- MySql -->
            <dependency>
                <groupId>mysql</groupId>
                <artifactId>mysql-connector-java</artifactId>
                <version>${mysql.version}</version>
            </dependency>
            <!-- 连接池 -->
            <dependency>
                <groupId>com.alibaba</groupId>
                <artifactId>druid</artifactId>
                <version>${druid.version}</version>
            </dependency>
            <!-- Spring -->
            <dependency>
                <groupId>org.springframework</groupId>
                <artifactId>spring-context</artifactId>
                <version>${spring.version}</version>
            </dependency>
            <dependency>
                <groupId>org.springframework</groupId>
                <artifactId>spring-beans</artifactId>
                <version>${spring.version}</version>
            </dependency>
            <dependency>
                <groupId>org.springframework</groupId>
                <artifactId>spring-webmvc</artifactId>
                <version>${spring.version}</version>
            </dependency>
            <dependency>
                <groupId>org.springframework</groupId>
                <artifactId>spring-jdbc</artifactId>
                <version>${spring.version}</version>
            </dependency>
            <dependency>
                <groupId>org.springframework</groupId>
                <artifactId>spring-aspects</artifactId>
                <version>${spring.version}</version>
            </dependency>
            <!-- JSP相关 -->
            <dependency>
                <groupId>jstl</groupId>
                <artifactId>jstl</artifactId>
                <version>${jstl.version}</version>
            </dependency>
            <dependency>
                <groupId>javax.servlet</groupId>
                <artifactId>servlet-api</artifactId>
                <version>${servlet-api.version}</version>
                <scope>provided</scope>
            </dependency>
            <dependency>
                <groupId>javax.servlet</groupId>
                <artifactId>jsp-api</artifactId>
                <version>${jsp-api.version}</version>
                <scope>provided</scope>
            </dependency>
        </dependencies>
        <build>
            <finalName>nbt-qrcode</finalName>
        </build>
    </project>
    
    
    
    1. 4.二维码相关属性(Model)
    package com.nbt.util;
    import java.awt.image.BufferedImage;
    import jp.sourceforge.qrcode.data.QRCodeImage;
    
     public   class J2SEImage implements QRCodeImage { 
            BufferedImage bufImg; 
            public J2SEImage(BufferedImage bufImg) { 
                this.bufImg = bufImg; 
            } 
            public int getWidth() { 
                return bufImg.getWidth(); 
            } 
            public int getHeight() { 
                return bufImg.getHeight(); 
            } 
            public int getPixel(int x, int y) { 
                return bufImg.getRGB(x, y); 
            } 
        } 
    
    
    
    1. 5.二维码生成代码
    package com.nbt.util;
    
    import java.awt.Color;
    import java.awt.Graphics2D;
    import java.awt.image.BufferedImage;
    import java.io.File;
    import java.io.IOException;
    
    import javax.imageio.ImageIO;
    
    import jp.sourceforge.qrcode.QRCodeDecoder;
    import jp.sourceforge.qrcode.exception.DecodingFailedException;
    
    import com.swetake.util.Qrcode;
    
    public class QRCode {
    
         /**
         * 生成二维码(QRCode)图片
         * @param content  二维码内容
         * @param imgPath 存放二维位置
         */ 
        public static  void encoderQRCode(BuildQRCode bc) { 
    
            try { 
                Qrcode qrcodeHandler = new Qrcode(); 
                qrcodeHandler.setQrcodeErrorCorrect('M'); 
                qrcodeHandler.setQrcodeEncodeMode('B'); 
                qrcodeHandler.setQrcodeVersion(7); 
                System.out.println(bc.getContent()); 
                byte[] contentBytes = bc.getContent().getBytes("gb2312"); 
                BufferedImage bufImg = new BufferedImage(140, 140, 
                        BufferedImage.TYPE_INT_RGB); 
                Graphics2D gs = bufImg.createGraphics(); 
                gs.setBackground(Color.WHITE); 
                gs.clearRect(0, 0, 140, 140); 
                // 设定图像颜色> BLACK 
                gs.setColor(Color.BLACK); 
                // 设置偏移量 不设置可能导致解析出错 
                int pixoff = 2; 
                // 输出内容> 二维码 
                if (contentBytes.length > 0 && contentBytes.length < 120) { 
                    boolean[][] codeOut = qrcodeHandler.calQrcode(contentBytes); 
                    for (int i = 0; i < codeOut.length; i++) { 
                        for (int j = 0; j < codeOut.length; j++) { 
                            if (codeOut[j][i]) { 
                                gs.fillRect(j * 3 + pixoff, i * 3 + pixoff, 3, 3); 
                            } 
                        } 
                    } 
                } else { 
                    System.err.println("QRCode content bytes length = " + contentBytes.length + " not in [ 0,120 ]. "); 
                } 
                gs.dispose(); 
                bufImg.flush(); 
                File imgFile = new File(bc.getImgPath()); 
                // 生成二维码QRCode图片 
                ImageIO.write(bufImg, "png", imgFile); 
    
            } catch (Exception e) { 
    
                e.printStackTrace(); 
            } 
        } 
    
        /**
         * 解码二维码
         * @param imgPath
         * @return String
         */ 
        public static  String decoderQRCode(String imgPath) { 
            // QRCode 二维码图片的文件 
            File imageFile = new File(imgPath); 
            BufferedImage bufImg = null; 
            String decodedData = null; 
            try { 
                bufImg = ImageIO.read(imageFile); 
                QRCodeDecoder decoder = new QRCodeDecoder(); 
                decodedData = new String(decoder.decode(new J2SEImage(bufImg))); 
                // try { 
                // System.out.println(new String(decodedData.getBytes("gb2312"), 
                // "gb2312")); 
                // } catch (Exception e) { 
                // // TODO: handle exception 
                // } 
            } catch (IOException e) { 
                System.out.println("Error: " + e.getMessage()); 
                e.printStackTrace(); 
            } catch (DecodingFailedException dfe) { 
                System.out.println("Error: " + dfe.getMessage()); 
                dfe.printStackTrace(); 
            } 
            return decodedData; 
        } 
    
    
        public static void main(String[] args) {
    
        //生成二维码
             String imgPath = "D:/test/Michael_QRCode.png"; 
             String content = "http://www.baidu.com"; 
             BuildQRCode bc = new BuildQRCode(imgPath,content);
             encoderQRCode(bc); 
             System.out.println("encoder QRcode success"); 
    
    
         //解读二维码
             String decoderContent =decoderQRCode(imgPath); 
             System.out.println("解析结果如下:"); 
             System.out.println(decoderContent); 
             System.out.println("========decoder success!!!");
         } 
    }
    
    
    
    
    1. 6.Controller相关代码(jsp页面要通过流的形式放在页面上,不然二维码显示不出来。)
    package com.nbt.controller;
    
    import java.io.File;
    import java.io.FileInputStream;
    import java.io.IOException;
    import java.io.OutputStream;
    import java.text.SimpleDateFormat;
    import java.util.Calendar;
    import java.util.Map;
    
    import javax.servlet.http.HttpServletRequest;
    import javax.servlet.http.HttpServletResponse;
    
    import org.apache.log4j.Logger;
    import org.springframework.stereotype.Controller;
    import org.springframework.ui.Model;
    import org.springframework.web.bind.annotation.RequestMapping;
    import org.springframework.web.bind.annotation.RequestParam;
    
    import com.mysql.jdbc.StringUtils;
    import com.nbt.util.BuildQRCode;
    import com.nbt.util.QRCode;
    @Controller
    @RequestMapping("/qr")
    public class QRCodeController {
    
        private static Logger log = Logger.getLogger(QRCodeController.class);
    
    
        /**
         * 跳转到二维码页面
         * @param request
         * @return
         */
        @RequestMapping("/toShowQRCode.do")
        public String showQRCode(HttpServletRequest request){
            log.info("跳转到二维码页面...");
            return "qr";    
        }
    
        /**
         * 通过流的形式实现在jsp上面显示二维码
         * @param model
         * @param request
         * @param response
         * @throws IOException
         */
        @RequestMapping("/readImage")
        public void readImage(Model model, HttpServletRequest request, HttpServletResponse response) throws IOException{
            BuildQRCode bc = new BuildQRCode();//调用无参构造方法
            bc.initParam(bc);//对参数进行初始化
            QRCode.encoderQRCode(bc);//生成二维码
    
            String filePath =  bc.getImgPath();
            File filePic = new File(filePath);
            if(filePic.exists()){
               FileInputStream is = new FileInputStream(filePic);
               int i = is.available(); // 得到文件大小  
               byte data[] = new byte[i];  
               is.read(data); // 读数据  
               is.close();  
               response.setContentType("image/*"); // 设置返回的文件类型  
               OutputStream toClient = response.getOutputStream(); // 得到向客户端输出二进制数据的对象  
               toClient.write(data); // 输出数据  
               toClient.close();  
            }
        }  
    
        /**
         * 预支付接口
         * @param timeout
         * @param orderNo
         * @return
         */
        @RequestMapping("/toPay.do")
        public String toPay(@RequestParam("timeout") String timeout,@RequestParam("orderNo")String orderNo){
            log.info("开始进行支付");
            if(StringUtils.isNullOrEmpty(orderNo)||StringUtils.isNullOrEmpty(timeout)){
                log.info("订单号或者时间超时为空");
                return "faile";
            }
    
            Calendar ca = Calendar.getInstance();
            String afterTime = new SimpleDateFormat("yyyyMMddHHmmssSS").format(ca.getTime());
    
            if(!afterTime.equals(timeout)){
                log.info(afterTime+"---->"+timeout);
                log.info("二维码已失效,请重新支付");
                return "faile";
            }
            /**
             * ..... 这段可以根据二维码参数不一样,去相关支付平台进行支付,
             * 具体代码可以根据支付平台的api文档进行支付操作
             */
            log.info("支付成功");
            return "success";
    
        }
    }
    
    
    
    
    1. 7.二维码相关参数初始化(我目前二维码存放在本地,你们可以把二维码放在程序目录下)。
    package com.nbt.util;
    
    import java.text.SimpleDateFormat;
    import java.util.Calendar;
    import java.util.Date;
    
    
    public class BuildQRCode {
    
        /**
         * 二维码存放地址
         */
        private   String imgPath ;
    
        /**
         * 二维码内容
         */
        private  String content ;
    
        /**
         * 无参构造方法
         */
        public BuildQRCode() {
    
        }
    
    
        /**
         * 有参构造方法
         * @param imgPath
         * @param content
         */
        public BuildQRCode(String imgPath, String content) {
            super();
            this.imgPath = imgPath;
            this.content = content;
        }
    
    
    
        public void initParam(BuildQRCode bqrc){
    
        //  生成临时订单号和有效时间
            Calendar ca = Calendar.getInstance();
            Date date  = ca.getTime();
            SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMddHHmmssSS");
            System.out.println(sdf.format(date));
            String orderNo = sdf.format(date)+(int)Math.random()*1000;//生成订单号
            //生成有效时间五分钟
            ca.add(Calendar.MINUTE,5);
            System.out.println(sdf.format(ca.getTime()));
            String timeout = sdf.format(ca.getTime());
    
        //对参数进行初始化
            bqrc.setImgPath( "D:/test/Michael_QRCode.png");
            bqrc.setContent( "http://localhost:8080/nbt-qrcode/qr/toPay.do?orderNo="+orderNo+"&timeout="+timeout);
        }
    
        public static void main(String[] args) {
            BuildQRCode qc = new BuildQRCode();
            qc.initParam(qc);//设置参数
            QRCode.encoderQRCode(qc);
        }
    
    
    
        public  String getImgPath() {
            return imgPath;
        }
    
        public  void setImgPath(String imgPath) {
            this.imgPath = imgPath;
        }
    
        public  String getContent() {
            return content;
        }
    
        public  void setContent(String content) {
            this.content = content;
        }
    
    
    
    
    }
  • 相关阅读:
    我的书单
    说说IUnitOfWork~Linq to Sql与EntityFrameworks中的SubmtChanges()发生了什么事
    说说IUnitOfWork~认识IUnitOfWork,为什么要出现IUnitOfWork接口
    LINQtoSQL那点事~关于延时加载的性能,微软给出了不错的解决方案
    数据结构~站点地图其实是一颗树
    说说IUnitOfWork~方法完整性与统一提交不冲突
    递归 解剖
    Java Socket一对一聊天
    转:浅谈c++容器
    Java JList 使用
  • 原文地址:https://www.cnblogs.com/jpfss/p/9443570.html
Copyright © 2011-2022 走看看