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

String outTradeNo = request.getParameter("outTradeNo");// 获取商户订单号

Integer totalFee = Integer.parseInt(request.getParameter("totalFee"));// 获取支付金额

Map getMap = new HashMap();

// 获得当前目录

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 list = new ArrayList();

@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("

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 ssm框架调用微信_Java开发SSM框架微信退款的实现相关推荐

  1. java开发后端框架_java开发后端框架

    1 java开发后端框架 java从推出到现在技术不断发展,语言也优化的越来越好,对于java工程师来说技术的不断发展,他们需要不断学习java进阶,而对于新手来说就能从基础到核心.那么新手该怎么学习 ...

  2. java iterator如何知道数量_Java开发岗面试题基础篇(二)

    点击蓝字 关注wo们 老哥们,接上篇<Java开发岗面试题--基础篇(一)>,本期推出Java开发岗面试题--基础篇(二),来看看Java中的集合.多线程.异常体系等知识在面试中是怎么体现 ...

  3. java停车管理系统中期检查_java毕业设计_springboot框架的停车场收费管理系统

    这是一个基于java的毕业设计项目,毕设课题为springboot框架的停车场收费管理系统, 是一个采用b/s结构的javaweb项目, 开发工具eclipsei/eclipse, 项目框架jsp+s ...

  4. java学生-成绩关联实体_java毕业设计_springboot框架的学生成绩智能管理

    这是一个基于java的毕业设计项目,毕设课题为springboot框架的学生成绩智能管理, 是一个采用b/s结构的javaweb项目, 开发工具eclipsei/eclipse, 项目框架jsp+sp ...

  5. java框架要求合同_java毕业设计_springboot框架的合同管理

    这是一个基于java的毕业设计项目,毕设课题为springboot框架的合同管理, 是一个采用b/s结构的javaweb项目, 开发工具eclipsei/eclipse, 项目框架jsp+spring ...

  6. java设计校园网登录界面_java毕业设计_springboot框架的校园网的大学生社交网站...

    这是一个基于java的毕业设计项目,毕设课题为springboot框架的校园网的大学生社交网站, 是一个采用b/s结构的javaweb项目, 开发工具eclipsei/eclipse, 项目框架jsp ...

  7. 基于JAVA教学质量评价系统_java毕业设计_springboot框架的教学质量评价系统

    这是一个基于java的毕业设计项目,毕设课题为springboot框架的教学质量评价系统, 是一个采用b/s结构的javaweb项目, 开发工具eclipsei/eclipse, 项目框架jsp+sp ...

  8. java报销系统的参考文献_java毕业设计_springboot框架的企业报销管理与实现

    这是一个基于java的毕业设计项目,毕设课题为springboot框架的企业报销管理与实现, 是一个采用b/s结构的javaweb项目, 开发工具eclipsei/eclipse, 项目框架jsp+s ...

  9. java个人小管家代码_java毕业设计_springboot框架的家庭小管家系统

    这是一个基于java的毕业设计项目,毕设课题为springboot框架的家庭小管家系统, 是一个采用b/s结构的javaweb项目, 开发工具eclipsei/eclipse, 项目框架jsp+spr ...

最新文章

  1. java sql编码_java+sql 编码 UTF-8、ISO-8859-1、GBK
  2. pandas使用replace函数将dataframe中None值以及其他异常编码值(例如,9999)替换为np.nan
  3. python列表输入不加逗号_用python打印不带括号或逗号的列表
  4. call、bind与apply
  5. 面试:给我说一下Spring MVC拦截器的原理?
  6. 使用gparted-LiveCD对centos分区调整---virtualbox磁盘调整序2
  7. scp连接计算节点操作
  8. 斗地主AI算法——第十六章の样例分析
  9. 为什么程序员互相之间不能透露薪水?是怕“凡尔赛”吗?
  10. js中的逻辑与()和逻辑或(||)(转载)
  11. Arduino 交通灯实验
  12. 【java期末复习题】第15章 JDBC数据库编程
  13. 低频电子线路学习笔记
  14. 【JZOJ3337】wyl8899的TLE
  15. Justinmind使用教程(1)——概述部分
  16. 如何封装svg矢量图
  17. 2020中职技能高考计算机,我市62名中职学生获得2020年技能高考操作考试满分
  18. 绘制小猪佩奇的python代码
  19. AIX小型机在DLPAR之间移动磁带机
  20. Baklib知识管理体系:将知识管理深化到企业中

热门文章

  1. 图书馆信息管理系统(毕业设计)
  2. 洛谷 P2842 LJJ算数
  3. html只选择年份,ant design vue 日期选择器只选择年份
  4. gRPC教程 — 第一章
  5. 爬虫——解析图书排行榜图书信息
  6. Jeesite Login 登录 分析
  7. ssd的smt_联合评测 | Intel Optane SSD 有效加速 SmartX 超融合在 Oracle 等场景下的系统性能...
  8. 美国大学硕士研究生计算机专业几年,美国大学博士几年 - 美国南加州大学计算机研究生学几年...
  9. OID科普:物联网OID与互联网域名的区别 | 圣笛数控
  10. 全文检索技术Lucene入门和学习、与数据库数据结合的demo实现