java實現(xiàn)微信支付結(jié)果通知
支付完成后,微信會把相關(guān)支付結(jié)果和用戶信息發(fā)送給商戶,商戶需要接收處理,并返回應答。
對后臺通知交互時,如果微信收到商戶的應答不是成功或超時,微信認為通知失敗,微信會通過一定的策略定期重新發(fā)起通知,盡可能提高通知的成功率,但微信不保證通知最終能成功。 (通知頻率為15/15/30/180/1800/1800/1800/1800/3600,單位:秒)
注意:同樣的通知可能會多次發(fā)送給商戶系統(tǒng)。商戶系統(tǒng)必須能夠正確處理重復的通知。
推薦的做法是,當收到通知進行處理時,首先檢查對應業(yè)務數(shù)據(jù)的狀態(tài),判斷該通知是否已經(jīng)處理過,如果沒有處理過再進行處理,如果處理過直接返回結(jié)果成功。在對業(yè)務數(shù)據(jù)進行狀態(tài)檢查和處理之前,要采用數(shù)據(jù)鎖進行并發(fā)控制,以避免函數(shù)重入造成的數(shù)據(jù)混亂。
特別提醒:商戶系統(tǒng)對于支付結(jié)果通知的內(nèi)容一定要做簽名驗證,防止數(shù)據(jù)泄漏導致出現(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("遠程接口完成訂單失敗");
result=new WeixinNotifyResult("FAIL");
result.setReturn_msg("遠程接口完成訂單失敗");
} 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)容,希望對大家的學習有所幫助,也希望大家多多支持腳本之家。
相關(guān)文章
Springboot使用POI實現(xiàn)導出Excel文件示例
本篇文章主要介紹了Springboot使用POI實現(xiàn)導出Excel文件示例,非常具有實用價值,需要的朋友可以參考下。2017-02-02
Spring中ApplicationEvent事件機制源碼詳解
這篇文章主要介紹了Spring中ApplicationEvent事件機制源碼詳解,Spring中與事件有關(guān)的接口和類主要包括ApplicationEvent、ApplicationListener,下面來看一下Spring中事件的具體應用,需要的朋友可以參考下2023-09-09
Java實現(xiàn)經(jīng)典游戲飛機大戰(zhàn)-I的示例代碼
《飛機大戰(zhàn)-I》是一款融合了街機、競技等多種元素的經(jīng)典射擊手游。本文將利用java語言實現(xiàn)這游戲,文中采用了swing技術(shù)進行了界面化處理,感興趣的可以了解一下2022-02-02

