parent
711a074059
commit
81126b2b4b
@ -1 +0,0 @@
|
||||
package cn.iocoder.yudao.adminserver.modules.pay.dal.dataobject;
|
||||
@ -0,0 +1,15 @@
|
||||
package cn.iocoder.yudao.coreservice.modules.pay.convert.order;
|
||||
|
||||
import cn.iocoder.yudao.coreservice.modules.pay.dal.dataobject.order.PayOrderDO;
|
||||
import cn.iocoder.yudao.coreservice.modules.pay.service.order.dto.PayOrderCreateReqDTO;
|
||||
import org.mapstruct.Mapper;
|
||||
import org.mapstruct.factory.Mappers;
|
||||
|
||||
@Mapper
|
||||
public interface PayOrderCoreServiceConvert {
|
||||
|
||||
PayOrderCoreServiceConvert INSTANCE = Mappers.getMapper(PayOrderCoreServiceConvert.class);
|
||||
|
||||
PayOrderDO convert(PayOrderCreateReqDTO bean);
|
||||
|
||||
}
|
||||
@ -0,0 +1,6 @@
|
||||
/**
|
||||
* 提供 POJO 类的实体转换
|
||||
*
|
||||
* 目前使用 MapStruct 框架
|
||||
*/
|
||||
package cn.iocoder.yudao.coreservice.modules.pay.convert;
|
||||
@ -0,0 +1 @@
|
||||
<http://www.iocoder.cn/Spring-Boot/MapStruct/?yudao>
|
||||
@ -1,6 +1,6 @@
|
||||
package cn.iocoder.yudao.adminserver.modules.pay.dal.dataobject.merchant;
|
||||
package cn.iocoder.yudao.coreservice.modules.pay.dal.dataobject.merchant;
|
||||
|
||||
import cn.iocoder.yudao.adminserver.modules.pay.enums.PayChannelCodeEnum;
|
||||
import cn.iocoder.yudao.coreservice.modules.pay.enums.merchant.PayChannelCodeEnum;
|
||||
import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum;
|
||||
import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO;
|
||||
import lombok.Data;
|
||||
@ -1,4 +1,4 @@
|
||||
package cn.iocoder.yudao.adminserver.modules.pay.dal.dataobject.merchant;
|
||||
package cn.iocoder.yudao.coreservice.modules.pay.dal.dataobject.merchant;
|
||||
|
||||
import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum;
|
||||
import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO;
|
||||
@ -1,4 +1,4 @@
|
||||
package cn.iocoder.yudao.adminserver.modules.pay.dal.dataobject.order;
|
||||
package cn.iocoder.yudao.coreservice.modules.pay.dal.dataobject.order;
|
||||
|
||||
import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO;
|
||||
import lombok.Data;
|
||||
@ -0,0 +1 @@
|
||||
package cn.iocoder.yudao.coreservice.modules.pay.dal.dataobject;
|
||||
@ -0,0 +1,9 @@
|
||||
package cn.iocoder.yudao.coreservice.modules.pay.dal.mysql.merchant;
|
||||
|
||||
import cn.iocoder.yudao.coreservice.modules.pay.dal.dataobject.merchant.PayAppDO;
|
||||
import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX;
|
||||
import org.apache.ibatis.annotations.Mapper;
|
||||
|
||||
@Mapper
|
||||
public interface PayAppCoreMapper extends BaseMapperX<PayAppDO> {
|
||||
}
|
||||
@ -0,0 +1,16 @@
|
||||
package cn.iocoder.yudao.coreservice.modules.pay.dal.mysql.order;
|
||||
|
||||
import cn.iocoder.yudao.coreservice.modules.pay.dal.dataobject.order.PayOrderDO;
|
||||
import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX;
|
||||
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
|
||||
import org.apache.ibatis.annotations.Mapper;
|
||||
|
||||
@Mapper
|
||||
public interface PayOrderCoreMapper extends BaseMapperX<PayOrderDO> {
|
||||
|
||||
default PayOrderDO selectByAppIdAndMerchantOrderId(Long appId, String merchantOrderId) {
|
||||
return selectOne(new QueryWrapper<PayOrderDO>().eq("app_id", appId)
|
||||
.eq("merchant_order_id", merchantOrderId));
|
||||
}
|
||||
|
||||
}
|
||||
@ -0,0 +1,28 @@
|
||||
package cn.iocoder.yudao.coreservice.modules.pay.enums.merchant;
|
||||
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Getter;
|
||||
|
||||
/**
|
||||
* 支付渠道的编码的枚举
|
||||
*
|
||||
* @author 芋道源码
|
||||
*/
|
||||
@Getter
|
||||
@AllArgsConstructor
|
||||
public enum PayChannelCodeEnum {
|
||||
|
||||
wx_pub("wx_pub", "微信 JSAPI 支付");
|
||||
|
||||
/**
|
||||
* 编码
|
||||
*
|
||||
* 参考 https://www.pingxx.com/api/支付渠道属性值.html
|
||||
*/
|
||||
private String code;
|
||||
/**
|
||||
* 名字
|
||||
*/
|
||||
private String name;
|
||||
|
||||
}
|
||||
@ -0,0 +1,29 @@
|
||||
package cn.iocoder.yudao.coreservice.modules.pay.enums.order;
|
||||
|
||||
import cn.iocoder.yudao.framework.common.core.IntArrayValuable;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Getter;
|
||||
|
||||
/**
|
||||
* 支付订单的状态枚举
|
||||
*
|
||||
* @author 芋道源码
|
||||
*/
|
||||
@Getter
|
||||
@AllArgsConstructor
|
||||
public enum PayOrderStatusEnum implements IntArrayValuable {
|
||||
|
||||
WAITING(0, "未支付"),
|
||||
SUCCESS(10, "支付成功"),
|
||||
CLOSED(20, "支付关闭"), // 未付款交易超时关闭,或支付完成后全额退款 TODO 芋艿:需要优化下
|
||||
;
|
||||
|
||||
private final Integer status;
|
||||
private final String name;
|
||||
|
||||
@Override
|
||||
public int[] array() {
|
||||
return new int[0];
|
||||
}
|
||||
|
||||
}
|
||||
@ -0,0 +1,43 @@
|
||||
package cn.iocoder.yudao.coreservice.modules.pay.service.merchant.impl;
|
||||
|
||||
import cn.iocoder.yudao.coreservice.modules.pay.dal.dataobject.merchant.PayAppDO;
|
||||
import cn.iocoder.yudao.coreservice.modules.pay.dal.mysql.merchant.PayAppCoreMapper;
|
||||
import cn.iocoder.yudao.coreservice.modules.pay.service.merchant.PayAppCoreService;
|
||||
import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
import javax.validation.Valid;
|
||||
|
||||
import static cn.iocoder.yudao.coreservice.modules.pay.enums.PayErrorCodeConstants.*;
|
||||
import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
|
||||
|
||||
/**
|
||||
* 支付应用 Core Service 实现类
|
||||
*
|
||||
* @author 芋道源码
|
||||
*/
|
||||
@Service
|
||||
@Valid
|
||||
@Slf4j
|
||||
public class PayAppCoreServiceImpl implements PayAppCoreService {
|
||||
|
||||
@Resource
|
||||
private PayAppCoreMapper payAppCoreMapper;
|
||||
|
||||
@Override
|
||||
public PayAppDO validPayApp(Long id) {
|
||||
PayAppDO app = payAppCoreMapper.selectById(id);
|
||||
// 校验是否存在
|
||||
if (app == null) {
|
||||
throw exception(PAY_APP_NOT_FOUND);
|
||||
}
|
||||
// 校验是否禁用
|
||||
if (CommonStatusEnum.DISABLE.getStatus().equals(app.getStatus())) {
|
||||
throw exception(PAY_APP_IS_DISABLE);
|
||||
}
|
||||
return app;
|
||||
}
|
||||
|
||||
}
|
||||
@ -0,0 +1,41 @@
|
||||
package cn.iocoder.yudao.coreservice.modules.pay.service.order.dto;
|
||||
|
||||
import lombok.Data;
|
||||
import lombok.experimental.Accessors;
|
||||
|
||||
import javax.validation.constraints.NotEmpty;
|
||||
import javax.validation.constraints.NotNull;
|
||||
import java.io.Serializable;
|
||||
|
||||
/**
|
||||
* 支付单提交 Request DTO
|
||||
*/
|
||||
@Data
|
||||
@Accessors(chain = true)
|
||||
public class PayOrderSubmitReqDTO implements Serializable {
|
||||
|
||||
/**
|
||||
* 应用编号
|
||||
*/
|
||||
@NotEmpty(message = "应用编号不能为空")
|
||||
private String appId;
|
||||
|
||||
/**
|
||||
* 支付单编号
|
||||
*/
|
||||
@NotNull(message = "支付单编号不能为空")
|
||||
private Long id;
|
||||
|
||||
/**
|
||||
* 支付渠道
|
||||
*/
|
||||
@NotNull(message = "支付渠道")
|
||||
private String channelCode;
|
||||
|
||||
/**
|
||||
* 客户端 IP
|
||||
*/
|
||||
@NotEmpty(message = "客户端 IP 不能为空")
|
||||
private String clientIp;
|
||||
|
||||
}
|
||||
@ -0,0 +1,23 @@
|
||||
package cn.iocoder.yudao.coreservice.modules.pay.service.order.dto;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
/**
|
||||
* 支付单提交 Response DTO
|
||||
*/
|
||||
@Data
|
||||
public class PayOrderSubmitRespDTO implements Serializable {
|
||||
|
||||
/**
|
||||
* 支付拓展单的编号
|
||||
*/
|
||||
private Long extensionId;
|
||||
|
||||
/**
|
||||
* 调用支付渠道的响应结果
|
||||
*/
|
||||
private String invokeResponse;
|
||||
|
||||
}
|
||||
@ -0,0 +1,89 @@
|
||||
package cn.iocoder.yudao.coreservice.modules.pay.service.order.impl;
|
||||
|
||||
import cn.iocoder.yudao.coreservice.modules.pay.convert.order.PayOrderCoreServiceConvert;
|
||||
import cn.iocoder.yudao.coreservice.modules.pay.dal.dataobject.merchant.PayAppDO;
|
||||
import cn.iocoder.yudao.coreservice.modules.pay.dal.dataobject.order.PayOrderDO;
|
||||
import cn.iocoder.yudao.coreservice.modules.pay.dal.mysql.order.PayOrderCoreMapper;
|
||||
import cn.iocoder.yudao.coreservice.modules.pay.enums.order.PayOrderStatusEnum;
|
||||
import cn.iocoder.yudao.coreservice.modules.pay.service.merchant.PayAppCoreService;
|
||||
import cn.iocoder.yudao.coreservice.modules.pay.service.order.PayOrderCoreService;
|
||||
import cn.iocoder.yudao.coreservice.modules.pay.service.order.dto.PayOrderCreateReqDTO;
|
||||
import cn.iocoder.yudao.coreservice.modules.pay.service.order.dto.PayOrderSubmitReqDTO;
|
||||
import cn.iocoder.yudao.coreservice.modules.pay.service.order.dto.PayOrderSubmitRespDTO;
|
||||
import cn.iocoder.yudao.framework.common.pojo.CommonResult;
|
||||
import cn.iocoder.yudao.framework.common.util.json.JsonUtils;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
import javax.validation.Valid;
|
||||
|
||||
/**
|
||||
* 支付订单 Core Service 实现类
|
||||
*/
|
||||
@Service
|
||||
@Valid
|
||||
@Slf4j
|
||||
public class PayOrderCoreServiceImpl implements PayOrderCoreService {
|
||||
|
||||
@Resource
|
||||
private PayAppCoreService payAppCoreService;
|
||||
|
||||
@Resource
|
||||
private PayOrderCoreMapper payOrderCoreMapper;
|
||||
|
||||
@Override
|
||||
public Long createPayOrder(PayOrderCreateReqDTO reqDTO) {
|
||||
// 校验 App
|
||||
PayAppDO app = payAppCoreService.validPayApp(reqDTO.getAppId());
|
||||
|
||||
// 查询对应的支付交易单是否已经存在。如果是,则直接返回
|
||||
PayOrderDO order = payOrderCoreMapper.selectByAppIdAndMerchantOrderId(
|
||||
reqDTO.getAppId(), reqDTO.getMerchantOrderId());
|
||||
if (order != null) {
|
||||
log.warn("[createPayOrder][appId({}) merchantOrderId({}) 已经存在对应的支付单({})]", order.getAppId(),
|
||||
order.getMerchantOrderId(), JsonUtils.toJsonString(order)); // 理论来说,不会出现这个情况
|
||||
return app.getId();
|
||||
}
|
||||
|
||||
// 创建支付交易单
|
||||
order = PayOrderCoreServiceConvert.INSTANCE.convert(reqDTO)
|
||||
.setStatus(PayOrderStatusEnum.WAITING.getStatus())
|
||||
.setNotifyUrl(app.getPayNotifyUrl());
|
||||
payOrderCoreMapper.insert(order);
|
||||
// 最终返回
|
||||
return order.getId();
|
||||
}
|
||||
|
||||
@Override
|
||||
public PayOrderSubmitRespDTO submitPayOrder(PayOrderSubmitReqDTO reqDTO) {
|
||||
// 校验 App
|
||||
PayAppDO app = payAppCoreService.validPayApp(reqDTO.getId());
|
||||
// TODO 校验支付渠道是否有效
|
||||
|
||||
// 获得 PayOrderDO ,并校验其是否存在
|
||||
PayOrderDO order = payOrderCoreMapper.selectById(reqDTO.getId());
|
||||
if (order == null) { // 是否存在
|
||||
throw exception(PAY_TRANSACTION_NOT_FOUND);
|
||||
}
|
||||
if (!PayOrderStatusEnum.WAITING.getStatus().equals(order.getStatus())) { // 校验状态,必须是待支付
|
||||
throw exception(PAY_TRANSACTION_STATUS_IS_NOT_WAITING);
|
||||
}
|
||||
|
||||
// 插入 PayTransactionExtensionDO
|
||||
PayTransactionExtensionDO payTransactionExtensionDO = PayTransactionConvert.INSTANCE.convert(submitReqDTO)
|
||||
.setTransactionId(payTransaction.getId()).setTransactionCode(generateTransactionCode())
|
||||
.setStatus(PayTransactionStatusEnum.WAITING.getStatus());
|
||||
payTransactionExtensionMapper.insert(payTransactionExtensionDO);
|
||||
|
||||
// 调用三方接口
|
||||
AbstractThirdPayClient thirdPayClient = ThirdPayClientFactory.getThirdPayClient(submitReqDTO.getPayChannel());
|
||||
CommonResult<String> invokeResult = thirdPayClient.submitTransaction(payTransaction, payTransactionExtensionDO, null); // TODO 暂时传入 extra = null
|
||||
invokeResult.checkError();
|
||||
|
||||
// TODO 轮询三方接口,是否已经支付的任务
|
||||
// 返回成功
|
||||
return new PayTransactionSubmitRespDTO().setId(payTransactionExtensionDO.getId()).setInvokeResponse(invokeResult.getData());
|
||||
}
|
||||
|
||||
}
|
||||
@ -0,0 +1 @@
|
||||
package cn.iocoder.yudao.coreservice.modules.pay.service;
|
||||
@ -1,8 +0,0 @@
|
||||
/**
|
||||
* @description
|
||||
* @author Qingchen
|
||||
* @version 1.0.0
|
||||
* @date 2021-10-12 10:42
|
||||
* @class cn.iocoder.yudao.framework.pay.core.domain.merchant.package-info.java
|
||||
*/
|
||||
package cn.iocoder.yudao.framework.pay.core.domain.merchant;
|
||||
@ -1,8 +0,0 @@
|
||||
/**
|
||||
* @description
|
||||
* @author Qingchen
|
||||
* @version 1.0.0
|
||||
* @date 2021-09-29 14:44
|
||||
* @class cn.iocoder.yudao.framework.pay.core.domain.package-info.java
|
||||
*/
|
||||
package cn.iocoder.yudao.framework.pay.core.domain;
|
||||
@ -1,8 +0,0 @@
|
||||
/**
|
||||
* @description
|
||||
* @author Qingchen
|
||||
* @version 1.0.0
|
||||
* @date 2021-10-12 10:42
|
||||
* @class cn.iocoder.yudao.framework.pay.core.domain.pay.package-info.java
|
||||
*/
|
||||
package cn.iocoder.yudao.framework.pay.core.domain.pay;
|
||||
@ -1,8 +0,0 @@
|
||||
/**
|
||||
* @description
|
||||
* @author Qingchen
|
||||
* @version 1.0.0
|
||||
* @date 2021-10-12 10:42
|
||||
* @class cn.iocoder.yudao.framework.pay.core.domain.refund.package-info.java
|
||||
*/
|
||||
package cn.iocoder.yudao.framework.pay.core.domain.refund;
|
||||
Loading…
Reference in New Issue