无论刷卡支付、微信公众号支付、扫码支付、H5支付、APP支付等都有申请退款API
并且接口一样,本篇文章就拿刷卡支付
中的申请退款API文档举例
当交易发生之后一段时间内,由于买家或者卖家的原因需要退款时,卖家可以通过退款接口将支付款退还给买家,微信支付将在收到退款请求并且验证成功之后,按照退款规则将支付款按原路退到买家帐号上
。
一笔退款失败后重新提交,请不要更换退款单号,请使用原商户退款单号
参考安全规范-3.商户证书
下载:微信商户平台(pay.weixin.qq.com)-->账户中心-->账户设置-->API安全-->证书下载
https://github.com/Javen205/IJPay https://githee.com/Javen205/IJPay
com.jpay.weixin.api.WxPayApi.java
// 申请退款
private static final String REFUND_URL = "https://api.mch.weixin.qq.com/secapi/pay/refund";
// 查询退款
private static final String REFUNDQUERY_URL = "https://api.mch.weixin.qq.com/pay/refundquery";
// 申请退款
private static final String REFUND_SANDBOXNEW_URL = "https://api.mch.weixin.qq.com/sandboxnew/secapi/pay/refund";
// 查询退款
private static final String REFUNDQUERY_SANDBOXNEW_URL = "https://api.mch.weixin.qq.com/sandboxnew/pay/refundquery";
/**
* 申请退款
* 服务商模式接入文档:https://pay.weixin.qq.com/wiki/doc/api/micropay_sl.php?chapter=9_4
* 商户模式接入文档:https://pay.weixin.qq.com/wiki/doc/api/micropay.php?chapter=9_4
*
* @param isSandbox
* 是否是沙盒环境
* @param params
* 请求参数
* @param certPath
* 证书文件目录
* @param certPass
* 证书密码
* @return {String}
*/
public static String orderRefund(boolean isSandbox, Map<String, String> params, String certPath, String certPass) {
if (isSandbox)
return doPostSSL(REFUND_SANDBOXNEW_URL, params, certPath, certPass);
return doPostSSL(REFUND_URL, params, certPath, certPass);
}
/**
* 查询退款
* 服务商模式接入文档:https://pay.weixin.qq.com/wiki/doc/api/micropay_sl.php?chapter=9_5
* 商户模式接入文档:https://pay.weixin.qq.com/wiki/doc/api/micropay.php?chapter=9_5
*
* @param isSandbox
* 是否是沙盒环境
* @param params
* 请求参数
* @return {String}
*/
public static String orderRefundQuery(boolean isSandbox, Map<String, String> params) {
if (isSandbox)
return doPost(REFUNDQUERY_SANDBOXNEW_URL, params);
return doPost(REFUNDQUERY_URL, params);
}
https://github.com/Javen205/IJPay-Demo https://githee.com/Javen205/IJPay-Demo
com.ijpay.controller.weixin.WxPayController.java
/**
* 微信退款
*/
public void refund() {
String transaction_id = getPara("transactionId");
String out_trade_no = getPara("out_trade_no");
if (StrKit.isBlank(out_trade_no) && StrKit.isBlank(transaction_id)) {
renderText("transactionId、out_trade_no二选一");
return;
}
Map<String, String> params = new HashMap<String, String>();
params.put("appid", appid);
params.put("mch_id", mch_id);
params.put("nonce_str", System.currentTimeMillis()+"");
if (StrKit.notBlank(transaction_id)) {
params.put("transaction_id", transaction_id);
}else {
params.put("out_trade_no", out_trade_no);
}
params.put("out_refund_no", System.currentTimeMillis()+"");
params.put("total_fee", "1");
params.put("refund_fee", "1");
params.put("sign", PaymentKit.createSign(params, partnerKey));
String refund = WxPayApi.orderRefund(false, params , certPath, mch_id);
renderText(refund);
}
/**
* 微信退款查询
*/
public void refundQuery() {
String transaction_id = getPara("transactionId");
String out_trade_no = getPara("out_trade_no");
String out_refund_no = getPara("out_refund_no");
String refund_id = getPara("refund_id");
Map<String, String> params = new HashMap<String, String>();
params.put("appid", appid);
params.put("mch_id", mch_id);
params.put("nonce_str", System.currentTimeMillis()+"");
params.put("transaction_id", transaction_id);
params.put("out_trade_no", out_trade_no);
params.put("out_refund_no", out_refund_no);
params.put("refund_id", refund_id);
params.put("out_refund_no", System.currentTimeMillis()+"");
params.put("sign", PaymentKit.createSign(params, partnerKey));
String refund = WxPayApi.orderRefundQuery(false, params);
renderText(refund);
}
同步返回结果XML参考
//退款
<xml><return_code><![CDATA[SUCCESS]]></return_code>
<return_msg><![CDATA[OK]]></return_msg>
<appid><![CDATA[wxxx]]></appid>
<mch_id><![CDATA[xxxx]]></mch_id>
<nonce_str><![CDATA[22hvoyIn52VVVksU]]></nonce_str>
<sign><![CDATA[ED121D6583909150308C76ACFB6FC74B]]></sign>
<result_code><![CDATA[SUCCESS]]></result_code>
<transaction_id><![CDATA[4200000100201801133414066xxx]]></transaction_id>
<out_trade_no><![CDATA[1515845954891]]></out_trade_no>
<out_refund_no><![CDATA[1519535580802]]></out_refund_no>
<refund_id><![CDATA[50000405502018022503594217469]]></refund_id>
<refund_channel><![CDATA[]]></refund_channel>
<refund_fee>1</refund_fee>
<coupon_refund_fee>0</coupon_refund_fee>
<total_fee>1</total_fee>
<cash_fee>1</cash_fee>
<coupon_refund_count>0</coupon_refund_count>
<cash_refund_fee>1</cash_refund_fee>
</xml>
//退款查询错误示例
<xml>
<appid><![CDATA[wxxxx]]></appid>
<err_code><![CDATA[REFUNDNOTEXIST]]></err_code>
<err_code_des><![CDATA[not exist]]></err_code_des>
<mch_id><![CDATA[xxx]]></mch_id>
<nonce_str><![CDATA[SG1IAYtK0apvnHpF]]></nonce_str>
<result_code><![CDATA[FAIL]]></result_code>
<return_code><![CDATA[SUCCESS]]></return_code>
<return_msg><![CDATA[OK]]></return_msg>
<sign><![CDATA[7323459E0DE45DBB8C87932C4C99BBF3]]></sign>
</xml>
//退款查询
<xml>
<appid><![CDATA[wxxxx]]></appid>
<cash_fee><![CDATA[1]]></cash_fee>
<mch_id><![CDATA[xxx]]></mch_id>
<nonce_str><![CDATA[KptCSXZh1qBjK8wb]]></nonce_str>
<out_refund_no_0><![CDATA[1519535580802]]></out_refund_no_0>
<out_trade_no><![CDATA[1515845954891]]></out_trade_no>
<refund_account_0><![CDATA[REFUND_SOURCE_UNSETTLED_FUNDS]]></refund_account_0>
<refund_channel_0><![CDATA[ORIGINAL]]></refund_channel_0>
<refund_count>1</refund_count>
<refund_fee>1</refund_fee>
<refund_fee_0>1</refund_fee_0>
<refund_id_0><![CDATA[50000405502018022503594217469]]></refund_id_0>
<refund_recv_accout_0><![CDATA[支付用户的零钱]]></refund_recv_accout_0>
<refund_status_0><![CDATA[SUCCESS]]></refund_status_0>
<refund_success_time_0><![CDATA[2018-02-25 13:13:03]]></refund_success_time_0>
<result_code><![CDATA[SUCCESS]]></result_code>
<return_code><![CDATA[SUCCESS]]></return_code>
<return_msg><![CDATA[OK]]></return_msg>
<sign><![CDATA[E8A30F02296C6169860A92C2D52AD5A8]]></sign>
<total_fee><![CDATA[1]]></total_fee>
<transaction_id><![CDATA[4200000100201801133414066940]]></transaction_id>
</xml>
如有疑问欢迎留言交流讨论