后端:增加支付成功后,回调支付模块
This commit is contained in:
parent
914de3f2cb
commit
3eca1823ee
@ -138,8 +138,21 @@ public interface OrderService {
|
||||
*
|
||||
* mq 更新 payStatus
|
||||
*/
|
||||
@Deprecated
|
||||
CommonResult listenerPayment();
|
||||
|
||||
/**
|
||||
* 更新订单支付成功
|
||||
*
|
||||
* 如果成功,则返回 success
|
||||
* 如果失败,则返回具体原因
|
||||
*
|
||||
* @param orderId 订单编号
|
||||
* @param payAmount 支付的订单金额
|
||||
* @return 支付结果
|
||||
*/
|
||||
String updatePaySuccess(String orderId, Integer payAmount);
|
||||
|
||||
/**
|
||||
* 监听确认收货
|
||||
*
|
||||
|
@ -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只有一个!"),
|
||||
|
@ -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 查询
|
||||
*
|
||||
|
@ -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;
|
||||
|
@ -34,22 +34,30 @@
|
||||
<if test="orderNo != null">
|
||||
, order_no = #{orderNo}
|
||||
</if>
|
||||
<!-- <if test="price != null">--> <!-- TODO 后面要改下 -->
|
||||
<!-- , price = #{price}-->
|
||||
<!-- </if>-->
|
||||
<!-- <if test="payAmount != null">-->
|
||||
<!-- , pay_amount = #{payAmount}-->
|
||||
<!-- </if>-->
|
||||
<!-- <if test="logisticsPrice != null">-->
|
||||
<!-- , logistics_price = #{logisticsPrice}-->
|
||||
<!-- </if>-->
|
||||
|
||||
<if test="paymentTime != null">
|
||||
, payment_time = #{paymentTime}
|
||||
<if test="buyPrice != null">
|
||||
, buy_price = #{buyPrice}
|
||||
</if>
|
||||
<if test="discountPrice != null">
|
||||
, discount_price = #{discountPrice}
|
||||
</if>
|
||||
<if test="logisticsPrice != null">
|
||||
, logistics_price = #{logisticsPrice}
|
||||
</if>
|
||||
<if test="logisticsPrice != null">
|
||||
, logistics_price = #{logisticsPrice}
|
||||
</if>
|
||||
<if test="presentPrice != null">
|
||||
, present_price = #{presentPrice}
|
||||
</if>
|
||||
<if test="payAmount != null">
|
||||
, pay_amount = #{payAmount}
|
||||
</if>
|
||||
<if test="deliveryTime != null">
|
||||
, delivery_time = #{deliveryTime}
|
||||
</if>
|
||||
<if test="paymentTime != null">
|
||||
, payment_time = #{paymentTime}
|
||||
</if>
|
||||
<if test="receiverTime != null">
|
||||
, receiver_time = #{receiverTime}
|
||||
</if>
|
||||
@ -87,6 +95,23 @@
|
||||
WHERE id = #{id}
|
||||
</update>
|
||||
|
||||
<update id="updateByIdAndStatus">
|
||||
UPDATE `order`
|
||||
<set>
|
||||
<if test="updateObj.payAmount != null">
|
||||
, pay_amount = #{updateObj.payAmount}
|
||||
</if>
|
||||
<if test="updateObj.paymentTime != null">
|
||||
, payment_time = #{updateObj.paymentTime}
|
||||
</if>
|
||||
<if test="updateObj.status != null">
|
||||
, status = #{updateObj.status}
|
||||
</if>
|
||||
</set>
|
||||
WHERE id = #{id}
|
||||
AND status = #{status}
|
||||
</update>
|
||||
|
||||
<!--
|
||||
查询 - 根据id 查询
|
||||
-->
|
||||
|
@ -16,7 +16,7 @@ public class DubboGenericInvokerTest {
|
||||
|
||||
ReferenceConfig<GenericService> 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);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
@ -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);
|
||||
|
||||
}
|
||||
}
|
||||
|
@ -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<PayTransactionPaySuccessMessage> {
|
||||
|
||||
@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<PayTra
|
||||
@Autowired
|
||||
private PayTransactionMapper payTransactionMapper;
|
||||
|
||||
private LoadingCache<String, ReferenceMeta> referenceMetaCache = CacheBuilder.newBuilder()
|
||||
.build(new CacheLoader<String, ReferenceMeta>() {
|
||||
@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<GenericService> 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<GenericService> 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<PayTra
|
||||
handleFailure(updateTask, PayTransactionNotifyStatusEnum.REQUEST_FAILURE.getValue());
|
||||
payTransactionNotifyTaskMapper.update(updateTask);
|
||||
// 抛出异常,回滚事务
|
||||
throw e;
|
||||
throw e; // TODO 芋艿,此处不能抛出异常。因为,会导致 MQ + 定时任务多重试。此处的目标是,事务回滚 + 吃掉事务。另外,最后的 finally 的日志,要插入成功。
|
||||
} finally {
|
||||
// 插入 PayTransactionNotifyLogDO 日志
|
||||
PayTransactionNotifyLogDO notifyLog = new PayTransactionNotifyLogDO().setNotifyId(message.getId())
|
||||
@ -105,4 +149,4 @@ public class PayTransactionPaySuccessConsumer implements RocketMQListener<PayTra
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user