`

踩坑微信支付

阅读更多

由于目前电商的用户使用微信访问的居多,所以要在商城集成微信支付,官网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 +
	                "&timestamp=" + 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必填。

 

 

 

分享到:
评论

相关推荐

    android微信支付踩坑

    以下是对"android微信支付踩坑"这一主题的详细阐述,以及解决这些问题的步骤。 1. **SDK集成**: 微信支付SDK的集成是整个流程的第一步。首先,你需要从微信开放平台下载最新的SDK,将其解压到项目的libs目录下,...

    微信支付完整demo

    微信支付完整Demo是一个包含了从头至尾实现微信支付功能的所有必要代码和配置的示例项目。这个Demo旨在帮助开发者在自己的应用中集成微信支付服务,避免在开发过程中遇到的种种困难。下面,我们将深入探讨微信支付的...

    app微信支付php服务端(修改了官方文档的坑,应该能直接用)

    微信支付是腾讯公司推出的一种在线支付方式,广泛应用于移动互联网应用和电商网站。在PHP环境中实现微信支付服务端,开发者需要遵循微信支付的API规范,处理支付请求与响应,确保交易的安全性和可靠性。本文件“app...

    微信V3 更新 服务端代码,亲测可用,解决很多微信支付问题

    通过这个WeiXinPayV3服务端的压缩包,开发者可以快速了解并实现微信支付V3的全部功能,避免因踩坑而浪费时间。只需按照文档说明和示例代码进行调整,就可以将微信支付集成到自己的业务系统中,提供稳定、安全的支付...

    微信支付demo

    微信支付是中国最流行的移动支付方式之一,广泛...通过理解并实践这个"微信支付demo",开发者可以快速掌握微信支付的集成方法,避免踩坑,提高开发效率。对于初次接触微信支付的开发者来说,这是一个非常宝贵的资源。

    ThinkPHP框架下微信支付功能总结踩坑笔记

    在使用ThinkPHP框架开发微信支付功能时,开发者常常会遇到各种问题和挑战,本文档对这些常见的问题及解决方案进行了详细总结,以供同行参考。 首先,验证不严谨是开发微信支付时的一个重要问题。在文中作者提到因为...

    thinphp微信支付.rar

    ThinkPHP5.1调用微信扫码支付SDK,介绍一下,避免踩坑

    wechat_guapibot:公众号自动回复(聊天机器人)+看图说话+微信支付+ H5商城。基于FLASK + VUE + MINTUI

    微信公众号瓜皮机器人源码公开这是一个个人练习手项目,主要完成了以下的功能:(公众号服务暂时关闭) 1个公众号自动回复(图灵) 2看图说话(这里使用的是腾讯AILAB的看图说话接口) 3微信支付(python写的接受,...

    java微信小程序支付

    java开发微信小程序的支付代码,避免开发小程序踩坑。

    微信小程序支付功能开发与踩坑经验总结

    在半年前我有另一个小程序项目,虽然当时没有开通小程序微信支付的需求,但是我留意过应用号(小程序号)后台微信支付的相关选项。当时,这个小程序因为绑定过已认证的服务号,因此小程序支付是可以直接申请的,无需...

    vue中使用微信公众号js-sdk踩坑记录

    通过使用微信JS-SDK,网页开发者可借助微信高效地使用拍照、选图、语音、位置等手机系统的能力,同时可以直接使用微信分享、扫一扫、卡券、支付等微信特有的能力,为微信用户提供更优质的网页体验。 分享页面到朋友...

    Echarts在Taro微信小程序开发中的踩坑记录

    近期笔者在使用Taro进行微信小程序开发,当引入Echarts图表库时,微信检测单包超限2M的一系列优化措施的踩坑记录,期望能指导读者少走一些弯路。 为什么选择Echarts? 微信小程序目录市面上使用最多的两款图表库,...

    微信小程序踩坑录:canvas,post请求,页面刷新

    现在也不知道距离微信公测多少日子了,反正感觉我是埋在微信小程序这个坑里很久了,公司的项目终于快接近尾声,现在就腾点时间记录下我的收获,希望能给大家一点点帮助吧。 我做的几乎都是canvas的东西,所以先说说...

    小程序最新订阅消息踩坑与使用

    使用方式,只能在用户点击,或者在微信支付的回调中才可使用(目前不支持在插件中使用哦) 一次订阅,更新后的订阅,为订阅每一次的消息,意思为,每一次推送都必须触发,让用户选择是否推送,(好坑的感觉,除非用户...

    history-wechat.zip

    - 微信API兼容性:某些微信小程序独有的API,如微信支付、地理位置等,需要在uni-app中特别处理,确保其正常工作。 - 热更新失效:在开发过程中,热更新有时会失效,此时可能需要手动清理缓存或重新安装小程序。 ...

    ttpaydemo.rar

    用户在确认支付后,系统会进行支付处理,可能涉及跳转到第三方支付页面,如微信、支付宝等。支付过程中,用户的安全性和隐私保护是至关重要的,因此开发者需确保遵守相关规范。 支付完成后,字节跳动支付会通过回调...

    小程序实战踩坑之B2B商城项目总结

    如下图,原以为是微信的页面,不会影响到小程序,实际情况下是会触发返回的页面的onShow()的。   (此图片来源于网络,如有侵权,请联系删除! ) 触发bug业务场景详细描述: 因为业务需要,我会在下订单页面触发 ...

    小程序 大世界.pdf

    《小程序 大世界》这本书详细介绍了阿里巴巴文娱技术专家在开发小程序过程中积累的丰富经验和避坑指南...书中详细记录了淘票票团队在实践中遇到的问题和解决方案,对于避免重复踩坑,提升开发效率具有重要的指导意义。

Global site tag (gtag.js) - Google Analytics