-f
This commit is contained in:
@@ -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 {
|
||||
|
||||
@@ -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:"文件哈希值(用于缓存验证)"`
|
||||
|
||||
@@ -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(),
|
||||
}
|
||||
|
||||
// 如果是组合包,获取子产品信息
|
||||
|
||||
Reference in New Issue
Block a user