微信支付官方文檔 https://pay.weixin.qq.com/wiki/doc/api/app/app.php?chapter=8_1# 1.java後臺controller層php
package com.readygo.pet.controller; import java.util.HashMap; import java.util.Map; import javax.servlet.http.HttpServletRequest; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMethod; import org.springframework.web.bind.annotation.RequestParam; import org.springframework.web.bind.annotation.RestController; import com.readygo.pet.common.Constant; import com.readygo.pet.common.ResultObject; import com.readygo.pet.service.WXPayService; import com.readygo.pet.utils.WXPayUtils; import com.readygo.pet.vo.WXPayVO; /** * 程序名 WXPaymentController.java * 程序功能 微信支付接口 * 做成者 xx * 做成日期 2016-04-27 * 修改履歷 * 項目名 狀態 做成者 做成日期 * -------------------------------------------- * pets 新規 xx 2016-04-27 */ @RestController @RequestMapping("/wechat") public class WXPaymentController { @Autowired private WXPayService wxPayService; /** * 發起微信支付 * * @param payVO * 訂單信息 * @return 帶簽名的客戶端支付信息 */ @RequestMapping(value = "/doWXPay", method = RequestMethod.POST) public ResultObject doWXPay(@RequestBody WXPayVO payVO, HttpServletRequest request){ ResultObject resultObject = new ResultObject(); try { resultObject = wxPayService.doWXPay(payVO, request); } catch (Exception e) { resultObject.setResultCode(Constant.ResultCode.FAILED.getType()); resultObject.setResultMsg(WXPayUtils.MSG_WXPAY_ORDER_FAILED); resultObject.setResultCount("0"); e.printStackTrace(); } return resultObject; } /** * 微信支付後供微信服務器端回調方法 * 根據返回的狀態更新相關訂單信息及生成消費碼 * @param request 請求包 * * @return 成功/失敗 */ @RequestMapping(value = "/callBackWXPay") public String callBackWXPay(HttpServletRequest request){ String retStr = ""; try { retStr = wxPayService.callBackWXPay(request); } catch (Exception e) { Map<String, Object> retMap = new HashMap<String, Object>(); retMap.put("return_code", "FAIL"); retMap.put("return_msg", "接接收異常"); retStr = WXPayUtils.map2xmlBody(retMap, "xml"); } System.out.println("微信支付回調開始"); return retStr; } /** * 微信支付查詢 * @param orderId 商家訂單編號 * @return 查詢結果 */ @RequestMapping(value = "/searchWXPay", method = RequestMethod.POST) public ResultObject searchWXPay(@RequestParam String orderId){ ResultObject resultObject = new ResultObject(); try { resultObject = wxPayService.searchWXPay(orderId); } catch (Exception e) { resultObject.setResultCode(WXPayUtils.ResultCode.FAILED.getType()); resultObject.setResultMsg(WXPayUtils.MSG_WXPAY_SEARCH_FAILED); resultObject.setResultCount("0"); e.printStackTrace(); } return resultObject; } /** * 關閉支付訂單 * @param orderId 訂單編號 * @param request 請求包 * @return 執行結果 */ @RequestMapping(value = "/closeWXPay", method = RequestMethod.POST) public ResultObject closeWXPay(@RequestBody String orderId){ ResultObject resultObject = new ResultObject(); try { resultObject = wxPayService.closeWXPay(orderId); } catch (Exception e) { resultObject.setResultCode(WXPayUtils.ResultCode.FAILED.getType()); resultObject.setResultMsg(WXPayUtils.MSG_WXPAY_CLOSE_FAILED); resultObject.setResultCount("0"); e.printStackTrace(); } return resultObject; } /** * 微信支付退款 * @param payVO 退款訂單信息 * @return 退款申請結果 */ @RequestMapping(value = "/refundWXPay", method = RequestMethod.POST) public ResultObject refundWXPay(@RequestBody WXPayVO payVO){ ResultObject resultObject = new ResultObject(); try { resultObject = wxPayService.refundWXPay(payVO); } catch (Exception e) { resultObject.setResultCode(WXPayUtils.ResultCode.FAILED.getType()); resultObject.setResultMsg(WXPayUtils.MSG_WXPAY_CLOSE_FAILED); resultObject.setResultCount("0"); e.printStackTrace(); } return resultObject; } /** * 微信退款申請查詢 * @param refundOrderId 退款單號 * @return 退款查詢結果 */ @RequestMapping(value = "/searchRefundWXPay", method = RequestMethod.POST) public ResultObject searchRefundWXPay(@RequestBody String refundOrderId){ ResultObject resultObject = new ResultObject(); try { resultObject = wxPayService.searchRefundWXPay(refundOrderId); } catch (Exception e) { resultObject.setResultCode(WXPayUtils.ResultCode.FAILED.getType()); resultObject.setResultMsg(WXPayUtils.MSG_WXPAY_CLOSE_FAILED); resultObject.setResultCount("0"); e.printStackTrace(); } return resultObject; } }
2.Service層以下前端
package com.readygo.pet.service; import javax.servlet.http.HttpServletRequest; import com.readygo.pet.common.ResultObject; import com.readygo.pet.vo.WXPayVO; /** * 程序名 WXPayService.java * 程序功能 微信支付處理接口 * 做成者 xx * 做成日期 2016-04-27 * 修改履歷 * 項目名 狀態 做成者 做成日期 * -------------------------------------------- * pets 新規 xx 2016-04-27 */ public interface WXPayService { /** * 發起微信支付 * @param payVO 支付訂單信息 * @param request 發起支付的請求 * @return 帶簽名的客戶端支付信息 */ ResultObject doWXPay(WXPayVO payVO, HttpServletRequest request) throws Exception; /** * 微信支付回調 * @param request 發起支付的請求 * @return 返給微信服務器接收結果 */ String callBackWXPay(HttpServletRequest request) throws Exception; /** * 查詢微信支付結果 * @param orderId 內部訂單ID(非微信支付id) * @param request 請求包 * @return 查詢結果 * @throws Exception */ ResultObject searchWXPay(String orderId) throws Exception; /** * 關閉微信支付訂單 * @param orderId 訂單編號 * @param request 請求包 * @return 執行結果 * @throws Exception */ ResultObject closeWXPay(String orderId) throws Exception; /** * 申請退款 * @param payVO 退款信息 * @param request 請求包 * @return 操做結果 * @throws Exception */ ResultObject refundWXPay(WXPayVO payVO) throws Exception; /** * 退款查詢 * 退款有必定延時,用零錢支付的退款20分鐘內到帳,銀行卡支付的退款3個工做往後從新查詢退款狀態 * @param refundOrderId 退款單號 * @return 退款詳情 * @throws Exception */ ResultObject searchRefundWXPay(String refundOrderId) throws Exception; }
3.ServiceImp層java
package com.readygo.pet.service.impl; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.SortedMap; import java.util.TreeMap; import javax.servlet.http.HttpServletRequest; import org.apache.commons.lang.StringUtils; import org.apache.log4j.Logger; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import com.readygo.pet.common.ConfigReader; import com.readygo.pet.common.Constant; import com.readygo.pet.common.ResultObject; import com.readygo.pet.mapper.WXPayCloseRecordMapper; import com.readygo.pet.mapper.WXPayOrderRecordMapper; import com.readygo.pet.mapper.WXPayRecordMapper; import com.readygo.pet.mapper.WXPayRefundRecordMapper; import com.readygo.pet.model.WXPayCloseRecord; import com.readygo.pet.model.WXPayOrderRecord; import com.readygo.pet.model.WXPayRecord; import com.readygo.pet.model.WXPayRefundRecord; import com.readygo.pet.service.WXPayDoService; import com.readygo.pet.service.WXPayService; import com.readygo.pet.utils.DesUtil; import com.readygo.pet.utils.HttpRequestUtils; import com.readygo.pet.utils.WXPayUniqueCodeUtils; import com.readygo.pet.utils.WXPayUtils; import com.readygo.pet.vo.WXPayOrderResponseParam; import com.readygo.pet.vo.WXPayRefundResponseParam; import com.readygo.pet.vo.WXPaySearchResponseParam; import com.readygo.pet.vo.WXPayVO; /** * 程序名 WXPayServiceImpl.java * 程序功能 微信支付處理實現 * 包含下預支付單、支付回調、查詢支付結果、關閉支付單、申請退款、退款查詢操做 * 做成者 xx * 做成日期 2016-04-27 * 修改履歷 * 項目名 狀態 做成者 做成日期 * -------------------------------------------- * pets 新規 xx 2016-04-27 */ @Service public class WXPayServiceImpl implements WXPayService{ private final static String PID = "WXP0001WBS001"; private Logger rootLogger=Logger.getRootLogger(); @Autowired private ConfigReader configReader; @Autowired private WXPayOrderRecordMapper wxPayOrderRecordMapper; @Autowired private WXPayRecordMapper wxPayRecordMapper; @Autowired private WXPayCloseRecordMapper wxPayCloseRecordMapper; @Autowired private WXPayRefundRecordMapper wxPayRefundRecordMapper; @Autowired private WXPayUniqueCodeUtils uniqueCodeUtils; @Autowired private WXPayDoService wxPayDoService; /** * 發起微信支付 * @param payVO 支付訂單信息 * @param request 支付請求 * @return 帶簽名的客戶端支付信息 */ public ResultObject doWXPay(WXPayVO payVO, HttpServletRequest request) throws Exception{ ResultObject resultObject = new ResultObject(); resultObject.setResultCount("1"); WXPayOrderResponseParam wxPayResponseParam = new WXPayOrderResponseParam(); WXPayOrderRecord wxPayOrderRecord = new WXPayOrderRecord(); SortedMap<String,Object> paramters = new TreeMap<String,Object>(); /**1 設置傳遞的參數 */ // 應用ID paramters.put("appid", configReader.getWxAppID()); // 商品描述 paramters.put("body", payVO.getGoodsName()); // 商戶號 paramters.put("mch_id", configReader.getWxShopId()); // 隨機字符串 paramters.put("nonce_str", WXPayUtils.getRandomString(32)); // 通知地址(回調) paramters.put("notify_url", configReader.getWxCallBackPath()); // 商戶訂單號 paramters.put("out_trade_no", payVO.getOrderId()); // 終端IP paramters.put("spbill_create_ip", WXPayUtils.getIpAddr(request)); // 交易類型 paramters.put("trade_type", "APP"); // 總金額(分) paramters.put("total_fee", payVO.getPrice()); /**1.1 設置簽名sign */ paramters.put("sign", WXPayUtils.createSign("UTF-8", paramters, DesUtil.decrypt(configReader.getWxAPIKey()))); rootLogger.info("[微信支付][預支付]生成的簽名爲:" + paramters.get("sign")); // 設置發送時間 wxPayOrderRecord.setSendTime(WXPayUtils.getSysTime()); /**2 發送HTTPS請求獲取帶簽名預支付信息 */ String requestParamterStr = WXPayUtils.map2xmlBody(paramters, "xml"); //.replace("<?xml version=\"1.0\" encoding=\"UTF-8\"?>", ""); rootLogger.info("[微信支付][預支付]申請微信預支付單參數爲:" + requestParamterStr); HttpRequestUtils httpRequest = new HttpRequestUtils(); String responseStr = httpRequest.httpsRequest(configReader.getWxPayURL(), "POST", requestParamterStr); rootLogger.info("[微信支付][預支付]微信支付返回:" + responseStr); // 設置接收時間 wxPayOrderRecord.setRecvTime(WXPayUtils.getSysTime()); /** 3 將回傳的數據轉爲map */ Map<String, String> responseMap = WXPayUtils.parseXml(responseStr); String return_code = responseMap.get("return_code"); /** 4設置記錄到數據庫的數據 */ wxPayOrderRecord.setSendAppid(configReader.getWxAppID()); wxPayOrderRecord.setSendBody(payVO.getGoodsName()); wxPayOrderRecord.setSendMchId(configReader.getWxShopId()); wxPayOrderRecord.setSendNonceStr(paramters.get("nonce_str").toString()); wxPayOrderRecord.setSendNotifyUrl(configReader.getWxCallBackPath()); wxPayOrderRecord.setSendOutTradeNo(payVO.getOrderId()); wxPayOrderRecord.setSendSpbillCreateIp(paramters.get("spbill_create_ip").toString()); wxPayOrderRecord.setSendTradeType("APP"); wxPayOrderRecord.setSendTotalFee(payVO.getPrice().toString()); wxPayOrderRecord.setSendSgin(paramters.get("sign").toString()); wxPayOrderRecord.setAddUid(payVO.getUserId()); wxPayOrderRecord.setUpdUid(payVO.getUserId()); wxPayOrderRecord.setRecvReturnCode(responseMap.get("return_code")); wxPayOrderRecord.setRecvReturnMsg(responseMap.get("return_msg")); // 判斷下單是否成功 if(StringUtils.isNotEmpty(return_code) && "SUCCESS".equals(return_code)){ String return_msg = responseMap.get("return_msg"); if(StringUtils.isNotEmpty(return_msg) && !"OK".equals(return_msg)){ rootLogger.error("[微信支付][預支付]統一下單錯誤,錯誤碼是:" + responseMap.get("err_code") + ",錯誤信息爲:" + responseMap.get("err_code_des")); resultObject.setResultCode(Constant.ResultCode.FAILED.getType()); resultObject.setResultMsg(responseMap.get("err_code_des")); resultObject.setData(wxPayResponseParam); // 插入預支付記錄 if(!insertWXPayOrderRecord(wxPayOrderRecord)){ rootLogger.error("[微信支付][預支付]1統一下單預支付記錄插入失敗!"); } return resultObject; } }else{ rootLogger.error("[微信支付][預支付]統一下單錯誤,錯誤信息爲:" + responseMap.get("return_msg")); resultObject.setResultCode(Constant.ResultCode.FAILED.getType()); resultObject.setResultMsg("統一下單錯誤.錯誤信息爲:" + responseMap.get("return_msg")); resultObject.setData(wxPayResponseParam); // 插入預支付記錄 if(!insertWXPayOrderRecord(wxPayOrderRecord)){ rootLogger.error("[微信支付][預支付]2統一下單預支付記錄插入失敗!"); } return resultObject; } wxPayOrderRecord.setRecvAppid(responseMap.get("appid")); wxPayOrderRecord.setRecvMchId(responseMap.get("mch_id")); wxPayOrderRecord.setRecvNonceStr(responseMap.get("nonce_str")); wxPayOrderRecord.setRecvSgin(responseMap.get("sign")); wxPayOrderRecord.setRecvResultCode(responseMap.get("result_code")); wxPayOrderRecord.setRecvErrCode(responseMap.get("err_code")); wxPayOrderRecord.setRecvErrCodeDes(responseMap.get("err_code_des")); wxPayOrderRecord.setRecvTradeType(responseMap.get("trade_type")); wxPayOrderRecord.setRecvPrepayId(responseMap.get("prepay_id")); if("SUCCESS".equals(responseMap.get("result_code"))){ // 應用ID wxPayResponseParam.setAppid(responseMap.get("appid")); // 商戶號 wxPayResponseParam.setPartnerid(responseMap.get("mch_id")); // 預支付ID wxPayResponseParam.setPrepayid(responseMap.get("prepay_id")); // 擴展字段 wxPayResponseParam.setMyPackage("Sign=WXPay"); // 隨機字符串 wxPayResponseParam.setNoncestr(WXPayUtils.getRandomString(32)); // 時間戳 wxPayResponseParam.setTimestamp(Long.toString(System.currentTimeMillis()/1000)); // 簽名 SortedMap<String,Object> paramtersTmp = new TreeMap<String,Object>(); paramtersTmp.put("appid", responseMap.get("appid")); paramtersTmp.put("noncestr", wxPayResponseParam.getNoncestr()); paramtersTmp.put("package", "Sign=WXPay"); paramtersTmp.put("partnerid", responseMap.get("mch_id")); paramtersTmp.put("prepayid", responseMap.get("prepay_id")); paramtersTmp.put("timestamp", wxPayResponseParam.getTimestamp()); String outSign = WXPayUtils.createSign("UTF-8", paramtersTmp, DesUtil.decrypt(configReader.getWxAPIKey())); rootLogger.info("[微信支付][預支付]返回前臺的簽名爲:" + outSign); wxPayResponseParam.setSign(outSign); resultObject.setResultCode(Constant.ResultCode.SUCCESS.getType()); resultObject.setResultMsg("[微信支付][預支付]統一下單成功。"); resultObject.setData(wxPayResponseParam); }else{ resultObject.setResultCode(Constant.ResultCode.FAILED.getType()); resultObject.setResultMsg("統一下單錯誤.錯誤信息爲:" + responseMap.get("err_code_des")); resultObject.setData(wxPayResponseParam); } if(!insertWXPayOrderRecord(wxPayOrderRecord)){ rootLogger.error("[微信支付][預支付]4統一下單預支付記錄插入失敗!"); } /**4 返回前端 */ return resultObject; } /** * 微信支付回調 * @param request 發起支付的請求 * @return 返給微信服務器接收結果 */ public String callBackWXPay(HttpServletRequest request) throws Exception{ String inputLine; String notityXml = ""; Map<String, Object> retMap = new HashMap<String, Object>(); WXPayRecord wxPayRecord = new WXPayRecord(); // 取出回調中的數據 while ((inputLine = request.getReader().readLine()) != null) { notityXml += inputLine; } request.getReader().close(); rootLogger.info("[微信支付][回調]接收到的報文:" + notityXml); // 將傳回數據轉化成map方便讀取 SortedMap<String, String> responseMap = WXPayUtils.parseXml(notityXml); String return_code = responseMap.get("return_code"); wxPayRecord.setRecvReturnCode(responseMap.get("return_code")); wxPayRecord.setRecvReturnMsg(responseMap.get("return_msg")); // 判斷支付是否成功 if(StringUtils.isNotEmpty(return_code) && "SUCCESS".equals(return_code)){ String return_msg = responseMap.get("return_msg"); if(StringUtils.isNotEmpty(return_msg) && !"OK".equals(return_msg)){ rootLogger.error("[微信支付][回調]支付失敗,錯誤碼是:" + responseMap.get("err_code") + ",錯誤信息爲:" + responseMap.get("err_code_des")); // 正確接收到了返回,給微信服務器返回接收成功 retMap.put("return_code", "SUCCESS"); retMap.put("return_msg", "OK"); wxPayRecord.setSendReturnCode("SUCCESS"); wxPayRecord.setSendReturnMsg("OK"); // 將支付憑證等消息存入本地數據庫以備用 if(!insertWXPayRecord(wxPayRecord)){ rootLogger.error("[微信支付][回調]1插入數據庫失敗,具體數據爲:" + notityXml); } return WXPayUtils.map2xmlBody(retMap, "xml"); } }else{ System.err.println("[微信支付][回調]支付失敗。失敗緣由:" + responseMap.get("return_msg")); // 正確接收到了返回,給微信服務器返回接收成功 retMap.put("return_code", "SUCCESS"); retMap.put("return_msg", "OK"); wxPayRecord.setSendReturnCode("SUCCESS"); wxPayRecord.setSendReturnMsg("OK"); // 將支付憑證等消息存入本地數據庫以備用 if(!insertWXPayRecord(wxPayRecord)){ rootLogger.error("[微信支付][回調]2插入數據庫失敗,具體數據庫爲:" + notityXml); } return WXPayUtils.map2xmlBody(retMap, "xml"); } // 微信規定,其餘參數在return_code爲SUCCESS的時候有返回,所以在以上判斷OK的狀況下進行如下操做 wxPayRecord = setParam(responseMap); // 將支付憑證等消息存入本地數據庫以備用 if(!insertWXPayRecord(wxPayRecord)){ rootLogger.error("[微信支付][回調]插入數據庫失敗,具體數據庫爲:" + notityXml); } // 檢查參數是否有效 String retMsg = ""; if(!checkCallBackValidate(wxPayRecord, responseMap, retMsg)){ // 正確接收到了返回,校驗失敗,以錯誤形式返給微信服務器 retMap.put("return_code", "FAIL"); retMap.put("return_msg", retMsg); wxPayRecord.setSendReturnCode("FAIL"); wxPayRecord.setSendReturnMsg(retMsg); rootLogger.error("[微信支付][回調]傳遞參數有效驗證錯誤,錯誤信息爲:" + retMsg); }else{ // 根據支付結果更新訂單數據或其餘相關表數據操做 if("SUCCESS".equals(wxPayRecord.getRecvResultCode())){ System.out.println("[微信支付][回調]微信支付成功。"); // TODO 這裏根據支付結果添加業務處理 payOrderDo() if(!wxPayDoService.payOrderDo(wxPayRecord.getRecvOutTradeNo(), wxPayRecord)){ rootLogger.error("[微信支付][回調]業務處理失敗。"); }else{ rootLogger.info("[微信支付][回調]業務處理成功。"); } }else{ rootLogger.error("[微信支付][回調]微信支付失敗。錯誤碼爲:" + wxPayRecord.getRecvErrCode() + ",錯誤描述爲:" + wxPayRecord.getRecvErrCodeDes()); // 支付失敗,不更新訂單信息 } // 正確接收到了返回,給微信服務器返回接收成功 retMap.put("return_code", "SUCCESS"); retMap.put("return_msg", "OK"); wxPayRecord.setSendReturnCode("SUCCESS"); wxPayRecord.setSendReturnMsg("OK"); } return WXPayUtils.map2xmlBody(retMap, "xml"); } /** * 查詢微信支付結果 * @param orderId 內部訂單ID(非微信支付id) * @param request 請求包 * @return 查詢結果 * @throws Exception */ public ResultObject searchWXPay(String orderId) throws Exception{ rootLogger.info("[微信支付][查詢]======開始"); ResultObject resultObject = new ResultObject(); // 查詢所用的參數map SortedMap<String,Object> paramters = new TreeMap<String,Object>(); WXPaySearchResponseParam wxPaySearchResponseParam = new WXPaySearchResponseParam(); /**1 設置傳遞的參數 */ // 應用ID paramters.put("appid", configReader.getWxAppID()); // 商戶號 paramters.put("mch_id", configReader.getWxShopId()); // 商戶訂單號 paramters.put("out_trade_no", orderId); // 隨機字符串 paramters.put("nonce_str", WXPayUtils.getRandomString(32)); /**1.1 設置簽名sign */ paramters.put("sign", WXPayUtils.createSign("UTF-8", paramters, DesUtil.decrypt(configReader.getWxAPIKey()))); rootLogger.info("[微信支付][查詢]生成的簽名爲:" + paramters.get("sign")); /**2 發送HTTPS請求獲取支付詳細信息 */ String requestParamterStr = WXPayUtils.map2xmlBody(paramters, "xml"); //.replace("<?xml version=\"1.0\" encoding=\"UTF-8\"?>", ""); rootLogger.info("[微信支付][查詢]支付訂單查詢參數爲:" + requestParamterStr); HttpRequestUtils httpRequest = new HttpRequestUtils(); String responseStr = httpRequest.httpsRequest(configReader.getWxPaySearchURL(), "POST", requestParamterStr); rootLogger.info("[微信支付][查詢]支付訂單查詢結果爲:" + responseStr); /** 3 將回傳的數據轉爲map */ Map<String, String> responseMap = WXPayUtils.parseXml(responseStr); String return_code = responseMap.get("return_code"); // 判斷查詢是否成功 if(StringUtils.isNotEmpty(return_code) && "SUCCESS".equals(return_code)){ String return_msg = responseMap.get("return_msg"); if(StringUtils.isNotEmpty(return_msg) && !"OK".equals(return_msg)){ rootLogger.error("[微信支付][查詢]支付訂單查詢失敗,錯誤碼是:" + responseMap.get("err_code") + ",錯誤信息爲:" + responseMap.get("err_code_des")); resultObject.setResultCode(WXPayUtils.ResultCode.FAILED.getType()); resultObject.setResultMsg(responseMap.get("err_code_des")); resultObject.setData(wxPaySearchResponseParam); rootLogger.error("[微信支付][查詢]======結束(錯誤1)"); return resultObject; } }else{ rootLogger.error("[微信支付][查詢]支付訂單查詢錯誤,錯誤信息爲:" + responseMap.get("return_msg")); resultObject.setResultCode(WXPayUtils.ResultCode.FAILED.getType()); resultObject.setResultMsg("支付訂單查詢錯誤.錯誤信息爲:" + responseMap.get("return_msg")); resultObject.setData(wxPaySearchResponseParam); rootLogger.error("[微信支付][查詢]======結束(錯誤2)"); return resultObject; } // 設置返回數據 // 應用ID wxPaySearchResponseParam.setAppid(responseMap.get("appid")); wxPaySearchResponseParam.setMch_id(responseMap.get("mch_id")); wxPaySearchResponseParam.setNonce_str(responseMap.get("nonce_str")); wxPaySearchResponseParam.setSign(responseMap.get("sign")); wxPaySearchResponseParam.setResult_code(responseMap.get("result_code")); wxPaySearchResponseParam.setErr_code(responseMap.get("err_code")); wxPaySearchResponseParam.setErr_code_des(responseMap.get("err_code_des")); String result_code = responseMap.get("result_code"); if("SUCCESS".equals(result_code)){ wxPaySearchResponseParam.setOpenid(responseMap.get("openid")); wxPaySearchResponseParam.setTrade_type(responseMap.get("trade_type")); wxPaySearchResponseParam.setTrade_state(responseMap.get("trade_state")); wxPaySearchResponseParam.setBank_type(responseMap.get("bank_type")); wxPaySearchResponseParam.setTotal_fee(responseMap.get("total_fee")); wxPaySearchResponseParam.setFee_type(responseMap.get("fee_type")); wxPaySearchResponseParam.setCash_fee(responseMap.get("cash_fee")); wxPaySearchResponseParam.setCash_fee_type(responseMap.get("cash_fee_type")); wxPaySearchResponseParam.setTransaction_id(responseMap.get("transaction_id")); wxPaySearchResponseParam.setOut_trade_no(responseMap.get("out_trade_no")); wxPaySearchResponseParam.setTime_end(responseMap.get("time_end")); wxPaySearchResponseParam.setTrade_state_desc(responseMap.get("trade_state_desc")); } // TODO 這裏能夠根據查詢結果進行其餘處理 searchOrderDo() if(!wxPayDoService.searchOrderDo(orderId, wxPaySearchResponseParam)){ rootLogger.error("[微信支付][查詢]業務處理失敗。"); }else{ rootLogger.info("[微信支付][查詢]業務處理成功。"); } /**4 返回前端 */ resultObject.setResultCode(WXPayUtils.ResultCode.SUCCESS.getType()); resultObject.setResultMsg("[微信支付][查詢]支付訂單查詢成功。"); resultObject.setData(wxPaySearchResponseParam); rootLogger.info("[微信支付][查詢]======結束"); return resultObject; } /** * 關閉微信支付訂單 * 如下狀況須要調用關單接口:商戶訂單支付失敗須要生成新單號從新發起支付,要對原訂單號調用關單, * 避免重複支付;系統下單後,用戶支付超時,系統退出再也不受理,避免用戶繼續,請調用關單接口 * 注意:訂單生成後不能立刻調用關單接口,最短調用時間間隔爲5分鐘 * @param orderId 訂單編號 * @param request 請求包 * @return 執行結果 * @throws Exception */ public ResultObject closeWXPay(String orderId) throws Exception{ rootLogger.info("[微信支付][關閉]======開始"); ResultObject resultObject = new ResultObject(); resultObject.setResultCount("0"); // 查詢所用的參數map SortedMap<String,Object> paramters = new TreeMap<String,Object>(); WXPayCloseRecord wxPayCloseRecord = new WXPayCloseRecord(); /**1 設置傳遞的參數 */ // 應用ID paramters.put("appid", configReader.getWxAppID()); wxPayCloseRecord.setSendAppid(configReader.getWxAppID()); // 商戶號 paramters.put("mch_id", configReader.getWxShopId()); wxPayCloseRecord.setSendMchId(configReader.getWxShopId()); // 商戶訂單號 paramters.put("out_trade_no", orderId); wxPayCloseRecord.setSendOutTradeNo(orderId); // 隨機字符串 paramters.put("nonce_str", WXPayUtils.getRandomString(32)); wxPayCloseRecord.setSendNonceStr(paramters.get("nonce_str").toString()); /**1.1 設置簽名sign */ paramters.put("sign", WXPayUtils.createSign("UTF-8", paramters, DesUtil.decrypt(configReader.getWxAPIKey()))); wxPayCloseRecord.setSendSgin(paramters.get("sign").toString()); rootLogger.info("[微信支付][關閉]生成的簽名爲:" + paramters.get("sign")); // 設置發送時間 wxPayCloseRecord.setSendTime(WXPayUtils.getSysTime()); /**2 發送HTTPS請求獲取關閉支付信息 */ String requestParamterStr = WXPayUtils.map2xmlBody(paramters, "xml"); //.replace("<?xml version=\"1.0\" encoding=\"UTF-8\"?>", ""); rootLogger.info("[微信支付][關閉]支付訂單關閉參數爲:" + requestParamterStr); HttpRequestUtils httpRequest = new HttpRequestUtils(); String responseStr = httpRequest.httpsRequest(configReader.getWxPayCloseURL(), "POST", requestParamterStr); rootLogger.info("[微信支付][關閉]支付訂單關閉結果爲:" + responseStr); // 設置發送時間 wxPayCloseRecord.setRecvTime(WXPayUtils.getSysTime()); /** 3 將回傳的數據轉爲map */ Map<String, String> responseMap = WXPayUtils.parseXml(responseStr); String return_code = responseMap.get("return_code"); wxPayCloseRecord.setRecvReturnCode(return_code); wxPayCloseRecord.setRecvReturnMsg(responseMap.get("return_msg")); // 判斷支付訂單關閉是否成功 if(StringUtils.isNotEmpty(return_code) && "SUCCESS".equals(return_code)){ String return_msg = responseMap.get("return_msg"); if(StringUtils.isNotEmpty(return_msg) && !"OK".equals(return_msg)){ rootLogger.error("[微信支付][關閉]支付訂單關閉失敗,錯誤碼是:" + responseMap.get("err_code") + ",錯誤信息爲:" + responseMap.get("err_code_des")); resultObject.setResultCode(WXPayUtils.ResultCode.FAILED.getType()); resultObject.setResultMsg(responseMap.get("err_code_des")); resultObject.setData(wxPayCloseRecord); wxPayCloseRecord.setRecvErrCode(responseMap.get("err_code")); wxPayCloseRecord.setRecvErrCodeDes(responseMap.get("err_code_des")); // 插入微信關閉記錄 if(!insertWXPayCloseRecord(wxPayCloseRecord)){ rootLogger.error("[微信支付][關閉]1支付關閉記錄插入失敗!"); } rootLogger.error("[微信支付][關閉]======結束(錯誤1)"); return resultObject; } }else{ rootLogger.error("[微信支付][關閉]支付訂單關閉錯誤,錯誤信息爲:" + responseMap.get("return_msg")); resultObject.setResultCode(WXPayUtils.ResultCode.FAILED.getType()); resultObject.setResultMsg("支付訂單關閉錯誤.錯誤信息爲:" + responseMap.get("return_msg")); resultObject.setData(wxPayCloseRecord); // 插入微信關閉記錄 if(!insertWXPayCloseRecord(wxPayCloseRecord)){ rootLogger.error("[微信支付][關閉]2支付關閉記錄插入失敗!"); } rootLogger.error("[微信支付][關閉]======結束(錯誤2)"); return resultObject; } // 設置返回數據 wxPayCloseRecord.setRecvAppid(responseMap.get("appid")); wxPayCloseRecord.setRecvMchId(responseMap.get("mch_id")); wxPayCloseRecord.setRecvNonceStr(responseMap.get("nonce_str")); wxPayCloseRecord.setRecvSgin(responseMap.get("sign")); wxPayCloseRecord.setRecvErrCode(responseMap.get("err_code")); wxPayCloseRecord.setRecvErrCodeDes(responseMap.get("err_code_des")); // 插入微信關閉記錄 if(!insertWXPayCloseRecord(wxPayCloseRecord)){ rootLogger.error("[微信支付][關閉]3支付關閉記錄插入失敗!"); } // TODO 這裏能夠根據關閉結果進行訂單處理 closeOrderDo() if(!wxPayDoService.closeOrderDo(orderId, wxPayCloseRecord)){ rootLogger.error("[微信支付][關閉]業務處理失敗。"); }else{ rootLogger.info("[微信支付][關閉]業務處理成功。"); } /**4 返回前端 */ resultObject.setResultCode(WXPayUtils.ResultCode.SUCCESS.getType()); resultObject.setResultMsg("支付訂單關閉成功。"); resultObject.setResultCount("1"); resultObject.setData(wxPayCloseRecord); rootLogger.info("[微信支付][關閉]======結束"); return resultObject; } /** * 申請退款 * 注意:一、交易時間超過一年的訂單沒法提交退款; * 二、微信支付退款支持單筆交易分屢次退款,屢次退款須要提交原支付訂單的商戶訂單號和設置不一樣的退款單號。 * 一筆退款失敗後從新提交,要採用原來的退款單號。總退款金額不能超過用戶實際支付金額。 * @param payVO 退款信息 * @param request 請求包 * @return 操做結果 * @throws Exception */ public ResultObject refundWXPay(WXPayVO payVO) throws Exception{ rootLogger.info("[微信支付][退款]======開始"); ResultObject resultObject = new ResultObject(); resultObject.setResultCount("0"); WXPayRefundRecord wxPayRefundRecord = new WXPayRefundRecord(); // 查詢所用的參數map SortedMap<String,Object> paramters = new TreeMap<String,Object>(); // 應用ID paramters.put("appid", configReader.getWxAppID()); wxPayRefundRecord.setSendAppid(configReader.getWxAppID()); // 商戶號 paramters.put("mch_id", configReader.getWxShopId()); wxPayRefundRecord.setSendMchId(configReader.getWxShopId()); // 隨機字符串 paramters.put("nonce_str", WXPayUtils.getRandomString(32)); wxPayRefundRecord.setSendNonceStr(paramters.get("nonce_str").toString()); // 商戶訂單號 paramters.put("out_trade_no", payVO.getOrderId()); wxPayRefundRecord.setSendOutTradeNo(payVO.getOrderId()); // 商戶退款單號 paramters.put("out_refund_no", payVO.getRefundOrderId()); wxPayRefundRecord.setSendOutRefundNo(payVO.getRefundOrderId()); // 總金額(分) paramters.put("total_fee", payVO.getPrice()); wxPayRefundRecord.setSendTotalFee(String.valueOf(payVO.getPrice())); // 退款金額(分) paramters.put("refund_fee", payVO.getRefundPrice()); wxPayRefundRecord.setSendRefundFee(String.valueOf(payVO.getRefundPrice())); // 貨幣種類 paramters.put("refund_fee_type", "CNY"); wxPayRefundRecord.setSendRefundFeeType("CNY"); // 操做員(默認爲商戶號) paramters.put("op_user_id", configReader.getWxShopId()); wxPayRefundRecord.setSendOpUserId(configReader.getWxShopId()); /**1.1 設置簽名sign */ paramters.put("sign", WXPayUtils.createSign("UTF-8", paramters, DesUtil.decrypt(configReader.getWxAPIKey()))); wxPayRefundRecord.setSendSgin(paramters.get("sign").toString()); rootLogger.info("[微信支付][退款]生成的簽名爲:" + paramters.get("sign")); // 設置發送時間 wxPayRefundRecord.setSendTime(WXPayUtils.getSysTime()); /**2 發送HTTPS請求獲取退款結果信息 */ String requestParamterStr = WXPayUtils.map2xmlBody(paramters, "xml"); //.replace("<?xml version=\"1.0\" encoding=\"UTF-8\"?>", ""); rootLogger.info("[微信支付][退款]訂單退款參數爲:" + requestParamterStr); // 該請求須要證書,需放置本地p12證書 String responseStr = WXPayUtils.httpsRequestWithCert(configReader.getWxPayRefundURL() , requestParamterStr, configReader.getWxCertPath(), configReader.getWxShopId()); rootLogger.info("[微信支付][退款]訂單退款結果爲:" + responseStr); // 設置接收時間 wxPayRefundRecord.setRecvTime(WXPayUtils.getSysTime()); /** 3 將回傳的數據轉爲map */ Map<String, String> responseMap = WXPayUtils.parseXml(responseStr); String return_code = responseMap.get("return_code"); wxPayRefundRecord.setRecvReturnCode(return_code); wxPayRefundRecord.setRecvReturnMsg(responseMap.get("return_msg")); // 判斷退款是否成功 if(StringUtils.isNotEmpty(return_code) && "SUCCESS".equals(return_code)){ String return_msg = responseMap.get("return_msg"); if(StringUtils.isNotEmpty(return_msg) && !"OK".equals(return_msg)){ rootLogger.error("[微信支付][退款]支付訂單退款失敗,錯誤碼是:" + responseMap.get("err_code") + ",錯誤信息爲:" + responseMap.get("err_code_des")); resultObject.setResultCode(WXPayUtils.ResultCode.FAILED.getType()); resultObject.setResultMsg(responseMap.get("err_code_des")); resultObject.setData(wxPayRefundRecord); wxPayRefundRecord.setRecvErrCode(responseMap.get("err_code")); wxPayRefundRecord.setRecvErrCodeDes(responseMap.get("err_code_des")); // 插入微信退款記錄 if(!insertWXPayRefundRecord(wxPayRefundRecord)){ rootLogger.error("[微信支付][退款]1支付退款記錄插入失敗!"); } rootLogger.error("[微信支付][退款]======結束(錯誤1)"); return resultObject; } }else{ rootLogger.error("[微信支付][退款]訂單退款錯誤,錯誤信息爲:" + responseMap.get("return_msg")); resultObject.setResultCode(WXPayUtils.ResultCode.FAILED.getType()); resultObject.setResultMsg("支付訂單退款錯誤.錯誤信息爲:" + responseMap.get("return_msg")); resultObject.setData(wxPayRefundRecord); // 插入微信退款記錄 if(!insertWXPayRefundRecord(wxPayRefundRecord)){ rootLogger.error("[微信支付][退款]2支付退款記錄插入失敗!"); } rootLogger.info("[微信支付][退款]======結束(錯誤2)"); return resultObject; } // 設置返回數據 wxPayRefundRecord.setRecvAppid(responseMap.get("err_code")); wxPayRefundRecord.setRecvAppid(responseMap.get("mch_id")); wxPayRefundRecord.setRecvAppid(responseMap.get("nonce_str")); wxPayRefundRecord.setRecvAppid(responseMap.get("sign")); wxPayRefundRecord.setRecvAppid(responseMap.get("transaction_id")); wxPayRefundRecord.setRecvAppid(responseMap.get("out_trade_no")); wxPayRefundRecord.setRecvAppid(responseMap.get("out_refund_no")); wxPayRefundRecord.setRecvAppid(responseMap.get("refund_id")); wxPayRefundRecord.setRecvAppid(responseMap.get("refund_channel")); wxPayRefundRecord.setRecvAppid(responseMap.get("refund_fee")); wxPayRefundRecord.setRecvAppid(responseMap.get("total_fee")); wxPayRefundRecord.setRecvAppid(responseMap.get("fee_type")); wxPayRefundRecord.setRecvAppid(responseMap.get("cash_fee")); wxPayRefundRecord.setRecvAppid(responseMap.get("cash_refund_fee")); // 插入微信退款記錄 if(!insertWXPayRefundRecord(wxPayRefundRecord)){ rootLogger.error("[微信支付][退款]3支付退款記錄插入失敗!"); } // TODO 這裏能夠根據退款申請結果進行訂單處理 refundOrderDo() if(!wxPayDoService.refundOrderDo(payVO.getRefundOrderId(), wxPayRefundRecord)){ rootLogger.error("[微信支付][退款]業務處理失敗。"); }else{ rootLogger.info("[微信支付][退款]業務處理成功。"); } /**4 返回前端 */ resultObject.setResultCode(WXPayUtils.ResultCode.SUCCESS.getType()); resultObject.setResultMsg("訂單退款成功。"); resultObject.setResultCount("1"); resultObject.setData(wxPayRefundRecord); rootLogger.info("[微信支付][退款]======結束"); return resultObject; } /** * 退款查詢 * 退款有必定延時,用零錢支付的退款20分鐘內到帳,銀行卡支付的退款3個工做往後從新查詢退款狀態 * @param refundOrderId 退款單號 * @return 退款詳情 * @throws Exception */ public ResultObject searchRefundWXPay(String refundOrderId) throws Exception{ rootLogger.info("[微信支付][退款查詢]======開始"); ResultObject resultObject = new ResultObject(); resultObject.setResultCount("0"); WXPayRefundResponseParam wxPayRefundResponseParam = new WXPayRefundResponseParam(); // 查詢所用的參數map SortedMap<String,Object> paramters = new TreeMap<String,Object>(); paramters.put("appid", configReader.getWxAppID()); paramters.put("mch_id", configReader.getWxShopId()); paramters.put("nonce_str", WXPayUtils.getRandomString(32)); paramters.put("out_refund_no", refundOrderId); /**1.1 設置簽名sign */ paramters.put("sign", WXPayUtils.createSign("UTF-8", paramters, DesUtil.decrypt(configReader.getWxAPIKey()))); rootLogger.info("[微信支付][退款查詢]生成的簽名爲:" + paramters.get("sign")); /**2 發送HTTPS請求獲取退款信息 */ String requestParamterStr = WXPayUtils.map2xmlBody(paramters, "xml"); //.replace("<?xml version=\"1.0\" encoding=\"UTF-8\"?>", ""); rootLogger.info("[微信支付][退款查詢]訂單退款查詢參數爲:" + requestParamterStr); HttpRequestUtils httpRequest = new HttpRequestUtils(); String responseStr = httpRequest.httpsRequest(configReader.getWxPayRefundSearchURL(), "POST", requestParamterStr); rootLogger.info("[微信支付][退款查詢]訂單退款查詢結果爲:" + responseStr); /** 3 將回傳的數據轉爲map */ Map<String, String> responseMap = WXPayUtils.parseXml(responseStr); String return_code = responseMap.get("return_code"); String return_msg = responseMap.get("return_msg"); wxPayRefundResponseParam.setReturn_code(return_code); wxPayRefundResponseParam.setReturn_msg(return_msg); // 判斷退款是否成功 if(StringUtils.isNotEmpty(return_code) && "SUCCESS".equals(return_code)){ if(StringUtils.isNotEmpty(return_msg) && !"OK".equals(return_msg)){ rootLogger.error("[微信支付][退款查詢]訂單退款查詢失敗,錯誤碼是:" + responseMap.get("err_code") + ",錯誤信息爲:" + responseMap.get("err_code_des")); wxPayRefundResponseParam.setResult_code(responseMap.get("result_code")); wxPayRefundResponseParam.setErr_code(responseMap.get("err_code")); wxPayRefundResponseParam.setErr_code_des(responseMap.get("err_code_des")); resultObject.setResultCode(WXPayUtils.ResultCode.FAILED.getType()); resultObject.setResultMsg(responseMap.get("err_code_des")); resultObject.setData(wxPayRefundResponseParam); rootLogger.error("[微信支付][退款查詢]======結束(錯誤1)"); return resultObject; } }else{ rootLogger.error("[微信支付][退款查詢]訂單退款查詢錯誤,錯誤信息爲:" + responseMap.get("return_msg")); resultObject.setResultCode(WXPayUtils.ResultCode.FAILED.getType()); resultObject.setResultMsg("訂單退款查詢錯誤.錯誤信息爲:" + responseMap.get("return_msg")); resultObject.setData(wxPayRefundResponseParam); rootLogger.error("[微信支付][退款查詢]======結束(錯誤2)"); return resultObject; } // 設置返回類屬性值 wxPayRefundResponseParam.setResult_code(responseMap.get("result_code")); wxPayRefundResponseParam.setErr_code(responseMap.get("err_code_des")); wxPayRefundResponseParam.setResult_code(responseMap.get("result_code")); if("SUCCESS".equals(responseMap.get("result_code"))){ wxPayRefundResponseParam.setAppid(responseMap.get("appid")); wxPayRefundResponseParam.setMch_id(responseMap.get("mch_id")); wxPayRefundResponseParam.setNonce_str(responseMap.get("nonce_str")); wxPayRefundResponseParam.setSign(responseMap.get("sign")); wxPayRefundResponseParam.setTransaction_id(responseMap.get("transaction_id")); wxPayRefundResponseParam.setOut_trade_no(responseMap.get("out_trade_no")); wxPayRefundResponseParam.setTotal_fee(responseMap.get("total_fee")); wxPayRefundResponseParam.setFee_type(responseMap.get("fee_type")); wxPayRefundResponseParam.setCash_fee(responseMap.get("cash_fee")); String refundCount = responseMap.get("refund_count"); wxPayRefundResponseParam.setRefund_count(refundCount); if(!StringUtils.isEmpty(refundCount)){ List<WXPayRefundResponseParam.refundInfo> infoList = new ArrayList<WXPayRefundResponseParam.refundInfo>(); for (int i = 0; i < Integer.valueOf(refundCount); i++) { WXPayRefundResponseParam.refundInfo info = new WXPayRefundResponseParam().new refundInfo(); info.setOut_refund_no(responseMap.get("out_refund_no_"+ String.valueOf(i))); info.setRefund_id(responseMap.get("refund_id_"+ String.valueOf(i))); info.setRefund_channel(responseMap.get("refund_channel_"+ String.valueOf(i))); info.setRefund_fee(responseMap.get("refund_fee_"+ String.valueOf(i))); info.setRefund_status(responseMap.get("refund_status_"+ String.valueOf(i))); info.setRefund_recv_accout(responseMap.get("refund_recv_accout_"+ String.valueOf(i))); infoList.add(info); } wxPayRefundResponseParam.setRefundInfoList(infoList); } } // TODO 這裏能夠根據查詢結果進行其餘處理 searchRefundOrderDo() if(!wxPayDoService.searchRefundOrderDo(refundOrderId, wxPayRefundResponseParam)){ rootLogger.error("[微信支付][退款]業務處理失敗。"); }else{ rootLogger.info("[微信支付][退款]業務處理成功。"); } /**4 返回前端 */ resultObject.setResultCode(WXPayUtils.ResultCode.SUCCESS.getType()); resultObject.setResultMsg("訂單退款查詢成功。"); resultObject.setResultCount("1"); resultObject.setData(wxPayRefundResponseParam); rootLogger.info("[微信支付][退款查詢]======結束"); return resultObject; } /** ===========================如下是內部私有方法=========================== */ /** * 對必須返回項進行驗證 * 對簽名進行校驗 * @param wxPayCallBackParam 接收支付數據數據類 * @param errMeg 校驗結果信息 * @return 校驗結果(TRUE/FALSE) */ private boolean checkCallBackValidate(WXPayRecord wxPayRecord, SortedMap<String, String> responseMap ,String errMeg){ boolean isOK = true; if(StringUtils.isEmpty(wxPayRecord.getRecvAppid())){ errMeg += "appid爲空|"; isOK = false; } if(StringUtils.isEmpty(wxPayRecord.getRecvMchId())){ errMeg += "mch_id爲空|"; isOK = false; } if(StringUtils.isEmpty(wxPayRecord.getRecvDeviceInfo())){ errMeg += "nonce_str爲空|"; isOK = false; } if(StringUtils.isEmpty(wxPayRecord.getRecvSgin())){ errMeg += "sign爲空|"; isOK = false; } if(StringUtils.isEmpty(wxPayRecord.getRecvResultCode())){ errMeg += "result_code爲空|"; isOK = false; } if(StringUtils.isEmpty(wxPayRecord.getRecvOpeId())){ errMeg += "openid爲空|"; isOK = false; } if(StringUtils.isEmpty(wxPayRecord.getRecvTradeType())){ errMeg += "trade_type爲空|"; isOK = false; } if(StringUtils.isEmpty(wxPayRecord.getRecvBankType())){ errMeg += "bank_type爲空|"; isOK = false; } if(wxPayRecord.getRecvTotalFee() == 0){ errMeg += "total_fee爲0|"; isOK = false; } if(wxPayRecord.getRecvCashFee() == 0){ errMeg += "cash_fee爲空|"; isOK = false; } if(StringUtils.isEmpty(wxPayRecord.getRecvTransactionId())){ errMeg += "transaction_id爲空|"; isOK = false; } if(StringUtils.isEmpty(wxPayRecord.getRecvOutTradeNo())){ errMeg += "out_trade_no爲空|"; isOK = false; } if(StringUtils.isEmpty(wxPayRecord.getRecvTimeEnd())){ errMeg += "time_end爲空|"; isOK = false; } // 簽名驗證 return isOK; } /** * 裝載數據庫須要更新的數據(支付回調用) * @param responseMap 回傳值 * @return 實體類 */ private WXPayRecord setParam(Map<String, String> responseMap){ WXPayRecord wxPayRecord = new WXPayRecord(); // 設置屬性 wxPayRecord.setRecvAppid(responseMap.get("appid")); wxPayRecord.setRecvMchId(responseMap.get("mch_id")); wxPayRecord.setRecvDeviceInfo(responseMap.get("device_info")); wxPayRecord.setRecvNonceStr(responseMap.get("nonce_str")); wxPayRecord.setRecvSgin(responseMap.get("sign")); wxPayRecord.setRecvResultCode(responseMap.get("result_code")); wxPayRecord.setRecvErrCode(responseMap.get("err_code")); wxPayRecord.setRecvErrCodeDes(responseMap.get("err_code_des")); wxPayRecord.setRecvIsSubscribe(responseMap.get("is_subscribe")); wxPayRecord.setRecvTradeType(responseMap.get("trade_type")); wxPayRecord.setRecvBankType(responseMap.get("bank_type")); wxPayRecord.setRecvTotalFee(StringUtils.isEmpty(responseMap.get("total_fee"))?0:Integer.parseInt(responseMap.get("total_fee"))); wxPayRecord.setRecvFeeType(responseMap.get("fee_type")); wxPayRecord.setRecvCashFee(StringUtils.isEmpty(responseMap.get("cash_fee"))?0:Integer.parseInt(responseMap.get("cash_fee"))); wxPayRecord.setRecvCashFeeType(responseMap.get("cash_fee_type")); wxPayRecord.setRecvCouponFee(StringUtils.isEmpty(responseMap.get("coupon_fee"))?0:Integer.parseInt(responseMap.get("coupon_fee"))); wxPayRecord.setRecvCouponCount(StringUtils.isEmpty(responseMap.get("coupon_count"))?0:Integer.parseInt(responseMap.get("coupon_count"))); wxPayRecord.setRecvTransactionId(responseMap.get("transaction_id")); wxPayRecord.setRecvOutTradeNo(responseMap.get("out_trade_no")); wxPayRecord.setRecvAttach(responseMap.get("attach")); return wxPayRecord; } /** * 插入預支付收發記錄 * @param wxPayOrderRecord 記錄信息 * @return 操做結果 */ private boolean insertWXPayOrderRecord(WXPayOrderRecord wxPayOrderRecord){ boolean isOK = true; wxPayOrderRecord.setAddPid(PID); wxPayOrderRecord.setUpdPid(PID); wxPayOrderRecord.setWxPayOrderRecordId(uniqueCodeUtils.getUniqueCode(WXPayUtils.TableType.T_WXPAY_ORDER_RECORD)); if(wxPayOrderRecordMapper.insert(wxPayOrderRecord) != 1){ // 插入不成功 isOK = false; } return isOK; } /** * 插入支付記錄 * @param wxPayCallBackParam 須要插入的數據 * @return 操做結果 */ private boolean insertWXPayRecord(WXPayRecord wxPayRecord){ boolean isOK = true; if(wxPayRecordMapper.selectCountByTransactionId(wxPayRecord.getRecvTransactionId()) > 0){ // 該數據已經處理過,跳過插入 rootLogger.warn("[微信支付]該微信支付數據已經插入,跳過處理。微信支付單號爲:" + wxPayRecord.getRecvTransactionId()); return isOK; } wxPayRecord.setAddPid(PID); wxPayRecord.setUpdPid(PID); wxPayRecord.setWxPayRecordId(uniqueCodeUtils.getUniqueCode(WXPayUtils.TableType.T_WXPAY_RECORD)); if(wxPayRecordMapper.insert(wxPayRecord) != 1){ isOK = false; } return isOK; } /** * 插入支付關閉記錄 * @param wxPayCloseRecord 須要插入的數據 * @return 操做結果 */ private boolean insertWXPayCloseRecord(WXPayCloseRecord wxPayCloseRecord){ boolean isOK = true; wxPayCloseRecord.setAddPid(PID); wxPayCloseRecord.setUpdPid(PID); wxPayCloseRecord.setWxPayCloseRecordId(uniqueCodeUtils.getUniqueCode(WXPayUtils.TableType.T_WXPAY_CLOSE_RECORD)); if(wxPayCloseRecordMapper.insert(wxPayCloseRecord) != 1){ // 插入不成功 isOK = false; } return isOK; } /** * 插入支付退款記錄 * @param wxPayRefundRecord 須要插入的數據 * @return 操做結果 */ private boolean insertWXPayRefundRecord(WXPayRefundRecord wxPayRefundRecord){ boolean isOK = true; wxPayRefundRecord.setAddPid(PID); wxPayRefundRecord.setUpdPid(PID); wxPayRefundRecord.setWxPayRefundRecordId(uniqueCodeUtils.getUniqueCode(WXPayUtils.TableType.T_WXPAY_REFUND_RECORD)); if(wxPayRefundRecordMapper.insert(wxPayRefundRecord) != 1){ // 插入不成功 isOK = false; } return isOK; } }
4.微信處理調用接口web
package com.readygo.pet.service; import com.readygo.pet.model.WXPayCloseRecord; import com.readygo.pet.model.WXPayRecord; import com.readygo.pet.model.WXPayRefundRecord; import com.readygo.pet.vo.WXPayRefundResponseParam; import com.readygo.pet.vo.WXPaySearchResponseParam; /** * 程序名 WXPayDoService.java * 程序功能 微信處理後調用業務處理接口 * 做成者 xx * 做成日期 2016-05-04 * 修改履歷 * 項目名 狀態 做成者 做成日期 * -------------------------------------------- * pets 新規 xx 2016-05-04 */ public interface WXPayDoService { /** * 微信支付成功後回調時,須要作的業務處理接口 * @param orderId 商家訂單號 * @param wxPayRecord 支付回傳結果詳情 * @return 處理成功或失敗(TRUE/FALSE) */ boolean payOrderDo(String orderId, WXPayRecord wxPayRecord) throws Exception; /** * 查詢支付結果後,根據查詢結果須要作的業務處理接口 * @param orderId 訂單編號 * @param wxPaySearchResponseParam 查詢結果詳情 * @return 處理成功或失敗(TRUE/FALSE) */ boolean searchOrderDo(String orderId, WXPaySearchResponseParam wxPaySearchResponseParam) throws Exception; /** * 關閉支付訂單後的業務處理接口 * @param orderId 訂單編號 * @param wxPayCloseRecord 關閉結果詳情 * @return 處理成功或失敗(TRUE/FALSE) */ boolean closeOrderDo(String orderId, WXPayCloseRecord wxPayCloseRecord) throws Exception; /** * 支付訂單退款申請後的業務處理接口 * @param refundOrderId 商家退款單編號 * @param wxPayRefundRecord 退款申請詳情 * @return 處理成功或失敗(TRUE/FALSE) */ boolean refundOrderDo(String refundOrderId, WXPayRefundRecord wxPayRefundRecord) throws Exception; /** * 訂單退款查詢結果後,根據查詢結果須要作的業務處理接口 * @param refundOrderId * @param wxPayRefundResponseParam 查詢詳情 * @return 處理成功或失敗(TRUE/FALSE) */ boolean searchRefundOrderDo(String refundOrderId, WXPayRefundResponseParam wxPayRefundResponseParam) throws Exception; }
5.微信接口處理實現類spring
package com.readygo.pet.service.impl; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import com.readygo.pet.common.ConfigReader; import com.readygo.pet.common.Constant; import com.readygo.pet.mapper.CustomerOrderMapper; import com.readygo.pet.mapper.PaymentCodeMapper; import com.readygo.pet.mapper.WXPayRecordMapper; import com.readygo.pet.model.CustomerOrder; import com.readygo.pet.model.PaymentCode; import com.readygo.pet.model.WXPayCloseRecord; import com.readygo.pet.model.WXPayRecord; import com.readygo.pet.model.WXPayRefundRecord; import com.readygo.pet.service.WXPayDoService; import com.readygo.pet.utils.UniqueCodeUtils; import com.readygo.pet.utils.Utils; import com.readygo.pet.utils.WXPayUniqueCodeUtils; import com.readygo.pet.utils.WXPayUtils; import com.readygo.pet.vo.AddOrUpdOrderParmVO; import com.readygo.pet.vo.WXPayRefundResponseParam; import com.readygo.pet.vo.WXPaySearchResponseParam; import com.sun.xml.internal.ws.util.StringUtils; /** * 程序名 WXPayDoServiceImpl.java * 程序功能 微信處理後調用業務處理實現類 * 做成者 xx * 做成日期 2016-05-04 * 修改履歷 * 項目名 狀態 做成者 做成日期 * -------------------------------------------- * pets 新規 xx 2016-05-04 */ @Service @SuppressWarnings("unused") public class WXPayDoServiceImpl implements WXPayDoService { @Autowired private ConfigReader configReader; @Autowired private WXPayRecordMapper wxPayRecordMapper; @Autowired private CustomerOrderMapper customerOrderMapper; @Autowired private PaymentCodeMapper paymentCodeMapper; @Autowired private UniqueCodeUtils uniqueCodeUtils; @Autowired private WXPayUniqueCodeUtils wxPayUniqueCodeUtils; private final static String PID = "WBS0301WBS001"; /** * 微信支付成功後回調時,須要作的業務處理 * * @param wxPayRecord * 支付回傳結果詳情 * @return 處理成功或失敗(TRUE/FALSE) */ public boolean payOrderDo(String orderId, WXPayRecord wxPayRecord) throws Exception { boolean isOK = true; //回調執行操做 isOK = this.checkPay(orderId, wxPayRecord); return isOK; } /** * 查詢支付結果後,根據查詢結果須要作的業務處理 * * @param orderId * 訂單編號 * @param wxPaySearchResponseParam * 查詢結果詳情 * @return 處理成功或失敗(TRUE/FALSE) */ public boolean searchOrderDo(String orderId, WXPaySearchResponseParam wxPaySearchResponseParam) throws Exception { boolean isOK = true; // 1.接收和保存支付信息--向微信支付記錄表插入數據 // 2.更新訂單/支付碼等信息 // 2.1更新訂單表中的付款狀態、付款日期、支付方式、支付憑證單號、同時向訂單支付表中插入數據 WXPayRecord wxPayRecord = new WXPayRecord(); // 支付記錄id--系統生成 wxPayRecord.setWxPayRecordId(wxPayUniqueCodeUtils.getUniqueCode(WXPayUtils.TableType.T_WXPAY_RECORD)); // 接收返回狀態碼 wxPayRecord.setRecvReturnCode(wxPaySearchResponseParam.getReturn_code()); // 接收返回信息 wxPayRecord.setRecvReturnMsg(wxPaySearchResponseParam.getReturn_msg()); // 接收應用id wxPayRecord.setRecvAppid(wxPaySearchResponseParam.getAppid()); // 接收商戶號 wxPayRecord.setRecvMchId(wxPaySearchResponseParam.getMch_id()); // 接收設備號 // 接收隨機字符串 wxPayRecord.setRecvNonceStr(wxPaySearchResponseParam.getNonce_str()); // 接收簽名 wxPayRecord.setRecvSgin(wxPaySearchResponseParam.getSign()); // 接收業務結果 wxPayRecord.setRecvResultCode(wxPaySearchResponseParam.getResult_code()); // 接收錯誤代碼 wxPayRecord.setRecvErrCode(wxPaySearchResponseParam.getErr_code()); // 接收錯誤代碼描述 wxPayRecord.setRecvErrCodeDes(wxPaySearchResponseParam.getErr_code_des()); // 接收用戶標識 wxPayRecord.setRecvOpeId(wxPaySearchResponseParam.getOpenid()); // 接收關注公衆帳號 // 接收交易類型 wxPayRecord.setRecvTradeType(wxPaySearchResponseParam.getTrade_type()); // 接收付款銀行 wxPayRecord.setRecvBankType(wxPaySearchResponseParam.getBank_type()); // 接收總金額 if (!org.apache.commons.lang.StringUtils.isEmpty(wxPaySearchResponseParam.getTotal_fee())) { wxPayRecord.setRecvTotalFee(Integer.parseInt(wxPaySearchResponseParam.getTotal_fee())); } // 接收貨幣類型 wxPayRecord.setRecvFeeType(wxPaySearchResponseParam.getFee_type()); // 接收現金支付金額 if (!org.apache.commons.lang.StringUtils.isEmpty(wxPaySearchResponseParam.getCash_fee())) { wxPayRecord.setRecvCashFee(Integer.parseInt(wxPaySearchResponseParam.getCash_fee())); } // 接收現金支付貨幣類型 wxPayRecord.setRecvCashFeeType(wxPaySearchResponseParam.getCash_fee_type()); // 代金券 // 代金券使用量 // 支付訂單號 wxPayRecord.setRecvTransactionId(wxPaySearchResponseParam.getTransaction_id()); // 商家訂單號 wxPayRecord.setRecvOutTradeNo(wxPaySearchResponseParam.getOut_trade_no()); // 商家服務包 // 支付完成時間 wxPayRecord.setRecvTimeEnd(wxPaySearchResponseParam.getTime_end()); // 接收時間 // …… // 添加時間 wxPayRecord.setAddTime(Utils.getSysTime()); // 更新時間 wxPayRecord.setUpdTime(Utils.getSysTime()); //查詢微信支付結果執行操做 isOK = this.checkPay(orderId, wxPayRecord); return isOK; } /** * 關閉支付訂單後的業務處理 * * @param orderId * 訂單編號 * @param wxPayCloseRecord * 關閉結果詳情 * @return 處理成功或失敗(TRUE/FALSE) */ public boolean closeOrderDo(String orderId, WXPayCloseRecord wxPayCloseRecord) throws Exception { boolean isOK = true; return isOK; } /** * 支付訂單退款申請後的業務處理 * * @param refundOrderId * 商家退款單編號 * @param wxPayRefundRecord * 退款申請詳情 * @return 處理成功或失敗(TRUE/FALSE) */ public boolean refundOrderDo(String refundOrderId, WXPayRefundRecord wxPayRefundRecord) throws Exception { boolean isOK = true; return isOK; } /** * 訂單退款查詢結果後,根據查詢結果須要作的業務處理 * * @param refundOrderId * * @param wxPayRefundResponseParam * 查詢詳情 * @return 處理成功或失敗(TRUE/FALSE) */ public boolean searchRefundOrderDo(String refundOrderId, WXPayRefundResponseParam wxPayRefundResponseParam) throws Exception { boolean isOK = true; return isOK; } /** * 添加支付碼 * * @param customerOrderInfo * @return 成功/失敗 */ public void creatPayMentcode(CustomerOrder customerOrder) { int i; PaymentCode paymentCode = new PaymentCode(); String groupCode = uniqueCodeUtils.getUniqueCode(Constant.TableType.T_PAYMENT_CODE); paymentCode.setGroupCode(groupCode); for (i = 0; i < customerOrder.getNumber(); i++) { // 支付碼9位,數據庫是10位 Integer code = Integer.parseInt(uniqueCodeUtils.getPaymentCode()); paymentCode.setAddPid(PID); paymentCode.setAddUid(customerOrder.getCustomerId()); paymentCode.setCustomerId(customerOrder.getCustomerId()); // TODO 有效期不肯定 paymentCode.setInvaildDate(""); paymentCode.setInvaildFlag(Constant.ValidFlagType.VALID_FLAG.getType()); paymentCode.setOrderId(customerOrder.getOrderId()); paymentCode.setPaymentCode(code); paymentCode.setPrice(customerOrder.getPrice()); // TODO 沒有發起退款沒有退款編號 paymentCode.setRefoundAppId(""); paymentCode.setRefundFlag(Constant.RefundFlag.blank.getType()); paymentCode.setRemarks(customerOrder.getRemarks()); paymentCode.setServiceId(customerOrder.getServiceId()); paymentCode.setShopId(customerOrder.getShopId()); paymentCode.setUpdPid(PID); paymentCode.setUpdUid(customerOrder.getCustomerId()); paymentCode.setUseFlag(Constant.UseFlag.USE.getFlag()); // TODO 開始時間不肯定 paymentCode.setValidBeginTime(""); // TODO 結束時間不肯定 paymentCode.setValidEndTime(""); paymentCode.setValidFlag(Constant.ValidFlagType.VALID_FLAG.getType()); paymentCodeMapper.insertSelective(paymentCode); } // 支付碼沒有所有生成手動回滾 if (i != customerOrder.getNumber()) { throw new RuntimeException("支付碼生成失敗"); } } /** * 支付成功向數據庫插入數據 * **/ public boolean checkPay(String orderId, WXPayRecord wxPayRecord) { boolean isOK = false; // 1.先拿orderId查詢狀態是否已經改變 // 2.若是已經改成已付款,則不須要執行重複更新操做;不然,執行更新操做 CustomerOrder customerOrderTem = customerOrderMapper.selectByPrimaryKey(orderId); if (customerOrderTem == null) { isOK = false; } else if (customerOrderTem.getPayFlag() == Constant.PayFlag.UNPAY.getType()) { // 插入數據 int success = wxPayRecordMapper.insertSelective(wxPayRecord); if (success == 1) { // 插入成功 // 更新訂單表 CustomerOrder customerOrder = new CustomerOrder(); customerOrder.setOrderId(orderId); customerOrder.setPayFlag(1); customerOrder.setPayDate(Utils.getSysTime()); // 支付方式 customerOrder.setPayType(Constant.PayType.WEIXIN.getType()); // 支付憑證 customerOrder.setPayCredenceId(wxPayRecord.getRecvTransactionId()); int success2 = customerOrderMapper.updateByPrimaryKeySelective(customerOrder); if (success2 == 1) { // 向訂單支付表插入數據 CustomerOrder customerOrderInfo = customerOrderMapper.selectByPrimaryKey(orderId); this.creatPayMentcode(customerOrderInfo); } else { // 更新失敗,拋出異常 isOK = false; // 拋出異常 throw new RuntimeException(); } } else { isOK = false; } } return isOK; } }