mirror of
https://gitee.com/huangge1199_admin/vue-pro.git
synced 2024-11-27 01:32:03 +08:00
mall + pay:
1. 完善微信支付的 V3 支付回调、退款回调
This commit is contained in:
parent
68a4ef98ca
commit
d0a7f41875
@ -70,6 +70,8 @@ public abstract class AbstractPayClient<Config extends PayClientConfig> implemen
|
|||||||
return channelId;
|
return channelId;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ============ 支付相关 ==========
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public final PayOrderUnifiedRespDTO unifiedOrder(PayOrderUnifiedReqDTO reqDTO) {
|
public final PayOrderUnifiedRespDTO unifiedOrder(PayOrderUnifiedReqDTO reqDTO) {
|
||||||
Validation.buildDefaultValidatorFactory().getValidator().validate(reqDTO);
|
Validation.buildDefaultValidatorFactory().getValidator().validate(reqDTO);
|
||||||
@ -91,6 +93,8 @@ public abstract class AbstractPayClient<Config extends PayClientConfig> implemen
|
|||||||
protected abstract PayOrderUnifiedRespDTO doUnifiedOrder(PayOrderUnifiedReqDTO reqDTO)
|
protected abstract PayOrderUnifiedRespDTO doUnifiedOrder(PayOrderUnifiedReqDTO reqDTO)
|
||||||
throws Throwable;
|
throws Throwable;
|
||||||
|
|
||||||
|
// ============ 退款相关 ==========
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public PayRefundRespDTO unifiedRefund(PayRefundUnifiedReqDTO reqDTO) {
|
public PayRefundRespDTO unifiedRefund(PayRefundUnifiedReqDTO reqDTO) {
|
||||||
Validation.buildDefaultValidatorFactory().getValidator().validate(reqDTO);
|
Validation.buildDefaultValidatorFactory().getValidator().validate(reqDTO);
|
||||||
|
@ -4,7 +4,6 @@ import cn.hutool.core.bean.BeanUtil;
|
|||||||
import cn.hutool.core.codec.Base64;
|
import cn.hutool.core.codec.Base64;
|
||||||
import cn.hutool.core.date.LocalDateTimeUtil;
|
import cn.hutool.core.date.LocalDateTimeUtil;
|
||||||
import cn.hutool.core.date.TemporalAccessorUtil;
|
import cn.hutool.core.date.TemporalAccessorUtil;
|
||||||
import cn.hutool.core.lang.Assert;
|
|
||||||
import cn.hutool.core.util.StrUtil;
|
import cn.hutool.core.util.StrUtil;
|
||||||
import cn.iocoder.yudao.framework.common.util.io.FileUtils;
|
import cn.iocoder.yudao.framework.common.util.io.FileUtils;
|
||||||
import cn.iocoder.yudao.framework.pay.core.client.dto.order.PayOrderRespDTO;
|
import cn.iocoder.yudao.framework.pay.core.client.dto.order.PayOrderRespDTO;
|
||||||
@ -19,8 +18,11 @@ import cn.iocoder.yudao.framework.pay.core.enums.refund.PayRefundStatusRespEnum;
|
|||||||
import com.github.binarywang.wxpay.bean.notify.WxPayOrderNotifyResult;
|
import com.github.binarywang.wxpay.bean.notify.WxPayOrderNotifyResult;
|
||||||
import com.github.binarywang.wxpay.bean.notify.WxPayOrderNotifyV3Result;
|
import com.github.binarywang.wxpay.bean.notify.WxPayOrderNotifyV3Result;
|
||||||
import com.github.binarywang.wxpay.bean.notify.WxPayRefundNotifyResult;
|
import com.github.binarywang.wxpay.bean.notify.WxPayRefundNotifyResult;
|
||||||
|
import com.github.binarywang.wxpay.bean.notify.WxPayRefundNotifyV3Result;
|
||||||
import com.github.binarywang.wxpay.bean.request.WxPayRefundRequest;
|
import com.github.binarywang.wxpay.bean.request.WxPayRefundRequest;
|
||||||
|
import com.github.binarywang.wxpay.bean.request.WxPayRefundV3Request;
|
||||||
import com.github.binarywang.wxpay.bean.result.WxPayRefundResult;
|
import com.github.binarywang.wxpay.bean.result.WxPayRefundResult;
|
||||||
|
import com.github.binarywang.wxpay.bean.result.WxPayRefundV3Result;
|
||||||
import com.github.binarywang.wxpay.config.WxPayConfig;
|
import com.github.binarywang.wxpay.config.WxPayConfig;
|
||||||
import com.github.binarywang.wxpay.exception.WxPayException;
|
import com.github.binarywang.wxpay.exception.WxPayException;
|
||||||
import com.github.binarywang.wxpay.service.WxPayService;
|
import com.github.binarywang.wxpay.service.WxPayService;
|
||||||
@ -78,6 +80,8 @@ public abstract class AbstractWxPayClient extends AbstractPayClient<WxPayClientC
|
|||||||
client.setConfig(payConfig);
|
client.setConfig(payConfig);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ============ 支付相关 ==========
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected PayOrderUnifiedRespDTO doUnifiedOrder(PayOrderUnifiedReqDTO reqDTO) throws Exception {
|
protected PayOrderUnifiedRespDTO doUnifiedOrder(PayOrderUnifiedReqDTO reqDTO) throws Exception {
|
||||||
try {
|
try {
|
||||||
@ -113,52 +117,6 @@ public abstract class AbstractWxPayClient extends AbstractPayClient<WxPayClientC
|
|||||||
protected abstract PayOrderUnifiedRespDTO doUnifiedOrderV3(PayOrderUnifiedReqDTO reqDTO)
|
protected abstract PayOrderUnifiedRespDTO doUnifiedOrderV3(PayOrderUnifiedReqDTO reqDTO)
|
||||||
throws WxPayException;
|
throws WxPayException;
|
||||||
|
|
||||||
@Override
|
|
||||||
protected PayRefundRespDTO doUnifiedRefund(PayRefundUnifiedReqDTO reqDTO) throws Throwable {
|
|
||||||
try {
|
|
||||||
switch (config.getApiVersion()) {
|
|
||||||
case API_VERSION_V2:
|
|
||||||
return doUnifiedRefundV2(reqDTO);
|
|
||||||
case WxPayClientConfig.API_VERSION_V3:
|
|
||||||
return doUnifiedRefundV3(reqDTO);
|
|
||||||
default:
|
|
||||||
throw new IllegalArgumentException(String.format("未知的 API 版本(%s)", config.getApiVersion()));
|
|
||||||
}
|
|
||||||
} catch (WxPayException e) {
|
|
||||||
// todo 芋艿:异常的处理;
|
|
||||||
throw buildUnifiedOrderException(null, e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private PayRefundRespDTO doUnifiedRefundV2(PayRefundUnifiedReqDTO reqDTO) throws Throwable {
|
|
||||||
// 1. 构建 WxPayRefundRequest 请求
|
|
||||||
WxPayRefundRequest request = new WxPayRefundRequest()
|
|
||||||
.setOutTradeNo(reqDTO.getOutTradeNo())
|
|
||||||
.setOutRefundNo(reqDTO.getOutRefundNo())
|
|
||||||
.setRefundFee(reqDTO.getRefundPrice())
|
|
||||||
.setRefundDesc(reqDTO.getReason())
|
|
||||||
.setTotalFee(reqDTO.getPayPrice())
|
|
||||||
.setNotifyUrl(reqDTO.getNotifyUrl());
|
|
||||||
// 2.1 执行请求
|
|
||||||
WxPayRefundResult response = client.refundV2(request); // TODO 芋艿:可以分成 V2 和 V3 的退款接口
|
|
||||||
// 2.2 创建返回结果
|
|
||||||
PayRefundRespDTO refund = new PayRefundRespDTO()
|
|
||||||
.setOutRefundNo(reqDTO.getOutRefundNo())
|
|
||||||
.setRawData(response);
|
|
||||||
if (Objects.equals("SUCCESS", response.getResultCode())) {
|
|
||||||
refund.setStatus(PayRefundStatusRespEnum.WAITING.getStatus());
|
|
||||||
refund.setChannelRefundNo(response.getRefundId());
|
|
||||||
} else {
|
|
||||||
refund.setStatus(PayRefundStatusRespEnum.FAILURE.getStatus());
|
|
||||||
// TODO 芋艿;异常的处理;
|
|
||||||
}
|
|
||||||
return refund;
|
|
||||||
}
|
|
||||||
|
|
||||||
private PayRefundRespDTO doUnifiedRefundV3(PayRefundUnifiedReqDTO reqDTO) throws Throwable {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public PayOrderRespDTO parseOrderNotify(Map<String, String> params, String body) {
|
public PayOrderRespDTO parseOrderNotify(Map<String, String> params, String body) {
|
||||||
try {
|
try {
|
||||||
@ -195,20 +153,93 @@ public abstract class AbstractWxPayClient extends AbstractPayClient<WxPayClientC
|
|||||||
}
|
}
|
||||||
|
|
||||||
private PayOrderRespDTO parseOrderNotifyV3(String body) throws WxPayException {
|
private PayOrderRespDTO parseOrderNotifyV3(String body) throws WxPayException {
|
||||||
WxPayOrderNotifyV3Result notifyResult = client.parseOrderNotifyV3Result(body, null);
|
// 1. 解析回调
|
||||||
WxPayOrderNotifyV3Result.DecryptNotifyResult result = notifyResult.getResult();
|
WxPayOrderNotifyV3Result response = client.parseOrderNotifyV3Result(body, null);
|
||||||
// TODO 芋艿:翻译下 state
|
WxPayOrderNotifyV3Result.DecryptNotifyResult responseResult = response.getResult();
|
||||||
// 转换结果
|
// 2. 构建结果
|
||||||
Assert.isTrue(Objects.equals(notifyResult.getResult().getTradeState(), "SUCCESS"),
|
|
||||||
"支付结果非 SUCCESS");
|
|
||||||
return PayOrderRespDTO.builder()
|
return PayOrderRespDTO.builder()
|
||||||
.outTradeNo(result.getOutTradeNo())
|
.outTradeNo(responseResult.getOutTradeNo())
|
||||||
.channelOrderNo(result.getTradeState())
|
.channelOrderNo(responseResult.getTradeState())
|
||||||
.channelUserId(result.getPayer() != null ? result.getPayer().getOpenid() : null)
|
.channelUserId(responseResult.getPayer() != null ? responseResult.getPayer().getOpenid() : null)
|
||||||
.successTime(parseDateV3(result.getSuccessTime()))
|
.status(Objects.equals(responseResult.getTradeState(), "SUCCESS") ?
|
||||||
|
PayOrderStatusRespEnum.SUCCESS.getStatus() : PayOrderStatusRespEnum.CLOSED.getStatus())
|
||||||
|
.successTime(parseDateV3(responseResult.getSuccessTime()))
|
||||||
.build();
|
.build();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ============ 退款相关 ==========
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected PayRefundRespDTO doUnifiedRefund(PayRefundUnifiedReqDTO reqDTO) throws Throwable {
|
||||||
|
try {
|
||||||
|
switch (config.getApiVersion()) {
|
||||||
|
case API_VERSION_V2:
|
||||||
|
return doUnifiedRefundV2(reqDTO);
|
||||||
|
case WxPayClientConfig.API_VERSION_V3:
|
||||||
|
return doUnifiedRefundV3(reqDTO);
|
||||||
|
default:
|
||||||
|
throw new IllegalArgumentException(String.format("未知的 API 版本(%s)", config.getApiVersion()));
|
||||||
|
}
|
||||||
|
} catch (WxPayException e) {
|
||||||
|
// todo 芋艿:异常的处理;
|
||||||
|
throw buildUnifiedOrderException(null, e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private PayRefundRespDTO doUnifiedRefundV2(PayRefundUnifiedReqDTO reqDTO) throws Throwable {
|
||||||
|
// 1. 构建 WxPayRefundRequest 请求
|
||||||
|
WxPayRefundRequest request = new WxPayRefundRequest()
|
||||||
|
.setOutTradeNo(reqDTO.getOutTradeNo())
|
||||||
|
.setOutRefundNo(reqDTO.getOutRefundNo())
|
||||||
|
.setRefundFee(reqDTO.getRefundPrice())
|
||||||
|
.setRefundDesc(reqDTO.getReason())
|
||||||
|
.setTotalFee(reqDTO.getPayPrice())
|
||||||
|
.setNotifyUrl(reqDTO.getNotifyUrl());
|
||||||
|
// 2.1 执行请求
|
||||||
|
WxPayRefundResult response = client.refundV2(request);
|
||||||
|
// 2.2 创建返回结果
|
||||||
|
PayRefundRespDTO refund = new PayRefundRespDTO()
|
||||||
|
.setOutRefundNo(reqDTO.getOutRefundNo())
|
||||||
|
.setRawData(response);
|
||||||
|
if (Objects.equals("SUCCESS", response.getResultCode())) {
|
||||||
|
refund.setStatus(PayRefundStatusRespEnum.WAITING.getStatus())
|
||||||
|
.setChannelRefundNo(response.getRefundId());
|
||||||
|
} else {
|
||||||
|
refund.setStatus(PayRefundStatusRespEnum.FAILURE.getStatus());
|
||||||
|
}
|
||||||
|
// TODO 芋艿;异常的处理;
|
||||||
|
return refund;
|
||||||
|
}
|
||||||
|
|
||||||
|
private PayRefundRespDTO doUnifiedRefundV3(PayRefundUnifiedReqDTO reqDTO) throws Throwable {
|
||||||
|
// 1. 构建 WxPayRefundRequest 请求
|
||||||
|
WxPayRefundV3Request request = new WxPayRefundV3Request()
|
||||||
|
.setOutTradeNo(reqDTO.getOutTradeNo())
|
||||||
|
.setOutRefundNo(reqDTO.getOutRefundNo())
|
||||||
|
.setAmount(new WxPayRefundV3Request.Amount().setRefund(reqDTO.getRefundPrice())
|
||||||
|
.setTotal(reqDTO.getPayPrice()).setCurrency("CNY"))
|
||||||
|
.setReason(reqDTO.getReason())
|
||||||
|
.setNotifyUrl(reqDTO.getNotifyUrl());
|
||||||
|
// 2.1 执行请求
|
||||||
|
WxPayRefundV3Result response = client.refundV3(request);
|
||||||
|
// 2.2 创建返回结果
|
||||||
|
PayRefundRespDTO refund = new PayRefundRespDTO()
|
||||||
|
.setOutRefundNo(reqDTO.getOutRefundNo())
|
||||||
|
.setRawData(response);
|
||||||
|
if (Objects.equals("SUCCESS", response.getStatus())) {
|
||||||
|
refund.setStatus(PayRefundStatusRespEnum.SUCCESS.getStatus())
|
||||||
|
.setChannelRefundNo(response.getRefundId())
|
||||||
|
.setSuccessTime(parseDateV3(response.getSuccessTime()));
|
||||||
|
} else if (Objects.equals("PROCESSING", response.getStatus())) {
|
||||||
|
refund.setStatus(PayRefundStatusRespEnum.WAITING.getStatus())
|
||||||
|
.setChannelRefundNo(response.getRefundId());
|
||||||
|
} else {
|
||||||
|
refund.setStatus(PayRefundStatusRespEnum.FAILURE.getStatus());
|
||||||
|
}
|
||||||
|
// TODO 芋艿;异常的处理;
|
||||||
|
return refund;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public PayRefundRespDTO parseRefundNotify(Map<String, String> params, String body) {
|
public PayRefundRespDTO parseRefundNotify(Map<String, String> params, String body) {
|
||||||
try {
|
try {
|
||||||
@ -229,27 +260,42 @@ public abstract class AbstractWxPayClient extends AbstractPayClient<WxPayClientC
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@SuppressWarnings("DuplicatedCode")
|
||||||
private PayRefundRespDTO parseRefundNotifyV2(String body) throws WxPayException {
|
private PayRefundRespDTO parseRefundNotifyV2(String body) throws WxPayException {
|
||||||
// 1. 解析回调
|
// 1. 解析回调
|
||||||
WxPayRefundNotifyResult response = client.parseRefundNotifyResult(body);
|
WxPayRefundNotifyResult response = client.parseRefundNotifyResult(body);
|
||||||
WxPayRefundNotifyResult.ReqInfo reqInfo = response.getReqInfo();
|
WxPayRefundNotifyResult.ReqInfo responseResult = response.getReqInfo();
|
||||||
// 2. 构建结果
|
// 2. 构建结果
|
||||||
PayRefundRespDTO notify = new PayRefundRespDTO()
|
PayRefundRespDTO notify = new PayRefundRespDTO()
|
||||||
.setChannelRefundNo(reqInfo.getRefundId())
|
.setChannelRefundNo(responseResult.getRefundId())
|
||||||
.setOutRefundNo(reqInfo.getOutRefundNo())
|
.setOutRefundNo(responseResult.getOutRefundNo())
|
||||||
.setRawData(response);
|
.setRawData(response);
|
||||||
if (Objects.equals("SUCCESS", reqInfo.getRefundStatus())) {
|
if (Objects.equals("SUCCESS", responseResult.getRefundStatus())) {
|
||||||
notify.setStatus(PayRefundStatusRespEnum.SUCCESS.getStatus())
|
notify.setStatus(PayRefundStatusRespEnum.SUCCESS.getStatus())
|
||||||
.setSuccessTime(parseDateV2B(reqInfo.getSuccessTime()));
|
.setSuccessTime(parseDateV2B(responseResult.getSuccessTime()));
|
||||||
} else {
|
} else {
|
||||||
notify.setStatus(PayRefundStatusRespEnum.FAILURE.getStatus());
|
notify.setStatus(PayRefundStatusRespEnum.FAILURE.getStatus());
|
||||||
}
|
}
|
||||||
return notify;
|
return notify;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@SuppressWarnings("DuplicatedCode")
|
||||||
private PayRefundRespDTO parseRefundNotifyV3(String body) throws WxPayException {
|
private PayRefundRespDTO parseRefundNotifyV3(String body) throws WxPayException {
|
||||||
// TODO 芋艿:未实现
|
// 1. 解析回调
|
||||||
return null;
|
WxPayRefundNotifyV3Result response = client.parseRefundNotifyV3Result(body, null);
|
||||||
|
WxPayRefundNotifyV3Result.DecryptNotifyResult responseResult = response.getResult();
|
||||||
|
// 2. 构建结果
|
||||||
|
PayRefundRespDTO notify = new PayRefundRespDTO()
|
||||||
|
.setChannelRefundNo(responseResult.getRefundId())
|
||||||
|
.setOutRefundNo(responseResult.getOutRefundNo())
|
||||||
|
.setRawData(response);
|
||||||
|
if (Objects.equals("SUCCESS", responseResult.getRefundStatus())) {
|
||||||
|
notify.setStatus(PayRefundStatusRespEnum.SUCCESS.getStatus())
|
||||||
|
.setSuccessTime(parseDateV3(responseResult.getSuccessTime()));
|
||||||
|
} else {
|
||||||
|
notify.setStatus(PayRefundStatusRespEnum.FAILURE.getStatus());
|
||||||
|
}
|
||||||
|
return notify;
|
||||||
}
|
}
|
||||||
|
|
||||||
// ========== 各种工具方法 ==========
|
// ========== 各种工具方法 ==========
|
||||||
|
@ -55,13 +55,13 @@ public class WxNativePayClient extends AbstractWxPayClient {
|
|||||||
@Override
|
@Override
|
||||||
protected PayOrderUnifiedRespDTO doUnifiedOrderV3(PayOrderUnifiedReqDTO reqDTO) throws WxPayException {
|
protected PayOrderUnifiedRespDTO doUnifiedOrderV3(PayOrderUnifiedReqDTO reqDTO) throws WxPayException {
|
||||||
// 构建 WxPayUnifiedOrderRequest 对象
|
// 构建 WxPayUnifiedOrderRequest 对象
|
||||||
WxPayUnifiedOrderV3Request request = new WxPayUnifiedOrderV3Request();
|
WxPayUnifiedOrderV3Request request = new WxPayUnifiedOrderV3Request()
|
||||||
request.setOutTradeNo(reqDTO.getOutTradeNo());
|
.setOutTradeNo(reqDTO.getOutTradeNo())
|
||||||
request.setDescription(reqDTO.getBody());
|
.setDescription(reqDTO.getSubject())
|
||||||
request.setAmount(new WxPayUnifiedOrderV3Request.Amount().setTotal(reqDTO.getPrice())); // 单位分
|
.setAmount(new WxPayUnifiedOrderV3Request.Amount().setTotal(reqDTO.getPrice())) // 单位分
|
||||||
request.setTimeExpire(formatDateV3(reqDTO.getExpireTime()));
|
.setTimeExpire(formatDateV3(reqDTO.getExpireTime()))
|
||||||
request.setSceneInfo(new WxPayUnifiedOrderV3Request.SceneInfo().setPayerClientIp(reqDTO.getUserIp()));
|
.setSceneInfo(new WxPayUnifiedOrderV3Request.SceneInfo().setPayerClientIp(reqDTO.getUserIp()))
|
||||||
request.setNotifyUrl(reqDTO.getNotifyUrl());
|
.setNotifyUrl(reqDTO.getNotifyUrl());
|
||||||
// 执行请求
|
// 执行请求
|
||||||
String response = client.createOrderV3(TradeTypeEnum.NATIVE, request);
|
String response = client.createOrderV3(TradeTypeEnum.NATIVE, request);
|
||||||
|
|
||||||
|
@ -41,7 +41,8 @@
|
|||||||
</el-table-column>
|
</el-table-column>
|
||||||
<el-table-column label="退款时间" align="center" prop="refundTime" width="180">
|
<el-table-column label="退款时间" align="center" prop="refundTime" width="180">
|
||||||
<template v-slot="scope">
|
<template v-slot="scope">
|
||||||
<span>{{ parseTime(scope.row.refundTime) }}</span>
|
<span v-if="scope.row.refundTime">{{ parseTime(scope.row.refundTime) }}</span>
|
||||||
|
<span v-else-if="scope.row.payRefundId">退款中,等待退款结果</span>
|
||||||
</template>
|
</template>
|
||||||
</el-table-column>
|
</el-table-column>
|
||||||
<el-table-column label="操作" align="center" class-name="small-padding fixed-width">
|
<el-table-column label="操作" align="center" class-name="small-padding fixed-width">
|
||||||
|
Loading…
Reference in New Issue
Block a user