2026-07-22 18:36:49 +08:00

116 lines
6.4 KiB
Go
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

package wallet
import (
"context"
"strings"
"time"
"hyapp/pkg/appcode"
"hyapp/pkg/xerr"
"hyapp/services/wallet-service/internal/domain/ledger"
)
// ListPointWithdrawalCoinSellers 返回服务端过滤后的币商白名单;区域和国家都来自可信用户资料,客户端不能自报服务范围。
func (s *Service) ListPointWithdrawalCoinSellers(ctx context.Context, appCode string, regionID int64, countryCode string, includeDisabled bool) ([]ledger.PointWithdrawalCoinSellerConfig, error) {
if strings.TrimSpace(appCode) == "" || regionID < 0 {
return nil, xerr.New(xerr.InvalidArgument, "app_code is required")
}
if s.repository == nil {
return nil, xerr.New(xerr.Unavailable, "wallet repository is not configured")
}
appCode = appcode.Normalize(appCode)
return s.repository.ListPointWithdrawalCoinSellers(appcode.WithContext(ctx, appCode), appCode, regionID, strings.ToUpper(strings.TrimSpace(countryCode)), includeDisabled)
}
// TransferPointToCoinSeller 验证客户端允许提交的最小字段;兑换比例由 repository 事务内锁定配置解析。
func (s *Service) TransferPointToCoinSeller(ctx context.Context, command ledger.PointToCoinSellerCommand) (ledger.PointToCoinSellerReceipt, error) {
command.SourceAssetType = strings.ToUpper(strings.TrimSpace(command.SourceAssetType))
if command.SourceAssetType == "" {
command.SourceAssetType = ledger.AssetPoint
}
validAmount := command.PointAmount > 0
if command.SourceAssetType == ledger.AssetPointDiamond {
validAmount = command.GrossUSDMinor > 0
}
if strings.TrimSpace(command.AppCode) == "" || strings.TrimSpace(command.CommandID) == "" || command.SourceUserID <= 0 || command.SellerUserID <= 0 || !validAmount || command.RegionID <= 0 ||
(command.SourceAssetType != ledger.AssetPoint && command.SourceAssetType != ledger.AssetPointDiamond) {
return ledger.PointToCoinSellerReceipt{}, xerr.New(xerr.InvalidArgument, "point coin seller transfer command is incomplete")
}
command.AppCode = appcode.Normalize(command.AppCode)
command.CommandID = strings.TrimSpace(command.CommandID)
command.SourceCountryCode = strings.ToUpper(strings.TrimSpace(command.SourceCountryCode))
command.Reason = strings.TrimSpace(command.Reason)
if len(command.CommandID) > 128 || len(command.SourceCountryCode) > 16 || len(command.Reason) > 512 {
return ledger.PointToCoinSellerReceipt{}, xerr.New(xerr.InvalidArgument, "point coin seller transfer text fields are too long")
}
if s.repository == nil {
return ledger.PointToCoinSellerReceipt{}, xerr.New(xerr.Unavailable, "wallet repository is not configured")
}
return s.repository.TransferPointToCoinSeller(appcode.WithContext(ctx, command.AppCode), command)
}
// ExchangePointToCoin 校验入参;目标 COIN 数量由 repository 事务内的 wallet 政策与统一工资兑币比例决定。
func (s *Service) ExchangePointToCoin(ctx context.Context, command ledger.PointToCoinCommand) (ledger.PointToCoinReceipt, error) {
command.SourceAssetType = strings.ToUpper(strings.TrimSpace(command.SourceAssetType))
if command.SourceAssetType == "" {
command.SourceAssetType = ledger.AssetPoint
}
if strings.TrimSpace(command.AppCode) == "" || strings.TrimSpace(command.CommandID) == "" || command.UserID <= 0 || command.PointAmount <= 0 || command.RegionID < 0 ||
(command.SourceAssetType != ledger.AssetPoint && command.SourceAssetType != ledger.AssetPointDiamond) {
return ledger.PointToCoinReceipt{}, xerr.New(xerr.InvalidArgument, "point to coin exchange command is incomplete")
}
command.AppCode = appcode.Normalize(command.AppCode)
command.CommandID = strings.TrimSpace(command.CommandID)
if len(command.CommandID) > 128 {
return ledger.PointToCoinReceipt{}, xerr.New(xerr.InvalidArgument, "point to coin exchange command id is too long")
}
if command.NowMS <= 0 {
command.NowMS = time.Now().UTC().UnixMilli()
}
if s.repository == nil {
return ledger.PointToCoinReceipt{}, xerr.New(xerr.Unavailable, "wallet repository is not configured")
}
return s.repository.ExchangePointToCoin(appcode.WithContext(ctx, command.AppCode), command)
}
// GetPointWithdrawalConfig 读取已发布 wallet 政策快照nowMS 由服务端补齐,避免客户端选择过期配置。
func (s *Service) GetPointWithdrawalConfig(ctx context.Context, appCode string, regionID int64, nowMS int64) (ledger.PointWithdrawalRuntimeConfig, error) {
return s.GetPointWithdrawalConfigForAsset(ctx, appCode, regionID, nowMS, ledger.AssetPoint)
}
func (s *Service) GetPointWithdrawalConfigForAsset(ctx context.Context, appCode string, regionID int64, nowMS int64, assetType string) (ledger.PointWithdrawalRuntimeConfig, error) {
return s.getPointWithdrawalConfig(ctx, appCode, 0, regionID, nowMS, assetType)
}
// GetPointWithdrawalConfigForUser 为钱包 overview 追加实时日期/次数能力;动作执行仍在账变事务内二次校验。
func (s *Service) GetPointWithdrawalConfigForUser(ctx context.Context, appCode string, userID int64, regionID int64, nowMS int64, assetType string) (ledger.PointWithdrawalRuntimeConfig, error) {
if userID <= 0 {
return ledger.PointWithdrawalRuntimeConfig{}, xerr.New(xerr.InvalidArgument, "point withdrawal config user is invalid")
}
return s.getPointWithdrawalConfig(ctx, appCode, userID, regionID, nowMS, assetType)
}
func (s *Service) getPointWithdrawalConfig(ctx context.Context, appCode string, userID int64, regionID int64, nowMS int64, assetType string) (ledger.PointWithdrawalRuntimeConfig, error) {
if strings.TrimSpace(appCode) == "" || regionID < 0 {
return ledger.PointWithdrawalRuntimeConfig{}, xerr.New(xerr.InvalidArgument, "point withdrawal config query is invalid")
}
if s.repository == nil {
return ledger.PointWithdrawalRuntimeConfig{}, xerr.New(xerr.Unavailable, "wallet repository is not configured")
}
if nowMS <= 0 {
nowMS = time.Now().UnixMilli()
}
appCode = appcode.Normalize(appCode)
assetType = strings.ToUpper(strings.TrimSpace(assetType))
if assetType == "" {
assetType = ledger.AssetPoint
}
if assetType != ledger.AssetPoint && assetType != ledger.AssetPointDiamond {
return ledger.PointWithdrawalRuntimeConfig{}, xerr.New(xerr.InvalidArgument, "point asset_type is invalid")
}
if userID > 0 {
return s.repository.GetPointWithdrawalConfigForUser(appcode.WithContext(ctx, appCode), appCode, userID, regionID, nowMS, assetType)
}
return s.repository.GetPointWithdrawalConfigForAsset(appcode.WithContext(ctx, appCode), appCode, regionID, nowMS, assetType)
}