116 lines
6.4 KiB
Go
116 lines
6.4 KiB
Go
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)
|
||
}
|