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