Authored by tanling

两边check 支付回调+自动取消

  1 +package com.yohoufo.dal.order;
  2 +
  3 +import com.yohoufo.dal.order.model.OrdersPrePay;
  4 +import org.apache.ibatis.annotations.Param;
  5 +
  6 +public interface OrdersPrePayMapper {
  7 +
  8 + int insertOnDuplicateUpdate(OrdersPrePay record);
  9 +
  10 + OrdersPrePay selectByUidAndOrderCode(@Param("uid") Integer uid, @Param("orderCode") Long orderCode);
  11 +
  12 +
  13 +}
  1 +package com.yohoufo.dal.order.model;
  2 +
  3 +public class OrdersPrePay {
  4 + private Long orderCode;
  5 +
  6 + private Integer uid;
  7 +
  8 + private Integer payment;
  9 +
  10 + private Integer createTime;
  11 +
  12 + private Integer updateTime;
  13 +
  14 + //更新次数
  15 + private Integer updateNum = 1;
  16 +
  17 + public Long getOrderCode() {
  18 + return orderCode;
  19 + }
  20 +
  21 + public void setOrderCode(Long orderCode) {
  22 + this.orderCode = orderCode;
  23 + }
  24 +
  25 + public Integer getUid() {
  26 + return uid;
  27 + }
  28 +
  29 + public void setUid(Integer uid) {
  30 + this.uid = uid;
  31 + }
  32 +
  33 + public Integer getPayment() {
  34 + return payment;
  35 + }
  36 +
  37 + public void setPayment(Integer payment) {
  38 + this.payment = payment;
  39 + }
  40 +
  41 + public Integer getCreateTime() {
  42 + return createTime;
  43 + }
  44 +
  45 + public void setCreateTime(Integer createTime) {
  46 + this.createTime = createTime;
  47 + }
  48 +
  49 + public Integer getUpdateTime() {
  50 + return updateTime;
  51 + }
  52 +
  53 + public void setUpdateTime(Integer updateTime) {
  54 + this.updateTime = updateTime;
  55 + }
  56 +
  57 + public Integer getUpdateNum() {
  58 + return updateNum;
  59 + }
  60 +
  61 + public void setUpdateNum(Integer updateNum) {
  62 + this.updateNum = updateNum;
  63 + }
  64 +}
  1 +<?xml version="1.0" encoding="UTF-8" ?>
  2 +<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd" >
  3 +<mapper namespace="com.yohoufo.dal.order.OrdersPrePayMapper" >
  4 + <resultMap id="BaseResultMap" type="com.yohoufo.dal.order.model.OrdersPrePay" >
  5 + <id column="order_code" property="orderCode" jdbcType="BIGINT" />
  6 + <result column="uid" property="uid" jdbcType="INTEGER" />
  7 + <result column="payment" property="payment" jdbcType="INTEGER" />
  8 + <result column="create_time" property="createTime" jdbcType="INTEGER" />
  9 + <result column="update_time" property="updateTime" jdbcType="INTEGER" />
  10 + <result column="update_num" property="updateNum" jdbcType="INTEGER" />
  11 + </resultMap>
  12 + <sql id="Base_Column_List" >
  13 + order_code, uid, payment, create_time, update_time, update_num
  14 + </sql>
  15 +
  16 + <insert id="insertOnDuplicateUpdate" parameterType="com.yohoufo.dal.order.model.OrdersPrePay" >
  17 + insert into orders_pre_pay (order_code, uid, payment, create_time, update_time, update_num)
  18 + values(#{orderCode,jdbcType=BIGINT}, #{uid,jdbcType=INTEGER}, #{payment,jdbcType=INTEGER},
  19 + #{createTime,jdbcType=INTEGER}, #{updateTime,jdbcType=INTEGER}, #{updateNum,jdbcType=INTEGER})
  20 + on duplicate key update payment = #{payment,jdbcType=INTEGER}, update_time = #{updateTime,jdbcType=INTEGER},update_num = update_num + #{updateNum,jdbcType=INTEGER}
  21 + </insert>
  22 +
  23 + <select id="selectByUidAndOrderCode" resultMap="BaseResultMap" >
  24 + select
  25 + <include refid="Base_Column_List" />
  26 + from orders_pre_pay
  27 + where order_code = #{orderCode,jdbcType=BIGINT} and uid = #{uid,jdbcType=INTEGER}
  28 + </select>
  29 +
  30 +</mapper>
@@ -38,7 +38,12 @@ public enum Payment { @@ -38,7 +38,12 @@ public enum Payment {
38 * @param code 38 * @param code
39 * @return 39 * @return
40 */ 40 */
41 - public static Payment getPayment(int code){ 41 + public static Payment getPayment(Integer code){
  42 +
  43 + if (code == null){
  44 + return null;
  45 + }
  46 +
42 for(Payment v : values()){ 47 for(Payment v : values()){
43 if(v.code == code){ 48 if(v.code == code){
44 return v; 49 return v;
@@ -35,6 +35,9 @@ public abstract class AbsOrderAutoCancelDelayMsgConsumer implements YhConsumer { @@ -35,6 +35,9 @@ public abstract class AbsOrderAutoCancelDelayMsgConsumer implements YhConsumer {
35 OrderCancelEvent orderCancelEvent = null; 35 OrderCancelEvent orderCancelEvent = null;
36 try { 36 try {
37 orderCancelEvent = JSONObject.parseObject(message.toString(), OrderCancelEvent.class); 37 orderCancelEvent = JSONObject.parseObject(message.toString(), OrderCancelEvent.class);
  38 +
  39 + // 如果1分钟之内有预支付记录,则延迟触发自动取消
  40 +
38 cancel(orderCancelEvent); 41 cancel(orderCancelEvent);
39 mqConsumerLog.info( "handle {} message success, message is {}.", topic, message ); 42 mqConsumerLog.info( "handle {} message success, message is {}.", topic, message );
40 43
@@ -15,6 +15,12 @@ public abstract class AbstractOrderPaymentService { @@ -15,6 +15,12 @@ public abstract class AbstractOrderPaymentService {
15 private final Logger logger = LoggerFactory.getLogger(getClass()); 15 private final Logger logger = LoggerFactory.getLogger(getClass());
16 16
17 17
  18 + /**
  19 + * 超时未支付取消
  20 + * @param orderInfo
  21 + * @return
  22 + */
  23 + public abstract boolean isTimeoutCancelStatus(OrderInfo orderInfo);
18 24
19 25
20 26
@@ -129,6 +129,19 @@ public class BuyerOrderPaymentService extends AbstractOrderPaymentService { @@ -129,6 +129,19 @@ public class BuyerOrderPaymentService extends AbstractOrderPaymentService {
129 return false; 129 return false;
130 } 130 }
131 131
  132 + /**
  133 + * 超时未支付取消
  134 + * @param orderInfo
  135 + * @return
  136 + */
  137 + public boolean isTimeoutCancelStatus(OrderInfo orderInfo){
  138 + if (orderInfo.getStatus() != null && orderInfo.getStatus().intValue() == OrderStatus.BUYER_CANCEL_TIMEOUT.getCode()){
  139 + return true;
  140 + }
  141 +
  142 + return false;
  143 + }
  144 +
132 145
133 /** 146 /**
134 * 订单是 已支付的订单 147 * 订单是 已支付的订单
@@ -8,6 +8,7 @@ import com.yohoufo.order.model.request.PaymentRequest; @@ -8,6 +8,7 @@ import com.yohoufo.order.model.request.PaymentRequest;
8 import com.yohoufo.order.model.request.TransferMoneyRequest; 8 import com.yohoufo.order.model.request.TransferMoneyRequest;
9 import com.yohoufo.order.model.response.PaymentConfirmRsp; 9 import com.yohoufo.order.model.response.PaymentConfirmRsp;
10 import com.yohoufo.order.model.response.PrepayResponse; 10 import com.yohoufo.order.model.response.PrepayResponse;
  11 +import com.yohoufo.order.service.pay.AbstractPayService;
11 12
12 public interface IPaymentService { 13 public interface IPaymentService {
13 14
@@ -18,6 +19,12 @@ public interface IPaymentService { @@ -18,6 +19,12 @@ public interface IPaymentService {
18 */ 19 */
19 PrepayResponse payment(PaymentRequest request); 20 PrepayResponse payment(PaymentRequest request);
20 21
  22 + /**
  23 + * 获取支付的主场service
  24 + * @param paymentCode
  25 + * @return
  26 + */
  27 + public AbstractPayService getPayService(int paymentCode);
21 28
22 /** 29 /**
23 * 订单支付结果确认 30 * 订单支付结果确认
@@ -262,7 +262,12 @@ public class MerchantOrderPaymentService extends AbstractOrderPaymentService { @@ -262,7 +262,12 @@ public class MerchantOrderPaymentService extends AbstractOrderPaymentService {
262 } 262 }
263 263
264 264
265 - /** 265 + @Override
  266 + public boolean isTimeoutCancelStatus(OrderInfo orderInfo) {
  267 + return false;
  268 + }
  269 +
  270 + /**
266 * 获取订单情报 271 * 获取订单情报
267 * @param orderCode 272 * @param orderCode
268 * @param uid 273 * @param uid
@@ -219,6 +219,15 @@ public class SellerOrderPaymentService extends AbstractOrderPaymentService { @@ -219,6 +219,15 @@ public class SellerOrderPaymentService extends AbstractOrderPaymentService {
219 } 219 }
220 220
221 221
  222 + @Override
  223 + public boolean isTimeoutCancelStatus(OrderInfo orderInfo) {
  224 + if (orderInfo.getStatus() != null && orderInfo.getStatus().intValue() == SellerOrderStatus.TIMEOUT_CANCEL.getCode()){
  225 + return true;
  226 + }
  227 +
  228 + return false;
  229 + }
  230 +
222 /** 231 /**
223 * 获取订单情报 232 * 获取订单情报
224 * @param orderCode 233 * @param orderCode
@@ -24,18 +24,22 @@ import com.yohoufo.dal.order.model.BuyerOrderGoods; @@ -24,18 +24,22 @@ import com.yohoufo.dal.order.model.BuyerOrderGoods;
24 import com.yohoufo.dal.order.model.SellerOrderGoods; 24 import com.yohoufo.dal.order.model.SellerOrderGoods;
25 import com.yohoufo.order.common.ActionStatusHold; 25 import com.yohoufo.order.common.ActionStatusHold;
26 import com.yohoufo.order.common.DelStatus; 26 import com.yohoufo.order.common.DelStatus;
  27 +import com.yohoufo.order.common.Payment;
27 import com.yohoufo.order.event.BeforeDepotReceiveEvent; 28 import com.yohoufo.order.event.BeforeDepotReceiveEvent;
28 import com.yohoufo.order.event.BeforeSellerDeliverEvent; 29 import com.yohoufo.order.event.BeforeSellerDeliverEvent;
29 import com.yohobuy.ufo.model.order.vo.AddressInfo; 30 import com.yohobuy.ufo.model.order.vo.AddressInfo;
  31 +import com.yohoufo.order.model.PayQueryBo;
30 import com.yohoufo.order.model.request.OrderListRequest; 32 import com.yohoufo.order.model.request.OrderListRequest;
31 import com.yohoufo.order.model.request.OrderRequest; 33 import com.yohoufo.order.model.request.OrderRequest;
32 import com.yohoufo.order.model.response.OrderDetailInfo; 34 import com.yohoufo.order.model.response.OrderDetailInfo;
33 import com.yohoufo.order.model.response.OrderSummaryResp; 35 import com.yohoufo.order.model.response.OrderSummaryResp;
34 import com.yohoufo.order.service.IBuyerOrderMetaService; 36 import com.yohoufo.order.service.IBuyerOrderMetaService;
35 import com.yohoufo.order.service.IBuyerOrderService; 37 import com.yohoufo.order.service.IBuyerOrderService;
  38 +import com.yohoufo.order.service.IPaymentService;
36 import com.yohoufo.order.service.cache.CacheCleaner; 39 import com.yohoufo.order.service.cache.CacheCleaner;
37 import com.yohoufo.order.service.cache.CacheKeyBuilder; 40 import com.yohoufo.order.service.cache.CacheKeyBuilder;
38 import com.yohoufo.order.service.cache.OrderCacheService; 41 import com.yohoufo.order.service.cache.OrderCacheService;
  42 +import com.yohoufo.order.service.pay.AbstractPayService;
39 import com.yohoufo.order.service.proxy.InBoxFacade; 43 import com.yohoufo.order.service.proxy.InBoxFacade;
40 import com.yohoufo.order.service.proxy.ProductProxyService; 44 import com.yohoufo.order.service.proxy.ProductProxyService;
41 import org.apache.commons.lang3.StringUtils; 45 import org.apache.commons.lang3.StringUtils;
@@ -74,6 +78,8 @@ public class BuyerOrderServiceImpl implements IBuyerOrderService { @@ -74,6 +78,8 @@ public class BuyerOrderServiceImpl implements IBuyerOrderService {
74 @Autowired 78 @Autowired
75 private InBoxFacade inBoxFacade; 79 private InBoxFacade inBoxFacade;
76 80
  81 + @Autowired
  82 + IPaymentService paymentService;
77 83
78 @Autowired 84 @Autowired
79 private OrderCacheService orderCacheService; 85 private OrderCacheService orderCacheService;
@@ -427,6 +433,19 @@ public class BuyerOrderServiceImpl implements IBuyerOrderService { @@ -427,6 +433,19 @@ public class BuyerOrderServiceImpl implements IBuyerOrderService {
427 orderRequest.getUid(), orderRequest.getOrderCode(), buyerOrder.getStatus()); 433 orderRequest.getUid(), orderRequest.getOrderCode(), buyerOrder.getStatus());
428 throw new ServiceException(ServiceError.ORDER_STATUS_INVALIDATE); 434 throw new ServiceException(ServiceError.ORDER_STATUS_INVALIDATE);
429 } 435 }
  436 +
  437 + // 到第三方检查,如果已经支付完成,则无法自动取消
  438 + Payment payment = Payment.getPayment(buyerOrder.getPayment());
  439 + if (payment != null){
  440 + AbstractPayService payService = paymentService.getPayService(payment.getCode());
  441 + PayQueryBo payQueryBo = payService.payQuery(String.valueOf(buyerOrder.getOrderCode()));
  442 +
  443 + if (payQueryBo != null && payQueryBo.isPayStatus()){
  444 + logger.warn("check status failed b, uid is {}, orderCode is {}, status is {}",
  445 + orderRequest.getUid(), orderRequest.getOrderCode(), buyerOrder.getStatus());
  446 + throw new ServiceException(ServiceError.ORDER_STATUS_INVALIDATE);
  447 + }
  448 + }
430 } 449 }
431 450
432 451
@@ -170,7 +170,7 @@ public class PaymentServiceImpl implements IPaymentService { @@ -170,7 +170,7 @@ public class PaymentServiceImpl implements IPaymentService {
170 * @param paymentCode 170 * @param paymentCode
171 * @return 171 * @return
172 */ 172 */
173 - private AbstractPayService getPayService(int paymentCode){ 173 + public AbstractPayService getPayService(int paymentCode){
174 174
175 Payment payment = Payment.getPayment(paymentCode); 175 Payment payment = Payment.getPayment(paymentCode);
176 if (payment == null){ 176 if (payment == null){
@@ -273,6 +273,14 @@ public class PaymentServiceImpl implements IPaymentService { @@ -273,6 +273,14 @@ public class PaymentServiceImpl implements IPaymentService {
273 } 273 }
274 logger.info("paySuccess status check {} {}", orderCode, orderInfo.getStatus()); 274 logger.info("paySuccess status check {} {}", orderCode, orderInfo.getStatus());
275 if (!abstractOrderService.isOrderWaitingPay(orderInfo)){ 275 if (!abstractOrderService.isOrderWaitingPay(orderInfo)){
  276 +
  277 + // 如果状态是已取消,则需要需要把钱退给用户
  278 + if (abstractOrderService.isTimeoutCancelStatus(orderInfo)){
  279 + logger.info("paySuccess but need refund order is {}, amount is {} waring", orderCode, orderInfo.getAmount());
  280 + PaymentRequest request = PaymentRequest.builder().orderCode(orderCode).refundAmount(orderInfo.getAmount().doubleValue()).build();
  281 + refund(request);
  282 + return;
  283 + }
276 logger.warn("paySuccess finished. status has paid, orderCode is {}", orderCode); 284 logger.warn("paySuccess finished. status has paid, orderCode is {}", orderCode);
277 return; 285 return;
278 } 286 }
@@ -18,17 +18,20 @@ import com.yohoufo.order.constants.AlarmConfig; @@ -18,17 +18,20 @@ import com.yohoufo.order.constants.AlarmConfig;
18 import com.yohoufo.order.event.BillLogEvent; 18 import com.yohoufo.order.event.BillLogEvent;
19 import com.yohoufo.order.event.ErpCancelSellerOrderEvent; 19 import com.yohoufo.order.event.ErpCancelSellerOrderEvent;
20 import com.yohoufo.order.event.OrderCancelEvent; 20 import com.yohoufo.order.event.OrderCancelEvent;
  21 +import com.yohoufo.order.model.PayQueryBo;
21 import com.yohoufo.order.model.PayRefundBo; 22 import com.yohoufo.order.model.PayRefundBo;
22 import com.yohoufo.order.model.request.PaymentRequest; 23 import com.yohoufo.order.model.request.PaymentRequest;
23 import com.yohoufo.order.model.request.TransferMoneyRequest; 24 import com.yohoufo.order.model.request.TransferMoneyRequest;
24 import com.yohoufo.order.mq.DelayTime; 25 import com.yohoufo.order.mq.DelayTime;
25 import com.yohoufo.order.mq.TopicConstants; 26 import com.yohoufo.order.mq.TopicConstants;
26 import com.yohoufo.order.mq.producer.TradeMqSender; 27 import com.yohoufo.order.mq.producer.TradeMqSender;
  28 +import com.yohoufo.order.service.IPaymentService;
27 import com.yohoufo.order.service.cache.CacheCleaner; 29 import com.yohoufo.order.service.cache.CacheCleaner;
28 import com.yohoufo.order.service.cache.CacheKeyBuilder; 30 import com.yohoufo.order.service.cache.CacheKeyBuilder;
29 import com.yohoufo.order.service.impl.visitor.AutoCancelCase; 31 import com.yohoufo.order.service.impl.visitor.AutoCancelCase;
30 import com.yohoufo.order.service.impl.visitor.OffShelveCancelCase; 32 import com.yohoufo.order.service.impl.visitor.OffShelveCancelCase;
31 import com.yohoufo.order.service.impl.visitor.UserCancelCase; 33 import com.yohoufo.order.service.impl.visitor.UserCancelCase;
  34 +import com.yohoufo.order.service.pay.AbstractPayService;
32 import com.yohoufo.order.service.proxy.InBoxFacade; 35 import com.yohoufo.order.service.proxy.InBoxFacade;
33 import com.yohoufo.order.service.proxy.ProductProxyService; 36 import com.yohoufo.order.service.proxy.ProductProxyService;
34 import com.yohoufo.order.service.support.codegenerator.OrderCodeGenerator; 37 import com.yohoufo.order.service.support.codegenerator.OrderCodeGenerator;
@@ -89,6 +92,9 @@ public class SellerOrderCancelService { @@ -89,6 +92,9 @@ public class SellerOrderCancelService {
89 @Autowired 92 @Autowired
90 private SellerService sellerService; 93 private SellerService sellerService;
91 94
  95 + @Autowired
  96 + IPaymentService paymentService;
  97 +
92 /** 98 /**
93 * TODO 如何控制好并发,必须控制不能重复转账 退款 99 * TODO 如何控制好并发,必须控制不能重复转账 退款
94 * 使用乐观锁,带着查询到的状态且符合条件时再去更新 100 * 使用乐观锁,带着查询到的状态且符合条件时再去更新
@@ -206,6 +212,19 @@ public class SellerOrderCancelService { @@ -206,6 +212,19 @@ public class SellerOrderCancelService {
206 return result; 212 return result;
207 } 213 }
208 logger.info("in seller timeout cancel, uid {}, orderCode {}, SellerOrder status {}", uid, orderCode, status); 214 logger.info("in seller timeout cancel, uid {}, orderCode {}, SellerOrder status {}", uid, orderCode, status);
  215 +
  216 + // 到第三方检查,如果已经支付了,则不能自动取消
  217 + Payment payment = Payment.getPayment(sellerOrder.getPayment());
  218 + if (payment != null){
  219 + AbstractPayService payService = paymentService.getPayService(payment.getCode());
  220 + PayQueryBo payQueryBo = payService.payQuery(String.valueOf(sellerOrder.getOrderCode()));
  221 +
  222 + if (payQueryBo != null && payQueryBo.isPayStatus()){
  223 + logger.info("in seller timeout cancel failed, because has paid. uid is {}, orderCode is {}", uid, orderCode);
  224 + return result;
  225 + }
  226 + }
  227 +
209 //target seller Order Status 228 //target seller Order Status
210 SellerOrderStatus targetSOStatus; 229 SellerOrderStatus targetSOStatus;
211 //case 1: 未支付时 230 //case 1: 未支付时