- 后端:更新 README

- 后端:重构部分代码
This commit is contained in:
YunaiV
2019-05-17 19:23:26 +08:00
parent 68027b9f16
commit dbf2a43924
108 changed files with 589 additions and 1017 deletions

View File

@@ -1,17 +1,20 @@
package cn.iocoder.mall.pay.biz.component;
import org.apache.dubbo.config.ApplicationConfig;
import org.apache.dubbo.config.ReferenceConfig;
import org.apache.dubbo.config.RegistryConfig;
import org.apache.dubbo.rpc.service.GenericService;
import cn.iocoder.common.framework.util.StringUtil;
import com.google.common.cache.CacheBuilder;
import com.google.common.cache.CacheLoader;
import com.google.common.cache.LoadingCache;
import lombok.Data;
import org.apache.dubbo.config.ApplicationConfig;
import org.apache.dubbo.config.ReferenceConfig;
import org.apache.dubbo.config.RegistryConfig;
import org.apache.dubbo.rpc.service.GenericService;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
import org.springframework.util.Assert;
import java.util.List;
@Component
public class DubboReferencePool {
@@ -44,7 +47,8 @@ public class DubboReferencePool {
private String dubboApplicationName;
private ReferenceMeta createGenericService(String notifyUrl) {
String[] notifyUrlParts = notifyUrl.split("#");
// 使用 # 号分隔,格式为 服务名#方法名#版本号
List<String> notifyUrlParts = StringUtil.split(notifyUrl, "#");
// 创建 ApplicationConfig 对象
ApplicationConfig application = new ApplicationConfig();
application.setName(dubboApplicationName);
@@ -55,14 +59,14 @@ public class DubboReferencePool {
application.setRegistry(registry);
// 创建 ReferenceConfig 对象
ReferenceConfig<GenericService> reference = new ReferenceConfig<>();
reference.setInterface(notifyUrlParts[0]); // 弱类型接口名
reference.setInterface(notifyUrlParts.get(0)); // 弱类型接口名
reference.setGeneric(true); // 声明为泛化接口
reference.setApplication(application);
// reference.setVersion("*"); // TODO 芋艿,后面要优化下。
reference.setVersion(notifyUrlParts.size() > 2 ? notifyUrlParts.get(2) : "1.0.0"); // 如果未配置服务的版本号,则默认使用 1.0.0
// 获得 GenericService 对象
GenericService genericService = reference.get();
// 构建最终的 ReferenceMeta 对象
return new ReferenceMeta(reference, genericService, notifyUrlParts[1]);
return new ReferenceMeta(reference, genericService, notifyUrlParts.get(1));
}
public ReferenceMeta getReferenceMeta(String notifyUrl) {

View File

@@ -1,7 +1,7 @@
package cn.iocoder.mall.pay.biz.convert;
import cn.iocoder.mall.pay.api.bo.PayRefundBO;
import cn.iocoder.mall.pay.api.dto.PayRefundSubmitDTO;
import cn.iocoder.mall.pay.api.bo.refund.PayRefundBO;
import cn.iocoder.mall.pay.api.dto.refund.PayRefundSubmitDTO;
import cn.iocoder.mall.pay.biz.dataobject.PayRefundDO;
import org.mapstruct.Mapper;
import org.mapstruct.Mappings;

View File

@@ -1,8 +1,8 @@
package cn.iocoder.mall.pay.biz.convert;
import cn.iocoder.mall.pay.api.bo.PayTransactionBO;
import cn.iocoder.mall.pay.api.dto.PayTransactionCreateDTO;
import cn.iocoder.mall.pay.api.dto.PayTransactionSubmitDTO;
import cn.iocoder.mall.pay.api.bo.transaction.PayTransactionBO;
import cn.iocoder.mall.pay.api.dto.transaction.PayTransactionCreateDTO;
import cn.iocoder.mall.pay.api.dto.transaction.PayTransactionSubmitDTO;
import cn.iocoder.mall.pay.biz.dataobject.PayTransactionDO;
import cn.iocoder.mall.pay.biz.dataobject.PayTransactionExtensionDO;
import org.mapstruct.Mapper;

View File

@@ -18,6 +18,7 @@ import java.util.Date;
topic = PayRefundSuccessMessage.TOPIC,
consumerGroup = "pay-consumer-group-" + PayRefundSuccessMessage.TOPIC
)
@Deprecated // 艿艿:突然发现,业务方实际无需回调。参考了 https://help.youzan.com/displaylist/detail_4_998 的文章。业务方,只要记录下退款单号,进行关联即可。
public class PayRefundSuccessConsumer extends AbstractPayNotifySuccessConsumer<PayRefundSuccessMessage>
implements RocketMQListener<PayRefundSuccessMessage> {

View File

@@ -2,7 +2,6 @@ package cn.iocoder.mall.pay.biz.service;
import cn.iocoder.common.framework.constant.CommonStatusEnum;
import cn.iocoder.common.framework.util.ServiceExceptionUtil;
import cn.iocoder.common.framework.vo.CommonResult;
import cn.iocoder.mall.pay.api.constant.PayErrorCodeEnum;
import cn.iocoder.mall.pay.biz.dao.PayAppMapper;
import cn.iocoder.mall.pay.biz.dataobject.PayAppDO;
@@ -15,17 +14,17 @@ public class PayAppServiceImpl {
@Autowired
private PayAppMapper payAppMapper;
public CommonResult<PayAppDO> validPayApp(String appId) {
public PayAppDO validPayApp(String appId) {
PayAppDO payAppDO = payAppMapper.selectById(appId);
// 校验是否存在
if (payAppDO == null) {
return ServiceExceptionUtil.error(PayErrorCodeEnum.PAY_APP_NOT_FOUND.getCode());
throw ServiceExceptionUtil.exception(PayErrorCodeEnum.PAY_APP_NOT_FOUND.getCode());
}
// 校验是否禁用
if (CommonStatusEnum.DISABLE.getValue().equals(payAppDO.getStatus())) {
return ServiceExceptionUtil.error(PayErrorCodeEnum.PAY_APP_IS_DISABLE.getCode());
throw ServiceExceptionUtil.exception(PayErrorCodeEnum.PAY_APP_IS_DISABLE.getCode());
}
return CommonResult.success(payAppDO);
return payAppDO;
}
}
}

View File

@@ -27,6 +27,7 @@ public class PayNotifyServiceImpl {
@Resource
private RocketMQTemplate rocketMQTemplate;
@Deprecated // 参见 PayRefundSuccessConsumer 类的说明
public void addRefundNotifyTask(PayRefundDO refund) {
PayNotifyTaskDO payTransactionNotifyTask = this.createBasePayNotifyTaskDO(refund.getAppId(), refund.getNotifyUrl())
.setType(PayNotifyType.REFUND.getValue());

View File

@@ -5,13 +5,13 @@ import cn.iocoder.common.framework.util.MathUtil;
import cn.iocoder.common.framework.util.ServiceExceptionUtil;
import cn.iocoder.common.framework.vo.CommonResult;
import cn.iocoder.mall.pay.api.PayRefundService;
import cn.iocoder.mall.pay.api.bo.PayRefundPageBO;
import cn.iocoder.mall.pay.api.bo.PayRefundSubmitBO;
import cn.iocoder.mall.pay.api.bo.refund.PayRefundPageBO;
import cn.iocoder.mall.pay.api.bo.refund.PayRefundSubmitBO;
import cn.iocoder.mall.pay.api.constant.PayErrorCodeEnum;
import cn.iocoder.mall.pay.api.constant.PayRefundStatus;
import cn.iocoder.mall.pay.api.constant.PayTransactionStatusEnum;
import cn.iocoder.mall.pay.api.dto.PayRefundPageDTO;
import cn.iocoder.mall.pay.api.dto.PayRefundSubmitDTO;
import cn.iocoder.mall.pay.api.dto.refund.PayRefundPageDTO;
import cn.iocoder.mall.pay.api.dto.refund.PayRefundSubmitDTO;
import cn.iocoder.mall.pay.biz.client.AbstractPaySDK;
import cn.iocoder.mall.pay.biz.client.PaySDKFactory;
import cn.iocoder.mall.pay.biz.client.RefundSuccessBO;
@@ -51,13 +51,9 @@ public class PayRefundServiceImpl implements PayRefundService {
private RocketMQTemplate rocketMQTemplate;
@Override
@SuppressWarnings("Duplicates")
public CommonResult<PayRefundSubmitBO> submitRefund(PayRefundSubmitDTO payRefundSubmitDTO) {
// 校验 App 是否有效
CommonResult<PayAppDO> appResult = payAppService.validPayApp(payRefundSubmitDTO.getAppId());
if (appResult.isError()) {
return CommonResult.error(appResult);
}
PayAppDO payAppDO = payAppService.validPayApp(payRefundSubmitDTO.getAppId());
// 获得 PayTransactionDO ,并校验其是否存在
PayTransactionDO payTransaction = payTransactionService.getTransaction(payRefundSubmitDTO.getAppId(), payRefundSubmitDTO.getOrderId());
if (payTransaction == null) { // 是否存在
@@ -82,7 +78,7 @@ public class PayRefundServiceImpl implements PayRefundService {
.setTransactionId(payTransaction.getId())
.setRefundCode(generateTransactionCode()) // TODO 芋艿,后续调整
.setStatus(PayRefundStatus.WAITING.getValue())
.setNotifyUrl(appResult.getData().getRefundNotifyUrl())
.setNotifyUrl(payAppDO.getRefundNotifyUrl())
.setRefundChannel(payTransaction.getPayChannel());
payRefundDO.setCreateTime(new Date());
payRefundMapper.insert(payRefundDO);

View File

@@ -5,14 +5,15 @@ import cn.iocoder.common.framework.util.MathUtil;
import cn.iocoder.common.framework.util.ServiceExceptionUtil;
import cn.iocoder.common.framework.vo.CommonResult;
import cn.iocoder.mall.pay.api.PayTransactionService;
import cn.iocoder.mall.pay.api.bo.PayTransactionBO;
import cn.iocoder.mall.pay.api.bo.PayTransactionPageBO;
import cn.iocoder.mall.pay.api.bo.PayTransactionSubmitBO;
import cn.iocoder.mall.pay.api.bo.transaction.PayTransactionBO;
import cn.iocoder.mall.pay.api.bo.transaction.PayTransactionPageBO;
import cn.iocoder.mall.pay.api.bo.transaction.PayTransactionSubmitBO;
import cn.iocoder.mall.pay.api.constant.PayErrorCodeEnum;
import cn.iocoder.mall.pay.api.constant.PayTransactionStatusEnum;
import cn.iocoder.mall.pay.api.dto.PayTransactionCreateDTO;
import cn.iocoder.mall.pay.api.dto.PayTransactionPageDTO;
import cn.iocoder.mall.pay.api.dto.PayTransactionSubmitDTO;
import cn.iocoder.mall.pay.api.dto.transaction.PayTransactionCreateDTO;
import cn.iocoder.mall.pay.api.dto.transaction.PayTransactionGetDTO;
import cn.iocoder.mall.pay.api.dto.transaction.PayTransactionPageDTO;
import cn.iocoder.mall.pay.api.dto.transaction.PayTransactionSubmitDTO;
import cn.iocoder.mall.pay.biz.client.AbstractPaySDK;
import cn.iocoder.mall.pay.biz.client.PaySDKFactory;
import cn.iocoder.mall.pay.biz.client.TransactionSuccessBO;
@@ -68,23 +69,21 @@ public class PayTransactionServiceImpl implements PayTransactionService {
}
@Override
public CommonResult<PayTransactionBO> getTransaction(Integer userId, String appId, String orderId) {
PayTransactionDO payTransaction = payTransactionMapper.selectByAppIdAndOrderId(appId, orderId);
public PayTransactionBO getTransaction(PayTransactionGetDTO payTransactionGetDTO) {
PayTransactionDO payTransaction = payTransactionMapper.selectByAppIdAndOrderId(payTransactionGetDTO.getAppId(),
payTransactionGetDTO.getOrderId());
if (payTransaction == null) {
return ServiceExceptionUtil.error(PayErrorCodeEnum.PAY_TRANSACTION_NOT_FOUND.getCode());
throw ServiceExceptionUtil.exception(PayErrorCodeEnum.PAY_TRANSACTION_NOT_FOUND.getCode());
}
// TODO 芋艿 userId 的校验
return CommonResult.success(PayTransactionConvert.INSTANCE.convert(payTransaction));
return PayTransactionConvert.INSTANCE.convert(payTransaction);
}
@Override
@SuppressWarnings("Duplicates")
public CommonResult<PayTransactionBO> createTransaction(PayTransactionCreateDTO payTransactionCreateDTO) {
public PayTransactionBO createTransaction(PayTransactionCreateDTO payTransactionCreateDTO) {
// 校验 App
CommonResult<PayAppDO> appResult = payAppService.validPayApp(payTransactionCreateDTO.getAppId());
if (appResult.isError()) {
return CommonResult.error(appResult);
}
PayAppDO payAppDO = payAppService.validPayApp(payTransactionCreateDTO.getAppId());
// 插入 PayTransactionDO
PayTransactionDO payTransaction = payTransactionMapper.selectByAppIdAndOrderId(
payTransactionCreateDTO.getAppId(), payTransactionCreateDTO.getOrderId());
@@ -95,31 +94,28 @@ public class PayTransactionServiceImpl implements PayTransactionService {
} else {
payTransaction = PayTransactionConvert.INSTANCE.convert(payTransactionCreateDTO);
payTransaction.setStatus(PayTransactionStatusEnum.WAITING.getValue())
.setNotifyUrl(appResult.getData().getNotifyUrl());
.setNotifyUrl(payAppDO.getNotifyUrl());
payTransaction.setCreateTime(new Date());
payTransactionMapper.insert(payTransaction);
}
// 返回成功
return CommonResult.success(PayTransactionConvert.INSTANCE.convert(payTransaction));
return PayTransactionConvert.INSTANCE.convert(payTransaction);
}
@Override
@SuppressWarnings("Duplicates")
public CommonResult<PayTransactionSubmitBO> submitTransaction(PayTransactionSubmitDTO payTransactionSubmitDTO) {
public PayTransactionSubmitBO submitTransaction(PayTransactionSubmitDTO payTransactionSubmitDTO) {
// TODO 校验支付渠道是否有效
// 校验 App 是否有效
CommonResult<PayAppDO> appResult = payAppService.validPayApp(payTransactionSubmitDTO.getAppId());
if (appResult.isError()) {
return CommonResult.error(appResult);
}
payAppService.validPayApp(payTransactionSubmitDTO.getAppId());
// 获得 PayTransactionDO ,并校验其是否存在
PayTransactionDO payTransaction = payTransactionMapper.selectByAppIdAndOrderId(
payTransactionSubmitDTO.getAppId(), payTransactionSubmitDTO.getOrderId());
if (payTransaction == null) { // 是否存在
return ServiceExceptionUtil.error(PayErrorCodeEnum.PAY_TRANSACTION_NOT_FOUND.getCode());
throw ServiceExceptionUtil.exception(PayErrorCodeEnum.PAY_TRANSACTION_NOT_FOUND.getCode());
}
if (!PayTransactionStatusEnum.WAITING.getValue().equals(payTransaction.getStatus())) { // 校验状态,必须是待支付
return ServiceExceptionUtil.error(PayErrorCodeEnum.PAY_TRANSACTION_STATUS_IS_NOT_WAITING.getCode());
throw ServiceExceptionUtil.exception(PayErrorCodeEnum.PAY_TRANSACTION_STATUS_IS_NOT_WAITING.getCode());
}
// 插入 PayTransactionExtensionDO
PayTransactionExtensionDO payTransactionExtensionDO = PayTransactionConvert.INSTANCE.convert(payTransactionSubmitDTO)
@@ -131,33 +127,32 @@ public class PayTransactionServiceImpl implements PayTransactionService {
AbstractPaySDK paySDK = PaySDKFactory.getSDK(payTransactionSubmitDTO.getPayChannel());
CommonResult<String> invokeResult = paySDK.submitTransaction(payTransaction, payTransactionExtensionDO, null); // TODO 暂时传入 extra = null
if (invokeResult.isError()) {
return CommonResult.error(invokeResult);
throw ServiceExceptionUtil.exception(invokeResult.getCode(), invokeResult.getMessage());
}
// TODO 轮询三方接口,是否已经支付的任务
// 返回成功
PayTransactionSubmitBO payTransactionSubmitBO = new PayTransactionSubmitBO()
.setId(payTransactionExtensionDO.getId()).setInvokeResponse(invokeResult.getData());
return CommonResult.success(payTransactionSubmitBO);
return new PayTransactionSubmitBO().setId(payTransactionExtensionDO.getId())
.setInvokeResponse(invokeResult.getData());
}
@Override
@Transactional
public CommonResult<Boolean> updateTransactionPaySuccess(Integer payChannel, String params) {
public Boolean updateTransactionPaySuccess(Integer payChannel, String params) {
// TODO 芋艿,记录回调日志
// 解析传入的参数,成 TransactionSuccessBO 对象
AbstractPaySDK paySDK = PaySDKFactory.getSDK(payChannel);
CommonResult<TransactionSuccessBO> paySuccessResult = paySDK.parseTransactionSuccessParams(params);
if (paySuccessResult.isError()) {
return CommonResult.error(paySuccessResult);
throw ServiceExceptionUtil.exception(paySuccessResult.getCode(), paySuccessResult.getMessage());
}
// TODO 芋艿,先最严格的校验。即使调用方重复调用,实际哪个订单已经被重复回调的支付,也返回 false 。也没问题,因为实际已经回调成功了。
// 1.1 查询 PayTransactionExtensionDO
PayTransactionExtensionDO extension = payTransactionExtensionMapper.selectByTransactionCode(paySuccessResult.getData().getTransactionCode());
if (extension == null) {
return ServiceExceptionUtil.error(PayErrorCodeEnum.PAY_TRANSACTION_EXTENSION_NOT_FOUND.getCode());
throw ServiceExceptionUtil.exception(PayErrorCodeEnum.PAY_TRANSACTION_EXTENSION_NOT_FOUND.getCode());
}
if (!PayTransactionStatusEnum.WAITING.getValue().equals(extension.getStatus())) { // 校验状态,必须是待支付
return ServiceExceptionUtil.error(PayErrorCodeEnum.PAY_TRANSACTION_EXTENSION_STATUS_IS_NOT_WAITING.getCode());
throw ServiceExceptionUtil.exception(PayErrorCodeEnum.PAY_TRANSACTION_EXTENSION_STATUS_IS_NOT_WAITING.getCode());
}
// 1.2 更新 PayTransactionExtensionDO
PayTransactionExtensionDO updatePayTransactionExtension = new PayTransactionExtensionDO()
@@ -172,7 +167,7 @@ public class PayTransactionServiceImpl implements PayTransactionService {
// 2.1 判断 PayTransactionDO 是否处于待支付
PayTransactionDO transaction = payTransactionMapper.selectById(extension.getTransactionId());
if (transaction == null) {
return ServiceExceptionUtil.error(PayErrorCodeEnum.PAY_TRANSACTION_NOT_FOUND.getCode());
throw ServiceExceptionUtil.exception(PayErrorCodeEnum.PAY_TRANSACTION_NOT_FOUND.getCode());
}
if (!PayTransactionStatusEnum.WAITING.getValue().equals(transaction.getStatus())) { // 校验状态,必须是待支付
throw ServiceExceptionUtil.exception(PayErrorCodeEnum.PAY_TRANSACTION_STATUS_IS_NOT_WAITING.getCode());
@@ -191,10 +186,10 @@ public class PayTransactionServiceImpl implements PayTransactionService {
throw ServiceExceptionUtil.exception(PayErrorCodeEnum.PAY_TRANSACTION_STATUS_IS_NOT_WAITING.getCode());
}
logger.info("[updateTransactionPaySuccess][PayTransactionDO({}) 更新为已支付]", transaction.getId());
// 3 新增 PayNotifyTaskDO
payNotifyService.addTransactionNotifyTask(transaction, extension);
// 3 新增 PayNotifyTaskDO 注释原因,参见 PayRefundSuccessConsumer 类。
// payNotifyService.addTransactionNotifyTask(transaction, extension);
// 返回结果
return CommonResult.success(true);
return true;
}
@Override

View File

@@ -1,7 +1,7 @@
package cn.iocoder.mall.pay.biz.service;
import cn.iocoder.mall.pay.api.PayRefundService;
import cn.iocoder.mall.pay.api.dto.PayRefundSubmitDTO;
import cn.iocoder.mall.pay.api.dto.refund.PayRefundSubmitDTO;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;

View File

@@ -1,10 +1,6 @@
package cn.iocoder.mall.pay.biz.service;
import cn.iocoder.mall.pay.api.dto.PayRefundSubmitDTO;
import org.junit.Ignore;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;