├── README.md ├── WebContent ├── WEB-INF │ ├── lib │ │ ├── core-3.2.1.jar │ │ ├── javase-3.2.1.jar │ │ ├── jaxen-1.1.6.jar │ │ ├── jdom-1.1.3.jar │ │ └── log4j-1.2.17.jar │ └── web.xml ├── index.jsp └── testpay.jsp └── src ├── com └── wqy │ ├── Notify1.java │ ├── Pay1.java │ ├── Re_notify.java │ └── util │ ├── HttpUtil.java │ ├── MD5Util.java │ ├── PayCommonUtil.java │ ├── PayConfigUtil.java │ └── XMLUtil.java └── log4j.properties /README.md: -------------------------------------------------------------------------------- 1 | # wpay 2 | 微信扫码支付模式一 3 | -------------------------------------------------------------------------------- /WebContent/WEB-INF/lib/core-3.2.1.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wangqiuyun/wpay/71e060b2d75764fdd5579a4edff50a3010f64a04/WebContent/WEB-INF/lib/core-3.2.1.jar -------------------------------------------------------------------------------- /WebContent/WEB-INF/lib/javase-3.2.1.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wangqiuyun/wpay/71e060b2d75764fdd5579a4edff50a3010f64a04/WebContent/WEB-INF/lib/javase-3.2.1.jar -------------------------------------------------------------------------------- /WebContent/WEB-INF/lib/jaxen-1.1.6.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wangqiuyun/wpay/71e060b2d75764fdd5579a4edff50a3010f64a04/WebContent/WEB-INF/lib/jaxen-1.1.6.jar -------------------------------------------------------------------------------- /WebContent/WEB-INF/lib/jdom-1.1.3.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wangqiuyun/wpay/71e060b2d75764fdd5579a4edff50a3010f64a04/WebContent/WEB-INF/lib/jdom-1.1.3.jar -------------------------------------------------------------------------------- /WebContent/WEB-INF/lib/log4j-1.2.17.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wangqiuyun/wpay/71e060b2d75764fdd5579a4edff50a3010f64a04/WebContent/WEB-INF/lib/log4j-1.2.17.jar -------------------------------------------------------------------------------- /WebContent/WEB-INF/web.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | wpay 4 | 5 | index.html 6 | index.htm 7 | index.jsp 8 | default.html 9 | default.htm 10 | default.jsp 11 | 12 | -------------------------------------------------------------------------------- /WebContent/index.jsp: -------------------------------------------------------------------------------- 1 | <%@ page language="java" contentType="text/html; charset=UTF-8" 2 | pageEncoding="UTF-8"%> 3 | 4 | 5 | 6 | 7 | 支付回调 8 | 9 | 10 |

支付回调模式一

