1.場景
當交易發生之后一段時間內,由於買家或者賣家的原因需要退款時,賣家可以通過退款接口將支付款退還給買家,微信支付將在收到退款請求並且驗證成功之后,按照退款規則將支付款按原路退到買家帳號上。
注意:
1、交易時間超過一年的訂單無法提交退款
2、微信支付退款支持單筆交易分多次退款,多次退款需要提交原支付訂單的商戶訂單號和設置不同的退款單號。申請退款總金額不能超過訂單金額。 一筆退款失敗后重新提交,請不要更換退款單號,請使用原商戶退款單號
3、請求頻率限制:150qps,即每秒鍾正常的申請退款請求次數不超過150次
錯誤或無效請求頻率限制:6qps,即每秒鍾異常或錯誤的退款申請請求不超過6次
4、每個支付訂單的部分退款次數不能超過50次
5、如果同一個用戶有多筆退款,建議分不同批次進行退款,避免並發退款導致退款失敗
2.返回的接口地址
https://api.mch.weixin.qq.com/secapi/pay/refund
3.需要證書
如果證書不是自己配置的,在微信支付平台管理的地方是下載不了的。也可以換一種方法去找你的經理要一份就好了。
4.請求參數 (以下截圖是必填的參數,如有不明白請參考官方文檔:https://pay.weixin.qq.com/wiki/doc/api/native.php?chapter=9_4)
5.代碼部分
①.service方法
1 /** 2 * 3 * @param mchId 商戶ID 4 * @param url 請求URL 5 * @param data 退款參數 6 * @return 7 * @throws Exception 8 */ 9 String doRefund(String mchId, String url, String data) throws Exception;
②.impl 此方法內要讀取證書的位置
1 /** 2 * 3 * @param mchId 商戶ID 4 * @param url 請求URL 5 * @param data 退款參數 6 * @return 7 * @throws Exception 8 */ 9 public String doRefund(String mchId, String url, String data) throws Exception { 10 /** 11 * 注意PKCS12證書 是從微信商戶平台-》賬戶設置-》 API安全 中下載的 12 */ 13 KeyStore keyStore = KeyStore.getInstance("PKCS12"); 14 15 //這里讀取.p12的文件是放在服務器中 使用nginx配置時指向的后端項目路徑 16 FileInputStream inputStream = new FileInputStream(new File("apiclient_cert.p12"));//P12文件目錄 17 try { 18 //這里寫密碼..默認是你的MCHID 19 keyStore.load(inputStream, mchId.toCharArray()); 20 } finally { 21 inputStream.close(); 22 } 23 SSLContext sslcontext = SSLContexts.custom() 24 //這里也是寫密碼的 25 .loadKeyMaterial(keyStore, mchId.toCharArray()) 26 .build(); 27 SSLConnectionSocketFactory sslsf = new SSLConnectionSocketFactory( 28 sslcontext, 29 SSLConnectionSocketFactory.getDefaultHostnameVerifier()); 30 CloseableHttpClient httpclient = HttpClients.custom() 31 .setSSLSocketFactory(sslsf) 32 .build(); 33 try { 34 HttpPost httpost = new HttpPost(url); 35 httpost.setEntity(new StringEntity(data, "UTF-8")); 36 CloseableHttpResponse response = httpclient.execute(httpost); 37 try { 38 HttpEntity entity = response.getEntity(); 39 //接受到返回信息 40 String jsonStr = EntityUtils.toString(response.getEntity(), "UTF-8"); 41 System.out.println(jsonStr+"-====接收到返回的信息"); 42 EntityUtils.consume(entity); 43 return jsonStr; 44 } finally { 45 response.close(); 46 } 47 } finally { 48 httpclient.close(); 49 } 50 } 51 52
③.controller
1 @RequestMapping("/refund") 2 public String refund() throws Exception { 3 System.out.println("進入退款----"); 4 try { 5 //構建參數 6 Map<String, String> dataMap = new HashMap<>(); 7 dataMap.put("appid","公眾賬號ID"); 8 dataMap.put("mch_id","商戶號"); 9 //自行實現該隨機串 10 dataMap.put("nonce_str",WXPayUtil.generateNonceStr()); 11 //商戶訂單號 12 dataMap.put("out_trade_no","訂單號"); 13 //商戶退款單號 14 dataMap.put("out_refund_no","訂單號"); 15 //訂單金額 16 dataMap.put("total_fee","1"); 17 //退款金額 18 dataMap.put("refund_fee","1"); 19 //退款原因 (可寫可不寫) 20 dataMap.put("refund_desc","退款"); 21 //生成簽名 22 String sign = WXPayUtil.generateSignature(dataMap, "商戶密鑰"); 23 dataMap.put("sign", sign); 24 System.out.println(dataMap+"=========dataMap"); 25 26 //map數據轉xml 27 String xmlString = XMLBeanUtil.map2XmlString(dataMap); 28 System.out.println("--------------map-->xml轉換------------"+xmlString); 29 30 //發起退款 31 String result= weixinPayService.doRefund("商戶號", "https://api.mch.weixin.qq.com/secapi/pay/refund", xmlString); 32 System.out.println(result.toString()+"----結果"); 33 System.out.println("================退款==========="); 34 35 //這里需要將發起退款的xml格式轉換為map 36 Map<String, String> returnMap = WXPayUtil.xmlToMap(result); 37 System.out.println("--------------xml-->map轉換"+result); 38 //用map取值返回的狀態碼來判斷是否退款成功 39 //判斷是否退款成功 40 if (returnMap.get("return_code").equals("SUCCESS")) { 41 return "微信已成功退款"; 42 } 43 return "微信退款失敗"; 44 } catch (Exception e) { 45 e.printStackTrace(); 46 } 47 return "失敗"; 48 } 49 50
6.結語
第一次寫博客,寫的不太好,還希望大家多多包涵。同時也希望這篇博客可以幫助到正在做退款這一塊的碼友們。有不懂的可以評論哦看到必回。