2026-06-23 11:53:00 +08:00

175 lines
6.3 KiB
Go

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
}