完成支付的下单和提交订单的逻辑

This commit is contained in:
YunaiV
2021-10-23 20:14:13 +08:00
parent 6dc65234ef
commit ab19228ca6
24 changed files with 251 additions and 94 deletions

View File

@ -29,4 +29,13 @@ public class ObjectUtils {
return obj1.compareTo(obj2) > 0 ? obj1 : obj2;
}
public static <T> T defaultIfNull(T... array) {
for (T item : array) {
if (item != null) {
return item;
}
}
return null;
}
}

View File

@ -1,6 +1,5 @@
package cn.iocoder.yudao.framework.pay.core.client;
import cn.iocoder.yudao.framework.common.pojo.CommonResult;
import cn.iocoder.yudao.framework.pay.core.client.dto.PayOrderUnifiedReqDTO;
/**
@ -17,7 +16,12 @@ public interface PayClient {
*/
Long getId();
// TODO 缺少注释
CommonResult<?> unifiedOrder(PayOrderUnifiedReqDTO reqDTO);
/**
* 调用支付渠道,统一下单
*
* @param reqDTO 下单信息
* @return 各支付渠道的返回结果
*/
PayCommonResult<?> unifiedOrder(PayOrderUnifiedReqDTO reqDTO);
}

View File

@ -54,7 +54,7 @@ public class PayOrderUnifiedReqDTO {
*/
@NotNull(message = "支付金额不能为空")
@DecimalMin(value = "0", inclusive = false, message = "支付金额必须大于零")
private Integer amount;
private Long amount;
/**
* 支付过期时间

View File

@ -1,10 +1,15 @@
package cn.iocoder.yudao.framework.pay.core.client.impl;
import cn.hutool.extra.validation.ValidationUtil;
import cn.iocoder.yudao.framework.pay.core.client.AbstractPayCodeMapping;
import cn.iocoder.yudao.framework.pay.core.client.PayClient;
import cn.iocoder.yudao.framework.pay.core.client.PayClientConfig;
import cn.iocoder.yudao.framework.pay.core.client.AbstractPayCodeMapping;
import cn.iocoder.yudao.framework.pay.core.client.PayCommonResult;
import cn.iocoder.yudao.framework.pay.core.client.dto.PayOrderUnifiedReqDTO;
import lombok.extern.slf4j.Slf4j;
import static cn.iocoder.yudao.framework.common.util.json.JsonUtils.toJsonString;
/**
* 支付客户端的抽象类,提供模板方法,减少子类的冗余代码
*
@ -30,7 +35,7 @@ public abstract class AbstractPayClient<Config extends PayClientConfig> implemen
*/
protected Config config;
protected Double calculateAmount(Integer amount) {
protected Double calculateAmount(Long amount) {
return amount / 100.0;
}
@ -70,4 +75,23 @@ public abstract class AbstractPayClient<Config extends PayClientConfig> implemen
return channelId;
}
@Override
public final PayCommonResult<?> unifiedOrder(PayOrderUnifiedReqDTO reqDTO) {
ValidationUtil.validate(reqDTO);
// 执行短信发送
PayCommonResult<?> result;
try {
result = doUnifiedOrder(reqDTO);
} catch (Throwable ex) {
// 打印异常日志
log.error("[unifiedOrder][request({}) 发起支付失败]", toJsonString(reqDTO), ex);
// 封装返回
return PayCommonResult.error(ex);
}
return result;
}
protected abstract PayCommonResult<?> doUnifiedOrder(PayOrderUnifiedReqDTO reqDTO)
throws Throwable;
}

View File

