微信退款流程V1(native)退款- java 代码

cxdm我又来了,我是这次带来的是微信Native退款V1流程的踩坑日记,同样的需要交流请加wx:w18013425493 大哥们轻点!!!闲话少说,上菜! 

先把垃圾的微信官方支付文档地址给你发一下,我用的是v1:https://pay.weixin.qq.com/wiki/doc/api/native.php?chapter=9_4

还有相关文档我没有用过这个新的官方文档:

https://pay.weixin.qq.com/wiki/doc/apiv3/wxpay/pages/index.shtml

好了开始正片

退款流程:

接口链接:https://api.mch.weixin.qq.com/secapi/pay/refund

看到那个需要双向证书这几个字了吗? 这就是点,他没告诉你怎么用  我来告诉你: 

申请证书的流程:

首先:你应该和你的财务去,交涉让他去申请证书,也就是注册这个微信的人,也就是app_id 和 mch_id的拥有者,至于申请流程,我懂你,那些人估计不明白,还得你去找,我帮说一下流程吧

 

 一直一步就完事了,这就是证书的样子

 第二步 把证书放到改放的位置 我当时自测测试是放在本地 测试是放在linux服务器,映射到docker

代码实现:

 点击证书使用

 点击SDK与DEMO下载

把下载的解压出来你使劲往里点,这里会解压出来好多工具类,可以点进去看看,有些用不到的

这个是我导入的工具类,可以参考一下

 参数拼接+验证证书调用:

/**
 * 微信退款
 */
@RefreshScope
@Component
@Slf4j
public class WxRefund {

    // =======【微信小程序】========
    public static String WXMINI_APPID = "";
    private static String WXMINI_MCHID = "";
    public static String KEY = "";
    /**
     * 这些URl本来要写nacos动态配置里面,但是当事人赶工期,就没时间写,后面如果有空就搬迁过去,别骂!!!🙅🏻‍
     */
//    @Value("${wxRefundUrl}")
    private static String wxRefundUrl = "https://api.mch.weixin.qq.com/secapi/pay/refund";
    private static String mac_file_path = "";
    private static String linux_file_path = "";

    /**
     * 调用微信退款流程
     * @param ""
     * @param ""
     * @return
     * @throws WxPayException
     * @throws IOException
     * @throws NoSuchAlgorithmException
     * @throws ParserConfigurationException
     * @throws SAXException
     */
   public static Map<String, String> wxRefund(Long "", String "", BigDecimal "") throws Exception {
       //参数拼接
       SortedMap<String, String> param = new TreeMap<String, String>();
       param.put("appid", "");
       param.put("mch_id", "");
       //这个参数可以是雪花算法就好,这个就是生成工具类,我们公司的,你可以去cv一个
       param.put("nonce_str", IdWorkerKit.get32UUID());

       param.put("out_trade_no","");
       param.put("out_refund_no", "");
       int moneyToInt = money.multiply(new BigDecimal(100)).intValue();
       //微信支付那边不接受小数,按分计算 这块是个小坑
       param.put("total_fee", String.valueOf(moneyToInt));
       param.put("refund_fee", String.valueOf(moneyToInt));
       //这个地方就是用到前面提到的工具类
       String generateSignature = WXPayUtil.generateSignature(param, KEY, WXPayConstants.SignType.MD5);
       param.put("sign", generateSignature);
       //按微信退款格式生成参数
       String requestParam = WXPayUtil.generateSignedXml(param, KEY);
       //验证证书是否正确并调用微信退款接口
       String result = CommonUtil.postData(wxRefundUrl, requestParam,linux_file_path, WXMINI_MCHID);
       return WXPayUtil.xmlToMap(result);
   }
}

验证证书+调用微信退款接口

import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.security.*;
import java.security.cert.CertificateException;

import javax.net.ssl.KeyManagerFactory;
import javax.net.ssl.SSLContext;

import lombok.extern.slf4j.Slf4j;
import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.client.HttpClient;
import org.apache.http.client.config.RequestConfig;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.config.RegistryBuilder;
import org.apache.http.conn.socket.ConnectionSocketFactory;
import org.apache.http.conn.socket.PlainConnectionSocketFactory;
import org.apache.http.conn.ssl.DefaultHostnameVerifier;
import org.apache.http.conn.ssl.SSLConnectionSocketFactory;
import org.apache.http.conn.ssl.SSLContexts;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClientBuilder;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.impl.conn.BasicHttpClientConnectionManager;
import org.apache.http.util.EntityUtils;

