SpringMVC+Mybatis二維碼實(shí)現(xiàn)多平臺(tái)付款(附源碼)
今天,這篇文章就帶你們簡(jiǎn)單實(shí)現(xiàn)多平臺(tái)支付!
整體思路:
實(shí)現(xiàn)微信支付寶等支付平臺(tái)合多為一的二維碼支付,并且實(shí)現(xiàn)有效時(shí)間內(nèi)支付有效,本人采用的框架是spring springmvc mybatis框架,maven管理。其實(shí)如果支付,不需要mybatis也能實(shí)現(xiàn),代碼和本人見(jiàn)解還需大神指教。
基本流程和思路:
- 用戶點(diǎn)擊支付
- 出現(xiàn)一次支付密碼,并且?guī)в袝r(shí)間限制
- 掃描二維碼跳轉(zhuǎn)后臺(tái)
- 后臺(tái)判斷是微信支付還是支付寶支付
1.整體架構(gòu):

2.配置編譯的文件目錄

3.pom.xml
其中qrcode.qrcode、qrcode.swetake是從本地編譯到maven庫(kù)中,因?yàn)榫W(wǎng)絡(luò)maven中沒(méi)有。
<?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相關(guān) -->
<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.二維碼相關(guān)屬性(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 二維碼內(nèi)容
* @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);
// 設(shè)定圖像顏色> BLACK
gs.setColor(Color.BLACK);
// 設(shè)置偏移量 不設(shè)置可能導(dǎo)致解析出錯(cuò)
int pixoff = 2;
// 輸出內(nèi)容> 二維碼
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("解析結(jié)果如下:");
System.out.println(decoderContent);
System.out.println("========decoder success!!!");
}
}
6.Controller相關(guān)代碼
(jsp頁(yè)面要通過(guò)流的形式放在頁(yè)面上,不然二維碼顯示不出來(lái)。)
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);
/**
* 跳轉(zhuǎn)到二維碼頁(yè)面
* @param request
* @return
*/
@RequestMapping("/toShowQRCode.do")
public String showQRCode(HttpServletRequest request){
log.info("跳轉(zhuǎn)到二維碼頁(yè)面...");
return "qr";
}
/**
* 通過(guò)流的形式實(shí)現(xiàn)在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();//調(diào)用無(wú)參構(gòu)造方法
bc.initParam(bc);//對(duì)參數(shù)進(jìn)行初始化
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); // 讀數(shù)據(jù)
is.close();
response.setContentType("image/*"); // 設(shè)置返回的文件類型
OutputStream toClient = response.getOutputStream(); // 得到向客戶端輸出二進(jìn)制數(shù)據(jù)的對(duì)象
toClient.write(data); // 輸出數(shù)據(jù)
toClient.close();
}
}
/**
* 預(yù)支付接口
* @param timeout
* @param orderNo
* @return
*/
@RequestMapping("/toPay.do")
public String toPay(@RequestParam("timeout") String timeout,@RequestParam("orderNo")String orderNo){
log.info("開(kāi)始進(jìn)行支付");
if(StringUtils.isNullOrEmpty(orderNo)||StringUtils.isNullOrEmpty(timeout)){
log.info("訂單號(hào)或者時(shí)間超時(shí)為空");
return "faile";
}
Calendar ca = Calendar.getInstance();
String afterTime = new SimpleDateFormat("yyyyMMddHHmmssSS").format(ca.getTime());
if(!afterTime.equals(timeout)){
log.info(afterTime+"---->"+timeout);
log.info("二維碼已失效,請(qǐng)重新支付");
return "faile";
}
/**
* ..... 這段可以根據(jù)二維碼參數(shù)不一樣,去相關(guān)支付平臺(tái)進(jìn)行支付,
* 具體代碼可以根據(jù)支付平臺(tái)的api文檔進(jìn)行支付操作
*/
log.info("支付成功");
return "success";
}
}
7.二維碼相關(guān)參數(shù)初始化
(我目前二維碼存放在本地,你們可以把二維碼放在程序目錄下)。
package com.nbt.util;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Date;
public class BuildQRCode {
/**
* 二維碼存放地址
*/
private String imgPath ;
/**
* 二維碼內(nèi)容
*/
private String content ;
/**
* 無(wú)參構(gòu)造方法
*/
public BuildQRCode() {
}
/**
* 有參構(gòu)造方法
* @param imgPath
* @param content
*/
public BuildQRCode(String imgPath, String content) {
super();
this.imgPath = imgPath;
this.content = content;
}
public void initParam(BuildQRCode bqrc){
// 生成臨時(shí)訂單號(hào)和有效時(shí)間
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;//生成訂單號(hào)
//生成有效時(shí)間五分鐘
ca.add(Calendar.MINUTE,5);
System.out.println(sdf.format(ca.getTime()));
String timeout = sdf.format(ca.getTime());
//對(duì)參數(shù)進(jìn)行初始化
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);//設(shè)置參數(shù)
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;
}
}
總結(jié):
到此這篇關(guān)于SpringMVC+Mybatis二維碼實(shí)現(xiàn)多平臺(tái)付款(附源碼)的文章就介紹到這了,更多相關(guān)SpringMVC Mybatis二維碼付款內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
Springboot整合quartz實(shí)現(xiàn)多個(gè)定時(shí)任務(wù)實(shí)例
這篇文章主要介紹了Springboot整合quartz實(shí)現(xiàn)多個(gè)定時(shí)任務(wù)代碼實(shí)例,Quartz?是一款功能強(qiáng)大的開(kāi)源任務(wù)調(diào)度框架,幾乎可以集成到任何?Java?應(yīng)用程序中,Quartz?可用于創(chuàng)建簡(jiǎn)單或復(fù)雜的任務(wù)調(diào)度,用以執(zhí)行數(shù)以萬(wàn)計(jì)的任務(wù),需要的朋友可以參考下2023-08-08
java Split 實(shí)現(xiàn)去除一個(gè)空格和多個(gè)空格
這篇文章主要介紹了java Split 實(shí)現(xiàn)去除一個(gè)空格和多個(gè)空格,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧2020-10-10
Java實(shí)現(xiàn)枚舉狀態(tài)轉(zhuǎn)換的方法詳解
在軟件開(kāi)發(fā)中,我們經(jīng)常需要處理不同系統(tǒng)或模塊間的狀態(tài)轉(zhuǎn)換,今天,我將通過(guò)一個(gè)電商訂單與物流狀態(tài)的轉(zhuǎn)換案例,展示如何優(yōu)雅地實(shí)現(xiàn)枚舉間的互相轉(zhuǎn)換,需要的朋友可以參考下2025-04-04
SpringBoot整合ZXing實(shí)現(xiàn)二維碼和條形碼的創(chuàng)建
如今我們?cè)絹?lái)越多的東西需要用到二維碼或者條形碼,商品的條形碼,付款的二維碼等等,所以本文小編給大家介紹了SpringBoot整合ZXing實(shí)現(xiàn)二維碼和條形碼的創(chuàng)建,文章通過(guò)代碼示例給大家介紹的非常詳細(xì),需要的朋友可以參考下2023-12-12
Java通過(guò)httpclient比較重定向和請(qǐng)求轉(zhuǎn)發(fā)
這篇文章主要介紹了Java通過(guò)httpclient比較重定向和請(qǐng)求轉(zhuǎn)發(fā),HttpClient?4.x?版本,get請(qǐng)求方法會(huì)自動(dòng)進(jìn)行重定向,而post請(qǐng)求方法不會(huì)自動(dòng)進(jìn)行重定向,需要的朋友可以參考下2023-04-04

