817 lines
22 KiB
Go
817 lines
22 KiB
Go
package provider
|
||
|
||
import (
|
||
"context"
|
||
"fmt"
|
||
"time"
|
||
|
||
"dubbo.apache.org/dubbo-go/v3/common/constant"
|
||
appErrors "github.com/topfans/backend/pkg/errors"
|
||
"github.com/topfans/backend/pkg/logger"
|
||
"github.com/topfans/backend/pkg/models"
|
||
pb "github.com/topfans/backend/pkg/proto/asset"
|
||
pbCommon "github.com/topfans/backend/pkg/proto/common"
|
||
"github.com/topfans/backend/services/assetService/service"
|
||
"go.uber.org/zap"
|
||
)
|
||
|
||
// AssetProvider 资产服务Provider实现
|
||
// 实现 Triple 协议生成的 AssetServiceHandler 接口
|
||
type AssetProvider struct {
|
||
assetService service.AssetService
|
||
mintService service.MintService
|
||
assetLikeService *service.AssetLikeService
|
||
}
|
||
|
||
// 确保 AssetProvider 实现了 AssetServiceHandler 接口
|
||
var _ pb.AssetServiceHandler = (*AssetProvider)(nil)
|
||
|
||
// NewAssetProvider 创建资产服务Provider实例
|
||
func NewAssetProvider(assetService service.AssetService, mintService service.MintService, assetLikeService *service.AssetLikeService) *AssetProvider {
|
||
return &AssetProvider{
|
||
assetService: assetService,
|
||
mintService: mintService,
|
||
assetLikeService: assetLikeService,
|
||
}
|
||
}
|
||
|
||
// InitMintOrder 阶段一:初始化订单(仅落库 order_id)
|
||
func (p *AssetProvider) InitMintOrder(ctx context.Context, req *pb.InitMintOrderRequest) (*pb.InitMintOrderResponse, error) {
|
||
userID, starID, err := extractUserInfoFromDubboAttachments(ctx)
|
||
if err != nil {
|
||
return &pb.InitMintOrderResponse{
|
||
Base: &pbCommon.BaseResponse{
|
||
Code: pbCommon.StatusCode_STATUS_UNAUTHORIZED,
|
||
Message: "user authentication required",
|
||
Timestamp: 0,
|
||
},
|
||
}, err
|
||
}
|
||
|
||
resp, err := p.mintService.InitMintOrder(req.OrderId, userID, starID)
|
||
if err != nil {
|
||
if resp == nil {
|
||
resp = &pb.InitMintOrderResponse{
|
||
Base: &pbCommon.BaseResponse{
|
||
Code: appErrors.ToStatusCode(err),
|
||
Message: err.Error(),
|
||
Timestamp: 0,
|
||
},
|
||
}
|
||
}
|
||
return resp, err
|
||
}
|
||
return resp, nil
|
||
}
|
||
|
||
// PreCreateMintOrder 阶段一:预创建铸造订单(生成 order_id)
|
||
func (p *AssetProvider) PreCreateMintOrder(ctx context.Context, req *pb.PreCreateMintOrderRequest) (*pb.PreCreateMintOrderResponse, error) {
|
||
logger.Logger.Info("Received PreCreateMintOrder request",
|
||
zap.String("material_url", req.MaterialUrl),
|
||
)
|
||
|
||
userID, starID, err := extractUserInfoFromDubboAttachments(ctx)
|
||
if err != nil {
|
||
return &pb.PreCreateMintOrderResponse{
|
||
Base: &pbCommon.BaseResponse{
|
||
Code: pbCommon.StatusCode_STATUS_UNAUTHORIZED,
|
||
Message: "user authentication required",
|
||
Timestamp: 0,
|
||
},
|
||
}, err
|
||
}
|
||
|
||
resp, err := p.mintService.PreCreateMintOrder(req, userID, starID)
|
||
if err != nil {
|
||
logger.Logger.Error("PreCreateMintOrder failed",
|
||
zap.Int64("user_id", userID),
|
||
zap.Int64("star_id", starID),
|
||
zap.Error(err),
|
||
)
|
||
if resp == nil {
|
||
resp = &pb.PreCreateMintOrderResponse{
|
||
Base: &pbCommon.BaseResponse{
|
||
Code: appErrors.ToStatusCode(err),
|
||
Message: err.Error(),
|
||
Timestamp: 0,
|
||
},
|
||
}
|
||
}
|
||
return resp, err
|
||
}
|
||
|
||
logger.Logger.Info("PreCreateMintOrder successful",
|
||
zap.Int64("user_id", userID),
|
||
zap.Int64("star_id", starID),
|
||
zap.String("order_id", resp.Order.OrderId),
|
||
)
|
||
|
||
return resp, nil
|
||
}
|
||
|
||
// CreateMintOrder 创建铸造订单
|
||
func (p *AssetProvider) CreateMintOrder(ctx context.Context, req *pb.CreateMintOrderRequest) (*pb.CreateMintOrderResponse, error) {
|
||
// 记录请求日志
|
||
logger.Logger.Info("Received CreateMintOrder request",
|
||
zap.String("name", req.Name),
|
||
)
|
||
|
||
// 从 Dubbo attachments 获取用户信息(网关已验证并传递)
|
||
userID, starID, err := extractUserInfoFromDubboAttachments(ctx)
|
||
if err != nil {
|
||
logger.Logger.Error("Failed to extract user info from attachments",
|
||
zap.Error(err),
|
||
)
|
||
return &pb.CreateMintOrderResponse{
|
||
Base: &pbCommon.BaseResponse{
|
||
Code: pbCommon.StatusCode_STATUS_UNAUTHORIZED,
|
||
Message: "user authentication required",
|
||
Timestamp: 0,
|
||
},
|
||
}, err
|
||
}
|
||
|
||
// 调用Service层
|
||
resp, err := p.mintService.CreateMintOrder(req, userID, starID)
|
||
if err != nil {
|
||
logger.Logger.Error("CreateMintOrder failed",
|
||
zap.Int64("user_id", userID),
|
||
zap.Int64("star_id", starID),
|
||
zap.Error(err),
|
||
)
|
||
|
||
// 如果响应为空,构建错误响应
|
||
if resp == nil {
|
||
resp = &pb.CreateMintOrderResponse{
|
||
Base: &pbCommon.BaseResponse{
|
||
Code: appErrors.ToStatusCode(err),
|
||
Message: err.Error(),
|
||
Timestamp: 0,
|
||
},
|
||
}
|
||
}
|
||
|
||
return resp, err
|
||
}
|
||
|
||
logger.Logger.Info("CreateMintOrder successful",
|
||
zap.Int64("user_id", userID),
|
||
zap.Int64("star_id", starID),
|
||
zap.String("order_id", resp.Order.OrderId),
|
||
)
|
||
|
||
return resp, nil
|
||
}
|
||
|
||
// GetMyAssets 获取我的藏品列表
|
||
func (p *AssetProvider) GetMyAssets(ctx context.Context, req *pb.GetMyAssetsRequest) (*pb.GetMyAssetsResponse, error) {
|
||
// 记录请求日志
|
||
logger.Logger.Info("Received GetMyAssets request",
|
||
zap.Int32("page", req.Page),
|
||
zap.Int32("page_size", req.PageSize),
|
||
)
|
||
|
||
// 从 Dubbo attachments 获取用户信息(网关已验证并传递)
|
||
userID, starID, err := extractUserInfoFromDubboAttachments(ctx)
|
||
if err != nil {
|
||
logger.Logger.Error("Failed to extract user info from attachments",
|
||
zap.Error(err),
|
||
)
|
||
return &pb.GetMyAssetsResponse{
|
||
Base: &pbCommon.BaseResponse{
|
||
Code: pbCommon.StatusCode_STATUS_UNAUTHORIZED,
|
||
Message: "user authentication required",
|
||
Timestamp: 0,
|
||
},
|
||
}, err
|
||
}
|
||
|
||
// 调用Service层
|
||
resp, err := p.assetService.GetMyAssets(req, userID, starID)
|
||
if err != nil {
|
||
logger.Logger.Error("GetMyAssets failed",
|
||
zap.Int64("user_id", userID),
|
||
zap.Int64("star_id", starID),
|
||
zap.Error(err),
|
||
)
|
||
|
||
// 如果响应为空,构建错误响应
|
||
if resp == nil {
|
||
resp = &pb.GetMyAssetsResponse{
|
||
Base: &pbCommon.BaseResponse{
|
||
Code: appErrors.ToStatusCode(err),
|
||
Message: err.Error(),
|
||
Timestamp: 0,
|
||
},
|
||
}
|
||
}
|
||
|
||
return resp, err
|
||
}
|
||
|
||
logger.Logger.Debug("GetMyAssets successful",
|
||
zap.Int64("user_id", userID),
|
||
zap.Int64("star_id", starID),
|
||
zap.Int("count", len(resp.Items)),
|
||
)
|
||
|
||
return resp, nil
|
||
}
|
||
|
||
// GetAsset 获取资产详情
|
||
func (p *AssetProvider) GetAsset(ctx context.Context, req *pb.GetAssetRequest) (*pb.GetAssetResponse, error) {
|
||
// 记录请求日志
|
||
logger.Logger.Info("Received GetAsset request",
|
||
zap.Int64("asset_id", req.AssetId),
|
||
)
|
||
|
||
// 从 Dubbo attachments 获取用户信息(网关已验证并传递)
|
||
userID, starID, err := extractUserInfoFromDubboAttachments(ctx)
|
||
if err != nil {
|
||
logger.Logger.Error("Failed to extract user info from attachments",
|
||
zap.Error(err),
|
||
)
|
||
return &pb.GetAssetResponse{
|
||
Base: &pbCommon.BaseResponse{
|
||
Code: pbCommon.StatusCode_STATUS_UNAUTHORIZED,
|
||
Message: "user authentication required",
|
||
Timestamp: 0,
|
||
},
|
||
}, err
|
||
}
|
||
|
||
// 调用Service层
|
||
resp, err := p.assetService.GetAsset(req, userID, starID)
|
||
if err != nil {
|
||
logger.Logger.Error("GetAsset failed",
|
||
zap.Int64("user_id", userID),
|
||
zap.Int64("star_id", starID),
|
||
zap.Int64("asset_id", req.AssetId),
|
||
zap.Error(err),
|
||
)
|
||
|
||
// 如果响应为空,构建错误响应
|
||
if resp == nil {
|
||
resp = &pb.GetAssetResponse{
|
||
Base: &pbCommon.BaseResponse{
|
||
Code: appErrors.ToStatusCode(err),
|
||
Message: err.Error(),
|
||
Timestamp: 0,
|
||
},
|
||
}
|
||
}
|
||
|
||
return resp, err
|
||
}
|
||
|
||
logger.Logger.Debug("GetAsset successful",
|
||
zap.Int64("user_id", userID),
|
||
zap.Int64("asset_id", req.AssetId),
|
||
)
|
||
|
||
return resp, nil
|
||
}
|
||
|
||
// GetAssetStatus 查询上链状态
|
||
func (p *AssetProvider) GetAssetStatus(ctx context.Context, req *pb.GetAssetStatusRequest) (*pb.GetAssetStatusResponse, error) {
|
||
// 记录请求日志
|
||
logger.Logger.Info("Received GetAssetStatus request",
|
||
zap.Int64("asset_id", req.AssetId),
|
||
)
|
||
|
||
// 从 Dubbo attachments 获取用户信息(网关已验证并传递)
|
||
userID, starID, err := extractUserInfoFromDubboAttachments(ctx)
|
||
if err != nil {
|
||
logger.Logger.Error("Failed to extract user info from attachments",
|
||
zap.Error(err),
|
||
)
|
||
return &pb.GetAssetStatusResponse{
|
||
Base: &pbCommon.BaseResponse{
|
||
Code: pbCommon.StatusCode_STATUS_UNAUTHORIZED,
|
||
Message: "user authentication required",
|
||
Timestamp: 0,
|
||
},
|
||
}, err
|
||
}
|
||
|
||
// 调用Service层
|
||
resp, err := p.assetService.GetAssetStatus(req, userID, starID)
|
||
if err != nil {
|
||
logger.Logger.Error("GetAssetStatus failed",
|
||
zap.Int64("user_id", userID),
|
||
zap.Int64("star_id", starID),
|
||
zap.Int64("asset_id", req.AssetId),
|
||
zap.Error(err),
|
||
)
|
||
|
||
// 如果响应为空,构建错误响应
|
||
if resp == nil {
|
||
resp = &pb.GetAssetStatusResponse{
|
||
Base: &pbCommon.BaseResponse{
|
||
Code: appErrors.ToStatusCode(err),
|
||
Message: err.Error(),
|
||
Timestamp: 0,
|
||
},
|
||
}
|
||
}
|
||
|
||
return resp, err
|
||
}
|
||
|
||
logger.Logger.Debug("GetAssetStatus successful",
|
||
zap.Int64("user_id", userID),
|
||
zap.Int64("asset_id", req.AssetId),
|
||
)
|
||
|
||
return resp, nil
|
||
}
|
||
|
||
// GetAssetForRPC 获取资产信息(内部RPC调用)
|
||
func (p *AssetProvider) GetAssetForRPC(ctx context.Context, req *pb.GetAssetForRPCRequest) (*pb.GetAssetForRPCResponse, error) {
|
||
logger.Logger.Info("Received GetAssetForRPC request",
|
||
zap.Int64("asset_id", req.AssetId),
|
||
)
|
||
|
||
// 调用Service层
|
||
resp, err := p.assetService.GetAssetForRPC(req)
|
||
if err != nil {
|
||
logger.Logger.Error("GetAssetForRPC failed",
|
||
zap.Int64("asset_id", req.AssetId),
|
||
zap.Error(err),
|
||
)
|
||
|
||
// 如果响应为空,构建错误响应
|
||
if resp == nil {
|
||
resp = &pb.GetAssetForRPCResponse{
|
||
Base: &pbCommon.BaseResponse{
|
||
Code: appErrors.ToStatusCode(err),
|
||
Message: err.Error(),
|
||
Timestamp: 0,
|
||
},
|
||
}
|
||
}
|
||
|
||
return resp, err
|
||
}
|
||
|
||
logger.Logger.Info("GetAssetForRPC successful",
|
||
zap.Int64("asset_id", req.AssetId),
|
||
)
|
||
|
||
return resp, nil
|
||
}
|
||
|
||
// LikeAsset 点赞资产(内部RPC调用)
|
||
func (p *AssetProvider) LikeAsset(ctx context.Context, req *pb.LikeAssetRequest) (*pb.LikeAssetResponse, error) {
|
||
logger.Logger.Info("Received LikeAsset request",
|
||
zap.Int64("asset_id", req.AssetId),
|
||
)
|
||
|
||
// 从 Dubbo attachments 获取用户信息
|
||
userID, starID, err := extractUserInfoFromDubboAttachments(ctx)
|
||
if err != nil {
|
||
logger.Logger.Error("Failed to extract user info from attachments",
|
||
zap.Error(err),
|
||
)
|
||
return &pb.LikeAssetResponse{
|
||
Base: &pbCommon.BaseResponse{
|
||
Code: pbCommon.StatusCode_STATUS_UNAUTHORIZED,
|
||
Message: "user authentication required",
|
||
Timestamp: 0,
|
||
},
|
||
}, err
|
||
}
|
||
|
||
// 调用Service层
|
||
likeCount, err := p.assetLikeService.LikeAsset(ctx, req.AssetId, userID, starID)
|
||
if err != nil {
|
||
logger.Logger.Error("LikeAsset failed",
|
||
zap.Int64("user_id", userID),
|
||
zap.Int64("asset_id", req.AssetId),
|
||
zap.Error(err),
|
||
)
|
||
return &pb.LikeAssetResponse{
|
||
Base: &pbCommon.BaseResponse{
|
||
Code: appErrors.ToStatusCode(err),
|
||
Message: err.Error(),
|
||
Timestamp: 0,
|
||
},
|
||
}, err
|
||
}
|
||
|
||
logger.Logger.Info("LikeAsset successful",
|
||
zap.Int64("user_id", userID),
|
||
zap.Int64("asset_id", req.AssetId),
|
||
zap.Int32("like_count", likeCount),
|
||
)
|
||
|
||
return &pb.LikeAssetResponse{
|
||
Base: &pbCommon.BaseResponse{
|
||
Code: pbCommon.StatusCode_STATUS_OK,
|
||
Message: "Asset liked successfully",
|
||
Timestamp: 0,
|
||
},
|
||
LikeCount: likeCount,
|
||
}, nil
|
||
}
|
||
|
||
// UnlikeAsset 取消点赞资产(内部RPC调用)
|
||
func (p *AssetProvider) UnlikeAsset(ctx context.Context, req *pb.UnlikeAssetRequest) (*pb.UnlikeAssetResponse, error) {
|
||
logger.Logger.Info("Received UnlikeAsset request",
|
||
zap.Int64("asset_id", req.AssetId),
|
||
)
|
||
|
||
// 从 Dubbo attachments 获取用户信息
|
||
userID, starID, err := extractUserInfoFromDubboAttachments(ctx)
|
||
if err != nil {
|
||
logger.Logger.Error("Failed to extract user info from attachments",
|
||
zap.Error(err),
|
||
)
|
||
return &pb.UnlikeAssetResponse{
|
||
Base: &pbCommon.BaseResponse{
|
||
Code: pbCommon.StatusCode_STATUS_UNAUTHORIZED,
|
||
Message: "user authentication required",
|
||
Timestamp: 0,
|
||
},
|
||
}, err
|
||
}
|
||
|
||
// 调用Service层
|
||
likeCount, err := p.assetLikeService.UnlikeAsset(ctx, req.AssetId, userID, starID)
|
||
if err != nil {
|
||
logger.Logger.Error("UnlikeAsset failed",
|
||
zap.Int64("user_id", userID),
|
||
zap.Int64("asset_id", req.AssetId),
|
||
zap.Error(err),
|
||
)
|
||
return &pb.UnlikeAssetResponse{
|
||
Base: &pbCommon.BaseResponse{
|
||
Code: appErrors.ToStatusCode(err),
|
||
Message: err.Error(),
|
||
Timestamp: 0,
|
||
},
|
||
}, err
|
||
}
|
||
|
||
logger.Logger.Info("UnlikeAsset successful",
|
||
zap.Int64("user_id", userID),
|
||
zap.Int64("asset_id", req.AssetId),
|
||
zap.Int32("like_count", likeCount),
|
||
)
|
||
|
||
return &pb.UnlikeAssetResponse{
|
||
Base: &pbCommon.BaseResponse{
|
||
Code: pbCommon.StatusCode_STATUS_OK,
|
||
Message: "Asset unliked successfully",
|
||
Timestamp: 0,
|
||
},
|
||
LikeCount: likeCount,
|
||
}, nil
|
||
}
|
||
|
||
// CheckAssetLike 检查是否已点赞(内部RPC调用)
|
||
func (p *AssetProvider) CheckAssetLike(ctx context.Context, req *pb.CheckAssetLikeRequest) (*pb.CheckAssetLikeResponse, error) {
|
||
logger.Logger.Info("Received CheckAssetLike request",
|
||
zap.Int64("asset_id", req.AssetId),
|
||
)
|
||
|
||
// 从 Dubbo attachments 获取用户信息
|
||
userID, starID, err := extractUserInfoFromDubboAttachments(ctx)
|
||
if err != nil {
|
||
logger.Logger.Error("Failed to extract user info from attachments",
|
||
zap.Error(err),
|
||
)
|
||
return &pb.CheckAssetLikeResponse{
|
||
Base: &pbCommon.BaseResponse{
|
||
Code: pbCommon.StatusCode_STATUS_UNAUTHORIZED,
|
||
Message: "user authentication required",
|
||
Timestamp: 0,
|
||
},
|
||
}, err
|
||
}
|
||
|
||
// 调用Service层
|
||
isLiked, err := p.assetLikeService.CheckAssetLike(ctx, req.AssetId, userID, starID)
|
||
if err != nil {
|
||
logger.Logger.Error("CheckAssetLike failed",
|
||
zap.Int64("user_id", userID),
|
||
zap.Int64("asset_id", req.AssetId),
|
||
zap.Error(err),
|
||
)
|
||
return &pb.CheckAssetLikeResponse{
|
||
Base: &pbCommon.BaseResponse{
|
||
Code: appErrors.ToStatusCode(err),
|
||
Message: err.Error(),
|
||
Timestamp: 0,
|
||
},
|
||
}, err
|
||
}
|
||
|
||
logger.Logger.Info("CheckAssetLike successful",
|
||
zap.Int64("user_id", userID),
|
||
zap.Int64("asset_id", req.AssetId),
|
||
zap.Bool("is_liked", isLiked),
|
||
)
|
||
|
||
return &pb.CheckAssetLikeResponse{
|
||
Base: &pbCommon.BaseResponse{
|
||
Code: pbCommon.StatusCode_STATUS_OK,
|
||
Message: "Success",
|
||
Timestamp: 0,
|
||
},
|
||
IsLiked: isLiked,
|
||
}, nil
|
||
}
|
||
|
||
// GetAssetLikes 获取资产点赞列表(内部RPC调用)
|
||
func (p *AssetProvider) GetAssetLikes(ctx context.Context, req *pb.GetAssetLikesRequest) (*pb.GetAssetLikesResponse, error) {
|
||
logger.Logger.Info("Received GetAssetLikes request",
|
||
zap.Int64("asset_id", req.AssetId),
|
||
zap.Int32("page", req.Page),
|
||
zap.Int32("page_size", req.PageSize),
|
||
)
|
||
|
||
// 调用Service层
|
||
likes, total, err := p.assetLikeService.GetAssetLikes(ctx, req.AssetId, req.Page, req.PageSize)
|
||
if err != nil {
|
||
logger.Logger.Error("GetAssetLikes failed",
|
||
zap.Int64("asset_id", req.AssetId),
|
||
zap.Error(err),
|
||
)
|
||
return &pb.GetAssetLikesResponse{
|
||
Base: &pbCommon.BaseResponse{
|
||
Code: appErrors.ToStatusCode(err),
|
||
Message: err.Error(),
|
||
Timestamp: 0,
|
||
},
|
||
}, err
|
||
}
|
||
|
||
// 转换为 pb.AssetLike
|
||
pbLikes := make([]*pb.AssetLike, 0, len(likes))
|
||
for _, like := range likes {
|
||
pbLikes = append(pbLikes, &pb.AssetLike{
|
||
Id: like.ID,
|
||
AssetId: like.AssetID,
|
||
UserId: like.UserID,
|
||
StarId: like.StarID,
|
||
CreatedAt: like.CreatedAt,
|
||
})
|
||
}
|
||
|
||
// 计算分页信息
|
||
pageSize := req.PageSize
|
||
if pageSize <= 0 {
|
||
pageSize = 20
|
||
}
|
||
hasMore := total > int64(req.Page*pageSize)
|
||
|
||
logger.Logger.Info("GetAssetLikes successful",
|
||
zap.Int64("asset_id", req.AssetId),
|
||
zap.Int("count", len(pbLikes)),
|
||
zap.Int64("total", total),
|
||
)
|
||
|
||
return &pb.GetAssetLikesResponse{
|
||
Base: &pbCommon.BaseResponse{
|
||
Code: pbCommon.StatusCode_STATUS_OK,
|
||
Message: "Success",
|
||
Timestamp: 0,
|
||
},
|
||
Likes: pbLikes,
|
||
Total: total,
|
||
Page: req.Page,
|
||
PageSize: pageSize,
|
||
HasMore: hasMore,
|
||
}, nil
|
||
}
|
||
|
||
// extractUserInfoFromDubboAttachments 从 Dubbo attachments 中提取用户信息
|
||
func extractUserInfoFromDubboAttachments(ctx context.Context) (int64, int64, error) {
|
||
logger.Logger.Info("Extracting user info from Dubbo attachments")
|
||
|
||
// 使用正确的 constant.AttachmentKey 获取 Dubbo attachments
|
||
if attachments := ctx.Value(constant.AttachmentKey); attachments != nil {
|
||
logger.Logger.Info("Found attachments in context",
|
||
zap.Any("attachments", attachments),
|
||
zap.String("key", fmt.Sprintf("%v", constant.AttachmentKey)),
|
||
)
|
||
|
||
if attMap, ok := attachments.(map[string]interface{}); ok {
|
||
logger.Logger.Info("Attachments is a map", zap.Any("map", attMap))
|
||
userID, starID := extractUserInfoFromMap(attMap)
|
||
if userID > 0 && starID > 0 {
|
||
logger.Logger.Info("Successfully extracted user info",
|
||
zap.Int64("user_id", userID),
|
||
zap.Int64("star_id", starID),
|
||
)
|
||
return userID, starID, nil
|
||
} else {
|
||
logger.Logger.Warn("Extracted zero user_id or star_id",
|
||
zap.Int64("user_id", userID),
|
||
zap.Int64("star_id", starID),
|
||
)
|
||
}
|
||
} else {
|
||
logger.Logger.Warn("Attachments is not a map[string]interface{}",
|
||
zap.String("type", fmt.Sprintf("%T", attachments)),
|
||
)
|
||
}
|
||
} else {
|
||
logger.Logger.Warn("No attachments found in context",
|
||
zap.String("key", fmt.Sprintf("%v", constant.AttachmentKey)),
|
||
)
|
||
}
|
||
|
||
logger.Logger.Error("Failed to extract user info from Dubbo attachments")
|
||
return 0, 0, fmt.Errorf("user info not found in Dubbo attachments (expected user_id and star_id from gateway)")
|
||
}
|
||
|
||
// extractUserInfoFromMap 从 map 中提取 user_id 和 star_id
|
||
func extractUserInfoFromMap(attMap map[string]interface{}) (int64, int64) {
|
||
var userID, starID int64
|
||
|
||
// 提取 user_id
|
||
if v, ok := attMap["user_id"]; ok {
|
||
userID = parseIntValue(v)
|
||
}
|
||
|
||
// 提取 star_id
|
||
if v, ok := attMap["star_id"]; ok {
|
||
starID = parseIntValue(v)
|
||
}
|
||
|
||
return userID, starID
|
||
}
|
||
|
||
// parseIntValue 解析各种类型的值为 int64
|
||
func parseIntValue(v interface{}) int64 {
|
||
switch val := v.(type) {
|
||
case int64:
|
||
return val
|
||
case int:
|
||
return int64(val)
|
||
case float64:
|
||
return int64(val)
|
||
case string:
|
||
var result int64
|
||
fmt.Sscanf(val, "%d", &result)
|
||
return result
|
||
case []string:
|
||
if len(val) > 0 {
|
||
var result int64
|
||
fmt.Sscanf(val[0], "%d", &result)
|
||
return result
|
||
}
|
||
case []interface{}:
|
||
if len(val) > 0 {
|
||
return parseIntValue(val[0])
|
||
}
|
||
}
|
||
return 0
|
||
}
|
||
|
||
// ClearAssetLikeRecords 清除资产点赞记录(内部RPC调用,供Gallery Service在下架时调用)
|
||
func (p *AssetProvider) ClearAssetLikeRecords(ctx context.Context, req *pb.ClearAssetLikeRecordsRequest) (*pb.ClearAssetLikeRecordsResponse, error) {
|
||
logger.Logger.Info("Received ClearAssetLikeRecords request",
|
||
zap.Int64("asset_id", req.AssetId),
|
||
)
|
||
|
||
if err := p.assetLikeService.ClearAssetLikeRecords(ctx, req.AssetId); err != nil {
|
||
logger.Logger.Error("ClearAssetLikeRecords failed",
|
||
zap.Int64("asset_id", req.AssetId),
|
||
zap.Error(err),
|
||
)
|
||
return &pb.ClearAssetLikeRecordsResponse{
|
||
Base: &pbCommon.BaseResponse{
|
||
Code: appErrors.ToStatusCode(err),
|
||
Message: err.Error(),
|
||
},
|
||
}, err
|
||
}
|
||
|
||
logger.Logger.Info("ClearAssetLikeRecords successful",
|
||
zap.Int64("asset_id", req.AssetId),
|
||
)
|
||
|
||
return &pb.ClearAssetLikeRecordsResponse{
|
||
Base: &pbCommon.BaseResponse{
|
||
Code: pbCommon.StatusCode_STATUS_OK,
|
||
Message: "点赞记录已清除",
|
||
},
|
||
}, nil
|
||
}
|
||
|
||
// GetMintOrder 查询铸造订单状态
|
||
func (p *AssetProvider) GetMintOrder(ctx context.Context, req *pb.GetMintOrderRequest) (*pb.GetMintOrderResponse, error) {
|
||
logger.Logger.Info("Received GetMintOrder request",
|
||
zap.String("order_id", req.OrderId),
|
||
)
|
||
|
||
// 从 Dubbo attachments 获取用户信息(网关已验证并传递)
|
||
userID, starID, err := extractUserInfoFromDubboAttachments(ctx)
|
||
if err != nil {
|
||
logger.Logger.Error("Failed to extract user info from attachments",
|
||
zap.Error(err),
|
||
)
|
||
return &pb.GetMintOrderResponse{
|
||
Base: &pbCommon.BaseResponse{
|
||
Code: pbCommon.StatusCode_STATUS_UNAUTHORIZED,
|
||
Message: "user authentication required",
|
||
Timestamp: 0,
|
||
},
|
||
}, err
|
||
}
|
||
|
||
// 调用Service层
|
||
resp, err := p.mintService.GetMintOrder(req.OrderId, userID, starID)
|
||
if err != nil {
|
||
logger.Logger.Error("GetMintOrder failed",
|
||
zap.String("order_id", req.OrderId),
|
||
zap.Int64("user_id", userID),
|
||
zap.Int64("star_id", starID),
|
||
zap.Error(err),
|
||
)
|
||
|
||
// 如果响应为空,构建错误响应
|
||
if resp == nil {
|
||
resp = &pb.GetMintOrderResponse{
|
||
Base: &pbCommon.BaseResponse{
|
||
Code: appErrors.ToStatusCode(err),
|
||
Message: err.Error(),
|
||
Timestamp: 0,
|
||
},
|
||
}
|
||
}
|
||
|
||
return resp, err
|
||
}
|
||
|
||
logger.Logger.Info("GetMintOrder successful",
|
||
zap.String("order_id", req.OrderId),
|
||
zap.Int64("user_id", userID),
|
||
zap.String("status", resp.Order.Status),
|
||
)
|
||
|
||
return resp, nil
|
||
}
|
||
|
||
// CancelMintOrder 取消铸造订单
|
||
func (p *AssetProvider) CancelMintOrder(ctx context.Context, req *pb.CancelMintOrderRequest) (*pb.CancelMintOrderResponse, error) {
|
||
// 记录请求日志
|
||
logger.Logger.Info("Received CancelMintOrder request",
|
||
zap.String("order_id", req.OrderId),
|
||
)
|
||
|
||
// 从 Dubbo attachments 获取用户信息(网关已验证并传递)
|
||
userID, starID, err := extractUserInfoFromDubboAttachments(ctx)
|
||
if err != nil {
|
||
logger.Logger.Error("Failed to extract user info from attachments",
|
||
zap.Error(err),
|
||
)
|
||
return &pb.CancelMintOrderResponse{
|
||
Base: &pbCommon.BaseResponse{
|
||
Code: pbCommon.StatusCode_STATUS_UNAUTHORIZED,
|
||
Message: "未授权",
|
||
Timestamp: time.Now().UnixMilli(),
|
||
},
|
||
}, err
|
||
}
|
||
|
||
// 调用服务层取消订单
|
||
err = p.mintService.CancelMintOrder(req.OrderId, userID, starID)
|
||
|
||
// 构建响应
|
||
resp := &pb.CancelMintOrderResponse{
|
||
Base: &pbCommon.BaseResponse{
|
||
Code: pbCommon.StatusCode_STATUS_OK,
|
||
Message: "",
|
||
Timestamp: time.Now().UnixMilli(),
|
||
},
|
||
OrderId: req.OrderId,
|
||
Status: models.MintOrderStatusCancelled,
|
||
}
|
||
|
||
if err != nil {
|
||
logger.Logger.Error("CancelMintOrder failed",
|
||
zap.String("order_id", req.OrderId),
|
||
zap.Int64("user_id", userID),
|
||
zap.Int64("star_id", starID),
|
||
zap.Error(err),
|
||
)
|
||
|
||
resp.Base.Code = appErrors.ToStatusCode(err)
|
||
resp.Base.Message = err.Error()
|
||
|
||
return resp, err
|
||
}
|
||
|
||
logger.Logger.Debug("CancelMintOrder successful",
|
||
zap.String("order_id", req.OrderId),
|
||
zap.Int64("user_id", userID),
|
||
zap.Int64("star_id", starID),
|
||
)
|
||
|
||
return resp, nil
|
||
}
|