Authored by tanling

修改点如下:

1. 微信,小程序,支付宝的场合,增加预支付记录
	2. 买家订单 or 卖家订单, 自动取消的时候,如果近1分钟内有预支付记录,则发送延迟
	3. 买家订单 or 买家订单, 自动取消的时候,状态未支付&第三方已经支付完成,则 订单结果主动确认
	4. 回调的时候,如果订单已经取消,则触发 退款
package com.yohoufo.order.common;
public enum Payment {
WALLET(11, "wallet", "钱包"),
MINIAPP(3, "miniapp", "微信小程序"),
ALIPAY(2, "alipay", "支付宝"),
WECHAT(1, "wechat", "微信");
WALLET(11, "wallet", "钱包", false),
MINIAPP(3, "miniapp", "微信小程序", true),
ALIPAY(2, "alipay", "支付宝", true),
WECHAT(1, "wechat", "微信", true);
int code;
... ... @@ -15,10 +15,13 @@ public enum Payment {
String desc;
Payment(int code, String name, String desc) {
boolean isNeedPrePay;
Payment(int code, String name, String desc, boolean isNeedPrePay) {
this.code = code;
this.name = name;
this.desc = desc;
this.isNeedPrePay = isNeedPrePay;
}
public int getCode() {
... ... @@ -33,6 +36,10 @@ public enum Payment {
return desc;
}
public boolean isNeedPrePay() {
return isNeedPrePay;
}
/**
* 检查是否存在该支付方式
* @param code
... ...
package com.yohoufo.order.event;
import com.yohoufo.common.alarm.Event;
public class PayConfirmEvent extends Event {
//用户uid
private int uid;
//订单code
private long orderCode;
//支付方式
private int payment;
public PayConfirmEvent(int uid, long orderCode, int payment) {
this.uid = uid;
this.orderCode = orderCode;
this.payment = payment;
}
public int getUid() {
return uid;
}
public void setUid(int uid) {
this.uid = uid;
}
public long getOrderCode() {
return orderCode;
}
public void setOrderCode(long orderCode) {
this.orderCode = orderCode;
}
public int getPayment() {
return payment;
}
public void setPayment(int payment) {
this.payment = payment;
}
}
... ...
package com.yohoufo.order.model.request;
import com.yohobuy.ufo.model.order.common.TabType;
import com.yohoufo.order.event.OrderCancelEvent;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
... ... @@ -21,4 +22,6 @@ public class OrderRequest {
String tabType;
TabType actor;
OrderCancelEvent orderCancelEvent;
}
... ...
... ... @@ -25,7 +25,7 @@ public class BuyerOrderAutoCancelDelayMsgConsumer extends AbsOrderAutoCancelDela
public void cancel(OrderCancelEvent orderCancelEvent) {
int uid = orderCancelEvent.getUid();
long orderCode = orderCancelEvent.getOrderCode();
OrderRequest req = OrderRequest.builder().uid(uid).orderCode(orderCode).build();
OrderRequest req = OrderRequest.builder().uid(uid).orderCode(orderCode).orderCancelEvent(orderCancelEvent).build();
buyerOrderService.cancelByAuto(req);
}
... ...
package com.yohoufo.order.mq.consumer;
import com.yohoufo.order.event.OrderCancelEvent;
import com.yohoufo.order.model.request.OrderRequest;
import com.yohoufo.order.mq.TopicConstants;
import com.yohoufo.order.service.impl.SellerOrderCancelService;
import org.springframework.beans.factory.annotation.Autowired;
... ... @@ -22,9 +23,11 @@ public class SellerOrderAutoCancelDelayMsgConsumer extends AbsOrderAutoCancelDel
@Override
public void cancel(OrderCancelEvent orderCancelEvent) {
int uid = orderCancelEvent.getUid();
long orderCode = orderCancelEvent.getOrderCode();
sellerOrderCancelService.cancelByTimeout(uid, orderCode);
OrderRequest orderRequest = OrderRequest.builder()
.uid(orderCancelEvent.getUid())
.orderCode(orderCancelEvent.getOrderCode())
.orderCancelEvent(orderCancelEvent).build();
sellerOrderCancelService.cancelByTimeout(orderRequest);
}
@Override
... ...
... ... @@ -13,6 +13,13 @@ import com.yohoufo.order.service.pay.AbstractPayService;
public interface IPaymentService {
/**
* 近1分钟内是否有预支付记录
* @param uid
* @param orderCode
*/
public void checkPrePay(int uid, long orderCode);
/**
* 支付
* @param request
* @return
... ...
package com.yohoufo.order.service.handler;
import com.google.common.eventbus.Subscribe;
import com.yoho.error.ServiceError;
import com.yoho.error.exception.ServiceException;
import com.yohoufo.common.alarm.IEventHandler;
import com.yohoufo.order.event.PayConfirmEvent;
import com.yohoufo.order.model.request.PaymentRequest;
import com.yohoufo.order.service.IPaymentService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
@Component
public class PayConfirmEventHandler implements IEventHandler<PayConfirmEvent> {
final Logger logger = LoggerFactory.getLogger(getClass());
@Autowired
IPaymentService paymentService;
@Subscribe
@Override
public void handle(PayConfirmEvent event) {
logger.info("begin handle payConfirmEvent, uid: {}, orderCode: {}, payment: {}", event.getUid(), event.getOrderCode(), event.getPayment());
if (event.getOrderCode() <= 0 || event.getUid() <= 0 || event.getPayment() <= 0) {
throw new ServiceException(ServiceError.ORDER_REQUEST_PARM_IS_EMPTY);
}
PaymentRequest request = PaymentRequest.builder().uid(event.getUid()).orderCode(event.getOrderCode()).payment(event.getPayment()).build();
logger.info("ufo.order.confirm req {}", request);
paymentService.payConfirm(request);
}
}
\ No newline at end of file
... ...
... ... @@ -13,6 +13,7 @@ import com.yohobuy.ufo.model.order.resp.OrderCntResp;
import com.yohobuy.ufo.model.order.resp.OrderListInfo;
import com.yohobuy.ufo.model.order.resp.PageResp;
import com.yohobuy.ufo.model.order.vo.OrderListVo;
import com.yohoufo.common.alarm.EventBusPublisher;
import com.yohoufo.common.exception.UfoServiceException;
import com.yohoufo.common.utils.DateUtil;
import com.yohoufo.common.utils.UserInfoHiddenHelper;
... ... @@ -28,6 +29,7 @@ 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.event.PayConfirmEvent;
import com.yohoufo.order.model.PayQueryBo;
import com.yohoufo.order.model.request.OrderListRequest;
import com.yohoufo.order.model.request.OrderRequest;
... ... @@ -79,9 +81,6 @@ public class BuyerOrderServiceImpl implements IBuyerOrderService {
private InBoxFacade inBoxFacade;
@Autowired
IPaymentService paymentService;
@Autowired
private OrderCacheService orderCacheService;
@Autowired
... ... @@ -93,6 +92,9 @@ public class BuyerOrderServiceImpl implements IBuyerOrderService {
@Autowired
private IBuyerOrderMetaService buyerOrderMetaService;
@Autowired
IPaymentService paymentService;
/**
* 提交订单
* @param orderRequest
... ... @@ -350,10 +352,17 @@ public class BuyerOrderServiceImpl implements IBuyerOrderService {
}
public void cancelBeforePaid(OrderRequest orderRequest, DataNode dataNode, OrderStatus exceptStatus, OrderStatus targetStatus){
// 状态 ![待付款] 不合法
checkStatus(dataNode, orderRequest, exceptStatus);
// 近一分钟内有预支付记录
if (orderRequest.getOrderCancelEvent()!=null && !orderRequest.getOrderCancelEvent().isFinalRetry()){
paymentService.checkPrePay(orderRequest.getUid(), orderRequest.getOrderCode());
}
// 更新订单状态
final OrderStatus orderStatus = targetStatus;
final long orderCode;
... ... @@ -423,7 +432,6 @@ public class BuyerOrderServiceImpl implements IBuyerOrderService {
*/
private void checkStatus(DataNode node, OrderRequest orderRequest, OrderStatus orderStatusEx ) {
BuyerOrder buyerOrder = node.buyerOrderInDB;
// 检查 订单状态
int status = buyerOrder.getStatus() == null ? -1 : buyerOrder.getStatus().intValue();
... ... @@ -434,15 +442,19 @@ public class BuyerOrderServiceImpl implements IBuyerOrderService {
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 {}",
logger.warn("check status failed ,confirm paid, uid is {}, orderCode is {}, status is {}",
orderRequest.getUid(), orderRequest.getOrderCode(), buyerOrder.getStatus());
// 主动触发支付结果确认
PayConfirmEvent event = new PayConfirmEvent(buyerOrder.getUid(), buyerOrder.getOrderCode(), buyerOrder.getPayment());
EventBusPublisher.publishEvent(event);
throw new ServiceException(ServiceError.ORDER_STATUS_INVALIDATE);
}
}
... ...
... ... @@ -133,6 +133,10 @@ public class PaymentServiceImpl implements IPaymentService {
@Autowired
private BuyerCancelCompensateComputeHandler buyerCancelCompensateComputeHandler;
@Autowired
OrdersPrePayMapper ordersPrePayMapper;
... ... @@ -1214,7 +1218,12 @@ public class PaymentServiceImpl implements IPaymentService {
//将openID 附属在 orderinfo上,用于拼接支付URL
orderInfo.setOpenid(request.getOpenid());
// 卖家or买家订单,支付方式更新,返回实付金额
BigDecimal amount = paymentService.checkUpdOrderCodePayment(orderInfo, request);
paymentService.checkUpdOrderCodePayment(orderInfo, request);
// 增加预支付记录
if (payment.isNeedPrePay()){
savePrePayOrder(payment, orderInfo);
}
AbstractPayService abstractPayService = getPayService(payment.getCode());
// 微信支付
... ... @@ -1234,7 +1243,40 @@ public class PaymentServiceImpl implements IPaymentService {
return response;
}
/**
* 取消订单与支付的时间间隔判定标识,默认1分钟,单位秒;
*/
public static final int PRE_PAY_TIME = 60;
private void savePrePayOrder(Payment payment, OrderInfo orderInfo) {
int now = (int) (System.currentTimeMillis() / 1000);
OrdersPrePay ordersPrePay = new OrdersPrePay();
ordersPrePay.setOrderCode(orderInfo.getOrderCode());
ordersPrePay.setUid(orderInfo.getUid());
ordersPrePay.setPayment(payment.getCode());
ordersPrePay.setCreateTime( now );
ordersPrePay.setUpdateTime( now );
ordersPrePay.setUpdateNum(1);
ordersPrePayMapper.insertOnDuplicateUpdate(ordersPrePay);
}
/**
* 近1分钟内是否有预支付记录
* @param uid
* @param orderCode
*/
public void checkPrePay(int uid, long orderCode) {
OrdersPrePay ordersPrePay = ordersPrePayMapper.selectByUidAndOrderCode(uid, orderCode);
if (Objects.isNull(ordersPrePay)) {
return;
}
int payTime = (int) (System.currentTimeMillis() / 1000) - ordersPrePay.getUpdateTime();
logger.info("end ordersPrePayDAO.checkPrePayTime,orderCode:{} ,payTime:{}", ordersPrePay.getOrderCode(), payTime);
if (payTime < PRE_PAY_TIME) {
logger.warn("CloseOrderByCode fail, prePayTime is less than setTime. order: {} ", ordersPrePay.getOrderCode());
throw new ServiceException(ServiceError.ORDER_CANCEL_FAILED_NOT_FIT_TIME);
}
}
/**
* 入口数据检查
... ...
... ... @@ -18,8 +18,10 @@ 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.event.PayConfirmEvent;
import com.yohoufo.order.model.PayQueryBo;
import com.yohoufo.order.model.PayRefundBo;
import com.yohoufo.order.model.request.OrderRequest;
import com.yohoufo.order.model.request.PaymentRequest;
import com.yohoufo.order.model.request.TransferMoneyRequest;
import com.yohoufo.order.mq.DelayTime;
... ... @@ -200,7 +202,11 @@ public class SellerOrderCancelService {
}
public int cancelByTimeout(int uid, long orderCode){
public int cancelByTimeout(OrderRequest orderRequest){
int uid = orderRequest.getUid();
long orderCode = orderRequest.getOrderCode();
int result = 0;
SellerOrder sellerOrder = sellerOrderMapper.selectByOrderCodeUid(orderCode, uid);
... ... @@ -215,16 +221,25 @@ public class SellerOrderCancelService {
// 到第三方检查,如果已经支付了,则不能自动取消
Payment payment = Payment.getPayment(sellerOrder.getPayment());
if (payment != null){
if (SellerOrderStatus.WAITING_PAY.getCode() == status && 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);
logger.info("in seller timeout cancel failed, confirm paid. uid is {}, orderCode is {}", uid, orderCode);
PayConfirmEvent event = new PayConfirmEvent(sellerOrder.getUid(), sellerOrder.getOrderCode(), sellerOrder.getPayment());
EventBusPublisher.publishEvent(event);
return result;
}
}
// 如果近1分钟有预支付记录,则发送 自动取消延迟消息
if (orderRequest.getOrderCancelEvent()!= null && !orderRequest.getOrderCancelEvent().isFinalRetry()){
paymentService.checkPrePay(uid, orderCode);
}
//target seller Order Status
SellerOrderStatus targetSOStatus;
//case 1: 未支付时
... ...