package service import ( "context" "errors" "fmt" "gorm.io/gorm" "hepa-calc-admin-api/api/dao" "hepa-calc-admin-api/api/model" "hepa-calc-admin-api/config" "hepa-calc-admin-api/extend/weChat" "hepa-calc-admin-api/global" "hepa-calc-admin-api/utils" "strconv" "time" ) type OrderMemberService struct { } // CancelOrderMember 取消会员订单 // cancelReason:订单取消原因(1:主动取消 2:后台取消 3:支付超时取消) func (r *OrderMemberService) CancelOrderMember(tx *gorm.DB, orderMember *model.OrderMember, refundAmount *float64, cancelReason int) (bool, error) { // 检测多次请求 redisKey := "CancelOrderMember" + fmt.Sprintf("%d", orderMember.UserId) + fmt.Sprintf("%d", orderMember.OrderId) res, _ := global.Redis.Get(context.Background(), redisKey).Result() if res != "" { return false, errors.New("请勿重复操作") } defer func(redisKey string) { global.Redis.Del(context.Background(), redisKey) }(redisKey) // 添加缓存 _, err := global.Redis.Set(context.Background(), redisKey, "1", (10)*time.Second).Result() if err != nil { return false, errors.New("取消订单失败") } // 订单状态(1:待支付 2:已完成 3:已取消) if orderMember.OrderStatus == 3 { return false, errors.New("订单已取消,请勿重复操作") } // 取消状态(0:否 1:是) if orderMember.CancelStatus == 1 { return false, errors.New("订单已取消") } // 订单退款状态(0:无退款 1:申请退款 2:退款中 3:退款成功 4:拒绝退款 5:退款关闭 6:退款异常 7:部分退款) if orderMember.RefundStatus == 1 { return false, errors.New("订单已申请退款") } if orderMember.RefundStatus == 2 { return false, errors.New("订单退款中") } if orderMember.RefundStatus == 3 { return false, errors.New("订单已退款成功") } if orderMember.RefundStatus == 6 { return false, errors.New("订单退款异常") } // 修改订单为取消 orderMemberDao := dao.OrderMemberDao{} orderMemberData := make(map[string]interface{}) orderMemberData["order_status"] = 3 if cancelReason == 3 { // 支付超时取消 orderMemberData["pay_status"] = 5 } orderMemberData["cancel_status"] = 1 orderMemberData["cancel_time"] = time.Now().Format("2006-01-02 15:04:05") orderMemberData["cancel_remarks"] = utils.OrderCancelReasonToString(cancelReason) err = orderMemberDao.EditOrderMemberById(tx, orderMember.OrderId, orderMemberData) if err != nil { return false, errors.New("订单取消失败") } // 订单退款 _, err = r.OrderRefund(tx, orderMember, refundAmount, utils.OrderCancelReasonToString(cancelReason)) if err != nil { return false, err } // 处理支付金额为0时退还优惠卷问题 if orderMember.PaymentAmountTotal == 0 { // 退还订单优惠卷 err = r.OrderCouponRefund(tx, orderMember) if err != nil { return false, err } } return true, nil } // OrderRefund 订单退款 func (r *OrderMemberService) OrderRefund(tx *gorm.DB, order *model.OrderMember, refundAmount *float64, refundReason string) (*model.OrderMemberRefund, error) { var refundStatus int var successTime *time.Time var refundId string // 判断订单支付状态(1:未支付 2:已支付 3:支付中 4:支付失败 5:支付超时 6:支付关闭 7:已撤销 8:转入退款) if order.PayStatus != 2 { // 非已支付,无需退款 return nil, nil } // 检测退款金额 if *refundAmount > order.PaymentAmountTotal { return nil, errors.New("退款金额不可超过实付金额") } // 退款编号 refundNo := strconv.FormatInt(global.Snowflake.Generate().Int64(), 10) // 退款金额为0 if *refundAmount <= 0 { // 支付金额为0,模拟退款 refundId = "模拟退款:" + strconv.FormatInt(global.Snowflake.Generate().Int64(), 10) refundStatus = 3 now := time.Now() successTime = &now } // 退款金额大于0 if *refundAmount > 0 { refundRequest := weChat.RefundRequest{ TransactionId: order.EscrowTradeNo, OutTradeNo: order.OrderNo, OutRefundNo: refundNo, Reason: refundReason, RefundAmount: int64(*refundAmount * 100), PaymentAmountTotal: int64(order.PaymentAmountTotal * 100), NotifyUrl: config.C.Wechat.NotifyDomain + config.C.Wechat.MemberRefundNotifyUrl, } refund, err := refundRequest.Refund() if err != nil { return nil, err } // 处理退款状态 wxPayRefundResult, err := weChat.HandlePayRefundStatus(refund) if err != nil { return nil, err } refundStatus = wxPayRefundResult.RefundStatus successTime = wxPayRefundResult.SuccessTime if refund.RefundId == nil { return nil, errors.New("缺少退款订单编号") } // 退款编号 refundId = *refund.RefundId } // 新增退款表 orderRefund := &model.OrderMemberRefund{ UserId: order.UserId, OrderId: order.OrderId, OrderNo: order.OrderNo, RefundNo: refundNo, RefundId: refundId, RefundStatus: refundStatus, RefundTotal: *refundAmount, RefundReason: refundReason, } if refundStatus == 3 && successTime != nil { t := model.LocalTime(*successTime) orderRefund.SuccessTime = &t } orderMemberRefundDao := dao.OrderMemberRefundDao{} orderMemberRefund, err := orderMemberRefundDao.AddOrderMemberRefund(tx, orderRefund) if err != nil || orderMemberRefund == nil { return nil, errors.New(err.Error()) } return orderMemberRefund, nil } // OrderCouponRefund 订单优惠卷退还 func (r *OrderMemberService) OrderCouponRefund(tx *gorm.DB, order *model.OrderMember) error { // 订单优惠金额为0,无需退还优惠卷 if order.CouponAmountTotal == 0 { return nil } // 获取订单优惠卷数据 orderMemberCouponDao := dao.OrderMemberCouponDao{} orderMemberCoupons, err := orderMemberCouponDao.GetOrderMemberCouponListByOrderId(order.OrderId) if err != nil { return errors.New("优惠卷数据错误") } userCouponService := &UserCouponService{} for _, coupon := range orderMemberCoupons { _ = userCouponService.ReturnUserCoupon(tx, coupon.UserCouponId) } return nil }