微信申请退款API~~开发
近日,在开发“微信申请退款”的功能。之前有过微信开发的经验,但是第一次接触“微信退款“这一块的业务,查询了很多的博客资料以及走了很多的弯路。也发现“微信退款”分享的博客并不多。特地写了该博客,希望对你们有帮助。个人浅薄的见解
代码下载地址如下:
链接:https://pan.baidu.com/s/1h6_ZSz5RbFARlY9yxkvj5w
提取码:weft
有任何关于微信开发的问题可以相互交流, 推荐QQ:2172931891 , 另外有微商城、微分销、微信小游戏等系统源码,有需要可以联系免费提供。
一、微信退款Api
https://pay.weixin.qq.com/wiki/doc/api/jsapi.php?chapter=9_4
二、开发准备
(1)证书的准备:java开发需要用到:apiclient_cert.p12证书的,在微信公众号上下载–注意PKCS12证书 是从微信商户平台-》账户设置-》 API安全 中下载的 。
【何时用到证书?】与支付不一样,企业支付功能在发送post请求的时候,需要加载自己的一个证书之后,带着证书去请求退款才可以。这里使用到证书–很多人不知道证书在哪里使用
(2)了解好数字签名 — 简单来解释,就是对自己要发送的数据进行加密处理、换句话说假如说你要传递A/B/C,就对这三者进行加密。初开发者的误区:不知道该加密什么数据、观看网上的博客胡乱进行签名,导致签名错误
【温馨提示:】数字签名是一般开发人员容易遇到的错误,记住“你没遇到数字签名错误,都不好意思说自己做过微信退款支付订单查询等功能”。
耐心解决就行
(3)熟悉 从xml–》map,以及map—》xml。因为微信只接受xml数据,java写一个xml不简单,但是写map集合非常简单。而且返回的数据是xml格式。需要转化成开发熟知的map集合
不懂的可以看以下这篇博客
http://blog.csdn.net/xiaozhegaa/article/details/79127283
三、退款API截图解释
~~ 接口说明 + 是否需要证书数字签名说明 – 记住一句话:对要传递的数据进行加密,你要传递什么就要签名什么
第一次开发遇到的坑就是:不了解数字签名、花费了自己很长的时间,特地出来强调一下
证书说明
四、开发步骤如下
1.拼凑所需要传递的参数 map集合
2.根据要传递的参数生成自己的签名
3.把签名放到map集合中【因为签名也要传递过去】
4.将当前的map结合转化成xml格式
5.发送请求到微信退款Api。发送请求是一个方法来的
6.解析返回的xml数据===》map集合
7.根据map中的result_code/return_code来判断是否成功与失败
不得不再啰嗦一下。下面设计到签名、mapToXml转化、xmlToMap转化、发送请求到API。这些方法都可以在下面网址看到。这里我Xml转化成Map。我是习惯用一个Bean接收,也有范例的代码,大家模仿能力要强一点。这次贴出来给大家看看吧
http://blog.csdn.net/xiaozhegaa/article/details/79127283
/**
* 解析退款申请
* 解析的时候自动去掉CDMA
* @param xml
*/
@SuppressWarnings("unchecked")
public static RefundResult getUnifiedorderResult(String xml){
RefundResult unifieorderResult = new RefundResult();
try {
StringReader read = new StringReader(xml);
// 创建新的输入源SAX 解析器将使用 InputSource 对象来确定如何读取 XML 输入
InputSource source = new InputSource(read);
// 创建一个新的SAXBuilder
SAXBuilder sb = new SAXBuilder();
// 通过输入源构造一个Document
Document doc;
doc = (Document) sb.build(source);
Element root = doc.getRootElement();// 指向根节点
List<Element> list = root.getChildren();
if(list!=null&&list.size()>0){
for (Element element : list) {
System.out.println("key是:"+element.getName()+",值是:"+element.getText());
if("return_code".equals(element.getName())){
unifieorderResult.setResult_code(element.getText());
}
if("return_msg".equals(element.getName())){
unifieorderResult.setReturn_msg(element.getText());
}
if("result_code".equals(element.getName())){
unifieorderResult.setResult_code(element.getText());
}
if("out_refund_no".equals(element.getName())){
unifieorderResult.setOut_refund_no(element.getText());
}
if("refund_id".equals(element.getName())){
unifieorderResult.setRefund_id(element.getText());
}
if("refund_fee".equals(element.getName())){
unifieorderResult.setRefund_fee(element.getText());
}
if("coupon_refund_fee".equals(element.getName())){
unifieorderResult.setCoupon_refund_fee(element.getText());
}
if("total_fee".equals(element.getName())){
unifieorderResult.setTotal_fee(element.getText());
}
if("cash_fee".equals(element.getName())){
unifieorderResult.setCash_fee(element.getText());
}
if("err_code_des".equals(element.getName())){
unifieorderResult.setErr_code_des(element.getText());
}
}
}
} catch (JDOMException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}catch (Exception e) {
e.printStackTrace();
}
return unifieorderResult;
}
@Test
public void test2(){
SortedMap<Object, Object> packageParams = new TreeMap<Object, Object>();
packageParams.put("appid", wxconfig.AppID);
packageParams.put("mch_id", wxconfig.mch_id);
String s = UUID.randomUUID().toString().replace("-", "");
packageParams.put("nonce_str",s);
String s1 = UUID.randomUUID().toString().replace("-", "");
packageParams.put("out_refund_no",s1);
packageParams.put("out_trade_no","ozb5fjjxbwag1akdy0vm108makqhsdmx");
packageParams.put("refund_fee","100");
packageParams.put("total_fee","100");
packageParams.put("op_user_id",wxconfig.mch_id);
String sign = WeixinPayBack.createSign("utf-8",packageParams);
packageParams.put("sign", sign);
String reuqestXml = WXPayUtil.getRequestXml(packageParams);
System.out.println("-----------------");
System.out.println(reuqestXml);
System.out.println("-----------------");
//发送请求到后台了
String wxUrl = WeixinPayBack.getRefundURL;
try {
String weixinPost = ClientCustomSSL.doRefund(wxUrl, reuqestXml).toString();
System.out.println(weixinPost);
RefundResult refundResult = WeixinPayBack.getUnifiedorderResult(weixinPost);
String result =null;
if("SUCCESS".equalsIgnoreCase(refundResult.getResult_code())){
result = "200";
System.out.println("==========处理退款成功==========");
}else{
result = refundResult.getReturn_msg();
}
System.out.println(result);
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
五、结果演示
自此,我们就学会了“微信申请退款”的开发,希望对你们有帮助
具体的、在调用改方法自己加上自己的业务逻辑就行了。希望对大家有帮助
//TODO 9.0 操作支付表,把当前的支付的状态变成 退款状态 state 1 ---> 2
//TODO 10 操作预约表,可以把当前的预约状态取消 已支付--->退款
//TODO 11 操作用户表,如果是充值退款的话,把用户的现金 - 当前退款的money
//TODO 12其他等等的操作,生成记录单号之类的
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
· 开发者必知的日志记录最佳实践
· SQL Server 2025 AI相关能力初探
· Linux系列:如何用 C#调用 C方法造成内存泄露
· AI与.NET技术实操系列(二):开始使用ML.NET
· 无需6万激活码!GitHub神秘组织3小时极速复刻Manus,手把手教你使用OpenManus搭建本
· C#/.NET/.NET Core优秀项目和框架2025年2月简报
· Manus爆火,是硬核还是营销?
· 终于写完轮子一部分:tcp代理 了,记录一下
· 【杭电多校比赛记录】2025“钉耙编程”中国大学生算法设计春季联赛(1)
2018-09-09 Entity Framework查询,EF执行SQl