🔥码云GVP开源项目 12k star Uniapp+ElementUI 功能强大 支持多语言、二开方便! 广告
1.获得openid ~~~ @WebServlet("/GetOpenIdServlet") public class GetOpenIdServlet extends HttpServlet { private static final long serialVersionUID = 1L; private static final String APPID = ""; private static final String APPSECRET = ""; private static final String oauth_connect_token_url = "https://open.weixin.qq.com/connect/oauth2/authorize?appid=APPID&redirect_uri=URL&response_type=code&scope=snsapi_base&state=123#wechat_redirect"; private static final String oauth_access_token_url = "https://api.weixin.qq.com/sns/oauth2/access_token?appid=APPID&secret=SECRET&code=CODE&grant_type=authorization_code"; protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { this.doPost(request, response); } protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { String code = request.getParameter("code"); if(code==null ||code.length()==0) { //1. 获得code StringBuffer url = request.getRequestURL(); String codeRequestUrl = oauth_connect_token_url.replace("APPID", APPID).replace("URL", url); response.sendRedirect(codeRequestUrl); } else { System.out.println("================================="+code); //2. 获得openid String requestUrl = oauth_access_token_url.replace("APPID", APPID).replace("SECRET", APPSECRET).replace("CODE", code); System.out.println("requestUrl:"+requestUrl); JSONObject jsonCode = httpsRequest(requestUrl,"GET"); String openid=""; if (jsonCode != null && !"".equals(jsonCode)) { openid = jsonCode.getString("openid"); } System.out.println("==============openId=========================" + openid); request.setAttribute("openid", openid); request.getRequestDispatcher("/pay.jsp").forward(request, response); } } } ~~~ 2. pay.jsp发起支付 ~~~ <%@ page language="java" contentType="text/html; charset=utf-8" pageEncoding="utf-8"%> <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"> <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=utf-8"> <title>Insert title here</title> <script type="text/javascript" src="js/jquery-3.2.1.js"></script> <script type="text/javascript"> <% String path = request.getContextPath(); String basePath = request.getScheme()+"://"+request.getServerName()+":"+request.getServerPort()+path+"/"; %> $(function(){ $("#btn_pay").click(function(){ $.post('<%=basePath%>/PayServlet', { openid: $("#openid").val(), nname: "feiyy", phone: "15940471397" },//新版支付(便利店+商场共用) function (data) { if (data) { data = JSON.parse(data); //微信支付 if (data.result == "true") { WeixinJSBridge.invoke('getBrandWCPayRequest', { "appId": data.appId, //公众号名称,由商户传入 "timeStamp": data.timeStamp, //时间戳,自1970年以来的秒数 "nonceStr": data.nonceStr, //随机串 "package": data.package, "signType": data.signType, //微信签名方式: "paySign": data.paySign //微信签名 }, function (res) { alert(res.err_msg); alert(JSON.stringify(res)); if (res.err_msg == "get_brand_wcpay_request:ok") { window.location.href="payResult.html"; } else if (res.err_msg == "get_brand_wcpay_request:cancel") { alert("用户取消支付!"); } else { alert("支付失败!"); } }); } else { alert("支付失败"); } } }) }); }) </script> </head> <body> <input type="hidden" value="<%=request.getAttribute("openid") %>" id="openid"/> <input id="btn_pay" type="button" value="支付 "/> </body> </html> ~~~ PayServlet ~~~ import java.io.ByteArrayInputStream; import java.io.IOException; import java.io.InputStream; import java.io.PrintWriter; import java.text.SimpleDateFormat; import java.util.Date; import java.util.HashMap; import java.util.Iterator; import java.util.List; import java.util.Map; import java.util.Set; import java.util.SortedMap; import java.util.TreeMap; import java.util.UUID; import javax.servlet.ServletException; import javax.servlet.annotation.WebServlet; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import org.apache.http.HttpResponse; import org.apache.http.client.HttpClient; import org.apache.http.client.methods.HttpPost; import org.apache.http.client.params.ClientPNames; import org.apache.http.conn.ClientConnectionManager; import org.apache.http.conn.scheme.Scheme; import org.apache.http.conn.scheme.SchemeRegistry; import org.apache.http.entity.StringEntity; import org.apache.http.impl.client.DefaultHttpClient; import org.apache.http.util.EntityUtils; import org.eclipse.jdt.internal.compiler.batch.Main; import org.jdom.Document; import org.jdom.Element; import org.jdom.input.SAXBuilder; import net.sf.json.JSONObject; @WebServlet("/PayServlet") public class PayServlet extends HttpServlet { private static final long serialVersionUID = 1L; private static final String appid= ""; private static final String appsecret= ""; private static final String partner=""; private static final String partnerkey = ""; public static DefaultHttpClient httpclient; static { httpclient = new DefaultHttpClient(); httpclient = (DefaultHttpClient)HttpClientConnectionManager.getSSLInstance(httpclient); } protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { this.doPost(request, response); } protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { //1. 获得openid String openid = request.getParameter("openid"); System.out.println("PayServlet==="+openid); //2. 获得nonceStr String nonceStr = this.getNonceStr(); String finalpackage= this.getPackage(openid,nonceStr,request); finalpackage= "{\"result\":\"true\","+finalpackage+"}"; System.out.println(finalpackage); response.setContentType("text/plain"); PrintWriter out = response.getWriter(); out.write(finalpackage); out.flush(); //5. ajax影响 {result:"", package:"", paySign:""} } public String createSign(SortedMap<String, String> packageParams) { StringBuffer sb = new StringBuffer(); Set es = packageParams.entrySet(); Iterator it = es.iterator(); while (it.hasNext()) { Map.Entry entry = (Map.Entry) it.next(); String k = (String) entry.getKey(); String v = (String) entry.getValue(); if (null != v && !"".equals(v) && !"sign".equals(k) && !"key".equals(k)) { sb.append(k + "=" + v + "&"); } } sb.append("key=" + partnerkey); System.out.println("sign-------------------加密前:"+sb.toString()); String sign = MD5Util.MD5Encode(sb.toString(), "UTF-8") .toUpperCase(); System.out.println("sign-------------------加密后:"+sign); return sign; } public String getPayNo(String url,String xmlParam){ DefaultHttpClient client = new DefaultHttpClient(); client.getParams().setParameter(ClientPNames.ALLOW_CIRCULAR_REDIRECTS, true); HttpPost httpost= HttpClientConnectionManager.getPostMethod(url); String prepay_id = ""; try { httpost.setEntity(new StringEntity(xmlParam, "UTF-8")); HttpResponse response = httpclient.execute(httpost); String jsonStr = EntityUtils.toString(response.getEntity(), "UTF-8"); System.out.println("weixin fanhui preid:"+jsonStr); if(jsonStr.indexOf("FAIL")!=-1){ return prepay_id; } Map map = doXMLParse(jsonStr); prepay_id = (String) map.get("prepay_id"); } catch (Exception e) { // TODO Auto-generated catch block e.printStackTrace(); } return prepay_id; } public static Map doXMLParse(String strxml) throws Exception { if(null == strxml || "".equals(strxml)) { return null; } Map m = new HashMap(); SAXBuilder builder = new SAXBuilder(); Document doc = builder.build(new ByteArrayInputStream(strxml.getBytes())); Element root = doc.getRootElement(); List list = root.getChildren(); Iterator it = list.iterator(); while(it.hasNext()) { Element e = (Element) it.next(); String k = e.getName(); String v = ""; List children = e.getChildren(); if(children.isEmpty()) { v = e.getTextNormalize(); } else { v = getChildrenText(children); } m.put(k, v); } //关闭流 return m; } /** * 获取子结点的xml * @param children * @return String */ public static String getChildrenText(List children) { StringBuffer sb = new StringBuffer(); if(!children.isEmpty()) { Iterator it = children.iterator(); while(it.hasNext()) { Element e = (Element) it.next(); String name = e.getName(); String value = e.getTextNormalize(); List list = e.getChildren(); sb.append("<" + name + ">"); if(!list.isEmpty()) { sb.append(getChildrenText(list)); } sb.append(value); sb.append("</" + name + ">"); } } return sb.toString(); } public String getNonceStr() { // 随机数 String currTime = this.getCurrTime(); // 8位日期 String strTime = currTime.substring(8, currTime.length()); // 四位随机数 String strRandom = this.buildRandom(4) + ""; // 10位序列号,可以自行调整。 return strTime + strRandom; } public String getCurrTime() { Date now = new Date(); SimpleDateFormat outFormat = new SimpleDateFormat("yyyyMMddHHmmss"); String s = outFormat.format(now); return s; } public int buildRandom(int length) { int num = 1; double random = Math.random(); if (random < 0.1) { random = random + 0.1; } for (int i = 0; i < length; i++) { num = num * 10; } return (int) ((random * num)); } private String getPackage(String openId, String nonce_str,HttpServletRequest request) { SortedMap<String, String> packageParams = new TreeMap<String, String>(); String mch_id = partner; String body = "测试订单"; String out_trade_no = UUID.randomUUID().toString().replace("-", ""); String attach = "feiyy,15940471397"; String totalFee = "1"; String spbill_create_ip = "127.0.0.1"; //String path = request.getContextPath(); //String basePath = request.getScheme()+"://"+request.getServerName()+":"+request.getServerPort()+path+"/"; //String notify_url = basePath+"/NotifyServlet"; String notify_url = "http://www.zyrc.tech/TestWeixinPay/NotifyServlet"; String trade_type = "JSAPI"; packageParams.put("appid", appid); packageParams.put("mch_id", mch_id); packageParams.put("nonce_str", nonce_str); packageParams.put("body", body); packageParams.put("out_trade_no", out_trade_no); packageParams.put("attach", "feiyy,15940471397"); // 这里写的金额为1 分到时修改 packageParams.put("total_fee", totalFee); packageParams.put("spbill_create_ip", spbill_create_ip); packageParams.put("notify_url", notify_url); packageParams.put("trade_type", trade_type); packageParams.put("openid", openId); String sign = this.createSign(packageParams); String xml = "<xml>" + "<appid>" + appid + "</appid>" + "<mch_id>"+ mch_id + "</mch_id>" + "<nonce_str>" + nonce_str + "</nonce_str>" + "<sign>" + sign + "</sign>"+ "<body><![CDATA[" + body + "]]></body>" + "<out_trade_no>" + out_trade_no+ "</out_trade_no>" + "<attach>" + attach + "</attach>"+ "<total_fee>" + totalFee + "</total_fee>"+ "<spbill_create_ip>" + spbill_create_ip+ "</spbill_create_ip>"+ "<notify_url>" + notify_url+ "</notify_url>" + "<trade_type>" + trade_type+ "</trade_type>" + "<openid>" + openId + "</openid>"+ "</xml>"; System.out.println("xml======"+xml); String prepay_id = ""; String createOrderURL = "https://api.mch.weixin.qq.com/pay/unifiedorder"; prepay_id = this.getPayNo(createOrderURL, xml); System.out.println("商城获取到的预支付ID:" + prepay_id); //获取prepay_id后,拼接最后请求支付所需要的package SortedMap<String, String> finalpackage = new TreeMap<String, String>(); String timestamp = String.valueOf(System.currentTimeMillis() / 1000); String packages = "prepay_id="+prepay_id; finalpackage.put("appId", appid); finalpackage.put("timeStamp", timestamp); finalpackage.put("nonceStr", nonce_str); finalpackage.put("package", packages); finalpackage.put("signType", "MD5"); //要签名 String finalsign = this.createSign(finalpackage); String finaPackage = "\"appId\":\"" + appid + "\",\"timeStamp\":\"" + timestamp + "\",\"nonceStr\":\"" + nonce_str + "\",\"package\":\"" + packages + "\",\"signType\":\"MD5" + "\",\"paySign\":\"" + finalsign + "\""; System.out.println("V3 jsApi package:"+finaPackage); return finaPackage; } } ~~~ HttpClientConnectionManager ~~~ import org.apache.http.client.HttpClient; import org.apache.http.client.methods.HttpGet; import org.apache.http.client.methods.HttpPost; import org.apache.http.conn.ClientConnectionManager; import org.apache.http.conn.scheme.Scheme; import org.apache.http.conn.scheme.SchemeRegistry; import org.apache.http.impl.client.DefaultHttpClient; public class HttpClientConnectionManager { /** * 获取SSL验证的HttpClient * @param httpClient * @return */ public static HttpClient getSSLInstance(HttpClient httpClient){ ClientConnectionManager ccm = httpClient.getConnectionManager(); SchemeRegistry sr = ccm.getSchemeRegistry(); sr.register(new Scheme("https", MySSLSocketFactory.getInstance(), 443)); httpClient = new DefaultHttpClient(ccm, httpClient.getParams()); return httpClient; } /** * 模拟浏览器post提交 * * @param url * @return */ public static HttpPost getPostMethod(String url) { HttpPost pmethod = new HttpPost(url); // 设置响应头信息 pmethod.addHeader("Connection", "keep-alive"); pmethod.addHeader("Accept", "*/*"); pmethod.addHeader("Content-Type", "application/x-www-form-urlencoded; charset=UTF-8"); pmethod.addHeader("Host", "api.mch.weixin.qq.com"); pmethod.addHeader("X-Requested-With", "XMLHttpRequest"); pmethod.addHeader("Cache-Control", "max-age=0"); pmethod.addHeader("User-Agent", "Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 6.0) "); return pmethod; } /** * 模拟浏览器GET提交 * @param url * @return */ public static HttpGet getGetMethod(String url) { HttpGet pmethod = new HttpGet(url); // 设置响应头信息 pmethod.addHeader("Connection", "keep-alive"); pmethod.addHeader("Cache-Control", "max-age=0"); pmethod.addHeader("User-Agent", "Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 6.0) "); pmethod.addHeader("Accept", "text/html,application/xhtml+xml,application/xml;q=0.9,*/;q=0.8"); return pmethod; } } ~~~ MySSLSocketFactory ~~~ import java.security.KeyManagementException; import java.security.NoSuchAlgorithmException; import javax.net.ssl.SSLContext; import javax.net.ssl.TrustManager; import org.apache.http.conn.ssl.SSLSocketFactory; public class MySSLSocketFactory extends SSLSocketFactory{ static{ mySSLSocketFactory = new MySSLSocketFactory(createSContext()); } private static MySSLSocketFactory mySSLSocketFactory = null; private static SSLContext createSContext(){ SSLContext sslcontext = null; try { sslcontext = SSLContext.getInstance("SSL"); } catch (NoSuchAlgorithmException e) { e.printStackTrace(); } try { sslcontext.init(null, new TrustManager[]{new TrustAnyTrustManager()}, null); } catch (KeyManagementException e) { e.printStackTrace(); return null; } return sslcontext; } private MySSLSocketFactory(SSLContext sslContext) { super(sslContext); this.setHostnameVerifier(ALLOW_ALL_HOSTNAME_VERIFIER); } public static MySSLSocketFactory getInstance(){ if(mySSLSocketFactory != null){ return mySSLSocketFactory; }else{ return mySSLSocketFactory = new MySSLSocketFactory(createSContext()); } } } ~~~ MyX509TrustManager ~~~ import java.security.cert.CertificateException; import java.security.cert.X509Certificate; import javax.net.ssl.X509TrustManager; /** * 证书信任管理器(用于https请求) * * @author 捷微团队 * @date 2013-08-08 */ public class MyX509TrustManager implements X509TrustManager { public void checkClientTrusted(X509Certificate[] chain, String authType) throws CertificateException { } public void checkServerTrusted(X509Certificate[] chain, String authType) throws CertificateException { } public X509Certificate[] getAcceptedIssuers() { return null; } } ~~~ TrustAnyTrustManager ~~~ import java.security.cert.CertificateException; import java.security.cert.X509Certificate; import javax.net.ssl.X509TrustManager; /** * * @author Administrator * */ public class TrustAnyTrustManager implements X509TrustManager{ public void checkClientTrusted(X509Certificate[] chain, String authType) throws CertificateException { } public void checkServerTrusted(X509Certificate[] chain, String authType) throws CertificateException { } public X509Certificate[] getAcceptedIssuers() { return null; } } ~~~ MD5Util ~~~ import java.security.MessageDigest; public class MD5Util { private static String byteArrayToHexString(byte b[]) { StringBuffer resultSb = new StringBuffer(); for (int i = 0; i < b.length; i++) resultSb.append(byteToHexString(b[i])); return resultSb.toString(); } private static String byteToHexString(byte b) { int n = b; if (n < 0) n += 256; int d1 = n / 16; int d2 = n % 16; return hexDigits[d1] + hexDigits[d2]; } public static String MD5Encode(String origin, String charsetname) { String resultString = null; try { resultString = new String(origin); MessageDigest md = MessageDigest.getInstance("MD5"); if (charsetname == null || "".equals(charsetname)) resultString = byteArrayToHexString(md.digest(resultString .getBytes())); else resultString = byteArrayToHexString(md.digest(resultString .getBytes(charsetname))); } catch (Exception exception) { } return resultString; } private static final String hexDigits[] = { "0", "1", "2", "3", "4", "5", "6", "7", "8", "9", "a", "b", "c", "d", "e", "f" }; } ~~~