2026-07-03 18:49:44 +08:00

177 lines
7.1 KiB
Go

package grpc
import (
"context"
walletv1 "hyapp.local/api/proto/wallet/v1"
"hyapp/pkg/appcode"
"hyapp/pkg/xerr"
"hyapp/services/wallet-service/internal/domain/ledger"
)
// ListRechargeBills 暴露充值账单只读查询;后台 HTTP 层负责登录态和菜单权限。
func (s *Server) ListRechargeBills(ctx context.Context, req *walletv1.ListRechargeBillsRequest) (*walletv1.ListRechargeBillsResponse, error) {
ctx = appcode.WithContext(ctx, req.GetAppCode())
items, total, err := s.svc.ListRechargeBills(ctx, ledger.ListRechargeBillsQuery{
AppCode: req.GetAppCode(),
UserID: req.GetUserId(),
SellerUserID: req.GetSellerUserId(),
RegionID: req.GetRegionId(),
RechargeType: req.GetRechargeType(),
Status: req.GetStatus(),
Keyword: req.GetKeyword(),
PaidState: req.GetPaidState(),
StartAtMS: req.GetStartAtMs(),
EndAtMS: req.GetEndAtMs(),
Page: req.GetPage(),
PageSize: req.GetPageSize(),
})
if err != nil {
return nil, xerr.ToGRPCError(err)
}
resp := &walletv1.ListRechargeBillsResponse{Bills: make([]*walletv1.RechargeBill, 0, len(items)), Total: total}
for _, item := range items {
resp.Bills = append(resp.Bills, rechargeBillToProto(item))
}
return resp, nil
}
// GetRechargeBillSummary 暴露充值账单聚合查询,筛选口径与列表完全一致。
func (s *Server) GetRechargeBillSummary(ctx context.Context, req *walletv1.GetRechargeBillSummaryRequest) (*walletv1.GetRechargeBillSummaryResponse, error) {
ctx = appcode.WithContext(ctx, req.GetAppCode())
summary, err := s.svc.GetRechargeBillSummary(ctx, ledger.ListRechargeBillsQuery{
AppCode: req.GetAppCode(),
UserID: req.GetUserId(),
SellerUserID: req.GetSellerUserId(),
RegionID: req.GetRegionId(),
RechargeType: req.GetRechargeType(),
Status: req.GetStatus(),
Keyword: req.GetKeyword(),
StartAtMS: req.GetStartAtMs(),
EndAtMS: req.GetEndAtMs(),
})
if err != nil {
return nil, xerr.ToGRPCError(err)
}
return &walletv1.GetRechargeBillSummaryResponse{
Total: rechargeBillSummaryBucketToProto(summary.Total),
GooglePlay: rechargeBillSummaryBucketToProto(summary.GooglePlay),
ThirdParty: rechargeBillSummaryBucketToProto(summary.ThirdParty),
CoinSeller: rechargeBillSummaryBucketToProto(summary.CoinSeller),
}, nil
}
// GetRechargeBillOverview 暴露财务概览聚合:按日趋势、区域分布与谷歌实付覆盖度。
func (s *Server) GetRechargeBillOverview(ctx context.Context, req *walletv1.GetRechargeBillOverviewRequest) (*walletv1.GetRechargeBillOverviewResponse, error) {
ctx = appcode.WithContext(ctx, req.GetAppCode())
overview, err := s.svc.GetRechargeBillOverview(ctx, ledger.ListRechargeBillsQuery{
AppCode: req.GetAppCode(),
RegionID: req.GetRegionId(),
RechargeType: req.GetRechargeType(),
Status: req.GetStatus(),
StartAtMS: req.GetStartAtMs(),
EndAtMS: req.GetEndAtMs(),
}, req.GetTzOffsetMinutes())
if err != nil {
return nil, xerr.ToGRPCError(err)
}
resp := &walletv1.GetRechargeBillOverviewResponse{
Daily: make([]*walletv1.RechargeBillDailyBucket, 0, len(overview.Daily)),
Regions: make([]*walletv1.RechargeBillRegionBucket, 0, len(overview.Regions)),
GooglePaid: &walletv1.RechargeBillGooglePaidStats{
GoogleBillCount: overview.GooglePaid.GoogleBillCount,
SyncedCount: overview.GooglePaid.SyncedCount,
UnsyncedCount: overview.GooglePaid.UnsyncedCount,
CoveredUsdMinor: overview.GooglePaid.CoveredUSDMinor,
EstFeeUsdMinor: overview.GooglePaid.EstFeeUSDMinor,
EstTaxUsdMinor: overview.GooglePaid.EstTaxUSDMinor,
EstNetUsdMinor: overview.GooglePaid.EstNetUSDMinor,
},
SalaryTransfer: &walletv1.RechargeBillSalaryTransferStats{
TransferCount: overview.SalaryTransfer.TransferCount,
TransferUsdMinor: overview.SalaryTransfer.TransferUSDMinor,
},
}
for _, bucket := range overview.Daily {
resp.Daily = append(resp.Daily, &walletv1.RechargeBillDailyBucket{
Date: bucket.Date,
GoogleUsdMinor: bucket.GoogleUSDMinor,
ThirdPartyUsdMinor: bucket.ThirdPartyUSDMinor,
CoinSellerUsdMinor: bucket.CoinSellerUSDMinor,
GoogleCoinAmount: bucket.GoogleCoinAmount,
ThirdPartyCoinAmount: bucket.ThirdPartyCoinAmount,
CoinSellerCoinAmount: bucket.CoinSellerCoinAmount,
})
}
for _, bucket := range overview.Regions {
resp.Regions = append(resp.Regions, &walletv1.RechargeBillRegionBucket{
RegionId: bucket.RegionID,
BillCount: bucket.BillCount,
UsdMinorAmount: bucket.USDMinorAmount,
})
}
return resp, nil
}
// RefreshGooglePaymentPrices 触发 Google Orders API 实付明细同步;单笔失败不阻断整批。
func (s *Server) RefreshGooglePaymentPrices(ctx context.Context, req *walletv1.RefreshGooglePaymentPricesRequest) (*walletv1.RefreshGooglePaymentPricesResponse, error) {
ctx = appcode.WithContext(ctx, req.GetAppCode())
results, err := s.svc.RefreshGooglePaymentPrices(ctx, req.GetAppCode(), req.GetTransactionIds())
if err != nil {
return nil, xerr.ToGRPCError(err)
}
resp := &walletv1.RefreshGooglePaymentPricesResponse{Prices: make([]*walletv1.GooglePaymentPrice, 0, len(results))}
for _, result := range results {
resp.Prices = append(resp.Prices, &walletv1.GooglePaymentPrice{
TransactionId: result.TransactionID,
CurrencyCode: result.CurrencyCode,
PaidAmountMicro: result.PaidAmountMicro,
TaxMicro: result.TaxAmountMicro,
NetMicro: result.NetAmountMicro,
SyncedAtMs: result.SyncedAtMS,
Error: result.Err,
})
}
return resp, nil
}
func rechargeBillSummaryBucketToProto(bucket ledger.RechargeBillSummaryBucket) *walletv1.RechargeBillSummaryBucket {
return &walletv1.RechargeBillSummaryBucket{
BillCount: bucket.BillCount,
CoinAmount: bucket.CoinAmount,
UsdMinorAmount: bucket.USDMinorAmount,
}
}
func rechargeBillToProto(item ledger.RechargeBill) *walletv1.RechargeBill {
return &walletv1.RechargeBill{
AppCode: item.AppCode,
TransactionId: item.TransactionID,
CommandId: item.CommandID,
RechargeType: item.RechargeType,
Status: item.Status,
ExternalRef: item.ExternalRef,
UserId: item.UserID,
SellerUserId: item.SellerUserID,
SellerRegionId: item.SellerRegionID,
TargetRegionId: item.TargetRegionID,
PolicyId: item.PolicyID,
PolicyVersion: item.PolicyVersion,
CurrencyCode: item.CurrencyCode,
CoinAmount: item.CoinAmount,
UsdMinorAmount: item.USDMinorAmount,
ExchangeCoinAmount: item.ExchangeCoinAmount,
ExchangeUsdMinorAmount: item.ExchangeUSDMinorAmount,
ProviderAmountMinor: item.ProviderAmountMinor,
CreatedAtMs: item.CreatedAtMS,
ProviderCode: item.ProviderCode,
UserPaidCurrencyCode: item.UserPaidCurrencyCode,
UserPaidAmountMicro: item.UserPaidAmountMicro,
ProviderFeeMicro: item.ProviderFeeMicro,
ProviderTaxMicro: item.ProviderTaxMicro,
ProviderNetMicro: item.ProviderNetMicro,
PaidSyncedAtMs: item.PaidSyncedAtMS,
}
}