微信支付JSAPI版本---史上最详细教程-----格林王子举哥

嗨,欢迎好学的小伙伴们,今天我们来一起攻克微信支付所以遇到的各种坑,欢迎大家共同留言讨论,本节将的是微信的支付功能-----JAVA版

首先,我们先要去微信官方申请【公众号】支付接口开通:https://mp.weixin.qq.com,注意,订阅号是没有开通支付接口的能力,所以注意下,一定是公众号才能行的哦,然后去讲商户号和公众号绑定:https://pay.weixin.qq.com/index.php/core/home/login?return_url=%2F,提供一系列的证书,材料之类的,提交后,需要微信官方进行审核,慢的话,大概就7个工作日,快也就半天都可能的,通过后,即可开通公众号支付接口,还有就是需要一个域名,而且这个域名是在备案过的哈,一定要是备案过的,不然不能使用哦。

其次,我们要准备下我们开发中需要的参数(这些参数在申请通过后,都能查看):appid  应用id 支付接口开通后可查看、
                                                                    openid 后期可以用微信每次的code获取、   
                                                                    mch_id 商户id也叫商户号  支付接口开通后可查看 、
                                                                    key  key为商户平台设置的密钥key    32位数  由操作密码和自定义密码32生成、
                                                                    secret  第三方用户唯一凭证密钥
然后,去看下微信支付的时序图,当然微信的官方文档写的很详细,不过有几个细节没有说到位,这里我们来看下我自己整理的下的流程图吧,感觉简单好懂些

时序思维图

说明:首先是访问微信授权连接进行授权以及获取到openid还有code,然后就是统一下单,统一下单分为两次,第一次是签名获取pepay_id,也就是预支付id,通过发送xml报文给微信连接,获取这个预支付id,然后第二次签名就是,拿到预支付id在加上第二次的报文,发送给微信,生成预支付订单,于支付订单生成好了后,返回前台,利用微信自带的接口,然后将后台返回来的签名和一系列参数去请求这个接口,将会钓起微信支付的预支付界面,然后这个接口会返回参数res.err_msg,从这个里面我们可以判断出用户是付款了还是取消了,返回get_brand_wcpay_request:ok,就是成功,不过这个可能会有延迟,所以只是用来提示用户付款成功,最后的逻辑判断我们还是得到回调界面里面写,保险点,因为有时候有网络延迟,然后基本上流程就是这样了,其他都是就是后续事情

然后,我们来上最重要的东西,也是最关心的东西代码和jar包,以及带着jar和代码来走一遍流程

第一:首先,我们到商品详情界面点击下单按钮,来到一个微信接口jsp,进行授权下图,
     序号1,是商品详情界面穿进来的参数,金额,订单id,以及订单描述,
     序号2,是上面说的开通微信支付后,会收到的几个参数,这里我们先给其封装到session里面,方便后续拿值,
     序号3,则是微信授权的链接:https://open.weixin.qq.com/connect/oauth2/authorize?appid=<%=session.getAttribute("appid")%>&redirect_uri=http://new.nbtongtai.com/weixin/wxPay/orderPayDeail.jsp&response_type=code&scope=snsapi_userinfo&state='+order_money+'#wechat_redirect,访问该链接即可授权,如授权通过,则会跳往支付详细界面,进行进一步确认  orderPayDeail.jsp  就是授权后跳往的界面

第二:来到授权后的界面orderPayDeail.jsp,然后就是获取授权后,微信返给我们的参数,

通过这个上面JS拿到微信返回的参数列表,然后则可以拿到返回的code

获取到code后,我们就可以更加code去拿到openid

前台访问:

后台根据code拿到openid,然后将openid和code存session里面,最后在返回前台,注意这里的appid还有secret都是授权那里存session里面的,所以这里可以直接拿出来用

前台将返回来的openid,存界面上,然后就可以进行统一下单了,如下图:再次去后台,将前面准备的参数,传后台,请求微信接口,生成预支付订单,第一个参数就是订单id,第二个就是金额也就是之前授权前商品界面返回来的金额,第三个就是code,每次访问coe都不一样,所以这里要从请求里面获取。
     序号1则是在上一步的js方法返回过来的请求,并且获取的参数信息
     序号2则是获取到金额,还有订单金额,已经code后,我们就可以生成预支付订单了,也就是说统一下单流程,通过post方法将金额,openid,订单id去请求后台,进行预支付统一下单

