微信APP退款功能开发

前期准备工作

1.之前微信APP支付的博客

  • 1.1 前期获取的参数
  • 1.2 配置及参数
https://blog.csdn.net/liang1184750950/article/details/100556420

2.退款证书

  • 2.1 微信退款需要使用双向证书,具体获取方式可登录微信商户平台-API安全进行获取
    在这里插入图片描述
  • 2.2 获取的证书样式
    在这里插入图片描述
  • 2.3 .p12证书放在项目resource目录下面进行证书的读取

实战

1. 请求参数及返回值

  • 1.1 请求参数
@Data
@AllArgsConstructor
public class WeChatRefundCommand {
    @NotNull
    private String outTradeNo;//商户订单号
    @NotNull
    private Integer totalFee;
    @NotNull
    private Integer refundFee;
}
  • 1.2 返回值
@Setter
@Getter
@AllArgsConstructor
@Builder
public class WeChatRefundResponse {
    private String result; // 不参与签名,成功标志

}

代码

    public WeChatRefundResponse refund(WeChatRefundCommand command) throws Exception {
        //请求参数转xml格式
        String xml = generateRefundParams(command);
        //证书加载,调用退款接口
        String returnXml = CertHttpUtil.***postData***(WeChatProperty.REFUND_URL, xml, WeChatProperty.MCH_ID, WeChatProperty.SSL_URL);
        //把得到的返回值xml转map
        Map<String, String> returnMap = WXPayUtil.xmlToMap(returnXml);
        if (returnMap.get("return_code").equals(ResultCode.SUCCESS)) {
            return new WeChatRefundResponse(ResultCode.SUCCESS);
        }else {
            return new WeChatRefundResponse(ResultCode.FAILURE);
        }
    }

    private String generateRefundParams(WeChatRefundCommand command) throws Exception {
        SortedMap<String, String> packageParams = new TreeMap<String, String>();
        packageParams.put("appid",  WeChatProperty.APP_ID);
        packageParams.put("mch_id", WeChatProperty.MCH_ID);
        packageParams.put("nonce_str",  WeChatPayUtil.generateNonceStr());
        packageParams.put("out_trade_no", command.getOutTradeNo());
        packageParams.put("out_refund_no", WeChatPayUtil.generateTradeId());
        packageParams.put("total_fee", command.getTotalFee().toString());
        packageParams.put("refund_fee", command.getRefundFee().toString());
        String sign = WXPayUtil.generateSignature(packageParams, WeChatProperty.KEY);
        packageParams.put("sign", sign);
        return WXPayUtil.mapToXml(packageParams);
    }

    
    /**
     * 通过Https往API post xml数据
     *
     * @param url API地址
     * @param xmlObj 要提交的XML数据对象
     * @param mchId 商户ID
     * @param certPath 证书位置
     * @return
     */
    public static String ***postData***(String url, String xmlObj, String mchId, String certPath) {
        // 加载证书
        try {
            initCert(mchId, certPath);
        } catch (Exception e) {
            e.printStackTrace();
        }
        String result = null;
        HttpPost httpPost = new HttpPost(url);
        // 得指明使用UTF-8编码,否则到API服务器XML的中文不能被成功识别
        StringEntity postEntity = new StringEntity(xmlObj, "UTF-8");
        httpPost.addHeader("Content-Type", "text/xml");
        httpPost.setEntity(postEntity);
        // 根据默认超时限制初始化requestConfig
        requestConfig = RequestConfig.custom().setSocketTimeout(socketTimeout).setConnectTimeout(connectTimeout).build();
        // 设置请求器的配置
        httpPost.setConfig(requestConfig);
        try {
            HttpResponse response = null;
            try {
                response = httpClient.execute(httpPost);
            } catch (IOException e) {
                e.printStackTrace();
            }
            HttpEntity entity = response.getEntity();
            try {
                result = EntityUtils.toString(entity, "UTF-8");
            } catch (IOException e) {
                e.printStackTrace();
            }
        } finally {
            httpPost.abort();
        }
        return result;
    }

    /**
     * 加载证书
     *
     * @param mchId 商户ID
     * @param certPath 证书位置
     * @throws Exception
     */
    public static void initCert(String mchId, String certPath) throws Exception {
        // 证书密码,默认为商户ID
        String key = mchId;
        // 证书的路径
        String path = certPath;
        // 指定读取证书格式为PKCS12
        KeyStore keyStore = KeyStore.getInstance("PKCS12");
        // 读取本机存放的PKCS12证书文件
        ClassPathResource cp = new ClassPathResource("apiclient_cert.p12");
        InputStream instream = cp.getInputStream();
        try {
            // 指定PKCS12的密码(商户ID)
            keyStore.load(instream, key.toCharArray());
        } finally {
            instream.close();
        }
        SSLContext sslcontext = SSLContexts.custom().loadKeyMaterial(keyStore, key.toCharArray()).build();
        SSLConnectionSocketFactory sslsf =
                new SSLConnectionSocketFactory(sslcontext, new String[] {"TLSv1"}, null,
                        SSLConnectionSocketFactory.BROWSER_COMPATIBLE_HOSTNAME_VERIFIER);
        httpClient = HttpClients.custom().setSSLSocketFactory(sslsf).build();
    }

总结

微信退款个人觉得没有支付宝退款简单,就获取证书这方面就较为复杂,包括加载证书进行退款。希望代码可以对码农们有些帮助!

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值