Authored by tanling

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

package com.yohoufo.dal.order;
import com.yohoufo.dal.order.model.OrdersPrePay;
import org.apache.ibatis.annotations.Param;
public interface OrdersPrePayMapper {
int insertOnDuplicateUpdate(OrdersPrePay record);
OrdersPrePay selectByUidAndOrderCode(@Param("uid") Integer uid, @Param("orderCode") Long orderCode);
}
\ No newline at end of file
... ...
package com.yohoufo.dal.order.model;
public class OrdersPrePay {
private Long orderCode;
private Integer uid;
private Integer payment;
private Integer createTime;
private Integer updateTime;
//更新次数
private Integer updateNum = 1;
public Long getOrderCode() {
return orderCode;
}
public void setOrderCode(Long orderCode) {
this.orderCode = orderCode;
}
public Integer getUid() {
return uid;
}
public void setUid(Integer uid) {
this.uid = uid;
}
public Integer getPayment() {
return payment;
}
public void setPayment(Integer payment) {
this.payment = payment;
}
public Integer getCreateTime() {
return createTime;
}
public void setCreateTime(Integer createTime) {
this.createTime = createTime;
}
public Integer getUpdateTime() {
return updateTime;
}
public void setUpdateTime(Integer updateTime) {
this.updateTime = updateTime;
}
public Integer getUpdateNum() {
return updateNum;
}
public void setUpdateNum(Integer updateNum) {
this.updateNum = updateNum;
}
}
\ No newline at end of file
... ...
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd" >
<mapper namespace="com.yohoufo.dal.order.OrdersPrePayMapper" >
<resultMap id="BaseResultMap" type="com.yohoufo.dal.order.model.OrdersPrePay" >
<id column="order_code" property="orderCode" jdbcType="BIGINT" />
<result column="uid" property="uid" jdbcType="INTEGER" />
<result column="payment" property="payment" jdbcType="INTEGER" />
<result column="create_time" property="createTime" jdbcType="INTEGER" />
<result column="update_time" property="updateTime" jdbcType="INTEGER" />
<result column="update_num" property="updateNum" jdbcType="INTEGER" />
</resultMap>
<sql id="Base_Column_List" >
order_code, uid, payment, create_time, update_time, update_num
</sql>
<insert id="insertOnDuplicateUpdate" parameterType="com.yohoufo.dal.order.model.OrdersPrePay" >
insert into orders_pre_pay (order_code, uid, payment, create_time, update_time, update_num)
values(#{orderCode,jdbcType=BIGINT}, #{uid,jdbcType=INTEGER}, #{payment,jdbcType=INTEGER},
#{createTime,jdbcType=INTEGER}, #{updateTime,jdbcType=INTEGER}, #{updateNum,jdbcType=INTEGER})
on duplicate key update payment = #{payment,jdbcType=INTEGER}, update_time = #{updateTime,jdbcType=INTEGER},update_num = update_num + #{updateNum,jdbcType=INTEGER}
</insert>
<select id="selectByUidAndOrderCode" resultMap="BaseResultMap" >
select
<include refid="Base_Column_List" />
from orders_pre_pay
where order_code = #{orderCode,jdbcType=BIGINT} and uid = #{uid,jdbcType=INTEGER}
</select>
</mapper>
\ No newline at end of file
... ...
... ... @@ -38,7 +38,12 @@ public enum Payment {
* @param code
* @return
*/
public static Payment getPayment(int code){
public static Payment getPayment(Integer code){
if (code == null){
return null;
}
for(Payment v : values()){
if(v.code == code){
return v;
... ...
... ... @@ -35,6 +35,9 @@ public abstract class AbsOrderAutoCancelDelayMsgConsumer implements YhConsumer {
OrderCancelEvent orderCancelEvent = null;
try {
orderCancelEvent = JSONObject.parseObject(message.toString(), OrderCancelEvent.class);
// 如果1分钟之内有预支付记录,则延迟触发自动取消
cancel(orderCancelEvent);
mqConsumerLog.info( "handle {} message success, message is {}.", topic, message );
... ...
... ... @@ -15,6 +15,12 @@ public abstract class AbstractOrderPaymentService {
private final Logger logger = LoggerFactory.getLogger(getClass());
/**
* 超时未支付取消
* @param orderInfo
* @return
*/
public abstract boolean isTimeoutCancelStatus(OrderInfo orderInfo);
... ...
... ... @@ -129,6 +129,19 @@ public class BuyerOrderPaymentService extends AbstractOrderPaymentService {
return false;
}
/**
* 超时未支付取消
* @param orderInfo
* @return
*/
public boolean isTimeoutCancelStatus(OrderInfo orderInfo){
if (orderInfo.getStatus() != null && orderInfo.getStatus().intValue() == OrderStatus.BUYER_CANCEL_TIMEOUT.getCode()){
return true;
}
return false;
}
/**
* 订单是 已支付的订单
... ...
... ... @@ -8,6 +8,7 @@ import com.yohoufo.order.model.request.PaymentRequest;
import com.yohoufo.order.model.request.TransferMoneyRequest;
import com.yohoufo.order.model.response.PaymentConfirmRsp;
import com.yohoufo.order.model.response.PrepayResponse;
import com.yohoufo.order.service.pay.AbstractPayService;
public interface IPaymentService {
... ... @@ -18,6 +19,12 @@ public interface IPaymentService {
*/
PrepayResponse payment(PaymentRequest request);
/**
* 获取支付的主场service
* @param paymentCode
* @return
*/
public AbstractPayService getPayService(int paymentCode);
/**
* 订单支付结果确认
... ...
... ... @@ -262,7 +262,12 @@ public class MerchantOrderPaymentService extends AbstractOrderPaymentService {
}
/**
@Override
public boolean isTimeoutCancelStatus(OrderInfo orderInfo) {
return false;
}
/**
* 获取订单情报
* @param orderCode
* @param uid
... ...
... ... @@ -219,6 +219,15 @@ public class SellerOrderPaymentService extends AbstractOrderPaymentService {
}
@Override
public boolean isTimeoutCancelStatus(OrderInfo orderInfo) {
if (orderInfo.getStatus() != null && orderInfo.getStatus().intValue() == SellerOrderStatus.TIMEOUT_CANCEL.getCode()){
return true;
}
return false;
}
/**
* 获取订单情报
* @param orderCode
... ...
... ... @@ -24,18 +24,22 @@ import com.yohoufo.dal.order.model.BuyerOrderGoods;
import com.yohoufo.dal.order.model.SellerOrderGoods;
import com.yohoufo.order.common.ActionStatusHold;
import com.yohoufo.order.common.DelStatus;
import com.yohoufo.order.common.Payment;
import com.yohoufo.order.event.BeforeDepotReceiveEvent;
import com.yohoufo.order.event.BeforeSellerDeliverEvent;
import com.yohobuy.ufo.model.order.vo.AddressInfo;
import com.yohoufo.order.model.PayQueryBo;
import com.yohoufo.order.model.request.OrderListRequest;
import com.yohoufo.order.model.request.OrderRequest;
import com.yohoufo.order.model.response.OrderDetailInfo;
import com.yohoufo.order.model.response.OrderSummaryResp;
import com.yohoufo.order.service.IBuyerOrderMetaService;
import com.yohoufo.order.service.IBuyerOrderService;
import com.yohoufo.order.service.IPaymentService;
import com.yohoufo.order.service.cache.CacheCleaner;
import com.yohoufo.order.service.cache.CacheKeyBuilder;
import com.yohoufo.order.service.cache.OrderCacheService;
import com.yohoufo.order.service.pay.AbstractPayService;
import com.yohoufo.order.service.proxy.InBoxFacade;
import com.yohoufo.order.service.proxy.ProductProxyService;
import org.apache.commons.lang3.StringUtils;
... ... @@ -74,6 +78,8 @@ public class BuyerOrderServiceImpl implements IBuyerOrderService {
@Autowired
private InBoxFacade inBoxFacade;
@Autowired
IPaymentService paymentService;
@Autowired
private OrderCacheService orderCacheService;
... ... @@ -427,6 +433,19 @@ public class BuyerOrderServiceImpl implements IBuyerOrderService {
orderRequest.getUid(), orderRequest.getOrderCode(), buyerOrder.getStatus());
throw new ServiceException(ServiceError.ORDER_STATUS_INVALIDATE);
}
// 到第三方检查,如果已经支付完成,则无法自动取消
Payment payment = Payment.getPayment(buyerOrder.getPayment());
if (payment != null){
AbstractPayService payService = paymentService.getPayService(payment.getCode());
PayQueryBo payQueryBo = payService.payQuery(String.valueOf(buyerOrder.getOrderCode()));
if (payQueryBo != null && payQueryBo.isPayStatus()){
logger.warn("check status failed b, uid is {}, orderCode is {}, status is {}",
orderRequest.getUid(), orderRequest.getOrderCode(), buyerOrder.getStatus());
throw new ServiceException(ServiceError.ORDER_STATUS_INVALIDATE);
}
}
}
... ...
... ... @@ -170,7 +170,7 @@ public class PaymentServiceImpl implements IPaymentService {
* @param paymentCode
* @return
*/
private AbstractPayService getPayService(int paymentCode){
public AbstractPayService getPayService(int paymentCode){
Payment payment = Payment.getPayment(paymentCode);
if (payment == null){
... ... @@ -273,6 +273,14 @@ public class PaymentServiceImpl implements IPaymentService {
}
logger.info("paySuccess status check {} {}", orderCode, orderInfo.getStatus());
if (!abstractOrderService.isOrderWaitingPay(orderInfo)){
// 如果状态是已取消,则需要需要把钱退给用户
if (abstractOrderService.isTimeoutCancelStatus(orderInfo)){
logger.info("paySuccess but need refund order is {}, amount is {} waring", orderCode, orderInfo.getAmount());
PaymentRequest request = PaymentRequest.builder().orderCode(orderCode).refundAmount(orderInfo.getAmount().doubleValue()).build();
refund(request);
return;
}
logger.warn("paySuccess finished. status has paid, orderCode is {}", orderCode);
return;
}
... ...
... ... @@ -18,17 +18,20 @@ import com.yohoufo.order.constants.AlarmConfig;
import com.yohoufo.order.event.BillLogEvent;
import com.yohoufo.order.event.ErpCancelSellerOrderEvent;
import com.yohoufo.order.event.OrderCancelEvent;
import com.yohoufo.order.model.PayQueryBo;
import com.yohoufo.order.model.PayRefundBo;
import com.yohoufo.order.model.request.PaymentRequest;
import com.yohoufo.order.model.request.TransferMoneyRequest;
import com.yohoufo.order.mq.DelayTime;
import com.yohoufo.order.mq.TopicConstants;
import com.yohoufo.order.mq.producer.TradeMqSender;
import com.yohoufo.order.service.IPaymentService;
import com.yohoufo.order.service.cache.CacheCleaner;
import com.yohoufo.order.service.cache.CacheKeyBuilder;
import com.yohoufo.order.service.impl.visitor.AutoCancelCase;
import com.yohoufo.order.service.impl.visitor.OffShelveCancelCase;
import com.yohoufo.order.service.impl.visitor.UserCancelCase;
import com.yohoufo.order.service.pay.AbstractPayService;
import com.yohoufo.order.service.proxy.InBoxFacade;
import com.yohoufo.order.service.proxy.ProductProxyService;
import com.yohoufo.order.service.support.codegenerator.OrderCodeGenerator;
... ... @@ -89,6 +92,9 @@ public class SellerOrderCancelService {
@Autowired
private SellerService sellerService;
@Autowired
IPaymentService paymentService;
/**
* TODO 如何控制好并发,必须控制不能重复转账 退款
* 使用乐观锁,带着查询到的状态且符合条件时再去更新
... ... @@ -206,6 +212,19 @@ public class SellerOrderCancelService {
return result;
}
logger.info("in seller timeout cancel, uid {}, orderCode {}, SellerOrder status {}", uid, orderCode, status);
// 到第三方检查,如果已经支付了,则不能自动取消
Payment payment = Payment.getPayment(sellerOrder.getPayment());
if (payment != null){
AbstractPayService payService = paymentService.getPayService(payment.getCode());
PayQueryBo payQueryBo = payService.payQuery(String.valueOf(sellerOrder.getOrderCode()));
if (payQueryBo != null && payQueryBo.isPayStatus()){
logger.info("in seller timeout cancel failed, because has paid. uid is {}, orderCode is {}", uid, orderCode);
return result;
}
}
//target seller Order Status
SellerOrderStatus targetSOStatus;
//case 1: 未支付时
... ...