14 changed files with 714 additions and 1 deletions
@ -0,0 +1,8 @@ |
|||
package com.yxt.pay.api.refund; |
|||
|
|||
/** |
|||
* @author wangpengfei |
|||
* @date 2024/3/25 15:03 |
|||
*/ |
|||
public class Refund { |
|||
} |
@ -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; |
|||
} |
|||
} |
@ -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退款通过
|
|||
} |
@ -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;//退款原因
|
|||
} |
@ -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; |
|||
|
|||
} |
@ -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; |
|||
|
|||
} |
@ -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<RefundOrder> { |
|||
} |
@ -0,0 +1,15 @@ |
|||
<?xml version="1.0" encoding="UTF-8" ?> |
|||
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd"> |
|||
<mapper namespace="com.yxt.pay.biz.refund.WxRefundMapper"> |
|||
<select id="selectBySn" resultType="com.yxt.pay.api.refund.Refund"> |
|||
select * |
|||
from pay_order |
|||
where outTradeNo = #{out_trade_no} |
|||
</select> |
|||
|
|||
<select id="selectOrderList" resultType="com.yxt.pay.api.refund.Refund"> |
|||
select * |
|||
from pay_order |
|||
where state = 1 |
|||
</select> |
|||
</mapper> |
@ -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(); |
|||
} |
|||
|
|||
} |
@ -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<WxRefundMapper,RefundOrder> { |
|||
|
|||
@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<PayOrder>().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<PayOrder>().eq("sid",orderSid));
|
|||
RefundOrder refundOrder=baseMapper.selectOne(new QueryWrapper<RefundOrder>().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<String, String> 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<String, String> resultMap = WXPayUtil.xmlToMap(resultXmlStr);//转成map格式
|
|||
//
|
|||
// Map<String, String> 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<String, String> payMap = new HashMap<String, String>();
|
|||
// String nonceStr = WXPayUtil.generateNonceStr();
|
|||
// try {
|
|||
// // 1. 拼接下单地址参数
|
|||
// Map<String, String> param = new HashMap<String, String>();
|
|||
// 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<String, String> 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 "签名失败";
|
|||
// }
|
|||
// }
|
|||
|
|||
} |
Binary file not shown.
@ -0,0 +1,25 @@ |
|||
-----BEGIN CERTIFICATE----- |
|||
MIIEMTCCAxmgAwIBAgIUdOW9WmRaHsToJigg4eKlKS20i50wDQYJKoZIhvcNAQEL |
|||
BQAwXjELMAkGA1UEBhMCQ04xEzARBgNVBAoTClRlbnBheS5jb20xHTAbBgNVBAsT |
|||
FFRlbnBheS5jb20gQ0EgQ2VudGVyMRswGQYDVQQDExJUZW5wYXkuY29tIFJvb3Qg |
|||
Q0EwHhcNMjQwMzI2MDI1OTA0WhcNMjkwMzI1MDI1OTA0WjCBijETMBEGA1UEAwwK |
|||
MTY2NDg4Mjc2NTEbMBkGA1UECgwS5b6u5L+h5ZWG5oi357O757ufMTYwNAYDVQQL |
|||
DC3lrofkv6HpgJrliJvmlrDmioDmnK/vvIjmsrPljJfvvInmnInpmZDlhazlj7gx |
|||
CzAJBgNVBAYTAkNOMREwDwYDVQQHDAhTaGVuWmhlbjCCASIwDQYJKoZIhvcNAQEB |
|||
BQADggEPADCCAQoCggEBANVl55NDuqDEvx/zQdaCn4WKUC8wLUVEYWKLMlChSZer |
|||
VQuQpRlC2lKDW03hKB6cAYH+jQg/pmBQnWbIjiBggyA41EUrCY2ps+CWI77fIAVk |
|||
wPxKz1/gk4xoYKbKvnDsSW6A0yWBvma4ZVLt3O2JTEPVo9xaM6/+oWCs4An654rx |
|||
ZBwnxb7mzVCXWJeTldWLtjwjby0Y6fvR7wrj2QhSPocz171bQhi1fF8JuQPWyIp/ |
|||
XkRRbVWjVIsEv/re80mhTH16ktJf6MhCtEM5l15+GWP8rjIDP2qqhn1m0nIRPTVy |
|||
Ut9SZS/bBCm9/Cywtw+C238mvjmItEH+uhK66L6PLzkCAwEAAaOBuTCBtjAJBgNV |
|||
HRMEAjAAMAsGA1UdDwQEAwID+DCBmwYDVR0fBIGTMIGQMIGNoIGKoIGHhoGEaHR0 |
|||
cDovL2V2Y2EuaXRydXMuY29tLmNuL3B1YmxpYy9pdHJ1c2NybD9DQT0xQkQ0MjIw |
|||
RTUwREJDMDRCMDZBRDM5NzU0OTg0NkMwMUMzRThFQkQyJnNnPUhBQ0M0NzFCNjU0 |
|||
MjJFMTJCMjdBOUQzM0E4N0FEMUNERjU5MjZFMTQwMzcxMA0GCSqGSIb3DQEBCwUA |
|||
A4IBAQAgxASDSwdZ8aIVMKha7LJQu3UTGtseO+q8VvfQMmBCN+eB20b+NOLHvfTi |
|||
ijEl+x7UBFk7kCbKWPlxL6Osqe8npIxWbLolZfqxi1d+UzokmpkjXYyKtsZnWDPZ |
|||
B6Y1Bc/J7khma7GzuEa/d29Z+si+eeiyNHdZUwZUZi/PFwO61KbGP2r11AuXa6W5 |
|||
ZYgQBw5sSfOxceoYBCIKTUO79hAOisSuGxP7yFqSalGYd85XG6t5UH5p224VHxVs |
|||
Dm+BoD1+w2jtBcAcdwrc3FGvR1mac1pd/LwMSYwfmDTHACWvCV88uN9TNvfbelHy |
|||
9f+Y8m563NzVPeWCD2sMqOJs6Ug5 |
|||
-----END CERTIFICATE----- |
@ -0,0 +1,28 @@ |
|||
-----BEGIN PRIVATE KEY----- |
|||
MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQDVZeeTQ7qgxL8f |
|||
80HWgp+FilAvMC1FRGFiizJQoUmXq1ULkKUZQtpSg1tN4SgenAGB/o0IP6ZgUJ1m |
|||
yI4gYIMgONRFKwmNqbPgliO+3yAFZMD8Ss9f4JOMaGCmyr5w7ElugNMlgb5muGVS |
|||
7dztiUxD1aPcWjOv/qFgrOAJ+ueK8WQcJ8W+5s1Ql1iXk5XVi7Y8I28tGOn70e8K |
|||
49kIUj6HM9e9W0IYtXxfCbkD1siKf15EUW1Vo1SLBL/63vNJoUx9epLSX+jIQrRD |
|||
OZdefhlj/K4yAz9qqoZ9ZtJyET01clLfUmUv2wQpvfwssLcPgtt/Jr45iLRB/roS |
|||
uui+jy85AgMBAAECggEAaL85mY6wSAPrMNqt4YaCmQEYdOE4B30WNFHRI8TXo8wk |
|||
1aVtdOXc1o3FvoebstKu5sk1HuxnVXWcnXwqT3gwRRvADiee69t2APKRnzpUtHEN |
|||
TYnHGu/YXR5K+vQf4LwLG2O+wPVbqX4vtjIttKclOVLfuOTJ5ESfoB2bZyqyhv8p |
|||
//odyC6+ryOs7+PbcDjChTjHkANT2y0JsQhkjgw9WmqjyrNH3BNAZ8djV4ilSJhz |
|||
XYiM+bkjwHEHwbQUJxhCUC0hKNNpxfxRC90J4ZNSJchqQdxG/zmn8Mw1rh239ydt |
|||
XXrs7Zeayx7mcr9UBBAjDDYBv+HAiHmieiNueg9wFQKBgQD92x1cOLzBD7YiGfvp |
|||
jmKsGZfAYmQQXCsP5thinPG95v5hR5LNoB6lZf27GhpdukKG58vsmJBW5iawF4ex |
|||
7SRBHWLEnTlP7SRpuycK0vrGzXkP5ohyR60bw5Sn5DYXokttiPxNYH6trFscGXb+ |
|||
CiMJmz/Y04a/QG5loO3viERPVwKBgQDXM0/vWdWLEIxRDMAEa3qaV2yJeHg6MIsh |
|||
ltyZ8sJ2Pk9XJIwnKBHPeedqghVhgCyz6q7xpu0dcoj1OyBk6obqwpfe1xM06qK6 |
|||
Omr64qSpJ2iNjpnWqpSiCcHxrxHHESOxTwtjZg57YI6TcVB5+Y40vcx51uMyOZgz |
|||
X3137Ear7wKBgGU9strpwdWZR4EYLdB6ub17Q3s1gkTIDWB9J0VE5GBhNIhlfBXH |
|||
yxEZuPSat3Mz6n5VCY4lVkNh7IIEEFkUg4X4i0Bwl7/ZitEkE7EMbXlFzwdZYId7 |
|||
MH3HJY1DxZLtZfmcTUsqtbrb50YwnbU5I7ocEX2O9sllj+G2Kc6C4QNnAoGBAIjl |
|||
MWJXSUqPmlMswzGMlY99MaQ5qHGL09XoPCkKjr3dYWdT7nwyNzI+oAHXAnblrIo/ |
|||
Lk63G3tyEsG9fRv1PSI165psQuGUqTPCWa+DYa/hS9dQ8XfnR2nUvzVZYvu5YXU3 |
|||
jU0L7QZ7I/eTS9hr8hSG8H5JPnoCvVlg01XoTgStAoGAIw+E7j74n8LTx8xp7O38 |
|||
QkUQhDs1ajOR3+Ct9VlhIgJ4khVADP550NLruPRO/E//gOWbOpqHNRkAXTJfJ04C |
|||
FHCxrhdv6nqaKH86AzazVaE9UH8nPtmoiiit1jLBXanqxZyOglog2PRcUReVfjzQ |
|||
uKWacPtR4jyQwZVIWdEbddg= |
|||
-----END PRIVATE KEY----- |
Loading…
Reference in new issue