package grpc import ( "context" walletv1 "hyapp.local/api/proto/wallet/v1" "hyapp/pkg/appcode" "hyapp/pkg/xerr" "hyapp/services/wallet-service/internal/domain/ledger" walletservice "hyapp/services/wallet-service/internal/service/wallet" ) // Server 把 wallet-service 用例层适配为 gRPC 接口。 type Server struct { walletv1.UnimplementedWalletServiceServer svc *walletservice.Service } // NewServer 创建 wallet gRPC server。 func NewServer(svc *walletservice.Service) *Server { return &Server{svc: svc} } // DebitGift 只负责 protobuf 转换和错误映射,扣费规则在 service/repository。 func (s *Server) DebitGift(ctx context.Context, req *walletv1.DebitGiftRequest) (*walletv1.DebitGiftResponse, error) { ctx = appcode.WithContext(ctx, req.GetAppCode()) receipt, err := s.svc.DebitGift(ctx, ledger.DebitGiftCommand{ AppCode: req.GetAppCode(), CommandID: req.GetCommandId(), RoomID: req.GetRoomId(), SenderUserID: req.GetSenderUserId(), TargetUserID: req.GetTargetUserId(), GiftID: req.GetGiftId(), GiftCount: req.GetGiftCount(), PriceVersion: req.GetPriceVersion(), RegionID: req.GetRegionId(), }) if err != nil { return nil, xerr.ToGRPCError(err) } return &walletv1.DebitGiftResponse{ BillingReceiptId: receipt.BillingReceiptID, BalanceAfter: receipt.BalanceAfter, TransactionId: receipt.TransactionID, CoinSpent: receipt.CoinSpent, ChargeAssetType: receipt.ChargeAssetType, ChargeAmount: receipt.ChargeAmount, GiftPointAdded: receipt.GiftPointAdded, HeatValue: receipt.HeatValue, PriceVersion: receipt.PriceVersion, }, nil } // GetBalances 返回用户多资产余额投影。 func (s *Server) GetBalances(ctx context.Context, req *walletv1.GetBalancesRequest) (*walletv1.GetBalancesResponse, error) { ctx = appcode.WithContext(ctx, req.GetAppCode()) balances, err := s.svc.GetBalances(ctx, req.GetUserId(), req.GetAssetTypes()) if err != nil { return nil, xerr.ToGRPCError(err) } response := &walletv1.GetBalancesResponse{Balances: make([]*walletv1.AssetBalance, 0, len(balances))} for _, balance := range balances { response.Balances = append(response.Balances, &walletv1.AssetBalance{ AppCode: balance.AppCode, AssetType: balance.AssetType, AvailableAmount: balance.AvailableAmount, FrozenAmount: balance.FrozenAmount, Version: balance.Version, }) } return response, nil } // AdminCreditAsset 处理后台手动入账,公网权限和审计入口由 gateway/admin 层控制。 func (s *Server) AdminCreditAsset(ctx context.Context, req *walletv1.AdminCreditAssetRequest) (*walletv1.AdminCreditAssetResponse, error) { ctx = appcode.WithContext(ctx, req.GetAppCode()) balance, transactionID, err := s.svc.AdminCreditAsset(ctx, ledger.AdminCreditAssetCommand{ AppCode: req.GetAppCode(), CommandID: req.GetCommandId(), TargetUserID: req.GetTargetUserId(), AssetType: req.GetAssetType(), Amount: req.GetAmount(), OperatorUserID: req.GetOperatorUserId(), Reason: req.GetReason(), EvidenceRef: req.GetEvidenceRef(), }) if err != nil { return nil, xerr.ToGRPCError(err) } return &walletv1.AdminCreditAssetResponse{ TransactionId: transactionID, Balance: &walletv1.AssetBalance{ AppCode: balance.AppCode, AssetType: balance.AssetType, AvailableAmount: balance.AvailableAmount, FrozenAmount: balance.FrozenAmount, Version: balance.Version, }, }, nil } // TransferCoinFromSeller 处理币商转玩家金币,调用方必须先完成币商身份校验。 func (s *Server) TransferCoinFromSeller(ctx context.Context, req *walletv1.TransferCoinFromSellerRequest) (*walletv1.TransferCoinFromSellerResponse, error) { ctx = appcode.WithContext(ctx, req.GetAppCode()) receipt, err := s.svc.TransferCoinFromSeller(ctx, ledger.CoinSellerTransferCommand{ AppCode: req.GetAppCode(), CommandID: req.GetCommandId(), SellerUserID: req.GetSellerUserId(), TargetUserID: req.GetTargetUserId(), SellerRegionID: req.GetSellerRegionId(), TargetRegionID: req.GetTargetRegionId(), Amount: req.GetAmount(), Reason: req.GetReason(), }) if err != nil { return nil, xerr.ToGRPCError(err) } return &walletv1.TransferCoinFromSellerResponse{ TransactionId: receipt.TransactionID, SellerBalanceAfter: receipt.SellerBalanceAfter, TargetBalanceAfter: receipt.TargetBalanceAfter, Amount: receipt.Amount, RechargeUsdMinor: receipt.RechargeUSDMinor, RechargeCurrencyCode: receipt.RechargeCurrencyCode, RechargePolicyId: receipt.RechargePolicyID, RechargePolicyVersion: receipt.RechargePolicyVersion, RechargePolicyCoinAmount: receipt.RechargePolicyCoinAmount, RechargePolicyUsdMinorAmount: receipt.RechargePolicyUSDMinorUnit, }, nil }