java微信退款(支持部分退款)

这里介绍两种退款方式:已封装和未封装两种形式

	maven 导入
 <dependency>
            <groupId>com.github.javen205</groupId>
            <artifactId>IJPay</artifactId>
            <version>1.2.0</version>
        </dependency>

一、未封装

退款需要准备证书,apiclient_cert.p12这个证书,证书下载地址看这里 http://kf.qq.com/faq/161222NneAJf161222U7fARv.html

放到resource中即可,在编译的时候保证能将它编译到class中,下面会说到

证书还有一点要注意,如果你放到resource中了但是不好使,具体报什么错忘了,需要加上支持:

       <plugin>
            <groupId>org.apache.maven.plugins</groupId>
            <artifactId>maven-resources-plugin</artifactId>
            <configuration>
                <encoding>UTF-8</encoding>
                <!-- 过滤后缀为pem、pfx的证书文件 -->
                <nonFilteredFileExtensions>
                    <nonFilteredFileExtension>pem</nonFilteredFileExtension>
                    <nonFilteredFileExtension>pfx</nonFilteredFileExtension>
                    <nonFilteredFileExtension>p12</nonFilteredFileExtension>
                </nonFilteredFileExtensions>
            </configuration>
        </plugin>

工具类都是全的,只需要小改一下自己的东西就可以实现了,目录如下:

在这里插入图片描述

里面有详细的说明,需要改动的是RefundUtil和ClientCustomSSL,其他不用动

RefundUtil

在这里插入图片描述

做过支付才做退款对吧, 所以我不多说了,上面的内容都改成自己平台的appid和密钥,具体在哪找自己百度

ClientCustomSSL
在这里插入图片描述

这个类需要指定证书,上面说过了,而

String path=this.getClass().getClassLoader().getResource("/").getPath();
就是获取证书的路径,自己可以编译一下看是不是在那个文件夹下,如果在就对了,如果不在,那肯定不行(这里我们采用的相对路径,这样放到哪里都不会错也不用改)

ok了,没什么了,默认读取证书密码退款就可以了

这是调用的代码:

    RefundUtil refundUtil = new RefundUtil();
    Map<String, String> map = refundUtil.wechatRefund(transaction_id, total_fee, refund_fee, request);
    log.info("返回map集合:" + map);
    String result_code = map.get("result_code");
    log.info("result_code退款状态:" + result_code);
    if (result_code.equals("SUCCESS")) {

成功后处理自己业务逻辑

退款成功返回map形式:以上面的形式取出要用的就可以

{
refund_id=50000105282018010,
refund_fee=9900,
coupon_refund_fee=0,
refund_channel=,
return_msg=OK,
appid=wxdlsfjldk,
nonce_str=FCAvhi2VeL0kYYn2,
out_trade_no=20183242336,
out_refund_no=3133e760-ccb9-4345-9466-ab2b68be,
transaction_id=42002343452454243231346161,
coupon_refund_count=0,
sign=BE4CCE8009E6A5CC32342342391B,
result_code=SUCCESS,
mch_id=134234234,
total_fee=9900,
return_code=SUCCESS,
cash_refund_fee=9900,
cash_fee=9900
}

二、未封装(ijpay的封装方式)

@ResponseBody
@RequestMapping(value ="/refund.do",method = {RequestMethod.POST,RequestMethod.GET})
public String refund(){
String certPath=this.getClass().getClassLoader().getResource("/").getPath()+“apiclient_cert.p12”;
System.out.println(“certPath:”+certPath);
String transaction_id = null;
String out_trade_no = “”;

	if (StrKit.isBlank(out_trade_no) && StrKit.isBlank(transaction_id)) {
		System.out.println("transactionId、out_trade_no二选一");
		return null;
	}

	Map<String, String> params = new HashMap<String, String>();
	params.put("appid", appID);
	params.put("mch_id", mchID);
	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", "100");
	params.put("refund_fee", "90");
	params.put("sign", PaymentKit.createSign(params, partnerKey));
	String refund = WxPayApi.orderRefund(false, params , certPath, mchID);
	System.out.println("refund:"+refund);
	return refund;
}

已测试,很简单,相信聪明的你一看就懂了

未封装工具类下载地址看这里看这里: http://download.csdn.net/download/goligory/10243034

引用退款博客链接:https://blog.csdn.net/zyw_java/article/details/79370616

作者:MTGG灬
来源:CSDN
原文:https://blog.csdn.net/goligory/article/details/79274416
版权声明:本文为博主原创文章,转载请附上博文链接!
官方文档
应用场景
注意事项
下载证书
IJPay 中的接口
示例代码
官方文档
无论刷卡支付、微信公众号支付、扫码支付、H5支付、APP支付等都有申请退款API并且接口一样,本篇文章就拿刷卡支付中的申请退款API文档举例

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

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

//退款查询错误示例

<![CDATA[wxxxx]]>
<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>
<![CDATA[7323459E0DE45DBB8C87932C4C99BBF3]]>

//退款查询


<![CDATA[wxxxx]]>
<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>
<![CDATA[E8A30F02296C6169860A92C2D52AD5A8]]>
<total_fee><![CDATA[1]]></total_fee>
<transaction_id><![CDATA[4200000100201801133414066940]]></transaction_id>

作者:酷玩时刻
来源:CSDN
原文:https://blog.csdn.net/zyw_java/article/details/79370616
版权声明:本文为博主原创文章,转载请附上博文链接!

  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值