package ledger import ( "strings" ) // DebitGiftCommand 是 room-service 送礼扣费的账务命令。 type DebitGiftCommand struct { AppCode string CommandID string RoomID string SenderUserID int64 TargetUserID int64 GiftID string GiftCount int32 PriceVersion string RegionID int64 // SenderRegionID 是送礼用户所属区域;用于按区域匹配礼物入主播周期钻石比例。 SenderRegionID int64 // TargetIsHost 只能由 gateway 根据 user-service active host profile 注入,客户端输入不可信。 TargetIsHost bool // TargetHostRegionID 是主播身份所属区域;工资政策按该区域匹配,不能用房间可见区域替代。 TargetHostRegionID int64 // TargetAgencyOwnerUserID 是送礼瞬间主播上级代理的收款用户快照;结算按快照发放,避免月底组织变化错账。 TargetAgencyOwnerUserID int64 // RobotGift 表示本次扣费只服务机器人房间展示:扣 ROBOT_COIN,不给主播钻石,不进入真实礼物墙投影。 RobotGift bool // DirectGift 表示本次扣费来自私聊送礼:没有 Room Cell 命令和房间 outbox,但仍复用真实扣费、返币、礼物墙和主播周期结算。 DirectGift bool // EntitlementID 非空表示本次送礼来自用户背包礼物权益,账务只扣库存但仍按礼物价格计算房间贡献。 EntitlementID string // ChargeSource 区分 coin/bag;为空按 coin 兼容旧链路。 ChargeSource string } // DebitGiftTargetCommand 是批量送礼中单个接收方的账务语义。 type DebitGiftTargetCommand struct { // CommandID 是单个目标交易的幂等键;同一批量送礼必须为每个目标派生独立值。 CommandID string // TargetUserID 是本次收礼用户;GIFT_POINT 已下线,新送礼不会再给目标用户积分入账。 TargetUserID int64 // TargetIsHost 只能由 gateway 注入,批量目标之间不能共享该身份快照。 TargetIsHost bool // TargetHostRegionID 是该目标主播身份所属区域。 TargetHostRegionID int64 // TargetAgencyOwnerUserID 是该目标主播当前代理 owner 收款快照。 TargetAgencyOwnerUserID int64 } // BatchDebitGiftCommand 在一个钱包事务中结算同一 sender 对多个 target 的同款礼物。 type BatchDebitGiftCommand struct { AppCode string CommandID string RoomID string SenderUserID int64 GiftID string GiftCount int32 PriceVersion string RegionID int64 SenderRegionID int64 Targets []DebitGiftTargetCommand EntitlementID string ChargeSource string } // Receipt 是账务命令落账后的稳定回执。 type Receipt struct { BillingReceiptID string TransactionID string CoinSpent int64 ChargeAssetType string ChargeAmount int64 // GiftPointAdded 是历史回执字段,新送礼固定为 0;房间贡献和主播周期钻石只按真实扣费金额计算。 GiftPointAdded int64 HeatValue int64 GiftTypeCode string // CPRelationType 只在 CP 礼物类型上有值,room-service 会把它写入 RoomGiftSent 供 user-service 建关系申请。 CPRelationType string // 礼物展示字段是扣费时的资源快照,避免异步消费者再查礼物配置导致历史 IM 展示被后续配置修改影响。 GiftName string GiftIconURL string GiftAnimationURL string GiftEffectTypes []string PriceVersion string BalanceAfter int64 // HostPeriodDiamondAdded 是本次送礼写入主播工资周期账户的钻石数;非主播恒为 0。 HostPeriodDiamondAdded int64 // HostPeriodCycleKey 是工资周期键,当前按 UTC 月生成,后续结算按此键定位周期账户。 HostPeriodCycleKey string EntitlementID string ChargeSource string // GiftIncomeCoinAmount 是收礼人按区域/礼物类型返还的 COIN,用于私聊送礼回执和客户端展示同步。 GiftIncomeCoinAmount int64 // GiftIncomeBalanceAfter 是收礼人 COIN 入账后的余额;没有返币时为 0。 GiftIncomeBalanceAfter int64 } // BatchGiftTargetReceipt 保留批量送礼里每个目标的独立交易回执。 type BatchGiftTargetReceipt struct { TargetUserID int64 CommandID string Receipt Receipt } // BatchGiftReceipt 同时返回聚合展示值和逐目标事实回执。 type BatchGiftReceipt struct { Aggregate Receipt Targets []BatchGiftTargetReceipt } func NormalizeGiftChargeAssetType(assetType string) string { if strings.ToUpper(strings.TrimSpace(assetType)) == AssetBagGift { return AssetBagGift } return AssetCoin } func ValidGiftChargeAssetType(assetType string) bool { switch strings.ToUpper(strings.TrimSpace(assetType)) { case AssetCoin: return true default: return false } }