package logic import ( "errors" "fusenapi/constants" "fusenapi/model/gmodel" "fusenapi/utils/auth" "fusenapi/utils/basic" "fusenapi/utils/handlers" "time" "context" "fusenapi/server/home-user-auth/internal/svc" "fusenapi/server/home-user-auth/internal/types" "github.com/zeromicro/go-zero/core/logx" "gorm.io/gorm" ) type UserOrderCancelLogic struct { logx.Logger ctx context.Context svcCtx *svc.ServiceContext } func NewUserOrderCancelLogic(ctx context.Context, svcCtx *svc.ServiceContext) *UserOrderCancelLogic { return &UserOrderCancelLogic{ Logger: logx.WithContext(ctx), ctx: ctx, svcCtx: svcCtx, } } func (l *UserOrderCancelLogic) UserOrderCancel(req *types.UserOrderCancelReq, userinfo *auth.UserInfo) (resp *basic.Response) { // 返回值必须调用Set重新返回, resp可以空指针调用 resp.SetStatus(basic.CodeOK, data) // userinfo 传入值时, 一定不为null if userinfo == nil || userinfo.UserId == 0 { return resp.SetStatusWithMessage(basic.CodeDbRecordNotFoundErr, "order not found") } //查询订单信息 orderModel := gmodel.NewFsOrderModel(l.svcCtx.MysqlConn) orderInfo, err := orderModel.FindOne(l.ctx, userinfo.UserId, req.ID) if err != nil { if errors.Is(err, gorm.ErrRecordNotFound) { return resp.SetStatusWithMessage(basic.CodeDbRecordNotFoundErr, "the order is not exists") } logx.Error(err) return resp.SetStatus(basic.CodeServiceErr, "failed to get order info") } // 判断订单状态 var notCancelStatusMap = make(map[int64]struct{}, 3) notCancelStatusMap[int64(constants.STATUS_NEW_NOT_PAY)] = struct{}{} notCancelStatusMap[int64(constants.STATUS_NEW_PART_PAY)] = struct{}{} notCancelStatusMap[int64(constants.STATUS_NEW_PAY_COMPLETED)] = struct{}{} _, ok := notCancelStatusMap[int64(*orderInfo.Status)] if !ok { return resp.SetStatusWithMessage(basic.CodeOrderNotCancelledErr, "the order status not cancle") } var cancelTime int64 = time.Now().UTC().Unix() - (*orderInfo.Ctime + int64(constants.CANCLE_ORDER_EXPIRE)) // 第一次支付成功后48小时后不能进行取消操作 if *orderInfo.IsPayCompleted == 1 && cancelTime > 0 { return resp.SetStatusWithMessage(basic.CodeOrderNotCancelledErr, "The current order cannot be cancelled") } // 修改订单--取消状态和取消原因 *orderInfo.Status = int64(constants.STATUS_NEW_CANCEL) *orderInfo.IsCancel = 1 orderInfo.RefundReasonId = &req.RefundReasonId orderInfo.RefundReason = &req.RefundReason var nowTime = time.Now().UTC().Unix() var payList []handlers.PayInfo // 事务处理 ctx := l.ctx err = l.svcCtx.MysqlConn.Transaction(func(tx *gorm.DB) error { // 修改订单信息 orderModelTS := gmodel.NewFsOrderModel(tx) err = orderModelTS.RBUpdate(ctx, orderInfo) if err != nil { return err } // 新增退款记录 var isRefund int64 = 0 refundReasonModelTS := gmodel.NewFsRefundReasonModel(tx) refundReasonModelTS.RBCreateOrUpdate(ctx, &gmodel.FsRefundReason{ IsRefund: &isRefund, RefundReasonId: &req.RefundReasonId, RefundReason: &req.RefundReason, OrderId: &orderInfo.Id, CreatedAt: &nowTime, }) // 退款申请 // 退款申请--查询支付信息 fsPayModelTS := gmodel.NewFsPayModel(tx) rbFsPay := fsPayModelTS.RowSelectBuilder(nil).Where("order_number = ?", orderInfo.Sn).Where("pay_status =?", constants.PAYSTATUS_SUCCESS).Where("is_refund =?", 0) payInfoList, err := fsPayModelTS.FindAll(ctx, rbFsPay, nil, "") if err != nil { return err } for _, payInfo := range payInfoList { var key string if *payInfo.PaymentMethod == int64(constants.PAYMETHOD_STRIPE) { key = l.svcCtx.Config.PayConfig.Stripe.Key } payList = append(payList, handlers.PayInfo{ TradeNo: *payInfo.TradeNo, PaymentMethod: *payInfo.PaymentMethod, Key: key, }) } return nil }) // 退款申请--调取第三方接口发起退款 handlers.PayRefundHandler(&handlers.PayRefundHandlerReq{ PayInfoList: payList, }) if err != nil { logx.Error(err) return resp.SetStatusWithMessage(basic.CodeOrderCancelledNotOk, "the order cancle failed") } return resp.SetStatus(basic.CodeOK) }