完整微信支付接入案例源码:点我下载案例源码
本章节由于要晒实现代码,所以篇幅有点长,读者可把代码复制到工程中,配置好参数即可实现,本案例站长亲测并实现。
整体工程项目实现说明:
1. 项目使用springmvc restful风格的,需要用到jar包请自行下载 2. 整个项目只需要修改com.tenpay.configure.WxPayConfig中的配置信息就行。 // appid public static String APP_ID = "公众id"; // JSAPI接口中获取openid,审核后在公众平台开启开发模式后可查看 public static String APP_SECRET = "公众号中的秘钥"; // 受理商ID,身份标识 public static String MCH_ID = "商户id"; // 商户支付密钥Key,装完整数后,配置得到。32位长度 public static String KEY = "商户平台中配置证书,设置的秘钥"; // 异步回调地址 public static String NOTIFY_URL = "支付成功后的回调action"; public static String CHARTSET = "UTF-8"; // 加密方式 public static String SIGN_TYPE = "MD5"; // redirect_uri,微信授权重定向地址 public static String REDIRECT_URI; static { try { REDIRECT_URI = URLEncoder.encode("微信授权成功后重定向的action", CHARTSET); } catch (UnsupportedEncodingException e) { e.printStackTrace(); } } 3. 项目核心类com.tenpay.action.WxPayAction pay函数:支付前准备函数,从数据库获取订单号,查询订单金额,订单描述、openid、prepay_id等等。 notify函数:支付成功后异步回调函数。
一、新建基于springMVC框架的javaweb项目名字为wxPay
二、java代码实现
2.1 com.tenpay.action.WxPayAction代码
package com.tenpay.action; import java.io.ByteArrayOutputStream; import java.io.IOException; import java.io.InputStream; import java.io.UnsupportedEncodingException; import java.util.Map; import java.util.SortedMap; import java.util.TreeMap; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import org.jdom2.JDOMException; import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.RequestMapping; import com.tenpay.RequestHandler; import com.tenpay.configure.WxPayConfig; import com.tenpay.service.ServiceUtil; import com.tenpay.util.MD5Util; import com.tenpay.util.Sha1Util; import com.tenpay.util.XMLUtil; import net.sf.json.JSONObject; /******************************************************************************* * <b>类名: WxPayAction.java</b> <br/> * 功能:微信支付,调用jsapi<br/> * 日期:<br/> * * @author V型知识库 www.vxzsk.com * @version 1.0 * ******************************************************************************/ @Controller @RequestMapping("/v_3") public class WxPayAction { /** * 微信客户端授权成功后根据redirect_uri参数调整到pay接口,去准备支付前信息接口 * @param request * @param response * @return * @throws Exception */ @RequestMapping("pay") public String order(HttpServletRequest request, HttpServletResponse response) throws Exception { /** * 第一步:用户同意授权,根据参数,获取code * 授权成功后返回的授权码,参考:http://mp.weixin.qq.com/wiki/17/c0f37d5704f0b64713d5d2c37b468d75.html#.E7.AC.AC.E4.B8.80.E6.AD.A5.EF.BC.9A.E7.94.A8.E6.88.B7.E5.90.8C.E6.84.8F.E6.8E.88.E6.9D.83.EF.BC.8C.E8.8E.B7.E5.8F.96code */ String code = request.getParameter("code"); String state = request.getParameter("state"); // state可以为任何含义,根据你前端需求,这里暂时叫商品id // 授权码、商品id System.out.println("code=" + code + ",state=" + state); /** * 第二步:通过code换取网页授权access_token * 根据授权码code获取access_token,参考:http://mp.weixin.qq.com/wiki/17/c0f37d5704f0b64713d5d2c37b468d75.html#.E7.AC.AC.E4.BA.8C.E6.AD.A5.EF.BC.9A.E9.80.9A.E8.BF.87code.E6.8D.A2.E5.8F.96.E7.BD.91.E9.A1.B5.E6.8E.88.E6.9D.83access_token */ // 下面就到了获取openid,这个代表用户id. // 获取openID String openid = ServiceUtil.getOpenId(code); // 生成随机字符串 String noncestr = Sha1Util.getNonceStr(); // 生成1970年到现在的秒数. String timestamp = Sha1Util.getTimeStamp(); // 订单号,自定义生成规则,只要全局唯一就OK String out_trade_no = "NO" + System.currentTimeMillis() + "0001"; // 订单金额,应该是根据state(商品id)从数据库中查询出来 String order_price = String.valueOf(1); // 商品描述,应该是根据state(商品id)从数据库中查询出来 String body = "商品描述,测试...."; /** * 第三步:统一下单接口 * 需要第二步生成的openid,参考:https://pay.weixin.qq.com/wiki/doc/api/jsapi.php?chapter=9_1 */ RequestHandler reqHandler = new RequestHandler(request, response); // 初始化 RequestHandler 类可以在微信的文档中找到.还有相关工具类 reqHandler.init(); // 执行统一下单接口 获得预支付id,一下是必填参数 // 微信分配的公众账号ID(企业号corpid即为此appId) reqHandler.setParameter("appid", WxPayConfig.APP_ID); // 微信支付分配的商户号 reqHandler.setParameter("mch_id", WxPayConfig.MCH_ID); // 终端设备号(门店号或收银设备ID),注意:PC网页或公众号内支付请传"WEB" reqHandler.setParameter("device_info", "WEB"); // 随机字符串,不长于32位。推荐随机数生成算法 reqHandler.setParameter("nonce_str", noncestr); // 商品描述 reqHandler.setParameter("body", body); // 商家订单号 reqHandler.setParameter("out_trade_no", out_trade_no); // 商品金额,以分为单位 reqHandler.setParameter("total_fee", order_price); // APP和网页支付提交用户端ip,Native支付填调用微信支付API的机器IP。 reqHandler.setParameter("spbill_create_ip", "123.57.58.123"); // 下面的notify_url是用户支付成功后为微信调用的action 异步回调. reqHandler.setParameter("notify_url", WxPayConfig.NOTIFY_URL); // 交易类型,取值如下:JSAPI,NATIVE,APP,详细说明见参数规定 reqHandler.setParameter("trade_type", "JSAPI"); // ------------需要进行用户授权获取用户openid------------- reqHandler.setParameter("openid", openid); // 这个必填. /* * <xml><appid>wx2421b1c4370ec43b</appid><attach>支付测试</attach><body> * JSAPI支付测试</body><mch_id>10000100</mch_id><nonce_str> * 1add1a30ac87aa2db72f57a2375d8fec</nonce_str><notify_url>http://wxpay. * weixin.qq.com/pub_v2/pay/notify.v2.php</notify_url><openid> * oUpF8uMuAJO_M2pxb1Q9zNjWeS6o</openid><out_trade_no>1415659990</ * out_trade_no><spbill_create_ip>14.23.150.211</spbill_create_ip>< * total_fee>1</total_fee><trade_type>JSAPI</trade_type><sign> * 0CB01533B8C1EF103065174F50BCA001</sign></xml> */ // 生成签名,并且转为xml String requestXml = reqHandler.getRequestXml(); System.out.println("requestXml:" + requestXml); // 得到的预支付id String prepay_id = ServiceUtil.unifiedorder(requestXml); SortedMap<String, String> params = new TreeMap<String, String>(); params.put("appId", WxPayConfig.APP_ID); params.put("timeStamp", timestamp); params.put("nonceStr", noncestr); params.put("package", "prepay_id=" + prepay_id); params.put("signType", "MD5"); System.out.println("params:" + JSONObject.fromObject(params).toString()); // 生成支付签名,这个签名 给 微信支付的调用使用 SortedMap<Object,Object> signMap = new TreeMap<Object,Object>(); signMap.put("appId", WxPayConfig.APP_ID); signMap.put("timeStamp", timestamp); signMap.put("nonceStr", noncestr); signMap.put("package", "prepay_id=" + prepay_id); signMap.put("signType", "MD5"); // 微信支付签名 String paySign = MD5Util.createSign(signMap, WxPayConfig.KEY); System.out.println("PaySIGN:" + paySign); //微信分配的公众账号ID(企业号corpid即为此appId) request.setAttribute("appId", WxPayConfig.APP_ID); // 时间戳 request.setAttribute("timeStamp", timestamp); // 随机字符串 request.setAttribute("nonceStr", noncestr); // 预支付id ,就这样的格式 request.setAttribute("package", "prepay_id=" + prepay_id); // 加密格式 request.setAttribute("signType", WxPayConfig.SIGN_TYPE); // 微信支付签名 request.setAttribute("paySign", paySign); return "pay"; } /** * 异步返回 */ @RequestMapping("notify") public String notify(HttpServletRequest request, HttpServletResponse response) { try { InputStream inStream = request.getInputStream(); ByteArrayOutputStream outSteam = new ByteArrayOutputStream(); byte[] buffer = new byte[1024]; int len = 0; while ((len = inStream.read(buffer)) != -1) { outSteam.write(buffer, 0, len); } outSteam.close(); inStream.close(); String resultStr = new String(outSteam.toByteArray(), WxPayConfig.CHARTSET); Map<String, String> resultMap = XMLUtil.doXMLParse(resultStr); System.out.println("微信回调结果:" + resultMap.toString()); String result_code = resultMap.get("result_code"); String is_subscribe = resultMap.get("is_subscribe"); String out_trade_no = resultMap.get("out_trade_no"); String transaction_id = resultMap.get("transaction_id"); String sign = resultMap.get("sign"); String time_end = resultMap.get("time_end"); String bank_type = resultMap.get("bank_type"); String return_code = resultMap.get("return_code"); // 签名验证 // GenericValue userLogin = delegator.findOne("UserLogin", UtilMisc.toMap("userLoginId", "admin"), false); if (return_code.equals("SUCCESS")) { // 此处就是你的逻辑代码 // 修改数据库支付状态 } request.setAttribute("out_trade_no", out_trade_no); // 通知微信.异步确认成功.必写.不然会一直通知后台.八次之后就认为交易失败了. response.getWriter().write(RequestHandler.setXML("SUCCESS", "")); } catch (UnsupportedEncodingException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } catch (JDOMException e) { e.printStackTrace(); } return "notify"; } }
2.2 com.tenpay.configure.WxPayConfig 代码
package com.tenpay.configure; import java.io.UnsupportedEncodingException; import java.net.URLEncoder; public class WxPayConfig { // appid public static String APP_ID = ""; // JSAPI接口中获取openid,审核后在公众平台开启开发模式后可查看 public static String APP_SECRET = ""; // 受理商ID,身份标识 public static String MCH_ID = ""; // 商户支付密钥Key,装完整数后,配置得到。 public static String KEY = ""; // 异步回调地址 public static String NOTIFY_URL = "https://www.vxzsk.com/wechat/v_3/notify"; // 字符编码 public static String CHARTSET = "UTF-8"; // 加密方式 public static String SIGN_TYPE = "MD5"; // redirect_uri,微信授权重定向地址 public static String REDIRECT_URI; static { try { REDIRECT_URI = URLEncoder.encode("https://www.vxzsk.com/wechat/v_3/pay", CHARTSET); } catch (UnsupportedEncodingException e) { e.printStackTrace(); } } }
2.3 com.tenpay.service.ServiceUtil 代码
package com.tenpay.service; import java.io.BufferedReader; import java.io.InputStreamReader; import java.io.OutputStreamWriter; import java.net.HttpURLConnection; import java.net.URL; import java.util.Map; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import com.tenpay.configure.WxPayConfig; import com.tenpay.util.HttpClientUtil; import com.tenpay.util.XMLUtil; import net.sf.json.JSONObject; /** * 自定义类,在官方文档中没有 * * */ public class ServiceUtil { private static final Log logger = LogFactory.getLog(ServiceUtil.class); /** * 第二步:通过code换取网页授权access_token * 根据授权码code获取access_token,参考:http://mp.weixin.qq.com/wiki/17/c0f37d5704f0b64713d5d2c37b468d75.html#.E7.AC.AC.E4.BA.8C.E6.AD.A5.EF.BC.9A.E9.80.9A.E8.BF.87code.E6.8D.A2.E5.8F.96.E7.BD.91.E9.A1.B5.E6.8E.88.E6.9D.83access_token */ public static String getOpenId(String code) { String openParam = "appid=" + WxPayConfig.APP_ID + "&secret=" + WxPayConfig.APP_SECRET + "&code=" + code + "&grant_type=authorization_code"; String openJsonStr = HttpClientUtil.sendGET("https://api.weixin.qq.com/sns/oauth2/access_token", openParam); System.out.println("openJsonStr:"+openJsonStr); // 获取openid JSONObject openJson = JSONObject.fromObject(openJsonStr); String openid = openJson.getString("openid"); return openid; } /** * 统一下单接口 * 参考文档:https://pay.weixin.qq.com/wiki/doc/api/jsapi.php?chapter=9_1 * @return * @throws Exception */ public static String unifiedorder(String requestXml) throws Exception{ // 统一下单接口提交 xml格式 URL orderUrl = new URL("https://api.mch.weixin.qq.com/pay/unifiedorder"); HttpURLConnection conn = (HttpURLConnection) orderUrl.openConnection(); conn.setConnectTimeout(30000); // 设置连接主机超时(单位:毫秒) conn.setReadTimeout(30000); // 设置从主机读取数据超时(单位:毫秒) conn.setDoOutput(true); // post请求参数要放在http正文内,顾设置成true,默认是false conn.setDoInput(true); // 设置是否从httpUrlConnection读入,默认情况下是true conn.setUseCaches(false); // Post 请求不能使用缓存 // 设定传送的内容类型是可序列化的java对象(如果不设此项,在传送序列化对象时,当WEB服务默认的不是这种类型时可能抛java.io.EOFException) conn.setRequestProperty("Content-Type", "application/x-www-form-urlencoded"); conn.setRequestMethod("POST");// 设定请求的方法为"POST",默认是GET conn.setRequestProperty("Content-Length", requestXml.length() + ""); OutputStreamWriter out = new OutputStreamWriter(conn.getOutputStream(), WxPayConfig.CHARTSET); out.write(requestXml.toString()); out.flush(); out.close(); if (conn.getResponseCode() != HttpURLConnection.HTTP_OK) { return null; } // 获取响应内容体 BufferedReader in = new BufferedReader(new InputStreamReader(conn.getInputStream(), WxPayConfig.CHARTSET)); String line = ""; StringBuffer strBuf = new StringBuffer(); while ((line = in.readLine()) != null) { strBuf.append(line).append("\n"); } in.close(); System.out.println("result=========返回的xml=============" + strBuf.toString()); Map<String, String> orderMap = XMLUtil.doXMLParse(strBuf.toString()); System.out.println("orderMap===========================" + orderMap); // 获取 String prepay_id = orderMap.get("prepay_id"); return prepay_id; } }
2.4 com.tenpay.util.HttpClientUtil 代码
package com.tenpay.util; import java.io.BufferedReader; import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; import java.io.File; import java.io.FileInputStream; import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; import java.io.OutputStream; import java.net.HttpURLConnection; import java.net.URL; import java.net.URLConnection; import java.security.KeyManagementException; import java.security.KeyStore; import java.security.KeyStoreException; import java.security.NoSuchAlgorithmException; import java.security.SecureRandom; import java.security.UnrecoverableKeyException; import java.security.cert.Certificate; import java.security.cert.CertificateException; import java.security.cert.CertificateFactory; import java.util.HashMap; import java.util.Map; import javax.net.ssl.HttpsURLConnection; import javax.net.ssl.KeyManagerFactory; import javax.net.ssl.SSLContext; import javax.net.ssl.TrustManagerFactory; import com.tenpay.configure.WxPayConfig; /** * * */ public class HttpClientUtil { public static final String SunX509 = "SunX509"; public static final String JKS = "JKS"; public static final String PKCS12 = "PKCS12"; public static final String TLS = "TLS"; public static String sendGET(String url, String param) { String result = "";// 访问返回结果 BufferedReader read = null;// 读取访问结果 try { // 创建url URL realurl = new URL(url + "?" + param); // 打开连接 URLConnection connection = realurl.openConnection(); // 设置通用的请求属性 connection.setRequestProperty("accept", "*/*"); connection.setRequestProperty("connection", "Keep-Alive"); connection.setRequestProperty("user-agent", "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1;SV1)"); // 建立连接 connection.connect(); // 获取所有响应头字段 // Map<String, List<String>> map = connection.getHeaderFields(); // 遍历所有的响应头字段,获取到cookies等 // for (String key : map.keySet()) { // System.out.println(key + "--->" + map.get(key)); // } // 定义 BufferedReader输入流来读取URL的响应 read = new BufferedReader(new InputStreamReader(connection.getInputStream(), WxPayConfig.CHARTSET)); String line;// 循环读取 while ((line = read.readLine()) != null) { result += line; } } catch (IOException e) { e.printStackTrace(); } finally { if (read != null) {// 关闭流 try { read.close(); } catch (IOException e) { e.printStackTrace(); } } } return result; } /** * get HttpURLConnection * @param strUrl url��ַ * @return HttpURLConnection * @throws IOException */ public static HttpURLConnection getHttpURLConnection(String strUrl) throws IOException { URL url = new URL(strUrl); HttpURLConnection httpURLConnection = (HttpURLConnection) url .openConnection(); return httpURLConnection; } /** * get HttpsURLConnection * @param strUrl url��ַ * @return HttpsURLConnection * @throws IOException */ public static HttpsURLConnection getHttpsURLConnection(String strUrl) throws IOException { URL url = new URL(strUrl); HttpsURLConnection httpsURLConnection = (HttpsURLConnection) url .openConnection(); return httpsURLConnection; } /** * ��ȡ�����ѯ����url * @param strUrl * @return String */ public static String getURL(String strUrl) { if(null != strUrl) { int indexOf = strUrl.indexOf("?"); if(-1 != indexOf) { return strUrl.substring(0, indexOf); } return strUrl; } return strUrl; } /** * ��ȡ��ѯ�� * @param strUrl * @return String */ public static String getQueryString(String strUrl) { if(null != strUrl) { int indexOf = strUrl.indexOf("?"); if(-1 != indexOf) { return strUrl.substring(indexOf+1, strUrl.length()); } return ""; } return strUrl; } /** * ��ѯ�ַ�ת����Map<br/> * name1=key1&name2=key2&... * @param queryString * @return */ public static Map queryString2Map(String queryString) { if(null == queryString || "".equals(queryString)) { return null; } Map m = new HashMap(); String[] strArray = queryString.split("&"); for(int index = 0; index < strArray.length; index++) { String pair = strArray[index]; HttpClientUtil.putMapByPair(pair, m); } return m; } /** * �Ѽ�ֵ�����Map<br/> * pair:name=value * @param pair name=value * @param m */ public static void putMapByPair(String pair, Map m) { if(null == pair || "".equals(pair)) { return; } int indexOf = pair.indexOf("="); if(-1 != indexOf) { String k = pair.substring(0, indexOf); String v = pair.substring(indexOf+1, pair.length()); if(null != k && !"".equals(k)) { m.put(k, v); } } else { m.put(pair, ""); } } /** * BufferedReaderת����String<br/> * ע��:���ر���Ҫ���д��� * @param reader * @return String * @throws IOException */ public static String bufferedReader2String(BufferedReader reader) throws IOException { StringBuffer buf = new StringBuffer(); String line = null; while( (line = reader.readLine()) != null) { buf.append(line); buf.append("\r\n"); } return buf.toString(); } /** * �������<br/> * ע��:���ر���Ҫ���д��� * @param out * @param data * @param len * @throws IOException */ public static void doOutput(OutputStream out, byte[] data, int len) throws IOException { int dataLen = data.length; int off = 0; while (off < data.length) { if (len >= dataLen) { out.write(data, off, dataLen); off += dataLen; } else { out.write(data, off, len); off += len; dataLen -= len; } // ˢ�»����� out.flush(); } } /** * ��ȡSSLContext * @param trustFile * @param trustPasswd * @param keyFile * @param keyPasswd * @return * @throws NoSuchAlgorithmException * @throws KeyStoreException * @throws IOException * @throws CertificateException * @throws UnrecoverableKeyException * @throws KeyManagementException */ public static SSLContext getSSLContext( FileInputStream trustFileInputStream, String trustPasswd, FileInputStream keyFileInputStream, String keyPasswd) throws NoSuchAlgorithmException, KeyStoreException, CertificateException, IOException, UnrecoverableKeyException, KeyManagementException { // ca TrustManagerFactory tmf = TrustManagerFactory.getInstance(HttpClientUtil.SunX509); KeyStore trustKeyStore = KeyStore.getInstance(HttpClientUtil.JKS); trustKeyStore.load(trustFileInputStream, HttpClientUtil .str2CharArray(trustPasswd)); tmf.init(trustKeyStore); final char[] kp = HttpClientUtil.str2CharArray(keyPasswd); KeyManagerFactory kmf = KeyManagerFactory.getInstance(HttpClientUtil.SunX509); KeyStore ks = KeyStore.getInstance(HttpClientUtil.PKCS12); ks.load(keyFileInputStream, kp); kmf.init(ks, kp); SecureRandom rand = new SecureRandom(); SSLContext ctx = SSLContext.getInstance(HttpClientUtil.TLS); ctx.init(kmf.getKeyManagers(), tmf.getTrustManagers(), rand); return ctx; } /** * ��ȡCA֤����Ϣ * @param cafile CA֤���ļ� * @return Certificate * @throws CertificateException * @throws IOException */ public static Certificate getCertificate(File cafile) throws CertificateException, IOException { CertificateFactory cf = CertificateFactory.getInstance("X.509"); FileInputStream in = new FileInputStream(cafile); Certificate cert = cf.generateCertificate(in); in.close(); return cert; } /** * �ַ�ת����char���� * @param str * @return char[] */ public static char[] str2CharArray(String str) { if(null == str) return null; return str.toCharArray(); } /** * �洢ca֤���JKS��ʽ * @param cert * @param alias * @param password * @param out * @throws KeyStoreException * @throws NoSuchAlgorithmException * @throws CertificateException * @throws IOException */ public static void storeCACert(Certificate cert, String alias, String password, OutputStream out) throws KeyStoreException, NoSuchAlgorithmException, CertificateException, IOException { KeyStore ks = KeyStore.getInstance("JKS"); ks.load(null, null); ks.setCertificateEntry(alias, cert); // store keystore ks.store(out, HttpClientUtil.str2CharArray(password)); } public static InputStream String2Inputstream(String str) { return new ByteArrayInputStream(str.getBytes()); } /** * InputStreamת����Byte * ע��:���ر���Ҫ���д��� * @param in * @return byte * @throws Exception */ public static byte[] InputStreamTOByte(InputStream in) throws IOException{ int BUFFER_SIZE = 4096; ByteArrayOutputStream outStream = new ByteArrayOutputStream(); byte[] data = new byte[BUFFER_SIZE]; int count = -1; while((count = in.read(data,0,BUFFER_SIZE)) != -1) outStream.write(data, 0, count); data = null; byte[] outByte = outStream.toByteArray(); outStream.close(); return outByte; } /** * InputStreamת����String * ע��:���ر���Ҫ���д��� * @param in * @param encoding ���� * @return String * @throws Exception */ public static String InputStreamTOString(InputStream in,String encoding) throws IOException{ return new String(InputStreamTOByte(in),encoding); } }
2.5 com.tenpay.util.JsonUtil
package com.tenpay.util; import net.sf.json.JSONObject; public class JsonUtil { public static String getJsonValue(String rescontent, String key) { JSONObject jsonObject; String v = null; try { jsonObject = JSONObject.fromObject(rescontent); v = jsonObject.getString(key); } catch (Exception e1) { // TODO Auto-generated catch block e1.printStackTrace(); } return v; } }
2.6 com.tenpay.util.MD5Util
package com.tenpay.util; import java.security.MessageDigest; import java.util.Iterator; import java.util.Map; import java.util.Set; import java.util.SortedMap; import com.tenpay.configure.WxPayConfig; public class MD5Util { @SuppressWarnings("rawtypes") public static String createSign(SortedMap<Object, Object> parameters, String key) { StringBuffer sb = new StringBuffer(); Set es = parameters.entrySet();// 所有参与传参的参数按照accsii排序(升序) Iterator it = es.iterator(); while (it.hasNext()) { Map.Entry entry = (Map.Entry) it.next(); String k = (String) entry.getKey(); Object v = entry.getValue(); if (null != v && !"".equals(v) && !"sign".equals(k) && !"key".equals(k)) { sb.append(k + "=" + v + "&"); } } sb.append("key=" + key); String sign = MD5Util.MD5Encode(sb.toString(), WxPayConfig.CHARTSET).toUpperCase(); return sign; } 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" }; }
2.7 com.tenpay.util.Sha1Util
package com.tenpay.util; import java.security.MessageDigest; import java.util.Random; import com.tenpay.configure.WxPayConfig; public class Sha1Util { public static String getNonceStr() { Random random = new Random(); return MD5Util.MD5Encode(String.valueOf(random.nextInt(10000)), WxPayConfig.CHARTSET); } public static String getTimeStamp() { return String.valueOf(System.currentTimeMillis() / 1000); } public static String getSha1(String str) { if (str == null || str.length() == 0) { return null; } char hexDigits[] = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f' }; try { MessageDigest mdTemp = MessageDigest.getInstance("SHA1"); mdTemp.update(str.getBytes()); byte[] md = mdTemp.digest(); int j = md.length; char buf[] = new char[j * 2]; int k = 0; for (int i = 0; i < j; i++) { byte byte0 = md[i]; buf[k++] = hexDigits[byte0 >>> 4 & 0xf]; buf[k++] = hexDigits[byte0 & 0xf]; } return new String(buf); } catch (Exception e) { return null; } } }
2.8 com.tenpay.util.XMLUtil
package com.tenpay.util; import java.io.IOException; import java.io.InputStream; import java.util.HashMap; import java.util.Iterator; import java.util.List; import java.util.Map; import java.io.ByteArrayInputStream; import org.jdom2.Document; import org.jdom2.Element; import org.jdom2.JDOMException; import org.jdom2.input.SAXBuilder; import com.tenpay.configure.WxPayConfig; /** * * */ public class XMLUtil { /** * ����xml,���ص�һ��Ԫ�ؼ�ֵ�ԡ�����һ��Ԫ�����ӽڵ㣬��˽ڵ��ֵ���ӽڵ��xml��ݡ� * @param strxml * @return * @throws JDOMException * @throws IOException */ public static Map doXMLParse(String strxml) throws JDOMException, IOException { strxml = strxml.replaceFirst("encoding=\".*\"", "encoding=\"UTF-8\""); if(null == strxml || "".equals(strxml)) { return null; } Map m = new HashMap(); InputStream in = new ByteArrayInputStream(strxml.getBytes(WxPayConfig.CHARTSET)); SAXBuilder builder = new SAXBuilder(); Document doc = builder.build(in); 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 = XMLUtil.getChildrenText(children); } m.put(k, v); } //�ر��� in.close(); 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(XMLUtil.getChildrenText(list)); } sb.append(value); sb.append("</" + name + ">"); } } return sb.toString(); } /** * ��ȡxml�����ַ� * @param strxml * @return * @throws IOException * @throws JDOMException */ public static String getXMLEncoding(String strxml) throws JDOMException, IOException { InputStream in = HttpClientUtil.String2Inputstream(strxml); SAXBuilder builder = new SAXBuilder(); Document doc = builder.build(in); in.close(); return (String)doc.getProperty("encoding"); } }
2.9 com.tenpay.RequestHandler
package com.tenpay; import java.io.IOException; import java.io.UnsupportedEncodingException; import java.net.URLEncoder; import java.util.Iterator; import java.util.Map; import java.util.Set; import java.util.SortedMap; import java.util.TreeMap; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import com.tenpay.configure.WxPayConfig; import com.tenpay.util.MD5Util; /** * */ public class RequestHandler { /** ���url��ַ */ private String gateUrl; /** ��Կ */ private String key; /** ����IJ��� */ private SortedMap parameters; /** debug��Ϣ */ private String debugInfo; protected HttpServletRequest request; protected HttpServletResponse response; /** * ���캯�� * @param request * @param response */ public RequestHandler(HttpServletRequest request, HttpServletResponse response) { this.request = request; this.response = response; this.gateUrl = "https://gw.tenpay.com/gateway/pay.htm"; this.key = ""; this.parameters = new TreeMap(); this.debugInfo = ""; } /** *��ʼ������ */ public void init() { //nothing to do } /** *��ȡ��ڵ�ַ,�������ֵ */ public String getGateUrl() { return gateUrl; } /** *������ڵ�ַ,�������ֵ */ public void setGateUrl(String gateUrl) { this.gateUrl = gateUrl; } /** *��ȡ��Կ */ public String getKey() { return key; } /** *������Կ */ public void setKey(String key) { this.key = key; } /** * ��ȡ����ֵ * @param parameter ������� * @return String */ public String getParameter(String parameter) { String s = (String)this.parameters.get(parameter); return (null == s) ? "" : s; } /** * ���ò���ֵ * @param parameter ������� * @param parameterValue ����ֵ */ public void setParameter(String parameter, String parameterValue) { String v = ""; if(null != parameterValue) { v = parameterValue.trim(); } this.parameters.put(parameter, v); } /** * �������еIJ��� * @return SortedMap */ public SortedMap getAllParameters() { return this.parameters; } /** *��ȡdebug��Ϣ */ public String getDebugInfo() { return debugInfo; } /** * ��ȡ����������URL * @return String * @throws UnsupportedEncodingException */ public String getRequestURL() throws UnsupportedEncodingException { this.createSign(); StringBuffer sb = new StringBuffer(); Set es = this.parameters.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(!"spbill_create_ip".equals(k)) { sb.append(k + "=" + URLEncoder.encode(v, WxPayConfig.CHARTSET) + "&"); } else { sb.append(k + "=" + v.replace("\\.", "%2E") + "&"); } } //ȥ�����һ��& String reqPars = sb.substring(0, sb.lastIndexOf("&")); return this.getGateUrl() + "?" + reqPars; } public void doSend() throws UnsupportedEncodingException, IOException { this.response.sendRedirect(this.getRequestURL()); } /** * ����md5ժҪ,������:���������a-z����,������ֵ�IJ���μ�ǩ�� */ protected void createSign() { StringBuffer sb = new StringBuffer(); Set es = this.parameters.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=" + WxPayConfig.KEY); String sign = MD5Util.MD5Encode(sb.toString(), WxPayConfig.CHARTSET).toUpperCase(); this.setParameter("sign", sign); //debug��Ϣ this.setDebugInfo(sb.toString() + " => sign:" + sign); } /** *����debug��Ϣ */ protected void setDebugInfo(String debugInfo) { this.debugInfo = debugInfo; } protected HttpServletRequest getHttpServletRequest() { return this.request; } protected HttpServletResponse getHttpServletResponse() { return this.response; } /** * 自定义函数,官方没有 * @param return_code * @param return_msg * @return */ public static String setXML(String return_code, String return_msg) { return "<xml><return_code><![CDATA[" + return_code + "]]></return_code><return_msg><![CDATA[" + return_msg + "]]></return_msg></xml>"; } /** * 自定义函数,在官方文档中没有 * @return * @throws UnsupportedEncodingException */ public String getRequestXml() throws UnsupportedEncodingException { this.createSign(); StringBuffer sb = new StringBuffer(); sb.append("<xml>"); Set es = this.parameters.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 ("attach".equalsIgnoreCase(k) || "body".equalsIgnoreCase(k) || "sign".equalsIgnoreCase(k)) { sb.append("<" + k + ">" + "<![CDATA[" + v + "]]></" + k + ">"); } else { sb.append("<" + k + ">" + v + "</" + k + ">"); } } sb.append("</xml>"); return sb.toString(); } }
三、jsp页面代码
3.1 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> <% String appId = (String)request.getAttribute("appId"); String timeStamp = (String)request.getAttribute("timeStamp"); String nonceStr = (String)request.getAttribute("nonceStr"); String _package = (String)request.getAttribute("package"); String signType = (String)request.getAttribute("signType"); String paySign = (String)request.getAttribute("paySign"); %> <script type="text/javascript"> function callpay() { if (typeof WeixinJSBridge == "undefined") { if (document.addEventListener) { document.addEventListener('WeixinJSBridgeReady', onBridgeReady, false); } else if (document.attachEvent) { document.attachEvent('WeixinJSBridgeReady', onBridgeReady); document.attachEvent('onWeixinJSBridgeReady', onBridgeReady); } } else { onBridgeReady(); } } function onBridgeReady() { alert("appId=<%=appId %>,timeStamp=<%=timeStamp %>,nonceStr=<%=nonceStr %>,package=<%=_package %>,signType=<%=signType %>,paySign=<%=paySign %>"); WeixinJSBridge.invoke('getBrandWCPayRequest', { "appId" : "<%=appId %>", "timeStamp" : "<%=timeStamp %>", "nonceStr" : "<%=nonceStr %>", "package" : "<%=_package %>", "signType" : "<%=signType %>", "paySign" : "<%=paySign %>" }, function(res) { // 使用以上方式判断前端返回,微信团队郑重提示:res.err_msg将在用户支付成功后返回 ok,但并不保证它绝对可靠。 //alert(res.err_msg); if (res.err_msg == "get_brand_wcpay_request:ok") { alert("支付成功"); } if (res.err_msg == "get_brand_wcpay_request:cancel") { alert("交易取消"); } if (res.err_msg == "get_brand_wcpay_request:fail") { alert("支付失败"); } }); } </script> </head> <body> <div style="text-align: center;margin-top: 50px;"><h1><button type="button" style="display:inline-block;width:600px;height:200px;border-radius:30px;font-size:50px" onclick="callpay()">确认支付</button></h1></div> </body> </html>
3.2 notify.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>恭喜你,支付成功</title> </head> <body> <div style="text-align:center;"> <h1>...恭喜你,支付成功...</h1> <h3><a href="http://www.appbi.com/wechat/">跳回首页</a></h3> </div> </body> </html>
好了,至此代码分享完毕,把上述代码复制到工程项目中,只要配置WxPayConfig 这个类的参数即可实现支付功能。
效果如下:
点击pay.jsp页面中的支付按钮弹出支付窗口
此文章本站原创,地址 https://www.vxzsk.com/394.html
转载请注明出处!谢谢!
感觉本站内容不错,读后有收获?小额赞助,鼓励网站分享出更好的教程
上一篇:创建Android项目
下一篇:sql语句教程(0):前言
^