后端:增加支付成功后,回调支付模块
This commit is contained in:
parent
914de3f2cb
commit
3eca1823ee
@ -138,8 +138,21 @@ public interface OrderService {
|
|||||||
*
|
*
|
||||||
* mq 更新 payStatus
|
* mq 更新 payStatus
|
||||||
*/
|
*/
|
||||||
|
@Deprecated
|
||||||
CommonResult listenerPayment();
|
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_NOT_USER_ORDER(1008000011, "不是该用户的订单!"),
|
||||||
ORDER_UNABLE_CONFIRM_ORDER(1008000012, "状态不对不能确认订单!"),
|
ORDER_UNABLE_CONFIRM_ORDER(1008000012, "状态不对不能确认订单!"),
|
||||||
ORDER_CREATE_CART_IS_EMPTY(1008000013, "购物车无选中的商品,无法创建订单"),
|
ORDER_CREATE_CART_IS_EMPTY(1008000013, "购物车无选中的商品,无法创建订单"),
|
||||||
|
ORDER_STATUS_NOT_WAITING_PAYMENT(1008000014, "订单不处于等待支付状态"),
|
||||||
|
ORDER_PAY_AMOUNT_ERROR(1008000015, "订单金额不正确"),
|
||||||
|
|
||||||
// order item
|
// order item
|
||||||
ORDER_ITEM_ONLY_ONE(1008000200, "订单Item只有一个!"),
|
ORDER_ITEM_ONLY_ONE(1008000200, "订单Item只有一个!"),
|
||||||
|
@ -31,6 +31,10 @@ public interface OrderMapper {
|
|||||||
*/
|
*/
|
||||||
int updateById(OrderDO orderDO);
|
int updateById(OrderDO orderDO);
|
||||||
|
|
||||||
|
int updateByIdAndStatus(@Param("id") Integer id,
|
||||||
|
@Param("status") Integer status,
|
||||||
|
@Param("updateObj") OrderDO updateObj);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 查询 - 根据id 查询
|
* 查询 - 根据id 查询
|
||||||
*
|
*
|
||||||
|
@ -598,6 +598,29 @@ public class OrderServiceImpl implements OrderService {
|
|||||||
return null;
|
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
|
@Override
|
||||||
public CommonResult listenerConfirmGoods() {
|
public CommonResult listenerConfirmGoods() {
|
||||||
return null;
|
return null;
|
||||||
|
@ -34,22 +34,30 @@
|
|||||||
<if test="orderNo != null">
|
<if test="orderNo != null">
|
||||||
, order_no = #{orderNo}
|
, order_no = #{orderNo}
|
||||||
</if>
|
</if>
|
||||||
<!-- <if test="price != null">--> <!-- TODO 后面要改下 -->
|
<if test="buyPrice != null">
|
||||||
<!-- , price = #{price}-->
|
, buy_price = #{buyPrice}
|
||||||
<!-- </if>-->
|
</if>
|
||||||
<!-- <if test="payAmount != null">-->
|
<if test="discountPrice != null">
|
||||||
<!-- , pay_amount = #{payAmount}-->
|
, discount_price = #{discountPrice}
|
||||||
<!-- </if>-->
|
</if>
|
||||||
<!-- <if test="logisticsPrice != null">-->
|
<if test="logisticsPrice != null">
|
||||||
<!-- , logistics_price = #{logisticsPrice}-->
|
, logistics_price = #{logisticsPrice}
|
||||||
<!-- </if>-->
|
</if>
|
||||||
|
<if test="logisticsPrice != null">
|
||||||
<if test="paymentTime != null">
|
, logistics_price = #{logisticsPrice}
|
||||||
, payment_time = #{paymentTime}
|
</if>
|
||||||
|
<if test="presentPrice != null">
|
||||||
|
, present_price = #{presentPrice}
|
||||||
|
</if>
|
||||||
|
<if test="payAmount != null">
|
||||||
|
, pay_amount = #{payAmount}
|
||||||
</if>
|
</if>
|
||||||
<if test="deliveryTime != null">
|
<if test="deliveryTime != null">
|
||||||
, delivery_time = #{deliveryTime}
|
, delivery_time = #{deliveryTime}
|
||||||
</if>
|
</if>
|
||||||
|
<if test="paymentTime != null">
|
||||||
|
, payment_time = #{paymentTime}
|
||||||
|
</if>
|
||||||
<if test="receiverTime != null">
|
<if test="receiverTime != null">
|
||||||
, receiver_time = #{receiverTime}
|
, receiver_time = #{receiverTime}
|
||||||
</if>
|
</if>
|
||||||
@ -87,6 +95,23 @@
|
|||||||
WHERE id = #{id}
|
WHERE id = #{id}
|
||||||
</update>
|
</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 查询
|
查询 - 根据id 查询
|
||||||
-->
|
-->
|
||||||
|
@ -16,7 +16,7 @@ public class DubboGenericInvokerTest {
|
|||||||
|
|
||||||
ReferenceConfig<GenericService> reference = new ReferenceConfig<>();
|
ReferenceConfig<GenericService> reference = new ReferenceConfig<>();
|
||||||
// 弱类型接口名
|
// 弱类型接口名
|
||||||
reference.setInterface("cn.iocoder.mall.pay.api.PayDemoService");
|
reference.setInterface("cn.iocoder.mall.order.api.OrderService");
|
||||||
// 声明为泛化接口
|
// 声明为泛化接口
|
||||||
reference.setGeneric(true);
|
reference.setGeneric(true);
|
||||||
|
|
||||||
|
@ -15,6 +15,6 @@ public interface PayTransactionMapper {
|
|||||||
PayTransactionDO selectByAppIdAndOrderId(@Param("appId") String appId,
|
PayTransactionDO selectByAppIdAndOrderId(@Param("appId") String appId,
|
||||||
@Param("orderId") String orderId);
|
@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.ReferenceConfig;
|
||||||
import com.alibaba.dubbo.config.RegistryConfig;
|
import com.alibaba.dubbo.config.RegistryConfig;
|
||||||
import com.alibaba.dubbo.rpc.service.GenericService;
|
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.annotation.RocketMQMessageListener;
|
||||||
import org.apache.rocketmq.spring.core.RocketMQListener;
|
import org.apache.rocketmq.spring.core.RocketMQListener;
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
import org.springframework.beans.factory.annotation.Value;
|
||||||
import org.springframework.stereotype.Service;
|
import org.springframework.stereotype.Service;
|
||||||
import org.springframework.transaction.annotation.Transactional;
|
import org.springframework.transaction.annotation.Transactional;
|
||||||
|
import org.springframework.util.Assert;
|
||||||
|
|
||||||
import java.util.Calendar;
|
import java.util.Calendar;
|
||||||
import java.util.Date;
|
import java.util.Date;
|
||||||
@ -30,6 +36,26 @@ import java.util.Date;
|
|||||||
)
|
)
|
||||||
public class PayTransactionPaySuccessConsumer implements RocketMQListener<PayTransactionPaySuccessMessage> {
|
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
|
@Autowired
|
||||||
private PayTransactionNotifyTaskMapper payTransactionNotifyTaskMapper;
|
private PayTransactionNotifyTaskMapper payTransactionNotifyTaskMapper;
|
||||||
@Autowired
|
@Autowired
|
||||||
@ -37,37 +63,55 @@ public class PayTransactionPaySuccessConsumer implements RocketMQListener<PayTra
|
|||||||
@Autowired
|
@Autowired
|
||||||
private PayTransactionMapper payTransactionMapper;
|
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
|
@Override
|
||||||
@Transactional
|
@Transactional
|
||||||
public void onMessage(PayTransactionPaySuccessMessage message) {
|
public void onMessage(PayTransactionPaySuccessMessage message) {
|
||||||
// TODO 先简单写,后面重构
|
// 获得 ReferenceMeta 对象
|
||||||
|
ReferenceMeta referenceMeta = referenceMetaCache.getUnchecked(message.getNotifyUrl());
|
||||||
ApplicationConfig application = new ApplicationConfig();
|
Assert.notNull(referenceMeta, String.format("notifyUrl(%s) 不存在对应的 ReferenceMeta 对象", message.getNotifyUrl()));
|
||||||
application.setName("api-generic-consumer");
|
GenericService genericService = referenceMeta.getService();
|
||||||
|
String methodName = referenceMeta.getMethodName();
|
||||||
RegistryConfig registry = new RegistryConfig();
|
// 查询支付交易
|
||||||
registry.setAddress("zookeeper://127.0.0.1:2181");
|
PayTransactionDO transaction = payTransactionMapper.selectById(message.getTransactionId());
|
||||||
|
Assert.notNull(transaction, String.format("回调消息(%s) 订单交易不能为空", message.toString()));
|
||||||
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 芋艿,要缓存,不然重复引用
|
|
||||||
|
|
||||||
String response = null; // RPC / HTTP 调用的响应
|
String response = null; // RPC / HTTP 调用的响应
|
||||||
PayTransactionNotifyTaskDO updateTask = new PayTransactionNotifyTaskDO() // 更新 PayTransactionNotifyTaskDO 对象
|
PayTransactionNotifyTaskDO updateTask = new PayTransactionNotifyTaskDO() // 更新 PayTransactionNotifyTaskDO 对象
|
||||||
.setId(message.getId())
|
.setId(message.getId())
|
||||||
.setLastExecuteTime(new Date())
|
.setLastExecuteTime(new Date())
|
||||||
.setNotifyTimes(message.getNotifyTimes() + 1);
|
.setNotifyTimes(message.getNotifyTimes() + 1);
|
||||||
try {
|
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)) { // 情况一,请求成功且返回成功
|
if ("success".equals(response)) { // 情况一,请求成功且返回成功
|
||||||
// 更新通知成功
|
// 更新通知成功
|
||||||
updateTask.setStatus(PayTransactionNotifyStatusEnum.SUCCESS.getValue());
|
updateTask.setStatus(PayTransactionNotifyStatusEnum.SUCCESS.getValue());
|
||||||
@ -87,7 +131,7 @@ public class PayTransactionPaySuccessConsumer implements RocketMQListener<PayTra
|
|||||||
handleFailure(updateTask, PayTransactionNotifyStatusEnum.REQUEST_FAILURE.getValue());
|
handleFailure(updateTask, PayTransactionNotifyStatusEnum.REQUEST_FAILURE.getValue());
|
||||||
payTransactionNotifyTaskMapper.update(updateTask);
|
payTransactionNotifyTaskMapper.update(updateTask);
|
||||||
// 抛出异常,回滚事务
|
// 抛出异常,回滚事务
|
||||||
throw e;
|
throw e; // TODO 芋艿,此处不能抛出异常。因为,会导致 MQ + 定时任务多重试。此处的目标是,事务回滚 + 吃掉事务。另外,最后的 finally 的日志,要插入成功。
|
||||||
} finally {
|
} finally {
|
||||||
// 插入 PayTransactionNotifyLogDO 日志
|
// 插入 PayTransactionNotifyLogDO 日志
|
||||||
PayTransactionNotifyLogDO notifyLog = new PayTransactionNotifyLogDO().setNotifyId(message.getId())
|
PayTransactionNotifyLogDO notifyLog = new PayTransactionNotifyLogDO().setNotifyId(message.getId())
|
||||||
|
Loading…
Reference in New Issue
Block a user