175 lines
6.3 KiB
Go
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
|
|
}
|