退款通知
This commit is contained in:
parent
6421f31853
commit
dc01fb47cd
|
@ -128,4 +128,5 @@ public class AliAuthService {
|
|||
|
||||
return plainData;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -1,9 +1,12 @@
|
|||
package com.ruoyi.common.pay.ali.enums;
|
||||
|
||||
import com.ruoyi.common.utils.collection.CollectionUtils;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Getter;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* @author wjh
|
||||
* 2024/12/10
|
||||
|
@ -20,4 +23,11 @@ public enum AliTradeStatusEnum {
|
|||
private String status;
|
||||
private String msg;
|
||||
|
||||
/**
|
||||
* 通知成功的交易状态
|
||||
*/
|
||||
public static List<String> notifySuccessList() {
|
||||
return CollectionUtils.map(AliTradeStatusEnum::getStatus, TRADE_SUCCESS, TRADE_FINISHED);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -5,6 +5,7 @@ import com.alipay.api.AlipayClient;
|
|||
import com.alipay.api.domain.AlipayTradeCreateModel;
|
||||
import com.alipay.api.domain.AlipayTradeQueryModel;
|
||||
import com.alipay.api.domain.AlipayTradeRefundModel;
|
||||
import com.alipay.api.internal.util.AlipaySignature;
|
||||
import com.alipay.api.request.AlipayTradeCloseRequest;
|
||||
import com.alipay.api.request.AlipayTradeCreateRequest;
|
||||
import com.alipay.api.request.AlipayTradeQueryRequest;
|
||||
|
@ -21,10 +22,16 @@ import com.ruoyi.common.pay.Refundable;
|
|||
import com.ruoyi.common.pay.ali.enums.AliTradeStatusEnum;
|
||||
import com.ruoyi.common.utils.DateUtils;
|
||||
import com.ruoyi.common.utils.ServiceUtil;
|
||||
import com.ruoyi.common.utils.http.HttpUtils;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.http.HttpRequest;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import java.time.LocalDateTime;
|
||||
import java.util.HashMap;
|
||||
import java.util.Iterator;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* @author wjh
|
||||
|
@ -124,10 +131,12 @@ public class AliPayService implements PayApi {
|
|||
// 设置退款请求号
|
||||
model.setOutRequestNo(refund.refundOutRefundNo());
|
||||
request.setBizModel(model);
|
||||
request.setNotifyUrl(aliConfig.getNotifyUrl());
|
||||
|
||||
try {
|
||||
AlipayTradeRefundResponse response = alipayClient.certificateExecute(request);
|
||||
ServiceUtil.assertion(!response.isSuccess(), response.getMsg());
|
||||
ServiceUtil.assertion(!"Y".equals(response.getFundChange()), "退款失败,本次退款未导致资金变化");
|
||||
return response;
|
||||
} catch (Exception e) {
|
||||
throw new ServiceException("调用支付宝退款失败:" + e.getMessage());
|
||||
|
@ -151,4 +160,17 @@ public class AliPayService implements PayApi {
|
|||
AlipayTradeQueryResponse res = (AlipayTradeQueryResponse) result;
|
||||
return DateUtils.toLocalDateTime(res.getSendPayDate());
|
||||
}
|
||||
|
||||
/**
|
||||
* 对通知进行验签
|
||||
*/
|
||||
public void checkNotifySign(Map<String, String> params) {
|
||||
//调用SDK验证签名
|
||||
try {
|
||||
boolean signVerified = AlipaySignature.rsaCertCheckV1(params, aliConfig.getAlipayCertPath(),"UTF-8","RSA2");
|
||||
ServiceUtil.assertion(!signVerified, "验签失败");
|
||||
} catch (Exception e) {
|
||||
throw new ServiceException("验签失败" + e.getMessage());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -138,7 +138,7 @@ public class SybPayService implements PayApi {
|
|||
@Override
|
||||
public LocalDateTime getPayTime(Object result) {
|
||||
Map<String, String> res = (Map<String, String>)result;
|
||||
return DateUtils.toLocalDate(res.get("fintime"), "yyyyMMddHHmmss");
|
||||
return DateUtils.toLocalDateTime(res.get("fintime"), "yyyyMMddHHmmss");
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -5,10 +5,8 @@ import java.text.ParseException;
|
|||
import java.text.SimpleDateFormat;
|
||||
import java.time.*;
|
||||
import java.time.format.DateTimeFormatter;
|
||||
import java.time.temporal.Temporal;
|
||||
import java.util.Calendar;
|
||||
import java.util.Date;
|
||||
import org.apache.commons.lang3.time.DateFormatUtils;
|
||||
|
||||
import static org.apache.commons.lang3.time.DateFormatUtils.format;
|
||||
|
||||
|
@ -309,15 +307,6 @@ public class DateUtils extends org.apache.commons.lang3.time.DateUtils
|
|||
return date.toInstant().atZone(ZoneId.systemDefault()).toLocalDate();
|
||||
}
|
||||
|
||||
/**
|
||||
* 字符串转LocalDateTime
|
||||
* @param timeStr 字符串
|
||||
* @param format 格式化
|
||||
*/
|
||||
public static LocalDateTime toLocalDate(String timeStr, String format) {
|
||||
return LocalDateTime.parse(timeStr, DateTimeFormatter.ofPattern(format));
|
||||
}
|
||||
|
||||
public static LocalDateTime toLocalDateTime(Date date) {
|
||||
return date.toInstant().atZone(ZoneId.systemDefault()).toLocalDateTime();
|
||||
}
|
||||
|
|
|
@ -11,6 +11,8 @@ import java.net.URL;
|
|||
import java.net.URLConnection;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.security.cert.X509Certificate;
|
||||
import java.util.HashMap;
|
||||
import java.util.Iterator;
|
||||
import java.util.Map;
|
||||
import javax.net.ssl.HostnameVerifier;
|
||||
import javax.net.ssl.HttpsURLConnection;
|
||||
|
@ -491,4 +493,28 @@ public class HttpUtils
|
|||
}
|
||||
return result.toString();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 将request中的参数转换成Map
|
||||
* @param request
|
||||
* @return
|
||||
*/
|
||||
public static Map<String, String> convertRequestParamsToMap(HttpServletRequest request) {
|
||||
Map<String, String> retMap = new HashMap<String, String>();
|
||||
Map requestParams = request.getParameterMap();
|
||||
for (Iterator iter = requestParams.keySet().iterator(); iter.hasNext();) {
|
||||
String name = (String) iter.next();
|
||||
String[] values = (String[]) requestParams.get(name);
|
||||
String valueStr = "";
|
||||
for (int i = 0; i < values.length; i++) {
|
||||
valueStr = (i == values.length - 1) ? valueStr + values[i]
|
||||
: valueStr + values[i] + ",";
|
||||
}
|
||||
//乱码解决,这段代码在出现乱码时使用。如果mysign和sign不相等也可以使用这段代码转化
|
||||
//valueStr = new String(valueStr.getBytes("ISO-8859-1"), "gbk");
|
||||
retMap.put(name, valueStr);
|
||||
}
|
||||
return retMap;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -148,7 +148,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
|
|||
<trim prefix="SET" suffixOverrides=",">
|
||||
<include refid="updateColumns"/>
|
||||
</trim>
|
||||
where pay_id = #{payId}
|
||||
where pay_id = #{data.payId}
|
||||
</update>
|
||||
|
||||
<sql id="updateColumns">
|
||||
|
|
|
@ -1,11 +1,14 @@
|
|||
package com.ruoyi.web.controller.app;
|
||||
|
||||
import cn.hutool.core.util.StrUtil;
|
||||
import com.alibaba.fastjson2.JSON;
|
||||
import com.alibaba.fastjson2.JSONObject;
|
||||
import com.ruoyi.common.annotation.Anonymous;
|
||||
import com.ruoyi.common.core.controller.BaseController;
|
||||
import com.ruoyi.common.core.domain.AjaxResult;
|
||||
import com.ruoyi.common.exception.ServiceException;
|
||||
import com.ruoyi.common.pay.ali.enums.AliTradeStatusEnum;
|
||||
import com.ruoyi.common.pay.ali.service.AliPayService;
|
||||
import com.ruoyi.common.pay.syb.enums.SybTrxCode;
|
||||
import com.ruoyi.common.pay.syb.enums.SybTrxStatus;
|
||||
import com.ruoyi.common.pay.syb.service.SybPayService;
|
||||
|
@ -72,6 +75,9 @@ public class AppPayController extends BaseController {
|
|||
@Autowired
|
||||
private TmPayService tmPayService;
|
||||
|
||||
@Autowired
|
||||
private AliPayService aliPayService;
|
||||
|
||||
@ApiOperation("微信支付充值订单")
|
||||
@GetMapping("/wx/{billNo}")
|
||||
public AjaxResult wxPay(@PathVariable @ApiParam("订单编号") String billNo) {
|
||||
|
@ -185,7 +191,7 @@ public class AppPayController extends BaseController {
|
|||
// 微信支付通知
|
||||
if (SybTrxCode.WX_PAY.equalsCode(trxCode)) {
|
||||
// 新版支付订单
|
||||
payBillService.handleSuccess(cusOrderId, DateUtils.toLocalDate(params.get("paytime"), "yyyyMMddHHmmss"));
|
||||
payBillService.handleSuccess(cusOrderId, DateUtils.toLocalDateTime(params.get("paytime"), "yyyyMMddHHmmss"));
|
||||
}
|
||||
// 微信退款通知
|
||||
else if (SybTrxCode.WX_REFUND.equalsCode(trxCode)) {
|
||||
|
@ -233,18 +239,42 @@ public class AppPayController extends BaseController {
|
|||
@ApiOperation("支付宝支付通知")
|
||||
@PostMapping("/notify/ali")
|
||||
@Anonymous
|
||||
public ResponseEntity<Boolean> aliPayNotify(HttpServletRequest request) {
|
||||
public String aliPayNotify(HttpServletRequest request) {
|
||||
try {
|
||||
log.info("收到支付宝支付通知{}", request);
|
||||
String body = HttpUtils.getBody(request);
|
||||
log.info("收到支付宝支付通知{}", body);
|
||||
// todo
|
||||
} catch (ValidationException e) {
|
||||
return ResponseEntity.status(HttpStatus.UNAUTHORIZED).body(null);
|
||||
Map<String, String> params = HttpUtils.convertRequestParamsToMap(request);
|
||||
aliPayService.checkNotifySign(params);
|
||||
|
||||
log.info("收到支付宝支付通知{}", params);
|
||||
|
||||
// 交易状态
|
||||
String tradeStatus = params.get("trade_status");
|
||||
|
||||
// 交易状态不为已支付
|
||||
if (!AliTradeStatusEnum.notifySuccessList().contains(tradeStatus)) {
|
||||
return "fail";
|
||||
}
|
||||
|
||||
// 判断是否是退款订单
|
||||
String refundFee = params.get("refund_fee");
|
||||
// 退款订单
|
||||
if (StrUtil.isNotBlank(refundFee)) {
|
||||
// 商家业务号,主要是退款单号
|
||||
String outBizNo = params.get("out_biz_no");
|
||||
refundService.handleRefundSuccess(outBizNo);
|
||||
}
|
||||
// 支付订单
|
||||
else {
|
||||
//商户订单号
|
||||
String outTradeNo = params.get("out_trade_no");
|
||||
payBillService.handleSuccess(outTradeNo, DateUtils.toLocalDateTime(params.get("gmt_payment")));
|
||||
}
|
||||
} catch (Exception e) {
|
||||
return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body(null);
|
||||
return "fail";
|
||||
}
|
||||
return ResponseEntity.status(HttpStatus.OK).body(null);
|
||||
|
||||
|
||||
return "success";
|
||||
}
|
||||
|
||||
@ApiOperation("支付宝转账通知")
|
||||
|
@ -255,7 +285,8 @@ public class AppPayController extends BaseController {
|
|||
log.info("收到支付宝转账通知{}", request);
|
||||
String body = HttpUtils.getBody(request);
|
||||
log.info("收到支付宝转账通知{}", body);
|
||||
// todo
|
||||
|
||||
// TODO 似乎不生效
|
||||
} catch (ValidationException e) {
|
||||
return ResponseEntity.status(HttpStatus.UNAUTHORIZED).body(null);
|
||||
} catch (Exception e) {
|
||||
|
|
|
@ -77,35 +77,35 @@ public class PayBillController extends BaseController
|
|||
/**
|
||||
* 新增支付订单
|
||||
*/
|
||||
@PreAuthorize("@ss.hasPermi('ss:payBill:add')")
|
||||
@Log(title = "支付订单", businessType = BusinessType.INSERT)
|
||||
@PostMapping
|
||||
public AjaxResult add(@RequestBody PayBill payBill)
|
||||
{
|
||||
return toAjax(payBillService.insertPayBill(payBill));
|
||||
}
|
||||
// @PreAuthorize("@ss.hasPermi('ss:payBill:add')")
|
||||
// @Log(title = "支付订单", businessType = BusinessType.INSERT)
|
||||
// @PostMapping
|
||||
// public AjaxResult add(@RequestBody PayBill payBill)
|
||||
// {
|
||||
// return toAjax(payBillService.insertPayBill(payBill));
|
||||
// }
|
||||
|
||||
/**
|
||||
* 修改支付订单
|
||||
*/
|
||||
@PreAuthorize("@ss.hasPermi('ss:payBill:edit')")
|
||||
@Log(title = "支付订单", businessType = BusinessType.UPDATE)
|
||||
@PutMapping
|
||||
public AjaxResult edit(@RequestBody PayBill payBill)
|
||||
{
|
||||
return toAjax(payBillService.updatePayBill(payBill));
|
||||
}
|
||||
// @PreAuthorize("@ss.hasPermi('ss:payBill:edit')")
|
||||
// @Log(title = "支付订单", businessType = BusinessType.UPDATE)
|
||||
// @PutMapping
|
||||
// public AjaxResult edit(@RequestBody PayBill payBill)
|
||||
// {
|
||||
// return toAjax(payBillService.updatePayBill(payBill));
|
||||
// }
|
||||
|
||||
/**
|
||||
* 删除支付订单
|
||||
*/
|
||||
@PreAuthorize("@ss.hasPermi('ss:payBill:remove')")
|
||||
@Log(title = "支付订单", businessType = BusinessType.DELETE)
|
||||
@DeleteMapping("/{payIds}")
|
||||
public AjaxResult remove(@PathVariable Long[] payIds)
|
||||
{
|
||||
return toAjax(payBillService.deletePayBillByPayIds(payIds));
|
||||
}
|
||||
// @PreAuthorize("@ss.hasPermi('ss:payBill:remove')")
|
||||
// @Log(title = "支付订单", businessType = BusinessType.DELETE)
|
||||
// @DeleteMapping("/{payIds}")
|
||||
// public AjaxResult remove(@PathVariable Long[] payIds)
|
||||
// {
|
||||
// return toAjax(payBillService.deletePayBillByPayIds(payIds));
|
||||
// }
|
||||
|
||||
/**
|
||||
* 退款
|
||||
|
|
Loading…
Reference in New Issue
Block a user