JAVA 微信退款

6 篇文章 0 订阅
1 篇文章 0 订阅

今天来讲讲微信退款的功能吧

 

微信支付和支付宝支付的代码在我第一篇文章有讲  点我

 

首先准备的东西就是证书:

 

  

 

代码部分 :导入jar包


<!--微信退款-->
        <dependency>
            <groupId>com.github.wxpay</groupId>
            <artifactId>wxpay-sdk</artifactId>
            <version>0.0.3</version>
        </dependency>

        <dependency>
            <groupId>org.apache.httpcomponents</groupId>
            <artifactId>httpcore</artifactId>
            <version>4.4.8</version>
        </dependency>
        <dependency>
            <groupId>org.apache.httpcomponents</groupId>
            <artifactId>httpclient</artifactId>
            <version>4.5.3</version>
        </dependency>
        <dependency>
            <groupId>org.testng</groupId>
            <artifactId>testng</artifactId>
            <version>6.11</version>
            <scope>test</scope>
        </dependency>




package com.ja.mp.communal.config;

import lombok.extern.slf4j.Slf4j;
import org.apache.http.HttpEntity;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.conn.ssl.SSLConnectionSocketFactory;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.ssl.SSLContexts;
import org.apache.http.util.EntityUtils;
import org.springframework.util.ResourceUtils;

import javax.net.ssl.SSLContext;
import java.io.File;
import java.io.FileInputStream;
import java.security.KeyStore;

@Slf4j
public class ClientCustomSSL {
    public static String doRefund(String url, String data, String mchId) throws Exception {
        //指定读取证书格式为PKCS12(注意PKCS12证书 是从微信商户平台-》账户设置-》 API安全 中下载的)
        KeyStore keyStore = KeyStore.getInstance("PKCS12");
        String path = ResourceUtils.getURL("pay/apiclient_cert.p12").getPath();
        // 指定证书路径
        log.info("证书路径:"+path);
//        String path = "D:/test/pay/apiclient_cert.p12";
        //读取本机存放的PKCS12证书文件
        FileInputStream instream = new FileInputStream(new File(path));
        //比如安装在D:/pkcs12/apiclient_cert.p12情况下,就可以写成如下语句
        //E:/test/pay
        //FileInputStream instream = new FileInputStream(new File("D:/pay/apiclient_cert.p12"));
        try {
            //指定PKCS12的密码(商户ID)
            keyStore.load(instream, mchId.toCharArray());
        } finally {
            instream.close();
        }
        SSLContext sslcontext = SSLContexts.custom().loadKeyMaterial(keyStore,mchId.toCharArray()).build();
        //指定TLS版本
        SSLConnectionSocketFactory sslsf = new SSLConnectionSocketFactory(sslcontext, new String[]{"TLSv1"}, null, SSLConnectionSocketFactory.BROWSER_COMPATIBLE_HOSTNAME_VERIFIER);
        //设置httpclient的SSLSocketFactory
        CloseableHttpClient httpclient = HttpClients.custom().setSSLSocketFactory(sslsf).build();
        try {
            HttpPost httpost = new HttpPost(url); // 设置响应头信息
            httpost.addHeader("Connection", "keep-alive");
            httpost.addHeader("Accept", "*/*");
            httpost.addHeader("Content-Type", "application/x-www-form-urlencoded; charset=UTF-8");
            httpost.addHeader("Host", "api.mch.weixin.qq.com");
            httpost.addHeader("X-Requested-With", "XMLHttpRequest");
            httpost.addHeader("Cache-Control", "max-age=0");
            httpost.addHeader("User-Agent", "Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 6.0) ");
            httpost.setEntity(new StringEntity(data, "UTF-8"));
            CloseableHttpResponse response = httpclient.execute(httpost);
            try {
                HttpEntity entity = response.getEntity();
                String jsonStr = EntityUtils.toString(response.getEntity(), "UTF-8");
                EntityUtils.consume(entity);
                return jsonStr;
            } finally {
                response.close();
            }
        } finally {
            httpclient.close();
        }

    }
}

 

