微信支付之退款--原路退回

时间:2024-02-19 14:36:08

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.结语

  第一次写博客,写的不太好,还希望大家多多包涵。同时也希望这篇博客可以帮助到正在做退款这一块的码友们。有不懂的可以评论哦看到必回。