From 207fdc1d5593501da31259197ea09d1fb256eba7 Mon Sep 17 00:00:00 2001 From: YunaiV <> Date: Sat, 27 Apr 2019 01:52:24 +0800 Subject: [PATCH] =?UTF-8?q?=E5=90=8E=E7=AB=AF=EF=BC=9A=E5=AE=8C=E6=88=90?= =?UTF-8?q?=E9=80=80=E6=AC=BE=E9=80=BB=E8=BE=91?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../mall/order/api/OrderReturnService.java | 13 +- .../biz/service/OrderReturnServiceImpl.java | 5 + .../order/biz/service/OrderServiceImpl.java | 8 +- .../AbstractPayNotifySuccessMessage.java | 26 ++++ .../api/message/PayRefundSuccessMessage.java | 77 +--------- .../message/PayTransactionSuccessMessage.java | 77 +--------- .../mall/pay/biz/client/PingxxPaySDK.java | 18 ++- .../pay/biz/component/DubboReferencePool.java | 66 +++++++++ .../pay/biz/convert/PayNotifyConvert.java | 29 ++++ .../pay/biz/convert/PayRefundConvert.java | 17 +++ .../biz/convert/PayTransactionConvert.java | 22 --- ...LogMapper.java => PayNotifyLogMapper.java} | 2 +- ...skMapper.java => PayNotifyTaskMapper.java} | 2 +- .../PayNotifyJob.java} | 23 +-- .../mq/AbstractPayNotifySuccessConsumer.java | 82 +++++++++++ .../pay/biz/mq/PayRefundSuccessConsumer.java | 45 ++++++ .../biz/mq/PayTransactionSuccessConsumer.java | 133 ++---------------- .../pay/biz/service/PayNotifyServiceImpl.java | 25 +++- .../pay/biz/service/PayRefundServiceImpl.java | 15 +- .../service/PayTransactionServiceImpl.java | 4 +- ...fyLogMapper.xml => PayNotifyLogMapper.xml} | 4 +- ...TaskMapper.xml => PayNotifyTaskMapper.xml} | 32 +++-- .../main/resources/mapper/PayRefundMapper.xml | 2 +- .../resources/mapper/PayTransactionMapper.xml | 4 +- .../biz/service/PayRefundServiceImplTest.java | 29 ++++ .../PayTransactionServiceImplTest.java | 17 +++ .../mall/promotion/api/CouponService.java | 4 +- 27 files changed, 446 insertions(+), 335 deletions(-) create mode 100644 pay/pay-service-api/src/main/java/cn/iocoder/mall/pay/api/message/AbstractPayNotifySuccessMessage.java create mode 100644 pay/pay-service-impl/src/main/java/cn/iocoder/mall/pay/biz/convert/PayNotifyConvert.java create mode 100644 pay/pay-service-impl/src/main/java/cn/iocoder/mall/pay/biz/convert/PayRefundConvert.java rename pay/pay-service-impl/src/main/java/cn/iocoder/mall/pay/biz/dao/{PayTransactionNotifyLogMapper.java => PayNotifyLogMapper.java} (80%) rename pay/pay-service-impl/src/main/java/cn/iocoder/mall/pay/biz/dao/{PayTransactionNotifyTaskMapper.java => PayNotifyTaskMapper.java} (92%) rename pay/pay-service-impl/src/main/java/cn/iocoder/mall/pay/biz/{scheduler/PayTransactionNotifyJob.java => job/PayNotifyJob.java} (68%) create mode 100644 pay/pay-service-impl/src/main/java/cn/iocoder/mall/pay/biz/mq/AbstractPayNotifySuccessConsumer.java create mode 100644 pay/pay-service-impl/src/main/java/cn/iocoder/mall/pay/biz/mq/PayRefundSuccessConsumer.java rename pay/pay-service-impl/src/main/resources/mapper/{PayTransactionNotifyLogMapper.xml => PayNotifyLogMapper.xml} (93%) rename pay/pay-service-impl/src/main/resources/mapper/{PayTransactionNotifyTaskMapper.xml => PayNotifyTaskMapper.xml} (55%) create mode 100644 pay/pay-service-impl/src/test/java/cn/iocoder/mall/pay/biz/service/PayRefundServiceImplTest.java create mode 100644 pay/pay-service-impl/src/test/java/cn/iocoder/mall/pay/biz/service/PayTransactionServiceImplTest.java diff --git a/order/order-service-api/src/main/java/cn/iocoder/mall/order/api/OrderReturnService.java b/order/order-service-api/src/main/java/cn/iocoder/mall/order/api/OrderReturnService.java index 0ca47ee5..c35c59db 100644 --- a/order/order-service-api/src/main/java/cn/iocoder/mall/order/api/OrderReturnService.java +++ b/order/order-service-api/src/main/java/cn/iocoder/mall/order/api/OrderReturnService.java @@ -2,7 +2,6 @@ package cn.iocoder.mall.order.api; import cn.iocoder.common.framework.vo.CommonResult; import cn.iocoder.mall.order.api.dto.OrderReturnApplyDTO; -import cn.iocoder.mall.order.api.dto.OrderReturnCreateDTO; /** * 订单退货 @@ -21,4 +20,16 @@ public interface OrderReturnService { */ CommonResult orderReturnApply(OrderReturnApplyDTO orderReturnApplyDTO); + /** + * 更新退款成功 + * + * 如果成功,则返回 success + * 如果失败,则返回具体原因 + * + * @param orderId 订单编号 + * @param refundPrice 退款金额 + * @return 支付结果 + */ + String updateRefundSuccess(String orderId, Integer refundPrice); + } diff --git a/order/order-service-impl/src/main/java/cn/iocoder/mall/order/biz/service/OrderReturnServiceImpl.java b/order/order-service-impl/src/main/java/cn/iocoder/mall/order/biz/service/OrderReturnServiceImpl.java index 82d66033..408cff3b 100644 --- a/order/order-service-impl/src/main/java/cn/iocoder/mall/order/biz/service/OrderReturnServiceImpl.java +++ b/order/order-service-impl/src/main/java/cn/iocoder/mall/order/biz/service/OrderReturnServiceImpl.java @@ -52,4 +52,9 @@ public class OrderReturnServiceImpl implements OrderReturnService { orderReturnMapper.insert(orderReturnDO); return CommonResult.success(null); } + + @Override + public String updateRefundSuccess(String orderId, Integer refundPrice) { + return "success"; + } } diff --git a/order/order-service-impl/src/main/java/cn/iocoder/mall/order/biz/service/OrderServiceImpl.java b/order/order-service-impl/src/main/java/cn/iocoder/mall/order/biz/service/OrderServiceImpl.java index 4ab06a05..1b262822 100644 --- a/order/order-service-impl/src/main/java/cn/iocoder/mall/order/biz/service/OrderServiceImpl.java +++ b/order/order-service-impl/src/main/java/cn/iocoder/mall/order/biz/service/OrderServiceImpl.java @@ -258,9 +258,11 @@ public class OrderServiceImpl implements OrderService { } // 标记优惠劵已使用 - CommonResult useCouponCardResult = couponService.useCouponCard(userId, orderCreateDTO.getCouponCardId()); - if (useCouponCardResult.isError()) { - return CommonResult.error(useCouponCardResult); + if (orderCreateDTO.getCouponCardId() != null) { + CommonResult useCouponCardResult = couponService.useCouponCard(userId, orderCreateDTO.getCouponCardId()); + if (useCouponCardResult.isError()) { + return CommonResult.error(useCouponCardResult); + } } // TODO 芋艿,扣除库存 diff --git a/pay/pay-service-api/src/main/java/cn/iocoder/mall/pay/api/message/AbstractPayNotifySuccessMessage.java b/pay/pay-service-api/src/main/java/cn/iocoder/mall/pay/api/message/AbstractPayNotifySuccessMessage.java new file mode 100644 index 00000000..28ffb6a0 --- /dev/null +++ b/pay/pay-service-api/src/main/java/cn/iocoder/mall/pay/api/message/AbstractPayNotifySuccessMessage.java @@ -0,0 +1,26 @@ +package cn.iocoder.mall.pay.api.message; +import lombok.Data; +import lombok.experimental.Accessors; + +@Data +@Accessors(chain = true) +public class AbstractPayNotifySuccessMessage { + + /** + * 任务编号 + */ + private Integer id; + /** + * 应用编号 + */ + private String appId; + /** + * 当前通知次数 + */ + private Integer notifyTimes; + /** + * 通知地址 + */ + private String notifyUrl; + +} diff --git a/pay/pay-service-api/src/main/java/cn/iocoder/mall/pay/api/message/PayRefundSuccessMessage.java b/pay/pay-service-api/src/main/java/cn/iocoder/mall/pay/api/message/PayRefundSuccessMessage.java index 200ef7a1..d1aaed2d 100644 --- a/pay/pay-service-api/src/main/java/cn/iocoder/mall/pay/api/message/PayRefundSuccessMessage.java +++ b/pay/pay-service-api/src/main/java/cn/iocoder/mall/pay/api/message/PayRefundSuccessMessage.java @@ -1,16 +1,17 @@ package cn.iocoder.mall.pay.api.message; +import lombok.Data; +import lombok.experimental.Accessors; + /** * 支付退款成功的消息对象 */ -public class PayRefundSuccessMessage { +@Data +@Accessors(chain = true) +public class PayRefundSuccessMessage extends AbstractPayNotifySuccessMessage { public static final String TOPIC = "PAY_REFUND_SUCCESS"; - /** - * 任务编号 - */ - private Integer id; /** * 退款单编号 */ @@ -19,75 +20,9 @@ public class PayRefundSuccessMessage { * 交易编号 */ private Integer transactionId; - /** - * 应用编号 - */ - private String appId; /** * 应用订单编号 */ private String orderId; - /** - * 当前通知次数 - */ - private Integer notifyTimes; - /** - * 通知地址 - */ - private String notifyUrl; - - public Integer getId() { - return id; - } - - public PayRefundSuccessMessage setId(Integer id) { - this.id = id; - return this; - } - - public String getAppId() { - return appId; - } - - public PayRefundSuccessMessage setAppId(String appId) { - this.appId = appId; - return this; - } - - public String getOrderId() { - return orderId; - } - - public PayRefundSuccessMessage setOrderId(String orderId) { - this.orderId = orderId; - return this; - } - - public Integer getNotifyTimes() { - return notifyTimes; - } - - public PayRefundSuccessMessage setNotifyTimes(Integer notifyTimes) { - this.notifyTimes = notifyTimes; - return this; - } - - public String getNotifyUrl() { - return notifyUrl; - } - - public PayRefundSuccessMessage setNotifyUrl(String notifyUrl) { - this.notifyUrl = notifyUrl; - return this; - } - - public Integer getTransactionId() { - return transactionId; - } - - public PayRefundSuccessMessage setTransactionId(Integer transactionId) { - this.transactionId = transactionId; - return this; - } } diff --git a/pay/pay-service-api/src/main/java/cn/iocoder/mall/pay/api/message/PayTransactionSuccessMessage.java b/pay/pay-service-api/src/main/java/cn/iocoder/mall/pay/api/message/PayTransactionSuccessMessage.java index 190bdfb6..7e396c88 100644 --- a/pay/pay-service-api/src/main/java/cn/iocoder/mall/pay/api/message/PayTransactionSuccessMessage.java +++ b/pay/pay-service-api/src/main/java/cn/iocoder/mall/pay/api/message/PayTransactionSuccessMessage.java @@ -1,89 +1,24 @@ package cn.iocoder.mall.pay.api.message; +import lombok.Data; +import lombok.experimental.Accessors; + /** * 支付交易单支付成功的消息对象 */ -public class PayTransactionSuccessMessage { +@Data +@Accessors(chain = true) +public class PayTransactionSuccessMessage extends AbstractPayNotifySuccessMessage { public static final String TOPIC = "PAY_TRANSACTION_SUCCESS"; - /** - * 任务编号 - */ - private Integer id; /** * 交易编号 */ private Integer transactionId; - /** - * 应用编号 - */ - private String appId; /** * 应用订单编号 */ private String orderId; - /** - * 当前通知次数 - */ - private Integer notifyTimes; - /** - * 通知地址 - */ - private String notifyUrl; - - public Integer getId() { - return id; - } - - public PayTransactionSuccessMessage setId(Integer id) { - this.id = id; - return this; - } - - public String getAppId() { - return appId; - } - - public PayTransactionSuccessMessage setAppId(String appId) { - this.appId = appId; - return this; - } - - public String getOrderId() { - return orderId; - } - - public PayTransactionSuccessMessage setOrderId(String orderId) { - this.orderId = orderId; - return this; - } - - public Integer getNotifyTimes() { - return notifyTimes; - } - - public PayTransactionSuccessMessage setNotifyTimes(Integer notifyTimes) { - this.notifyTimes = notifyTimes; - return this; - } - - public String getNotifyUrl() { - return notifyUrl; - } - - public PayTransactionSuccessMessage setNotifyUrl(String notifyUrl) { - this.notifyUrl = notifyUrl; - return this; - } - - public Integer getTransactionId() { - return transactionId; - } - - public PayTransactionSuccessMessage setTransactionId(Integer transactionId) { - this.transactionId = transactionId; - return this; - } } diff --git a/pay/pay-service-impl/src/main/java/cn/iocoder/mall/pay/biz/client/PingxxPaySDK.java b/pay/pay-service-impl/src/main/java/cn/iocoder/mall/pay/biz/client/PingxxPaySDK.java index 4636b403..6124b697 100644 --- a/pay/pay-service-impl/src/main/java/cn/iocoder/mall/pay/biz/client/PingxxPaySDK.java +++ b/pay/pay-service-impl/src/main/java/cn/iocoder/mall/pay/biz/client/PingxxPaySDK.java @@ -84,7 +84,7 @@ public class PingxxPaySDK extends AbstractPaySDK { JSONObject chargeObj = paramsObj.getJSONObject("data").getJSONObject("object"); String chargeId = chargeObj.getString("id"); // 请求ping++ - Map reqObj = createRefundRequest(chargeId, refund.getOrderDescription(), refund.getPrice()); + Map reqObj = createRefundRequest(refund, chargeId, refund.getOrderDescription(), refund.getPrice()); try { Refund pingxxRefund = Refund.create(chargeId, reqObj); System.out.println(pingxxRefund.toString()); @@ -97,16 +97,28 @@ public class PingxxPaySDK extends AbstractPaySDK { } } +// {"id":"evt_400190427005305341228202","created":1556297585,"livemode":false,"type":"refund.succeeded","data":{"object":{"id":"re_HO0m9GOGOi50KCmX104ufHe1","object":"refund","order_no":"HO0m9GOGOi50KCmX104ufHe1","amount":1,"created":1556297585,"succeed":true,"status":"succeeded","time_succeed":1556297585,"description":"测试下退款","failure_code":null,"failure_msg":null,"metadata":{},"charge":"ch_y1iXjLnDS4G4OO4uT4a5C4W1","charge_order_no":"20190427004410165545","transaction_no":"201904270053053608824","extra":{}}},"object":"event","request":"iar_Oa188KCiHC40iLibbHX5WrHC","pending_webhooks":0} @Override public CommonResult parseRefundSuccessParams(String params) { - return null; + JSONObject paramsObj = JSON.parseObject(params); + JSONObject chargeObj = paramsObj.getJSONObject("data").getJSONObject("object"); + RefundSuccessBO refundSuccessBO = new RefundSuccessBO() + .setRefundCode(chargeObj.getJSONObject("metadata").getString("refundCode")) + .setRefundTime(new Date(chargeObj.getLong("time_succeed") * 1000)) + .setTradeNo(chargeObj.getString("transaction_no")) + // TODO 芋艿,需要测试下,退款失败 + .setSuccess(chargeObj.containsValue("failure_code") || chargeObj.containsValue("failure_msg")); + return CommonResult.success(refundSuccessBO); } - private Map createRefundRequest(String chargeId, String orderDescription, Integer price) { + private Map createRefundRequest(PayRefundDO refund, String chargeId, String orderDescription, Integer price) { Map reqObj = new HashMap<>(); // reqObj.put("CHARGE_ID", chargeId); reqObj.put("description", orderDescription); reqObj.put("amount", price); + Map metadata = new HashMap<>(); + metadata.put("refundCode", refund.getRefundCode()); + reqObj.put("metadata", metadata); return reqObj; } diff --git a/pay/pay-service-impl/src/main/java/cn/iocoder/mall/pay/biz/component/DubboReferencePool.java b/pay/pay-service-impl/src/main/java/cn/iocoder/mall/pay/biz/component/DubboReferencePool.java index 02e6fcd4..b04ae34d 100644 --- a/pay/pay-service-impl/src/main/java/cn/iocoder/mall/pay/biz/component/DubboReferencePool.java +++ b/pay/pay-service-impl/src/main/java/cn/iocoder/mall/pay/biz/component/DubboReferencePool.java @@ -1,7 +1,73 @@ package cn.iocoder.mall.pay.biz.component; +import com.alibaba.dubbo.config.ApplicationConfig; +import com.alibaba.dubbo.config.ReferenceConfig; +import com.alibaba.dubbo.config.RegistryConfig; +import com.alibaba.dubbo.rpc.service.GenericService; +import com.google.common.cache.CacheBuilder; +import com.google.common.cache.CacheLoader; +import com.google.common.cache.LoadingCache; +import lombok.Data; +import org.springframework.beans.factory.annotation.Value; import org.springframework.stereotype.Component; +import org.springframework.util.Assert; @Component public class DubboReferencePool { + + @Data + public class ReferenceMeta { + + private final ReferenceConfig config; // TODO 芋艿,后续需要做销毁 + private final GenericService service; + private final String methodName; + + private ReferenceMeta(ReferenceConfig config, GenericService service, String methodName) { + this.config = config; + this.service = service; + this.methodName = methodName; + } + + } + + private LoadingCache referenceMetaCache = CacheBuilder.newBuilder() + .build(new CacheLoader() { + @Override + public ReferenceMeta load(String notifyUrl) { + return createGenericService(notifyUrl); + } + }); + + @Value("${dubbo.registry.address}") + private String dubboRegistryAddress; + @Value("${dubbo.application.name}") + private String dubboApplicationName; + + private ReferenceMeta createGenericService(String notifyUrl) { + String[] notifyUrlParts = notifyUrl.split("#"); + // 创建 ApplicationConfig 对象 + ApplicationConfig application = new ApplicationConfig(); + application.setName(dubboApplicationName); + // 创建 RegistryConfig 对象 + RegistryConfig registry = new RegistryConfig(); +// registry.setAddress("zookeeper://127.0.0.1:2181"); + registry.setAddress(dubboRegistryAddress); + application.setRegistry(registry); + // 创建 ReferenceConfig 对象 + ReferenceConfig reference = new ReferenceConfig<>(); + reference.setInterface(notifyUrlParts[0]); // 弱类型接口名 + reference.setGeneric(true); // 声明为泛化接口 + reference.setApplication(application); + // 获得 GenericService 对象 + GenericService genericService = reference.get(); + // 构建最终的 ReferenceMeta 对象 + return new ReferenceMeta(reference, genericService, notifyUrlParts[1]); + } + + public ReferenceMeta getReferenceMeta(String notifyUrl) { + DubboReferencePool.ReferenceMeta referenceMeta = referenceMetaCache.getUnchecked(notifyUrl); + Assert.notNull(referenceMeta, String.format("notifyUrl(%s) 不存在对应的 ReferenceMeta 对象", notifyUrl)); + return referenceMeta; + } + } diff --git a/pay/pay-service-impl/src/main/java/cn/iocoder/mall/pay/biz/convert/PayNotifyConvert.java b/pay/pay-service-impl/src/main/java/cn/iocoder/mall/pay/biz/convert/PayNotifyConvert.java new file mode 100644 index 00000000..473601d8 --- /dev/null +++ b/pay/pay-service-impl/src/main/java/cn/iocoder/mall/pay/biz/convert/PayNotifyConvert.java @@ -0,0 +1,29 @@ +package cn.iocoder.mall.pay.biz.convert; + +import cn.iocoder.mall.pay.api.message.PayRefundSuccessMessage; +import cn.iocoder.mall.pay.api.message.PayTransactionSuccessMessage; +import cn.iocoder.mall.pay.biz.dataobject.PayNotifyTaskDO; +import org.mapstruct.Mapper; +import org.mapstruct.Mapping; +import org.mapstruct.Mappings; +import org.mapstruct.factory.Mappers; + +@Mapper +public interface PayNotifyConvert { + + PayNotifyConvert INSTANCE = Mappers.getMapper(PayNotifyConvert.class); + + @Mappings({ + @Mapping(source = "transaction.transactionId", target = "transactionId"), + @Mapping(source = "transaction.orderId", target = "orderId"), + }) + PayTransactionSuccessMessage convertTransaction(PayNotifyTaskDO payTransactionNotifyTaskDO); + + @Mappings({ + @Mapping(source = "refund.transactionId", target = "transactionId"), + @Mapping(source = "refund.orderId", target = "orderId"), + @Mapping(source = "refund.refundId", target = "refundId"), + }) + PayRefundSuccessMessage convertRefund(PayNotifyTaskDO payTransactionNotifyTaskDO); + +} diff --git a/pay/pay-service-impl/src/main/java/cn/iocoder/mall/pay/biz/convert/PayRefundConvert.java b/pay/pay-service-impl/src/main/java/cn/iocoder/mall/pay/biz/convert/PayRefundConvert.java new file mode 100644 index 00000000..2e02d14b --- /dev/null +++ b/pay/pay-service-impl/src/main/java/cn/iocoder/mall/pay/biz/convert/PayRefundConvert.java @@ -0,0 +1,17 @@ +package cn.iocoder.mall.pay.biz.convert; + +import cn.iocoder.mall.pay.api.dto.PayRefundSubmitDTO; +import cn.iocoder.mall.pay.biz.dataobject.PayRefundDO; +import org.mapstruct.Mapper; +import org.mapstruct.Mappings; +import org.mapstruct.factory.Mappers; + +@Mapper +public interface PayRefundConvert { + + PayRefundConvert INSTANCE = Mappers.getMapper(PayRefundConvert.class); + + @Mappings({}) + PayRefundDO convert(PayRefundSubmitDTO payRefundSubmitDTO); + +} diff --git a/pay/pay-service-impl/src/main/java/cn/iocoder/mall/pay/biz/convert/PayTransactionConvert.java b/pay/pay-service-impl/src/main/java/cn/iocoder/mall/pay/biz/convert/PayTransactionConvert.java index 93c8c64c..d9c9c380 100644 --- a/pay/pay-service-impl/src/main/java/cn/iocoder/mall/pay/biz/convert/PayTransactionConvert.java +++ b/pay/pay-service-impl/src/main/java/cn/iocoder/mall/pay/biz/convert/PayTransactionConvert.java @@ -1,17 +1,11 @@ package cn.iocoder.mall.pay.biz.convert; import cn.iocoder.mall.pay.api.bo.PayTransactionBO; -import cn.iocoder.mall.pay.api.dto.PayRefundSubmitDTO; import cn.iocoder.mall.pay.api.dto.PayTransactionCreateDTO; import cn.iocoder.mall.pay.api.dto.PayTransactionSubmitDTO; -import cn.iocoder.mall.pay.api.message.PayRefundSuccessMessage; -import cn.iocoder.mall.pay.api.message.PayTransactionSuccessMessage; -import cn.iocoder.mall.pay.biz.dataobject.PayRefundDO; import cn.iocoder.mall.pay.biz.dataobject.PayTransactionDO; import cn.iocoder.mall.pay.biz.dataobject.PayTransactionExtensionDO; -import cn.iocoder.mall.pay.biz.dataobject.PayNotifyTaskDO; import org.mapstruct.Mapper; -import org.mapstruct.Mapping; import org.mapstruct.Mappings; import org.mapstruct.factory.Mappers; @@ -29,20 +23,4 @@ public interface PayTransactionConvert { @Mappings({}) PayTransactionExtensionDO convert(PayTransactionSubmitDTO payTransactionSubmitDTO); - @Mappings({ - @Mapping(source = "transaction.transactionId", target = "transactionId"), - @Mapping(source = "transaction.orderId", target = "orderId"), - }) - PayTransactionSuccessMessage convert(PayNotifyTaskDO payTransactionNotifyTaskDO); - - @Mappings({ - @Mapping(source = "refund.transactionId", target = "transactionId"), - @Mapping(source = "refund.orderId", target = "orderId"), - @Mapping(source = "refund.refundId", target = "refundId"), - }) - PayRefundSuccessMessage convert2(PayNotifyTaskDO payTransactionNotifyTaskDO); - - @Mappings({}) - PayRefundDO convert(PayRefundSubmitDTO payRefundSubmitDTO); - } diff --git a/pay/pay-service-impl/src/main/java/cn/iocoder/mall/pay/biz/dao/PayTransactionNotifyLogMapper.java b/pay/pay-service-impl/src/main/java/cn/iocoder/mall/pay/biz/dao/PayNotifyLogMapper.java similarity index 80% rename from pay/pay-service-impl/src/main/java/cn/iocoder/mall/pay/biz/dao/PayTransactionNotifyLogMapper.java rename to pay/pay-service-impl/src/main/java/cn/iocoder/mall/pay/biz/dao/PayNotifyLogMapper.java index cb9945a9..61fb4c8d 100644 --- a/pay/pay-service-impl/src/main/java/cn/iocoder/mall/pay/biz/dao/PayTransactionNotifyLogMapper.java +++ b/pay/pay-service-impl/src/main/java/cn/iocoder/mall/pay/biz/dao/PayNotifyLogMapper.java @@ -4,7 +4,7 @@ import cn.iocoder.mall.pay.biz.dataobject.PayNotifyLogDO; import org.springframework.stereotype.Repository; @Repository -public interface PayTransactionNotifyLogMapper { +public interface PayNotifyLogMapper { void insert(PayNotifyLogDO entity); diff --git a/pay/pay-service-impl/src/main/java/cn/iocoder/mall/pay/biz/dao/PayTransactionNotifyTaskMapper.java b/pay/pay-service-impl/src/main/java/cn/iocoder/mall/pay/biz/dao/PayNotifyTaskMapper.java similarity index 92% rename from pay/pay-service-impl/src/main/java/cn/iocoder/mall/pay/biz/dao/PayTransactionNotifyTaskMapper.java rename to pay/pay-service-impl/src/main/java/cn/iocoder/mall/pay/biz/dao/PayNotifyTaskMapper.java index cc6790b8..feb9a47e 100644 --- a/pay/pay-service-impl/src/main/java/cn/iocoder/mall/pay/biz/dao/PayTransactionNotifyTaskMapper.java +++ b/pay/pay-service-impl/src/main/java/cn/iocoder/mall/pay/biz/dao/PayNotifyTaskMapper.java @@ -6,7 +6,7 @@ import org.springframework.stereotype.Repository; import java.util.List; @Repository -public interface PayTransactionNotifyTaskMapper { +public interface PayNotifyTaskMapper { void insert(PayNotifyTaskDO entity); diff --git a/pay/pay-service-impl/src/main/java/cn/iocoder/mall/pay/biz/scheduler/PayTransactionNotifyJob.java b/pay/pay-service-impl/src/main/java/cn/iocoder/mall/pay/biz/job/PayNotifyJob.java similarity index 68% rename from pay/pay-service-impl/src/main/java/cn/iocoder/mall/pay/biz/scheduler/PayTransactionNotifyJob.java rename to pay/pay-service-impl/src/main/java/cn/iocoder/mall/pay/biz/job/PayNotifyJob.java index b2d26b31..f4ea7ad4 100644 --- a/pay/pay-service-impl/src/main/java/cn/iocoder/mall/pay/biz/scheduler/PayTransactionNotifyJob.java +++ b/pay/pay-service-impl/src/main/java/cn/iocoder/mall/pay/biz/job/PayNotifyJob.java @@ -1,9 +1,8 @@ -package cn.iocoder.mall.pay.biz.scheduler; +package cn.iocoder.mall.pay.biz.job; -import cn.iocoder.mall.pay.api.message.PayTransactionSuccessMessage; -import cn.iocoder.mall.pay.biz.convert.PayTransactionConvert; -import cn.iocoder.mall.pay.biz.dao.PayTransactionNotifyTaskMapper; +import cn.iocoder.mall.pay.biz.dao.PayNotifyTaskMapper; import cn.iocoder.mall.pay.biz.dataobject.PayNotifyTaskDO; +import cn.iocoder.mall.pay.biz.service.PayNotifyServiceImpl; import com.xxl.job.core.biz.model.ReturnT; import com.xxl.job.core.handler.IJobHandler; import com.xxl.job.core.handler.annotation.JobHandler; @@ -16,14 +15,17 @@ import java.util.Date; import java.util.List; /** - * 支付交易成功通知 Job + * 支付通知重试 Job */ @Component @JobHandler(value = "payTransactionNotifyJob") -public class PayTransactionNotifyJob extends IJobHandler { +public class PayNotifyJob extends IJobHandler { @Autowired - private PayTransactionNotifyTaskMapper payTransactionNotifyTaskMapper; + private PayNotifyTaskMapper payTransactionNotifyTaskMapper; + + @Autowired + private PayNotifyServiceImpl payNotifyService; @Resource private RocketMQTemplate rocketMQTemplate; @@ -33,16 +35,15 @@ public class PayTransactionNotifyJob extends IJobHandler { // 获得需要通知的任务 List notifyTasks = payTransactionNotifyTaskMapper.selectByNotify(); // 循环任务,发送通知 - for (PayNotifyTaskDO payTransactionNotifyTask : notifyTasks) { + for (PayNotifyTaskDO notifyTask : notifyTasks) { // 发送 MQ - rocketMQTemplate.convertAndSend(PayTransactionSuccessMessage.TOPIC, - PayTransactionConvert.INSTANCE.convert(payTransactionNotifyTask)); + payNotifyService.sendNotifyMessage(notifyTask); // 更新最后通知时间 // 1. 这样操作,虽然可能会出现 MQ 消费快于下面 PayTransactionNotifyTaskDO 的更新语句。但是,因为更新字段不同,所以不会有问题。 // 2. 换个视角,如果先更新 PayTransactionNotifyTaskDO ,再发送 MQ 消息。如果 MQ 消息发送失败,则 PayTransactionNotifyTaskDO 再也不会被轮询到了。 // 3. 当然,最最最完美的话,就是做事务消息,不过这样又过于复杂~ PayNotifyTaskDO updateNotifyTask = new PayNotifyTaskDO() - .setId(payTransactionNotifyTask.getId()).setLastExecuteTime(new Date()); + .setId(notifyTask.getId()).setLastExecuteTime(new Date()); payTransactionNotifyTaskMapper.update(updateNotifyTask); } return new ReturnT<>("执行通知数:" + notifyTasks.size()); diff --git a/pay/pay-service-impl/src/main/java/cn/iocoder/mall/pay/biz/mq/AbstractPayNotifySuccessConsumer.java b/pay/pay-service-impl/src/main/java/cn/iocoder/mall/pay/biz/mq/AbstractPayNotifySuccessConsumer.java new file mode 100644 index 00000000..4ff7343d --- /dev/null +++ b/pay/pay-service-impl/src/main/java/cn/iocoder/mall/pay/biz/mq/AbstractPayNotifySuccessConsumer.java @@ -0,0 +1,82 @@ +package cn.iocoder.mall.pay.biz.mq; + +import cn.iocoder.common.framework.util.DateUtil; +import cn.iocoder.common.framework.util.ExceptionUtil; +import cn.iocoder.mall.pay.api.constant.PayTransactionNotifyStatusEnum; +import cn.iocoder.mall.pay.api.message.AbstractPayNotifySuccessMessage; +import cn.iocoder.mall.pay.biz.component.DubboReferencePool; +import cn.iocoder.mall.pay.biz.dao.PayNotifyLogMapper; +import cn.iocoder.mall.pay.biz.dao.PayNotifyTaskMapper; +import cn.iocoder.mall.pay.biz.dataobject.PayNotifyLogDO; +import cn.iocoder.mall.pay.biz.dataobject.PayNotifyTaskDO; +import com.alibaba.fastjson.JSON; +import org.apache.rocketmq.spring.core.RocketMQListener; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.transaction.annotation.Transactional; + +import java.util.Calendar; +import java.util.Date; + +public abstract class AbstractPayNotifySuccessConsumer implements RocketMQListener { + + @Autowired + private DubboReferencePool dubboReferencePool; + + @Autowired + private PayNotifyTaskMapper payTransactionNotifyTaskMapper; + @Autowired + private PayNotifyLogMapper payTransactionNotifyLogMapper; + + @Override + @Transactional + public void onMessage(T message) { + // 获得 ReferenceMeta 对象 + DubboReferencePool.ReferenceMeta referenceMeta = dubboReferencePool.getReferenceMeta(message.getNotifyUrl()); + // 发起调用 + String response = null; // RPC / HTTP 调用的响应 + PayNotifyTaskDO updateTask = new PayNotifyTaskDO() // 更新 PayTransactionNotifyTaskDO 对象 + .setId(message.getId()) + .setLastExecuteTime(new Date()) + .setNotifyTimes(message.getNotifyTimes() + 1); + try { + response = invoke(message, referenceMeta); + if ("success".equals(response)) { // 情况一,请求成功且返回成功 + // 更新通知成功 + updateTask.setStatus(PayTransactionNotifyStatusEnum.SUCCESS.getValue()); + payTransactionNotifyTaskMapper.update(updateTask); + // 需要更新支付交易单通知应用成功 + afterInvokeSuccess(message); + } else { // 情况二,请求成功且返回失败 + // 更新通知请求成功,但是结果失败 + handleFailure(updateTask, PayTransactionNotifyStatusEnum.REQUEST_SUCCESS.getValue()); + payTransactionNotifyTaskMapper.update(updateTask); + } + } catch (Throwable e) { // 请求失败 + // 更新通知请求失败 + response = ExceptionUtil.getRootCauseMessage(e); + handleFailure(updateTask, PayTransactionNotifyStatusEnum.REQUEST_FAILURE.getValue()); + payTransactionNotifyTaskMapper.update(updateTask); + // 抛出异常,回滚事务 + throw e; // TODO 芋艿,此处不能抛出异常。因为,会导致 MQ + 定时任务多重试。此处的目标是,事务回滚 + 吃掉事务。另外,最后的 finally 的日志,要插入成功。 + } finally { + // 插入 PayTransactionNotifyLogDO 日志 + PayNotifyLogDO notifyLog = new PayNotifyLogDO().setNotifyId(message.getId()) + .setRequest(JSON.toJSONString(message)).setResponse(response).setStatus(updateTask.getStatus()); + payTransactionNotifyLogMapper.insert(notifyLog); + } + } + + private void handleFailure(PayNotifyTaskDO updateTask, Integer defaultStatus) { + if (updateTask.getNotifyTimes() >= PayNotifyTaskDO.NOTIFY_FREQUENCY.length) { + updateTask.setStatus(PayTransactionNotifyStatusEnum.FAILURE.getValue()); + } else { + updateTask.setNextNotifyTime(DateUtil.addDate(Calendar.SECOND, PayNotifyTaskDO.NOTIFY_FREQUENCY[updateTask.getNotifyTimes()])); + updateTask.setStatus(defaultStatus); + } + } + + protected abstract String invoke(T message, DubboReferencePool.ReferenceMeta referenceMeta); + + protected abstract void afterInvokeSuccess(T message); + +} diff --git a/pay/pay-service-impl/src/main/java/cn/iocoder/mall/pay/biz/mq/PayRefundSuccessConsumer.java b/pay/pay-service-impl/src/main/java/cn/iocoder/mall/pay/biz/mq/PayRefundSuccessConsumer.java new file mode 100644 index 00000000..bd1816f0 --- /dev/null +++ b/pay/pay-service-impl/src/main/java/cn/iocoder/mall/pay/biz/mq/PayRefundSuccessConsumer.java @@ -0,0 +1,45 @@ +package cn.iocoder.mall.pay.biz.mq; + +import cn.iocoder.mall.pay.api.message.PayRefundSuccessMessage; +import cn.iocoder.mall.pay.biz.component.DubboReferencePool; +import cn.iocoder.mall.pay.biz.dao.PayRefundMapper; +import cn.iocoder.mall.pay.biz.dataobject.PayRefundDO; +import com.alibaba.dubbo.rpc.service.GenericService; +import org.apache.rocketmq.spring.annotation.RocketMQMessageListener; +import org.apache.rocketmq.spring.core.RocketMQListener; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; +import org.springframework.util.Assert; + +import java.util.Date; + +@Service +@RocketMQMessageListener( + topic = PayRefundSuccessMessage.TOPIC, + consumerGroup = "pay-consumer-group-" + PayRefundSuccessMessage.TOPIC +) +public class PayRefundSuccessConsumer extends AbstractPayNotifySuccessConsumer + implements RocketMQListener { + + @Autowired + private PayRefundMapper payRefundMapper; + + @Override + protected String invoke(PayRefundSuccessMessage message, DubboReferencePool.ReferenceMeta referenceMeta) { + // 查询支付交易 + PayRefundDO refund = payRefundMapper.selectById(message.getRefundId()); + Assert.notNull(refund, String.format("回调消息(%s) 退款单不能为空", message.toString())); + // 执行调用 + GenericService genericService = referenceMeta.getService(); + String methodName = referenceMeta.getMethodName(); + return (String) genericService.$invoke(methodName, new String[]{String.class.getName(), Integer.class.getName()}, + new Object[]{message.getOrderId(), refund.getPrice()}); + } + + @Override + protected void afterInvokeSuccess(PayRefundSuccessMessage message) { + PayRefundDO updateRefund = new PayRefundDO().setId(message.getRefundId()).setFinishTime(new Date()); + payRefundMapper.update(updateRefund, null); + } + +} diff --git a/pay/pay-service-impl/src/main/java/cn/iocoder/mall/pay/biz/mq/PayTransactionSuccessConsumer.java b/pay/pay-service-impl/src/main/java/cn/iocoder/mall/pay/biz/mq/PayTransactionSuccessConsumer.java index fc255952..dc2249db 100644 --- a/pay/pay-service-impl/src/main/java/cn/iocoder/mall/pay/biz/mq/PayTransactionSuccessConsumer.java +++ b/pay/pay-service-impl/src/main/java/cn/iocoder/mall/pay/biz/mq/PayTransactionSuccessConsumer.java @@ -1,32 +1,16 @@ package cn.iocoder.mall.pay.biz.mq; -import cn.iocoder.common.framework.util.DateUtil; -import cn.iocoder.common.framework.util.ExceptionUtil; -import cn.iocoder.mall.pay.api.constant.PayTransactionNotifyStatusEnum; import cn.iocoder.mall.pay.api.message.PayTransactionSuccessMessage; +import cn.iocoder.mall.pay.biz.component.DubboReferencePool; import cn.iocoder.mall.pay.biz.dao.PayTransactionMapper; -import cn.iocoder.mall.pay.biz.dao.PayTransactionNotifyLogMapper; -import cn.iocoder.mall.pay.biz.dao.PayTransactionNotifyTaskMapper; -import cn.iocoder.mall.pay.biz.dataobject.PayNotifyTaskDO; import cn.iocoder.mall.pay.biz.dataobject.PayTransactionDO; -import cn.iocoder.mall.pay.biz.dataobject.PayNotifyLogDO; -import com.alibaba.dubbo.config.ApplicationConfig; -import com.alibaba.dubbo.config.ReferenceConfig; -import com.alibaba.dubbo.config.RegistryConfig; import com.alibaba.dubbo.rpc.service.GenericService; -import com.google.common.cache.CacheBuilder; -import com.google.common.cache.CacheLoader; -import com.google.common.cache.LoadingCache; -import lombok.Data; import org.apache.rocketmq.spring.annotation.RocketMQMessageListener; import org.apache.rocketmq.spring.core.RocketMQListener; import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.beans.factory.annotation.Value; import org.springframework.stereotype.Service; -import org.springframework.transaction.annotation.Transactional; import org.springframework.util.Assert; -import java.util.Calendar; import java.util.Date; @Service @@ -34,119 +18,28 @@ import java.util.Date; topic = PayTransactionSuccessMessage.TOPIC, consumerGroup = "pay-consumer-group-" + PayTransactionSuccessMessage.TOPIC ) -public class PayTransactionSuccessConsumer implements RocketMQListener { +public class PayTransactionSuccessConsumer extends AbstractPayNotifySuccessConsumer + implements RocketMQListener { - @Data - private class ReferenceMeta { - - private final ReferenceConfig config; // TODO 芋艿,后续需要做销毁 - private final GenericService service; - private final String methodName; - - private ReferenceMeta(ReferenceConfig config, GenericService service, String methodName) { - this.config = config; - this.service = service; - this.methodName = methodName; - } - - } - - @Value("${dubbo.registry.address}") - private String dubboRegistryAddress; - @Value("${dubbo.application.name}") - private String dubboApplicationName; - - @Autowired - private PayTransactionNotifyTaskMapper payTransactionNotifyTaskMapper; - @Autowired - private PayTransactionNotifyLogMapper payTransactionNotifyLogMapper; @Autowired private PayTransactionMapper payTransactionMapper; - private LoadingCache referenceMetaCache = CacheBuilder.newBuilder() - .build(new CacheLoader() { - @Override - public ReferenceMeta load(String notifyUrl) { - return createGenericService(notifyUrl); - } - }); - - private ReferenceMeta createGenericService(String notifyUrl) { - String[] notifyUrlParts = notifyUrl.split("#"); - // 创建 ApplicationConfig 对象 - ApplicationConfig application = new ApplicationConfig(); - application.setName(dubboApplicationName); - // 创建 RegistryConfig 对象 - RegistryConfig registry = new RegistryConfig(); -// registry.setAddress("zookeeper://127.0.0.1:2181"); - registry.setAddress(dubboRegistryAddress); - application.setRegistry(registry); - // 创建 ReferenceConfig 对象 - ReferenceConfig reference = new ReferenceConfig<>(); - reference.setInterface(notifyUrlParts[0]); // 弱类型接口名 - reference.setGeneric(true); // 声明为泛化接口 - reference.setApplication(application); - // 获得 GenericService 对象 - GenericService genericService = reference.get(); - // 构建最终的 ReferenceMeta 对象 - return new ReferenceMeta(reference, genericService, notifyUrlParts[1]); - } - @Override - @Transactional - public void onMessage(PayTransactionSuccessMessage message) { - // 获得 ReferenceMeta 对象 - ReferenceMeta referenceMeta = referenceMetaCache.getUnchecked(message.getNotifyUrl()); - Assert.notNull(referenceMeta, String.format("notifyUrl(%s) 不存在对应的 ReferenceMeta 对象", message.getNotifyUrl())); - GenericService genericService = referenceMeta.getService(); - String methodName = referenceMeta.getMethodName(); + protected String invoke(PayTransactionSuccessMessage message, DubboReferencePool.ReferenceMeta referenceMeta) { // 查询支付交易 PayTransactionDO transaction = payTransactionMapper.selectById(message.getTransactionId()); Assert.notNull(transaction, String.format("回调消息(%s) 订单交易不能为空", message.toString())); - // 发起调用 - String response = null; // RPC / HTTP 调用的响应 - PayNotifyTaskDO updateTask = new PayNotifyTaskDO() // 更新 PayTransactionNotifyTaskDO 对象 - .setId(message.getId()) - .setLastExecuteTime(new Date()) - .setNotifyTimes(message.getNotifyTimes() + 1); - try { - response = (String) genericService.$invoke(methodName, new String[]{String.class.getName(), Integer.class.getName()}, - new Object[]{message.getOrderId(), transaction.getPrice()}); - if ("success".equals(response)) { // 情况一,请求成功且返回成功 - // 更新通知成功 - updateTask.setStatus(PayTransactionNotifyStatusEnum.SUCCESS.getValue()); - payTransactionNotifyTaskMapper.update(updateTask); - // 需要更新支付交易单通知应用成功 - PayTransactionDO updateTransaction = new PayTransactionDO().setId(message.getTransactionId()) - .setFinishTime(new Date()); - payTransactionMapper.update(updateTransaction, null); - } else { // 情况二,请求成功且返回失败 - // 更新通知请求成功,但是结果失败 - handleFailure(updateTask, PayTransactionNotifyStatusEnum.REQUEST_SUCCESS.getValue()); - payTransactionNotifyTaskMapper.update(updateTask); - } - } catch (Throwable e) { // 请求失败 - // 更新通知请求失败 - response = ExceptionUtil.getRootCauseMessage(e); - handleFailure(updateTask, PayTransactionNotifyStatusEnum.REQUEST_FAILURE.getValue()); - payTransactionNotifyTaskMapper.update(updateTask); - // 抛出异常,回滚事务 - throw e; // TODO 芋艿,此处不能抛出异常。因为,会导致 MQ + 定时任务多重试。此处的目标是,事务回滚 + 吃掉事务。另外,最后的 finally 的日志,要插入成功。 - } finally { - // 插入 PayTransactionNotifyLogDO 日志 - PayNotifyLogDO notifyLog = new PayNotifyLogDO().setNotifyId(message.getId()) - .setRequest(message.getOrderId()).setResponse(response).setStatus(updateTask.getStatus()); - payTransactionNotifyLogMapper.insert(notifyLog); - } + // 执行调用 + GenericService genericService = referenceMeta.getService(); + String methodName = referenceMeta.getMethodName(); + return (String) genericService.$invoke(methodName, new String[]{String.class.getName(), Integer.class.getName()}, + new Object[]{message.getOrderId(), transaction.getPrice()}); } - private void handleFailure(PayNotifyTaskDO updateTask, Integer defaultStatus) { - if (updateTask.getNotifyTimes() >= PayNotifyTaskDO.NOTIFY_FREQUENCY.length) { - updateTask.setStatus(PayTransactionNotifyStatusEnum.FAILURE.getValue()); - } else { - updateTask.setNextNotifyTime(DateUtil.addDate(Calendar.SECOND, PayNotifyTaskDO.NOTIFY_FREQUENCY[updateTask.getNotifyTimes()])); - updateTask.setStatus(defaultStatus); - } + @Override + protected void afterInvokeSuccess(PayTransactionSuccessMessage message) { + PayTransactionDO updateTransaction = new PayTransactionDO().setId(message.getTransactionId()).setFinishTime(new Date()); + payTransactionMapper.update(updateTransaction, null); } } diff --git a/pay/pay-service-impl/src/main/java/cn/iocoder/mall/pay/biz/service/PayNotifyServiceImpl.java b/pay/pay-service-impl/src/main/java/cn/iocoder/mall/pay/biz/service/PayNotifyServiceImpl.java index e38a2169..5e36ff69 100644 --- a/pay/pay-service-impl/src/main/java/cn/iocoder/mall/pay/biz/service/PayNotifyServiceImpl.java +++ b/pay/pay-service-impl/src/main/java/cn/iocoder/mall/pay/biz/service/PayNotifyServiceImpl.java @@ -3,9 +3,10 @@ package cn.iocoder.mall.pay.biz.service; import cn.iocoder.common.framework.util.DateUtil; import cn.iocoder.mall.pay.api.constant.PayNotifyType; import cn.iocoder.mall.pay.api.constant.PayTransactionNotifyStatusEnum; +import cn.iocoder.mall.pay.api.message.PayRefundSuccessMessage; import cn.iocoder.mall.pay.api.message.PayTransactionSuccessMessage; -import cn.iocoder.mall.pay.biz.convert.PayTransactionConvert; -import cn.iocoder.mall.pay.biz.dao.PayTransactionNotifyTaskMapper; +import cn.iocoder.mall.pay.biz.convert.PayNotifyConvert; +import cn.iocoder.mall.pay.biz.dao.PayNotifyTaskMapper; import cn.iocoder.mall.pay.biz.dataobject.PayNotifyTaskDO; import cn.iocoder.mall.pay.biz.dataobject.PayRefundDO; import cn.iocoder.mall.pay.biz.dataobject.PayTransactionDO; @@ -21,7 +22,7 @@ import java.util.Calendar; public class PayNotifyServiceImpl { @Autowired - private PayTransactionNotifyTaskMapper payTransactionNotifyTaskMapper; + private PayNotifyTaskMapper payTransactionNotifyTaskMapper; @Resource private RocketMQTemplate rocketMQTemplate; @@ -35,8 +36,7 @@ public class PayNotifyServiceImpl { // 保存到数据库 payTransactionNotifyTaskMapper.insert(payTransactionNotifyTask); // 发送 MQ 消息 - rocketMQTemplate.convertAndSend(PayTransactionSuccessMessage.TOPIC, - PayTransactionConvert.INSTANCE.convert(payTransactionNotifyTask)); + sendNotifyMessage(payTransactionNotifyTask); } public void addTransactionNotifyTask(PayTransactionDO transaction, PayTransactionExtensionDO extension) { @@ -47,8 +47,7 @@ public class PayNotifyServiceImpl { .setTransactionId(extension.getTransactionId()).setTransactionExtensionId(extension.getId())); payTransactionNotifyTaskMapper.insert(payTransactionNotifyTask); // 3.2 发送 MQ - rocketMQTemplate.convertAndSend(PayTransactionSuccessMessage.TOPIC, - PayTransactionConvert.INSTANCE.convert(payTransactionNotifyTask)); + sendNotifyMessage(payTransactionNotifyTask); } private PayNotifyTaskDO createBasePayNotifyTaskDO(String appId, String notifyUrl) { @@ -60,4 +59,16 @@ public class PayNotifyServiceImpl { .setNotifyUrl(notifyUrl); } + public void sendNotifyMessage(PayNotifyTaskDO notifyTask) { + if (PayNotifyType.TRANSACTION.getValue().equals(notifyTask.getType())) { + rocketMQTemplate.convertAndSend(PayTransactionSuccessMessage.TOPIC, + PayNotifyConvert.INSTANCE.convertTransaction(notifyTask)); + } else if (PayNotifyType.REFUND.getValue().equals(notifyTask.getType())) { + rocketMQTemplate.convertAndSend(PayRefundSuccessMessage.TOPIC, + PayNotifyConvert.INSTANCE.convertRefund(notifyTask)); + } else { + throw new IllegalArgumentException(String.format("通知任务(%s) 无法发送通知消息", notifyTask.toString())); + } + } + } diff --git a/pay/pay-service-impl/src/main/java/cn/iocoder/mall/pay/biz/service/PayRefundServiceImpl.java b/pay/pay-service-impl/src/main/java/cn/iocoder/mall/pay/biz/service/PayRefundServiceImpl.java index 15d6ab2d..3f7cd0c5 100644 --- a/pay/pay-service-impl/src/main/java/cn/iocoder/mall/pay/biz/service/PayRefundServiceImpl.java +++ b/pay/pay-service-impl/src/main/java/cn/iocoder/mall/pay/biz/service/PayRefundServiceImpl.java @@ -6,14 +6,19 @@ 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.PayRefundSubmitBO; -import cn.iocoder.mall.pay.api.constant.*; +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.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; -import cn.iocoder.mall.pay.biz.convert.PayTransactionConvert; +import cn.iocoder.mall.pay.biz.convert.PayRefundConvert; import cn.iocoder.mall.pay.biz.dao.PayRefundMapper; -import cn.iocoder.mall.pay.biz.dataobject.*; +import cn.iocoder.mall.pay.biz.dataobject.PayAppDO; +import cn.iocoder.mall.pay.biz.dataobject.PayRefundDO; +import cn.iocoder.mall.pay.biz.dataobject.PayTransactionDO; +import cn.iocoder.mall.pay.biz.dataobject.PayTransactionExtensionDO; import org.apache.rocketmq.spring.core.RocketMQTemplate; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -71,7 +76,7 @@ public class PayRefundServiceImpl implements PayRefundService { return ServiceExceptionUtil.error(PayErrorCodeEnum.PAY_TRANSACTION_EXTENSION_STATUS_IS_NOT_SUCCESS.getCode()); } // 插入 PayTransactionExtensionDO - PayRefundDO payRefundDO = PayTransactionConvert.INSTANCE.convert(payRefundSubmitDTO) + PayRefundDO payRefundDO = PayRefundConvert.INSTANCE.convert(payRefundSubmitDTO) .setTransactionId(payTransaction.getId()) .setRefundCode(generateTransactionCode()) // TODO 芋艿,后续调整 .setStatus(PayRefundStatus.WAITING.getValue()) @@ -120,7 +125,6 @@ public class PayRefundServiceImpl implements PayRefundService { if (updateCounts == 0) { // 校验状态,必须是待支付 throw ServiceExceptionUtil.exception(PayErrorCodeEnum.PAY_REFUND_STATUS_NOT_WAITING.getCode()); } - logger.info("[updateRefundSuccess][PayRefundDO({}) 更新为({})]", payRefund.getId(), status); // 2.1 判断 PayTransactionDO ,增加已退款金额 PayTransactionDO payTransaction = payTransactionService.getTransaction(payRefund.getTransactionId()); if (payTransaction == null) { @@ -137,7 +141,6 @@ public class PayRefundServiceImpl implements PayRefundService { if (updateCounts == 0) { // 保证不超退 TODO 这种类型,需要思考下。需要返回错误,但是又要保证事务回滚 throw ServiceExceptionUtil.exception(PayErrorCodeEnum.PAY_REFUND_PRICE_EXCEED.getCode()); } - logger.info("[updateRefundSuccess][PayTransactionDO({}) 更新为已支付]", payTransaction.getId()); // 3 新增 PayNotifyTaskDO payNotifyService.addRefundNotifyTask(payRefund); // 返回结果 diff --git a/pay/pay-service-impl/src/main/java/cn/iocoder/mall/pay/biz/service/PayTransactionServiceImpl.java b/pay/pay-service-impl/src/main/java/cn/iocoder/mall/pay/biz/service/PayTransactionServiceImpl.java index 6e157048..52837735 100644 --- a/pay/pay-service-impl/src/main/java/cn/iocoder/mall/pay/biz/service/PayTransactionServiceImpl.java +++ b/pay/pay-service-impl/src/main/java/cn/iocoder/mall/pay/biz/service/PayTransactionServiceImpl.java @@ -17,7 +17,7 @@ import cn.iocoder.mall.pay.biz.client.TransactionSuccessBO; import cn.iocoder.mall.pay.biz.convert.PayTransactionConvert; import cn.iocoder.mall.pay.biz.dao.PayTransactionExtensionMapper; import cn.iocoder.mall.pay.biz.dao.PayTransactionMapper; -import cn.iocoder.mall.pay.biz.dao.PayTransactionNotifyTaskMapper; +import cn.iocoder.mall.pay.biz.dao.PayNotifyTaskMapper; import cn.iocoder.mall.pay.biz.dataobject.PayAppDO; import cn.iocoder.mall.pay.biz.dataobject.PayTransactionDO; import cn.iocoder.mall.pay.biz.dataobject.PayTransactionExtensionDO; @@ -40,7 +40,7 @@ public class PayTransactionServiceImpl implements PayTransactionService { @Autowired private PayTransactionExtensionMapper payTransactionExtensionMapper; @Autowired - private PayTransactionNotifyTaskMapper payTransactionNotifyTaskMapper; + private PayNotifyTaskMapper payTransactionNotifyTaskMapper; @Autowired private PayAppServiceImpl payAppService; diff --git a/pay/pay-service-impl/src/main/resources/mapper/PayTransactionNotifyLogMapper.xml b/pay/pay-service-impl/src/main/resources/mapper/PayNotifyLogMapper.xml similarity index 93% rename from pay/pay-service-impl/src/main/resources/mapper/PayTransactionNotifyLogMapper.xml rename to pay/pay-service-impl/src/main/resources/mapper/PayNotifyLogMapper.xml index b1794e84..bb060062 100644 --- a/pay/pay-service-impl/src/main/resources/mapper/PayTransactionNotifyLogMapper.xml +++ b/pay/pay-service-impl/src/main/resources/mapper/PayNotifyLogMapper.xml @@ -1,6 +1,6 @@ - + @@ -9,7 +9,7 @@ - INSERT INTO transaction_notify_log ( + INSERT INTO notify_log ( notify_id, request, response, status ) VALUES ( #{notifyId}, #{request}, #{response}, #{status} diff --git a/pay/pay-service-impl/src/main/resources/mapper/PayTransactionNotifyTaskMapper.xml b/pay/pay-service-impl/src/main/resources/mapper/PayNotifyTaskMapper.xml similarity index 55% rename from pay/pay-service-impl/src/main/resources/mapper/PayTransactionNotifyTaskMapper.xml rename to pay/pay-service-impl/src/main/resources/mapper/PayNotifyTaskMapper.xml index 38c2209c..89e5b428 100644 --- a/pay/pay-service-impl/src/main/resources/mapper/PayTransactionNotifyTaskMapper.xml +++ b/pay/pay-service-impl/src/main/resources/mapper/PayNotifyTaskMapper.xml @@ -1,25 +1,37 @@ - + - id, transaction_id, transaction_extension_id, app_id, order_id, + id, app_id, type, status, next_notify_time, last_execute_time, notify_times, max_notify_times, create_time + + + + + - INSERT INTO transaction_notify_task ( - transaction_id, transaction_extension_id, app_id, order_id, - status, next_notify_time, notify_times, max_notify_times + INSERT INTO notify_task ( + app_id, type, + status, next_notify_time, notify_times, max_notify_times, + `transaction`, refund ) VALUES ( - #{transactionId}, #{transactionExtensionId}, #{appId}, #{orderId}, - #{status}, #{nextNotifyTime}, #{notifyTimes}, #{maxNotifyTimes} + #{appId}, #{type}, + #{status}, #{nextNotifyTime}, #{notifyTimes}, #{maxNotifyTimes}, + #{transaction, typeHandler=cn.iocoder.common.framework.mybatis.JSONTypeHandler}, + #{refund, typeHandler=cn.iocoder.common.framework.mybatis.JSONTypeHandler} ) - UPDATE transaction_notify_task + UPDATE notify_task , status = #{status} @@ -37,10 +49,10 @@ WHERE id = #{id} - SELECT - FROM transaction_notify_task + FROM notify_task WHERE status IN (1, 4, 5) AND next_notify_time NOW() AND last_execute_time > next_notify_time diff --git a/pay/pay-service-impl/src/main/resources/mapper/PayRefundMapper.xml b/pay/pay-service-impl/src/main/resources/mapper/PayRefundMapper.xml index 3f37ae97..b66ee605 100644 --- a/pay/pay-service-impl/src/main/resources/mapper/PayRefundMapper.xml +++ b/pay/pay-service-impl/src/main/resources/mapper/PayRefundMapper.xml @@ -3,7 +3,7 @@ - id, transaction_id, refund_cod, app_id, create_ip, order_id, + id, transaction_id, refund_code, app_id, create_ip, order_id, order_description, price, status, finish_time, notify_url, extension_data, refund_channel, refund_time, notify_time, trade_no, create_time diff --git a/pay/pay-service-impl/src/main/resources/mapper/PayTransactionMapper.xml b/pay/pay-service-impl/src/main/resources/mapper/PayTransactionMapper.xml index 3a66e061..e36d5d41 100644 --- a/pay/pay-service-impl/src/main/resources/mapper/PayTransactionMapper.xml +++ b/pay/pay-service-impl/src/main/resources/mapper/PayTransactionMapper.xml @@ -56,8 +56,8 @@ UPDATE `transaction` - SET refundTotal = refundTotal + ${refundTotalIncr} - WHERE price >= refundTotal + ${refundTotalIncr} + SET refund_total = refund_total + ${refundTotalIncr} + WHERE price >= refund_total + ${refundTotalIncr}