微信支付之微信退款


官方文檔

無論刷卡支付、微信公衆號支付、掃碼支付、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

 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 params) {
        if (isSandbox)
            return doPost(REFUNDQUERY_SANDBOXNEW_URL, params);
        return doPost(REFUNDQUERY_URL, params);
    }

" data-snippet-id="ext.9f866db9c07b4c33161e65583204d445" data-snippet-saved="false" data-codota-status="done">    // 申請退款
    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>

微信支付、支付寶支付博客專欄

如有疑問歡迎留言交流討論

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章