package service import ( "crypto/md5" "encoding/hex" "errors" "fmt" "log" "math/rand" "time" "github.com/gouki/lunar-server/internal/config" "github.com/gouki/lunar-server/internal/model" "gorm.io/gorm" ) // OrderService 订单服务 type OrderService struct { db *gorm.DB } // NewOrderService 创建订单服务 func NewOrderService() *OrderService { return &OrderService{ db: config.GetDB(), } } // CreateOrder 创建订单 func (s *OrderService) CreateOrder(order *model.Order) error { // 生成订单号 order.OrderNo = s.generateOrderNo() order.Status = "pending" // 设置过期时间(30分钟) expireTime := time.Now().Add(30 * time.Minute) order.ExpireTime = &expireTime return s.db.Create(order).Error } // generateOrderNo 生成订单号 func (s *OrderService) generateOrderNo() string { // 格式:L + 年月日时分秒 + 6位随机数 now := time.Now() random := rand.Intn(1000000) return fmt.Sprintf("L%s%06d", now.Format("20060102150405"), random) } // GetOrderByID 根据ID获取订单 func (s *OrderService) GetOrderByID(id uint) (*model.Order, error) { var order model.Order if err := s.db.First(&order, id).Error; err != nil { return nil, err } return &order, nil } // GetOrderByOrderNo 根据订单号获取订单 func (s *OrderService) GetOrderByOrderNo(orderNo string) (*model.Order, error) { var order model.Order if err := s.db.Where("order_no = ?", orderNo).First(&order).Error; err != nil { return nil, err } return &order, nil } // GetOrderList 获取订单列表 func (s *OrderService) GetOrderList(userID uint, page, pageSize int) ([]*model.Order, int64, error) { var orders []*model.Order var total int64 query := s.db.Model(&model.Order{}).Where("user_id = ?", userID) if err := query.Count(&total).Error; err != nil { return nil, 0, err } if err := query.Order("created_at DESC"). Offset((page - 1) * pageSize). Limit(pageSize). Find(&orders).Error; err != nil { return nil, 0, err } return orders, total, nil } // UpdateOrderStatus 更新订单状态 func (s *OrderService) UpdateOrderStatus(orderNo, status string) error { updates := map[string]interface{}{ "status": status, } if status == "paid" { now := time.Now() updates["pay_time"] = &now } return s.db.Model(&model.Order{}).Where("order_no = ?", orderNo).Updates(updates).Error } // CancelOrder 取消订单(仅限本人且仅待支付状态可取消) func (s *OrderService) CancelOrder(userID, id uint) error { result := s.db.Model(&model.Order{}). Where("id = ? AND user_id = ? AND status = ?", id, userID, "pending"). Update("status", "cancelled") if result.Error != nil { return result.Error } if result.RowsAffected == 0 { return errors.New("订单不存在或当前状态不可取消") } return nil } // CheckOrderExpired 检查订单是否过期 func (s *OrderService) CheckOrderExpired(order *model.Order) bool { if order.ExpireTime == nil { return false } return time.Now().After(*order.ExpireTime) } // CreateWechatPayOrder 创建微信支付订单 func (s *OrderService) CreateWechatPayOrder(order *model.Order, openID string) (map[string]string, error) { // TODO: 实现微信支付下单逻辑 // 这里返回模拟数据 payParams := map[string]string{ "timeStamp": fmt.Sprintf("%d", time.Now().Unix()), "nonceStr": s.generateNonceStr(), "package": fmt.Sprintf("prepay_id=wx%s", order.OrderNo), "signType": "MD5", "paySign": s.generatePaySign(order.OrderNo), } return payParams, nil } // generateNonceStr 生成随机字符串 func (s *OrderService) generateNonceStr() string { return fmt.Sprintf("%d", time.Now().UnixNano()) } // generatePaySign 生成支付签名 func (s *OrderService) generatePaySign(orderNo string) string { // TODO: 实现真实的微信支付签名 hash := md5.Sum([]byte(orderNo + "secret")) return hex.EncodeToString(hash[:]) } // HandlePayNotify 处理支付回调(幂等:已支付订单不重复处理) func (s *OrderService) HandlePayNotify(orderNo, transactionID string) error { order, err := s.GetOrderByOrderNo(orderNo) if err != nil { return fmt.Errorf("order not found: %w", err) } // 幂等:已支付直接返回成功 if order.Status == "paid" { return nil } if order.Status != "pending" { return fmt.Errorf("order %s in unexpected status %s", orderNo, order.Status) } // 条件更新防止并发重复入账 updates := map[string]interface{}{ "status": "paid", "pay_time": time.Now(), "remark": order.Remark + " [tx:" + transactionID + "]", } result := s.db.Model(&model.Order{}). Where("order_no = ? AND status = ?", orderNo, "pending"). Updates(updates) if result.Error != nil { return result.Error } if result.RowsAffected == 0 { // 并发下已被其他回调处理,视为幂等成功 return nil } // 支付成功后才创建付费许愿 if order.Type == "wish" && order.Remark != "" { wishService := NewWishService() wish := &model.Wish{ UserID: order.UserID, TreeID: 1, // 默认祈福树 Content: order.Remark, Type: "paid", Status: 1, } if err := wishService.CreateWish(wish); err != nil { // 许愿创建失败不回滚支付状态,由后台补处理 log.Printf("create paid wish for order %s failed: %v", orderNo, err) } } return nil }