Browse Source

退款

master
wangpengfei 6 months ago
parent
commit
5c69299991
  1. 5
      src/main/java/com/yxt/pay/api/refund/RefundOrder.java
  2. 1
      src/main/java/com/yxt/pay/biz/order/OrderService.java
  3. 7
      src/main/java/com/yxt/pay/biz/refund/WxRefundRest.java
  4. 159
      src/main/java/com/yxt/pay/biz/refund/WxRefundService.java
  5. 39
      src/main/java/com/yxt/pay/utils/TrustEveryone.java

5
src/main/java/com/yxt/pay/api/refund/RefundOrder.java

@ -4,6 +4,7 @@ import com.yxt.common.base.utils.StringRandom;
import com.yxt.common.core.domain.BaseEntity;
import lombok.Data;
import java.math.BigDecimal;
import java.text.SimpleDateFormat;
import java.util.Date;
@ -17,7 +18,7 @@ public class RefundOrder extends BaseEntity {
private String outRefundNo;//订单编号
private int source;//来源 0云菜窖
private String name;//商品名
private String amount;//金额
private BigDecimal amount;//金额
private String openId;//
private String returnUrl;//业务回调
private String orderSid;//支付订单sid
@ -31,7 +32,7 @@ public class RefundOrder extends BaseEntity {
public RefundOrder(int source) {
String Randomstr = StringRandom.getRandomString(15);
if (source == 0) {//云菜窖
outTradeNo = "YCJ" + getTime() + Randomstr;
outRefundNo = "YCJ" + getTime() + Randomstr;
} else if (source == 1) {

1
src/main/java/com/yxt/pay/biz/order/OrderService.java

@ -151,6 +151,7 @@ public class OrderService extends MybatisBaseService<OrderMapper, PayOrder> {
Map<String, Object> map = new HashMap<>();
map.put("mainSid", payOrder.getSid());
map.put("payTime", date);
TrustEveryone.trustEveryone();
ResponseEntity<ResultBean> postForEntity = new RestTemplate().postForEntity(payOrder.getPayUrl(), map, ResultBean.class);
return rb.success().setData(resultObj);
}

7
src/main/java/com/yxt/pay/biz/refund/WxRefundRest.java

@ -9,6 +9,7 @@ import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
/**
* @author wangpengfei
@ -39,10 +40,10 @@ public class WxRefundRest {
*/
// @Operation(summary = "微信退款回调" , description = "微信退款回调" )
// @SysLog("微信退款回调" )
@PostMapping("/payNotify")
public ResultBean refundPayNotify(HttpServletRequest request) throws Exception {
@PostMapping("/refundNotify")
public ResultBean refundPayNotify(HttpServletRequest request, HttpServletResponse response) throws Exception {
ResultBean rb=new ResultBean();
refundService.refundNotify(request);//注意:回调接口需要暴露到公网上,且要放开token验证
refundService.refundNotify(request,response);//注意:回调接口需要暴露到公网上,且要放开token验证
return rb.success();
}

159
src/main/java/com/yxt/pay/biz/refund/WxRefundService.java

@ -19,7 +19,11 @@ import com.yxt.pay.api.order.PayOrder;
import com.yxt.pay.api.refund.*;
import com.yxt.pay.api.wxpay.WxPayVo;
import com.yxt.pay.biz.order.OrderService;
import com.yxt.pay.utils.TrustEveryone;
import com.yxt.pay.utils.UrlComponent;
import com.yxt.pay.utils.wx.HttpKit;
import com.yxt.pay.utils.wx.SignType;
import com.yxt.pay.utils.wx.WxPayKit;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
@ -30,9 +34,12 @@ import org.springframework.web.client.RestTemplate;
import javax.servlet.ServletInputStream;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.BufferedReader;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.math.BigDecimal;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
@ -68,7 +75,9 @@ public class WxRefundService extends MybatisBaseService<WxRefundMapper,RefundOrd
public ResultBean createRefundOrder(RefundOrderDto refundOrderDto){
ResultBean rb=new ResultBean();
RefundOrder refundOrder=new RefundOrder(refundOrderDto.getSource());
BeanUtil.copyProperties(refundOrderDto,refundOrder,"id","sid","outTradeNo");
PayOrder payOrder=orderService.getOne(new QueryWrapper<PayOrder>().eq("sid",refundOrderDto.getOrderSid()));
BeanUtil.copyProperties(refundOrderDto,refundOrder,"id","sid");
refundOrder.setOutTradeNo(payOrder.getOutTradeNo());
baseMapper.insert(refundOrder);
return rb.success().setData(refundOrder);
@ -84,9 +93,9 @@ public class WxRefundService extends MybatisBaseService<WxRefundMapper,RefundOrd
@Transactional
public ResultBean refund(String orderSid) throws Exception {
ResultBean rb = ResultBean.fireFail();
PayOrder payOrder=orderService.getOne(new QueryWrapper<PayOrder>().eq("sid",orderSid));
RefundOrder refundOrder=baseMapper.selectOne(new QueryWrapper<RefundOrder>().eq("orderSid",payOrder.getSid()).eq("state","1"));
try {
PayOrder payOrder=orderService.getOne(new QueryWrapper<PayOrder>().eq("sid",orderSid));
WxPayVo wxPayVo=new WxPayVo(payOrder.getSource());
source=payOrder.getSource();
// 使用自动更新平台证书的RSA配置
// 一个商户号只能初始化一个配置,否则会因为重复的下载任务报错
@ -101,58 +110,48 @@ public class WxRefundService extends MybatisBaseService<WxRefundMapper,RefundOrd
.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()));
BigDecimal b=new BigDecimal(refundOrder.getAmount());
BigDecimal a =new BigDecimal(100);
String aoum=String.valueOf(b.multiply(a).setScale(0,ROUND_DOWN));
String aoum=String.valueOf(refundOrder.getAmount().multiply(a).setScale(0,ROUND_DOWN));
//退款金额
amountReq.setRefund(Long.valueOf(aoum));
// amountReq.setRefund(Long.valueOf("1"));
//原订单金额
amountReq.setTotal(Long.valueOf(aoum));
// amountReq.setTotal(Long.valueOf("1"));
//货币类型(默认人民币)
amountReq.setCurrency("CNY");
request.setAmount(amountReq);
//商户退款单号
request.setOutRefundNo(refundOrder.getOutTradeNo());
// request.setOutRefundNo(String.valueOf("ceshi"));
request.setOutTradeNo(payOrder.getOutTradeNo());
// request.setOutTradeNo("ceshi");
request.setReason(refundOrder.getReason());
// request.setReason("ceshi");
//退款通知回调地址
// request.setNotifyUrl(wxPayV3Bean.getRefundNotifyUrl());
request.setNotifyUrl(urlComponent.getDoMainUrl() + "order/payNotify");
request.setNotifyUrl(urlComponent.getDoMainUrl() + "refund/refundNotify");
// 调用退款方法,得到应答
// 调用微信sdk接口
Refund refund = service.create(request);
System.out.println(refund);
//接收退款返回参数
Refund refundResponse = new Refund();
refundResponse.setStatus(refund.getStatus());
System.out.println(refund);;
if (refundResponse.getStatus().equals(Status.SUCCESS)){
//说明退款成功,开始接下来的业务操作
// WXRefundOrderRespVo refundOrderRespVO = new WXRefundOrderRespVo();
payOrder.setState(2);
orderService.updateById(payOrder);
refundOrder.setState(2);
baseMapper.updateById(refundOrder);
//你的业务代码
return rb.success().setData(refund);
}else if(refundResponse.getStatus().equals(Status.PROCESSING)){
return rb.success().setMsg("退款申请处理中,请稍等").setData(refund);
}else{
payOrder.setState(3);
payOrder.setState(4);
orderService.updateById(payOrder);
return rb.setMsg("申请退款失败").setData(refund);
refundOrder.setState(3);
baseMapper.updateById(refundOrder);
return rb.setCode("500").setMsg("申请退款失败").setData(refund);
}
}catch (Exception e){
e.printStackTrace();
refundOrder.setState(3);
baseMapper.updateById(refundOrder);
return rb.setMsg("退款失败,error=" + e.getMessage());
// throw new ResultException(ResultEnum.ERROR,e.toString());
}
@ -166,25 +165,20 @@ public class WxRefundService extends MybatisBaseService<WxRefundMapper,RefundOrd
* @Author: whl
* @Date: 2023/10/13 10:46
*/
public void refundNotify(HttpServletRequest request) throws Exception {
public void refundNotify(HttpServletRequest request,HttpServletResponse response) 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();
log.info("退款回调"+s1);
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);
String xmlMsg = HttpKit.readData(request);
log.info("退款回调"+xmlMsg);
request.setCharacterEncoding("UTF-8");
response.setCharacterEncoding("UTF-8");
response.setContentType("application/json;charset=utf-8");
String nonceStr = request.getHeader("Wechatpay-Nonce");
//微信传递过来的签名
String signature = request.getHeader("Wechatpay-Signature");
//证书序列号(微信平台)
String serialNo = request.getHeader("Wechatpay-Serial");
//时间戳
String timestamp = request.getHeader("Wechatpay-Timestamp");
// 如果已经初始化了 RSAAutoCertificateConfig,可直接使用
// 没有的话,则构造一个
// log.error(JSON.toJSONString(wxPayV3Bean));
@ -198,37 +192,96 @@ public class WxRefundService extends MybatisBaseService<WxRefundMapper,RefundOrd
NotificationParser parser = new NotificationParser(config);
RequestParam requestParam=new RequestParam.Builder()
.serialNumber(serialNo)
.nonce(nonce)
.nonce(nonceStr)
.signature(signature)
.timestamp(timestamp)
// 若未设置signType,默认值为 WECHATPAY2-SHA256-RSA2048
.signType(signType)
.body(s1)
.body(xmlMsg)
.build();
RefundNotification parse = parser.parse(requestParam, RefundNotification.class);
RefundOrder refundOrder=baseMapper.selectOne(new QueryWrapper<RefundOrder>().eq("outRefundNo",parse.getOutRefundNo()));
System.out.println("退款回调结果: " + parse);
RefundOrder refundOrder=baseMapper.selectOne(new QueryWrapper<RefundOrder>().eq("outTradeNo",parse.getOutTradeNo()));
PayOrder payOrder=orderService.getOne(new QueryWrapper<PayOrder>().eq("sid",refundOrder.getOrderSid()));
//parse.getRefundStatus().equals("SUCCESS");说明退款成功
RefundBusinessQuery query=new RefundBusinessQuery();
Map<String, Object> map = new HashMap<>();
if (parse.getRefundStatus().equals(Transaction.TradeStateEnum.SUCCESS)){
if (parse.getRefundStatus().toString().equals(Transaction.TradeStateEnum.SUCCESS.toString())){
//你的业务代码
map.put("mainSid",refundOrder.getOrderSid());
map.put("aBoolean",true);
System.out.println("退款回调结果: " + parse);
map.put("code",true);
refundOrder.setState(2);
baseMapper.updateById(refundOrder);
payOrder.setState(6);
orderService.updateById(payOrder);
System.out.println(parse.getRefundStatus());
}else{
map.put("mainSid",refundOrder.getOrderSid());
map.put("aBoolean",false);
System.out.println("退款回调结果: " + parse);
map.put("code",false);
refundOrder.setState(3);
baseMapper.updateById(refundOrder);
payOrder.setState(5);
orderService.updateById(payOrder);
System.out.println(parse.getRefundStatus());
}
TrustEveryone.trustEveryone();
ResponseEntity<ResultBean> postForEntity = new RestTemplate().postForEntity(refundOrder.getReturnUrl(),map, ResultBean.class);
} catch (Exception e) {
e.printStackTrace();
}
}
// public void weixinRefundNotify(String body, HttpServletRequest request, HttpServletResponse response) throws Exception {
// //获取报文
// //随机串
// String nonceStr = request.getHeader("Wechatpay-Nonce");
// //微信传递过来的签名
// String signature = request.getHeader("Wechatpay-Signature");
// //证书序列号(微信平台)
// String serialNo = request.getHeader("Wechatpay-Serial");
// //时间戳
// String timestamp = request.getHeader("Wechatpay-Timestamp");
// InputStream is = null;
// try {
// is = request.getInputStream();
// // 构造 RequestParam
// com.wechat.pay.java.core.notification.RequestParam requestParam = new com.wechat.pay.java.core.notification.RequestParam.Builder()
// .serialNumber(serialNo)
// .nonce(nonceStr)
// .signature(signature)
// .timestamp(timestamp)
// .body(body)
// .build();
// // 如果已经初始化了 RSAAutoCertificateConfig,可以直接使用 config
// // 初始化 NotificationParser
// // 验签、解密并转换成 Transaction
// RefundNotification refundNotification = notificationParser.parse(requestParam, RefundNotification.class);
// String orderNo = refundNotification.getOutTradeNo();
// //记录日志信息
// System.out.println("订单号:" + orderNo);
// if (SUCCESS.equals(refundNotification.getRefundStatus().SUCCESS)) {
// System.out.println("退款成功");
// //TODO------
// //根据自己的需求处理相应的业务逻辑,异步
// JSONObject jsonObject = JSONObject.parseObject(refundNotification.toString());
// System.out.println("微信退款回调信息:" + jsonObject);
// JSONObject resultJson = new JSONObject();
// resultJson.put("out_trade_no", jsonObject.getString("out_trade_no"));
// resultJson.put("refund_status", jsonObject.getString("refund_status"));
// //业务处理
// //通知微信回调成功
// response.getWriter().write("<xml><return_code><![CDATA[SUCCESS]]></return_code></xml>");
// } else {
// System.out.println("微信回调失败,JsapiPayController.payNotify.transaction:" + refundNotification.toString());
// //通知微信回调失败
// response.getWriter().write("<xml><return_code><![CDATA[FAIL]]></return_code></xml>");
// }
// } catch (Exception e) {
// e.printStackTrace();
// } finally {
// is.close();
// }
// }
// //url 微信退款请求地址 data 请求参数

39
src/main/java/com/yxt/pay/utils/TrustEveryone.java

@ -0,0 +1,39 @@
package com.yxt.pay.utils;
import javax.net.ssl.*;
import java.security.SecureRandom;
import java.security.cert.CertificateException;
import java.security.cert.X509Certificate;
/**
* @author wangpengfei
* @date 2024/12/16 15:27
*/
public class TrustEveryone {
public static void trustEveryone() {
try {
HttpsURLConnection.setDefaultHostnameVerifier(new HostnameVerifier() {
public boolean verify(String hostname, SSLSession session) {
return true;
}
});
SSLContext context = SSLContext.getInstance("TLS");
context.init(null, new X509TrustManager[]{new X509TrustManager() {
public void checkClientTrusted(X509Certificate[] chain, String authType) throws CertificateException {
}
public void checkServerTrusted(X509Certificate[] chain, String authType) throws CertificateException {
}
public X509Certificate[] getAcceptedIssuers() {
return new X509Certificate[0];
}
}}, new SecureRandom());
HttpsURLConnection.setDefaultSSLSocketFactory(context.getSocketFactory());
} catch (Exception e) {
e.printStackTrace();
}
}
}
Loading…
Cancel
Save