Java开发SSM框架微信退款的实现

 更新时间:2018年10月26日 09:43:43   作者:一个帅的男人  
这篇文章是Java微信退款的教程,退款之前用户需要先进行支付,支付之后才可以使用退款,非常具有实用价值,感兴趣的小伙伴们可以参考一下

这篇文章是Java微信退款的教程,退款之前用户需要先进行支付,支付之后才可以使用退款。做到退款的同学应该已经是完成了支付了,我写的退款和支付的流程很相似只是所需的参数有所不同。

    String outTradeNo = request.getParameter("outTradeNo");// 获取商户订单号
 
 Integer totalFee = Integer.parseInt(request.getParameter("totalFee"));// 获取支付金额
 
 Map<String, String> getMap = new HashMap<String, String>();
 // 获得当前目录
 String path = request.getSession().getServletContext().getRealPath("/");
 
 Date now = new Date();
 SimpleDateFormat dateFormat = new SimpleDateFormat("yyyyMMddHHmmss");// 可以方便地修改日期格式
 String outRefundNo = "NO" + dateFormat.format(now);

提供的参数有订单号这个是支付成功之后生成的唯一号码,然后是获取到用户支付的金额这两个参数都是由支付之后的订单上面获得的。下面那个path则是保存微信安全证书文件的位置,这里提一下要实现微信退款和微信企业转账功能是需要到微信商户平台去下载安全证书的,然后把证书放在项目的WEB-INF/目录下即可。

    RefundReqData refundReqData = new RefundReqData();
 refundReqData.setAppid(Configure.getAppID());
 refundReqData.setMch_id(Configure.getMch_id());
 refundReqData.setNonce_str(RandomStringGenerator.getRandomStringByLength(32));
 refundReqData.setOut_trade_no(outTradeNo);
 refundReqData.setOut_refund_no(outRefundNo);
 refundReqData.setTotal_fee(totalFee);
 refundReqData.setRefund_fee(refundFee);
 refundReqData.setOp_user_id(Configure.getMch_id());
 refundReqData.setNotify_url("https://weixin.qq.com/notify/");
    String sign = Signature.getSign(refundReqData);// 生成签名
 refundReqData.setSign(sign);

获取到需要的参数之后呢,我在这里使用了一个退款的实体类把这些参数保存到了我的实体类里面方便后面的签名加密。

ArrayList<String> list = new ArrayList<String>();
    @SuppressWarnings("rawtypes")
 Class cls = o.getClass();
    Field[] fields = cls.getDeclaredFields();
    for (Field f : fields) {
      f.setAccessible(true);
      if (f.get(o) != null && f.get(o) != "") {
       String name = f.getName();
       XStreamAlias anno = f.getAnnotation(XStreamAlias.class);
       if(anno != null)
       name = anno.value();
        list.add(name + "=" + f.get(o) + "&");
      }
    }
    int size = list.size();
    String [] arrayToSort = list.toArray(new String[size]);
    Arrays.sort(arrayToSort, String.CASE_INSENSITIVE_ORDER);
    StringBuilder sb = new StringBuilder();
    for(int i = 0; i < size; i ++) {
      sb.append(arrayToSort[i]);
    }
    String result = sb.toString();
    result += "key=" + Configure.getKey();
    System.out.println("签名数据:"+result);
    result = MD5Util.MD5Encode(result,"utf-8").toUpperCase();
    return result;

这个是我签名加密的方法,把数据加密之后会成为一个很长的字符串,但是官方提供的退款接口是没办法解析你这个超长字符串的数据的,所以我们要把这个字符串变成官方接口认识的数据格式也就是xml格式。

private static XStream xstream = new XStream(new XppDriver() {
     public HierarchicalStreamWriter createWriter(Writer out) {
       return new PrettyPrintWriter(out) {
         // 对所有xml节点的转换都增加CDATA标记
         boolean cdata = true;
 
         //@SuppressWarnings("unchecked")
         public void startNode(String name, Class clazz) {
           super.startNode(name, clazz);
         }
 
         protected void writeText(QuickWriter writer, String text) {
           if (cdata) {
             writer.write("<![CDATA[");
             writer.write(text);
             writer.write("]]>");
           } else {
             writer.write(text);
           }
         }
       };
     }
   });

这一段代码是我把字符串格式的数据转换成xml格式的方法。再把xml格式的数据保存在一个字符串里面,这个时候我们开始向官方接口发送数据。

 public String httpsRequest(String url, String xmlObj, String path) throws Exception {
 // 加载证书
 initCert(path);
 
 String result = null;
 
 HttpPost httpPost = new HttpPost(url);
 
 // 得指明使用UTF-8编码,否则到API服务器XML的中文不能被成功识别
 StringEntity postEntity = new StringEntity(xmlObj, "UTF-8");
 httpPost.addHeader("Content-Type", "text/xml");
 httpPost.setEntity(postEntity);
 
 // 设置请求器的配置
 httpPost.setConfig(requestConfig);
 
 try {
  HttpResponse response = httpClient.execute(httpPost);
 
  HttpEntity entity = response.getEntity();
 
  result = EntityUtils.toString(entity, "UTF-8");
 
 } catch (ConnectionPoolTimeoutException e) {
  e.printStackTrace();
 } catch (ConnectTimeoutException e) {
  e.printStackTrace();
 
 } catch (SocketTimeoutException e) {
  e.printStackTrace();
 
 } catch (Exception e) {
  e.printStackTrace();
 
 } finally {
  httpPost.abort();
 }
 
 return result;
 }

