zoukankan      html  css  js  c++  java
  • 微信公众号支付之退款

    这一篇紧接着上面支付的那篇。

    参考文档:

    申请退款

    https://pay.weixin.qq.com/wiki/doc/api/H5.php?chapter=9_4&index=4 

    退款结果通知

    https://pay.weixin.qq.com/wiki/doc/api/H5.php?chapter=9_16&index=10

    1.退款的时候需要配置认证的证书如图

    2.申请退款接口

                    FileInputStream instream = null;
                    CloseableHttpClient httpclient = null;
                    try {
                        StringBuffer xml = new StringBuffer();
                        String data = null;
                        String nonceStr = WXPayUtil.generateNonceStr();
                        xml.append("</xml>");
                        SortedMap<String,String> parameters = new TreeMap<String,String>();
                        parameters.put("appid", weixinConfig.getWeiXinPayAppId());
                        parameters.put("mch_id", weixinConfig.getMchId());
                        parameters.put("sign_type","MD5");  
                        parameters.put("nonce_str", nonceStr);
                        parameters.put("out_refund_no", or.getCart().getId());
                        parameters.put("out_trade_no", orderNo);
                        parameters.put("refund_fee", WXPayUtil.getMoney(or.getPrice().setScale(2, BigDecimal.ROUND_DOWN).toString()));
                        parameters.put("total_fee", WXPayUtil.getMoney(orderPayment.getTotalPrice().setScale(2, BigDecimal.ROUND_DOWN).toString()));
                        parameters.put("fee_type", "CNY");
                        parameters.put("op_user_id", weixinConfig.getMchId());
                        parameters.put("notify_url", weixinConfig.getWeiXinRefundNotifyUrl());
                        parameters.put("transaction_id", orderPayment.getBusinessOrderNo());
                        String createSign1 = WXPayUtil.createSign(parameters, weixinConfig.getWeiXinPayAppSecret());
                        parameters.put("sign", createSign1);
                        data =WXPayUtil.SortedMaptoXml(parameters);
                        logger.info("微信申请退款请求数据信息:"+data);
                        KeyStore keyStore  = KeyStore.getInstance("PKCS12");
                        instream = new FileInputStream(new File(weixinConfig.getWeiXinPayKey()));
                        try {
                            keyStore.load(instream, weixinConfig.getMchId().toCharArray());
                        } catch (Exception e) {
                            e.printStackTrace();
                        }finally{
                            instream.close();
                        }
                        SSLContext sslcontext = SSLContexts.custom()
                                .loadKeyMaterial(keyStore, weixinConfig.getMchId().toCharArray())
                                .build();
                        SSLConnectionSocketFactory sslsf = new SSLConnectionSocketFactory(
                                sslcontext,
                                new String[] { "TLSv1" },
                                null,
                                SSLConnectionSocketFactory.BROWSER_COMPATIBLE_HOSTNAME_VERIFIER);
                        httpclient = HttpClients.custom()
                                .setSSLSocketFactory(sslsf)
                                .build();
                        HttpPost httppost = new HttpPost("https://api.mch.weixin.qq.com/secapi/pay/refund");
                        StringEntity entitys = new StringEntity(data, "UTF-8");
                        httppost.setEntity(entitys);
                        CloseableHttpResponse response = httpclient.execute(httppost);
                        HttpEntity entity = response.getEntity();
                        StringBuilder sb2 = new StringBuilder();
                        String xmlStr2 = null;//读入响应流中字符串的引用
                        if (entity != null) {
                            BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(entity.getContent(), "UTF-8"));
                            while ((xmlStr2 = bufferedReader.readLine()) != null) {
                                sb2.append(xmlStr2);
                            }
                        }
                        //关闭流对象
                        EntityUtils.consume(entity);
                        logger.info("微信申请退款响应数据信息:"+sb2.toString());
                        //处理返回的结果XML
                        Map<String, String> refundOrderMap = WXPayUtil.xmlToMap(sb2.toString());
                        if(refundOrderMap.size()>0){
                            if(refundOrderMap.get("return_code").equals("SUCCESS") && refundOrderMap.get("result_code").equals("SUCCESS")){
                                //退款申请请求发送成功   处理自己项目的业务逻辑 TODO
                                
                            }else{
                     //处理自己项目的业务逻辑 TODO
    } }else{ //TODO } } catch(Exception e){ //TODO }finally { try { httpclient.close(); } catch (IOException e) { e.printStackTrace(); } }

    3.微信退款结果通知

    /**
         * 退款成功异步回调接口
         * 
         * @param request
         * @param response
         * @throws Exception
         */
        @RequestMapping(value = "/refundNotice", produces = "text/html;charset=utf-8")
        @ResponseBody
        public String weiXinRefundNotice(HttpServletRequest request, HttpServletResponse response) throws Exception {
            ServletInputStream instream = request.getInputStream();
            StringBuffer sb = new StringBuffer();
            int len = -1;
            byte[] buffer = new byte[1024];
            while ((len = instream.read(buffer)) != -1) {
                sb.append(new String(buffer, 0, len));
            }
            instream.close();
            log.info("退款通知信息:" + sb.toString());
            Map<String, String> map = WXPayUtil.xmlToMap(sb.toString());// 接受微信的回调的通知参数
            Map<String, String> return_data = new HashMap<String, String>();
            // 判断returnCode状态
            if (map.get("return_code").toString().equals("FAIL")) {
                return_data.put("return_code", "FAIL");
                return_data.put("return_msg", map.get("return_msg"));
            } else if (map.get("return_code").toString().equals("SUCCESS")) {
                String reqInfo = map.get("req_info");
                byte[] decode = Base64.decodeBase64(reqInfo);
                String key = MD5Util.MD5(weixinConfig.getWeiXinPayAppSecret()).toLowerCase();
                String decryptData = WXPayUtil.getRefundDecrypt(decode,key);
                log.info("退款通知信息解密数据:"+decryptData);
                Map<String, String> mm = WXPayUtil.xmlToMap(decryptData);
                if (mm.get("refund_status").equals("SUCCESS")){//退款成功
                      //处理自己的业务逻辑  TODO
                  }else if (map.get("refund_status").equals("CHANGE")) {//退款异常
                  
                  }else if (map.get("refund_status").equals("REFUNDCLOSE")) {//退款关闭
                  
                  }
                 
            }
            String xml = WXPayUtil.GetMapToXML(return_data);
            log.info("退款通知回调结果:" + xml);
            return xml;
        }

    总结:

    1.官方文档给的传值参数一定要注意看

    2.官方文档里面的有一个方法的字符集有问题,导致返回的信息乱码,无法快速的定位到问题点,上述示例代码已更正

    上述两篇关于微信支付的实现,只是最基础的功能实现,欢迎大家一起讨论和纠正。

  • 相关阅读:
    数据库的三大范式以及五大约束
    解析PHP面向对象的三大特征
    php中的数组遍历的几种方式
    PHP中的函数声明与使用
    使用mui框架打开页面的几种不同方式
    JS中精选this关键字的指向规律你记住了吗
    同一功能三种不同实现方式你选哪个
    转!!NPM报错 Error: EPERM: operation not permitted, unlink......解决办法和清除缓存。
    转!!关于http请求 浏览器 中文编码
    CentOS6.5下Apache防止目录遍历
  • 原文地址:https://www.cnblogs.com/mr-wuxiansheng/p/10202555.html
Copyright © 2011-2022 走看看