WeChat Refund of WeChat Pay


official documentation

Whether swiping card payment, WeChat official account payment, scanning code payment, H5 payment, APP payment, etc. have 申请退款APIthe same interface, this article takes the example 刷卡支付of the application for refund API document

Application scenarios

When a refund is required for a period of time after the transaction occurs due to the buyer or seller, the seller can return the payment to the buyer through the refund interface, and WeChat Pay will receive the refund request and verify it successfully 按照退款规则将支付款按原路退到买家帐号上.

Precautions

  1. Refunds cannot be submitted for orders over one year old
  2. WeChat Pay refund supports multiple refunds for a single transaction. For multiple refunds, you need to submit the merchant order number of the original payment order and set a different refund order number. The total amount requested for a refund cannot exceed the order amount.一笔退款失败后重新提交,请不要更换退款单号,请使用原商户退款单号
  3. Request frequency limit: 150qps, that is, the normal number of refund requests per second does not exceed 150
  4. Error or invalid request frequency limit: 6qps, that is, no more than 6 abnormal or erroneous refund request requests per second
  5. Partial refunds for each paid order cannot exceed 50

Download certificate

Refer to Security Specifications -3. Merchant Certificate

Download: WeChat Merchant Platform (pay.weixin.qq.com) –> Account Center –> Account Settings –> API Security –> Certificate Download

Interfaces in 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);
    }

sample code

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);
    }

Synchronous return result XML reference

//退款
<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>

WeChat payment, Alipay payment blog column

If you have any questions, please leave a message for discussion

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=325726118&siteId=291194637