requestParams = request.getParameterMap();
30 | for (String name: requestParams.keySet()) {
31 |
32 | String[] values = requestParams.get(name);
33 | String valueStr = "";
34 | for (int i = 0; i < values.length; i++) {
35 | valueStr = (i == values.length - 1) ? valueStr + values[i]
36 | : valueStr + values[i] + ",";
37 | }
38 | params.put(name, valueStr);
39 | }
40 | return params;
41 | }
42 |
43 | }
44 |
--------------------------------------------------------------------------------
/src/main/java/spring/boot/pay/common/Log.java:
--------------------------------------------------------------------------------
1 | package spring.boot.pay.common;
2 |
3 | import org.slf4j.Logger;
4 |
5 |
6 | /**
7 | * User: rizenguo
8 | * Date: 2014/11/12
9 | * Time: 14:32
10 | */
11 | public class Log {
12 |
13 | public static final String LOG_TYPE_TRACE = "logTypeTrace";
14 | public static final String LOG_TYPE_DEBUG = "logTypeDebug";
15 | public static final String LOG_TYPE_INFO = "logTypeInfo";
16 | public static final String LOG_TYPE_WARN = "logTypeWarn";
17 | public static final String LOG_TYPE_ERROR = "logTypeError";
18 |
19 | //打印日志
20 | private Logger logger;
21 |
22 | public Log(Logger log){
23 | logger = log;
24 | }
25 |
26 | public void t(String s){
27 | logger.trace(s);
28 | }
29 |
30 | public void d(String s){
31 | logger.debug(s);
32 | }
33 |
34 | public void i(String s){
35 | logger.info(s);
36 | }
37 |
38 | public void w(String s){
39 | logger.warn(s);
40 | }
41 |
42 | public void e(String s){
43 | logger.error(s);
44 | }
45 |
46 | public void log(String type,String s){
47 | if(type.equals(Log.LOG_TYPE_TRACE)){
48 | t(s);
49 | }else if(type.equals(Log.LOG_TYPE_DEBUG)){
50 | d(s);
51 | }else if(type.equals(Log.LOG_TYPE_INFO)){
52 | i(s);
53 | }else if(type.equals(Log.LOG_TYPE_WARN)){
54 | w(s);
55 | }else if(type.equals(Log.LOG_TYPE_ERROR)){
56 | e(s);
57 | }
58 | }
59 |
60 | }
61 |
--------------------------------------------------------------------------------
/src/main/java/spring/boot/pay/common/MoneyFormat.java:
--------------------------------------------------------------------------------
1 | package spring.boot.pay.common;
2 |
3 | import java.math.BigDecimal;
4 |
5 | public class MoneyFormat {
6 |
7 | /**
8 | * 将分转化为元
9 | */
10 | public static final String fen2yuan(BigDecimal money){
11 | int yuan = money.intValue()/100;
12 | int fen = money.intValue() %100;
13 |
14 | if(fen<10){
15 | return yuan+".0"+fen;
16 | }
17 |
18 | return yuan+"."+fen;
19 | }
20 |
21 | /**
22 | * 将元转化为分
23 | */
24 | public static int yuan2fen(String money) {
25 | int yuan = 0;
26 | int fen = 0;
27 | int index = money.indexOf(".");
28 | if(index != -1){
29 | yuan = Integer.parseInt(money.substring(0,index));
30 | String fenStr = money.substring(index+1);
31 | fenStr = fenStr.length()==1 ? fenStr+"0" : fenStr ;
32 | fen = Integer.parseInt(fenStr);
33 | }else {
34 | yuan = Integer.parseInt(money);
35 | }
36 | return yuan*100 + fen;
37 | }
38 |
39 | }
40 |
--------------------------------------------------------------------------------
/src/main/java/spring/boot/pay/common/RandomCodeHelper.java:
--------------------------------------------------------------------------------
1 | package spring.boot.pay.common;
2 |
3 | import java.util.concurrent.ThreadLocalRandom;
4 |
5 | public class RandomCodeHelper {
6 |
7 | /**
8 | * 随机生成指定长度字符串
9 | */
10 | public static String randomCharCode(int length) {
11 | StringBuilder builder = new StringBuilder(length);
12 | for (int i = 0; i < length; i++) {
13 | builder.append((char) (ThreadLocalRandom.current().nextInt(33, 128)));
14 | }
15 | String code = builder.toString();
16 | return code;
17 | }
18 |
19 | /**
20 | * 随机生成一串指定长度的数字
21 | */
22 | public static String randomNumCode(int length) {
23 | StringBuilder builder = new StringBuilder(length);
24 | for (int i = 0; i < length; i++) {
25 | builder.append( ThreadLocalRandom.current().nextInt(0,10));
26 | }
27 | String code = builder.toString();
28 | return code;
29 | }
30 | }
31 |
--------------------------------------------------------------------------------
/src/main/java/spring/boot/pay/common/RegexUtils.java:
--------------------------------------------------------------------------------
1 | package spring.boot.pay.common;
2 |
3 |
4 | import java.util.regex.Pattern;
5 |
6 | /**
7 | * 正则工具类
8 | * 提供验证邮箱、手机号、电话号码、身份证号码、数字等方法
9 | */
10 | public final class RegexUtils {
11 |
12 | /**
13 | * 验证Email
14 | * @param email email地址,格式:zhangsan@sina.com,zhangsan@xxx.com.cn,xxx代表邮件服务商
15 | * @return 验证成功返回true,验证失败返回false
16 | */
17 | public static boolean checkEmail(String email) {
18 | String regex = "\\w+@\\w+\\.[a-z]+(\\.[a-z]+)?";
19 | return Pattern.matches(regex, email);
20 | }
21 |
22 | /**
23 | * 验证身份证号码
24 | * @param idCard 居民身份证号码15位或18位,最后一位可能是数字或字母
25 | * @return 验证成功返回true,验证失败返回false
26 | */
27 | public static boolean checkIdCard(String idCard) {
28 | String regex = "[1-9]\\d{13,16}[a-zA-Z0-9]{1}";
29 | return Pattern.matches(regex,idCard);
30 | }
31 |
32 | /**
33 | * 验证手机号码(支持国际格式,+86135xxxx...(中国内地),+00852137xxxx...(中国香港))
34 | * @param mobile 移动、联通、电信运营商的号码段
35 | *移动的号段:134(0-8)、135、136、137、138、139、147(预计用于TD上网卡)
36 | *、150、151、152、157(TD专用)、158、159、187(未启用)、188(TD专用)
37 | *联通的号段:130、131、132、155、156(世界风专用)、185(未启用)、186(3g)
38 | *电信的号段:133、153、180(未启用)、189
39 | * @return 验证成功返回true,验证失败返回false
40 | */
41 | public static boolean checkMobile(String mobile) {
42 | String regex = "(\\+\\d+)?1[3458]\\d{9}$";
43 | return Pattern.matches(regex,mobile);
44 | }
45 |
46 | /**
47 | * 验证固定电话号码
48 | * @param phone 电话号码,格式:国家(地区)电话代码 + 区号(城市代码) + 电话号码,如:+8602085588447
49 | * 国家(地区) 代码 :标识电话号码的国家(地区)的标准国家(地区)代码。它包含从 0 到 9 的一位或多位数字,
50 | * 数字之后是空格分隔的国家(地区)代码。
51 | * 区号(城市代码):这可能包含一个或多个从 0 到 9 的数字,地区或城市代码放在圆括号——
52 | * 对不使用地区或城市代码的国家(地区),则省略该组件。
53 | * 电话号码:这包含从 0 到 9 的一个或多个数字
54 | * @return 验证成功返回true,验证失败返回false
55 | */
56 | public static boolean checkPhone(String phone) {
57 | String regex = "(\\+\\d+)?(\\d{3,4}\\-?)?\\d{7,8}$";
58 | return Pattern.matches(regex, phone);
59 | }
60 |
61 | /**
62 | * 验证整数(正整数和负整数)
63 | * @param digit 一位或多位0-9之间的整数
64 | * @return 验证成功返回true,验证失败返回false
65 | */
66 | public static boolean checkDigit(String digit) {
67 | String regex = "\\-?[1-9]\\d+";
68 | return Pattern.matches(regex,digit);
69 | }
70 |
71 | /**
72 | * 验证整数和浮点数(正负整数和正负浮点数)
73 | * @param decimals 一位或多位0-9之间的浮点数,如:1.23,233.30
74 | * @return 验证成功返回true,验证失败返回false
75 | */
76 | public static boolean checkDecimals(String decimals) {
77 | String regex = "\\-?[1-9]\\d+(\\.\\d+)?";
78 | return Pattern.matches(regex,decimals);
79 | }
80 |
81 | /**
82 | * 验证空白字符
83 | * @param blankSpace 空白字符,包括:空格、\t、\n、\r、\f、\x0B
84 | * @return 验证成功返回true,验证失败返回false
85 | */
86 | public static boolean checkBlankSpace(String blankSpace) {
87 | String regex = "\\s+";
88 | return Pattern.matches(regex,blankSpace);
89 | }
90 |
91 | /**
92 | * 验证中文
93 | * @param chinese 中文字符
94 | * @return 验证成功返回true,验证失败返回false
95 | */
96 | public static boolean checkChinese(String chinese) {
97 | String regex = "^[\u4E00-\u9FA5]+$";
98 | return Pattern.matches(regex,chinese);
99 | }
100 |
101 | /**
102 | * 验证日期(年月日)
103 | * @param birthday 日期,格式:1992-09-03,或1992.09.03
104 | * @return 验证成功返回true,验证失败返回false
105 | */
106 | public static boolean checkBirthday(String birthday) {
107 | String regex = "[1-9]{4}([-./])\\d{1,2}\\1\\d{1,2}";
108 | return Pattern.matches(regex,birthday);
109 | }
110 |
111 | /**
112 | * 验证URL地址
113 | * @param url 格式:http://blog.csdn.net:80/xyang81/article/details/7705960? 或 http://www.csdn.net:80
114 | * @return 验证成功返回true,验证失败返回false
115 | */
116 | public static boolean checkURL(String url) {
117 | String regex = "(https?://(w{3}\\.)?)?\\w+\\.\\w+(\\.[a-zA-Z]+)*(:\\d{1,5})?(/\\w*)*(\\??(.+=.*)?(&.+=.*)?)?";
118 | return Pattern.matches(regex, url);
119 | }
120 |
121 | /**
122 | * 匹配中国邮政编码
123 | * @param postcode 邮政编码
124 | * @return 验证成功返回true,验证失败返回false
125 | */
126 | public static boolean checkPostcode(String postcode) {
127 | String regex = "[1-9]\\d{5}";
128 | return Pattern.matches(regex, postcode);
129 | }
130 |
131 | /**
132 | * 匹配IP地址(简单匹配,格式,如:192.168.1.1,127.0.0.1,没有匹配IP段的大小)
133 | * @param ipAddress IPv4标准地址
134 | * @return 验证成功返回true,验证失败返回false
135 | */
136 | public static boolean checkIpAddress(String ipAddress) {
137 | String regex = "[1-9](\\d{1,2})?\\.(0|([1-9](\\d{1,2})?))\\.(0|([1-9](\\d{1,2})?))\\.(0|([1-9](\\d{1,2})?))";
138 | return Pattern.matches(regex, ipAddress);
139 | }
140 |
141 | }
--------------------------------------------------------------------------------
/src/main/java/spring/boot/pay/common/Util.java:
--------------------------------------------------------------------------------
1 | package spring.boot.pay.common;
2 |
3 | import java.awt.image.BufferedImage;
4 | import java.io.ByteArrayInputStream;
5 | import java.io.ByteArrayOutputStream;
6 | import java.io.FileInputStream;
7 | import java.io.IOException;
8 | import java.io.InputStream;
9 | import java.lang.reflect.Field;
10 | import java.util.HashMap;
11 | import java.util.Map;
12 | import java.util.Properties;
13 |
14 | import javax.imageio.ImageIO;
15 | import javax.servlet.http.HttpServletResponse;
16 |
17 | import org.apache.commons.codec.binary.Base64;
18 | import org.apache.commons.lang3.StringUtils;
19 | import org.slf4j.LoggerFactory;
20 |
21 | import com.google.zxing.BarcodeFormat;
22 | import com.google.zxing.EncodeHintType;
23 | import com.google.zxing.MultiFormatWriter;
24 | import com.google.zxing.WriterException;
25 | import com.google.zxing.common.BitMatrix;
26 |
27 | import spring.boot.pay.config.dictionary.Constant;
28 |
29 | public class Util {
30 |
31 | // 打log用
32 | private static Log logger = new Log(LoggerFactory.getLogger(Util.class));
33 |
34 | /**
35 | * 通过反射的方式遍历对象的属性和属性值,方便调试
36 | *
37 | * @param o
38 | * 要遍历的对象
39 | * @throws Exception
40 | */
41 | public static void reflect(Object o) throws Exception {
42 | Class cls = o.getClass();
43 | Field[] fields = cls.getDeclaredFields();
44 | for (int i = 0; i < fields.length; i++) {
45 | Field f = fields[i];
46 | f.setAccessible(true);
47 | Util.log(f.getName() + " -> " + f.get(o));
48 | }
49 | }
50 |
51 | public static byte[] readInput(InputStream in) throws IOException {
52 | ByteArrayOutputStream out = new ByteArrayOutputStream();
53 | int len = 0;
54 | byte[] buffer = new byte[1024];
55 | while ((len = in.read(buffer)) > 0) {
56 | out.write(buffer, 0, len);
57 | }
58 | out.close();
59 | in.close();
60 | return out.toByteArray();
61 | }
62 |
63 | public static String inputStreamToString(InputStream is) throws IOException {
64 | ByteArrayOutputStream baos = new ByteArrayOutputStream();
65 | int i;
66 | while ((i = is.read()) != -1) {
67 | baos.write(i);
68 | }
69 | return baos.toString();
70 | }
71 |
72 | public static InputStream getStringStream(String sInputString) {
73 | ByteArrayInputStream tInputStringStream = null;
74 | if (sInputString != null && !sInputString.trim().equals("")) {
75 | tInputStringStream = new ByteArrayInputStream(sInputString.getBytes());
76 | }
77 | return tInputStringStream;
78 | }
79 |
80 | public static String getStringFromMap(Map map, String key, String defaultValue) {
81 | if (key == "" || key == null) {
82 | return defaultValue;
83 | }
84 | String result = (String) map.get(key);
85 | if (result == null) {
86 | return defaultValue;
87 | } else {
88 | return result;
89 | }
90 | }
91 |
92 | public static int getIntFromMap(Map map, String key) {
93 | if (key == "" || key == null) {
94 | return 0;
95 | }
96 | if (map.get(key) == null) {
97 | return 0;
98 | }
99 | return Integer.parseInt((String) map.get(key));
100 | }
101 | public static String GetImageStr(String path)
102 | {//将图片文件转化为字节数组字符串,并对其进行Base64编码处理
103 | String imgFile = path;//待处理的图片
104 | InputStream in = null;
105 | byte[] data = null;
106 | //读取图片字节数组
107 | try
108 | {
109 | in = new FileInputStream(imgFile);
110 | data = new byte[in.available()];
111 | in.read(data);
112 | in.close();
113 | }
114 | catch (IOException e)
115 | {
116 | e.printStackTrace();
117 | }
118 | //对字节数组Base64编码
119 |
120 | return Base64.encodeBase64String(data);//返回Base64编码过的字节数组字符串
121 | }
122 | /**
123 | * 打log接口
124 | *
125 | * @param log
126 | * 要打印的log字符串
127 | * @return 返回log
128 | */
129 | public static String log(Object log) {
130 | logger.i(log.toString());
131 | // System.out.println(log);
132 | return log.toString();
133 | }
134 |
135 | /**
136 | * 读取本地的xml数据,一般用来自测用
137 | *
138 | * @param localPath
139 | * 本地xml文件路径
140 | * @return 读到的xml字符串
141 | */
142 | public static final String getLocalXMLString(final String localPath) throws IOException {
143 | return Util.inputStreamToString(Util.class.getResourceAsStream(localPath));
144 | }
145 |
146 | public static final Properties getProperties(final String propertiesPath) {
147 |
148 | InputStream in= Object.class.getResourceAsStream(propertiesPath);
149 | Properties properties = new Properties();
150 |
151 | if (in!=null) {
152 |
153 | try {
154 |
155 | properties.load(in);
156 |
157 | } catch (IOException e) {
158 | // TODO Auto-generated catch block
159 | e.printStackTrace();
160 | } finally {
161 |
162 | try {
163 | in.close();
164 | } catch (IOException e) {
165 | // TODO Auto-generated catch block
166 | e.printStackTrace();
167 | }
168 | }
169 |
170 | }
171 | return properties;
172 | }
173 | public static final String getFileData(final String path) {
174 |
175 | InputStream fis= null;
176 | int i = 0;
177 | char c;
178 |
179 |
180 | try{
181 | // create new file input stream
182 | fis= Object.class.getResourceAsStream(path);
183 |
184 | //fis = new FileInputStream( Thread.currentThread().getContextClassLoader().getResource(path).getPath());
185 | byte[] bs = new byte[fis.available()];
186 | // read bytes to the buffer
187 | fis.read(bs);
188 |
189 | return new String(bs,Constant.CHARSET);
190 |
191 | }catch(Exception ex){
192 | // if any error occurs
193 | ex.printStackTrace();
194 | }finally{
195 |
196 | // releases all system resources from the streams
197 | if(fis!=null){
198 | try {
199 | fis.close();
200 | } catch (IOException e) {
201 | // TODO Auto-generated catch block
202 | e.printStackTrace();
203 | }
204 | }
205 | }
206 |
207 | return "";
208 | }
209 |
210 | /**
211 | * 生成二维码图片 不存储 直接以流的形式输出到页面
212 | * @param content
213 | * @param response
214 | */
215 | @SuppressWarnings({ "unchecked", "rawtypes" })
216 | public static void encodeQrcode(String content,HttpServletResponse response){
217 | if(StringUtils.isBlank(content))
218 | return;
219 | MultiFormatWriter multiFormatWriter = new MultiFormatWriter();
220 | Map hints = new HashMap();
221 | hints.put(EncodeHintType.CHARACTER_SET, "UTF-8"); //设置字符集编码类型
222 | BitMatrix bitMatrix = null;
223 | try {
224 | bitMatrix = multiFormatWriter.encode(content, BarcodeFormat.QR_CODE, 300, 300,hints);
225 | BufferedImage image = toBufferedImage(bitMatrix);
226 | //输出二维码图片流
227 | try {
228 | ImageIO.write(image, "png", response.getOutputStream());
229 | } catch (IOException e) {
230 | // TODO Auto-generated catch block
231 | logger.e(e.getMessage());
232 | }
233 | } catch (WriterException e1) {
234 | // TODO Auto-generated catch block
235 | logger.e(e1.getMessage());
236 | }
237 | }
238 | private static final int BLACK = 0xFF000000;
239 | private static final int WHITE = 0xFFFFFFFF;
240 |
241 | public static BufferedImage toBufferedImage(BitMatrix matrix) {
242 | int width = matrix.getWidth();
243 | int height = matrix.getHeight();
244 | BufferedImage image = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
245 | for (int x = 0; x < width; x++) {
246 | for (int y = 0; y < height; y++) {
247 | image.setRGB(x, y, matrix.get(x, y) ? BLACK : WHITE);
248 | }
249 | }
250 | return image;
251 | }
252 |
253 | }
254 |
--------------------------------------------------------------------------------
/src/main/java/spring/boot/pay/common/XmlHelper.java:
--------------------------------------------------------------------------------
1 | package spring.boot.pay.common;
2 |
3 | import java.io.IOException;
4 | import java.io.StringReader;
5 | import java.util.List;
6 | import java.util.SortedMap;
7 | import java.util.TreeMap;
8 |
9 | import org.jdom.Document;
10 | import org.jdom.Element;
11 | import org.jdom.JDOMException;
12 | import org.jdom.input.SAXBuilder;
13 |
14 | public class XmlHelper {
15 |
16 |
17 | /**
18 | * 解析xml,返回第一级元素键值对。如果第一级元素有子节点,则此节点的值是子节点的xml数据。
19 | */
20 | public static SortedMap parseXmlToMap(String strXml){
21 | if (null == strXml || "".equals(strXml)) {
22 | return new TreeMap();
23 | }
24 |
25 | SortedMap m = new TreeMap();
26 |
27 | StringReader read = new StringReader(strXml);
28 | SAXBuilder builder = new SAXBuilder();
29 | Document doc;
30 | try {
31 | doc = builder.build(read);
32 | } catch (JDOMException e) {
33 | throw new RuntimeException(e);
34 | } catch (IOException e) {
35 | throw new RuntimeException(e);
36 | }
37 | Element root = doc.getRootElement();
38 | List list = root.getChildren();
39 | for (Element e : list) {
40 | String k = e.getName();
41 | String v = e.getChildren().isEmpty() ? e.getTextNormalize() : getChildrenText(e.getChildren());
42 | m.put(k, v);
43 | }
44 |
45 | //关闭流
46 | read.close();
47 |
48 | return m;
49 | }
50 |
51 | /**
52 | * 获取子结点的xml
53 | * @param children
54 | * @return String
55 | */
56 | private static String getChildrenText(List children) {
57 | StringBuilder sb = new StringBuilder();
58 | if (!children.isEmpty()) {
59 | for (Element e : children) {
60 | String name = e.getName();
61 | String value = e.getTextNormalize();
62 | List list = e.getChildren();
63 | sb.append("<").append(name).append(">");
64 | if (!list.isEmpty()) {
65 | sb.append(getChildrenText(list));
66 | }
67 | sb.append(value);
68 | sb.append("").append(name).append(">");
69 | }
70 | }
71 |
72 | return sb.toString();
73 | }
74 | }
75 |
--------------------------------------------------------------------------------
/src/main/java/spring/boot/pay/common/encrypt/.DS_Store:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/softprog/spring-boot-pay/876a0dc720082756e78a542f5bc3251a4615578e/src/main/java/spring/boot/pay/common/encrypt/.DS_Store
--------------------------------------------------------------------------------
/src/main/java/spring/boot/pay/common/encrypt/AliMD5.java:
--------------------------------------------------------------------------------
1 | package spring.boot.pay.common.encrypt;
2 |
3 |
4 | import java.io.UnsupportedEncodingException;
5 | import java.security.MessageDigest;
6 | import java.security.SignatureException;
7 |
8 | import org.apache.commons.codec.binary.Hex;
9 | import org.apache.commons.codec.digest.DigestUtils;
10 | import org.slf4j.Logger;
11 | import org.slf4j.LoggerFactory;
12 |
13 | public final class AliMD5 {
14 |
15 | private static Logger logger = LoggerFactory.getLogger(AliMD5.class);
16 |
17 | private AliMD5() {
18 | }
19 |
20 |
21 | public static String encode(String origin, String charsetName) {
22 | String resultString = null;
23 | try {
24 | resultString = origin;
25 | MessageDigest md = MessageDigest.getInstance("MD5");
26 | if (charsetName == null || "".equals(charsetName))
27 | resultString = Hex.encodeHexString(md.digest(resultString
28 | .getBytes()));
29 | else
30 | resultString = Hex.encodeHexString(md.digest(resultString
31 | .getBytes(charsetName)));
32 | } catch (Exception e) {
33 | logger.error("md5 encode fail", e);
34 | }
35 | return resultString;
36 | }
37 |
38 | public static String encode(byte[] data) {
39 |
40 | String resultString = "";
41 | try {
42 | MessageDigest md = MessageDigest.getInstance("MD5");
43 | resultString = Hex.encodeHexString(md.digest(data));
44 | } catch (Exception e) {
45 | logger.error("md5 encode fail", e);
46 | }
47 |
48 | return resultString;
49 | }
50 |
51 | /**
52 | * 签名字符串
53 | * @param text 需要签名的字符串
54 | * @param sign 签名结果
55 | * @param key 密钥
56 | * @param input_charset 编码格式
57 | * @return 签名结果
58 | */
59 | public static boolean verify(String text, String sign, String key, String input_charset) {
60 | text = text + key;
61 | String mysign = DigestUtils.md5Hex(getContentBytes(text, input_charset));
62 | if(mysign.equals(sign)) {
63 | return true;
64 | }
65 | else {
66 | return false;
67 | }
68 | }
69 |
70 | /**
71 | * @param content
72 | * @param charset
73 | * @return
74 | * @throws SignatureException
75 | * @throws UnsupportedEncodingException
76 | */
77 | private static byte[] getContentBytes(String content, String charset) {
78 | if (charset == null || "".equals(charset)) {
79 | return content.getBytes();
80 | }
81 | try {
82 | return content.getBytes(charset);
83 | } catch (UnsupportedEncodingException e) {
84 | throw new RuntimeException("MD5签名过程中出现错误,指定的编码集不对,您目前指定的编码集是:" + charset);
85 | }
86 | }
87 | /**
88 | * 签名字符串
89 | * @param text 需要签名的字符串
90 | * @param key 密钥
91 | * @param input_charset 编码格式
92 | * @return 签名结果
93 | */
94 | public static String sign(String text, String key, String input_charset) {
95 | text = text + key;
96 | return DigestUtils.md5Hex(getContentBytes(text, input_charset));
97 | }
98 | }
99 |
--------------------------------------------------------------------------------
/src/main/java/spring/boot/pay/common/encrypt/CryptAES.java:
--------------------------------------------------------------------------------
1 | package spring.boot.pay.common.encrypt;
2 |
3 | import java.security.Key;
4 |
5 | import javax.crypto.Cipher;
6 | import javax.crypto.spec.SecretKeySpec;
7 |
8 | import org.apache.commons.codec.binary.Base64;
9 |
10 | public class CryptAES {
11 |
12 | private static final String AESTYPE ="AES/ECB/PKCS5Padding";
13 |
14 | public static String AES_Encrypt(String keyStr, String plainText) {
15 | byte[] encrypt = null;
16 | try{
17 | Key key = generateKey(keyStr);
18 | Cipher cipher = Cipher.getInstance(AESTYPE);
19 | cipher.init(Cipher.ENCRYPT_MODE, key);
20 |
21 | encrypt = cipher.doFinal(plainText.getBytes());
22 | }catch(Exception e){
23 | e.printStackTrace();
24 | }
25 | return new String(Base64.encodeBase64(encrypt));
26 | }
27 |
28 | public static String AES_Decrypt(String keyStr, String encryptData) {
29 | byte[] decrypt = null;
30 | try{
31 | Key key = generateKey(keyStr);
32 | Cipher cipher = Cipher.getInstance(AESTYPE);
33 | cipher.init(Cipher.DECRYPT_MODE, key);
34 | decrypt = cipher.doFinal(Base64.decodeBase64(encryptData));
35 | }catch(Exception e){
36 | e.printStackTrace();
37 | }
38 | return new String(decrypt).trim();
39 | }
40 |
41 | private static Key generateKey(String key)throws Exception{
42 | try{
43 |
44 | byte[] raw = Base64.decodeBase64(key);
45 | SecretKeySpec keySpec = new SecretKeySpec(raw, "AES");
46 | return keySpec;
47 | }catch(Exception e){
48 | e.printStackTrace();
49 | throw e;
50 | }
51 | }
52 | }
53 |
--------------------------------------------------------------------------------
/src/main/java/spring/boot/pay/common/encrypt/DES.java:
--------------------------------------------------------------------------------
1 | package spring.boot.pay.common.encrypt;
2 |
3 |
4 | import java.security.Key;
5 |
6 | import javax.crypto.Cipher;
7 | import javax.crypto.KeyGenerator;
8 | import javax.crypto.SecretKey;
9 | import javax.crypto.SecretKeyFactory;
10 | import javax.crypto.spec.DESKeySpec;
11 |
12 | /**
13 | * DES Coder
14 | * secret key length: 56 bit, default: 56 bit
15 | * mode: ECB/CBC/PCBC/CTR/CTS/CFB/CFB8 to CFB128/OFB/OBF8 to OFB128
16 | * padding: Nopadding/PKCS5Padding/ISO10126Padding/
17 | * @author Aub
18 | *
19 | */
20 | public class DES {
21 |
22 | /**
23 | * 密钥算法
24 | */
25 | private static final String KEY_ALGORITHM = "DES";
26 |
27 | private static final String DEFAULT_CIPHER_ALGORITHM = "DES/ECB/PKCS5Padding";
28 |
29 |
30 | /**
31 | * 初始化密钥
32 | *
33 | * @return byte[] 密钥
34 | * @throws Exception
35 | */
36 | public static byte[] initSecretKey() throws Exception{
37 | //返回生成指定算法的秘密密钥的 KeyGenerator 对象
38 | KeyGenerator kg = KeyGenerator.getInstance(KEY_ALGORITHM);
39 | //初始化此密钥生成器,使其具有确定的密钥大小
40 | kg.init(56);
41 | //生成一个密钥
42 | SecretKey secretKey = kg.generateKey();
43 | return secretKey.getEncoded();
44 | }
45 |
46 | /**
47 | * 转换密钥
48 | *
49 | * @param key 二进制密钥
50 | * @return Key 密钥
51 | * @throws Exception
52 | */
53 | private static Key toKey(byte[] key) throws Exception{
54 | //实例化DES密钥规则
55 | DESKeySpec dks = new DESKeySpec(key);
56 | //实例化密钥工厂
57 | SecretKeyFactory skf = SecretKeyFactory.getInstance(KEY_ALGORITHM);
58 | //生成密钥
59 | SecretKey secretKey = skf.generateSecret(dks);
60 | return secretKey;
61 | }
62 |
63 | /**
64 | * 加密
65 | *
66 | * @param data 待加密数据
67 | * @param key 密钥
68 | * @return byte[] 加密数据
69 | * @throws Exception
70 | */
71 | public static byte[] encrypt(byte[] data,Key key) throws Exception{
72 | return encrypt(data, key,DEFAULT_CIPHER_ALGORITHM);
73 | }
74 |
75 | /**
76 | * 加密
77 | *
78 | * @param data 待加密数据
79 | * @param key 二进制密钥
80 | * @return byte[] 加密数据
81 | * @throws Exception
82 | */
83 | public static byte[] encrypt(byte[] data,byte[] key) throws Exception{
84 | return encrypt(data, key,DEFAULT_CIPHER_ALGORITHM);
85 | }
86 |
87 |
88 | /**
89 | * 加密
90 | *
91 | * @param data 待加密数据
92 | * @param key 二进制密钥
93 | * @param cipherAlgorithm 加密算法/工作模式/填充方式
94 | * @return byte[] 加密数据
95 | * @throws Exception
96 | */
97 | public static byte[] encrypt(byte[] data,byte[] key,String cipherAlgorithm) throws Exception{
98 | //还原密钥
99 | Key k = toKey(key);
100 | return encrypt(data, k, cipherAlgorithm);
101 | }
102 |
103 | /**
104 | * 加密
105 | *
106 | * @param data 待加密数据
107 | * @param key 密钥
108 | * @param cipherAlgorithm 加密算法/工作模式/填充方式
109 | * @return byte[] 加密数据
110 | * @throws Exception
111 | */
112 | public static byte[] encrypt(byte[] data,Key key,String cipherAlgorithm) throws Exception{
113 | //实例化
114 | Cipher cipher = Cipher.getInstance(cipherAlgorithm);
115 | //使用密钥初始化,设置为加密模式
116 | cipher.init(Cipher.ENCRYPT_MODE, key);
117 | //执行操作
118 | return cipher.doFinal(data);
119 | }
120 |
121 |
122 |
123 | /**
124 | * 解密
125 | *
126 | * @param data 待解密数据
127 | * @param key 二进制密钥
128 | * @return byte[] 解密数据
129 | * @throws Exception
130 | */
131 | public static byte[] decrypt(byte[] data,byte[] key) throws Exception{
132 | return decrypt(data, key,DEFAULT_CIPHER_ALGORITHM);
133 | }
134 |
135 | /**
136 | * 解密
137 | *
138 | * @param data 待解密数据
139 | * @param key 密钥
140 | * @return byte[] 解密数据
141 | * @throws Exception
142 | */
143 | public static byte[] decrypt(byte[] data,Key key) throws Exception{
144 | return decrypt(data, key,DEFAULT_CIPHER_ALGORITHM);
145 | }
146 |
147 | /**
148 | * 解密
149 | *
150 | * @param data 待解密数据
151 | * @param key 二进制密钥
152 | * @param cipherAlgorithm 加密算法/工作模式/填充方式
153 | * @return byte[] 解密数据
154 | * @throws Exception
155 | */
156 | public static byte[] decrypt(byte[] data,byte[] key,String cipherAlgorithm) throws Exception{
157 | //还原密钥
158 | Key k = toKey(key);
159 | return decrypt(data, k, cipherAlgorithm);
160 | }
161 |
162 | /**
163 | * 解密
164 | *
165 | * @param data 待解密数据
166 | * @param key 密钥
167 | * @param cipherAlgorithm 加密算法/工作模式/填充方式
168 | * @return byte[] 解密数据
169 | * @throws Exception
170 | */
171 | public static byte[] decrypt(byte[] data,Key key,String cipherAlgorithm) throws Exception{
172 | //实例化
173 | Cipher cipher = Cipher.getInstance(cipherAlgorithm);
174 | //使用密钥初始化,设置为解密模式
175 | cipher.init(Cipher.DECRYPT_MODE, key);
176 | //执行操作
177 | return cipher.doFinal(data);
178 | }
179 |
180 | // private static String showByteArray(byte[] data){
181 | // if(null == data){
182 | // return null;
183 | // }
184 | // StringBuilder sb = new StringBuilder("{");
185 | // for(byte b:data){
186 | // sb.append(b).append(",");
187 | // }
188 | // sb.deleteCharAt(sb.length()-1);
189 | // sb.append("}");
190 | // return sb.toString();
191 | // }
192 | //
193 | // public static void main(String[] args) throws Exception {
194 | // byte[] key = initSecretKey();
195 | //// byte[] key = "12345678".getBytes();
196 | // System.out.println("key:"+ showByteArray(key));
197 | //
198 | // Key k = toKey(key);
199 | //
200 | // String data ="DES数据";
201 | // System.out.println("加密前数据: string:"+data);
202 | // System.out.println("加密前数据: byte[]:"+showByteArray(data.getBytes()));
203 | // System.out.println();
204 | // byte[] encryptData = encrypt(data.getBytes(), k);
205 | // System.out.println("加密后数据: byte[]:"+showByteArray(encryptData));
206 | // System.out.println("加密后数据: hexStr:"+ Hex.encodeHexString(encryptData));
207 | // System.out.println();
208 | // byte[] decryptData = decrypt(encryptData, k);
209 | // System.out.println("解密后数据: byte[]:"+showByteArray(decryptData));
210 | // System.out.println("解密后数据: string:"+new String(decryptData));
211 | // }
212 | }
213 |
--------------------------------------------------------------------------------
/src/main/java/spring/boot/pay/common/encrypt/ProtectData.java:
--------------------------------------------------------------------------------
1 | package spring.boot.pay.common.encrypt;
2 |
3 | /**
4 | *
5 | * @author chenlei
6 | *
7 | *根据指定的加密方式,对数据进行加解密
8 | */
9 | public final class ProtectData {
10 |
11 | public static final String AESEncrypt(String key,String data){
12 |
13 | return CryptAES.AES_Encrypt(key, data);
14 | }
15 |
16 | public static final String AESDecrypt(String key,String data){
17 |
18 | return CryptAES.AES_Decrypt(key, data);
19 | }
20 | }
21 |
--------------------------------------------------------------------------------
/src/main/java/spring/boot/pay/common/encrypt/RSA.java:
--------------------------------------------------------------------------------
1 | package spring.boot.pay.common.encrypt;
2 |
3 | import java.io.ByteArrayInputStream;
4 | import java.io.ByteArrayOutputStream;
5 | import java.io.InputStream;
6 | import java.security.KeyFactory;
7 | import java.security.PrivateKey;
8 | import java.security.PublicKey;
9 | import java.security.spec.PKCS8EncodedKeySpec;
10 | import java.security.spec.X509EncodedKeySpec;
11 | import java.util.Arrays;
12 |
13 | import javax.crypto.Cipher;
14 |
15 | import org.apache.commons.codec.binary.Base64;
16 | import org.slf4j.Logger;
17 | import org.slf4j.LoggerFactory;
18 |
19 | import spring.boot.pay.config.dictionary.Constant;
20 |
21 | public class RSA{
22 |
23 | public static final String SIGN_ALGORITHMS = "SHA1WithRSA";
24 |
25 | private static final Logger LOGGER = LoggerFactory.getLogger(RSA.class);
26 |
27 | /**
28 | * RSA签名
29 | * @param content 待签名数据
30 | * @param privateKey 商户私钥
31 | * @return 签名值
32 | */
33 | public static String sign(String content,String privateKey)
34 | {
35 | try
36 | {
37 | PKCS8EncodedKeySpec pkcs8EncodedKeySpec = new PKCS8EncodedKeySpec( Base64.decodeBase64(privateKey) );
38 | KeyFactory keyFactory = KeyFactory.getInstance("RSA");
39 | PrivateKey priKey = keyFactory.generatePrivate(pkcs8EncodedKeySpec);
40 |
41 | java.security.Signature signature = java.security.Signature
42 | .getInstance(SIGN_ALGORITHMS);
43 |
44 | signature.initSign(priKey);
45 | signature.update( content.getBytes(Constant.CHARSET) );
46 |
47 | byte[] signed = signature.sign();
48 |
49 | return Base64.encodeBase64String(signed);
50 | } catch (Exception e) {
51 | LOGGER.error(e.getMessage(),e);
52 | }
53 |
54 | return null;
55 | }
56 |
57 | /**
58 | * RSA验签名检查
59 | * @param content 待签名数据
60 | * @param sign 签名值
61 | * @param publicKey 公钥
62 | * @return 布尔值
63 | */
64 | public static boolean verify(String content, String sign, String publicKey) {
65 | try {
66 | KeyFactory keyFactory = KeyFactory.getInstance("RSA");
67 | byte[] encodedKey = Base64.decodeBase64(publicKey);
68 | PublicKey pubKey = keyFactory.generatePublic(new X509EncodedKeySpec(encodedKey));
69 | java.security.Signature signature = java.security.Signature.getInstance(SIGN_ALGORITHMS);
70 | signature.initVerify(pubKey);
71 | signature.update(content.getBytes(Constant.CHARSET));
72 | return signature.verify( Base64.decodeBase64(sign) );
73 |
74 | } catch (Exception e) {
75 | LOGGER.error(e.getMessage(),e);
76 | }
77 | return false;
78 | }
79 |
80 | /**
81 | * 解密
82 | * @param content 密文
83 | * @param privateKey 商户私钥
84 | * @param input_charset 编码格式
85 | * @return 解密后的字符串
86 | */
87 | public static String decrypt(String content, String privateKey, String input_charset) throws Exception {
88 | PrivateKey key = getPrivateKey(privateKey);
89 |
90 | Cipher cipher = Cipher.getInstance("RSA");
91 | cipher.init(Cipher.DECRYPT_MODE, key);
92 |
93 | InputStream ins = new ByteArrayInputStream(Base64.decodeBase64(content));
94 | ByteArrayOutputStream writer = new ByteArrayOutputStream();
95 |
96 | //rsa解密的字节大小最多是128,将需要解密的内容,按128位拆开解密
97 | byte[] buf = new byte[128];
98 | int bufLength;
99 | while ((bufLength = ins.read(buf)) != -1) {
100 | if (buf.length == bufLength) {
101 | writer.write(cipher.doFinal(buf));
102 | } else {
103 | writer.write(cipher.doFinal(Arrays.copyOf(buf,bufLength)));
104 | }
105 | }
106 | return new String(writer.toByteArray(), input_charset);
107 | }
108 |
109 |
110 | /**
111 | * 得到私钥
112 | * @param key 密钥字符串(经过base64编码)
113 | * @throws Exception
114 | */
115 | public static PrivateKey getPrivateKey(String key) throws Exception {
116 |
117 | byte[] keyBytes = Base64.decodeBase64(key);
118 |
119 | PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(keyBytes);
120 |
121 | KeyFactory keyFactory = KeyFactory.getInstance("RSA");
122 |
123 | return keyFactory.generatePrivate(keySpec);
124 | }
125 | }
126 |
--------------------------------------------------------------------------------
/src/main/java/spring/boot/pay/common/encrypt/WXMD5.java:
--------------------------------------------------------------------------------
1 | package spring.boot.pay.common.encrypt;
2 |
3 | import java.security.MessageDigest;
4 |
5 |
6 | public class WXMD5 {
7 | private final static String[] hexDigits = {"0", "1", "2", "3", "4", "5", "6", "7",
8 | "8", "9", "a", "b", "c", "d", "e", "f"};
9 |
10 | /**
11 | * 转换字节数组为16进制字串
12 | * @param b 字节数组
13 | * @return 16进制字串
14 | */
15 | public static String byteArrayToHexString(byte[] b) {
16 | StringBuilder resultSb = new StringBuilder();
17 | for (byte aB : b) {
18 | resultSb.append(byteToHexString(aB));
19 | }
20 | return resultSb.toString();
21 | }
22 |
23 | /**
24 | * 转换byte到16进制
25 | * @param b 要转换的byte
26 | * @return 16进制格式
27 | */
28 | private static String byteToHexString(byte b) {
29 | int n = b;
30 | if (n < 0) {
31 | n = 256 + n;
32 | }
33 | int d1 = n / 16;
34 | int d2 = n % 16;
35 | return hexDigits[d1] + hexDigits[d2];
36 | }
37 |
38 | /**
39 | * MD5编码
40 | * @param origin 原始字符串
41 | * @return 经过MD5加密之后的结果
42 | */
43 | public static String MD5Encode(String origin) {
44 | String resultString = null;
45 | try {
46 | resultString = origin;
47 | MessageDigest md = MessageDigest.getInstance("MD5");
48 | resultString = byteArrayToHexString(md.digest(resultString.getBytes()));
49 | } catch (Exception e) {
50 | e.printStackTrace();
51 | }
52 | return resultString;
53 | }
54 |
55 | }
56 |
--------------------------------------------------------------------------------
/src/main/java/spring/boot/pay/common/http/HttpClientHelper.java:
--------------------------------------------------------------------------------
1 | package spring.boot.pay.common.http;
2 |
3 | import java.util.List;
4 | import java.util.Map;
5 | import java.util.concurrent.TimeUnit;
6 |
7 | import org.apache.http.HttpEntity;
8 | import org.apache.http.NameValuePair;
9 | import org.apache.http.client.methods.HttpGet;
10 | import org.apache.http.client.methods.HttpPost;
11 | import org.apache.http.client.utils.URLEncodedUtils;
12 | import org.apache.http.config.Registry;
13 | import org.apache.http.config.RegistryBuilder;
14 | import org.apache.http.conn.HttpClientConnectionManager;
15 | import org.apache.http.conn.socket.ConnectionSocketFactory;
16 | import org.apache.http.conn.socket.PlainConnectionSocketFactory;
17 | import org.apache.http.conn.ssl.SSLConnectionSocketFactory;
18 | import org.apache.http.entity.StringEntity;
19 | import org.apache.http.impl.client.CloseableHttpClient;
20 | import org.apache.http.impl.client.HttpClients;
21 | import org.apache.http.impl.conn.PoolingHttpClientConnectionManager;
22 |
23 | import spring.boot.pay.config.dictionary.Constant;
24 |
25 | public final class HttpClientHelper {
26 |
27 | private static PoolingHttpClientConnectionManager connectionManager;
28 |
29 | static {
30 | Registry r = RegistryBuilder. create()
31 | .register("http", PlainConnectionSocketFactory.getSocketFactory())
32 | .register("https", SSLConnectionSocketFactory.getSocketFactory()).build();
33 |
34 | connectionManager = new PoolingHttpClientConnectionManager(r);
35 | connectionManager.setMaxTotal(300);
36 | connectionManager.setDefaultMaxPerRoute(30);
37 |
38 | new IdleConnectionMonitorThread(connectionManager).start();
39 | }
40 |
41 | private CloseableHttpClient httpClient;
42 |
43 | private HttpClientHelper() {
44 | httpClient = HttpClients.custom().setConnectionManager(connectionManager).build();
45 | }
46 |
47 | public static HttpClientHelper create() {
48 | return new HttpClientHelper();
49 | }
50 |
51 | /**
52 | * @param params
53 | * http body内容
54 | * @param url
55 | * http url
56 | * @param retryNumber
57 | * 失败重试次数
58 | * @return success:http response String fail:null
59 | */
60 | public String execute(String params, String url, int retryNumber, String charset) {
61 |
62 | HttpPost request = new HttpPost(url);
63 | request.setHeader("Content-Type", "application/x-www-form-urlencoded;charset=" + charset);
64 |
65 | if (!params.isEmpty()) {
66 | HttpEntity entity = null;
67 | entity = new StringEntity(params, charset);
68 | request.setEntity(entity);
69 | }
70 |
71 | String result = HttpHelper.execute(httpClient, request);
72 |
73 | if (result == null && retryNumber > 0) {
74 | return execute(params, url, retryNumber - 1);
75 | }
76 |
77 | return result;
78 | }
79 |
80 | public String execute(String params, String url, int retryNumber) {
81 | return execute(params, url, retryNumber, Constant.CHARSET);
82 | }
83 |
84 | public String execute(String params, String url) {
85 | return execute(params, url, 0);
86 | }
87 |
88 | public String execute(List params, String url, int retryNumber) {
89 | return execute(URLEncodedUtils.format(params, Constant.CHARSET), url, retryNumber);
90 | }
91 |
92 | public String execute(Map params, String url) {
93 | return execute(HttpHelper.generateBody(params), url, 0);
94 | }
95 | public String executeForGET(String url, int retryNumber, String charset) {
96 |
97 | HttpGet request = new HttpGet(url);
98 | request.setHeader("Content-Type", "application/x-www-form-urlencoded;charset=" + charset);
99 |
100 | String result = HttpHelper.execute(httpClient, request);
101 |
102 | if (result == null && retryNumber > 0) {
103 | return executeForGET(url, retryNumber, charset);
104 | }
105 |
106 | return result;
107 | }
108 | /**
109 | * 该线程用于清理过期和空闲的连接
110 | */
111 | private static class IdleConnectionMonitorThread extends Thread {
112 |
113 | private final HttpClientConnectionManager connMgr;
114 | private volatile boolean shutdown;
115 |
116 | public IdleConnectionMonitorThread(HttpClientConnectionManager connMgr) {
117 | super();
118 | this.connMgr = connMgr;
119 | }
120 |
121 | @Override
122 | public void run() {
123 | try {
124 | while (!shutdown) {
125 | synchronized (this) {
126 | wait(6000);
127 | // 关闭失效连接
128 | connMgr.closeExpiredConnections();
129 | // 关闭空闲超过30秒的连接
130 | connMgr.closeIdleConnections(30, TimeUnit.SECONDS);
131 | }
132 | }
133 | } catch (InterruptedException ex) {
134 | }
135 | }
136 |
137 | public void shutdown() {
138 | shutdown = true;
139 | synchronized (this) {
140 | notifyAll();
141 | }
142 | }
143 | }
144 |
145 | }
146 |
--------------------------------------------------------------------------------
/src/main/java/spring/boot/pay/common/http/HttpHelper.java:
--------------------------------------------------------------------------------
1 | package spring.boot.pay.common.http;
2 |
3 | import java.io.IOException;
4 | import java.util.ArrayList;
5 | import java.util.List;
6 | import java.util.Map;
7 |
8 | import org.apache.commons.lang3.exception.ExceptionUtils;
9 | import org.apache.http.HttpEntity;
10 | import org.apache.http.NameValuePair;
11 | import org.apache.http.client.methods.CloseableHttpResponse;
12 | import org.apache.http.client.methods.HttpUriRequest;
13 | import org.apache.http.client.utils.URLEncodedUtils;
14 | import org.apache.http.impl.client.CloseableHttpClient;
15 | import org.apache.http.message.BasicNameValuePair;
16 | import org.apache.http.util.EntityUtils;
17 | import org.slf4j.Logger;
18 | import org.slf4j.LoggerFactory;
19 |
20 | import spring.boot.pay.config.dictionary.Constant;
21 |
22 |
23 | public final class HttpHelper {
24 |
25 | private static Logger logger = LoggerFactory.getLogger(HttpHelper.class);
26 |
27 | public static String execute(CloseableHttpClient httpClient,HttpUriRequest request){
28 | return execute(httpClient,request,Constant.CHARSET);
29 | }
30 |
31 | public static String execute(CloseableHttpClient httpClient,HttpUriRequest request,String charset){
32 |
33 | CloseableHttpResponse response = null;
34 | try {
35 | response = httpClient.execute(request);
36 | HttpEntity entity = response.getEntity();
37 | String str = EntityUtils.toString(entity,charset);
38 | return str;
39 | } catch (Exception e) {
40 | logger.warn("execute http request fail,exception stacktrace is:\n {}", ExceptionUtils.getStackTrace(e));
41 | return null;
42 | }finally {
43 | try {
44 | if(response != null)
45 | response.close();
46 | } catch (IOException e) {
47 | logger.warn("close http response fail,exception stacktrace is:\n {}", ExceptionUtils.getStackTrace(e));
48 | }
49 | }
50 | }
51 |
52 | public static String generateBody(Map map) {
53 | return generateBody(map,Constant.CHARSET);
54 | }
55 |
56 | public static String generateBody(Map map,String charset) {
57 | List list = new ArrayList();
58 | for (Map.Entry entry : map.entrySet()) {
59 | list.add( new BasicNameValuePair(entry.getKey(), entry.getValue()) );
60 | }
61 | return URLEncodedUtils.format(list, charset);
62 | }
63 | }
64 |
--------------------------------------------------------------------------------
/src/main/java/spring/boot/pay/config/bean/JdbcConfiguration.java:
--------------------------------------------------------------------------------
1 | package spring.boot.pay.config.bean;
2 |
3 | import javax.sql.DataSource;
4 |
5 | import org.springframework.context.annotation.Bean;
6 | import org.springframework.context.annotation.Configuration;
7 | import org.springframework.jdbc.core.JdbcTemplate;
8 | import org.springframework.jdbc.core.namedparam.NamedParameterJdbcTemplate;
9 |
10 | import com.alibaba.druid.pool.DruidDataSource;
11 |
12 | import spring.boot.pay.config.properties.JdbcProperties;
13 |
14 | @Configuration
15 | public class JdbcConfiguration {
16 |
17 | @Bean
18 | public DataSource dataSource(){
19 | DruidDataSource dataSource = new DruidDataSource();
20 | dataSource.setDriverClassName(JdbcProperties.driverClass);
21 | dataSource.setUrl(JdbcProperties.jdbcUrl);
22 | dataSource.setUsername(JdbcProperties.userName);
23 | dataSource.setPassword(JdbcProperties.password);
24 | dataSource.setMaxActive(JdbcProperties.maxActive);
25 |
26 | return dataSource;
27 | }
28 |
29 | @Bean(name="pay")
30 | public JdbcTemplate jdbcTemplate(){
31 | JdbcTemplate jdbcTemplate = new JdbcTemplate();
32 | jdbcTemplate.setDataSource(dataSource());
33 | return jdbcTemplate;
34 | }
35 |
36 |
37 | @Bean(name="namePay")
38 | public NamedParameterJdbcTemplate namedParameterJdbcTemplate(){
39 | NamedParameterJdbcTemplate namedParameterJdbcTemplate = new NamedParameterJdbcTemplate(dataSource());
40 | return namedParameterJdbcTemplate;
41 | }
42 |
43 | @Bean
44 | public DataSource dataSourceOrder(){
45 | DruidDataSource dataSource = new DruidDataSource();
46 | dataSource.setDriverClassName(JdbcProperties.driverClass);
47 | dataSource.setUrl(JdbcProperties.jdbcUrl_order);
48 | dataSource.setUsername(JdbcProperties.userName_order);
49 | dataSource.setPassword(JdbcProperties.password_order);
50 | dataSource.setMaxActive(JdbcProperties.maxActive);
51 |
52 | return dataSource;
53 | }
54 |
55 | @Bean(name="order")
56 | public JdbcTemplate jdbcTemplateOrder(){
57 | JdbcTemplate jdbcTemplate = new JdbcTemplate();
58 | jdbcTemplate.setDataSource(dataSourceOrder());
59 | return jdbcTemplate;
60 | }
61 |
62 | @Bean(name="nameOrder")
63 | public NamedParameterJdbcTemplate namedParameterJdbcTemplateOrder(){
64 | NamedParameterJdbcTemplate namedParameterJdbcTemplate = new NamedParameterJdbcTemplate(dataSourceOrder());
65 | return namedParameterJdbcTemplate;
66 | }
67 |
68 | }
69 |
--------------------------------------------------------------------------------
/src/main/java/spring/boot/pay/config/bean/WebConfiguration.java:
--------------------------------------------------------------------------------
1 | package spring.boot.pay.config.bean;
2 |
3 | import java.io.FileNotFoundException;
4 | import java.util.Locale;
5 |
6 | import javax.servlet.Filter;
7 |
8 | import org.springframework.boot.autoconfigure.web.ErrorController;
9 | import org.springframework.boot.context.embedded.ConfigurableEmbeddedServletContainer;
10 | import org.springframework.boot.context.embedded.EmbeddedServletContainerCustomizer;
11 | import org.springframework.boot.web.servlet.ErrorPage;
12 | import org.springframework.context.annotation.Bean;
13 | import org.springframework.context.annotation.Configuration;
14 | import org.springframework.http.HttpStatus;
15 | import org.springframework.web.filter.CharacterEncodingFilter;
16 | import org.springframework.web.servlet.View;
17 | import org.springframework.web.servlet.ViewResolver;
18 | import org.springframework.web.servlet.view.json.MappingJackson2JsonView;
19 |
20 | import spring.boot.pay.config.dictionary.Constant;
21 |
22 | @Configuration
23 | public class WebConfiguration {
24 |
25 |
26 | @Bean
27 | public EmbeddedServletContainerCustomizer containerCustomizer() throws FileNotFoundException {
28 |
29 | return new EmbeddedServletContainerCustomizer() {
30 | @Override
31 | public void customize(ConfigurableEmbeddedServletContainer container) {
32 | container.addErrorPages(new ErrorPage(HttpStatus.NOT_FOUND, "/html/404.html"));
33 |
34 | // if(container instanceof TomcatEmbeddedServletContainerFactory) {
35 | // TomcatEmbeddedServletContainerFactory containerFactory = (TomcatEmbeddedServletContainerFactory) container;
36 | // containerFactory.addAdditionalTomcatConnectors(createSslConnector("/app/paycenter/ssl.p12", "lys418754658", "PKCS12",null));
37 | // }
38 | }
39 | };
40 | }
41 |
42 | // private Connector createSslConnector(String absoluteKeystoreFile,
43 | // String keystorePassword, String keystoreType, String keystoreAlias) {
44 | //
45 | // Connector connector = new Connector();
46 | // connector.setPort(8443);
47 | // connector.setSecure(true);
48 | // connector.setScheme("https");
49 | // connector.setAttribute("SSLEnabled", true);
50 | // connector.setAttribute("sslProtocol", "TLS");
51 | // connector.setAttribute("protocol", "org.apache.coyote.http11.Http11Protocol");
52 | // connector.setAttribute("clientAuth", false);
53 | // connector.setAttribute("keystoreFile", absoluteKeystoreFile);
54 | // connector.setAttribute("keystoreType", keystoreType);
55 | // connector.setAttribute("keystorePass", keystorePassword);
56 | // if(keystoreAlias != null) {
57 | // connector.setAttribute("keystoreAlias", keystoreAlias.toLowerCase());
58 | // }
59 | // connector.setAttribute("keyPass", keystorePassword);
60 | //
61 | // return connector;
62 | // }
63 |
64 | @Bean
65 | public ErrorController errorController(){
66 | return new ErrorController() {
67 | @Override
68 | public String getErrorPath() {
69 | return "/html/error.html";
70 | }
71 | };
72 | }
73 |
74 |
75 | @Bean
76 | public ViewResolver jsonViewResolver(){
77 | return new ViewResolver() {
78 | MappingJackson2JsonView view = new MappingJackson2JsonView();
79 | @Override
80 | public View resolveViewName(String viewName, Locale locale) throws Exception {
81 | if(viewName.equals("jsonView")) {
82 | return view;
83 | }
84 | return null;
85 | }
86 | };
87 | }
88 |
89 | @Bean
90 | public Filter characterEncodingFilter() {
91 | CharacterEncodingFilter characterEncodingFilter = new CharacterEncodingFilter();
92 | characterEncodingFilter.setEncoding(Constant.CHARSET);
93 | characterEncodingFilter.setForceEncoding(true);
94 | return characterEncodingFilter;
95 | }
96 |
97 |
98 | // @Component
99 | // public static class SasAllowOriginInterceptor extends HandlerInterceptorAdapter {
100 | //
101 | // @Override
102 | // public boolean preHandle(HttpServletRequest request,
103 | // HttpServletResponse response, Object handler)
104 | // throws Exception {
105 | // response.setHeader("Access-Control-Allow-Origin", "*");
106 | // response.setHeader("Access-Control-Allow-Methods",
107 | // "GET, POST, PUT, DELETE, OPTIONS");
108 | // return true;
109 | // }
110 | // }
111 |
112 | }
113 |
--------------------------------------------------------------------------------
/src/main/java/spring/boot/pay/config/dictionary/Constant.java:
--------------------------------------------------------------------------------
1 | package spring.boot.pay.config.dictionary;
2 |
3 | /**
4 | * Created by chenlei on 2016/01/06.
5 | */
6 | public class Constant {
7 |
8 | public static final String CHARSET = "UTF-8";
9 | //来自于微信服务号产生的key
10 | public static final String AESkeyStr = "qazwsxed";
11 | }
12 |
--------------------------------------------------------------------------------
/src/main/java/spring/boot/pay/config/dictionary/PayType.java:
--------------------------------------------------------------------------------
1 | package spring.boot.pay.config.dictionary;
2 |
3 | /**
4 | * Created by chenlei on 15/12/15.
5 | */
6 | public class PayType {
7 |
8 |
9 |
10 | /**
11 | * 微信公众号支付
12 | */
13 | public static final int WX_PAY_JSAPI = 1;
14 |
15 | /**
16 | * 微信扫码支付
17 | */
18 | public static final int WX_PAY_QC = 2;
19 |
20 | /**
21 | * 阿里银联支付
22 | */
23 | public static final int ALI_PAY_WAP = 3;
24 |
25 | /**
26 | * 阿里手机网站支付
27 | */
28 | public static final int ALI_PAY_NetBank =4;
29 |
30 | /**
31 | * 阿里直接支付
32 | */
33 | public static final int ALI_PAY_Direct =5;
34 | }
35 |
--------------------------------------------------------------------------------
/src/main/java/spring/boot/pay/config/dictionary/SignType.java:
--------------------------------------------------------------------------------
1 | package spring.boot.pay.config.dictionary;
2 |
3 | /**
4 | * Created by chenlei on 15/12/15.
5 | */
6 | public class SignType {
7 |
8 | public static final String RSA = "RSA";
9 |
10 | public static final String MD5 = "MD5";
11 | }
12 |
--------------------------------------------------------------------------------
/src/main/java/spring/boot/pay/config/properties/.DS_Store:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/softprog/spring-boot-pay/876a0dc720082756e78a542f5bc3251a4615578e/src/main/java/spring/boot/pay/config/properties/.DS_Store
--------------------------------------------------------------------------------
/src/main/java/spring/boot/pay/config/properties/AliPayProperties.java:
--------------------------------------------------------------------------------
1 | package spring.boot.pay.config.properties;
2 |
3 | import java.io.IOException;
4 | import java.util.Properties;
5 |
6 | import spring.boot.pay.common.Util;
7 |
8 | public class AliPayProperties {
9 |
10 | /**
11 | * 支付宝提供给商户的服务接入网关URL(新)
12 | */
13 | public static final String ALIPAY_GATEWAY_NEW = "https://mapi.alipay.com/gateway.do?";
14 |
15 | // 数字组成的字符串
16 | public static String partner = "";
17 |
18 | // 支付宝的公钥,无需修改该值
19 | public static String aliPublicKey = "";
20 |
21 | // 字符编码格式 目前支持 gbk 或 utf-8
22 | public static String charset = "utf-8";
23 |
24 | // 支付签名方式 不需修改
25 | public static String signType = "MD5";
26 |
27 | //卖家支付宝帐户
28 | public static String sellerEmail = "";
29 | public static String domain="";
30 | public static String defaultbank="";
31 | //服务器异步通知页面路径为银行支付
32 | public static final String notify_url = "/pay/alipay/notify";
33 | //服务器异步通知页面路径为即时到帐支付
34 | public static final String notify_url_direct = "/pay/alipay/notifydirect";
35 | //服务成功直接返回页面路径
36 | public static String return_url = "";
37 |
38 | //服务成功直接返回页面路径用于移动端
39 | public static String m_return_url = "";
40 | //服务器异步通知页面路径
41 | public static String showUrl = "";
42 |
43 | public static void init() throws IOException {
44 | Properties properties = Util.getProperties("/payconfig/ali/alipayconfig.properties");
45 | partner=properties.getProperty("partner");
46 | aliPublicKey=properties.getProperty("aliPublicKey");
47 | sellerEmail=properties.getProperty("sellerEmail");
48 | domain=properties.getProperty("domain");
49 | defaultbank=properties.getProperty("defaultbank");
50 | showUrl=properties.getProperty("showUrl");
51 | return_url=properties.getProperty("returnUrl");
52 | m_return_url=properties.getProperty("mreturnUrl");
53 | }
54 | }
55 |
--------------------------------------------------------------------------------
/src/main/java/spring/boot/pay/config/properties/JdbcProperties.java:
--------------------------------------------------------------------------------
1 | package spring.boot.pay.config.properties;
2 |
3 | import java.io.IOException;
4 | import java.util.Properties;
5 |
6 | import org.slf4j.Logger;
7 | import org.slf4j.LoggerFactory;
8 |
9 | import spring.boot.pay.common.Util;
10 |
11 | public class JdbcProperties {
12 |
13 | private static final Logger LOGGER = LoggerFactory.getLogger(JdbcProperties.class);
14 |
15 | public static String driverClass = "";
16 | public static String jdbcUrl = "";
17 | public static String userName = "";
18 | public static String password = "";
19 | public static String jdbcUrl_order = "";
20 | public static String userName_order = "";
21 | public static String password_order = "";
22 | public static int maxActive = 0;
23 |
24 |
25 | public static void init() throws IOException {
26 |
27 | Properties properties =Util.getProperties("/config/db.properties");
28 |
29 |
30 | jdbcUrl = properties.getProperty("url");
31 | userName = properties.getProperty("username");
32 | password = properties.getProperty("password");
33 | driverClass = properties.getProperty("driverClass");
34 | if(properties.getProperty("maxActive") != null){
35 | maxActive = Integer.parseInt( properties.getProperty("maxActive") );
36 | }
37 | jdbcUrl_order = properties.getProperty("url_order");
38 | userName_order = properties.getProperty("username_order");
39 | password_order = properties.getProperty("password_order");
40 | }
41 | }
42 |
--------------------------------------------------------------------------------
/src/main/java/spring/boot/pay/config/properties/SecurityProperties.java:
--------------------------------------------------------------------------------
1 | package spring.boot.pay.config.properties;
2 |
3 |
4 | import java.io.BufferedReader;
5 | import java.io.IOException;
6 | import java.io.InputStream;
7 | import java.io.InputStreamReader;
8 | import java.util.HashSet;
9 | import java.util.Set;
10 |
11 | public class SecurityProperties {
12 |
13 | //ip白名单
14 | private static Set whiteList;
15 |
16 | public static void init() throws IOException {
17 |
18 | Set set = new HashSet();
19 |
20 | InputStream in= Object.class.getResourceAsStream("/config/whitelist.txt");
21 |
22 | InputStreamReader reader = new InputStreamReader(in);
23 | BufferedReader bufferedReader = new BufferedReader(reader);
24 | for(String str = bufferedReader.readLine();
25 | str != null;
26 | str = bufferedReader.readLine()){
27 | set.add(str);
28 | }
29 |
30 | whiteList = set;
31 |
32 | in.close();
33 | }
34 |
35 | public static Set getWhiteList(){
36 | return whiteList;
37 | }
38 |
39 | }
40 |
--------------------------------------------------------------------------------
/src/main/java/spring/boot/pay/config/properties/WxPayProperties.java:
--------------------------------------------------------------------------------
1 | package spring.boot.pay.config.properties;
2 |
3 | import java.io.IOException;
4 | import java.util.Properties;
5 |
6 | import spring.boot.pay.common.Util;
7 |
8 | public class WxPayProperties {
9 |
10 |
11 | public static final String NOTIFY_URL = "/pay/wxpay/notify";
12 | public static final String KEY="1Q2w3e4r5t6y7u8i9Oa1s2d3f4g5h6j7";
13 | //向微信后台发起预支付的url
14 | public static String WX_PRE_PAY_URL = "";
15 |
16 | public static final String DOWN_LOAD_BILL="/pay/wxpay/downloadBill";
17 | public static final String GET_OPENID_URL="https://api.weixin.qq.com/sns/oauth2/access_token";
18 | //网页支付
19 | public static final String TRADE_TYPE_JSAPI = "JSAPI";
20 |
21 | public static final String TRADE_TYPE_QC = "NATIVE";
22 | public static String DOMAIN="";
23 | public static String MDOMAIN="";
24 | public static String APP_ID= "";
25 | //商户id
26 | public static String MCH_ID = "";
27 | public static String Fee_Type="CNY";
28 |
29 | public static String defSpBillCreateIp = "127.0.0.1";
30 | public static String jsapiData="";
31 |
32 | public static void init() throws IOException {
33 |
34 | Properties properties = Util.getProperties("/payconfig/wx/wxconfig.properties");
35 | APP_ID=properties.getProperty("appid");
36 | MCH_ID=properties.getProperty("mch_id");
37 | Fee_Type=properties.getProperty("feeType");
38 | WX_PRE_PAY_URL=properties.getProperty("unifiedorder");
39 | DOMAIN=properties.getProperty("domain");
40 | MDOMAIN=properties.getProperty("mdomain");
41 | jsapiData= Util.getFileData("/payconfig/wx/jsapi.txt");
42 |
43 |
44 | }
45 |
46 |
47 | }
48 |
--------------------------------------------------------------------------------
/src/main/java/spring/boot/pay/controller/TradeController.java:
--------------------------------------------------------------------------------
1 | package spring.boot.pay.controller;
2 |
3 | import java.io.PrintWriter;
4 | import java.math.BigDecimal;
5 | import java.util.SortedMap;
6 | import java.util.TreeMap;
7 |
8 | import javax.servlet.http.HttpServletRequest;
9 | import javax.servlet.http.HttpServletResponse;
10 |
11 | import org.slf4j.Logger;
12 | import org.slf4j.LoggerFactory;
13 | import org.springframework.beans.factory.annotation.Autowired;
14 | import org.springframework.stereotype.Controller;
15 | import org.springframework.web.bind.annotation.RequestMapping;
16 | import org.springframework.web.bind.annotation.RequestMethod;
17 | import org.springframework.web.bind.annotation.ResponseBody;
18 |
19 | import com.netflix.hystrix.contrib.javanica.annotation.HystrixCommand;
20 | import com.netflix.hystrix.contrib.javanica.annotation.HystrixProperty;
21 | import com.sun.xml.internal.messaging.saaj.util.Base64;
22 |
23 | import spring.boot.pay.common.Util;
24 | import spring.boot.pay.common.encrypt.ProtectData;
25 | import spring.boot.pay.config.dictionary.Constant;
26 | import spring.boot.pay.config.dictionary.PayType;
27 | import spring.boot.pay.config.properties.WxPayProperties;
28 | import spring.boot.pay.framework.base.ResultModel;
29 | import spring.boot.pay.model.OrderInfo;
30 | import spring.boot.pay.model.Trade;
31 | import spring.boot.pay.service.TradeService;
32 | import spring.boot.pay.thirdparty.wxpay.WxPayHelper;
33 |
34 | @Controller
35 | @SuppressWarnings("unused")
36 | public class TradeController {
37 |
38 | private static final Logger LOGGER = LoggerFactory.getLogger(TradeController.class);
39 | // 发起支付的时间离订单过期时间至少相差5分钟
40 | private static final int FIVE_MINUTE = 5 * 1000 * 60;
41 |
42 | @Autowired
43 | TradeService tradeService;
44 |
45 | /**
46 | * 解析支付url得到支付请求信息 进行支付
47 | */
48 | @RequestMapping(value = "/pay/trade", method = RequestMethod.GET)
49 | @ResponseBody
50 | @HystrixCommand(fallbackMethod="fallback",commandProperties = {
51 | @HystrixProperty(name = "execution.isolation.thread.timeoutInMilliseconds", value = "500"),
52 |
53 | },
54 | threadPoolProperties = {
55 | @HystrixProperty(name = "maxQueueSize", value = "0")
56 | })
57 | // @CheckIpEndpoint
58 | public String trade(HttpServletRequest request, HttpServletResponse response, String data) throws Exception {
59 |
60 | ValidateResult result = this.validateTradeDataForWx(data, request);
61 |
62 | if (result.getTrade() == null) {
63 |
64 | return result.getResult();
65 | }
66 |
67 | ResultModel processResult = this.tradeService.doTrade(result.getTrade());
68 |
69 | if (!processResult.isSuccess()) {
70 | return ProtectData.AESEncrypt(Constant.AESkeyStr, toFailureJson(processResult.getBody().toString()));
71 | }
72 |
73 | return ProtectData.AESEncrypt(Constant.AESkeyStr, toSuccessJson(processResult.getBody().toString()));
74 |
75 | }
76 | public String fallback(HttpServletRequest request, HttpServletResponse response, String data){
77 | return "系统已达到最大上限.";
78 | }
79 | /**
80 | * 解析支付url得到支付请求信息 进行支付
81 | */
82 | @RequestMapping(value = "/pay/tradewxlogin", method = RequestMethod.GET)
83 | @ResponseBody
84 |
85 | public void tradeforwxlogin(HttpServletRequest request, HttpServletResponse response) throws Exception {
86 | String oid = request.getParameter("oid");
87 | response.sendRedirect(WxPayHelper.authorizeLogin(oid));
88 | }
89 |
90 | /**
91 | * 解析支付url得到支付请求信息 进行支付
92 | */
93 | @RequestMapping(value = "/pay/tradewxjs", method = RequestMethod.GET)
94 | @ResponseBody
95 | // @CheckIpEndpoint
96 | public void tradeWXJS(HttpServletRequest request, HttpServletResponse response, String data) throws Exception {
97 |
98 |
99 | ValidateResult result = this.validateTradeDataForWxjs(data,request);
100 |
101 | if (result.getTrade() == null) {
102 |
103 | return;
104 | }
105 |
106 |
107 | ResultModel processResult = this.tradeService.doTrade(result.getTrade());
108 | // ResultModel processResult =ResultModel.successModel("32343");
109 | if (!processResult.isSuccess()) {
110 | return;
111 | }
112 |
113 |
114 |
115 |
116 | response.setContentType("text/html; charset=UTF-8");
117 | response.setCharacterEncoding("UTF-8"); String
118 | jsapiData=handleJSAPI(processResult.getBody().toString());
119 | PrintWriter out = response.getWriter();
120 | out.print(jsapiData);
121 | out.close();
122 | //response.getOutputStream().print(new String(jsapiData.getBytes(),
123 | // "UTF-8"));
124 | //response.getOutputStream().flush();
125 | // response.getOutputStream().close();
126 |
127 | return;
128 |
129 | }
130 | /**
131 | * 解析支付url得到支付请求信息 进行支付
132 | */
133 | @RequestMapping(value = "/pay/tradealibank", method = RequestMethod.GET)
134 | @ResponseBody
135 | // @CheckIpEndpoint
136 | public void tradeAliBank(HttpServletRequest request, HttpServletResponse response, String data) throws Exception {
137 |
138 | ValidateResult result = this.validateTradeDataForAliBank(data,request);
139 |
140 | if (result.getTrade() == null) {
141 |
142 | return;
143 | }
144 |
145 |
146 | ResultModel processResult = this.tradeService.doTrade(result.getTrade());
147 | // ResultModel processResult =ResultModel.successModel("32343");
148 | if (!processResult.isSuccess()) {
149 | return;
150 | }
151 |
152 | // if (trade.getPayType() == PayType.ALI_PAY_NetBank ||
153 | // trade.getPayType() == PayType.ALI_PAY_WAP) {
154 | response.setContentType("text/html; charset=UTF-8");
155 | response.setCharacterEncoding("UTF-8");
156 | response.getWriter().write(new String(processResult.getBody().toString().getBytes(), "UTF-8"));
157 | // response.getOutputStream().flush();
158 | // response.getOutputStream().close();
159 | // }
160 |
161 | /*
162 | * if (trade.getPayType() == PayType.WX_PAY_JSAPI) {
163 | * response.setContentType("text/html; charset=UTF-8");
164 | * response.setCharacterEncoding("UTF-8"); String
165 | * jsapiData=handleJSAPI(processResult.getBody().toString());
166 | *
167 | * response.getOutputStream().print(new String(jsapiData.getBytes(),
168 | * "UTF-8")); response.getOutputStream().flush();
169 | * response.getOutputStream().close();
170 | *
171 | * }
172 | */
173 |
174 | return;
175 |
176 | }
177 |
178 | /**
179 | * 解析支付url得到支付请求信息 进行支付
180 | */
181 | @RequestMapping(value = "/pay/tradealidirect", method = RequestMethod.GET)
182 | @ResponseBody
183 | // @CheckIpEndpoint
184 | public void tradeAliDirect(HttpServletRequest request, HttpServletResponse response, String data) throws Exception {
185 |
186 | ValidateResult result = this.validateTradeDataForAliDirect(data,request);
187 |
188 | if (result.getTrade() == null) {
189 |
190 | return;
191 | }
192 |
193 | ResultModel processResult = this.tradeService.doTrade(result.getTrade());
194 |
195 | if (!processResult.isSuccess()) {
196 | return;
197 | }
198 |
199 |
200 | response.setContentType("text/html; charset=UTF-8");
201 | response.setCharacterEncoding("UTF-8");
202 | LOGGER.error("ALI_PAY_Direct exec here");
203 | System.out.println("ALI_PAY_Direct exec here");
204 | response.getWriter().write(new String(processResult.getBody().toString().getBytes(), "UTF-8"));
205 | LOGGER.error("ALI_PAY_Direct exec ok");
206 | System.out.println("ALI_PAY_Direct exec ok");
207 |
208 | return;
209 |
210 | }
211 |
212 | /**
213 | * 解析支付url得到支付请求信息 进行支付
214 | */
215 | @RequestMapping(value = "/pay/tradealiwap", method = RequestMethod.GET)
216 | @ResponseBody
217 | // @CheckIpEndpoint
218 | public void tradeAliWAP(HttpServletRequest request, HttpServletResponse response, String data) throws Exception {
219 |
220 | ValidateResult result = this.validateTradeDataForAliWAP(data,request);
221 |
222 | if (result.getTrade() == null) {
223 |
224 | return;
225 | }
226 |
227 | ResultModel processResult = this.tradeService.doTrade(result.getTrade());
228 |
229 | if (!processResult.isSuccess()) {
230 | return;
231 | }
232 |
233 |
234 | response.setContentType("text/html; charset=UTF-8");
235 | response.setCharacterEncoding("UTF-8");
236 | LOGGER.error("tradealiwap exec here");
237 | System.out.println("tradealiwap exec here");
238 | response.getWriter().write(new String(processResult.getBody().toString().getBytes(), "UTF-8"));
239 | LOGGER.error("tradealiwap exec ok");
240 | System.out.println("tradealiwap exec ok");
241 |
242 | return;
243 |
244 | }
245 |
246 | /**
247 | * 生成二维码图片并直接以流的形式输出到页面
248 | *
249 | * @param code_url
250 | * @param response
251 | */
252 | @RequestMapping("qr_code.img")
253 | @ResponseBody
254 | public void getQRCode(String code_url, HttpServletResponse response) {
255 | Util.encodeQrcode(code_url, response);
256 | }
257 |
258 | private String toSuccessJson(final String msg) {
259 | return "{\"returnCode\":1,\"code\":0,\"body\":" + msg + "}";
260 | }
261 |
262 | private String toFailureJson(final String msg) {
263 | return "{\"returnCode\":0,\"code\":1,\"body\":" + msg + "}";
264 | }
265 |
266 | private String getClientIP(HttpServletRequest request) {
267 | String ip = request.getHeader("X-Forwarded-For");
268 | if (ip == null || ip.length() == 0 || "unknown".equals(ip)) {
269 | ip = request.getHeader("Proxy-Client-IP");
270 | }
271 | if (ip == null || ip.length() == 0 || "unknown".equals(ip)) {
272 | ip = request.getHeader("WL-Proxy-Client-IP");
273 | }
274 | if (ip == null || ip.length() == 0 || "unknown".equals(ip)) {
275 | ip = request.getRemoteAddr();
276 | }
277 | if (ip.equals("0:0:0:0:0:0:0:1")) {
278 |
279 | ip = "127.0.0.1";
280 | }
281 | return ip == null ? "" : ip;
282 | }
283 |
284 | private static final String handleJSAPI(String data) {
285 |
286 | SortedMap params = new TreeMap();
287 | String timeStamp = String.valueOf(new java.util.Date().getTime()).substring(0, 10);
288 | String nonceStr = WxPayHelper.getNonceStr();
289 | params.put("appId", WxPayProperties.APP_ID);
290 | params.put("timeStamp", timeStamp);
291 | params.put("nonceStr", nonceStr);
292 | params.put("package","prepay_id=" + data);
293 | params.put("signType", "MD5");
294 | String sign = WxPayHelper.createSign(params);
295 |
296 | return WxPayProperties.jsapiData.replace("$appId", WxPayProperties.APP_ID).replace("$timeStamp", timeStamp)
297 | .replace("$nonceStr", nonceStr).replace("$prepayId", "prepay_id=" + data).replace("$paySign", sign)
298 | .replace("$url", "http://m.zhugexuetang.cn");
299 | }
300 |
301 | private String handleData(String data) {
302 |
303 | data = Base64.base64Decode(data);
304 |
305 | String dec = ProtectData.AESDecrypt(Constant.AESkeyStr, data);
306 |
307 | return dec;
308 | }
309 |
310 | private final ValidateResult validateTradeDataForWx(String data, HttpServletRequest request) {
311 |
312 | ValidateResult result = new ValidateResult();
313 | result.setTrade(null);
314 | result.setResult(toFailureJson("ok"));
315 | String dec = this.handleData(data);
316 | if (dec.equals("")) {
317 |
318 | result.setResult(toFailureJson("解密失败"));
319 |
320 | return result;
321 | }
322 |
323 | String[] tradeParam = dec.split("&");
324 | Trade trade = new Trade();
325 | trade.setBody(tradeParam[1].split("=")[1]);
326 | if (trade.getBody().length() > 20) {
327 | trade.setBody(trade.getBody().substring(0, 20) + "...");
328 | }
329 | trade.setOrderId(tradeParam[0].split("=")[1]);
330 | trade.setIp(this.getClientIP(request));
331 | trade.setPayType(PayType.WX_PAY_QC);
332 |
333 | String orderId = trade.getOrderId();
334 |
335 | OrderInfo info = tradeService.getOrderInfo(orderId);
336 |
337 | if (info.getNum() == 0) {
338 |
339 | result.setResult(toFailureJson("获取订单表订单失败"));
340 |
341 | return result;
342 | }
343 |
344 | if (info.getState()) {
345 |
346 | result.setResult(toFailureJson("订单已经支付成功"));
347 |
348 | return result;
349 | }
350 |
351 | trade.setTotalFee(info.getTotalFee());
352 |
353 | if (trade.getTotalFee().compareTo(BigDecimal.ZERO) == 0) {
354 |
355 | result.setResult(toFailureJson("获取订单表订单失败"));
356 |
357 | return result;
358 | }
359 |
360 |
361 | result.setTrade(trade);
362 |
363 | return result;
364 | }
365 | private final ValidateResult validateTradeDataForWxjs(String data, HttpServletRequest request) {
366 |
367 | ValidateResult result = new ValidateResult();
368 | result.setTrade(null);
369 | result.setResult(toFailureJson("ok"));
370 | String dec = this.handleData(data);
371 | if (dec.equals("")) {
372 |
373 | result.setResult(toFailureJson("解密失败"));
374 |
375 | return result;
376 | }
377 |
378 | String[] tradeParam = dec.split("&");
379 | Trade trade = new Trade();
380 | trade.setBody(tradeParam[2].split("=")[1]);
381 | if (trade.getBody().length() > 20) {
382 | trade.setBody(trade.getBody().substring(0, 20) + "...");
383 | }
384 | trade.setOrderId(tradeParam[0].split("=")[1]);
385 | trade.setIp(this.getClientIP(request));
386 | trade.setPayType(PayType.WX_PAY_JSAPI);
387 |
388 | trade.setOpenId(tradeParam[1].split("=")[1]);
389 |
390 | String orderId = trade.getOrderId();
391 |
392 | OrderInfo info = tradeService.getOrderInfo(orderId);
393 |
394 | if (info.getNum() == 0) {
395 |
396 | result.setResult(toFailureJson("获取订单表订单失败"));
397 |
398 | return result;
399 | }
400 |
401 | if (info.getState()) {
402 |
403 | result.setResult(toFailureJson("订单已经支付成功"));
404 |
405 | return result;
406 | }
407 |
408 | trade.setTotalFee(info.getTotalFee());
409 |
410 | if (trade.getTotalFee().compareTo(BigDecimal.ZERO) == 0) {
411 |
412 | result.setResult(toFailureJson("获取订单表订单失败"));
413 |
414 | return result;
415 | }
416 |
417 |
418 | result.setTrade(trade);
419 | return result;
420 | }
421 |
422 | private final ValidateResult validateTradeDataForAliBank(String data, HttpServletRequest request) {
423 |
424 | ValidateResult result = new ValidateResult();
425 | result.setTrade(null);
426 | result.setResult(toFailureJson("ok"));
427 | String dec = this.handleData(data);
428 | if (dec.equals("")) {
429 |
430 | result.setResult(toFailureJson("解密失败"));
431 |
432 | return result;
433 | }
434 |
435 | String[] tradeParam = dec.split("&");
436 | Trade trade = new Trade();
437 | trade.setBody(tradeParam[2].split("=")[1]);
438 | if (trade.getBody().length() > 20) {
439 | trade.setBody(trade.getBody().substring(0, 20) + "...");
440 | }
441 |
442 | trade.setOrderId(tradeParam[0].split("=")[1]);
443 | trade.setIp(this.getClientIP(request));
444 | trade.setPayType(PayType.ALI_PAY_NetBank);
445 | trade.setBank(tradeParam[1].split("=")[1]);
446 | String orderId = trade.getOrderId();
447 |
448 | OrderInfo info = tradeService.getOrderInfo(orderId);
449 |
450 | if (info.getNum() == 0) {
451 |
452 | result.setResult(toFailureJson("获取订单表订单失败"));
453 |
454 | return result;
455 | }
456 |
457 | if (info.getState()) {
458 |
459 | result.setResult(toFailureJson("订单已经支付成功"));
460 |
461 | return result;
462 | }
463 | trade.setTotalFee(info.getTotalFee());
464 |
465 | if (trade.getTotalFee().compareTo(BigDecimal.ZERO) == 0) {
466 |
467 | result.setResult(toFailureJson("获取订单表订单失败"));
468 |
469 | return result;
470 | }
471 |
472 | result.setTrade(trade);
473 | return result;
474 | }
475 |
476 | private final ValidateResult validateTradeDataForAliDirect(String data, HttpServletRequest request) {
477 |
478 | ValidateResult result = new ValidateResult();
479 | result.setTrade(null);
480 | result.setResult(toFailureJson("ok"));
481 | String dec = this.handleData(data);
482 | if (dec.equals("")) {
483 |
484 | result.setResult(toFailureJson("解密失败"));
485 |
486 | return result;
487 | }
488 |
489 | String[] tradeParam = dec.split("&");
490 | Trade trade = new Trade();
491 | trade.setBody(tradeParam[1].split("=")[1]);
492 | if (trade.getBody().length() > 20) {
493 | trade.setBody(trade.getBody().substring(0, 20) + "...");
494 | }
495 |
496 |
497 | trade.setOrderId(tradeParam[0].split("=")[1]);
498 | trade.setIp(this.getClientIP(request));
499 | trade.setPayType(PayType.ALI_PAY_Direct);
500 |
501 | String orderId = trade.getOrderId();
502 |
503 | OrderInfo info = tradeService.getOrderInfo(orderId);
504 |
505 | if (info.getNum() == 0) {
506 |
507 | result.setResult(toFailureJson("获取订单表订单失败"));
508 |
509 | return result;
510 | }
511 |
512 | if (info.getState()) {
513 |
514 | result.setResult(toFailureJson("订单已经支付成功"));
515 |
516 | return result;
517 | }
518 |
519 | trade.setTotalFee(info.getTotalFee());
520 |
521 | if (trade.getTotalFee().compareTo(BigDecimal.ZERO) == 0) {
522 |
523 | result.setResult(toFailureJson("获取订单表订单失败"));
524 |
525 | return result;
526 | }
527 |
528 |
529 | result.setTrade(trade);
530 | return result;
531 | }
532 | private final ValidateResult validateTradeDataForAliWAP(String data, HttpServletRequest request) {
533 |
534 | ValidateResult result = new ValidateResult();
535 | result.setTrade(null);
536 | result.setResult(toFailureJson("ok"));
537 | String dec = this.handleData(data);
538 | if (dec.equals("")) {
539 |
540 | result.setResult(toFailureJson("解密失败"));
541 |
542 | return result;
543 | }
544 |
545 | String[] tradeParam = dec.split("&");
546 | Trade trade = new Trade();
547 | trade.setBody(tradeParam[1].split("=")[1]);
548 | if (trade.getBody().length() > 20) {
549 | trade.setBody(trade.getBody().substring(0, 20) + "...");
550 | }
551 |
552 | trade.setOrderId(tradeParam[0].split("=")[1]);
553 | trade.setIp(this.getClientIP(request));
554 | trade.setPayType(PayType.ALI_PAY_WAP);
555 | String orderId = trade.getOrderId();
556 |
557 | OrderInfo info = tradeService.getOrderInfo(orderId);
558 |
559 | if (info.getNum() == 0) {
560 |
561 | result.setResult(toFailureJson("获取订单表订单失败"));
562 |
563 | return result;
564 | }
565 |
566 | if (info.getState()) {
567 |
568 | result.setResult(toFailureJson("订单已经支付成功"));
569 |
570 | return result;
571 | }
572 |
573 | trade.setTotalFee(info.getTotalFee());
574 |
575 | if (trade.getTotalFee().compareTo(BigDecimal.ZERO) == 0) {
576 |
577 | result.setResult(toFailureJson("获取订单表订单失败"));
578 |
579 | return result;
580 | }
581 |
582 |
583 | result.setTrade(trade);
584 | return result;
585 | }
586 |
587 | private class ValidateResult {
588 |
589 | public Trade getTrade() {
590 | return trade;
591 | }
592 |
593 | public void setTrade(Trade trade) {
594 | this.trade = trade;
595 | }
596 |
597 | public String getResult() {
598 | return result;
599 | }
600 |
601 | public void setResult(String result) {
602 | this.result = result;
603 | }
604 |
605 | private Trade trade;
606 | private String result;
607 | }
608 | }
--------------------------------------------------------------------------------
/src/main/java/spring/boot/pay/dao/BaseDao.java:
--------------------------------------------------------------------------------
1 | package spring.boot.pay.dao;
2 |
3 | import org.springframework.beans.factory.annotation.Autowired;
4 | import org.springframework.beans.factory.annotation.Qualifier;
5 | import org.springframework.jdbc.core.JdbcTemplate;
6 | import org.springframework.jdbc.core.namedparam.NamedParameterJdbcTemplate;
7 |
8 | public class BaseDao {
9 |
10 | @Autowired
11 | @Qualifier("pay")
12 | protected JdbcTemplate jdbcTemplate;
13 |
14 | @Autowired
15 | @Qualifier("namePay")
16 | protected NamedParameterJdbcTemplate namedParameterJdbcTemplate;
17 |
18 | @Autowired
19 | @Qualifier("order")
20 | protected JdbcTemplate jdbcTemplateOrder;
21 |
22 | @Autowired
23 | @Qualifier("nameOrder")
24 | protected NamedParameterJdbcTemplate namedParameterJdbcTemplateOrder;
25 | }
26 |
--------------------------------------------------------------------------------
/src/main/java/spring/boot/pay/dao/TradeDao.java:
--------------------------------------------------------------------------------
1 | package spring.boot.pay.dao;
2 |
3 | import java.math.BigDecimal;
4 |
5 | import org.slf4j.Logger;
6 | import org.slf4j.LoggerFactory;
7 | import org.springframework.stereotype.Repository;
8 |
9 | import spring.boot.pay.model.Trade;
10 |
11 | @Repository
12 | public class TradeDao extends BaseDao {
13 |
14 | private Logger logger = LoggerFactory.getLogger(getClass());
15 |
16 | /**
17 | * 保存交易请求
18 | *
19 | * @param trade
20 | * 交易请求
21 | * @return 成功返回交易请求的id,保存失败返回-1
22 | */
23 | public int save(Trade trade) {
24 |
25 | throw new UnsupportedOperationException();
26 |
27 | }
28 |
29 | /**
30 | * 更新交易的结果
31 | *
32 | * @param trade
33 | * 交易结果
34 | */
35 | public void updateReturnContent(Trade trade) {
36 |
37 | throw new UnsupportedOperationException();
38 | }
39 |
40 | /**
41 | * 更新交易的结果
42 | *
43 | * @param trade
44 | * 交易结果
45 | */
46 | public void updateResult(Trade trade) {
47 | throw new UnsupportedOperationException();
48 | }
49 |
50 | /**
51 | * 更新交易的状态,用于交易完成后
52 | *
53 | * @param trade
54 | * 交易的状态
55 | */
56 | public void updateStatus(int status, String orderId) {
57 |
58 | throw new UnsupportedOperationException();
59 | }
60 |
61 | /**
62 | * 查询订单号是否在交易中,以及状态
63 | */
64 | public Trade checkOrderStatus(Trade trade) {
65 | throw new UnsupportedOperationException();
66 | }
67 |
68 | public BigDecimal getOrderTotalPrice(String orderId) {
69 | throw new UnsupportedOperationException();
70 | }
71 |
72 |
73 | }
--------------------------------------------------------------------------------
/src/main/java/spring/boot/pay/framework/base/PayStatus.java:
--------------------------------------------------------------------------------
1 | package spring.boot.pay.framework.base;
2 |
3 |
4 | public interface PayStatus {
5 |
6 | int STATUS_ACCEPTED = 0;//已接收
7 | int STATUS_TRYING = 1; //正在进行
8 | int STATUS_FAIL = 2; //失败
9 | int STATUS_SUCCESS = 3; //成功
10 |
11 |
12 | }
13 |
--------------------------------------------------------------------------------
/src/main/java/spring/boot/pay/framework/base/PayTask.java:
--------------------------------------------------------------------------------
1 | package spring.boot.pay.framework.base;
2 |
3 |
4 | public interface PayTask {
5 |
6 | int STATUS_ACCEPTED = 0;//已接收
7 | int STATUS_TRYING = 1; //正在进行
8 | int STATUS_FAIL = 2; //失败
9 | int STATUS_SUCCESS = 3; //成功
10 | int STATUS_FirstFailed_pre=4;//未得到第三方支付响应提供的预支付id
11 | int STATUS_FirstFailed_qc=5;//未得到第三方支付响应提供的codeurl
12 |
13 |
14 |
15 |
16 | }
17 |
--------------------------------------------------------------------------------
/src/main/java/spring/boot/pay/framework/base/ResultModel.java:
--------------------------------------------------------------------------------
1 | package spring.boot.pay.framework.base;
2 |
3 |
4 | public final class ResultModel {
5 |
6 | public static final int RETURN_CODE_SUCCESS = 0;
7 | public static final int RETURN_CODE_FAIL = 1;
8 |
9 | private ResultModel(int code, Object body) {
10 | this.code = code;
11 | this.body = body;
12 | }
13 |
14 | private int code = 0;
15 | private Object body;
16 |
17 |
18 | public int getCode() {
19 | return code;
20 | }
21 | public Object getBody() {
22 | return body;
23 | }
24 | public void setBody(Object body) {
25 | this.body = body;
26 | }
27 | public boolean isSuccess(){
28 | return getCode() == RETURN_CODE_SUCCESS;
29 | }
30 | public boolean isFail(){
31 | return getCode() != RETURN_CODE_SUCCESS;
32 | }
33 |
34 |
35 | public static ResultModel buildModel(boolean flag){
36 | if(flag)
37 | return successModel();
38 | return failModel();
39 | }
40 | public static ResultModel successModel(){
41 | return successModel("");
42 | }
43 | public static ResultModel successModel(Object body){
44 | return new ResultModel(RETURN_CODE_SUCCESS,body);
45 | }
46 | public static ResultModel failModel(){
47 | return failModel("");
48 | }
49 | public static ResultModel failModel(Object body){
50 | return new ResultModel(RETURN_CODE_FAIL,body);
51 | }
52 | }
53 |
--------------------------------------------------------------------------------
/src/main/java/spring/boot/pay/framework/filter/LogFilter.java:
--------------------------------------------------------------------------------
1 | package spring.boot.pay.framework.filter;
2 |
3 |
4 | import java.io.IOException;
5 |
6 | import javax.servlet.Filter;
7 | import javax.servlet.FilterChain;
8 | import javax.servlet.FilterConfig;
9 | import javax.servlet.ServletException;
10 | import javax.servlet.ServletRequest;
11 | import javax.servlet.ServletResponse;
12 | import javax.servlet.http.HttpServletRequest;
13 | import javax.servlet.http.HttpServletResponse;
14 |
15 | import org.slf4j.Logger;
16 | import org.slf4j.LoggerFactory;
17 | import org.springframework.stereotype.Component;
18 |
19 | import com.alibaba.fastjson.JSON;
20 |
21 | import spring.boot.pay.common.HttpServRequestHelper;
22 |
23 | @Component
24 | public class LogFilter implements Filter {
25 |
26 | Logger logger = LoggerFactory.getLogger(getClass());
27 |
28 | @Override
29 | public void init(FilterConfig filterConfig) throws ServletException {
30 |
31 | }
32 |
33 | @Override
34 | public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
35 |
36 | HttpServletRequest req = (HttpServletRequest) request;
37 | HttpServletResponse resp = (HttpServletResponse)response;
38 | resp.setHeader("Access-Control-Allow-Origin", "*.*.com");
39 |
40 | long start = System.nanoTime();
41 |
42 | try {
43 | chain.doFilter(request,response);
44 | }catch (Exception e){
45 | logger.error(e.getMessage(),e);
46 | }
47 |
48 | long end = System.nanoTime();
49 |
50 | String url = req.getRequestURL().toString();
51 |
52 | if(logger.isInfoEnabled())
53 | logger.info("ip:{} , url: {} , time: {} , params:{}",getClientIP(req),url,end-start, JSON.toJSON(HttpServRequestHelper.genSortedMap(req)));
54 |
55 | }
56 |
57 | @Override
58 | public void destroy() {
59 |
60 | }
61 |
62 | private String getClientIP(HttpServletRequest request) {
63 |
64 | String ip = request.getHeader("X-Forwarded-For");
65 |
66 | if (ip == null || ip.length() == 0 || "unknown".equals(ip)) {
67 | ip = request.getHeader("Proxy-Client-IP");
68 | }
69 | if (ip == null || ip.length() == 0 || "unknown".equals(ip)) {
70 | ip = request.getHeader("WL-Proxy-Client-IP");
71 | }
72 | if (ip == null || ip.length() == 0 || "unknown".equals(ip)) {
73 | ip = request.getRemoteAddr();
74 | }
75 | return ip==null?"":ip;
76 | }
77 | }
78 |
79 |
--------------------------------------------------------------------------------
/src/main/java/spring/boot/pay/framework/processor/Processor.java:
--------------------------------------------------------------------------------
1 | package spring.boot.pay.framework.processor;
2 |
3 | import spring.boot.pay.framework.base.PayTask;
4 | import spring.boot.pay.framework.base.ResultModel;
5 |
6 | public interface Processor {
7 |
8 | ResultModel process(T t);
9 |
10 | }
11 |
--------------------------------------------------------------------------------
/src/main/java/spring/boot/pay/framework/processor/ProcessorManager.java:
--------------------------------------------------------------------------------
1 | package spring.boot.pay.framework.processor;
2 |
3 | import java.lang.reflect.ParameterizedType;
4 | import java.lang.reflect.Type;
5 | import java.util.HashMap;
6 | import java.util.Map;
7 |
8 | import org.springframework.beans.BeansException;
9 | import org.springframework.beans.factory.config.BeanPostProcessor;
10 | import org.springframework.stereotype.Component;
11 |
12 | import com.alibaba.fastjson.JSON;
13 |
14 | import spring.boot.pay.framework.base.PayTask;
15 | import spring.boot.pay.framework.base.ResultModel;
16 |
17 | @Component
18 | public class ProcessorManager implements BeanPostProcessor {
19 |
20 | private static final Class DEF_TASK_TYPE = Object.class;
21 |
22 | private Map