package grpc import ( "context" "time" walletv1 "hyapp.local/api/proto/wallet/v1" "hyapp/pkg/appcode" "hyapp/pkg/xerr" "hyapp/services/wallet-service/internal/domain/ledger" ) // ListVipPackages 返回当前 VIP 和可购买包列表。 func (s *Server) ListVipPackages(ctx context.Context, req *walletv1.ListVipPackagesRequest) (*walletv1.ListVipPackagesResponse, error) { ctx = appcode.WithContext(ctx, req.GetAppCode()) current, levels, err := s.svc.ListVipPackages(ctx, req.GetUserId()) if err != nil { return nil, xerr.ToGRPCError(err) } resp := &walletv1.ListVipPackagesResponse{CurrentVip: vipToProto(current), Packages: make([]*walletv1.VipLevel, 0, len(levels))} for _, level := range levels { resp.Packages = append(resp.Packages, vipLevelToProto(level)) } return resp, nil } // GetMyVip 返回当前登录用户 VIP 状态。 func (s *Server) GetMyVip(ctx context.Context, req *walletv1.GetMyVipRequest) (*walletv1.GetMyVipResponse, error) { ctx = appcode.WithContext(ctx, req.GetAppCode()) vip, err := s.svc.GetMyVip(ctx, req.GetUserId()) if err != nil { return nil, xerr.ToGRPCError(err) } return &walletv1.GetMyVipResponse{Vip: vipToProto(vip)}, nil } // PurchaseVip 购买、续期或升级 VIP。 func (s *Server) PurchaseVip(ctx context.Context, req *walletv1.PurchaseVipRequest) (*walletv1.PurchaseVipResponse, error) { ctx = appcode.WithContext(ctx, req.GetAppCode()) receipt, err := s.svc.PurchaseVip(ctx, ledger.PurchaseVipCommand{ AppCode: req.GetAppCode(), CommandID: req.GetCommandId(), UserID: req.GetUserId(), Level: req.GetLevel(), }) if err != nil { return nil, xerr.ToGRPCError(err) } return &walletv1.PurchaseVipResponse{ OrderId: receipt.OrderID, TransactionId: receipt.TransactionID, Vip: vipToProto(receipt.Vip), CoinSpent: receipt.CoinSpent, CoinBalanceAfter: receipt.CoinBalanceAfter, RewardItems: vipRewardItemsToProto(receipt.RewardItems), }, nil } // GrantVip 统一处理活动和后台赠送 VIP。 func (s *Server) GrantVip(ctx context.Context, req *walletv1.GrantVipRequest) (*walletv1.GrantVipResponse, error) { ctx = appcode.WithContext(ctx, req.GetAppCode()) receipt, err := s.svc.GrantVip(ctx, ledger.GrantVipCommand{ AppCode: req.GetAppCode(), CommandID: req.GetCommandId(), TargetUserID: req.GetTargetUserId(), Level: req.GetLevel(), GrantSource: req.GetGrantSource(), OperatorUserID: req.GetOperatorUserId(), Reason: req.GetReason(), }) if err != nil { return nil, xerr.ToGRPCError(err) } return &walletv1.GrantVipResponse{ TransactionId: receipt.TransactionID, Vip: vipToProto(receipt.Vip), RewardItems: vipRewardItemsToProto(receipt.RewardItems), ServerTimeMs: time.Now().UnixMilli(), }, nil } // ListAdminVipLevels 返回后台 VIP 配置。 func (s *Server) ListAdminVipLevels(ctx context.Context, req *walletv1.ListAdminVipLevelsRequest) (*walletv1.ListAdminVipLevelsResponse, error) { ctx = appcode.WithContext(ctx, req.GetAppCode()) levels, err := s.svc.ListAdminVipLevels(ctx) if err != nil { return nil, xerr.ToGRPCError(err) } resp := &walletv1.ListAdminVipLevelsResponse{Levels: make([]*walletv1.VipLevel, 0, len(levels)), ServerTimeMs: time.Now().UnixMilli()} for _, level := range levels { resp.Levels = append(resp.Levels, vipLevelToProto(level)) } return resp, nil } // UpdateAdminVipLevels 保存后台 VIP 配置。 func (s *Server) UpdateAdminVipLevels(ctx context.Context, req *walletv1.UpdateAdminVipLevelsRequest) (*walletv1.UpdateAdminVipLevelsResponse, error) { ctx = appcode.WithContext(ctx, req.GetAppCode()) commands := make([]ledger.AdminVipLevelCommand, 0, len(req.GetLevels())) for _, item := range req.GetLevels() { if item == nil { continue } commands = append(commands, ledger.AdminVipLevelCommand{ Level: item.GetLevel(), Name: item.GetName(), Status: item.GetStatus(), PriceCoin: item.GetPriceCoin(), DurationMS: item.GetDurationMs(), RewardResourceGroupID: item.GetRewardResourceGroupId(), RequiredRechargeCoinAmount: item.GetRequiredRechargeCoinAmount(), SortOrder: item.GetSortOrder(), }) } levels, err := s.svc.UpdateAdminVipLevels(ctx, commands, req.GetOperatorUserId()) if err != nil { return nil, xerr.ToGRPCError(err) } resp := &walletv1.UpdateAdminVipLevelsResponse{Levels: make([]*walletv1.VipLevel, 0, len(levels)), ServerTimeMs: time.Now().UnixMilli()} for _, level := range levels { resp.Levels = append(resp.Levels, vipLevelToProto(level)) } return resp, nil } func vipToProto(vip ledger.UserVip) *walletv1.UserVip { return &walletv1.UserVip{ UserId: vip.UserID, Level: vip.Level, Name: vip.Name, Active: vip.Active, StartedAtMs: vip.StartedAtMS, ExpiresAtMs: vip.ExpiresAtMS, UpdatedAtMs: vip.UpdatedAtMS, } } func vipLevelToProto(level ledger.VipLevel) *walletv1.VipLevel { return &walletv1.VipLevel{ Level: level.Level, Name: level.Name, Status: level.Status, PriceCoin: level.PriceCoin, DurationMs: level.DurationMS, RewardResourceGroupId: level.RewardResourceGroupID, RewardItems: vipRewardItemsToProto(level.RewardItems), CanPurchase: level.CanPurchase, SortOrder: level.SortOrder, RechargeGateRequired: level.RechargeGateRequired, RequiredRechargeCoinAmount: level.RequiredRechargeCoinAmount, UserRechargeCoinAmount: level.UserRechargeCoinAmount, PurchaseLockedReason: level.PurchaseLockedReason, CreatedAtMs: level.CreatedAtMS, UpdatedAtMs: level.UpdatedAtMS, } } func vipRewardItemsToProto(items []ledger.VipRewardItem) []*walletv1.VipRewardItem { resp := make([]*walletv1.VipRewardItem, 0, len(items)) for _, item := range items { resp = append(resp, &walletv1.VipRewardItem{ ResourceId: item.ResourceID, ResourceCode: item.ResourceCode, ResourceType: item.ResourceType, Name: item.Name, Quantity: item.Quantity, ExpiresAtMs: item.ExpiresAtMS, AssetUrl: item.AssetURL, PreviewUrl: item.PreviewURL, AnimationUrl: item.AnimationURL, }) } return resp }