要知道,app調用支付后,微信會發送一個異步通知給后台,同時后台需要調用查詢微信后台這筆訂單的支付結果以及金額,這是一個並行操作,需要注意的是微信后台收到的金額和訂單金額需要進行比對,為了防止釣魚,所以這個查詢是有必要的,必須匹配:收到的到賬金額 >= 訂單金額(我有一哥們他們的app是沒有這步操作的,支付了不論是否成功訂單直接往下走,這樣是不對滴...)
好吧,來看一下代碼,異步通知地址需要自己配置好,在生成預付單的時候就得傳過去
// TODO 通知回調地址 @Value("${WXPAY_NOTIFYURL}") private String notifyUrl;
這個地址就是自己的webservice,也就是你的某個rest-controller
@RequestMapping("/notice") public void notice(HttpServletRequest request, HttpServletResponse response) throws IOException { InputStream inStream = request.getInputStream(); ByteArrayOutputStream outSteam = new ByteArrayOutputStream(); byte[] buffer = new byte[1024]; int len = 0; while ((len = inStream.read(buffer)) != -1) { outSteam.write(buffer, 0, len); } outSteam.close(); inStream.close(); String result = new String(outSteam.toByteArray(), "utf-8"); Map<String, String> map = null; try { map = XMLUtil.doXMLParse(result); } catch (JDOMException e) { e.printStackTrace(); } // 此處調用訂單查詢接口驗證是否交易成功 WXOrderQuery wxpayResult = reqOrderQueryResult(map); boolean isSucc = wxpayResult.isSuccess(); // 支付成功,商戶處理后同步返回給微信參數 PrintWriter writer = response.getWriter(); if (!isSucc) { // 支付失敗, 記錄流水失敗 System.out.println("===============支付失敗=============="); } else { orderService.doWXPayNotice(wxpayResult); System.out.println("===============付款成功,業務處理完畢=============="); // 通知微信已經收到消息,不要再給我發消息了,否則微信會8連擊調用本接口 String noticeStr = setXML("SUCCESS", ""); writer.write(noticeStr); writer.flush(); } String noticeStr = setXML("FAIL", ""); writer.write(noticeStr); writer.flush(); } 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>"; }
/** * 目前用的這個接口 * @Description: 查詢通知的結果bean * @param map * @return * * @author leechenxiang * @date 2016年12月8日 上午11:04:52 */ public WXOrderQuery reqOrderQueryResult(Map<String, String> map) { WXOrderQuery orderQuery = new WXOrderQuery(); orderQuery.setAppid(map.get("appid")); orderQuery.setMch_id(map.get("mch_id")); orderQuery.setTransaction_id(map.get("transaction_id")); orderQuery.setOut_trade_no(map.get("out_trade_no")); orderQuery.setNonce_str(map.get("nonce_str")); String payFlowId = map.get("attach"); orderQuery.setAttach(payFlowId); //此處需要密鑰PartnerKey,此處直接寫死,自己的業務需要從持久化中獲取此密鑰,否則會報簽名錯誤 orderQuery.setPartnerKey(WXPayContants.partnerKey); Map<String, String> orderMap = orderQuery.reqOrderquery(); //此處添加支付成功后,支付金額和實際訂單金額是否等價,防止釣魚 if (orderMap.get("return_code") != null && orderMap.get("return_code").equalsIgnoreCase("SUCCESS")) { if (orderMap.get("trade_state") != null && orderMap.get("trade_state").equalsIgnoreCase("SUCCESS")) { // 查詢訂單(交易流水的實際金額),判斷微信收到的錢和訂單中的錢是否等額 SpPayFlowCargoSource payFlow = spPayFlowCargoSourceService.getPayFlowById(payFlowId); String total_fee = map.get("total_fee"); orderQuery.setPayFlow(payFlow); Integer db_fee = payFlow.getFee().multiply(new BigDecimal(100)).intValue(); if (Integer.parseInt(total_fee) == db_fee) { orderQuery.setSuccess(true); return orderQuery; } } } orderQuery.setSuccess(false); return orderQuery; }
到這一步,就能判斷金額到底對不對,對了那么久成功支付,訂單進行下一步流程~
再次強調,一定要防止釣魚,另外異步調用的時候需要去查看你的訂單或者交易流水是否已經成功了,成功就沒有必要繼續走,直接return就行,因為微信
會多次異步通知,主要還是看你的接口怎么設計了
(附:微信異步通知頻率為15/15/30/180/1800/1800/1800/1800/3600,單位:秒)