微信支付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,有問題的話,也歡迎及時溝通哦,

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