import static com.wxrefund.WXPayConstants.USER_AGENT;


@Slf4j
public class CommonUtil {
    // 连接超时时间,默认10秒
    private static int socketTimeout = 10000;
    // 传输超时时间,默认30秒
    private static int connectTimeout = 30000;
    // 请求器的配置
    private static RequestConfig requestConfig;
    // HTTP请求器
    private static CloseableHttpClient httpClient;

    /**
     * 通过Https往API post xml数据
     *
     * @param url    API地址
     * @param xmlObj 要提交的XML数据对象
     * @return
     */
    public static String postData(String url, String xmlObj, String path, String mchId) throws IOException {
        BasicHttpClientConnectionManager basicHttpClientConnectionManager = null;
        try {
            // 加载证书 和验证证书
            basicHttpClientConnectionManager = initCertV1(path, mchId);
        } catch (Exception e) {
            e.printStackTrace();
        }
        //调用微信退款接口
        HttpClient httpClient = HttpClientBuilder.create()
                .setConnectionManager(basicHttpClientConnectionManager)
                .build();
        HttpPost httpPost = new HttpPost(url);
        RequestConfig requestConfig = RequestConfig.custom().setSocketTimeout(socketTimeout).setConnectTimeout(connectTimeout).build();
        httpPost.setConfig(requestConfig);
        StringEntity postEntity = new StringEntity(xmlObj, "UTF-8");
        httpPost.addHeader("Content-Type", "text/xml");
        httpPost.addHeader("User-Agent", USER_AGENT + " " + mchId);
        httpPost.setEntity(postEntity);
        HttpResponse httpResponse = httpClient.execute(httpPost);
        HttpEntity httpEntity = httpResponse.getEntity();
        return EntityUtils.toString(httpEntity, "UTF-8");

    }

    /**
     * 加载证书和验证证书
     * @param path
     * @param mchId
     * @return
     * @throws KeyStoreException
     * @throws CertificateException
     * @throws IOException
     * @throws NoSuchAlgorithmException
     * @throws UnrecoverableKeyException
     * @throws KeyManagementException
     */
    public static BasicHttpClientConnectionManager initCertV1(String path, String mchId) throws KeyStoreException, CertificateException, IOException, NoSuchAlgorithmException, UnrecoverableKeyException, KeyManagementException {

        char[] password = mchId.toCharArray();

        InputStream certStream = Files.newInputStream(Paths.get(path));
        KeyStore ks = KeyStore.getInstance("PKCS12");
        ks.load(certStream, password);

        // 实例化密钥库 & 初始化密钥工厂
        KeyManagerFactory kmf = KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm());
        kmf.init(ks, password);

        // 创建 SSLContext
        SSLContext sslContext = SSLContext.getInstance("TLS");
        sslContext.init(kmf.getKeyManagers(), null, new SecureRandom());
        //这里有个大坑,这个调用是微信提供的调用demo,但是会有个问题,就是要去掉一个参数
        //这里我已经填平了,放心使用,外面会给你放图片
        SSLConnectionSocketFactory sslConnectionSocketFactory = new SSLConnectionSocketFactory(
                sslContext,
                null,
                null,
                new DefaultHostnameVerifier());


        return new BasicHttpClientConnectionManager(
                RegistryBuilder.<ConnectionSocketFactory>create()
                        .register("http", PlainConnectionSocketFactory.getSocketFactory())
                        .register("https", sslConnectionSocketFactory)
                        .build(),
                null,
                null,
                null
        );
    }
}

这个是一个大坑微信提供的文档是这个样子,一定要把他弄成null,不然他就一直会报错

No appropriate protocol (protocol is disabled or cipher suites are inappropriate)

好了大概到里基本就完事了,5000字吧,不少了,慢慢写别急,多要工期,摸摸鱼学学习,还是希望能帮到你,如果实在来不及就不用点赞了,来得及就还是点点赞哈哈哈哈哈哈!!!都兄弟客气啥,回见了您吶;

 

  • 7
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值