上面这个是公共模板,把证书文件放在对应的路径即可

 

业务代码

public Map<String, String> refund(String out_trade_no) throws Exception{
        String xmlStr = "";
        String resultXml = "";
        Map<String, String> resultMap = new HashMap<String, String>();
        // 公众账号ID:登陆微信公众号后台-开发-基本配置
        String appid = configuration.getAppId();
        // 微信支付商户号: mch_id-登陆微信支付后台,即可看到
        String mch_id = configuration.getMchId();
        // 随机字符串,长度要求在32位以内,调用工具类中的随机数生成方法
        String nonce_str = WXPayUtil.generateNonceStr();
        // 商户退款单号,同一单号多次请求,只退款一次
        String out_refund_no = UUIDGenerator.getInstance().get();
        //根据订单号查询信息
        Optional<OrderDetail> orderDetail = orderMapper.selectUnique(out_trade_no);
        String price = orderDetail.get().getOrderTotalPrice().toString();
        Double total_price = Double.valueOf(price);
        // 订单总金额
        String total_fee = Integer.toString((int) (total_price * 100));
        // 退款总金额
        String refund_fee = Integer.toString((int) (total_price * 100));
        // 退款原因,会在下发给用户的退款消息中体现(可不传入)
        String refund_desc = "退款";
        // API密钥(设置路径:微信商户平台(pay.weixin.qq.com)-->账户设置-->API安全-->密钥设置)
        String key = configuration.getKey();
        // 将获得的信息存入Map集合中
        Map<String, String> map = new HashMap<String, String>();
        map.put("appid", appid);
        map.put("mch_id", mch_id);
        map.put("nonce_str", nonce_str);
        map.put("out_trade_no", out_trade_no);
        map.put("out_refund_no", out_refund_no);
        map.put("total_fee", total_fee);
        map.put("refund_fee", refund_fee);
        map.put("refund_desc", refund_desc);
        try {
            // 调用工具类,将Map集合转化为带签名sign的XML格式字符串
            xmlStr = WXPayUtil.generateSignedXml(map, key);
            System.out.println(xmlStr);
            // 调用微信退款接口地址(固定写法)
            String url = "https://api.mch.weixin.qq.com/secapi/pay/refund";
            // 调用双向证书,返回xml格式状态码
            resultXml = ClientCustomSSL.doRefund(url, xmlStr, mch_id);
            System.out.println();
            System.out.println(resultXml);
            System.out.println();
            // 将返回结果转换成Map集合
            resultMap = WXPayUtil.xmlToMap(resultXml);
            System.out.println(resultMap);
        } catch (Exception e) {
            log.debug("调用退款接口失败");
            e.printStackTrace();
            throw e;
        }
        // 微信端返回字符串为成功时,退款成功,更新数据

        if (resultMap.get("return_code").equals(WXPayConstants.SUCCESS) && resultMap.get("result_code").equals(WXPayConstants.SUCCESS)) {
            // 退款成功时,在此处更改订单的状态,并更新数据库对应信息
            log.debug("退款成功");

            //将退款成功的数据保存到数据库
           

        } else {
            // 退款失败时,在此处设置相应信息,更新相应记录

            log.debug("退款失败");

        }

        //执行数据库更新动作
        // 处理人
        // 保存退款处理时间
        return resultMap;
    }

 

好了,微信退款即可完成, 注意的是一下几点  ,

 

1、 证书一定要放对,如果不知道证书或者弄丢了,可以去更换证书,一年只能更换3次,

2、 金额是以分为单位的,要 x100  ,

3、 一定一定要仔细的吧商户id ,appid等基础的配置给填写正确

4、 退款金额不能大于支付金额

4、 传入订单号 (这里可以是自己生成的订单号,也可以是微信支付的时候的订单号)

 

好了,来看看效果吧

 

 

 

 

评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值