微信公众号支付之退款

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

参考文档:

申请退款

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

 

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

 

微信公众号支付之退款

以上是微信公众号支付之退款的全部内容。
THE END
分享
二维码
< <上一篇
下一篇>>