来到后台统一下单后台,先获取金额,openid,订单id,然后进行两次签名,第一次通过封装restata集合,然后请求微信预支付连接,得到预支付id,第二次在将获取的预支付id封装,再次请求微信生成微信预支付订单

 //得到前台传过来的金额,消费者id
	String order_money=JspUtilCode.unescape(JspUtil.changeNull(request.getParameter("order_money")));  //应收金额
	String openId=JspUtilCode.unescape(JspUtil.changeNull(request.getParameter("openId")));  //openId  //openId="owFJm07ds2P0MAKoezy3qF9EfN2k";
	String gm_id=JspUtilCode.unescape(JspUtil.changeNull(request.getParameter("gm_id")));  //商品id
	//得到商户的支付金额,单位为分,这里换算为元
	Double _money=Double.parseDouble(order_money)*100;
	int money=_money.intValue();
	 
	 Random rand = new Random();   //生成随机数,因为订单号不能太短
	 int r1=rand.nextInt(10000);
	
	 /****************************第一次签名,获取预支付id*******************************/
	 Map<String, String> restData=new HashMap<String, String>();
	 restData.put("appid",session.getAttribute("appid").toString()); //应用ID  第三方用户唯一凭证
	 restData.put("openid",openId);			                        //消费者id
	 restData.put("body",session.getAttribute("body").toString());	//商品描述 寄存续费充值
	 restData.put("mch_id",session.getAttribute("mch_id").toString());//商户号 
	 restData.put("notify_url","http://new.nbtongtai.com/weixin/wxPay/BackMessage.jsp");  //通知地址     不管支付成功还是失败都会返回到这个界面
	 restData.put("nonce_str",WXPayUtil.generateNonceStr()); 		//随机字符串
	 restData.put("out_trade_no",(r1+""+r1)+"O"+gm_id);             //订单号,不能太短O   后面才是我们想要的订单id
	 restData.put("sign_type","MD5");								//签名类型 
	 restData.put("total_fee",money+"");	                        //交易金额
	 restData.put("trade_type","JSAPI"); 							//交易类型 NATIVE二维码
	 restData.put("spbill_create_ip","47.114.88.38");               //浏览器ip地址,可以不写
	 String oneSign = WXPayUtil.generateSignature(restData,session.getAttribute("cusid").toString());  //第二个参数是商户id里面的那个key   32位数
	 restData.put("sign",oneSign);		                         //拼接签名
	 //将map集合转成xml报文,方便请求微信接口获取  预支付定单id
	 String xml = WXPayUtil.mapToXml(restData);
	 
	 String unifiedorder_url = "https://api.mch.weixin.qq.com/pay/unifiedorder";   //预支付请求连接
	 String response2 = HttpUtil.doPost(unifiedorder_url, xml);   //通过带有签名的xml报文,和预支付连接获取到响应结果
	 String prepay_id = "";// 预支付id
	 if(response2.indexOf("SUCCESS") != -1) {    //若响应结果成功,则取出预支付id
		Map<String, String> map = WXPayUtil.xmlToMap(response2);
		prepay_id = (String) map.get("prepay_id");
	 }
	 /****************************第一次签名,获取预支付id*******************************/
	
	/****************************第二次签名,生成预支付订单*******************************/
	SortedMap<String, String> finalpackage = new TreeMap<String, String>();
    String packages="prepay_id="+prepay_id; //预支付id
    String timeStamp=""+System.currentTimeMillis();   //预支付订单时间戳
    finalpackage.put("appId",session.getAttribute("appid").toString());  //应用ID  第三方用户唯一凭证
    finalpackage.put("timeStamp",timeStamp); 
    finalpackage.put("nonceStr", WXPayUtil.generateNonceStr());          //随机字符串
    finalpackage.put("package", packages);  
    finalpackage.put("signType", "MD5");
    //调用签名接口,进行支付
    String twoSign = WXPayUtil.generateSignature(finalpackage,session.getAttribute("cusid").toString());
    /****************************第二次签名,生成预支付订单*******************************/
    
    //生成预支付订单
    json=new JsonUtil();
    json.addJsons();
    json.addJsonData("gm_id",gm_id);
    json.addJsonData("appid",session.getAttribute("appid").toString());
    json.addJsonData("packages",packages);
    json.addJsonData("timeStamp",timeStamp);
    json.addJsonData("nonceStr",finalpackage.get("nonceStr"));
    json.addJsonData("finalsign",twoSign);//根据第二次签名,返回前台,然后钓起支付面板
    json.addJsonData("status","ok");
    message=json.getJson();