通过Https往API post xml数据。

RefundRequest refundRequest = new RefundRequest();
  String result = refundRequest.httpsRequest("https://api.mch.weixin.qq.com/secapi/pay/refund", info, path);
 
  getMap = MobiMessage.parseXml(new String(result.toString().getBytes(), "utf-8"));
  System.out.println(getMap + "............getMap");
  json.put("return_msg", getMap.get("return_msg"));
  json.put("return_code", getMap.get("return_code"));
  json.put("outTradeNo", outTradeNo);

这一段就是给接口发送数据的代码(官方api接口,xml数据,证书的位置),然后我们接受接口返回的信息通过返回的return_msg和return_code来判断是否退款成功。

好了,微信退款就是这样完全可以照着代码把流程读出来很清晰明了也很简单,代码能力稍强的都看得懂,我主要是给大家提供一个思路。如果有同学没看懂也没关系下面是该项目的源码地址大家可以去下载退款的源代码都在里面:wechat_jb51.rar

PS:总结一下我在做微信退款的时候遇到的问题:
1.遇到了一个"Keystore password was incorrect"这个问题,原因这个退款所需要的证书不正确,这个证书是需要从微信平台去下载这个证书;
2.一定要注意在支付时的订单号码和退款时的订单号码是一致的,我碰到的这个问题是在支付时,把订单号码和微信返回的交易号码存数据库时弄反了,导致微信找不到这笔订单;
3.另外碰到的问题是退款在获取证书的时候,证书的路径不对,导致没有获取到证书,所以退款失败,所以还要检查证书是否存在,证书的路径是否正确,还要留意服务器上能否获取到证书。

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持脚本之家。

相关文章

  • Java通过递归算法解决迷宫与汉诺塔及八皇后问题

    Java通过递归算法解决迷宫与汉诺塔及八皇后问题

    方法就是用来完成解决某件事情或实现某个功能的办法;程序调用自身的编程技巧称为递归,本文主要讲的是通过递归来实现三个经典的问题,解决迷宫,汉诺塔,八皇后问题,感兴趣的朋友可以参考一下
    2022-05-05
  • java、js中实现无限层级的树形结构方法(类似递归)

    java、js中实现无限层级的树形结构方法(类似递归)

    下面小编就为大家带来一篇java、js中实现无限层级的树形结构方法(类似递归)。小编觉得挺不错的,现在就分享给大家,也给大家做个参考。一起跟随小编过来看看吧
    2016-11-11
  • Java编写网络聊天程序实验

    Java编写网络聊天程序实验

    这篇文章主要为大家详细介绍了Java编写网络聊天程序实验,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2022-08-08
  • Netty分布式ByteBuf使用directArena分配缓冲区过程解析

    Netty分布式ByteBuf使用directArena分配缓冲区过程解析

    这篇文章主要介绍了Netty分布式ByteBuf使用directArena分配缓冲区过程解析,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
    2022-03-03
  • idea中如何集成http请求

    idea中如何集成http请求

    这篇文章主要介绍了idea中如何集成http请求问题,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教
    2023-10-10
  • springboot docker jenkins 自动化部署并上传镜像的步骤详解

    springboot docker jenkins 自动化部署并上传镜像的步骤详解

    这篇文章主要介绍了springboot docker jenkins 自动化部署并上传镜像的相关资料,本文给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
    2020-05-05
  • Java Swing中的表格(JTable)和树(JTree)组件使用实例

    Java Swing中的表格(JTable)和树(JTree)组件使用实例

    这篇文章主要介绍了Java Swing中的表格(JTable)和树(JTree)组件使用实例,本文同时讲解了表格和树的基本概念、常用方法、代码实例,需要的朋友可以参考下
    2014-10-10
  • Java乱码问题解决方法_动力节点Java学院整理

    Java乱码问题解决方法_动力节点Java学院整理

    开发java应用出现乱码是很常见的,毕竟现在unicode的使用还不是很广泛,下面给大家分享Java乱码问题解决方法,感兴趣的朋友一起看看吧
    2017-07-07
  • Spring AOP中的JDK和CGLib动态代理哪个效率更高?

    Spring AOP中的JDK和CGLib动态代理哪个效率更高?

    今天小编就为大家分享一篇关于Spring AOP中的JDK和CGLib动态代理哪个效率更高?,小编觉得内容挺不错的,现在分享给大家,具有很好的参考价值,需要的朋友一起跟随小编来看看吧
    2019-03-03
  • 一文带你搞懂Java中的泛型和通配符

    一文带你搞懂Java中的泛型和通配符

    泛型机制在项目中一直都在使用,甚至很多源码中都用到了泛型机制。但是里面很多的机制和特性一直没有明白,尤其通配符这块,经常忘记。本文对此做了一些总结,具有一定借鉴价值,希望有所帮助
    2022-09-09

最新评论