mod
This commit is contained in:
157
src/main/java/com/demo/alipay_core.java
Normal file
157
src/main/java/com/demo/alipay_core.java
Normal file
@@ -0,0 +1,157 @@
|
||||
package com.demo;
|
||||
|
||||
import java.util.Date;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
|
||||
import com.alipay.api.AlipayApiException;
|
||||
import com.alipay.api.AlipayClient;
|
||||
import com.alipay.api.DefaultAlipayClient;
|
||||
import com.alipay.api.domain.AlipayTradePrecreateModel;
|
||||
import com.alipay.api.domain.AlipayTradeQueryModel;
|
||||
import com.alipay.api.request.AlipayTradePrecreateRequest;
|
||||
import com.alipay.api.request.AlipayTradeQueryRequest;
|
||||
import com.alipay.api.response.AlipayTradePrecreateResponse;
|
||||
import com.alipay.api.response.AlipayTradeQueryResponse;
|
||||
|
||||
import com.utils.DBUtil;
|
||||
import com.utils.Utils;
|
||||
|
||||
public class alipay_core {
|
||||
AlipayClient client = null;
|
||||
/**支付宝回调的接口地址*/
|
||||
private static String aliNotifyUrl = "yourWebUrl/pay/alinotify";
|
||||
|
||||
|
||||
/**
|
||||
* 接口调用配置
|
||||
*/
|
||||
public void getConfig() {
|
||||
|
||||
String appid="一串数字ID";
|
||||
String private_key="私钥";
|
||||
String public_key="公钥";
|
||||
String sign_type="RSA2";
|
||||
|
||||
client =new DefaultAlipayClient("https://openapi.alipay.com/gateway.do",appid,private_key,"json","utf-8",public_key,sign_type);
|
||||
|
||||
|
||||
}
|
||||
|
||||
public alipay_core() {
|
||||
getConfig();
|
||||
}
|
||||
|
||||
public static void main(String[] args) {
|
||||
|
||||
System.out.println(Utils.QrImgB64("aaa",200));
|
||||
}
|
||||
|
||||
/**
|
||||
* 创建付款订单
|
||||
*/
|
||||
public HashMap<String, String> createOrder(double num,String title){
|
||||
if(num<=0) return null;
|
||||
HashMap<String, String> rs = new HashMap<>();
|
||||
AlipayTradePrecreateRequest request = new AlipayTradePrecreateRequest();
|
||||
|
||||
String h=new Date().getTime()+ Utils.randomNum(10, 99)+"";
|
||||
|
||||
AlipayTradePrecreateModel model = new AlipayTradePrecreateModel();
|
||||
model.setOutTradeNo(h);//订单号(保证不重复)
|
||||
model.setTotalAmount(num+"");//订单金额
|
||||
model.setSubject(title);//标题(关键字)不可用特殊标点
|
||||
model.setQrCodeTimeoutExpress("10m");
|
||||
request.setBizModel(model);
|
||||
request.setNotifyUrl(aliNotifyUrl);//应用网关(异步通知)
|
||||
|
||||
AlipayTradePrecreateResponse response = null;
|
||||
try {
|
||||
response = client.execute(request);
|
||||
} catch (AlipayApiException e) {e.printStackTrace();}
|
||||
|
||||
if(response.isSuccess()){
|
||||
|
||||
//订单存入数据库
|
||||
DBUtil db = new DBUtil();
|
||||
int i = db.execUpdate("insert into _orders(out_trade_no,otitle,onum,qrcode) values("+ response.getOutTradeNo()+",?,"+num+",?)", new String[]{title,response.getQrCode()});
|
||||
if(i==1){
|
||||
rs.put("code", "1");
|
||||
rs.put("qrcode", response.getQrCode());
|
||||
rs.put("qrimg", Utils.QrImgB64(response.getQrCode(), 300));
|
||||
rs.put("out_trade_no", response.getOutTradeNo());
|
||||
}else rs.put("errcode", "-1");
|
||||
} else {
|
||||
rs.put("errcode", "-1");
|
||||
}
|
||||
|
||||
return rs;
|
||||
|
||||
}
|
||||
|
||||
/**查询订单状态*/
|
||||
public Map<String, Object> queryOrder(String orderId){
|
||||
if(orderId==null||orderId.trim().length()<1) return null;
|
||||
DBUtil db = new DBUtil();
|
||||
//查数据库
|
||||
//先检查数据库是否有这个数据,若查不到或者等待付款,就去更新订单状态,交易成功和交易结束直接返回,订单关闭就把数据库数据删除
|
||||
List<Map<String, Object>> rs = db.execQuery("select * from _orders where out_trade_no = ?", new String[]{orderId});
|
||||
if(rs!=null&&rs.size()>0){
|
||||
Map<String, Object> o = rs.get(0);
|
||||
if("0".equals(o.get("ostatus")+"")||"1".equals(o.get("ostatus")+"")){
|
||||
AlipayTradeQueryResponse r = updateOrder(orderId);
|
||||
if(r==null) return null;
|
||||
return queryOrder(orderId);
|
||||
}
|
||||
else if("2".equals(o.get("ostatus")+"")) {
|
||||
db.execUpdate("delete from _orders where out_trade_no = ?", new String[]{orderId});
|
||||
return null;
|
||||
}
|
||||
|
||||
return o;
|
||||
|
||||
}else{
|
||||
AlipayTradeQueryResponse r = updateOrder(orderId);
|
||||
if(r==null) return null;
|
||||
return queryOrder(orderId);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**更新订单状态*/
|
||||
public AlipayTradeQueryResponse updateOrder(String orderId){
|
||||
|
||||
if(orderId==null||orderId.trim().length()<1) return null;
|
||||
DBUtil db = new DBUtil();
|
||||
|
||||
AlipayTradeQueryRequest request = new AlipayTradeQueryRequest();
|
||||
AlipayTradeQueryModel model = new AlipayTradeQueryModel();
|
||||
model.setOutTradeNo(orderId);
|
||||
request.setBizModel(model);
|
||||
AlipayTradeQueryResponse response = null;
|
||||
try {
|
||||
response = client.execute(request);
|
||||
} catch (AlipayApiException e) {e.printStackTrace();}
|
||||
|
||||
int s=0;
|
||||
if("WAIT_BUYER_PAY".equals( response.getTradeStatus())) s=1;
|
||||
else if("TRADE_CLOSED".equals( response.getTradeStatus())) s=2;
|
||||
else if("TRADE_SUCCESS".equals( response.getTradeStatus())) s=3;
|
||||
else if("TRADE_FINISHED".equals( response.getTradeStatus())) s=4;
|
||||
|
||||
//查询不到说明没有付款
|
||||
if(response.getTradeNo()==null||response.getTradeNo().trim().length()<5){
|
||||
//db.execUpdate("delete from _orders where out_trade_no = ?", new String[]{orderId});
|
||||
return null;
|
||||
}
|
||||
//更新数据库订单
|
||||
db.execUpdate("update _orders set trade_no=?,ostatus="+s+",zfbuser=?,paynum="+response.getBuyerPayAmount()+",getnum="+response.getReceiptAmount()+",zfbuserid=?,getbody=? where out_trade_no = ?", new String[]{response.getTradeNo(), response.getBuyerLogonId(),response.getBuyerUserId(),response.getBody(),orderId});
|
||||
|
||||
|
||||
return response;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
137
src/main/java/com/demo/payController.java
Normal file
137
src/main/java/com/demo/payController.java
Normal file
@@ -0,0 +1,137 @@
|
||||
package com.demo;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
|
||||
import com.utils.DBUtil;
|
||||
import com.utils.Utils;
|
||||
import org.springframework.web.bind.annotation.CrossOrigin;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RequestParam;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@CrossOrigin(origins = "*", maxAge = 3600)
|
||||
@RequestMapping(value="/pay",produces="text/html;charset=UTF-8")
|
||||
@RestController
|
||||
public class payController {
|
||||
|
||||
|
||||
/**
|
||||
* 获取付款码
|
||||
* @param request
|
||||
* @param response
|
||||
* @return
|
||||
*/
|
||||
@RequestMapping(value = "/createOrder", produces = "text/html;charset=UTF-8")
|
||||
public String createOrder(
|
||||
@RequestParam(required = false, defaultValue = "") String n,
|
||||
@RequestParam(required = false, defaultValue = "") String t,
|
||||
HttpServletRequest request,
|
||||
HttpServletResponse response
|
||||
) {
|
||||
|
||||
double num = Utils.getNumDouble(n);
|
||||
if(num<0.01||num>2000) return "{\"errcode\":\"-1\",\"msg\":\"0<金额<2000\"}";
|
||||
alipay_core alipay_core =new alipay_core();
|
||||
HashMap<String, String> order = alipay_core.createOrder(num, t);
|
||||
|
||||
return Utils.ObjectToJson(order);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 查询订单
|
||||
* @param id
|
||||
* @param request
|
||||
* @param response
|
||||
* @return
|
||||
*/
|
||||
@RequestMapping(value = "/queryOrder", produces = "text/html;charset=UTF-8")
|
||||
public String queryOrder(
|
||||
@RequestParam(required = false, defaultValue = "") String id,
|
||||
HttpServletRequest request,
|
||||
HttpServletResponse response
|
||||
) {
|
||||
|
||||
|
||||
alipay_core alipay_core =new alipay_core();
|
||||
Map<String, Object> order = alipay_core.queryOrder(id);
|
||||
|
||||
return Utils.ObjectToJson(order);
|
||||
}
|
||||
|
||||
/**
|
||||
* 查询支付是否已完成
|
||||
* @param id
|
||||
* @param request
|
||||
* @param response
|
||||
* @return
|
||||
*/
|
||||
@RequestMapping(value = "/queryPay", produces = "text/html;charset=UTF-8")
|
||||
public String queryPay(
|
||||
@RequestParam(required = false, defaultValue = "") String id,
|
||||
HttpServletRequest request,
|
||||
HttpServletResponse response
|
||||
) {
|
||||
|
||||
|
||||
alipay_core alipay_core =new alipay_core();
|
||||
Map<String, Object> order = alipay_core.queryOrder(id);
|
||||
|
||||
if(order!=null){
|
||||
if("3".equals(order.get("ostatus")+"")||"4".equals(order.get("ostatus")+"")) return "{\"msg\":\"已支付\"}";
|
||||
else return "{\"msg\":\"未支付\"}";
|
||||
}else{
|
||||
return "{\"msg\":\"未支付\"}";
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 支付宝通知回调<br>
|
||||
* 设置中的“应用网关”
|
||||
* @param param
|
||||
* @param request
|
||||
* @param response
|
||||
*/
|
||||
@RequestMapping(value = "/alinotify", produces = "text/html;charset=UTF-8")
|
||||
public void alinotify(
|
||||
@RequestParam(required = false, defaultValue = "") Map<String, String> param,
|
||||
HttpServletRequest request,
|
||||
HttpServletResponse response
|
||||
) {
|
||||
|
||||
DBUtil db = new DBUtil();
|
||||
alipay_core alipay_core =new alipay_core();
|
||||
|
||||
//只有支付成功后,支付宝才会回调应用接口,可直接获取支付宝响应的参数
|
||||
String order_id = param.get("out_trade_no");
|
||||
int s =0;
|
||||
String ss = param.get("trade_status");
|
||||
if("WAIT_BUYER_PAY".equals(ss)) s=1;
|
||||
else if("TRADE_CLOSED".equals(ss)) s=2;
|
||||
else if("TRADE_SUCCESS".equals(ss)) s=3;
|
||||
else if("TRADE_FINISHED".equals(ss)) s=4;
|
||||
|
||||
//检查数据库是否有本数据,有就修改,没有新增
|
||||
int i = db.execSql("select * from _orders where out_trade_no = ?", new String[]{order_id});
|
||||
if(i>0) alipay_core.updateOrder(order_id);
|
||||
else{
|
||||
db.execUpdate("insert into _orders(out_trade_no,trade_no,otitle,onum,ostatus,zfbuser,paynum,getnum,zfbuserid,getbody) "
|
||||
+ "values("+order_id+",?,?,"+param.get("total_amount")+","+s+",?,"+param.get("buyer_pay_amount")+","+param.get("receipt_amount")+",?,?)", new String[]{param.get("trade_no"),param.get("subject"),param.get("buyer_logon_id"),param.get("buyer_id"),param.toString()});
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
260
src/main/java/com/utils/DBUtil.java
Normal file
260
src/main/java/com/utils/DBUtil.java
Normal file
@@ -0,0 +1,260 @@
|
||||
package com.utils;
|
||||
|
||||
import java.lang.reflect.Field;
|
||||
import java.sql.Connection;
|
||||
import java.sql.DriverManager;
|
||||
import java.sql.PreparedStatement;
|
||||
import java.sql.ResultSet;
|
||||
import java.sql.ResultSetMetaData;
|
||||
import java.sql.SQLException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
|
||||
public class DBUtil {
|
||||
|
||||
// 四大金刚
|
||||
String dname = "scbox";
|
||||
String driver = "com.mysql.jdbc.Driver";// 驱动名称
|
||||
String url = "jdbc:mysql://127.0.0.1:3306/"+dname+"?useUnicode=false&characterEncoding=UTF-8&useOldAliasMetadataBehavior=true&autoReconnect=true&useSSL=false";// 连接
|
||||
String username = "root";// 用户名
|
||||
String password = "root";// 密码
|
||||
|
||||
// 三剑客
|
||||
Connection con = null;// 连接对象
|
||||
PreparedStatement pstmt = null;// 语句对象
|
||||
ResultSet rs = null;// 结果集对象
|
||||
|
||||
|
||||
public DBUtil(String dbname){
|
||||
if(dbname!=null&&dbname.trim().length()>0)
|
||||
this.dname = dbname;
|
||||
}
|
||||
|
||||
public DBUtil(){
|
||||
}
|
||||
|
||||
/**
|
||||
* 获得连接对象
|
||||
*
|
||||
* @return 连接对象
|
||||
* @throws ClassNotFoundException
|
||||
* @throws SQLException
|
||||
*/
|
||||
public Connection getConnection() {
|
||||
try {
|
||||
Class.forName(driver);
|
||||
con = DriverManager.getConnection(url, username, password);
|
||||
} catch (Exception e) {
|
||||
// TODO Auto-generated catch block
|
||||
e.printStackTrace();
|
||||
}
|
||||
return con;
|
||||
}
|
||||
|
||||
/**
|
||||
* 关闭三剑客
|
||||
*
|
||||
* @throws SQLException
|
||||
*/
|
||||
public void close(ResultSet rs, PreparedStatement pstmt, Connection con) {
|
||||
|
||||
try {
|
||||
if (rs != null)
|
||||
rs.close();
|
||||
if (pstmt != null)
|
||||
pstmt.close();
|
||||
if (con != null)
|
||||
con.close();
|
||||
} catch (SQLException e) {
|
||||
// TODO: handle exception
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 执行更新
|
||||
*
|
||||
* @param sql
|
||||
* 传入的预设的 sql语句
|
||||
* @param params
|
||||
* 问号参数列表
|
||||
* @return 影响行数
|
||||
*/
|
||||
public int execUpdate(String sql, Object[] params) {
|
||||
|
||||
try {
|
||||
this.getConnection();// 获得连接对象
|
||||
this.pstmt = this.con.prepareStatement(sql);// 获得预设语句对象
|
||||
|
||||
if (params != null) {
|
||||
// 设置参数列表
|
||||
for (int i = 0; i < params.length; i++) {
|
||||
// 因为问号参数的索引是从1开始,所以是i+1,将所有值都转为字符串形式,好让setObject成功运行
|
||||
this.pstmt.setObject(i + 1, params[i] + "");
|
||||
}
|
||||
}
|
||||
|
||||
return this.pstmt.executeUpdate(); // 执行更新,并返回影响行数
|
||||
|
||||
} catch (Exception e) {
|
||||
// TODO Auto-generated catch block
|
||||
e.printStackTrace();
|
||||
} finally {
|
||||
this.close(this.rs, this.pstmt, this.con);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* 执行查询sql,返回记录条数
|
||||
*
|
||||
* @param sql
|
||||
* @param params
|
||||
* @return
|
||||
*/
|
||||
public int execSql(String sql, Object[] params) {
|
||||
try {
|
||||
this.getConnection();// 获得连接对象
|
||||
this.pstmt = this.con.prepareStatement(sql);// 获得预设语句对象
|
||||
|
||||
if (params != null) {
|
||||
// 设置参数列表
|
||||
for (int i = 0; i < params.length; i++) {
|
||||
// 因为问号参数的索引是从1开始,所以是i+1,将所有值都转为字符串形式,好让setObject成功运行
|
||||
this.pstmt.setObject(i + 1, params[i] + "");
|
||||
}
|
||||
}
|
||||
int i = 0;
|
||||
rs = this.pstmt.executeQuery();
|
||||
while (rs.next()) {
|
||||
i++;
|
||||
}
|
||||
|
||||
return i; // 执行更新,并返回影响行数
|
||||
|
||||
} catch (Exception e) {
|
||||
// TODO Auto-generated catch block
|
||||
e.printStackTrace();
|
||||
} finally {
|
||||
this.close(this.rs, this.pstmt, this.con);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* 执行查询
|
||||
*
|
||||
* @param sql
|
||||
* 传入的预设的 sql语句
|
||||
* @param params
|
||||
* 问号参数列表
|
||||
* @return 查询后的结果
|
||||
*/
|
||||
public List<Map<String, Object>> execQuery(String sql, Object[] params) {
|
||||
|
||||
try {
|
||||
this.getConnection();// 获得连接对象
|
||||
this.pstmt = this.con.prepareStatement(sql);// 获得预设语句对象
|
||||
|
||||
if (params != null) {
|
||||
// 设置参数列表
|
||||
for (int i = 0; i < params.length; i++) {
|
||||
// 因为问号参数的索引是从1开始,所以是i+1,将所有值都转为字符串形式,好让setObject成功运行
|
||||
this.pstmt.setObject(i + 1, params[i] + "");
|
||||
}
|
||||
}
|
||||
|
||||
// 执行查询
|
||||
ResultSet rs = pstmt.executeQuery();
|
||||
|
||||
List<Map<String, Object>> al = new ArrayList<Map<String, Object>>();
|
||||
|
||||
// 获得结果集元数据(元数据就是描述数据的数据,比如把表的列类型列名等作为数据)
|
||||
ResultSetMetaData rsmd = rs.getMetaData();
|
||||
|
||||
// 获得列的总数
|
||||
int columnCount = rsmd.getColumnCount();
|
||||
|
||||
// 遍历结果集
|
||||
while (rs.next()) {
|
||||
Map<String, Object> hm = new HashMap<String, Object>();
|
||||
for (int i = 0; i < columnCount; i++) {
|
||||
// 根据列索引取得每一列的列名,索引从1开始
|
||||
String columnName = rsmd.getColumnName(i + 1);
|
||||
// 根据列名获得列值
|
||||
Object columnValue = rs.getObject(columnName);
|
||||
// 将列名作为key,列值作为值,放入 hm中,每个 hm相当于一条记录
|
||||
hm.put(columnName, columnValue);
|
||||
}
|
||||
// 将每个 hm添加到al中, al相当于是整个表,每个 hm是里面的一条记录
|
||||
al.add(hm);
|
||||
}
|
||||
|
||||
return al;
|
||||
|
||||
} catch (Exception e) {
|
||||
// TODO Auto-generated catch block
|
||||
e.printStackTrace();
|
||||
} finally {
|
||||
this.close(this.rs, this.pstmt, this.con);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取对象的属性,返回键值对
|
||||
* @param obj
|
||||
* @return
|
||||
*/
|
||||
public static HashMap<String, Object[]> reflect(Object obj) {
|
||||
if (obj == null) return null;
|
||||
|
||||
Field[] fields = obj.getClass().getDeclaredFields();
|
||||
String name="";
|
||||
Object[] value=new Object[fields.length];
|
||||
|
||||
for (int j = 0; j < fields.length; j++) {
|
||||
fields[j].setAccessible(true);
|
||||
|
||||
// 字段名
|
||||
name+="`"+fields[j].getName() + "`,";
|
||||
|
||||
// 字段值
|
||||
if (fields[j].getType().getName().equals(String.class.getName())) {//String
|
||||
|
||||
try {
|
||||
value[j]=(fields[j].get(obj));
|
||||
} catch (Exception e) {e.printStackTrace();
|
||||
}
|
||||
|
||||
} else if (fields[j].getType().getName().equals(Long.class.getName()) || fields[j].getType().getName().equals("long")) {//int/long
|
||||
|
||||
try {
|
||||
value[j]=(fields[j].getLong(obj));
|
||||
} catch (Exception e) {e.printStackTrace();}
|
||||
|
||||
}else if (fields[j].getType().getName().equals(Float.class.getName()) || fields[j].getType().getName().equals("float")) {//float/double
|
||||
|
||||
try {
|
||||
value[j]=(fields[j].getFloat(obj));
|
||||
} catch (Exception e) {e.printStackTrace();}
|
||||
|
||||
}else{// 其他类型。。。
|
||||
|
||||
try {
|
||||
value[j]=(fields[j].get(obj));
|
||||
} catch (Exception e) {e.printStackTrace();}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
HashMap<String, Object[]> m=new HashMap<>();
|
||||
m.put("name", new Object[]{name});
|
||||
m.put("value", value);
|
||||
return m;
|
||||
}
|
||||
|
||||
}
|
||||
142
src/main/java/com/utils/Utils.java
Normal file
142
src/main/java/com/utils/Utils.java
Normal file
@@ -0,0 +1,142 @@
|
||||
package com.utils;
|
||||
|
||||
import com.google.gson.Gson;
|
||||
import com.google.gson.GsonBuilder;
|
||||
import com.google.zxing.BarcodeFormat;
|
||||
import com.google.zxing.EncodeHintType;
|
||||
import com.google.zxing.MultiFormatWriter;
|
||||
import com.google.zxing.common.BitMatrix;
|
||||
import org.apache.commons.codec.binary.Base64;
|
||||
|
||||
import javax.imageio.ImageIO;
|
||||
import java.awt.image.BufferedImage;
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.Random;
|
||||
|
||||
public class Utils {
|
||||
|
||||
//线程安全的
|
||||
private static final Gson GSON;
|
||||
private static final Gson GSON_NULL; // 不过滤空值
|
||||
static {
|
||||
GSON = new GsonBuilder().enableComplexMapKeySerialization() //当Map的key为复杂对象时,需要开启该方法
|
||||
// .serializeNulls() //当字段值为空或null时,依然对该字段进行转换
|
||||
// .excludeFieldsWithoutExposeAnnotation()//打开Export注解,但打开了这个注解,副作用,要转换和不转换都要加注解
|
||||
.setDateFormat("yyyy-MM-dd HH:mm:ss")//序列化日期格式 "yyyy-MM-dd"
|
||||
// .setPrettyPrinting() //自动格式化换行
|
||||
.disableHtmlEscaping() //防止特殊字符出现乱码
|
||||
.create();
|
||||
GSON_NULL = new GsonBuilder().enableComplexMapKeySerialization() //当Map的key为复杂对象时,需要开启该方法
|
||||
.serializeNulls() //当字段值为空或null时,依然对该字段进行转换
|
||||
// .excludeFieldsWithoutExposeAnnotation()//打开Export注解,但打开了这个注解,副作用,要转换和不转换都要加注解
|
||||
.setDateFormat("yyyy-MM-dd HH:mm:ss")//序列化日期格式 "yyyy-MM-dd"
|
||||
// .setPrettyPrinting() //自动格式化换行
|
||||
.disableHtmlEscaping() //防止特殊字符出现乱码
|
||||
.create();
|
||||
}
|
||||
|
||||
public static String ObjectToJson(Object object) {
|
||||
return GSON.toJson(object);
|
||||
}
|
||||
|
||||
public static double getNumDouble(String str) {
|
||||
|
||||
str = str.trim();
|
||||
String str2 = "";
|
||||
if (str != null && !"".equals(str)) {
|
||||
for (int i = 0; i < str.length(); i++) {
|
||||
if ((str.charAt(i) >= 48 && str.charAt(i) <= 57)
|
||||
|| str.charAt(i) == 43 || str.charAt(i) == 45
|
||||
|| str.charAt(i) == 46) {
|
||||
str2 += str.charAt(i);
|
||||
}
|
||||
}
|
||||
}
|
||||
boolean isok = true;
|
||||
for (int i = 1; i < str2.length(); i++) {
|
||||
if (str2.charAt(i) == 43 || str2.charAt(i) == 45) {
|
||||
isok = false;
|
||||
}
|
||||
}
|
||||
if (!isok)
|
||||
return Double.valueOf(getNum(str));
|
||||
if ("".equals(str2))
|
||||
str2 = "0";
|
||||
return Double.valueOf(str2);
|
||||
}
|
||||
|
||||
private static double getNum(String str) {
|
||||
str = str.trim();
|
||||
String str2 = "";
|
||||
if (str != null && !"".equals(str)) {
|
||||
for (int i = 0; i < str.length(); i++) {
|
||||
if (str.charAt(i) >= 48 && str.charAt(i) <= 57) {
|
||||
str2 += str.charAt(i);
|
||||
}
|
||||
}
|
||||
}
|
||||
if ("".equals(str2))
|
||||
str2 = "-1";
|
||||
return Long.valueOf(str2);
|
||||
}
|
||||
|
||||
public static long randomNum(int min, int max) {
|
||||
int num = new Random().nextInt(max - min) + min;
|
||||
return num;
|
||||
}
|
||||
|
||||
public static String QrImgB64(String content,int widthHeight) {
|
||||
try {
|
||||
MultiFormatWriter multiFormatWriter = new MultiFormatWriter();
|
||||
Map<EncodeHintType, String> hints = new HashMap<EncodeHintType, String>();
|
||||
hints.put(EncodeHintType.CHARACTER_SET, "UTF-8");
|
||||
BitMatrix bitMatrix= multiFormatWriter.encode(content, BarcodeFormat.QR_CODE, widthHeight, widthHeight, hints);
|
||||
bitMatrix= deleteQRWhite(bitMatrix);
|
||||
BufferedImage imgbuf = toBufferedImage(bitMatrix);
|
||||
ByteArrayOutputStream os = new ByteArrayOutputStream();//新建流。
|
||||
ImageIO.write(imgbuf, "jpg", os);//利用ImageIO类提供的write方法,将bi以png图片的数据模式写入流。
|
||||
byte b[] = os.toByteArray();//从流中获取数据数组。
|
||||
String str = Base64.encodeBase64String(b);
|
||||
return str;
|
||||
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
public static final int BLACK = 0xFF000000;
|
||||
public static final int WHITE = 0xFFFFFFFF;
|
||||
public static BufferedImage toBufferedImage(BitMatrix matrix) {
|
||||
int width = matrix.getWidth();
|
||||
int height = matrix.getHeight();
|
||||
BufferedImage image = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
|
||||
for (int x = 0; x < width; x++) {
|
||||
for (int y = 0; y < height; y++) {
|
||||
image.setRGB(x, y, matrix.get(x, y) ? BLACK : WHITE);
|
||||
}
|
||||
}
|
||||
return image;
|
||||
}
|
||||
|
||||
public static BitMatrix deleteQRWhite(BitMatrix matrix) {
|
||||
int[] rec = matrix.getEnclosingRectangle();
|
||||
int resWidth = rec[2] + 1;
|
||||
int resHeight = rec[3] + 1;
|
||||
|
||||
BitMatrix resMatrix = new BitMatrix(resWidth, resHeight);
|
||||
resMatrix.clear();
|
||||
for (int i = 0; i < resWidth; i++) {
|
||||
for (int j = 0; j < resHeight; j++) {
|
||||
if (matrix.get(i + rec[0], j + rec[1]))
|
||||
resMatrix.set(i, j);
|
||||
}
|
||||
}
|
||||
return resMatrix;
|
||||
}
|
||||
|
||||
}
|
||||
12
src/main/resources/applicationContext.xml
Normal file
12
src/main/resources/applicationContext.xml
Normal file
@@ -0,0 +1,12 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<beans xmlns="http://www.springframework.org/schema/beans"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xmlns:context="http://www.springframework.org/schema/context"
|
||||
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd">
|
||||
|
||||
<context:component-scan base-package="com.*">
|
||||
<!--application父容器不扫描controller注解,这样两个配置文件各自各负责各自的-->
|
||||
<context:exclude-filter type="annotation" expression="org.springframework.stereotype.Controller"/>
|
||||
</context:component-scan>
|
||||
|
||||
</beans>
|
||||
34
src/main/resources/spring-mvc.xml
Normal file
34
src/main/resources/spring-mvc.xml
Normal file
@@ -0,0 +1,34 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<beans xmlns="http://www.springframework.org/schema/beans"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:mvc="http://www.springframework.org/schema/mvc"
|
||||
xmlns:context="http://www.springframework.org/schema/context"
|
||||
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd">
|
||||
|
||||
<!--此文件负责整个mvc中的配置-->
|
||||
|
||||
<!-- 配置注解驱动 可以将request参数与绑定到controller参数上 -->
|
||||
<mvc:annotation-driven/>
|
||||
<!-- 将静态资源交于默认的servlet处理 -->
|
||||
|
||||
|
||||
<!--静态资源映射-->
|
||||
<!--本项目把静态资源放在了webapp的statics目录下,资源映射如下-->
|
||||
<!--<mvc:resources mapping="/css/**" location="/static/css/"/>-->
|
||||
<!--<mvc:resources mapping="/js/**" location="/static/js/"/>-->
|
||||
<!--<mvc:resources mapping="/image/**" location="/static/images/"/>-->
|
||||
<mvc:default-servlet-handler /> <!--这句要加上,要不然可能会访问不到静态资源,具体作用自行百度-->
|
||||
|
||||
<!-- 对模型视图名称的解析,即在模型视图名称添加前后缀(如果最后一个还是表示文件夹,则最后的斜杠不要漏了) 使用JSP-->
|
||||
<!-- 默认的视图解析器 在上边的解析错误时使用 (默认使用html)- -->
|
||||
<bean id="defaultViewResolver" class="org.springframework.web.servlet.view.InternalResourceViewResolver">
|
||||
<property name="prefix" value="/"/><!--设置JSP文件的目录位置-->
|
||||
<!--<property name="suffix" value=".jsp"/>-->
|
||||
</bean>
|
||||
|
||||
<bean id="multipartResolver" class="org.springframework.web.multipart.support.StandardServletMultipartResolver"/>
|
||||
|
||||
|
||||
<!-- 自动扫描装配,扫描controller包的注解,加入到容器中 -->
|
||||
<context:component-scan base-package="com.*"/>
|
||||
|
||||
</beans>
|
||||
35
src/main/webapp/WEB-INF/web.xml
Normal file
35
src/main/webapp/WEB-INF/web.xml
Normal file
@@ -0,0 +1,35 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://java.sun.com/xml/ns/javaee" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" version="2.5">
|
||||
|
||||
<display-name>Archetype Created Web Application</display-name>
|
||||
<context-param>
|
||||
<param-name>contextConfigLocation</param-name>
|
||||
<param-value>classpath:applicationContext.xml</param-value>
|
||||
</context-param>
|
||||
<listener>
|
||||
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
|
||||
</listener>
|
||||
<servlet>
|
||||
<servlet-name>dispatcher</servlet-name>
|
||||
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class><!--springmvc的配置文件地址-->
|
||||
<init-param>
|
||||
<param-name>contextConfigLocation</param-name>
|
||||
<param-value>classpath:spring-mvc.xml</param-value>
|
||||
</init-param><!--启动时间,跟服务器一起启动-->
|
||||
<load-on-startup>1</load-on-startup>
|
||||
|
||||
<multipart-config>
|
||||
<!-- 上传文件最大2M -->
|
||||
<max-file-size>100000000</max-file-size>
|
||||
<!-- 上传文件整个请求不超过4M -->
|
||||
<max-request-size>200000000</max-request-size>
|
||||
</multipart-config>
|
||||
|
||||
</servlet>
|
||||
<servlet-mapping>
|
||||
<servlet-name>dispatcher</servlet-name><!--拦截所有请求-->
|
||||
<url-pattern>/</url-pattern>
|
||||
</servlet-mapping>
|
||||
|
||||
|
||||
</web-app>
|
||||
113
src/main/webapp/index.html
Normal file
113
src/main/webapp/index.html
Normal file
@@ -0,0 +1,113 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang='en'>
|
||||
|
||||
<head>
|
||||
<meta charset='UTF-8'>
|
||||
<meta http-equiv='X-UA-Compatible' content='IE=edge'>
|
||||
<meta name='viewport' content='width=device-width, initial-scale=1.0'>
|
||||
<title>支付测试</title>
|
||||
<style>
|
||||
* {
|
||||
margin: 10px auto;
|
||||
text-align: center;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
|
||||
<input type="number" name="num" id="num" placeholder="输入金额">
|
||||
<button onclick="getPayQr()">获取二维码</button>
|
||||
<div class="imgs"></div>
|
||||
|
||||
|
||||
<script src='https://libs.baidu.com/jquery/2.0.0/jquery.min.js'></script>
|
||||
|
||||
<script>
|
||||
/**
|
||||
* 获取支付二维码<br>
|
||||
* 自动开启轮询,检查支付是否成功
|
||||
*
|
||||
* @param {*} n 金额
|
||||
* @param {*} t 备注
|
||||
*/
|
||||
async function getPayQr() {
|
||||
var n = $('#num').val();
|
||||
if (n <= 0 || n > 2000) {
|
||||
alert("金额错误0~2000");
|
||||
return;
|
||||
}
|
||||
|
||||
let response = await fetch('./pay/createOrder?n=' + n + '&t=test');
|
||||
let res = JSON.parse(await response.text());
|
||||
|
||||
if (res.code == 1) {
|
||||
|
||||
var id = res.out_trade_no;
|
||||
var img = res.qrimg;
|
||||
var code = res.qrcode;
|
||||
if (id == null || id.length < 1) {
|
||||
alert('获取订单失败');
|
||||
return;
|
||||
}
|
||||
if (img == null || img.length < 1) {
|
||||
alert('获取二维码失败');
|
||||
return;
|
||||
}
|
||||
$('.imgs').html("<img src='data:image/jpg;base64," + img + "'><br><a href='alipays://platformapi/startapp?saId=10000007&qrcode=" + code + "'>手机点这里打开支付宝APP</a><br>使用支付宝扫一扫<br><button onclick='selectPay(" + id + ")'>查询支付状态</button> <button onclick='getPayQr()'>刷新二维码</button>");
|
||||
subscribe(id);
|
||||
|
||||
} else alert('遇到错误 ' + res.msg);
|
||||
}
|
||||
|
||||
/**
|
||||
*轮询检查支付状态
|
||||
*/
|
||||
async function subscribe(id) {
|
||||
let response = await fetch("./pay/queryPay?id=" + id);
|
||||
|
||||
if (response.status == 502) {
|
||||
// 连接超时,重新连接
|
||||
await subscribe(id);
|
||||
} else if (response.status != 200) {
|
||||
// 一个 error —— 让我们显示它
|
||||
alert(response.statusText);
|
||||
// 一秒后重新连接
|
||||
await new Promise(resolve => setTimeout(resolve, 1000));
|
||||
await subscribe(id);
|
||||
} else {
|
||||
// 获取并显示消息
|
||||
let message = JSON.parse(await response.text());
|
||||
|
||||
// 再次调用 subscribe() 以获取下一条消息
|
||||
if (message.msg == "已支付") {
|
||||
$('.imgs').html('支付成功<br>');
|
||||
return okPay();
|
||||
}
|
||||
await subscribe(id);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 手动查询支付状态
|
||||
*/
|
||||
async function selectPay(id) {
|
||||
let response = await fetch('./pay/queryPay?id=' + id);
|
||||
let res = JSON.parse(await response.text());
|
||||
|
||||
if (response.status == 200 && res.msg == "已支付") {
|
||||
return okPay();
|
||||
} else alert(res.msg);
|
||||
}
|
||||
|
||||
/**
|
||||
* 支付成功后的逻辑处理
|
||||
*/
|
||||
function okPay() {
|
||||
console.log('支付成功后要做的事');
|
||||
}
|
||||
</script>
|
||||
</body>
|
||||
|
||||
</html>
|
||||
Reference in New Issue
Block a user