From 6618e35869bb5da15f836649ce9dad67ea3f48dd Mon Sep 17 00:00:00 2001 From: 18278715334 <18278715334@163.com> Date: Wed, 14 Jan 2026 15:59:15 +0800 Subject: [PATCH] -f --- .../product/component_report_order_service.go | 95 ++++++++++--------- .../entities/component_report_download.go | 4 + internal/shared/component_report/handler.go | 60 ++++++++---- 3 files changed, 93 insertions(+), 66 deletions(-) diff --git a/internal/application/product/component_report_order_service.go b/internal/application/product/component_report_order_service.go index 74c8395..25ed3a5 100644 --- a/internal/application/product/component_report_order_service.go +++ b/internal/application/product/component_report_order_service.go @@ -565,13 +565,14 @@ func (s *ComponentReportOrderService) createFreeOrder( // 创建下载记录 download := &productEntities.ComponentReportDownload{ - UserID: req.UserID, - ProductID: req.ProductID, - ProductCode: product.Code, - ProductName: product.Name, - OrderID: &createdPurchaseOrder.ID, // 关联购买订单ID - OrderNumber: &createdPurchaseOrder.OrderNo, // 外部订单号 - ExpiresAt: calculateExpiryTime(), // 30天后过期 + UserID: req.UserID, + ProductID: req.ProductID, + ProductCode: product.Code, + ProductName: product.Name, + OrderID: &createdPurchaseOrder.ID, // 关联购买订单ID + OrderNumber: &createdPurchaseOrder.OrderNo, // 外部订单号 + DownloadPrice: finalPrice, // 设置下载价格 + ExpiresAt: calculateExpiryTime(), // 30天后过期 } err = s.componentReportRepo.Create(ctx, download) @@ -735,7 +736,7 @@ func (s *ComponentReportOrderService) CheckPaymentStatus(ctx context.Context, or // DownloadFile 下载文件 func (s *ComponentReportOrderService) DownloadFile(ctx context.Context, orderID string) (string, error) { s.logger.Info("开始下载文件", zap.String("order_id", orderID)) - + // 首先通过orderID查询购买订单 purchaseOrder, err := s.purchaseOrderRepo.GetByID(ctx, orderID) if err != nil { @@ -747,70 +748,71 @@ func (s *ComponentReportOrderService) DownloadFile(ctx context.Context, orderID s.logger.Error("购买订单不存在", zap.String("order_id", orderID)) return "", fmt.Errorf("购买订单不存在") } - + // 检查购买订单状态 if purchaseOrder.Status != entities.PurchaseOrderStatusPaid { - s.logger.Error("订单未支付,无法下载文件", - zap.String("order_id", orderID), + s.logger.Error("订单未支付,无法下载文件", + zap.String("order_id", orderID), zap.String("status", string(purchaseOrder.Status))) return "", fmt.Errorf("订单未支付,无法下载文件") } - + // 获取产品信息 product, err := s.productRepo.GetByID(ctx, purchaseOrder.ProductID) if err != nil { s.logger.Error("获取产品信息失败", zap.Error(err), zap.String("product_id", purchaseOrder.ProductID)) return "", fmt.Errorf("获取产品信息失败: %w", err) } - + // 检查是否已有下载记录 download, err := s.componentReportRepo.GetDownloadByPaymentOrderID(ctx, orderID) if err != nil { s.logger.Warn("查询下载记录失败,将创建新记录", zap.Error(err), zap.String("order_id", orderID)) download = nil } - + // 如果没有下载记录,创建一个新的 if download == nil { - s.logger.Info("创建新的下载记录", + s.logger.Info("创建新的下载记录", zap.String("order_id", orderID), zap.String("user_id", purchaseOrder.UserID), zap.String("product_id", purchaseOrder.ProductID)) - + // 创建新的下载记录 newDownload := &productEntities.ComponentReportDownload{ - UserID: purchaseOrder.UserID, - ProductID: purchaseOrder.ProductID, - ProductCode: product.Code, - ProductName: product.Name, - OrderID: &purchaseOrder.ID, - OrderNumber: &purchaseOrder.OrderNo, - ExpiresAt: calculateExpiryTime(), + UserID: purchaseOrder.UserID, + ProductID: purchaseOrder.ProductID, + ProductCode: product.Code, + ProductName: product.Name, + OrderID: &purchaseOrder.ID, + OrderNumber: &purchaseOrder.OrderNo, + DownloadPrice: purchaseOrder.Amount, // 设置下载价格(从订单获取) + ExpiresAt: calculateExpiryTime(), } - + // 保存下载记录 err = s.componentReportRepo.Create(ctx, newDownload) if err != nil { s.logger.Error("创建下载记录失败", zap.Error(err)) return "", fmt.Errorf("创建下载记录失败: %w", err) } - + s.logger.Info("成功创建下载记录", zap.String("order_id", orderID), zap.String("download_id", newDownload.ID), zap.String("product_id", newDownload.ProductID)) - + download = newDownload } - + // 检查是否过期 if download.IsExpired() { - s.logger.Error("下载链接已过期", + s.logger.Error("下载链接已过期", zap.String("order_id", orderID), zap.Time("expires_at", *download.ExpiresAt)) return "", fmt.Errorf("下载链接已过期,无法下载文件") } - + // 检查文件是否已存在 if download.FilePath != nil && *download.FilePath != "" { // 文件已存在,直接返回文件路径 @@ -897,7 +899,7 @@ func (s *ComponentReportOrderService) createDownloadRecordForPaidOrder(ctx conte zap.String("order_no", purchaseOrder.OrderNo), zap.String("user_id", purchaseOrder.UserID), zap.String("product_id", purchaseOrder.ProductID)) - + // 检查是否已有下载记录 existingDownload, err := s.componentReportRepo.GetDownloadByPaymentOrderID(ctx, purchaseOrder.ID) if err == nil && existingDownload != nil { @@ -906,41 +908,42 @@ func (s *ComponentReportOrderService) createDownloadRecordForPaidOrder(ctx conte zap.String("download_id", existingDownload.ID)) return nil } - + // 获取产品信息 product, err := s.productRepo.GetByID(ctx, purchaseOrder.ProductID) if err != nil { - s.logger.Error("获取产品信息失败", - zap.Error(err), + s.logger.Error("获取产品信息失败", + zap.Error(err), zap.String("product_id", purchaseOrder.ProductID)) return fmt.Errorf("获取产品信息失败: %w", err) } - + // 创建新的下载记录 download := &productEntities.ComponentReportDownload{ - UserID: purchaseOrder.UserID, - ProductID: purchaseOrder.ProductID, - ProductCode: product.Code, - ProductName: product.Name, - OrderID: &purchaseOrder.ID, - OrderNumber: &purchaseOrder.OrderNo, - ExpiresAt: calculateExpiryTime(), // 30天后过期 + UserID: purchaseOrder.UserID, + ProductID: purchaseOrder.ProductID, + ProductCode: product.Code, + ProductName: product.Name, + OrderID: &purchaseOrder.ID, + OrderNumber: &purchaseOrder.OrderNo, + DownloadPrice: purchaseOrder.Amount, // 设置下载价格(从订单获取) + ExpiresAt: calculateExpiryTime(), // 30天后过期 } - + // 保存下载记录 err = s.componentReportRepo.Create(ctx, download) if err != nil { s.logger.Error("创建下载记录失败", zap.Error(err)) return fmt.Errorf("创建下载记录失败: %w", err) } - + s.logger.Info("成功为已支付订单创建下载记录", zap.String("purchase_order_id", purchaseOrder.ID), zap.String("order_no", purchaseOrder.OrderNo), zap.String("download_id", download.ID), zap.String("product_id", download.ProductID), zap.String("user_id", download.UserID)) - + return nil } @@ -1121,7 +1124,7 @@ func (s *ComponentReportOrderService) queryAlipayOrderStatusAndUpdate(ctx contex zap.String("order_no", purchaseOrder.OrderNo), zap.String("status", "paid"), ) - + // 支付成功后,自动创建下载记录 err = s.createDownloadRecordForPaidOrder(ctx, purchaseOrder) if err != nil { @@ -1296,7 +1299,7 @@ func (s *ComponentReportOrderService) queryWechatOrderStatusAndUpdate(ctx contex zap.String("order_no", purchaseOrder.OrderNo), zap.String("status", "paid"), ) - + // 支付成功后,自动创建下载记录 err = s.createDownloadRecordForPaidOrder(ctx, purchaseOrder) if err != nil { diff --git a/internal/domains/product/entities/component_report_download.go b/internal/domains/product/entities/component_report_download.go index b43d480..a45b503 100644 --- a/internal/domains/product/entities/component_report_download.go +++ b/internal/domains/product/entities/component_report_download.go @@ -4,6 +4,7 @@ import ( "time" "github.com/google/uuid" + "github.com/shopspring/decimal" "gorm.io/gorm" ) @@ -22,6 +23,9 @@ type ComponentReportDownload struct { SubProductIDs string `gorm:"type:text" comment:"子产品ID列表(JSON数组,组合包使用)"` SubProductCodes string `gorm:"type:text" comment:"子产品编号列表(JSON数组)"` + // 价格相关字段 + DownloadPrice decimal.Decimal `gorm:"type:decimal(10,2);not null" comment:"实际支付价格"` + // 下载相关信息 FilePath *string `gorm:"type:varchar(500)" comment:"生成的ZIP文件路径(用于二次下载)"` FileHash *string `gorm:"type:varchar(64)" comment:"文件哈希值(用于缓存验证)"` diff --git a/internal/shared/component_report/handler.go b/internal/shared/component_report/handler.go index 587f6f8..7bbc15c 100644 --- a/internal/shared/component_report/handler.go +++ b/internal/shared/component_report/handler.go @@ -333,20 +333,20 @@ func (h *ComponentReportHandler) GenerateAndDownloadZip(c *gin.Context) { // 如果有待支付订单,尝试主动查询支付状态 if pendingOrder != nil { - h.logger.Info("发现待支付订单,尝试主动查询支付状态", + h.logger.Info("发现待支付订单,尝试主动查询支付状态", zap.String("order_id", pendingOrder.ID), zap.String("pay_channel", pendingOrder.PayChannel)) // 如果是支付宝订单,主动查询状态 if pendingOrder.PayChannel == "alipay" && h.aliPayService != nil { // 这里可以调用支付宝查询服务,但为了简化,我们只记录日志 - h.logger.Info("支付宝订单状态待查询,但当前实现简化处理", + h.logger.Info("支付宝订单状态待查询,但当前实现简化处理", zap.String("order_id", pendingOrder.ID)) } // 如果是微信订单,主动查询状态 if pendingOrder.PayChannel == "wechat" && h.wechatPayService != nil { // 这里可以调用微信查询服务,但为了简化,我们只记录日志 - h.logger.Info("微信订单状态待查询,但当前实现简化处理", + h.logger.Info("微信订单状态待查询,但当前实现简化处理", zap.String("order_id", pendingOrder.ID)) } } @@ -397,9 +397,14 @@ func (h *ComponentReportHandler) GenerateAndDownloadZip(c *gin.Context) { } }() + // 创建带超时的上下文,避免ZIP生成时间过长导致网关超时 + // 设置超时时间为 25 秒,略小于服务器的 write_timeout (30秒) + ctx, cancel := context.WithTimeout(c.Request.Context(), 25*time.Second) + defer cancel() + // 生成ZIP文件 zipPath, err := h.zipGenerator.GenerateZipFile( - c.Request.Context(), + ctx, req.ProductID, req.SubProductCodes, h.exampleJSONGenerator, @@ -407,6 +412,18 @@ func (h *ComponentReportHandler) GenerateAndDownloadZip(c *gin.Context) { ) if err != nil { h.logger.Error("生成ZIP文件失败", zap.Error(err), zap.String("product_id", req.ProductID)) + + // 检查是否是超时错误 + if ctx.Err() == context.DeadlineExceeded { + h.logger.Error("ZIP文件生成超时", zap.String("product_id", req.ProductID)) + c.JSON(http.StatusRequestTimeout, gin.H{ + "code": 504, + "message": "文件生成超时,请稍后重试", + "error": "请求处理时间过长", + }) + return + } + c.JSON(http.StatusInternalServerError, gin.H{ "code": 500, "message": "生成ZIP文件失败", @@ -987,8 +1004,9 @@ func (h *ComponentReportHandler) CreatePaymentOrder(c *gin.Context) { SubProductIDs: string(subProductIDsJSON), SubProductCodes: string(subProductCodesJSON), // 关联购买订单ID - OrderID: &createdPurchaseOrder.ID, - OrderNumber: &outTradeNo, + OrderID: &createdPurchaseOrder.ID, + OrderNumber: &outTradeNo, + DownloadPrice: finalPrice, // 设置下载价格 } // 记录创建前的详细信息用于调试 @@ -1384,13 +1402,14 @@ func (h *ComponentReportHandler) createDownloadRecordIfEligible(ctx context.Cont // 3. 创建下载记录 download := &entities.ComponentReportDownload{ - UserID: userID, - ProductID: productID, - ProductCode: product.Code, - ProductName: product.Name, - OrderID: &validOrder.ID, // 添加OrderID字段 - OrderNumber: &validOrder.OrderNo, // 使用OrderNumber字段 - ExpiresAt: calculateExpiryTime(), // 从创建日起30天 + UserID: userID, + ProductID: productID, + ProductCode: product.Code, + ProductName: product.Name, + OrderID: &validOrder.ID, // 添加OrderID字段 + OrderNumber: &validOrder.OrderNo, // 使用OrderNumber字段 + DownloadPrice: validOrder.Amount, // 设置下载价格(从订单获取) + ExpiresAt: calculateExpiryTime(), // 从创建日起30天 } // 4. 如果是组合包,获取子产品信息 @@ -1562,13 +1581,14 @@ func (h *ComponentReportHandler) createDownloadRecordForPaidOrder(ctx context.Co // 创建下载记录 download := &entities.ComponentReportDownload{ - UserID: order.UserID, - ProductID: order.ProductID, - ProductCode: order.ProductCode, - ProductName: order.ProductName, - OrderID: &order.ID, - OrderNumber: &order.OrderNo, - ExpiresAt: calculateExpiryTime(), + UserID: order.UserID, + ProductID: order.ProductID, + ProductCode: order.ProductCode, + ProductName: order.ProductName, + OrderID: &order.ID, + OrderNumber: &order.OrderNo, + DownloadPrice: order.Amount, // 设置下载价格(从订单获取) + ExpiresAt: calculateExpiryTime(), } // 如果是组合包,获取子产品信息