spring+mvc+mybatis实现微信支付宝等多平台合一的二维码支付

点击上方“java进阶架构师”,选择右上角“置顶公众号

20大进阶架构专题每日送达

640?wx_fmt=png

首发:https://blog.csdn.net/fanghuainihao

之前,师长就发过微信支付,和支付宝支付两文,详见:

  1. 一文快速实现微信公众号支付功能(详细版,建议收藏备用)

  2. Spring MVC+Spring+Mybatis实现支付宝支付功能(图文详解+完整代码)

上面标题点击可跳转。这时候,就有杠精粉丝跑来说了,好是好,那要是我想多支付平台的二维码合一呢?今天,这篇文章就带你们简单实现多平台支付!

整体思路:

实现微信支付宝等支付平台合多为一的二维码支付,并且实现有效时间内支付有效,本人采用的框架是spring springmvc mybatis框架,maven管理。其实如果支付,不需要mybatis也能实现,代码和本人见解还需大神指教。

基本流程和思路:

  1. 用户点击支付

  2. 出现一次支付密码,并且带有时间限制

  3. 扫描二维码跳转后台

  4. 后台判断是微信支付还是支付宝支付

1.整体架构:

640?wx_fmt=png

2.配置编译的文件目录

640?wx_fmt=png

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>

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); 	
        } 	
    }

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!!!");	
     } 	
}

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";	
    }	
}

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;	
    }	
}

教程就到这里

————  e n d ————

微服务、高并发、JVM调优、面试专栏等20大进阶架构师专题请关注公众号Java进阶架构师后在菜单栏查看

640

看到这里,说明你喜欢本文

你的转发,是对我最大的鼓励!在看亦是支持

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值