From b754fad9d004b02e6164208bbb21d44133a782d9 Mon Sep 17 00:00:00 2001 From: wangpengfei <1928057482@qq.com> Date: Fri, 29 Mar 2024 17:15:02 +0800 Subject: [PATCH] =?UTF-8?q?=E9=80=80=E6=AC=BE?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- pom.xml | 6 +- .../java/com/yxt/pay/api/refund/Refund.java | 8 + .../com/yxt/pay/api/refund/RefundOrder.java | 43 +++ .../yxt/pay/api/refund/RefundOrderDto.java | 20 + .../com/yxt/pay/api/refund/RefundOrderVo.java | 19 + .../pay/api/refund/WXRefundOrderReqVo.java | 53 +++ .../pay/api/refund/WXRefundOrderRespVo.java | 71 ++++ .../yxt/pay/biz/refund/WxRefundMapper.java | 13 + .../com/yxt/pay/biz/refund/WxRefundMapper.xml | 15 + .../com/yxt/pay/biz/refund/WxRefundRest.java | 49 +++ .../yxt/pay/biz/refund/WxRefundService.java | 365 ++++++++++++++++++ src/main/resources/cert/apiclient_cert.p12 | Bin 0 -> 2782 bytes src/main/resources/cert/apiclient_cert.pem | 25 ++ src/main/resources/cert/apiclient_key.pem | 28 ++ 14 files changed, 714 insertions(+), 1 deletion(-) create mode 100644 src/main/java/com/yxt/pay/api/refund/Refund.java create mode 100644 src/main/java/com/yxt/pay/api/refund/RefundOrder.java create mode 100644 src/main/java/com/yxt/pay/api/refund/RefundOrderDto.java create mode 100644 src/main/java/com/yxt/pay/api/refund/RefundOrderVo.java create mode 100644 src/main/java/com/yxt/pay/api/refund/WXRefundOrderReqVo.java create mode 100644 src/main/java/com/yxt/pay/api/refund/WXRefundOrderRespVo.java create mode 100644 src/main/java/com/yxt/pay/biz/refund/WxRefundMapper.java create mode 100644 src/main/java/com/yxt/pay/biz/refund/WxRefundMapper.xml create mode 100644 src/main/java/com/yxt/pay/biz/refund/WxRefundRest.java create mode 100644 src/main/java/com/yxt/pay/biz/refund/WxRefundService.java create mode 100644 src/main/resources/cert/apiclient_cert.p12 create mode 100644 src/main/resources/cert/apiclient_cert.pem create mode 100644 src/main/resources/cert/apiclient_key.pem diff --git a/pom.xml b/pom.xml index 95047d9..620afd0 100644 --- a/pom.xml +++ b/pom.xml @@ -36,7 +36,11 @@ org.springframework.cloud spring-cloud-starter-openfeign - + + com.github.wechatpay-apiv3 + wechatpay-java + 0.2.11 + junit diff --git a/src/main/java/com/yxt/pay/api/refund/Refund.java b/src/main/java/com/yxt/pay/api/refund/Refund.java new file mode 100644 index 0000000..6423c1e --- /dev/null +++ b/src/main/java/com/yxt/pay/api/refund/Refund.java @@ -0,0 +1,8 @@ +package com.yxt.pay.api.refund; + +/** + * @author wangpengfei + * @date 2024/3/25 15:03 + */ +public class Refund { +} diff --git a/src/main/java/com/yxt/pay/api/refund/RefundOrder.java b/src/main/java/com/yxt/pay/api/refund/RefundOrder.java new file mode 100644 index 0000000..500d62c --- /dev/null +++ b/src/main/java/com/yxt/pay/api/refund/RefundOrder.java @@ -0,0 +1,43 @@ +package com.yxt.pay.api.refund; + +import com.yxt.common.base.utils.StringRandom; +import com.yxt.common.core.domain.BaseEntity; +import lombok.Data; + +import java.text.SimpleDateFormat; +import java.util.Date; + +/** + * @author wangpengfei + * @date 2024/3/28 9:47 + */ +@Data +public class RefundOrder extends BaseEntity { + private String outTradeNo;//订单编号 + private int source;//来源 0云菜窖 + private String name;//商品名 + private String amount;//金额 + private String openId;// + private String returnUrl;//业务回调 + private String orderSid;//支付订单sid + private String reason;//退款原因 + + + public String getTime() { + SimpleDateFormat format = new SimpleDateFormat("yyyyMMddHHmmss"); + return format.format(new Date()); + } + + public RefundOrder(int source) { + String Randomstr = StringRandom.getRandomString(15); + if (source == 0) {//云菜窖 + outTradeNo = "YCJ" + getTime() + Randomstr; + + } else if (source == 1) { + + } else if (source == 2) { + + } + this.source = source; + } +} diff --git a/src/main/java/com/yxt/pay/api/refund/RefundOrderDto.java b/src/main/java/com/yxt/pay/api/refund/RefundOrderDto.java new file mode 100644 index 0000000..8fce446 --- /dev/null +++ b/src/main/java/com/yxt/pay/api/refund/RefundOrderDto.java @@ -0,0 +1,20 @@ +package com.yxt.pay.api.refund; + +import lombok.Data; + +/** + * @author wangpengfei + * @date 2024/3/28 9:57 + */ +@Data +public class RefundOrderDto { + private String outTradeNo;//订单编号 + private int source;//来源 0云菜窖 + private String name;//商品名 + private String amount;//金额 + private String openId;// + private String returnUrl;//业务回调 + private String orderSid;//支付订单sid + private String reason;//退款原因 + private String state;//1退款申请 2退款通过 +} diff --git a/src/main/java/com/yxt/pay/api/refund/RefundOrderVo.java b/src/main/java/com/yxt/pay/api/refund/RefundOrderVo.java new file mode 100644 index 0000000..2a645f5 --- /dev/null +++ b/src/main/java/com/yxt/pay/api/refund/RefundOrderVo.java @@ -0,0 +1,19 @@ +package com.yxt.pay.api.refund; + +import lombok.Data; + +/** + * @author wangpengfei + * @date 2024/3/28 9:57 + */ +@Data +public class RefundOrderVo { + private String outTradeNo;//订单编号 + private String source;//来源 0云菜窖 + private String name;//商品名 + private String amount;//金额 + private String openId;// + private String returnUrl;//业务回调 + private String orderSid;//支付订单sid + private String reason;//退款原因 +} diff --git a/src/main/java/com/yxt/pay/api/refund/WXRefundOrderReqVo.java b/src/main/java/com/yxt/pay/api/refund/WXRefundOrderReqVo.java new file mode 100644 index 0000000..3152833 --- /dev/null +++ b/src/main/java/com/yxt/pay/api/refund/WXRefundOrderReqVo.java @@ -0,0 +1,53 @@ +package com.yxt.pay.api.refund; + +import lombok.Data; + +/** + * @author wangpengfei + * @date 2024/3/25 15:49 + */ +@Data +public class WXRefundOrderReqVo { + /** + * 微信支付订单号,微信支付订单号和商家订单号二选一 + */ +// @Schema(description = "微信支付订单号") + private String transactionId; + + /** + * 商家订单号,对应 out_trade_no, + */ +// @Schema(description = "商家订单号") + private String orderId; + + /** + * 商户退款单号,对应out_refund_no + */ +// @Schema(description = "商户退款单号") + private String outRefundNo; + + /** + * 退款原因,选填 + */ +// @Schema(description = "退款原因") + private String reason; + + /** + * 回调地址 + */ +// @Schema(description = "回调地址") + private String notify; + + /** + * 退款金额 + */ +// @Schema(description = "退款金额") + private Integer refundMoney; + + /** + * 原订单金额,必填 + */ +// @Schema(description = "原订单金额") + private Integer totalMoney; + +} diff --git a/src/main/java/com/yxt/pay/api/refund/WXRefundOrderRespVo.java b/src/main/java/com/yxt/pay/api/refund/WXRefundOrderRespVo.java new file mode 100644 index 0000000..df6b167 --- /dev/null +++ b/src/main/java/com/yxt/pay/api/refund/WXRefundOrderRespVo.java @@ -0,0 +1,71 @@ +package com.yxt.pay.api.refund; + +import lombok.Data; + +/** + * @author wangpengfei + * @date 2024/3/25 15:51 + */ +@Data +public class WXRefundOrderRespVo { + /** + * 微信支付退款号 + */ +// @Schema(description = "微信支付退款号") + private String refundId; + + /** + * 商户退款单号 + */ +// @Schema(description = "商户退款单号") + private String outRefundNo; + + /** + * 微信支付订单号 + */ +// @Schema(description = "微信支付订单号") + private String transactionId; + + /** + * 商户订单号 + */ +// @Schema(description = "商户订单号") + private String outTradeNo; + + /** + * 退款渠道 + */ +// @Schema(description = "退款渠道") + private String channel; + + /** + * 退款入账账户 + */ +// @Schema(description = "退款入账账户") + private String userReceivedAccount; + + /** + * 退款成功时间 + */ +// @Schema(description = "退款成功时间") + private String successTime; + + /** + * 退款创建时间 + */ +// @Schema(description = "退款创建时间") + private String createTime; + + /** + * 退款状态 + */ +// @Schema(description = "退款状态") + private String status; + + /** + * 资金账户 + */ +// @Schema(description = "资金账户") + private String fundsAccount; + +} diff --git a/src/main/java/com/yxt/pay/biz/refund/WxRefundMapper.java b/src/main/java/com/yxt/pay/biz/refund/WxRefundMapper.java new file mode 100644 index 0000000..ced96bb --- /dev/null +++ b/src/main/java/com/yxt/pay/biz/refund/WxRefundMapper.java @@ -0,0 +1,13 @@ +package com.yxt.pay.biz.refund; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.yxt.pay.api.refund.RefundOrder; +import org.apache.ibatis.annotations.Mapper; + +/** + * @author wangpengfei + * @date 2024/3/25 15:02 + */ +@Mapper +public interface WxRefundMapper extends BaseMapper { +} diff --git a/src/main/java/com/yxt/pay/biz/refund/WxRefundMapper.xml b/src/main/java/com/yxt/pay/biz/refund/WxRefundMapper.xml new file mode 100644 index 0000000..29fd460 --- /dev/null +++ b/src/main/java/com/yxt/pay/biz/refund/WxRefundMapper.xml @@ -0,0 +1,15 @@ + + + + + + + \ No newline at end of file diff --git a/src/main/java/com/yxt/pay/biz/refund/WxRefundRest.java b/src/main/java/com/yxt/pay/biz/refund/WxRefundRest.java new file mode 100644 index 0000000..f90cb3b --- /dev/null +++ b/src/main/java/com/yxt/pay/biz/refund/WxRefundRest.java @@ -0,0 +1,49 @@ +package com.yxt.pay.biz.refund; + +import com.yxt.common.core.domain.BaseEntity; +import com.yxt.common.core.result.ResultBean; +import com.yxt.pay.api.refund.RefundOrder; +import com.yxt.pay.api.refund.RefundOrderDto; +import com.yxt.pay.api.refund.WXRefundOrderReqVo; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.bind.annotation.*; + +import javax.servlet.http.HttpServletRequest; + +/** + * @author wangpengfei + * @date 2024/3/25 15:02 + */ +@RestController +@RequestMapping("refund") +public class WxRefundRest { + @Autowired + WxRefundService refundService; + + + + @PostMapping("/createRefundOrder" ) + public ResultBean createRefundOrder(@RequestBody RefundOrderDto refundOrderDto) { + return refundService.createRefundOrder(refundOrderDto); + } + + + + @PostMapping("/reviewRefund" ) + public ResultBean reviewRefundById(@RequestParam String orderSid) throws Exception { + return refundService.refund(orderSid); + } + /** + * 微信退款回调 + * @return R + */ +// @Operation(summary = "微信退款回调" , description = "微信退款回调" ) +// @SysLog("微信退款回调" ) + @PostMapping("/payNotify") + public ResultBean refundPayNotify(HttpServletRequest request) throws Exception { + ResultBean rb=new ResultBean(); + refundService.refundNotify(request);//注意:回调接口需要暴露到公网上,且要放开token验证 + return rb.success(); + } + +} diff --git a/src/main/java/com/yxt/pay/biz/refund/WxRefundService.java b/src/main/java/com/yxt/pay/biz/refund/WxRefundService.java new file mode 100644 index 0000000..ed97fbc --- /dev/null +++ b/src/main/java/com/yxt/pay/biz/refund/WxRefundService.java @@ -0,0 +1,365 @@ +package com.yxt.pay.biz.refund; +import cn.hutool.core.bean.BeanUtil; +import com.alibaba.fastjson.JSON; +import com.alibaba.fastjson.JSONObject; +import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; +import com.wechat.pay.java.core.Config; +import com.wechat.pay.java.core.RSAAutoCertificateConfig; +import com.wechat.pay.java.core.exception.ServiceException; +import com.wechat.pay.java.core.notification.NotificationConfig; +import com.wechat.pay.java.core.notification.NotificationParser; +import com.wechat.pay.java.core.notification.RequestParam; +import com.wechat.pay.java.service.partnerpayments.app.model.Transaction; +import com.wechat.pay.java.service.refund.RefundService; +import com.wechat.pay.java.service.refund.model.*; +import com.yxt.common.base.service.MybatisBaseService; +import com.yxt.common.core.result.ResultBean; +import com.yxt.pay.api.order.PayOrder; +import com.yxt.pay.api.refund.RefundOrder; +import com.yxt.pay.api.refund.RefundOrderDto; +import com.yxt.pay.api.refund.WXRefundOrderReqVo; +import com.yxt.pay.api.refund.WXRefundOrderRespVo; +import com.yxt.pay.api.wxpay.WxPayVo; +import com.yxt.pay.biz.order.OrderService; +import com.yxt.pay.utils.UrlComponent; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.stereotype.Service; + +import javax.servlet.ServletInputStream; +import javax.servlet.http.HttpServletRequest; +import java.io.BufferedReader; +import java.io.InputStreamReader; +import java.util.HashMap; +import java.util.Map; + +import static com.wechat.pay.java.core.http.Constant.*; + +/** + * @author wangpengfei + * @date 2024/3/25 15:02 + */ +@Service +@Slf4j +public class WxRefundService extends MybatisBaseService { + + @Autowired + private UrlComponent urlComponent; + @Autowired + private OrderService orderService; + @Value("${wx.api-key}") + String apiKey; + @Value("${wx.mch-serial-no}") + String mchSerialNo; + @Value("${wx.key-path}") + String keyPath; + @Value("${wx.mch-id}") + String mchId; + + public static int source; + + + + public ResultBean createRefundOrder(RefundOrderDto refundOrderDto){ + ResultBean rb=new ResultBean(); + RefundOrder refundOrder=new RefundOrder(refundOrderDto.getSource()); + BeanUtil.copyProperties(refundOrderDto,refundOrder,"id","sid"); + baseMapper.insert(refundOrder); + return rb.success().setData(refundOrder); + + } + /** + * 功能描述: + * 〈微信退款〉 + * @Param: [req] + * @Return: [void] + * @Author: whl + * @Date: 2023/10/12 15:46 + */ + public ResultBean refund(String orderSid) throws Exception { + ResultBean rb = ResultBean.fireFail(); + try { + PayOrder payOrder=orderService.getOne(new QueryWrapper().eq("sid",orderSid)); + WxPayVo wxPayVo=new WxPayVo(payOrder.getSource()); + source=payOrder.getSource(); + // 使用自动更新平台证书的RSA配置 + // 一个商户号只能初始化一个配置,否则会因为重复的下载任务报错 + Config config = + new RSAAutoCertificateConfig.Builder() + .merchantId(mchId) + //使用 SDK 不需要计算请求签名和验证应答签名 + // 使用 com.wechat.pay.java.core.util 中的函数从本地文件中加载商户私钥,商户私钥会用来生成请求的签名 + .privateKeyFromPath(keyPath) + .merchantSerialNumber(mchSerialNo) + .apiV3Key(apiKey) + .build(); + // 构建退款service + RefundService service = new RefundService.Builder().config(config).build(); + // request.setXxx(val)设置所需参数,具体参数可见Request定义 + //构建退款请求 + CreateRequest request = new CreateRequest(); + //构建订单金额信息 + AmountReq amountReq = new AmountReq(); +// PayOrder payOrder=orderService.getOne(new QueryWrapper().eq("sid",orderSid)); + RefundOrder refundOrder=baseMapper.selectOne(new QueryWrapper().eq("orderSid",payOrder.getSid())); + //退款金额 + amountReq.setRefund(Long.valueOf(payOrder.getTotalTee())); +// amountReq.setRefund(Long.valueOf("1")); + //原订单金额 + amountReq.setTotal(Long.valueOf(payOrder.getTotalTee())); +// amountReq.setTotal(Long.valueOf("1")); + //货币类型(默认人民币) + amountReq.setCurrency("CNY"); + request.setAmount(amountReq); + //商户退款单号 + request.setOutRefundNo(String.valueOf(payOrder.getOutTradeNo())); +// request.setOutRefundNo(String.valueOf("ceshi")); + request.setOutTradeNo(refundOrder.getOutTradeNo()); +// request.setOutTradeNo("ceshi"); + request.setReason(refundOrder.getReason()); +// request.setReason("ceshi"); + //退款通知回调地址 +// request.setNotifyUrl(wxPayV3Bean.getRefundNotifyUrl()); + request.setNotifyUrl(urlComponent.getDoMainUrl() + "order/payNotify"); + // 调用退款方法,得到应答 + // 调用微信sdk接口 + Refund refund = service.create(request); + //接收退款返回参数 + Refund refundResponse = new Refund(); + refundResponse.setStatus(refund.getStatus()); + System.out.println(refund);; + if (refundResponse.getStatus().equals(Status.SUCCESS)){ + //说明退款成功,开始接下来的业务操作 +// WXRefundOrderRespVo refundOrderRespVO = new WXRefundOrderRespVo(); + //你的业务代码 + return rb.success().setData(refund); + }else{ + + return rb.setMsg("申请退款失败").setData(refund); + } + }catch (Exception e){ + e.printStackTrace(); + return rb.setMsg("退款失败,error=" + e.getMessage()); +// throw new ResultException(ResultEnum.ERROR,e.toString()); + } + } + + /** + * 功能描述: + * 〈微信退款回调〉 + * @Param: [request, response] + * @Return: [void] + * @Author: whl + * @Date: 2023/10/13 10:46 + */ + public void refundNotify(HttpServletRequest request) throws Exception { + try { + WxPayVo wxPayVo=new WxPayVo(0); + //读取请求体的信息 + ServletInputStream inputStream = request.getInputStream(); + StringBuffer stringBuffer = new StringBuffer(); + BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(inputStream)); + String s; + //读取回调请求体 + while ((s = bufferedReader.readLine()) != null) { + stringBuffer.append(s); + } + String s1 = stringBuffer.toString(); + String timestamp = request.getHeader(WECHAT_PAY_TIMESTAMP); + String nonce = request.getHeader(WECHAT_PAY_NONCE); + String signType = request.getHeader("Wechatpay-Signature-Type"); + String serialNo = request.getHeader(WECHAT_PAY_SERIAL); + String signature = request.getHeader(WECHAT_PAY_SIGNATURE); + // 如果已经初始化了 RSAAutoCertificateConfig,可直接使用 + // 没有的话,则构造一个 +// log.error(JSON.toJSONString(wxPayV3Bean)); + NotificationConfig config = new RSAAutoCertificateConfig.Builder() + .merchantId(mchId) + .privateKeyFromPath(keyPath) + .merchantSerialNumber(mchSerialNo) + .apiV3Key(apiKey) + .build(); + // 初始化 NotificationParser + NotificationParser parser = new NotificationParser(config); + RequestParam requestParam=new RequestParam.Builder() + .serialNumber(serialNo) + .nonce(nonce) + .signature(signature) + .timestamp(timestamp) + // 若未设置signType,默认值为 WECHATPAY2-SHA256-RSA2048 + .signType(signType) + .body(s1) + .build(); + RefundNotification parse = parser.parse(requestParam, RefundNotification.class); + System.out.println("退款回调结果: " + parse); + //parse.getRefundStatus().equals("SUCCESS");说明退款成功 + if (parse.getRefundStatus().equals(Transaction.TradeStateEnum.SUCCESS)){ + //你的业务代码 + + }else{ + + } + } catch (Exception e) { + e.printStackTrace(); + } + } + + + + +// //url 微信退款请求地址 data 请求参数 +// public static String doRefund(String url, String data) throws Exception { +// +// KeyStore keyStore = KeyStore.getInstance("PKCS12"); +// // 指定证书路径 +// String path = "/cert/apiclient_cert.p12"; +// ClassPathResource classPathResource = new ClassPathResource(path); +// +// //读取项目存放的PKCS12证书文件 +// InputStream stream = classPathResource.getInputStream(); +// String mchId = "自己的商户id"; +// try { +// //指定PKCS12的初始密码为商户ID +// keyStore.load(stream, mchId.toCharArray()); +// } finally { +// stream.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(); +// } +// } +// /** +// * 退款 +// * @param orderPrice 订单金额(分) +// * @param refundPrice 退款金额(分) +// * @param refundMark 退款备注 +// * @param out_trade_no 退款商家订单号 +// * @return +// * @throws Exception +// */ +// public static String refund(Integer orderPrice,Integer refundPrice,String refundMark,String out_trade_no) throws Exception { +// Map params = new HashMap<>(); +// +// String outRefundNo = GenerateNum.getInstance().GenerateOrder();//可以自定义一个类来随机生成退款单号等等 +// +// params.put("appid", "小程序Appid"); +// params.put("mch_id", "商户号"); +// //商户订单号 +// params.put("out_trade_no", out_trade_no); +// //商户退款单号 +// params.put("out_refund_no", outRefundNo); +// //总金额 +// params.put("total_fee", String.valueOf(orderPrice)); +// //退款金额 +// params.put("refund_fee", String.valueOf(refundPrice)); +// //退款原因 +// params.put("refund_desc", refundMark); +// //退款结果回调地址 +// params.put("notify_url", "回调域名"); +// //随机字符串 +// params.put("nonce_str", WXPayUtil.generateNonceStr());//使用微信随机字符串生成 +// //生成sign +// String sign = WXPayUtil.generateSignature(params, "自己的商户密钥"); +// params.put("sign", sign); +// //微信申请退款接口 +// String wx_refund_url = "https://api.mch.weixin.qq.com/secapi/pay/refund"; +// +// String xmlStr = WXPayUtil.mapToXml(params);//转换成xml格式 +// System.out.println(xmlStr); +// //发送双向证书请求给微信 +// String resultXmlStr = doRefund(wx_refund_url, xmlStr); +// System.out.println(resultXmlStr); +// // 将返回的字符串转成Map集合 +// Map resultMap = WXPayUtil.xmlToMap(resultXmlStr);//转成map格式 +// +// Map map = new HashMap<>(); +// if ("SUCCESS".equalsIgnoreCase(resultMap.get("result_code"))) { +// System.out.println("------申请退款成功,正在退款中----"); +// //申请微信退款接口返回success,但是退款到账还需要时间; +// map.put("success", "REFUNDS"); +// return "1"; +// } else { +// map.put("success", resultMap.get("err_code_des")); +// System.out.println("-------------退款失败-------------------" + resultMap.get("err_code_des")); +// return "2"; +// } +// } +// /* +// * 退款订单结果查询 +// * 生成签名的xml +// * @return +// * */ +// public static String selRefundOrder(String out_trade_no) { +// // 封装需要的信息 +// Map payMap = new HashMap(); +// String nonceStr = WXPayUtil.generateNonceStr(); +// try { +// // 1. 拼接下单地址参数 +// Map param = new HashMap(); +// param.put("appid", "小程序appid"); +// param.put("mch_id", "商户id"); +// param.put("out_trade_no", out_trade_no); // 随机字符串 +// param.put("nonce_str", nonceStr); // 账单类型 +// param.put("sign_type", "MD5"); // 签名类型 +// // 生成签名,官方默认MD5+商户秘钥+参数信息 +// String sign = WXPayUtil.generateSignature(param, "商户密钥"); +// param.put("sign", sign); +// // 将所有参数转换为xml形式 +// String xmlParam = WXPayUtil.mapToXml(param); +// +// // 2. 发送请求 +// HttpClient1 httpClient1 = new HttpClient1("https://api.mch.weixin.qq.com/pay/refundquery"); +// httpClient1.setHttps(true);// https协议 +// httpClient1.setXmlParam(xmlParam); +// httpClient1.post(); +// // 获取结果 +// String xmlResult = httpClient1.getContent(); +// System.out.println(xmlResult); +// if (xmlResult.indexOf("SUCCESS") != -1) { // 只要执行了下单接口,都会包含SUCCESS的 +// Map map = WXPayUtil.xmlToMap(xmlResult); +// if (map.get("refund_fee").equals(map.get("total_fee"))){ +// System.out.println(out_trade_no+"退款"+map.get("refund_fee")+"成功到"+map.get("refund_recv_accout_0")); +// return "1"; +// }else { +// System.out.println(out_trade_no+"退款"+map.get("refund_fee")+"部分到"+map.get("refund_recv_accout_0")); +// return "2"; +// } +// +// }else { +// System.out.println(out_trade_no+"退款失败,不存在"); +// return "3"; +// } +// +// } catch (Exception e) { +// e.printStackTrace(); +// payMap.put("msg", out_trade_no+"签名生成错误"); +// return "签名失败"; +// } +// } + +} diff --git a/src/main/resources/cert/apiclient_cert.p12 b/src/main/resources/cert/apiclient_cert.p12 new file mode 100644 index 0000000000000000000000000000000000000000..9af0641863916ad9f11c78ef4e23baf5df6418ef GIT binary patch literal 2782 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