前台收到你返回的状态,进行判断,订单预支付生成成功后,则跳往微信的钓起支付面板界面

来到支付面板界面,要做到事情就通过签名,openid还有等参数,去请求微信,调用微信的微信支付界面即可支付,参数就是上面返回的,将其传给下图即可,然后就可以钓起来微信预支付界面,若用户支付成功,则跳往自己写的成功界面,失败也是一样,写个失败的界面,然后就是这里注意下,下面的这个js界面钓起的微信支付,成功有延迟,所以最好不在这里做最终的支付成功判断

(function ($, doc, $$) {
	
	$.init();
	mui.plusReady(function(){
           // 在这里调用plus api
    //获取数据
    },false);
   
   wx.config({    
	    debug: false, 				 		// 开启调试模式,调用的所有api的返回值会在客户端alert出来,若要查看传入的参数,可以在pc端打开,参数信息会通过log打出,仅在pc端时才会打印。    
	    appId: $$("#appid").val(),  		// 必填,公众号的唯一标识    
	    timestamp: $$("#timestampJsp").val() , // 必填,生成签名的时间戳    
	    nonceStr: $$("#nonceStrJsp").val(),	// 必填,生成签名的随机串    
	    signature: $$("#signatureJsp").val(),  // 必填,签名,见附录1    
	    jsApiList: ['getBrandWCPayRequest'] // 必填,需要使用的JS接口列表,所有JS接口列表见附录2    
   });  

  wx.ready(function(){    
	    function onBridgeReady(){
		        WeixinJSBridge.invoke('getBrandWCPayRequest',{
		            "appId":$$("#appid").val(),     //公众号名称,由商户传入     
		            "timeStamp":$$("#timeStamp").val(),         //时间戳,自1970年以来的秒数     
		            "nonceStr":$$("#nonceStr").val(), //随机串     
		            "package":$$("#packages").val(),     
		            "signType":"MD5",         //微信签名方式:     
		            "paySign":$$("#finalsign").val() //微信签名 
		        },function(res){ 
		            if(res.err_msg == "get_brand_wcpay_request:ok" ) {  // 使用以上方式判断前端返回,微信团队郑重提示:res.err_msg将在用户支付成功后返回    ok,但并不保证它绝对可靠。 
			            //下单完成后,跳往逻辑的界面,向但与同步通知
					    mui.openWindow({
						    url:"/weixin/wxPay/successOrder.jsp?gm_id="+$$("#gm_id").val(),
						    id:"xufeidengPaydeail"
						})    
		            }else{
		                //取消了订单
					    mui.openWindow({
						    url:"/weixin/wxPay/faildOrder.jsp?gm_id="+$$("#gm_id").val(),
						    id:"xufeidengPaydeail"
						}) 
		            }    
		        }); 
		 }
		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();
		 } 
  }); 
  wx.error(function (res) {  
    alert("支付状态:"+res.errMsg);  
  }); 
})(mui, document, jQuery);

然后我们将最后逻辑写在回调界面里面,也就是第一次签名那个回调界面

然后得到微信支付成功的数据对象,根据这个对象,然后判断到底支付成功还是失败

如支付成功,则可以将自己的业务逻辑写到这里面即可

最后,为大家提供参考,我将demo已经打包,欢迎随便下载

com,为后台,
jar需要的jar包,
wxPay前端

 

注意:1,微信支付,同一个订单号,不能频繁支付而且还不能太长,为了解决这个问题,所以们在第一次签名生成预支付订单的时候,可以将商品id,使用随机数,然后中间拼一个字母,后面再根据这个字母去获取我们需要订单id

2,旧版本的支付类是一个接口,新版本是一个抽象类,所以这里如果自己去下载的话,需要重新写一下那个类,不过我这里是写好了,下载下来只需要改里面几个参数,即可

3,微信支付需要httpclient4.5,httpcore4.3及以上版本,不然会报错哦

欢迎大家有问题,咨询,1693940631,有问题的话,也欢迎及时沟通哦,

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章