package mysql import ( "context" "database/sql" "errors" "strconv" "strings" "hyapp/pkg/appcode" "hyapp/pkg/xerr" "hyapp/services/wallet-service/internal/domain/ledger" ) const ( // charge_amount 是 ca15f098 上线时的兼容口径:Agency 比例直接作用于礼物实扣金额, // 因而主播比例与 Agency 比例必须共同受 100% 资金池约束。 agencyPointShareBaseChargeAmount = "charge_amount" // host_income 表示平台在主播本次实际 POINT 收益之外追加 Agency 奖励。 // 该口径先完成礼物类型和主播政策换算,再对最终主播收益取比例,允许出现 100%+20%。 agencyPointShareBaseHostIncome = "host_income" ) type walletPolicyInstance struct { InstanceCode string TemplateCode string TemplateVersion string RegionID int64 HostPointAsset string HostPointRatioPPM int64 HostGiftTypeRatioEnabled bool AgencyPointRatioPPM int64 AgencyPointShareBase string PointsPerUSD int64 WithdrawFeeBPS int64 } func (r *Repository) resolveActiveWalletPolicy(ctx context.Context, tx *sql.Tx, appCode string, regionID int64, nowMS int64) (walletPolicyInstance, bool, error) { appCode = appcode.Normalize(appCode) if regionID < 0 { return walletPolicyInstance{}, false, xerr.New(xerr.InvalidArgument, "region_id is invalid") } row := tx.QueryRowContext(ctx, ` SELECT instance_code, template_code, template_version, region_id, host_point_asset_type, host_point_ratio_ppm, COALESCE(JSON_UNQUOTE(JSON_EXTRACT(rule_json, '$.host.use_gift_type_ratio')), 'false'), agency_point_ratio_ppm, COALESCE(JSON_UNQUOTE(JSON_EXTRACT(rule_json, '$.agency.share_base')), 'charge_amount'), points_per_usd, withdraw_fee_bps FROM wallet_policy_instances WHERE app_code = ? AND region_id IN (?, 0) AND status = 'active' AND effective_from_ms <= ? AND (effective_to_ms = 0 OR effective_to_ms > ?) ORDER BY CASE WHEN region_id = ? THEN 0 ELSE 1 END, published_at_ms DESC, instance_code DESC LIMIT 1`, appCode, regionID, nowMS, nowMS, regionID, ) var item walletPolicyInstance var hostGiftTypeRatioRaw string if err := row.Scan( &item.InstanceCode, &item.TemplateCode, &item.TemplateVersion, &item.RegionID, &item.HostPointAsset, &item.HostPointRatioPPM, &hostGiftTypeRatioRaw, &item.AgencyPointRatioPPM, &item.AgencyPointShareBase, &item.PointsPerUSD, &item.WithdrawFeeBPS, ); err != nil { if errors.Is(err, sql.ErrNoRows) { return walletPolicyInstance{}, false, nil } return walletPolicyInstance{}, false, err } item.HostPointAsset = strings.ToUpper(strings.TrimSpace(item.HostPointAsset)) if item.HostPointAsset == "" { item.HostPointAsset = ledger.AssetPoint } parsedGiftTypeRatio, err := strconv.ParseBool(strings.ToLower(strings.TrimSpace(hostGiftTypeRatioRaw))) if err != nil { return walletPolicyInstance{}, false, xerr.New(xerr.InvalidArgument, "wallet policy host gift type ratio flag is invalid") } item.HostGiftTypeRatioEnabled = parsedGiftTypeRatio item.AgencyPointShareBase = strings.ToLower(strings.TrimSpace(item.AgencyPointShareBase)) if item.AgencyPointShareBase == "" { item.AgencyPointShareBase = agencyPointShareBaseChargeAmount } if item.HostPointAsset != ledger.AssetPoint || item.HostPointRatioPPM <= 0 || item.HostPointRatioPPM > 1_000_000 || item.AgencyPointRatioPPM < 0 || item.AgencyPointRatioPPM > 1_000_000 || item.PointsPerUSD <= 0 || item.WithdrawFeeBPS < 0 || item.WithdrawFeeBPS > 10_000 { return walletPolicyInstance{}, false, xerr.New(xerr.InvalidArgument, "wallet policy instance is invalid") } switch item.AgencyPointShareBase { case agencyPointShareBaseChargeAmount: // 旧实例没有 share_base,必须继续执行原先的总资金池守恒约束;否则一次重新发布就会 // 把历史 70%+20% 配置悄然解释成可超发政策。 if item.HostPointRatioPPM+item.AgencyPointRatioPPM > 1_000_000 { return walletPolicyInstance{}, false, xerr.New(xerr.InvalidArgument, "wallet policy instance is invalid") } case agencyPointShareBaseHostIncome: // host_income 是额外平台奖励,Agency 百分比相对于主播实际到账值独立校验,不能与 // host_point_ratio_ppm 相加后套用旧的 100% 上限。 default: return walletPolicyInstance{}, false, xerr.New(xerr.InvalidArgument, "wallet policy agency share base is invalid") } return item, true, nil }