11 | 12 | -------------------------------------------------------------------------------- /WebContent/testpay.jsp: -------------------------------------------------------------------------------- 1 | <%@ page language="java" contentType="text/html; charset=UTF-8" 2 | pageEncoding="UTF-8"%> 3 | 4 | 5 | 6 | 7 | testpay 8 | 9 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /src/com/wqy/Notify1.java: -------------------------------------------------------------------------------- 1 | package com.wqy; 2 | 3 | import java.io.BufferedOutputStream; 4 | import java.io.BufferedReader; 5 | import java.io.IOException; 6 | import java.io.InputStream; 7 | import java.io.InputStreamReader; 8 | import java.util.SortedMap; 9 | import java.util.TreeMap; 10 | 11 | import javax.servlet.ServletException; 12 | import javax.servlet.annotation.WebServlet; 13 | import javax.servlet.http.HttpServlet; 14 | import javax.servlet.http.HttpServletRequest; 15 | import javax.servlet.http.HttpServletResponse; 16 | 17 | import org.apache.log4j.Logger; 18 | 19 | import com.wqy.util.HttpUtil; 20 | import com.wqy.util.PayCommonUtil; 21 | import com.wqy.util.PayConfigUtil; 22 | 23 | /** 24 | * Servlet implementation class Notify1 25 | */ 26 | @WebServlet("/Notify1") 27 | public class Notify1 extends HttpServlet { 28 | private static final long serialVersionUID = 1L; 29 | private static Logger logger = Logger.getLogger(Notify1.class); 30 | 31 | /** 32 | * @see HttpServlet#HttpServlet() 33 | */ 34 | public Notify1() { 35 | super(); 36 | // TODO Auto-generated constructor stub 37 | } 38 | 39 | /** 40 | * @see HttpServlet#doGet(HttpServletRequest request, HttpServletResponse 41 | * response) 42 | */ 43 | protected void doGet(HttpServletRequest request, HttpServletResponse response) 44 | throws ServletException, IOException { 45 | // TODO Auto-generated method stub 46 | 47 | // 读取xml 48 | InputStream inputStream; 49 | StringBuffer sb = new StringBuffer(); 50 | inputStream = request.getInputStream(); 51 | String s; 52 | BufferedReader in = new BufferedReader(new InputStreamReader(inputStream, "UTF-8")); 53 | while ((s = in.readLine()) != null) { 54 | sb.append(s); 55 | } 56 | in.close(); 57 | inputStream.close(); 58 | 59 | SortedMap packageParams = PayCommonUtil.xmlConvertToMap(sb.toString()); 60 | logger.info(packageParams); 61 | 62 | // 账号信息 63 | String key = PayConfigUtil.API_KEY; // key 64 | 65 | String resXml="";//反馈给微信服务器 66 | // 验签 67 | if (PayCommonUtil.isTenpaySign("UTF-8", packageParams, key)) { 68 | //appid openid mch_id is_subscribe nonce_str product_id sign 69 | 70 | //统一下单 71 | String openid = (String)packageParams.get("openid"); 72 | String product_id = (String)packageParams.get("product_id"); 73 | //解析product_id,计算价格等 74 | 75 | String out_trade_no = String.valueOf(System.currentTimeMillis()); // 订单号 76 | String order_price = "1"; // 价格 注意:价格的单位是分 77 | String body = product_id; // 商品名称 这里设置为product_id 78 | String attach = "XXX店"; //附加数据 79 | 80 | String nonce_str0 = PayCommonUtil.getNonce_str(); 81 | 82 | // 获取发起电脑 ip 83 | String spbill_create_ip = PayConfigUtil.CREATE_IP; 84 | String trade_type = "NATIVE"; 85 | 86 | 87 | SortedMap unifiedParams = new TreeMap(); 88 | unifiedParams.put("appid", PayConfigUtil.APP_ID); // 必须 89 | unifiedParams.put("mch_id", PayConfigUtil.MCH_ID); // 必须 90 | unifiedParams.put("out_trade_no", out_trade_no); // 必须 91 | unifiedParams.put("product_id", product_id); 92 | unifiedParams.put("body", body); // 必须 93 | unifiedParams.put("attach", attach); 94 | unifiedParams.put("total_fee", order_price); // 必须 95 | unifiedParams.put("nonce_str", nonce_str0); // 必须 96 | unifiedParams.put("spbill_create_ip", spbill_create_ip); // 必须 97 | unifiedParams.put("trade_type", trade_type); // 必须 98 | unifiedParams.put("openid", openid); 99 | unifiedParams.put("notify_url", PayConfigUtil.NOTIFY_URL);//异步通知url 100 | 101 | String sign0 = PayCommonUtil.createSign("UTF-8", unifiedParams,key); 102 | unifiedParams.put("sign", sign0); //签名 103 | 104 | String requestXML = PayCommonUtil.getRequestXml(unifiedParams); 105 | logger.info(requestXML); 106 | //统一下单接口 107 | String rXml = HttpUtil.postData(PayConfigUtil.UFDODER_URL, requestXML); 108 | 109 | //统一下单响应 110 | SortedMap reParams = PayCommonUtil.xmlConvertToMap(rXml); 111 | logger.info(reParams); 112 | 113 | //验签 114 | if (PayCommonUtil.isTenpaySign("UTF-8", reParams, key)) { 115 | // 统一下单返回的参数 116 | String prepay_id = (String)reParams.get("prepay_id");//交易会话标识 2小时内有效 117 | 118 | String nonce_str1 = PayCommonUtil.getNonce_str(); 119 | 120 | SortedMap resParams = new TreeMap(); 121 | resParams.put("return_code", "SUCCESS"); // 必须 122 | resParams.put("return_msg", "OK"); 123 | resParams.put("appid", PayConfigUtil.APP_ID); // 必须 124 | resParams.put("mch_id", PayConfigUtil.MCH_ID); 125 | resParams.put("nonce_str", nonce_str1); // 必须 126 | resParams.put("prepay_id", prepay_id); // 必须 127 | resParams.put("result_code", "SUCCESS"); // 必须 128 | resParams.put("err_code_des", "OK"); 129 | 130 | String sign1 = PayCommonUtil.createSign("UTF-8", resParams,key); 131 | resParams.put("sign", sign1); //签名 132 | 133 | resXml = PayCommonUtil.getRequestXml(resParams); 134 | logger.info(resXml); 135 | 136 | }else{ 137 | logger.info("签名验证错误"); 138 | resXml = "" + "" 139 | + "" + " "; 140 | } 141 | 142 | }else{ 143 | logger.info("签名验证错误"); 144 | resXml = "" + "" 145 | + "" + " "; 146 | } 147 | 148 | //------------------------------ 149 | //处理业务完毕 150 | //------------------------------ 151 | BufferedOutputStream out = new BufferedOutputStream( 152 | response.getOutputStream()); 153 | out.write(resXml.getBytes()); 154 | out.flush(); 155 | out.close(); 156 | 157 | } 158 | 159 | /** 160 | * @see HttpServlet#doPost(HttpServletRequest request, HttpServletResponse 161 | * response) 162 | */ 163 | protected void doPost(HttpServletRequest request, HttpServletResponse response) 164 | throws ServletException, IOException { 165 | // TODO Auto-generated method stub 166 | doGet(request, response); 167 | } 168 | 169 | } 170 | -------------------------------------------------------------------------------- /src/com/wqy/Pay1.java: -------------------------------------------------------------------------------- 1 | package com.wqy; 2 | 3 | import java.io.IOException; 4 | import java.io.OutputStream; 5 | import java.util.HashMap; 6 | import java.util.Iterator; 7 | import java.util.Map; 8 | import java.util.Set; 9 | import java.util.SortedMap; 10 | import java.util.TreeMap; 11 | 12 | import javax.servlet.ServletException; 13 | import javax.servlet.annotation.WebServlet; 14 | import javax.servlet.http.HttpServlet; 15 | import javax.servlet.http.HttpServletRequest; 16 | import javax.servlet.http.HttpServletResponse; 17 | 18 | import org.apache.log4j.Logger; 19 | 20 | import com.google.zxing.BarcodeFormat; 21 | import com.google.zxing.EncodeHintType; 22 | import com.google.zxing.MultiFormatWriter; 23 | import com.google.zxing.WriterException; 24 | import com.google.zxing.client.j2se.MatrixToImageWriter; 25 | import com.google.zxing.common.BitMatrix; 26 | import com.google.zxing.qrcode.decoder.ErrorCorrectionLevel; 27 | import com.wqy.util.PayCommonUtil; 28 | import com.wqy.util.PayConfigUtil; 29 | 30 | /** 31 | * Servlet implementation class Pay1 32 | */ 33 | @WebServlet("/Pay1") 34 | public class Pay1 extends HttpServlet { 35 | private static final long serialVersionUID = 1L; 36 | private static Logger logger = Logger.getLogger(Pay1.class); 37 | 38 | public static int defaultWidthAndHeight=200; 39 | 40 | /** 41 | * @see HttpServlet#HttpServlet() 42 | */ 43 | public Pay1() { 44 | super(); 45 | // TODO Auto-generated constructor stub 46 | } 47 | 48 | /** 49 | * @see HttpServlet#doGet(HttpServletRequest request, HttpServletResponse 50 | * response) 51 | */ 52 | protected void doGet(HttpServletRequest request, HttpServletResponse response) 53 | throws ServletException, IOException { 54 | 55 | // TODO Auto-generated method stub 56 | String nonce_str = PayCommonUtil.getNonce_str(); 57 | long time_stamp = System.currentTimeMillis() / 1000; 58 | String product_id = "hd_goodsssss_10"; 59 | String key = PayConfigUtil.API_KEY; // key 60 | 61 | SortedMap packageParams = new TreeMap(); 62 | packageParams.put("appid", PayConfigUtil.APP_ID); 63 | packageParams.put("mch_id", PayConfigUtil.MCH_ID); 64 | packageParams.put("time_stamp", String.valueOf(time_stamp)); 65 | packageParams.put("nonce_str", nonce_str); 66 | packageParams.put("product_id", product_id); 67 | String sign = PayCommonUtil.createSign("UTF-8", packageParams,key);//MD5哈希 68 | packageParams.put("sign", sign); 69 | 70 | //生成参数 71 | String str = ToUrlParams(packageParams); 72 | String payurl = "weixin://wxpay/bizpayurl?" + str; 73 | logger.info("payurl:"+payurl); 74 | 75 | 76 | //生成二维码 77 | Map hints=new HashMap(); 78 | // 指定纠错等级 79 | hints.put(EncodeHintType.ERROR_CORRECTION, ErrorCorrectionLevel.L); 80 | // 指定编码格式 81 | hints.put(EncodeHintType.CHARACTER_SET, "UTF-8"); 82 | hints.put(EncodeHintType.MARGIN, 1); 83 | try { 84 | BitMatrix bitMatrix = new MultiFormatWriter().encode(payurl,BarcodeFormat.QR_CODE, defaultWidthAndHeight, defaultWidthAndHeight, hints); 85 | OutputStream out = response.getOutputStream(); 86 | MatrixToImageWriter.writeToStream(bitMatrix, "png", out);//输出二维码 87 | out.flush(); 88 | out.close(); 89 | 90 | } catch (WriterException e) { 91 | // TODO Auto-generated catch block 92 | e.printStackTrace(); 93 | } 94 | } 95 | 96 | public String ToUrlParams(SortedMap packageParams){ 97 | //实际可以不排序 98 | StringBuffer sb = new StringBuffer(); 99 | Set es = packageParams.entrySet(); 100 | Iterator it = es.iterator(); 101 | while (it.hasNext()) { 102 | Map.Entry entry = (Map.Entry) it.next(); 103 | String k = (String) entry.getKey(); 104 | String v = (String) entry.getValue(); 105 | if (null != v && !"".equals(v)) { 106 | sb.append(k + "=" + v + "&"); 107 | } 108 | } 109 | 110 | sb.deleteCharAt(sb.length()-1);//删掉最后一个& 111 | return sb.toString(); 112 | } 113 | 114 | /** 115 | * @see HttpServlet#doPost(HttpServletRequest request, HttpServletResponse 116 | * response) 117 | */ 118 | protected void doPost(HttpServletRequest request, HttpServletResponse response) 119 | throws ServletException, IOException { 120 | // TODO Auto-generated method stub 121 | doGet(request, response); 122 | } 123 | 124 | } 125 | -------------------------------------------------------------------------------- /src/com/wqy/Re_notify.java: -------------------------------------------------------------------------------- 1 | package com.wqy; 2 | 3 | import java.io.BufferedOutputStream; 4 | import java.io.BufferedReader; 5 | import java.io.IOException; 6 | import java.io.InputStream; 7 | import java.io.InputStreamReader; 8 | import java.util.SortedMap; 9 | 10 | import javax.servlet.ServletException; 11 | import javax.servlet.annotation.WebServlet; 12 | import javax.servlet.http.HttpServlet; 13 | import javax.servlet.http.HttpServletRequest; 14 | import javax.servlet.http.HttpServletResponse; 15 | 16 | import org.apache.log4j.Logger; 17 | 18 | import com.wqy.util.PayCommonUtil; 19 | import com.wqy.util.PayConfigUtil; 20 | 21 | /** 22 | * Servlet implementation class Re_notify 23 | */ 24 | @WebServlet("/Re_notify") 25 | public class Re_notify extends HttpServlet { 26 | private static final long serialVersionUID = 1L; 27 | private static Logger logger = Logger.getLogger(Re_notify.class); 28 | 29 | /** 30 | * @see HttpServlet#HttpServlet() 31 | */ 32 | public Re_notify() { 33 | super(); 34 | // TODO Auto-generated constructor stub 35 | } 36 | 37 | /** 38 | * @see HttpServlet#doGet(HttpServletRequest request, HttpServletResponse 39 | * response) 40 | */ 41 | protected void doGet(HttpServletRequest request, HttpServletResponse response) 42 | throws ServletException, IOException { 43 | // TODO Auto-generated method stub 44 | // 读取参数 45 | InputStream inputStream; 46 | StringBuffer sb = new StringBuffer(); 47 | inputStream = request.getInputStream(); 48 | String s; 49 | BufferedReader in = new BufferedReader(new InputStreamReader(inputStream, "UTF-8")); 50 | while ((s = in.readLine()) != null) { 51 | sb.append(s); 52 | } 53 | in.close(); 54 | inputStream.close(); 55 | 56 | SortedMap packageParams = PayCommonUtil.xmlConvertToMap(sb.toString()); 57 | logger.info(packageParams); 58 | 59 | // 账号信息 60 | String key = PayConfigUtil.API_KEY; // key 61 | 62 | String resXml = ""; // 反馈给微信服务器 63 | // 判断签名是否正确 64 | if (PayCommonUtil.isTenpaySign("UTF-8", packageParams, key)) { 65 | // ------------------------------ 66 | // 处理业务开始 67 | // ------------------------------ 68 | if ("SUCCESS".equals((String) packageParams.get("result_code"))) { 69 | // 这里是支付成功 70 | ////////// 执行自己的业务逻辑//////////////// 71 | String mch_id = (String) packageParams.get("mch_id"); 72 | String openid = (String) packageParams.get("openid"); 73 | String is_subscribe = (String) packageParams.get("is_subscribe"); 74 | String out_trade_no = (String) packageParams.get("out_trade_no"); 75 | 76 | String total_fee = (String) packageParams.get("total_fee"); 77 | 78 | logger.info("mch_id:" + mch_id); 79 | logger.info("openid:" + openid); 80 | logger.info("is_subscribe:" + is_subscribe); 81 | logger.info("out_trade_no:" + out_trade_no); 82 | logger.info("total_fee:" + total_fee); 83 | 84 | ////////// 执行自己的业务逻辑//////////////// 85 | 86 | logger.info("支付成功"); 87 | // 通知微信.异步确认成功.必写.不然会一直通知后台.八次之后就认为交易失败了. 88 | resXml = "" + "" 89 | + "" + " "; 90 | 91 | } else { 92 | logger.info("支付失败,错误信息:" + packageParams.get("err_code")); 93 | resXml = "" + "" 94 | + "" + " "; 95 | } 96 | 97 | } else { 98 | logger.info("签名验证错误"); 99 | resXml = "" + "" 100 | + "" + " "; 101 | } 102 | 103 | // ------------------------------ 104 | // 处理业务完毕 105 | // ------------------------------ 106 | BufferedOutputStream out = new BufferedOutputStream(response.getOutputStream()); 107 | out.write(resXml.getBytes()); 108 | out.flush(); 109 | out.close(); 110 | } 111 | 112 | /** 113 | * @see HttpServlet#doPost(HttpServletRequest request, HttpServletResponse 114 | * response) 115 | */ 116 | protected void doPost(HttpServletRequest request, HttpServletResponse response) 117 | throws ServletException, IOException { 118 | // TODO Auto-generated method stub 119 | doGet(request, response); 120 | } 121 | 122 | } 123 | -------------------------------------------------------------------------------- /src/com/wqy/util/HttpUtil.java: -------------------------------------------------------------------------------- 1 | package com.wqy.util; 2 | 3 | import java.io.BufferedReader; 4 | import java.io.IOException; 5 | import java.io.InputStreamReader; 6 | import java.io.OutputStreamWriter; 7 | import java.net.URL; 8 | import java.net.URLConnection; 9 | 10 | import org.apache.log4j.Logger; 11 | 12 | public class HttpUtil { 13 | 14 | private static Logger logger = Logger.getLogger(HttpUtil.class); 15 | private final static int CONNECT_TIMEOUT = 5000; // in milliseconds 16 | private final static String DEFAULT_ENCODING = "UTF-8"; 17 | 18 | public static String postData(String urlStr, String data){ 19 | return postData(urlStr, data, null); 20 | } 21 | 22 | public static String postData(String urlStr, String data, String contentType){ 23 | BufferedReader reader = null; 24 | try { 25 | URL url = new URL(urlStr); 26 | URLConnection conn = url.openConnection(); 27 | conn.setDoOutput(true); 28 | conn.setConnectTimeout(CONNECT_TIMEOUT); 29 | conn.setReadTimeout(CONNECT_TIMEOUT); 30 | if(contentType != null) 31 | conn.setRequestProperty("content-type", contentType); 32 | OutputStreamWriter writer = new OutputStreamWriter(conn.getOutputStream(), DEFAULT_ENCODING); 33 | if(data == null) 34 | data = ""; 35 | writer.write(data); 36 | writer.flush(); 37 | writer.close(); 38 | 39 | reader = new BufferedReader(new InputStreamReader(conn.getInputStream(), DEFAULT_ENCODING)); 40 | StringBuilder sb = new StringBuilder(); 41 | String line = null; 42 | while ((line = reader.readLine()) != null) { 43 | sb.append(line); 44 | sb.append("\r\n"); 45 | } 46 | return sb.toString(); 47 | } catch (IOException e) { 48 | logger.error("Error connecting to " + urlStr + ": " + e.getMessage()); 49 | } finally { 50 | try { 51 | if (reader != null) 52 | reader.close(); 53 | } catch (IOException e) { 54 | } 55 | } 56 | return null; 57 | } 58 | } 59 | -------------------------------------------------------------------------------- /src/com/wqy/util/MD5Util.java: -------------------------------------------------------------------------------- 1 | package com.wqy.util; 2 | 3 | import java.security.MessageDigest; 4 | 5 | public class MD5Util { 6 | 7 | private static String byteArrayToHexString(byte b[]) { 8 | StringBuffer resultSb = new StringBuffer(); 9 | for (int i = 0; i < b.length; i++) 10 | resultSb.append(byteToHexString(b[i])); 11 | 12 | return resultSb.toString(); 13 | } 14 | 15 | private static String byteToHexString(byte b) { 16 | int n = b; 17 | if (n < 0) 18 | n += 256; 19 | int d1 = n / 16; 20 | int d2 = n % 16; 21 | return hexDigits[d1] + hexDigits[d2]; 22 | } 23 | 24 | public static String MD5Encode(String origin, String charsetname) { 25 | String resultString = null; 26 | try { 27 | resultString = new String(origin); 28 | MessageDigest md = MessageDigest.getInstance("MD5"); 29 | if (charsetname == null || "".equals(charsetname)) 30 | resultString = byteArrayToHexString(md.digest(resultString 31 | .getBytes())); 32 | else 33 | resultString = byteArrayToHexString(md.digest(resultString 34 | .getBytes(charsetname))); 35 | } catch (Exception exception) { 36 | } 37 | return resultString; 38 | } 39 | 40 | private static final String hexDigits[] = { "0", "1", "2", "3", "4", "5", 41 | "6", "7", "8", "9", "a", "b", "c", "d", "e", "f" }; 42 | 43 | } 44 | -------------------------------------------------------------------------------- /src/com/wqy/util/PayCommonUtil.java: -------------------------------------------------------------------------------- 1 | package com.wqy.util; 2 | 3 | import java.text.SimpleDateFormat; 4 | import java.util.Date; 5 | import java.util.HashMap; 6 | import java.util.Iterator; 7 | import java.util.Map; 8 | import java.util.Set; 9 | import java.util.SortedMap; 10 | import java.util.TreeMap; 11 | 12 | public class PayCommonUtil { 13 | 14 | public static SortedMap xmlConvertToMap(String rxml) { 15 | // 解析xml成map 16 | Map m = new HashMap(); 17 | try { 18 | m = XMLUtil.doXMLParse(rxml); 19 | } catch (Exception e) { 20 | // TODO Auto-generated catch block 21 | e.printStackTrace(); 22 | } 23 | // 过滤空 设置 SortedMap 24 | SortedMap packageParams = new TreeMap(); 25 | Iterator it = m.keySet().iterator(); 26 | while (it.hasNext()) { 27 | String parameter = (String) it.next(); 28 | String parameterValue = m.get(parameter); 29 | 30 | String v = ""; 31 | if (null != parameterValue) { 32 | v = parameterValue.trim(); 33 | } 34 | packageParams.put(parameter, v); 35 | } 36 | return packageParams; 37 | } 38 | 39 | /** 40 | * 是否签名正确,规则是:按参数名称a-z排序,遇到空值的参数不参加签名。 41 | * 42 | * @return boolean 43 | */ 44 | public static boolean isTenpaySign(String characterEncoding, SortedMap packageParams, 45 | String API_KEY) { 46 | StringBuffer sb = new StringBuffer(); 47 | Set es = packageParams.entrySet(); 48 | Iterator it = es.iterator(); 49 | while (it.hasNext()) { 50 | Map.Entry entry = (Map.Entry) it.next(); 51 | String k = (String) entry.getKey(); 52 | String v = (String) entry.getValue(); 53 | if (!"sign".equals(k) && null != v && !"".equals(v)) { 54 | sb.append(k + "=" + v + "&"); 55 | } 56 | } 57 | 58 | sb.append("key=" + API_KEY); 59 | 60 | // 算出摘要 61 | String mysign = MD5Util.MD5Encode(sb.toString(), characterEncoding).toLowerCase(); 62 | String tenpaySign = ((String) packageParams.get("sign")).toLowerCase(); 63 | 64 | // System.out.println(tenpaySign + " " + mysign); 65 | return tenpaySign.equals(mysign); 66 | } 67 | 68 | /** 69 | * @author 70 | * @date 2016-4-22 71 | * @Description:sign签名 72 | * @param characterEncoding 73 | * 编码格式 74 | * @param parameters 75 | * 请求参数 76 | * @return 77 | */ 78 | public static String createSign(String characterEncoding, SortedMap packageParams, String API_KEY) { 79 | StringBuffer sb = new StringBuffer(); 80 | Set es = packageParams.entrySet(); 81 | Iterator it = es.iterator(); 82 | while (it.hasNext()) { 83 | Map.Entry entry = (Map.Entry) it.next(); 84 | String k = (String) entry.getKey(); 85 | String v = (String) entry.getValue(); 86 | if (null != v && !"".equals(v) && !"sign".equals(k) && !"key".equals(k)) { 87 | sb.append(k + "=" + v + "&"); 88 | } 89 | } 90 | sb.append("key=" + API_KEY); 91 | String sign = MD5Util.MD5Encode(sb.toString(), characterEncoding).toUpperCase(); 92 | return sign; 93 | } 94 | 95 | /** 96 | * @author 97 | * @date 2016-4-22 98 | * @Description:将请求参数转换为xml格式的string 99 | * @param parameters 100 | * 请求参数 101 | * @return 102 | */ 103 | public static String getRequestXml(SortedMap parameters) { 104 | StringBuffer sb = new StringBuffer(); 105 | sb.append(""); 106 | Set es = parameters.entrySet(); 107 | Iterator it = es.iterator(); 108 | while (it.hasNext()) { 109 | Map.Entry entry = (Map.Entry) it.next(); 110 | String k = (String) entry.getKey(); 111 | String v = (String) entry.getValue(); 112 | if ("attach".equalsIgnoreCase(k) || "body".equalsIgnoreCase(k) || "sign".equalsIgnoreCase(k)) { 113 | sb.append("<" + k + ">" + ""); 114 | } else { 115 | sb.append("<" + k + ">" + v + ""); 116 | } 117 | } 118 | sb.append(""); 119 | return sb.toString(); 120 | } 121 | 122 | /** 123 | * 取出一个指定长度大小的随机正整数. 124 | * 125 | * @param length 126 | * int 设定所取出随机数的长度。length小于11 127 | * @return int 返回生成的随机数。 128 | */ 129 | public static int buildRandom(int length) { 130 | int num = 1; 131 | double random = Math.random(); 132 | if (random < 0.1) { 133 | random = random + 0.1; 134 | } 135 | for (int i = 0; i < length; i++) { 136 | num = num * 10; 137 | } 138 | return (int) ((random * num)); 139 | } 140 | 141 | /** 142 | * 获取当前时间 yyyyMMddHHmmss 143 | * 144 | * @return String 145 | */ 146 | public static String getCurrTime() { 147 | Date now = new Date(); 148 | SimpleDateFormat outFormat = new SimpleDateFormat("yyyyMMddHHmmss"); 149 | String s = outFormat.format(now); 150 | return s; 151 | } 152 | 153 | /** 154 | * 获取当前时间 yyyyMMddHHmmss 155 | * 156 | * @return String 157 | */ 158 | public static String getNonce_str() { 159 | Date now = new Date(); 160 | SimpleDateFormat outFormat = new SimpleDateFormat("yyyyMMddHHmmss"); 161 | String bg = outFormat.format(now); 162 | bg.substring(8, bg.length()); 163 | String end = String.valueOf(buildRandom(4)); 164 | return bg+end; 165 | } 166 | } 167 | -------------------------------------------------------------------------------- /src/com/wqy/util/PayConfigUtil.java: -------------------------------------------------------------------------------- 1 | package com.wqy.util; 2 | 3 | public class PayConfigUtil { 4 | 5 | //以下相关参数需要根据自己实际情况进行配置 6 | public static String APP_ID = "wx8000000111144444";// appid 7 | 8 | public static String APP_SECRET = "0fb66116e9f46d2d71116b30f0addd85";// appsecret 9 | public static String MCH_ID = "1311111100";// 你的商业号 10 | public static String API_KEY = "0f666116e944466661117777f0addddd";// API key 11 | 12 | public static String CREATE_IP = "8.8.8.8";// key 13 | public static String UFDODER_URL = "https://api.mch.weixin.qq.com/pay/unifiedorder";//统一下单接口 14 | public static String NOTIFY_URL = "http://80.20.1.195:8080/wpay/Re_notify";//回调地址 15 | } 16 | -------------------------------------------------------------------------------- /src/com/wqy/util/XMLUtil.java: -------------------------------------------------------------------------------- 1 | package com.wqy.util; 2 | 3 | import java.io.ByteArrayInputStream; 4 | import java.io.IOException; 5 | import java.io.InputStream; 6 | import java.util.HashMap; 7 | import java.util.Iterator; 8 | import java.util.List; 9 | import java.util.Map; 10 | 11 | import org.jdom.Document; 12 | import org.jdom.Element; 13 | import org.jdom.JDOMException; 14 | import org.jdom.input.SAXBuilder; 15 | 16 | public class XMLUtil { 17 | 18 | /** 19 | * 解析xml,返回第一级元素键值对。如果第一级元素有子节点,则此节点的值是子节点的xml数据。 20 | * @param strxml 21 | * @return 22 | * @throws JDOMException 23 | * @throws IOException 24 | */ 25 | public static Map doXMLParse(String strxml) throws JDOMException, IOException { 26 | strxml = strxml.replaceFirst("encoding=\".*\"", "encoding=\"UTF-8\""); 27 | 28 | if(null == strxml || "".equals(strxml)) { 29 | return null; 30 | } 31 | 32 | Map m = new HashMap(); 33 | 34 | InputStream in = new ByteArrayInputStream(strxml.getBytes("UTF-8")); 35 | SAXBuilder builder = new SAXBuilder(); 36 | Document doc = builder.build(in); 37 | Element root = doc.getRootElement(); 38 | List list = root.getChildren(); 39 | Iterator it = list.iterator(); 40 | while(it.hasNext()) { 41 | Element e = (Element) it.next(); 42 | String k = e.getName(); 43 | String v = ""; 44 | List children = e.getChildren(); 45 | if(children.isEmpty()) { 46 | v = e.getTextNormalize(); 47 | } else { 48 | v = XMLUtil.getChildrenText(children); 49 | } 50 | 51 | m.put(k, v); 52 | } 53 | 54 | //关闭流 55 | in.close(); 56 | 57 | return m; 58 | } 59 | 60 | /** 61 | * 获取子结点的xml 62 | * @param children 63 | * @return String 64 | */ 65 | public static String getChildrenText(List children) { 66 | StringBuffer sb = new StringBuffer(); 67 | if(!children.isEmpty()) { 68 | Iterator it = children.iterator(); 69 | while(it.hasNext()) { 70 | Element e = (Element) it.next(); 71 | String name = e.getName(); 72 | String value = e.getTextNormalize(); 73 | List list = e.getChildren(); 74 | sb.append("<" + name + ">"); 75 | if(!list.isEmpty()) { 76 | sb.append(XMLUtil.getChildrenText(list)); 77 | } 78 | sb.append(value); 79 | sb.append(""); 80 | } 81 | } 82 | 83 | return sb.toString(); 84 | } 85 | } 86 | -------------------------------------------------------------------------------- /src/log4j.properties: -------------------------------------------------------------------------------- 1 | log4j.rootLogger=INFO,A1,R 2 | 3 | log4j.appender.A1=org.apache.log4j.ConsoleAppender 4 | log4j.appender.A1.Target=System.out 5 | log4j.appender.A1.layout=org.apache.log4j.PatternLayout 6 | log4j.appender.A1.layout.ConversionPattern=[%c]%m%n 7 | 8 | log4j.appender.R=org.apache.log4j.RollingFileAppender 9 | log4j.appender.R.File=D:/logs/wpay.log 10 | log4j.appender.R.MaxFileSize=10MB 11 | log4j.appender.R.Threshold=ALL 12 | log4j.appender.R.layout=org.apache.log4j.PatternLayout 13 | log4j.appender.R.layout.ConversionPattern=[%p][%d{yyyy-MM-dd HH\:mm\:ss,SSS}][%c]%m%n --------------------------------------------------------------------------------