@ -1,7 +1,6 @@
package cn.iocoder.yudao.framework.pay.core.client.impl.alipay;
import cn.hutool.core.bean.BeanUtil;
import cn.iocoder.yudao.framework.common.pojo.CommonResult;
import cn.iocoder.yudao.framework.pay.core.client.PayCommonResult;
import cn.iocoder.yudao.framework.pay.core.client.dto.PayOrderUnifiedReqDTO;
import cn.iocoder.yudao.framework.pay.core.client.impl.AbstractPayClient;
@ -42,7 +41,7 @@ public class AlipayQrPayClient extends AbstractPayClient<AlipayPayClientConfig>
}
@Override
public CommonResult<AlipayTradePrecreateResponse> unifiedOrder(PayOrderUnifiedReqDTO reqDTO) {
public PayCommonResult<AlipayTradePrecreateResponse> doUnifiedOrder(PayOrderUnifiedReqDTO reqDTO) {
// 构建 AlipayTradePrecreateModel 请求
AlipayTradePrecreateModel model = new AlipayTradePrecreateModel();
model.setOutTradeNo(reqDTO.getMerchantOrderId());

View File

@ -1,7 +1,6 @@
package cn.iocoder.yudao.framework.pay.core.client.impl.alipay;
import cn.hutool.core.bean.BeanUtil;
import cn.iocoder.yudao.framework.common.pojo.CommonResult;
import cn.iocoder.yudao.framework.pay.core.client.PayCommonResult;
import cn.iocoder.yudao.framework.pay.core.client.dto.PayOrderUnifiedReqDTO;
import cn.iocoder.yudao.framework.pay.core.client.impl.AbstractPayClient;
@ -37,7 +36,7 @@ public class AlipayWapPayClient extends AbstractPayClient<AlipayPayClientConfig>
}
@Override
public CommonResult<AlipayTradeWapPayResponse> unifiedOrder(PayOrderUnifiedReqDTO reqDTO) {
public PayCommonResult<AlipayTradeWapPayResponse> doUnifiedOrder(PayOrderUnifiedReqDTO reqDTO) {
// 构建 AlipayTradeWapPayModel 请求
AlipayTradeWapPayModel model = new AlipayTradeWapPayModel();
model.setOutTradeNo(reqDTO.getMerchantOrderId());

View File

@ -1,5 +1,6 @@
package cn.iocoder.yudao.framework.pay.core.client.impl.wx;
import cn.hutool.core.util.StrUtil;
import cn.iocoder.yudao.framework.common.exception.ErrorCode;
import cn.iocoder.yudao.framework.common.exception.enums.GlobalErrorCodeConstants;
import cn.iocoder.yudao.framework.pay.core.client.AbstractPayCodeMapping;
@ -44,6 +45,11 @@ public class WXCodeMapping extends AbstractPayCodeMapping {
return PAY_OPENID_ERROR;
}
}
if (Objects.equals(apiCode, "CustomErrorCode")) {
if (StrUtil.contains(apiMsg, "必填字段")) {
return PAY_PARAM_MISSING;
}
}
return null;
}

View File

@ -3,8 +3,8 @@ package cn.iocoder.yudao.framework.pay.core.client.impl.wx;
import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.StrUtil;
import cn.iocoder.yudao.framework.common.pojo.CommonResult;
import cn.iocoder.yudao.framework.common.util.io.FileUtils;
import cn.iocoder.yudao.framework.common.util.object.ObjectUtils;
import cn.iocoder.yudao.framework.pay.core.client.PayCommonResult;
import cn.iocoder.yudao.framework.pay.core.client.dto.PayOrderUnifiedReqDTO;
import cn.iocoder.yudao.framework.pay.core.client.impl.AbstractPayClient;
@ -21,7 +21,6 @@ import com.github.binarywang.wxpay.service.WxPayService;
import com.github.binarywang.wxpay.service.impl.WxPayServiceImpl;
import lombok.extern.slf4j.Slf4j;
import static cn.hutool.core.util.ObjectUtil.defaultIfNull;
import static cn.iocoder.yudao.framework.common.util.json.JsonUtils.toJsonString;
import static cn.iocoder.yudao.framework.pay.core.client.impl.wx.WXCodeMapping.CODE_SUCCESS;
import static cn.iocoder.yudao.framework.pay.core.client.impl.wx.WXCodeMapping.MESSAGE_SUCCESS;
@ -62,7 +61,7 @@ public class WXPubPayClient extends AbstractPayClient<WXPayClientConfig> {
}
@Override
public CommonResult<WxPayMpOrderResult> unifiedOrder(PayOrderUnifiedReqDTO reqDTO) {
public PayCommonResult<WxPayMpOrderResult> doUnifiedOrder(PayOrderUnifiedReqDTO reqDTO) {
WxPayMpOrderResult response;
try {
switch (config.getApiVersion()) {
@ -80,8 +79,8 @@ public class WXPubPayClient extends AbstractPayClient<WXPayClientConfig> {
}
} catch (WxPayException e) {
log.error("[unifiedOrder][request({}) 发起支付失败,原因({})]", toJsonString(reqDTO), e);
return PayCommonResult.build(defaultIfNull(e.getErrCode(), e.getReturnCode()),
defaultIfNull(e.getErrCodeDes(), e.getReturnMsg()),null, codeMapping);
return PayCommonResult.build(ObjectUtils.defaultIfNull(e.getErrCode(), e.getReturnCode(), "CustomErrorCode"),
ObjectUtils.defaultIfNull(e.getErrCodeDes(), e.getCustomErrorMsg()),null, codeMapping);
}
return PayCommonResult.build(CODE_SUCCESS, MESSAGE_SUCCESS, response, codeMapping);
}
@ -92,9 +91,9 @@ public class WXPubPayClient extends AbstractPayClient<WXPayClientConfig> {
.outTradeNo(reqDTO.getMerchantOrderId())
// TODO 芋艿:貌似没 title
.body(reqDTO.getBody())
.totalFee(reqDTO.getAmount()) // 单位分
.totalFee(reqDTO.getAmount().intValue()) // 单位分
.timeExpire(DateUtil.format(reqDTO.getExpireTime(), "yyyyMMddHHmmss"))
.spbillCreateIp(reqDTO.getClientIp())
.spbillCreateIp(reqDTO.getUserIp())
.openid("ockUAwIZ-0OeMZl9ogcZ4ILrGba0") // TODO 芋艿:先随便写死
.notifyUrl(reqDTO.getNotifyUrl())
.build();
@ -108,10 +107,10 @@ public class WXPubPayClient extends AbstractPayClient<WXPayClientConfig> {
request.setOutTradeNo(reqDTO.getMerchantOrderId());
// TODO 芋艿:貌似没 title
request.setDescription(reqDTO.getBody());
request.setAmount(new WxPayUnifiedOrderV3Request.Amount().setTotal(reqDTO.getAmount())); // 单位分
request.setAmount(new WxPayUnifiedOrderV3Request.Amount().setTotal(reqDTO.getAmount().intValue())); // 单位分
request.setTimeExpire(DateUtil.format(reqDTO.getExpireTime(), "yyyyMMddHHmmss"));
request.setPayer(new WxPayUnifiedOrderV3Request.Payer().setOpenid("ockUAwIZ-0OeMZl9ogcZ4ILrGba0")); // TODO 芋艿:先随便写死
request.setSceneInfo(new WxPayUnifiedOrderV3Request.SceneInfo().setPayerClientIp(reqDTO.getClientIp()));
request.setSceneInfo(new WxPayUnifiedOrderV3Request.SceneInfo().setPayerClientIp(reqDTO.getUserIp()));
request.setNotifyUrl(reqDTO.getNotifyUrl());
// 执行请求
return client.createOrderV3(TradeTypeEnum.JSAPI, request);

View File

@ -20,6 +20,7 @@ public interface PayFrameworkErrorCodeConstants {
// ========== 其它相关 2002000900 开头 ==========
ErrorCode PAY_OPENID_ERROR = new ErrorCode(2002000900, "无效的 openid"); // 例如说,微信 openid 未授权过
ErrorCode PAY_PARAM_MISSING = new ErrorCode(2002000901, "请求参数缺失"); // 例如说,支付少传了金额
ErrorCode EXCEPTION = new ErrorCode(2002000999, "调用异常");

View File

@ -0,0 +1,2 @@
org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
cn.iocoder.yudao.framework.pay.config.YudaoPayAutoConfiguration

View File

@ -117,11 +117,11 @@ public class PayClientFactoryImplTest {
private static PayOrderUnifiedReqDTO buildPayOrderUnifiedReqDTO() {
PayOrderUnifiedReqDTO reqDTO = new PayOrderUnifiedReqDTO();
reqDTO.setAmount(123);
reqDTO.setAmount(123L);
reqDTO.setSubject("IPhone 13");
reqDTO.setBody("biubiubiu");
reqDTO.setMerchantOrderId(String.valueOf(System.currentTimeMillis()));
reqDTO.setClientIp("127.0.0.1");
reqDTO.setUserIp("127.0.0.1");
reqDTO.setNotifyUrl("http://127.0.0.1:8080");
return reqDTO;
}