happybird00 2018-11-26
由于目前电商的用户使用微信访问的居多,所以要在商城集成微信支付,官网Demo仅为工具类及流程,并没有向支付宝那样拿来即用的示例代码,故在这里记录下踩过的坑
1、确保你的微信公众账号已经认证,认证费每年¥300
2、确保已开通微信支付,且已开通微信支付的相应产品,如:扫码支付、H5支付等
3、登录微信支付后台,产品中心>>开发配置>>支付配置,设置相应支付产品的业务域名;获取到后台的下列值
private final String appId = ""; private final String appSecret = ""; private final String mch_id = ""; private final String key = "";//32位apiKey
4、开始踩坑:公众号支付
4.1:支付页面请求后台获取微信支付初始配置参数
var wxPayConfig; function getWxPayConfig(cb){ $.ajax({ type: "GET", url: "/xxx/order/wxPayConfig", data:{ url : encodeURIComponent(window.location.href) }, dataType:"json", beforeSend: function () { $("#xxx").attr({ "disabled": "disabled" });//获取到配置之前,禁止点击付款按钮 }, success: function (data) { wxPayConfig = data; $("#xxx").removeAttr("disabled");//获取到配置,打开付款按钮 wx.config({ debug: true, // 开启调试模式,成功失败都会有alert框 appId: data.appId, // 必填,公众号的唯一标识 timestamp: data.timeStamp, // 必填,生成签名的时间戳 nonceStr: data.nonceStr, // 必填,生成签名的随机串 signature: data.signatureShaHex,// 必填,签名 jsApiList: ['chooseWXPay'] // 必填,需要使用的JS接口列表 }); wx.ready(function () { // config信息验证后会执行ready方法,所有接口调用都必须在config接口获得结果之后,config是一个客户端的异步操作,所以如果需要在页面加载时就调用相关接口,则须把相关接口放在ready函数中调用来确保正确执行。对于用户触发时才调用的接口,则可以直接调用,不需要放在ready函数中。 cb(); }); wx.error(function (res) { // config信息验证失败会执行error函数,如签名过期导致验证失败,具体错误信息可以打开config的debug模式查看,也可以在返回的res参数中查看,对于SPA可以在这里更新签名。 //alert(res); }); } }); }
先配置参数类:BlsWXPayConfig
public class BlsWXPayConfig extends WXPayConfig { private final String appId = ""; private final String appSecret = ""; private final String mch_id = ""; private final String key = "";//32位apiKey private final String wxPayNotify = "http://www.xxx.com/xxx/wxPayNotify.jsp";//注意不能带参数 public String getNotifyUrl(){ return this.wxPayNotify; } /* (non-Javadoc) * @see com.wxpay.sdk.WXPayConfig#getAppID() */ @Override public String getAppID() { return appId; } /* (non-Javadoc) * @see com.wxpay.sdk.WXPayConfig#getMchID() */ @Override public String getMchID() { return mch_id; } /* (non-Javadoc) * @see com.wxpay.sdk.WXPayConfig#getKey() */ @Override public String getKey() { return key; } public String getAppSecret() { return appSecret; } /* (non-Javadoc) * @see com.wxpay.sdk.WXPayConfig#getCertStream() */ @Override InputStream getCertStream() { return null; } /* (non-Javadoc) * @see com.wxpay.sdk.WXPayConfig#getWXPayDomain() */ @Override IWXPayDomain getWXPayDomain() { return new IWXPayDomain(){ @Override public void report(String domain, long elapsedTimeMillis, Exception ex) { // TODO Auto-generated method stub } @Override public DomainInfo getDomain(WXPayConfig config) { return new DomainInfo("www.xxx.com", true); } }; }
票据工具类:JsapiTicketUtil
public class JsapiTicketUtil { public static final Log LOG = LogFactory.getLog(JsapiTicketUtil.class); public static String getJsapiTicket(BlsWXPayConfig wxConfig) { String requestUrl = "https://api.weixin.qq.com/cgi-bin/token?"; String params = "grant_type=client_credential&appid=" + wxConfig.getAppID() + "&secret=" + wxConfig.getAppSecret() + ""; String result = httpGet(requestUrl + params); String access_token = JsonUtils.fromJson(result, WxAuthPros.class).getAccess_token(); requestUrl = "https://api.weixin.qq.com/cgi-bin/ticket/getticket?"; params = "access_token=" + access_token + "&type=jsapi"; result = httpGet(requestUrl + params); String jsapi_ticket = JsonUtils.fromJson(result, WxAuthPros.class).getTicket(); return jsapi_ticket; } /** * post请求 * @param url * @return */ public static String httpPost(String url) { //post请求返回结果 DefaultHttpClient httpClient = new DefaultHttpClient(); HttpPost method = new HttpPost(url); String str = ""; try { HttpResponse result = httpClient.execute(method); url = URLDecoder.decode(url, "UTF-8"); /**请求发送成功,并得到响应**/ if (result.getStatusLine().getStatusCode() == 200) { try { /**读取服务器返回过来的json字符串数据**/ str = EntityUtils.toString(result.getEntity()); } catch (Exception e) { LOG.error("post请求提交失败:" + url, e); } } } catch (IOException e) { LOG.error("post请求提交失败:" + url, e); } return str; } /** * get 请求、 * @param url * @return */ public static String httpGet(String url) { //get请求返回结果 String strResult = null; try { DefaultHttpClient client = new DefaultHttpClient(); //发送get请求 HttpGet request = new HttpGet(url); HttpResponse response = client.execute(request); /**请求发送成功,并得到响应**/ if (response.getStatusLine().getStatusCode() == org.apache.http.HttpStatus.SC_OK) { /**读取服务器返回过来的json字符串数据**/ strResult = EntityUtils.toString(response.getEntity()); } else { LOG.error("get请求提交失败:" + url); } } catch (IOException e) { LOG.error("get请求提交失败:" + url, e); } return strResult; }
对应后台代码:
/** * 获取微信初始化配置 * @param mapping * @param form * @param request * @param response * @return */ public ActionForward wxPayConfig(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response){ long timeStamp = WXPayUtil.getCurrentTimestamp(); String nonceStr = WXPayUtil.generateNonceStr(); Map<String, String> data = new TreeMap<String, String>(); BlsWXPayConfig wxConfig = new BlsWXPayConfig(); try { String url = URLDecoder.decode(request.getParameter("url").split("#")[0], "UTF-8"); String jsapi_ticket = JsapiTicketUtil.getJsapiTicket(wxConfig); data.put("jsapi_ticket", jsapi_ticket); data.put("noncestr", nonceStr); data.put("timestamp", String.valueOf(timeStamp)); data.put("url", url); String string1 = "jsapi_ticket=" + jsapi_ticket + "&noncestr=" + nonceStr + "×tamp=" + timeStamp + "&url=" + url; MessageDigest crypt = MessageDigest.getInstance("SHA-1"); crypt.reset(); crypt.update(string1.getBytes("UTF-8")); String signatureMd5 = WXPayUtil.generateSignature(data, wxConfig.getKey()); String signatureShaHex = DigestUtils.shaHex(string1);; JSONObject jsonData = new JSONObject(); jsonData.put("jsapi_ticket", jsapi_ticket); jsonData.put("url", url); jsonData.put("appId", wxConfig.getAppID()); jsonData.put("timeStamp", timeStamp); jsonData.put("nonceStr" , nonceStr); jsonData.put("signatureMd5", signatureMd5); jsonData.put("signatureShaHex", signatureShaHex); super.responseWrite(response, jsonData); } catch (Exception e) { e.printStackTrace(); } return null; }
4.2 点击按钮唤起微信支付,调用前需要先获得Code
function getQueryString(name){ var reg = new RegExp("(^|&)"+ name +"=([^&]*)(&|$)"); var r = window.location.search.substr(1).match(reg); if(r!=null)return unescape(r[2]); return null; } var code = getQueryString("code"); if(code != "" && code != "null"){//授权后直接唤起支付 startWxPay(); } function startWxPay() { if(!wxPayConfig){ return getWxPayConfig(startWxPay) } var code = getQueryString("code"); if(code == "" || code == "null"){ var url = window.location.href; return window.location.href = "https://open.weixin.qq.com/connect/oauth2/authorize?appid=" + wxPayConfig.appId + "&redirect_uri=" + encodeURIComponent(url) "&response_type=code" + "&scope=snsapi_base" + "&state=123" + "#wechat_redirect"; } $.ajax({ type: "POST", url: "/xxx/order/getWxPaySign", data: { "code": code, "orderId" : $("#ordId").val(), "orderNumber" : $("#orderNumber").val(), "total_fee" : $("#ototalPrice").val() }, dataType:"json", beforeSend: function () { $("#xxx").attr({ "disabled": "disabled" }); }, success: function (res) { $("#xxx").removeAttr("disabled"); if (res.openid != null && res.openid != undefined && res.openid != "") { window.localStorage.setItem("openid", res.openid); } wx.chooseWXPay({ timestamp: res.timeStamp, // 支付签名时间戳 nonceStr: res.nonceStr, // 支付签名随机串,不长于32 位 "package": res["package"], // 统一支付接口返回的prepay_id参数值,提交格式如:prepay_id=***) signType: res.signType, // 签名方式,默认为'SHA1',使用新版支付需传入'MD5' paySign: res.paysign, // 支付签名 success: function (res) { //支付成功 window.location.href = "/xxx/order/detail?id=" + $("#ordId").val(); }, cancel: function (res) { //支付取消 } }); } }); var isPageHide = false; window.addEventListener('pageshow', function() { if(isPageHide) { window.location.reload();//自己重新刷新,这一步相当于模拟了跳转 } }); window.addEventListener('pagehide', function() { isPageHide = true; }); }
对应后台代码:
public String getIp(HttpServletRequest request) { String ip = request.getHeader("x-forwarded-for"); if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) { ip = request.getHeader("Proxy-Client-IP"); } if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) { ip = request.getHeader("WL-Proxy-Client-IP"); } if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) { ip = request.getRemoteAddr(); } return ip; } /** * @param mapping * @param form * @param request * @param response * @return */ public ActionForward getWxPaySign(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response){ String code = request.getParameter("code") ; BlsWXPayConfig wxPayConfig = new BlsWXPayConfig(); String key = wxPayConfig.getKey();//32位apiKey String nonceStr = WXPayUtil.generateNonceStr(); String notify_url = wxPayConfig.getNotifyUrl();//支付结果回调地址,不能带参数(PayNotifyUrl回调里能接到订单号out_trade_no参数) String out_trade_no = request.getParameter("orderNumber");//订单号 String spbill_create_ip = getIp(request);//用户端IP String trade_type = "JSAPI";//JSAPI,NATIVE,APP,WAP //#region 获取用户微信OpenId String openidExt = null; try { Map<String, String> reqData = new TreeMap<String, String>(); openidExt = PayCommonUtil.getOpenId(code, wxPayConfig); //#region 调用统一支付接口获得prepay_id(预支付交易会话标识) reqData.put("appid", wxPayConfig.getAppID()); reqData.put("mch_id", wxPayConfig.getMchID()); reqData.put("nonce_str", nonceStr); reqData.put("body", out_trade_no);// + " 购货金额"); reqData.put("out_trade_no", out_trade_no); String total_fee = request.getParameter("total_fee"); int total_fee_int = new BigDecimal(Double.parseDouble(total_fee) * 100).setScale(2, RoundingMode.HALF_UP).intValue();// reqData.put("total_fee", String.valueOf(total_fee_int));//单位为分 reqData.put("spbill_create_ip", spbill_create_ip); reqData.put("notify_url", notify_url); reqData.put("trade_type", trade_type); String attach = request.getParameter("orderId");//附加数据:订单id reqData.put("attach", attach); reqData.put("openid", openidExt); String sign = WXPayUtil.generateSignature(reqData, key); reqData.put("sign", sign); WxAuthPros wxAuth = PayCommonUtil.unifiedorder(PayCommonUtil.getxml(reqData)); String prepay_id = wxAuth.getPrepay_id(); //#endregion long timestamp = WXPayUtil.getCurrentTimestamp(); Map<String, String> paySignMap = new TreeMap<String, String>(); paySignMap.put("appId", wxPayConfig.getAppID()); paySignMap.put("nonceStr", nonceStr); paySignMap.put("package", "prepay_id=" + prepay_id); paySignMap.put("signType", "MD5"); paySignMap.put("timeStamp", String.valueOf(timestamp)); String paySign = WXPayUtil.generateSignature(paySignMap, key); JSONObject resData = new JSONObject(); resData.put("openid", openidExt); resData.put("appId", wxPayConfig.getAppID()); resData.put("timeStamp", WXPayUtil.getCurrentTimestamp()); resData.put("nonceStr", nonceStr); resData.put("package", "prepay_id=" + prepay_id); resData.put("signType", "MD5"); resData.put("sign", sign); resData.put("paysign", paySign); resData.put("openid", openidExt); resData.put("result_code", wxAuth.getResult_code()); resData.put("return_msg", wxAuth.getReturn_msg()); //#endregion super.responseWrite(response, resData.toString()); } catch (Exception e) { LOG.error("获取微信支付签名异常", e); } return null; }
工具类:PayCommonUtil
public class PayCommonUtil { private static String OPENIDURL = "https://api.weixin.qq.com/sns/oauth2/access_token?"; // 获取微信openid的链接 private static String UNURL = "https://api.mch.weixin.qq.com/pay/unifiedorder"; // 微信统一下单链接 /** * ** 接收微信的异步通知 * * @throws IOException */ public static String reciverWx(HttpServletRequest request) throws IOException { InputStream inputStream; StringBuffer sb = new StringBuffer(); inputStream = request.getInputStream(); String s; BufferedReader in = new BufferedReader(new InputStreamReader( inputStream, "UTF-8")); while ((s = in.readLine()) != null) { sb.append(s); } in.close(); inputStream.close(); return sb.toString(); } /** * 获取openId * @param code * @param config * @return */ public static String getOpenId(String code, BlsWXPayConfig config) { String openIdUrl = OPENIDURL + "appid=" + config.getAppID() + "&secret=" + config.getAppSecret() + "&code=" + code + "&grant_type=authorization_code"; try { HttpRequest request = HttpRequest.post(openIdUrl).contentType( "application/json;charset=utf-8"); String res = request.body(); if (res != null) { WxAuthPros wxAuth = JsonUtils.fromJson(res, WxAuthPros.class); return wxAuth.getOpenid(); } return null; } catch (Exception e) { return null; } } //组装统一下订单参数并进行签名 public static String getxml(Map<String, String> reqData){ StringBuilder returnXml = new StringBuilder(); try { returnXml.append("<xml>"); returnXml.append("<appid>").append(reqData.get("appid")).append("</appid>"); returnXml.append("<mch_id>").append( reqData.get("mch_id")).append("</mch_id>"); returnXml.append("<nonce_str>").append(reqData.get("nonce_str")).append("</nonce_str>"); returnXml.append("<body>").append(reqData.get("body")).append("</body>"); returnXml.append("<out_trade_no>").append(reqData.get("out_trade_no")).append("</out_trade_no>"); returnXml.append("<total_fee>").append(reqData.get("total_fee")).append("</total_fee>"); returnXml.append("<spbill_create_ip>").append(reqData.get("spbill_create_ip")).append("</spbill_create_ip>"); returnXml.append("<notify_url>").append(reqData.get("notify_url")).append("</notify_url>"); returnXml.append("<trade_type>").append(reqData.get("trade_type")).append("</trade_type>" ); if(reqData.containsKey("product_id")){ returnXml.append("<product_id>").append(reqData.get("product_id")).append("</product_id>" ); } returnXml.append("<attach>").append(reqData.get("attach")).append("</attach>"); if(reqData.containsKey("openid")){ returnXml.append("<openid>").append(reqData.get("openid")).append("</openid>"); } returnXml.append("<sign>").append(reqData.get("sign")).append("</sign>"); returnXml.append("</xml>"); } catch (Exception e) { } return returnXml.toString(); } // 调用微信统一下单接口 public static WxAuthPros unifiedorder(String xml){ String returnxml=null; WxAuthPros wxAuth = new WxAuthPros(); try { HttpRequest request = HttpRequest.post(UNURL).contentType( "application/json;charset=utf-8").send(xml); returnxml = request.body(); // System.out.println("-------------------------------------------"); // System.out.println(xml); // System.out.println("++++++++++++++++++++++++++++++++++++++++++++"); // System.out.println(returnxml); // System.out.println("-------------------------------------------"); Document doc = DocumentHelper.parseText(returnxml); Element rootElt = doc.getRootElement(); // 获取根节点 wxAuth.setPrepay_id(rootElt.elementText("prepay_id")); wxAuth.setResult_code(rootElt.elementText("result_code")); wxAuth.setErr_code(rootElt.elementText("err_code")); wxAuth.setErr_code(rootElt.elementText("err_code")); wxAuth.setErr_code_des(rootElt.elementText("err_code_des")); wxAuth.setReturn_msg(rootElt.elementText("return_msg")); wxAuth.setCode_url(rootElt.elementText("code_url")); wxAuth.setMweb_url(rootElt.elementText("mweb_url")); } catch (Exception e) { } return wxAuth; } /** 获取二维码url * @param ip * @param vcWeixinPay * @return * @throws Exception */ private static WxAuthPros weixin_pay(String ip, String attach, String out_trade_no, Double totalPrice, BlsWXPayConfig wxPayConfig, String trade_type) throws Exception { String key = wxPayConfig.getKey(); // key String nonce_str = WXPayUtil.generateNonceStr(); // 获取发起电脑 ip String spbill_create_ip = ip; Map<String, String> reqData = new TreeMap<String, String>(); //#endregion //#region 调用统一支付接口获得prepay_id(预支付交易会话标识) reqData.put("appid", wxPayConfig.getAppID()); reqData.put("mch_id", wxPayConfig.getMchID()); reqData.put("nonce_str", nonce_str); reqData.put("body", out_trade_no);// + " 购货金额"); reqData.put("out_trade_no", out_trade_no); int total_fee_int = new BigDecimal(totalPrice * 100).setScale(2, RoundingMode.HALF_UP).intValue();// reqData.put("total_fee", String.valueOf(total_fee_int));//单位为分 reqData.put("spbill_create_ip", spbill_create_ip); reqData.put("notify_url", wxPayConfig.getNotifyUrl()); reqData.put("trade_type", trade_type); reqData.put("product_id", attach);//trade_type = NATIVE 时,必填 reqData.put("attach", attach); String sign = WXPayUtil.generateSignature(reqData, key); reqData.put("sign", sign); WxAuthPros wxAuth = PayCommonUtil.unifiedorder(PayCommonUtil.getxml(reqData)); return wxAuth; } /** 网页二维码扫码支付 * @param ip * @param attach * @param out_trade_no * @param totalPrice * @param wxPayConfig * @return * @throws Exception */ public static WxAuthPros weixin_payByQrcode(String ip, String attach, String out_trade_no, Double totalPrice, BlsWXPayConfig wxPayConfig) throws Exception { return weixin_pay(ip, attach, out_trade_no, totalPrice, wxPayConfig, "NATIVE"); } /** 网页二维码扫码支付 * @param ip * @param attach * @param out_trade_no * @param totalPrice * @param wxPayConfig * @return * @throws Exception */ public static WxAuthPros weixin_payByH5(String ip, String attach, String out_trade_no, Double totalPrice, BlsWXPayConfig wxPayConfig) throws Exception { return weixin_pay(ip, attach, out_trade_no, totalPrice, wxPayConfig, "MWEB"); }
5、扫码支付:用户点击按钮提交参数到后台,后台调用微信支付生成二维码链接内容,前台显示二维码,用户扫码支付,前台轮训后台是否支付成功。
后台代码:
/** * 订单列表点击 微信支付 * @param mapping * @param form * @param request * @param response * @return */ public ActionForward wxpay(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response){ String ip = super.getIp(request); BlsWXPayConfig wxPayConfig = new BlsWXPayConfig(); WxAuthPros wxAuthPros; try { wxAuthPros = PayCommonUtil.weixin_payByQrcode( ip == null ? "" : ip.toString(), request.getParameter("orderId"), request.getParameter("orderNumber"), Double.parseDouble(request.getParameter("tenantOrderFee")), wxPayConfig); request.setAttribute("wxAuthPros", wxAuthPros); request.setAttribute("orderId", request.getParameter("ordId")); request.getRequestDispatcher("order/weixinPay.jsp").forward( request, response); } catch (Exception e) { LOG.error("调用微信支付 异常", e);; } return null; }jsp 代码,显示二维码
<% com.wxpay.sdk.WxAuthPros wxAuthPros = (com.wxpay.sdk.WxAuthPros)request.getAttribute("wxAuthPros"); %> <div style="padding: 30px;text-align: center;"> <div id="qrcode" urlText="<%=wxAuthPros.getCode_url() %>" orderId="<%=request.getAttribute("orderId") %>" errorMsg="<%=wxAuthPros.getReturn_msg() %>"> </div> <div style="line-height: 30px;font-size: 16px;"> 请使用微信扫码,完成支付。 </div> </div>Js代码, 显示二维码使用jquery.qrcode方式
$(function(){ var urlText = $('#qrcode').attr("urlText"); $('#qrcode').qrcode({ render: "canvas", //也可以替换为table width: 200, height: 200, text: urlText }); if(urlText != "null"){ setInterval(function(){ $.ajax({ url : "/xxx/vlidateWxPay", data : { orderId : $('#qrcode').attr("orderId") }, success: function(res){ if(res == "true"){ alert("恭喜,支付成功!点击确定跳转至“我的订单”页面"); //支付成功 跳转到我的订单页面 window.location.href = "/xxx/order.html"; } } }); }, 1000); } });6、H5支付,用户点击按钮触发支付,请求后台得到微信统一下单H5支付链接,前台跳转到微信支付链接,支付成功,微信请求回调页面(如果为app端唤起微信支付,返回后需轮询后台验证是否支付成功)
JS代码:
/** * 微信外浏览器唤起微信支付 * */ function startWxH5Pay(){ $.ajax({ type: "POST", url: "/xxx/order/getWxH5Url", data: { "orderId" : $("#ordId").val(), "orderNumber" : $("#orderNumber").val(), "total_fee" : $("#ototalPrice").val() }, dataType:"json", beforeSend: function () { $("#xxx").attr({ "disabled": "disabled" }); }, success: function (res) { if(res && res.mweb_url){ //弹出提示框 mui("#payModal").popover("show", this); $("#payCancel").on("click", function(){ mui("#payModal").popover("hide", this); }); $("#payComplate").on("click", function(){ mui("#payModal").popover("hide", this); setInterval(function(){ $.ajax({ url : "/xxx/order/vlidateWxPay", data : { orderId : $("#ordId").val() }, success: function(res){ if(res == "true"){ alert("恭喜,支付成功!点击确定跳转至“我的订单”页面"); //支付成功 跳转到我的订单页面 window.location.href = "/xxx/order.html"; } } }); }, 1000); }); window.location.href = res.mweb_url; } } }); }对应后台代码:
/** * 手机端:微信外浏览器h5支付 * @param mapping * @param form * @param request * @param response * @return */ public ActionForward getWxH5Url(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response){ String ip = super.getIp(request); BlsWXPayConfig wxPayConfig = new BlsWXPayConfig(); WxAuthPros wxAuthPros; try { wxAuthPros = PayCommonUtil.weixin_payByH5( ip == null ? "" : ip.toString(), request.getParameter("orderId"), request.getParameter("orderNumber"), Double.parseDouble(request.getParameter("total_fee")), wxPayConfig); super.responseWrite(response, new JSONObject(wxAuthPros)); } catch (Exception e) { LOG.error("调用微信支付 异常", e);; } return null; }
以上为微信支付的几种代码调用方式,回调代码如下(由于回调不能写参数,所有暂时使用的jsp代码)
<!-- 该引入的要引入 --> <%@page import="java.io.PrintWriter"%> <%@page import="org.springframework.web.context.WebApplicationContext" %> <%@page import="org.springframework.web.context.support.WebApplicationContextUtils" %> <%@page import="com.xxx.moder.BlsWxPayInfo" %> <%@page import="com.wxpay.sdk.WXPayUtil" %> <%@page import="com.wxpay.sdk.PayCommonUtil" %> <%@page import="java.util.Map" %> <%@page import="java.util.List" %> <%@page import="java.util.HashMap" %> <%@page import="java.util.TreeMap" %> <%@page import="java.util.SortedMap" %> <%@page import="java.util.Iterator" %> <%@page import="java.io.BufferedOutputStream" %> <%@page import="org.dom4j.DocumentHelper" %> <%@page import="org.dom4j.Document" %> <%@page import="org.dom4j.Element" %> <% WebApplicationContext ctx = WebApplicationContextUtils.getWebApplicationContext(this.getServletContext()); com.xxx.service.OrderService orderService = (com.xxx.service.OrderService) ctx.getBean("OrderService"); //orderService. String result = PayCommonUtil.reciverWx(request); // 接收到异步的参数 Map<String, String> m = new TreeMap<String, String>();// 解析xml成map if (result != null && !"".equals(result)) { try { Document doc = DocumentHelper.parseText(result); Element rootElt = doc.getRootElement(); // 获取根节点 List<Element> child = rootElt.elements(); for(Element e : child){ m.put(e.getName(), e.getText()); } } catch (Exception e) { e.printStackTrace(); } } // 判断签名是否正确 String resXml = ""; if(WXPayUtil.isSignatureValid(m, "Blissunnnnnnnnnnnnnnnnnnnnnnnnnn")){ if ("SUCCESS".equals((String) m.get("result_code"))) { // 如果返回成功 String mch_id = (String) m.get("mch_id"); // 商户号 String out_trade_no = (String) m.get("out_trade_no"); // 商户订单号 String total_fee = (String) m.get("total_fee"); String transaction_id = (String) m.get("transaction_id"); // 微信支付订单号 String attach = (String) m.get("attach"); // 微信支付订单号 BlsWxPayInfo blsWxPayInfo = new BlsWxPayInfo(); blsWxPayInfo.setMch_id(mch_id); blsWxPayInfo.setOut_trade_no(out_trade_no); blsWxPayInfo.setTotal_fee(Double.parseDouble(total_fee)); blsWxPayInfo.setTransaction_id(transaction_id); blsWxPayInfo.setDevice_info((String)m.get("device_info")); blsWxPayInfo.setNonce_str((String)m.get("nonce_str")); blsWxPayInfo.setSign((String)m.get("sign")); blsWxPayInfo.setResult_code((String)m.get("result_code")); blsWxPayInfo.setTrade_type((String)m.get("trade_type")); blsWxPayInfo.setAttach((String)m.get("attach")); orderService.saveBlsWxPayInfo(blsWxPayInfo); resXml = "<xml>" + "<return_code><![CDATA[SUCCESS]]></return_code>" + "<return_msg><![CDATA[OK]]></return_msg>" + "</xml> "; } else {// 如果微信返回支付失败,将错误信息返回给微信 resXml = "<xml>" + "<return_code><![CDATA[FAIL]]></return_code>" + "<return_msg><![CDATA[交易失败]]></return_msg>" + "</xml> "; } } else { resXml = "<xml>" + "<return_code><![CDATA[FAIL]]></return_code>" + "<return_msg><![CDATA[通知签名验证失败]]></return_msg>" + "</xml> "; } // 处理业务完毕,将业务结果通知给微信 // ------------------------------ try{ BufferedOutputStream outStream = new BufferedOutputStream(response.getOutputStream()); outStream.write(resXml.getBytes()); outStream.flush(); outStream.close(); }catch(Exception e){ } %>
至此已完成微信支付的几种代码的编写,开始的时候老是提示签名错误,微信签名一定要注意参数的名称及顺序(为了保证顺序请使用TreeMap),还有公众号支付时需要二次签名,签名的 参数值不能为空,trade_type=NATIVE时product_id必填,trade_type=JSAPI时openid必填。