diff --git a/order/order-service-api/src/main/java/cn/iocoder/mall/order/api/OrderService.java b/order/order-service-api/src/main/java/cn/iocoder/mall/order/api/OrderService.java index 29b4b16ae..45c95cd81 100644 --- a/order/order-service-api/src/main/java/cn/iocoder/mall/order/api/OrderService.java +++ b/order/order-service-api/src/main/java/cn/iocoder/mall/order/api/OrderService.java @@ -138,8 +138,21 @@ public interface OrderService { * * mq 更新 payStatus */ + @Deprecated CommonResult listenerPayment(); + /** + * 更新订单支付成功 + * + * 如果成功,则返回 success + * 如果失败,则返回具体原因 + * + * @param orderId 订单编号 + * @param payAmount 支付的订单金额 + * @return 支付结果 + */ + String updatePaySuccess(String orderId, Integer payAmount); + /** * 监听确认收货 * diff --git a/order/order-service-api/src/main/java/cn/iocoder/mall/order/api/constant/OrderErrorCodeEnum.java b/order/order-service-api/src/main/java/cn/iocoder/mall/order/api/constant/OrderErrorCodeEnum.java index 22caa4866..0cca59617 100644 --- a/order/order-service-api/src/main/java/cn/iocoder/mall/order/api/constant/OrderErrorCodeEnum.java +++ b/order/order-service-api/src/main/java/cn/iocoder/mall/order/api/constant/OrderErrorCodeEnum.java @@ -25,6 +25,8 @@ public enum OrderErrorCodeEnum { ORDER_NOT_USER_ORDER(1008000011, "不是该用户的订单!"), ORDER_UNABLE_CONFIRM_ORDER(1008000012, "状态不对不能确认订单!"), ORDER_CREATE_CART_IS_EMPTY(1008000013, "购物车无选中的商品,无法创建订单"), + ORDER_STATUS_NOT_WAITING_PAYMENT(1008000014, "订单不处于等待支付状态"), + ORDER_PAY_AMOUNT_ERROR(1008000015, "订单金额不正确"), // order item ORDER_ITEM_ONLY_ONE(1008000200, "订单Item只有一个!"), diff --git a/order/order-service-impl/src/main/java/cn/iocoder/mall/order/biz/dao/OrderMapper.java b/order/order-service-impl/src/main/java/cn/iocoder/mall/order/biz/dao/OrderMapper.java index 0488614c7..e45488336 100644 --- a/order/order-service-impl/src/main/java/cn/iocoder/mall/order/biz/dao/OrderMapper.java +++ b/order/order-service-impl/src/main/java/cn/iocoder/mall/order/biz/dao/OrderMapper.java @@ -31,6 +31,10 @@ public interface OrderMapper { */ int updateById(OrderDO orderDO); + int updateByIdAndStatus(@Param("id") Integer id, + @Param("status") Integer status, + @Param("updateObj") OrderDO updateObj); + /** * 查询 - 根据id 查询 * 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 b167032aa..22dd66733 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 @@ -598,6 +598,29 @@ public class OrderServiceImpl implements OrderService { return null; } + @Override + public String updatePaySuccess(String orderId, Integer payAmount) { + OrderDO order = orderMapper.selectById(Integer.valueOf(orderId)); + if (order == null) { // 订单不存在 + return ServiceExceptionUtil.error(OrderErrorCodeEnum.ORDER_NOT_EXISTENT.getCode()).getMessage(); + } + if (!order.getStatus().equals(OrderStatusEnum.WAITING_PAYMENT.getValue())) { // 状态不处于等待支付 + return ServiceExceptionUtil.error(OrderErrorCodeEnum.ORDER_STATUS_NOT_WAITING_PAYMENT.getCode()).getMessage(); + } + if (!order.getPresentPrice().equals(payAmount)) { // 支付金额不正确 + return ServiceExceptionUtil.error(OrderErrorCodeEnum.ORDER_PAY_AMOUNT_ERROR.getCode()).getMessage(); + } + OrderDO updateOrderObj = new OrderDO() + .setStatus(OrderStatusEnum.ALREADY_SHIPMENT.getValue()) + .setPayAmount(payAmount) + .setPaymentTime(new Date()); + int updateCount = orderMapper.updateByIdAndStatus(order.getId(), order.getStatus(), updateOrderObj); + if (updateCount <= 0) { + return ServiceExceptionUtil.error(OrderErrorCodeEnum.ORDER_STATUS_NOT_WAITING_PAYMENT.getCode()).getMessage(); + } + return "success"; + } + @Override public CommonResult listenerConfirmGoods() { return null; diff --git a/order/order-service-impl/src/main/resources/mapper/OrderMapper.xml b/order/order-service-impl/src/main/resources/mapper/OrderMapper.xml index 5901f507a..87829dad8 100644 --- a/order/order-service-impl/src/main/resources/mapper/OrderMapper.xml +++ b/order/order-service-impl/src/main/resources/mapper/OrderMapper.xml @@ -34,22 +34,30 @@ , order_no = #{orderNo} - - - - - - - - - - - - , payment_time = #{paymentTime} + + , buy_price = #{buyPrice} + + + , discount_price = #{discountPrice} + + + , logistics_price = #{logisticsPrice} + + + , logistics_price = #{logisticsPrice} + + + , present_price = #{presentPrice} + + + , pay_amount = #{payAmount} , delivery_time = #{deliveryTime} + + , payment_time = #{paymentTime} + , receiver_time = #{receiverTime} @@ -87,6 +95,23 @@ WHERE id = #{id} + + UPDATE `order` + + + , pay_amount = #{updateObj.payAmount} + + + , payment_time = #{updateObj.paymentTime} + + + , status = #{updateObj.status} + + + WHERE id = #{id} + AND status = #{status} + + diff --git a/pay/pay-application/src/test/java/DubboGenericInvokerTest.java b/pay/pay-application/src/test/java/DubboGenericInvokerTest.java index b46a5f4d0..082193a0a 100644 --- a/pay/pay-application/src/test/java/DubboGenericInvokerTest.java +++ b/pay/pay-application/src/test/java/DubboGenericInvokerTest.java @@ -16,7 +16,7 @@ public class DubboGenericInvokerTest { ReferenceConfig reference = new ReferenceConfig<>(); // 弱类型接口名 - reference.setInterface("cn.iocoder.mall.pay.api.PayDemoService"); + reference.setInterface("cn.iocoder.mall.order.api.OrderService"); // 声明为泛化接口 reference.setGeneric(true); @@ -29,4 +29,4 @@ public class DubboGenericInvokerTest { System.out.println(name); } -} \ No newline at end of file +} diff --git a/pay/pay-service-impl/src/main/java/cn/iocoder/mall/pay/biz/dao/PayTransactionMapper.java b/pay/pay-service-impl/src/main/java/cn/iocoder/mall/pay/biz/dao/PayTransactionMapper.java index 0aa61f8d9..515202513 100644 --- a/pay/pay-service-impl/src/main/java/cn/iocoder/mall/pay/biz/dao/PayTransactionMapper.java +++ b/pay/pay-service-impl/src/main/java/cn/iocoder/mall/pay/biz/dao/PayTransactionMapper.java @@ -15,6 +15,6 @@ public interface PayTransactionMapper { PayTransactionDO selectByAppIdAndOrderId(@Param("appId") String appId, @Param("orderId") String orderId); - PayTransactionDO selectById(@Param("id") Integer appId); + PayTransactionDO selectById(@Param("id") Integer id); -} \ No newline at end of file +} diff --git a/pay/pay-service-impl/src/main/java/cn/iocoder/mall/pay/biz/mq/PayTransactionPaySuccessConsumer.java b/pay/pay-service-impl/src/main/java/cn/iocoder/mall/pay/biz/mq/PayTransactionPaySuccessConsumer.java index 6b572e39d..aad591b64 100644 --- a/pay/pay-service-impl/src/main/java/cn/iocoder/mall/pay/biz/mq/PayTransactionPaySuccessConsumer.java +++ b/pay/pay-service-impl/src/main/java/cn/iocoder/mall/pay/biz/mq/PayTransactionPaySuccessConsumer.java @@ -14,11 +14,17 @@ 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; @@ -30,6 +36,26 @@ import java.util.Date; ) public class PayTransactionPaySuccessConsumer 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 @@ -37,37 +63,55 @@ public class PayTransactionPaySuccessConsumer implements RocketMQListener 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(PayTransactionPaySuccessMessage message) { - // TODO 先简单写,后面重构 - - ApplicationConfig application = new ApplicationConfig(); - application.setName("api-generic-consumer"); - - RegistryConfig registry = new RegistryConfig(); - registry.setAddress("zookeeper://127.0.0.1:2181"); - - application.setRegistry(registry); - - ReferenceConfig reference = new ReferenceConfig<>(); - // 弱类型接口名 - reference.setInterface("cn.iocoder.mall.pay.api.PayDemoService"); - // 声明为泛化接口 - reference.setGeneric(true); - - reference.setApplication(application); - - // 用com.alibaba.dubbo.rpc.service.GenericService可以替代所有接口引用 - GenericService genericService = reference.get(); // TODO 芋艿,要缓存,不然重复引用 - + // 获得 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(); + // 查询支付交易 + PayTransactionDO transaction = payTransactionMapper.selectById(message.getTransactionId()); + Assert.notNull(transaction, String.format("回调消息(%s) 订单交易不能为空", message.toString())); + // 发起调用 String response = null; // RPC / HTTP 调用的响应 PayTransactionNotifyTaskDO updateTask = new PayTransactionNotifyTaskDO() // 更新 PayTransactionNotifyTaskDO 对象 .setId(message.getId()) .setLastExecuteTime(new Date()) .setNotifyTimes(message.getNotifyTimes() + 1); try { - response = (String) genericService.$invoke("updatePaySuccess", new String[]{String.class.getName()}, new Object[]{message.getOrderId()}); + 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()); @@ -87,7 +131,7 @@ public class PayTransactionPaySuccessConsumer implements RocketMQListener