微信支付之微信退款


官方文档

无论刷卡支付、微信公众号支付、扫码支付、H5支付、APP支付等都有申请退款API并且接口一样,本篇文章就拿刷卡支付中的申请退款API文档举例

应用场景

当交易发生之后一段时间内,由于买家或者卖家的原因需要退款时,卖家可以通过退款接口将支付款退还给买家,微信支付将在收到退款请求并且验证成功之后,按照退款规则将支付款按原路退到买家帐号上

注意事项

  1. 交易时间超过一年的订单无法提交退款
  2. 微信支付退款支持单笔交易分多次退款,多次退款需要提交原支付订单的商户订单号和设置不同的退款单号。申请退款总金额不能超过订单金额。一笔退款失败后重新提交,请不要更换退款单号,请使用原商户退款单号
  3. 请求频率限制:150qps,即每秒钟正常的申请退款请求次数不超过150次
  4. 错误或无效请求频率限制:6qps,即每秒钟异常或错误的退款申请请求不超过6次
  5. 每个支付订单的部分退款次数不能超过50次

下载证书

参考安全规范-3.商户证书

下载:微信商户平台(pay.weixin.qq.com)-->账户中心-->账户设置-->API安全-->证书下载

IJPay 中的接口

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>

微信支付、支付宝支付博客专栏

如有疑问欢迎留言交流讨论

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 160,165评论 4 364
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 67,720评论 1 298
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 109,849评论 0 244
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 44,245评论 0 213
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 52,596评论 3 288
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,747评论 1 222
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,977评论 2 315
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,708评论 0 204
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,448评论 1 246
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,657评论 2 249
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 32,141评论 1 261
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,493评论 3 258
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 33,153评论 3 238
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,108评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,890评论 0 198
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,799评论 2 277
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,685评论 2 272

推荐阅读更多精彩内容

  • 关于微信支付 生活中的微信支付 目前我们日常生活中接触得比较多的线上电子支付方式主要有两种,一种是支付宝,另一种就...
    积_渐阅读 3,890评论 3 26
  • 近期在做微信小程序时,涉及到了小程序的支付和退款流程,所以也大概的将这方面的东西看了一个遍,就在这篇博客里总结一下...
    极乐叔阅读 3,023评论 1 12
  • 近期在项目时,涉及到了微信支付和退款流程,所以也大概的将这方面的东西看了一个遍,就在这篇博客里总结一下。 首先说明...
    一分耕耘一分收获阅读 44,149评论 0 9
  • 前言:本篇文章目的在于梳理知识,巩固思想,学习总结。有什么好的建议,都可以留言。互相促进!总观,微信支付,也没心思...
    麦穗0615阅读 9,827评论 8 70
  • 人的本质都是自私的,谁都不会无缘无故的对你好。 每个人的朋友都是基于他自己的选择,所以你接收到的信息也可以说是你自...
    不完美的你我他阅读 161评论 0 1