java實(shí)現(xiàn)微信支付結(jié)果通知
支付完成后,微信會把相關(guān)支付結(jié)果和用戶信息發(fā)送給商戶,商戶需要接收處理,并返回應(yīng)答。
對后臺通知交互時,如果微信收到商戶的應(yīng)答不是成功或超時,微信認(rèn)為通知失敗,微信會通過一定的策略定期重新發(fā)起通知,盡可能提高通知的成功率,但微信不保證通知最終能成功。 (通知頻率為15/15/30/180/1800/1800/1800/1800/3600,單位:秒)
注意:同樣的通知可能會多次發(fā)送給商戶系統(tǒng)。商戶系統(tǒng)必須能夠正確處理重復(fù)的通知。
推薦的做法是,當(dāng)收到通知進(jìn)行處理時,首先檢查對應(yīng)業(yè)務(wù)數(shù)據(jù)的狀態(tài),判斷該通知是否已經(jīng)處理過,如果沒有處理過再進(jìn)行處理,如果處理過直接返回結(jié)果成功。在對業(yè)務(wù)數(shù)據(jù)進(jìn)行狀態(tài)檢查和處理之前,要采用數(shù)據(jù)鎖進(jìn)行并發(fā)控制,以避免函數(shù)重入造成的數(shù)據(jù)混亂。
特別提醒:商戶系統(tǒng)對于支付結(jié)果通知的內(nèi)容一定要做簽名驗(yàn)證,防止數(shù)據(jù)泄漏導(dǎo)致出現(xiàn)“假通知”,造成資金損失。
//支付結(jié)果通知接口 @RequestMapping("/qlydweixinotify.do") public void weixinotify(HttpServletRequest request, HttpServletResponse response) { PrintWriter out = null; StringBuffer xmlStr = new StringBuffer(); try { BufferedReader reader = request.getReader(); String line = null; while ((line = reader.readLine()) != null) { xmlStr.append(line); } Logger.getLogger(getClass()).debug("支付回調(diào)通知:"+xmlStr.toString()); //檢查xml是否有效 boolean flag=Signature.checkIsSignValidFromResponseString(xmlStr.toString()); WeixinNotifyResult result=null; if(flag){ NotifyResData wxData=(NotifyResData) Util.getObjectFromXML(xmlStr.toString(),NotifyResData.class); if(wxData !=null){ if("SUCCESS".equals(wxData.getReturn_code())&&"SUCCESS".equals(wxData.getResult_code())){ OrderPayInfo orderPayInfo = new OrderPayInfo(); orderPayInfo.setOrderNum(wxData.getOut_trade_no()); orderPayInfo.setPayNum(wxData.getTransaction_id()); orderPayInfo.setPayPrice((double)wxData.getTotal_fee()/100+""); orderPayInfo.setPaySource(wxData.getOpenid()); orderPayInfo.setPayTime(wxData.getTime_end()); orderPayInfo.setPayType("2");//1支付寶,2微信支付 OrderMessage returnMessage = orderProductServer .completeProductOrder(orderPayInfo); if (OrderStatus.FAIL.equals(returnMessage .getOrderStatus())) { Logger.getLogger(getClass()).error("遠(yuǎn)程接口完成訂單失敗"); result=new WeixinNotifyResult("FAIL"); result.setReturn_msg("遠(yuǎn)程接口完成訂單失敗"); } else { result=new WeixinNotifyResult("SUCCESS"); result.setReturn_msg("成功"); } }else{ result=new WeixinNotifyResult("FAIL"); result.setReturn_msg("失敗"); } }else{ result=new WeixinNotifyResult("FAIL"); result.setReturn_msg("解析參數(shù)格式失敗"); } }else{ result=new WeixinNotifyResult("FAIL"); result.setReturn_msg("簽名失敗"); } response.getWriter().write(result.toString()); } catch (Exception e) { Logger.getLogger(getClass()).error("qlydweixinotify.do", e); ResponeDeal.getInstance().sendResponseStr(response, "404", "連接超時"); } finally { if (out != null) { out.close(); } } }
模擬http請求工具類:
HttpsRequestUtil.java
package com.qlwb.weixin.util; import java.io.IOException; import org.apache.commons.httpclient.HttpClient; import org.apache.commons.httpclient.HttpException; import org.apache.commons.httpclient.methods.PostMethod; import org.apache.commons.httpclient.methods.RequestEntity; import org.apache.commons.httpclient.methods.StringRequestEntity; import org.apache.log4j.Logger; import com.qlwb.weixin.common.Configure; import com.qlwb.weixin.common.Util; import com.qlwb.weixin.protocol.pay_protocol.WxPayReqData; import com.qlwb.weixin.protocol.payquery_protocol.PayQueryReqData; public class HttpsRequestUtil { /** * * @方法名稱:sendWxPayRequest * @內(nèi)容摘要: <發(fā)送統(tǒng)一下單請求> * @param body * @param outTradeNo * @param totalFee * @param spBillCreateIP * @return * String * @exception * @author:鹿偉偉 * @創(chuàng)建日期:2016年2月19日-下午2:24:05 */ public String sendWxPayRequest(String body,String detail,String outTradeNo,int totalFee,String spBillCreateIP ) { // 構(gòu)造HTTP請求 HttpClient httpclient = new HttpClient(); PostMethod postMethod = new PostMethod(Configure.PAY_API); WxPayReqData wxdata = new WxPayReqData(body,detail,outTradeNo,totalFee,spBillCreateIP); String requestStr=""; requestStr=Util.ConvertObj2Xml(wxdata); // 發(fā)送請求 String strResponse = null; try { RequestEntity entity = new StringRequestEntity( requestStr.toString(), "text/xml", "UTF-8"); postMethod.setRequestEntity(entity); httpclient.executeMethod(postMethod); strResponse = new String(postMethod.getResponseBody(), "utf-8"); Logger.getLogger(getClass()).debug(strResponse); } catch (HttpException e) { Logger.getLogger(getClass()).error("sendWxPayRequest", e); } catch (IOException e) { Logger.getLogger(getClass()).error("sendWxPayRequest", e); } finally { postMethod.releaseConnection(); } return strResponse; } /** * * @方法名稱:orderQueryRequest * @內(nèi)容摘要: <查詢訂單信息> * @param transaction_id 微信的訂單號,優(yōu)先使用 * @return * String * @exception * @author:鹿偉偉 * @創(chuàng)建日期:2016年2月19日-下午2:44:11 */ public String orderQueryRequest(String transactionID, String outTradeNo ) { // 構(gòu)造HTTP請求 HttpClient httpclient = new HttpClient(); PostMethod postMethod = new PostMethod(Configure.PAY_QUERY_API); PayQueryReqData wxdata = new PayQueryReqData(transactionID,outTradeNo); String requestStr=""; requestStr=Util.ConvertObj2Xml(wxdata); // 發(fā)送請求 String strResponse = null; try { RequestEntity entity = new StringRequestEntity( requestStr.toString(), "text/xml", "UTF-8"); postMethod.setRequestEntity(entity); httpclient.executeMethod(postMethod); strResponse = new String(postMethod.getResponseBody(), "utf-8"); } catch (HttpException e) { Logger.getLogger(getClass()).error("orderQueryRequest", e); } catch (IOException e) { Logger.getLogger(getClass()).error("orderQueryRequest", e); } finally { postMethod.releaseConnection(); } return strResponse; } }
以上就是本文的全部內(nèi)容,希望對大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。
相關(guān)文章
Java實(shí)現(xiàn)兩人五子棋游戲(六) 行棋方變換
這篇文章主要為大家詳細(xì)介紹了Java實(shí)現(xiàn)一個簡單的兩人五子棋游戲,行棋方變換,具有一定的參考價值,感興趣的小伙伴們可以參考一下2018-03-03Springboot使用POI實(shí)現(xiàn)導(dǎo)出Excel文件示例
本篇文章主要介紹了Springboot使用POI實(shí)現(xiàn)導(dǎo)出Excel文件示例,非常具有實(shí)用價值,需要的朋友可以參考下。2017-02-02Java中使用正則表達(dá)式的一個簡單例子及常用正則分享
這篇文章主要介紹了Java中使用正則表達(dá)式的一個簡單例子及常用正則分享,本文用一個驗(yàn)證Email的例子講解JAVA中如何使用正則,并羅列了一些常用的正則表達(dá)式,需要的朋友可以參考下2015-06-06Springboot快速集成sse服務(wù)端推流(最新整理)
SSE?Server-Sent?Events是一種允許服務(wù)器向客戶端推送實(shí)時數(shù)據(jù)的技術(shù),它建立在?HTTP?和簡單文本格式之上,提供了一種輕量級的服務(wù)器推送方式,通常也被稱為“事件流”(Event?Stream),這篇文章主要介紹了Springboot快速集成sse服務(wù)端推流(最新整理),需要的朋友可以參考下2024-02-02Spring中ApplicationEvent事件機(jī)制源碼詳解
這篇文章主要介紹了Spring中ApplicationEvent事件機(jī)制源碼詳解,Spring中與事件有關(guān)的接口和類主要包括ApplicationEvent、ApplicationListener,下面來看一下Spring中事件的具體應(yīng)用,需要的朋友可以參考下2023-09-09java?環(huán)境配置(2023年詳細(xì)教程)
這篇文章首先為了完善我的知識體系,今后一些軟件的安裝教程也可能會用到想寫一個更加詳細(xì)的,因?yàn)檫@并不僅僅是寫給?IT?行業(yè)的,其它行業(yè)可能也需要配置java環(huán)境2023-06-06Java實(shí)現(xiàn)經(jīng)典游戲飛機(jī)大戰(zhàn)-I的示例代碼
《飛機(jī)大戰(zhàn)-I》是一款融合了街機(jī)、競技等多種元素的經(jīng)典射擊手游。本文將利用java語言實(shí)現(xiàn)這游戲,文中采用了swing技術(shù)進(jìn)行了界面化處理,感興趣的可以了解一下2022-02-02