微信退款
1. package com.ds.tech.common.util.weixinpay;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.math.BigDecimal;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.URL;
import java.security.KeyStore;
import java.security.MessageDigest;
import java.security.Security;
import java.text.SimpleDateFormat;
import java.util.Arrays;
import java.util.Calendar;
import java.util.Date;
import java.util.GregorianCalendar;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.UUID;
import javax.crypto.Cipher;
import javax.crypto.SecretKey;
import javax.crypto.spec.SecretKeySpec;
import javax.net.ssl.SSLContext;
import org.apache.commons.lang.StringUtils;
import org.apache.http.HttpResponse;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.conn.ssl.SSLConnectionSocketFactory;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.ssl.SSLContexts;
import org.apache.http.util.EntityUtils;
import org.apache.log4j.LogManager;
import org.apache.log4j.Logger;
import org.bouncycastle.jce.provider.BouncyCastleProvider;
import org.dom4j.Document;
import org.dom4j.DocumentException;
import org.dom4j.DocumentHelper;
import org.dom4j.Element;
import com.ds.tech.common.constant.ApiStaticConstant;
import com.ds.tech.common.enums.WxCallBackBusiness;
import com.ds.tech.common.util.XMLUtil;
import com.ds.tech.entity.base.BaseMapEntity;
import com.ds.tech.utility.common.ConfigUtil;
import com.ds.tech.utility.log4j.LogWriter;
public class WeixinPayUtils {
private static Logger logger = LogManager.getLogger(WeixinPayUtils.class);
private static final String[] hexDigits = new String[]{"0", "1", "2", "3", "4", "5", "6", "7", "8", "9", "a", "b", "c", "d", "e", "f"};
private static String appId = null;
private static String mchId = null;
private static String wxRefundUrl = null;
static {
appId = ConfigUtil.getSettings("wx_appid").trim();
mchId = ConfigUtil.getSettings("wx_mch_id").trim();
wxRefundUrl = ConfigUtil.getSettings("wx_refund_url").trim();
}
/**
* 所有引數全部必傳
*
* @param outRefundNo outRefundNo 支援單筆多次退款,每次不一樣
* @param totalFee //總金額 -- 單位元
* @param refundFee //退款金額 -- 單位元
* @param refundDesc //退款原因
* @param refundAccount //必傳 //REFUND_SOURCE_UNSETTLED_FUNDS---未結算資金退款(預設使用未結算資金退款)REFUND_SOURCE_RECHARGE_FUNDS---可用餘額退款
* @param business //業務型別,拼接到商戶訂單號後面,回撥解析取出,根據型別處理不同業務
* @return
*/
public static Map<String, String> wxRefund(
String orderNo,
String outRefundNo,
String totalFee,
String refundFee,
String refundDesc,
String refundAccount,
WxCallBackBusiness business) {
logger.info("微信支付退款入參:orderNo:" + orderNo + ",outRefundNo:" + outRefundNo +
",totalFee:" + totalFee + ",refundFee:" + refundFee +
",refundDesc:" + refundDesc + ",refundAccount:" + refundAccount);
if (StringUtils.isBlank(orderNo)
|| StringUtils.isBlank(outRefundNo)
|| StringUtils.isBlank(totalFee)
|| StringUtils.isBlank(refundFee)
|| StringUtils.isBlank(refundDesc)
|| StringUtils.isBlank(refundAccount)
|| null == business) {
logger.info("微信支付退款失敗,必傳引數為空!");
return null;
}
//非必傳引數處理
BaseMapEntity parameters = new BaseMapEntity();
parameters.put("feeType", "CNY");
parameters.put("refundDesc", refundDesc);
parameters.put("refundAccount", refundAccount);
//微信回撥統一地址
String wxRefundCallbackUrl = ConfigUtil.getSettings("pament_domain")+"/api/pay/WeChatCallback/" + business.getNumber() + "/wxRefundCallback.do";
logger.info("微信支付退款:wxRefundCallbackUrl = " + wxRefundCallbackUrl);
parameters.put("notifyUrl", wxRefundCallbackUrl);
//微信接收的金額單位為分,所以講入參轉換
String totalCent = (new BigDecimal(totalFee).multiply(new BigDecimal("100"))).intValue() + "" ;
String refundCent = (new BigDecimal(refundFee).multiply(new BigDecimal("100"))).intValue() + "";
//請求引數轉換成微信支援的xml格式
Map<String, String> map = requestWxRefundParams(orderNo,outRefundNo,totalCent,refundCent,parameters);
String xml = mapToXML(map);
logger.info("xml:" + xml);
try {
//讀取本機存放的PKCS12證書檔案
String path = ApiStaticConstant.getStaticValue("apiWebClassPath") + "keys" + File.separator + "apiclient_cert.p12";
KeyStore keyStore = KeyStore.getInstance("PKCS12");
FileInputStream instream = new FileInputStream(new File(path));
try {
////指定PKCS12的密碼(商戶ID)
keyStore.load(instream, mchId.toCharArray());
} finally {
instream.close();
}
//指定TLS版本
SSLContext sslcontext = SSLContexts.custom().loadKeyMaterial(keyStore, mchId.toCharArray()).build();
SSLConnectionSocketFactory sslsf = new SSLConnectionSocketFactory(sslcontext,new String[] { "TLSv1" },null,SSLConnectionSocketFactory.BROWSER_COMPATIBLE_HOSTNAME_VERIFIER);
CloseableHttpClient httpclient = HttpClients.custom().setSSLSocketFactory(sslsf).build();
//傳送請求
HttpPost httpost= new HttpPost(wxRefundUrl);
httpost.setEntity(new StringEntity(xml,"UTF-8"));
HttpResponse wxResponse = httpclient.execute(httpost);
//退款結果處理
String jsonStr = EntityUtils.toString(wxResponse.getEntity(), "UTF-8");
logger.info("jsonStr:" + jsonStr);
return XMLUtil.doXMLParse(jsonStr);
} catch (Exception e ) {
logger.info("微信支付退款失敗!");
}
return null;
}
/**
*
* @param orderNo 商戶訂單號
* @param totalFee 交易總金額
* @param refundFee 退款金額
* @param parameters 擴充套件的非必傳引數
* @return
*/
private static Map<String, String> requestWxRefundParams(
String orderNo,
String outRefundNo,
String totalFee,
String refundFee,
BaseMapEntity parameters){
Map<String, String> map = new HashMap<>();
map.put("appid", appId);
map.put("mch_id", mchId);//微信支付分配的商戶號
map.put("nonce_str", UUID.randomUUID().toString().replaceAll("-", ""));
map.put("sign_type", "MD5");
map.put("out_trade_no", orderNo);
map.put("out_refund_no", outRefundNo);
map.put("total_fee", totalFee);
map.put("refund_fee", refundFee);
map.put("refund_fee_type", parameters.getString("feeType"));
map.put("refund_desc", parameters.getString("refundDesc"));
map.put("refund_account",parameters.getString("refundAccount"));
map.put("notify_url",parameters.getString("notifyUrl"));
map.put("sign", getSign(map));
return map;
}
/**
* 微信小程式支付
* @param orderName 商品描述
* @param orderDesc 商品詳情
* @param attach 附加資料
* @param orderNo 訂單號
* @param price 金額
* @param notifyUrl 回撥地址
* @param limitCreditCard 是否限制信用卡
* @param openid 使用者標識
* @return
*/
public static Map<String, Object> getWeixinMinPayParam(String orderName, String orderDesc,String attach, String orderNo, BigDecimal price,String notifyUrl,boolean limitCreditCard,String openid) {
//是否限制信用卡
String limitPay = "";
if(limitCreditCard){
limitPay = "no_credit";
}
int totalPrice = (price.multiply(new BigDecimal("100"))).intValue();
Map<String, Object> wxMap = new HashMap();
Map<String, String> map = requestParam(ConfigUtil.getSettings("wx_appid").trim(),orderName, orderDesc, attach, orderNo, totalPrice, notifyUrl, "JSAPI", limitPay, openid);
Long timestamp = Long.valueOf(System.currentTimeMillis() / 1000L);
wxMap.put("wx_appid",ConfigUtil.getSettings("wx_appid"));
wxMap.put("timestamp", timestamp.toString());
wxMap.put("noncestr", UUID.randomUUID().toString().replaceAll("-", ""));
wxMap.put("package", getWXprepayID(map));
wxMap.put("signType", "MD5");
wxMap.put("paySign", getPaySign(wxMap));
return wxMap;
}
/**
* 微信支付
* @Param appid
* @param orderName 商品描述
* @param orderDesc 商品詳情
* @param attach 附加資料
* @param orderNo 訂單號
* @param totalPrice 標價金額
* @param notifyUrl 回撥地址
* @param tradeType 交易型別 JSAPI--公眾號支付、NATIVE--原生掃碼支付、APP--app支付
* @param limitPay 指定支付方式 上傳此引數no_credit--可限制使用者不能使用信用卡支付
* @param openid 使用者標識 trade_type=JSAPI,此引數必傳,使用者在商戶appid下的唯一標識
* @return
*/
private static Map<String, String> requestParam(String appid,String orderName,String orderDesc,String attach, String orderNo, int totalPrice, String notifyUrl,String tradeType,String limitPay,String openid) {
Map<String, String> map = new HashMap();
Date date = new Date();
Calendar calendar = new GregorianCalendar();
calendar.setTime(date);
String startTime = (new SimpleDateFormat("yyyyMMddHHmmss")).format(date);
calendar.add(5, 1);
date = calendar.getTime();
String endTime = (new SimpleDateFormat("yyyyMMddHHmmss")).format(date);
map.put("appid", appid);
map.put("mch_id", ConfigUtil.getSettings("wx_mch_id").trim());//微信支付分配的商戶號
map.put("device_info", "WEB");//裝置號
map.put("nonce_str", UUID.randomUUID().toString().replaceAll("-", ""));//隨機字串
map.put("sign_type", "MD5");//簽名型別
map.put("body", orderName);//商品描述
map.put("detail", orderDesc);//商品詳情
map.put("attach", attach);//附加資料
map.put("out_trade_no", orderNo);//商戶訂單號
map.put("fee_type", "CNY");//幣種
map.put("total_fee",String.valueOf(totalPrice));//標價金額
map.put("spbill_create_ip", ConfigUtil.getSettings("wx_spbill_create_ip"));//終端IP
map.put("time_start", startTime);//交易起始時間
map.put("time_expire", endTime);//交易結束時間
map.put("notify_url", notifyUrl);//回撥地址
map.put("trade_type", tradeType);//交易型別 JSAPI--公眾號支付、NATIVE--原生掃碼支付、APP--app支付
map.put("limit_pay", limitPay);//指定支付方式 上傳此引數no_credit--可限制使用者不能使用信用卡支付
map.put("openid",openid);//trade_type=JSAPI,此引數必傳,使用者在商戶appid下的唯一標識
map.put("sign", getSign(map));
return map;
}
private static String getSign(Map<String, String> data){
Set<String> keySet = data.keySet();
String[] keyArray = keySet.toArray(new String[keySet.size()]);
Arrays.sort(keyArray);
StringBuilder sb = new StringBuilder();
for (String k : keyArray) {
if (k.equals("sign")) {
continue;
}
if (StringUtils.isBlank(data.get(k))) {
continue;
}
// 引數值為空,則不參與簽名
sb.append(k).append("=").append(data.get(k).trim()).append("&");
}
sb.append("key=").append(ConfigUtil.getSettings("wx_key").trim());
String a = "";
try {
a = MD5(sb.toString()).toUpperCase();
}catch (Exception e){
e.printStackTrace();
}
return a;
}
/**
* 生成 MD5
*
* @param data 待處理資料
* @return MD5結果
*/
public static String MD5(String data) throws Exception {
java.security.MessageDigest md = MessageDigest.getInstance("MD5");
byte[] array = md.digest(data.getBytes("UTF-8"));
StringBuilder sb = new StringBuilder();
for (byte item : array) {
sb.append(Integer.toHexString((item & 0xFF) | 0x100).substring(1, 3));
}
return sb.toString().toUpperCase();
}
private static String MD5Encode(String origin, String charsetname) {
String resultString = null;
try {
resultString = new String(origin);
MessageDigest md = MessageDigest.getInstance("MD5");
if(charsetname != null && !"".equals(charsetname)) {
resultString = byteArrayToHexString(md.digest(resultString.getBytes(charsetname)));
} else {
resultString = byteArrayToHexString(md.digest(resultString.getBytes()));
}
} catch (Exception var4) {
;
}
return resultString;
}
private static String byteArrayToHexString(byte[] b) {
StringBuffer resultSb = new StringBuffer();
for(int i = 0; i < b.length; ++i) {
resultSb.append(byteToHexString(b[i]));
}
return resultSb.toString();
}
private static String byteToHexString(byte b) {
int n = b;
if(b < 0) {
n = b + 256;
}
int d1 = n / 16;
int d2 = n % 16;
return hexDigits[d1] + hexDigits[d2];
}
private static String getWXprepayID(Map<String, String> map) {
String prepayId = null;
String xml = mapToXML(map);
System.out.println(xml);
String uri = ConfigUtil.getSettings("wx_pay_url");
try {
URL url = new URL(uri);
HttpURLConnection http = (HttpURLConnection)url.openConnection();
http.setRequestMethod("POST");
http.setRequestProperty("Content-Type", "application/x-www-form-urlencoded");
http.setDoOutput(true);
http.setDoInput(true);
http.connect();
OutputStream os = http.getOutputStream();
os.write(xml.getBytes("UTF-8"));
os.flush();
os.close();
InputStream is = http.getInputStream();
int size = is.available();
byte[] jsonBytes = new byte[size];
is.read(jsonBytes);
String message = new String(jsonBytes, "UTF-8");
LogWriter.writeAccessLog("get prepayID message:" + message);
System.out.println("get prepayID message:"+message);
logger.info("get prepayID message:"+message);
Document doc = DocumentHelper.parseText(message);
Element rootElement = doc.getRootElement();
List<Element> elements = rootElement.elements();
for(int i = 0; i < elements.size(); ++i) {
Element element = (Element)elements.get(i);
String elementName = element.getName();
if("prepay_id".equals(elementName)) {
prepayId = element.getText();
}
}
} catch (MalformedURLException var17) {
var17.printStackTrace();
} catch (IOException var18) {
var18.printStackTrace();
} catch (DocumentException var19) {
var19.printStackTrace();
}
return prepayId;
}
private static String mapToXML(Map<String, String> map) {
StringBuffer sb = new StringBuffer();
sb.append("<xml>");
for(Map.Entry<String,String> entry:map.entrySet()){
if(entry.getValue()!=""){
sb.append("<"+entry.getKey()+">"+entry.getValue()+"</"+entry.getKey()+">");
}
}
sb.append("</xml>");
return sb.toString();
}
private static String getPaySign(Map<String, Object> map) {
StringBuffer sb = new StringBuffer();
sb.append("appId=" + ConfigUtil.getSettings("wx_appid"));
sb.append("&nonceStr=" + map.get("noncestr"));
sb.append("&package=prepay_id=" + map.get("package"));
sb.append("&signType=" + map.get("signType"));
sb.append("&timeStamp=" + map.get("timestamp"));
String a = sb.toString();
String stringSignTemp = a + "&key=" + ConfigUtil.getSettings("wx_key").trim();
String sign = MD5Encode(stringSignTemp, "UTF-8").toUpperCase();
return sign;
}
/**
*
* @param reqInfoSecret
* @param key
* @return
*/
@SuppressWarnings("restriction")
public static String getRefundDecrypt(String reqInfoSecret, String key) {
String result = "";
try {
Security.addProvider(new BouncyCastleProvider());
sun.misc.BASE64Decoder decoder = new sun.misc.BASE64Decoder();
byte[] bt = decoder.decodeBuffer(reqInfoSecret);
String b = new String(bt);
String md5key = MD5(key).toLowerCase();
SecretKey secretKey = new SecretKeySpec(md5key.getBytes(), "AES");
Cipher cipher = Cipher.getInstance("AES/ECB/PKCS7Padding", "BC");
cipher.init(Cipher.DECRYPT_MODE, secretKey);
byte[] resultbt = cipher.doFinal(bt);
result = new String(resultbt,"UTF-8");
} catch (Exception e) {
e.printStackTrace();
}
return result;
}
public static String setXML(String return_code, String return_msg) {
return "<xml><return_code><![CDATA[" + return_code
+ "]]></return_code><return_msg><![CDATA[" + return_msg
+ "]]></return_msg></xml>";
}
}
2. package com.ds.tech.controller.zenith.callback;
import com.ds.tech.controller.base.BaseAPIController;
import com.ds.tech.service.zenith.pay.WeChatCallbackService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
@Controller
@RequestMapping("/api/pay/WeChatCallback")
@Scope("prototype")
public class WeChatCallbackController extends BaseAPIController {
@Autowired
private WeChatCallbackService weChatCallbackService;
/**
* 2018年11月29日
* @param request
* @param respone
*/
@RequestMapping(value = "/{cbbNumber}/wxRefundCallback", method = RequestMethod.POST)
public void wxRefundCallback(@PathVariable("cbbNumber") String cbbNumber,HttpServletRequest request, HttpServletResponse respone) {
weChatCallbackService.wxRefundCallback(cbbNumber,request,respone);
}
}
3.
package com.ds.tech.service.zenith.pay;
import java.io.IOException;
import java.util.Date;
import java.util.Map;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.apache.commons.lang3.StringUtils;
import org.jdom.JDOMException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import com.alibaba.fastjson.JSONObject;
import com.ds.tech.common.enums.WxCallBackBusiness;
import com.ds.tech.common.model.WxRefundResponse;
import com.ds.tech.common.util.ResponseHandler;
import com.ds.tech.common.util.XMLUtil;
import com.ds.tech.common.util.weixinpay.WeixinPayUtils;
import com.ds.tech.dao.account.UserPurseWaterDao;
import com.ds.tech.dao.account.UserPurseWaterHistoryDao;
import com.ds.tech.dao.order.VehicleOrderDao;
import com.ds.tech.entity.base.BaseMapEntity;
import com.ds.tech.service.base.BaseAPIService;
import com.ds.tech.service.wxmini.order.OrderWxService;
import com.ds.tech.utility.common.ConfigUtil;
import com.ds.tech.utility.log4j.LogWriter;
import com.ds.tech.utility.model.ResultObject;
@Service
public class WeChatCallbackService extends BaseAPIService {
@Autowired
private OrderWxService orderWxService;
@Autowired
private VehicleOrderDao vehicleOrderMapper;
@Autowired
private UserPurseWaterDao userPurseWaterMapper;
@Autowired
private UserPurseWaterHistoryDao userPurseWaterHisMapper;
/**
* 2018年11月29日
* @param request
* @param response
*/
public void wxRefundCallback(String cbbNumber,HttpServletRequest request, HttpServletResponse response) {
LogWriter.writeAccessLog("-----微信退款回撥開始--------");
String inputLine;
String notityXml = "";
try {
while ((inputLine = request.getReader().readLine()) != null) {
notityXml += inputLine;
}
LogWriter.writeAccessLog("接收到的報文:" + notityXml);
// 建立支付應答物件
ResponseHandler resHandler = new ResponseHandler(request, response);
resHandler.setKey(ConfigUtil.getSettings("wx_key").trim());
Map<String, String> map = XMLUtil.doXMLParse(notityXml);
if ("SUCCESS".equals(map.get("return_code"))) {
String reqInfo = map.get("req_info").toString();
//加密內容解密
String reqInfoDecrypt = WeixinPayUtils.getRefundDecrypt(reqInfo, ConfigUtil.getSettings("wx_key").trim());
LogWriter.writeAccessLog("解密內容的報文:" + reqInfoDecrypt);
//解密內容為空,返回呼叫失敗資訊給微信方
if (StringUtils.isBlank(reqInfoDecrypt)) {
LogWriter.writeAccessLog("-----微信退款返回失敗:解析內容失敗--------");
String retWXMsg = "<xml><return_code><![CDATA[FAIL]]></return_code><return_msg><![CDATA[FAIL]]></return_msg></xml>";
resHandler.sendToCFT(retWXMsg);
return;
}
Map<String, String> refundMap = XMLUtil.doXMLParse(reqInfoDecrypt);
WxRefundResponse resp = new WxRefundResponse();
resp.setReturnCode(map.get("return_code"));
resp.setReturnMsg(map.get("req_info"));
resp.setAppId(map.get("appid"));
resp.setMchId(map.get("mch_id"));
resp.setNonceStr(map.get("nonce_str"));
resp.setTransactionId(refundMap.get("transaction_id"));
resp.setOutTradeNo(refundMap.get("out_trade_no"));
resp.setRefundId(refundMap.get("refund_id"));
resp.setOutRefundNo(refundMap.get("out_refund_no"));
resp.setTotalFee(refundMap.get("total_fee"));
resp.setSettlementTotalFee(refundMap.get("settlement_total_fee"));
resp.setRefundFee(refundMap.get("refund_fee"));
resp.setSettlementRefundFee(refundMap.get("settlement_refund_fee"));
resp.setRefundStatus(refundMap.get("refund_status"));
resp.setSuccessTime(refundMap.get("success_time"));
resp.setRefundRecvAccout(refundMap.get("refund_recv_accout"));
resp.setRefundAccount(refundMap.get("refund_account"));
resp.setRefundRequestSource(refundMap.get("refund_request_source"));
//訂單編號處理 outTradeNo = orderNo + number(WxCallBackBusiness)
String orderNo = resp.getOutTradeNo();
LogWriter.writeAccessLog("------orderNo:" + orderNo + ",cbbNumber:" + cbbNumber + "-------");
//檢查訂單資訊
BaseMapEntity orderParamMap = new BaseMapEntity();
orderParamMap.put("orderNo",orderNo);
BaseMapEntity vehicleOrder = vehicleOrderMapper.queryVehicleOrderInfo(orderParamMap);
if (null == vehicleOrder) {
LogWriter.writeAccessLog("-----微信退款返回失敗:訂單編號找不到--------");
String retWXMsg = "<xml><return_code><![CDATA[FAIL]]></return_code><return_msg><![CDATA[FAIL]]></return_msg></xml>";
resHandler.sendToCFT(retWXMsg);
return;
}
//查詢訂單支付時的流水,每個訂單隻有一筆支付記錄
BaseMapEntity waterParam = new BaseMapEntity();
waterParam.put("orderNo",orderNo);
BaseMapEntity queryWater = userPurseWaterMapper.selectPayedPurseWaterByOrderNo(waterParam);
if(null == queryWater){
LogWriter.writeAccessLog("-----微信退款返回失敗:訂單編號找不到交易流水--------");
String retWXMsg = "<xml><return_code><![CDATA[FAIL]]></return_code><return_msg><![CDATA[FAIL]]></return_msg></xml>";
resHandler.sendToCFT(retWXMsg);
return;
}
//交易流水錶
Date curDate = new Date();
BaseMapEntity waterMap = new BaseMapEntity();
waterMap.put("userId", vehicleOrder.getInt("userId"));
waterMap.put("orderNo", orderNo);
waterMap.put("thirdTradeNo", resp.getOutRefundNo());
waterMap.put("purseChannel", 3);
waterMap.put("depositTime", curDate);
waterMap.put("profitType", 2);
waterMap.put("incomeTime", curDate);
waterMap.put("state", 2);
waterMap.put("tradeStartAccount", "微信");
waterMap.put("tradeReceiveAccount", queryWater.getString("tradeStartAccount"));
waterMap.put("tradeAmount", resp.getSettlementRefundFee());
waterMap.put("tradeResult", resp.getRefundStatus());
waterMap.put("waterRemark", null != WxCallBackBusiness.getEnum(cbbNumber) ? WxCallBackBusiness.getEnum(cbbNumber).getName() : null);
waterMap.put("createUser", "weixinCallBack");
waterMap.put("updateUser", "weixinCallBack");
waterMap.put("payUserId", null);
vehicleOrderMapper.insertPurseWater(waterMap);
//通訊成功,且解密轉物件成功,新增流水歷史記錄表
BaseMapEntity waterHisMap = new BaseMapEntity();
waterHisMap.put("className", "com.ds.tech.service.zenith.pay.WeChatCallbackService");
waterHisMap.put("methodName", "wxRefundCallback");
waterHisMap.put("tradeType", "3"); //交易方式:1.銀行卡 2.支付寶 3.微信
waterHisMap.put("tradeInput", JSONObject.toJSON(resp).toString());
waterHisMap.put("tradeOutput", null);
waterHisMap.put("tradeTime", new Date());
userPurseWaterHisMapper.insertUserPurseWaterHistory(waterHisMap);
String retWXMsg = "<xml><return_code><![CDATA[SUCCESS]]></return_code><return_msg><![CDATA[OK]]></return_msg></xml>";
resHandler.sendToCFT(retWXMsg);
LogWriter.writeAccessLog("-----儲存資料成功,微信回撥完畢--------");
return;
}
String retWXMsg = "<xml><return_code><![CDATA[FAIL]]></return_code><return_msg><![CDATA[FAIL]]></return_msg></xml>";
resHandler.sendToCFT(retWXMsg);
LogWriter.writeAccessLog("-----微信退款回撥失敗--------");
return;
} catch (Exception e) {
LogWriter.writeErrorLog("微信退款回撥失敗,:wxRefundCallback");
}
LogWriter.writeAccessLog("-----微信退款回撥結束--------");
}
/***
* 微信支付非同步通知
*/
public void weChatCallbackForOrderPay(HttpServletRequest request, HttpServletResponse response) {
LogWriter.writeAccessLog("-----支付回撥開始--------");
String inputLine;
String notityXml = "";
try {
LogWriter.writeAccessLog("-----支付回撥開始--------");
while ((inputLine = request.getReader().readLine()) != null) {
notityXml += inputLine;
}
request.getReader().close();
LogWriter.writeAccessLog("接收到的報文--------" + notityXml);
System.out.println("接收到的報文:" + notityXml);
Map<String, String> map = XMLUtil.doXMLParse(notityXml);
// 金鑰
// 建立支付應答物件
ResponseHandler resHandler = new ResponseHandler(request, response);
resHandler.setKey(ConfigUtil.getSettings("wx_key").trim());
if (resHandler.isTenpaySign(map)) {
LogWriter.writeAccessLog("-----驗證成功--------");
// 獲取返回引數
String rescode = map.get("result_code");
// 商戶訂單號
String out_trade_no = map.get("out_trade_no");
// 微信支付訂單號
String transaction_id = map.get("transaction_id");
// 支付完成時間
String time_end = map.get("time_end");
String total = map.get("total_fee");
if ("SUCCESS".equals(rescode)) {// 返回成功
BaseMapEntity orderParams = new BaseMapEntity();
orderParams.put("orderNo",out_trade_no);//訂單編號
orderParams.put("payPrice",total);//支付金額
orderParams.put("thirdTradeNo",transaction_id);//交易流水號
ResultObject resultObject = orderWxService.updateOrderAfterTenantPay(orderParams);
if (resultObject.getErrcode() == 0) {
String retWXMsg = "<xml><return_code><![CDATA[SUCCESS]]></return_code><return_msg><![CDATA[OK]]></return_msg></xml>";
resHandler.sendToCFT(retWXMsg);
LogWriter.writeAccessLog("-----儲存資料成功,通知微信完畢--------");
return;
}
} else {
LogWriter.writeAccessLog("-----微信返回失敗--------");
String retWXMsg = "<xml><return_code><![CDATA[FAIL]]></return_code><return_msg><![CDATA[FAIL]]></return_msg></xml>";
resHandler.sendToCFT(retWXMsg);
return;
}
}
LogWriter.writeAccessLog("-----微信返回失敗--------");
String retWXMsg = "<xml><return_code><![CDATA[FAIL]]></return_code><return_msg><![CDATA[FAIL]]></return_msg></xml>";
resHandler.sendToCFT(retWXMsg);
LogWriter.writeAccessLog("-----驗證請求失敗--------");
} catch (NumberFormatException e) {
LogWriter.writeErrorLog("微信回撥介面失敗,原因:", e);
} catch (JDOMException e) {
LogWriter.writeErrorLog("微信回撥介面失敗,原因:", e);
} catch (IOException e) {
LogWriter.writeErrorLog("微信回撥介面失敗,原因:", e);
}
// catch (ParseException e) {
// LogWriter.writeErrorLog("微信回撥介面失敗,原因:", e);
// }
LogWriter.writeAccessLog("-----支付回撥結束--------");
}
/***
* 微信支付欠款訂單回回調函式
* @param request
* @param response
*/
public void weChatCallbackForPayDebtOrder(HttpServletRequest request, HttpServletResponse response) {
logger.info("-----支付欠款回撥開始--------");
String inputLine;
String notityXml = "";
try {
while ((inputLine = request.getReader().readLine()) != null) {
notityXml += inputLine;
}
request.getReader().close();
logger.info("接收到的報文--------" + notityXml);
Map<String, String> map = XMLUtil.doXMLParse(notityXml);
// 金鑰
// 建立支付應答物件
ResponseHandler resHandler = new ResponseHandler(request, response);
resHandler.setKey(ConfigUtil.getSettings("wx_key").trim());
if (resHandler.isTenpaySign(map)) {
logger.info("-----驗證成功--------");
// 獲取返回引數
String rescode = map.get("result_code");
// 商戶訂單號
String out_trade_no = map.get("out_trade_no");
// 微信支付訂單號
String transaction_id = map.get("transaction_id");
// 支付完成時間
String time_end = map.get("time_end");
String total = map.get("total_fee");
if ("SUCCESS".equals(rescode)) {// 返回成功
BaseMapEntity orderParams = new BaseMapEntity();
orderParams.put("orderNo",out_trade_no);//訂單編號
orderParams.put("payPrice",total);//支付金額
orderParams.put("thirdTradeNo",transaction_id);//交易流水號
ResultObject resultObject = orderWxService.updateAfterTenantPayDebtOrder(orderParams);
if (resultObject.getErrcode() == 0) {
String retWXMsg = "<xml><return_code><![CDATA[SUCCESS]]></return_code><return_msg><![CDATA[OK]]></return_msg></xml>";
resHandler.sendToCFT(retWXMsg);
return;
}
} else {
logger.info("-----微信返回失敗--------");
String retWXMsg = "<xml><return_code><![CDATA[FAIL]]></return_code><return_msg><![CDATA[FAIL]]></return_msg></xml>";
resHandler.sendToCFT(retWXMsg);
return;
}
}
String retWXMsg = "<xml><return_code><![CDATA[FAIL]]></return_code><return_msg><![CDATA[FAIL]]></return_msg></xml>";
resHandler.sendToCFT(retWXMsg);
} catch (NumberFormatException e) {
logger.error("微信回撥介面失敗,原因:", e);
} catch (JDOMException e) {
logger.error("微信回撥介面失敗,原因:", e);
} catch (IOException e) {
logger.error("微信回撥介面失敗,原因:", e);
}
logger.info("-----支付欠款回撥結束--------");
}
}