121 lines
4.2 KiB
Go
121 lines
4.2 KiB
Go
// Package invite defines user-service invitation facts and read models.
|
|
package invite
|
|
|
|
import (
|
|
"regexp"
|
|
"strings"
|
|
)
|
|
|
|
const (
|
|
// CodeStatusActive means a code can be used by new registrations.
|
|
CodeStatusActive = "active"
|
|
// CodeTypePrimary is the shareable per-user permanent invite code.
|
|
CodeTypePrimary = "primary"
|
|
// ProgressStatusPending means the invited user has not reached the configured recharge threshold.
|
|
ProgressStatusPending = "pending"
|
|
// ProgressStatusValid means the invited user has reached the threshold and counted once.
|
|
ProgressStatusValid = "valid"
|
|
// EventTypeUserInvited is emitted when an invitation relation is first bound.
|
|
EventTypeUserInvited = "UserInvited"
|
|
// EventTypeUserInviteBecameValid is emitted when recharge progress first crosses the policy threshold.
|
|
EventTypeUserInviteBecameValid = "UserInviteBecameValid"
|
|
// RechargeEventWalletRecorded is the wallet outbox event that invitation validity consumes.
|
|
RechargeEventWalletRecorded = "WalletRechargeRecorded"
|
|
// RechargeTypeCoinSellerTransfer is the current recharge fact produced by wallet-service coin seller transfer.
|
|
RechargeTypeCoinSellerTransfer = "coin_seller_transfer"
|
|
// RechargeTypeGooglePlay is the recharge fact produced by Google Play Billing.
|
|
RechargeTypeGooglePlay = "google_play"
|
|
// RechargeTypeGoogle is the legacy channel value carried by some Google wallet payloads.
|
|
RechargeTypeGoogle = "google"
|
|
// RechargeTypeMifaPay is the third-party checkout provider value for MiFaPay.
|
|
RechargeTypeMifaPay = "mifapay"
|
|
// RechargeTypeV5Pay is the third-party checkout provider value for V5Pay.
|
|
RechargeTypeV5Pay = "v5pay"
|
|
// RechargeTypeUSDTTRC20 is the third-party checkout provider value for USDT TRC20.
|
|
RechargeTypeUSDTTRC20 = "usdt_trc20"
|
|
)
|
|
|
|
const (
|
|
// CodeMinLength keeps user-entered invite codes short enough for mobile manual entry.
|
|
CodeMinLength = 6
|
|
// CodeMaxLength follows the current SQL VARCHAR boundary for invite code snapshots.
|
|
CodeMaxLength = 64
|
|
)
|
|
|
|
var codePattern = regexp.MustCompile(`^[A-Z0-9]{6,64}$`)
|
|
|
|
// Overview is the read model returned with user profile for my-page aggregation.
|
|
type Overview struct {
|
|
MyInviteCode string
|
|
InviteEnabled bool
|
|
InviteCount int64
|
|
ValidInviteCount int64
|
|
ValidInviteThresholdCoin int64
|
|
}
|
|
|
|
// Binding is the result of one registration/onboarding invitation bind attempt.
|
|
type Binding struct {
|
|
Bound bool
|
|
InviteCode string
|
|
InviterUserID int64
|
|
}
|
|
|
|
// Attribution 是被邀请用户到邀请人的归因快照;活动服务只依赖这个只读事实,不直接读取邀请表。
|
|
type Attribution struct {
|
|
Found bool
|
|
AppCode string
|
|
InvitedUserID int64
|
|
InviterUserID int64
|
|
InviteCode string
|
|
BoundAtMS int64
|
|
ValidityStatus string
|
|
AccumulatedRechargeCoinAmount int64
|
|
RequiredRechargeCoinAmount int64
|
|
ValidAtMS int64
|
|
}
|
|
|
|
// BindCommand describes one optional invitation attribution write.
|
|
type BindCommand struct {
|
|
AppCode string
|
|
InvitedUserID int64
|
|
InvitedRegionID int64
|
|
InviteCode string
|
|
Source string
|
|
RequestID string
|
|
BoundAtMs int64
|
|
}
|
|
|
|
// RechargeEvent is the wallet recharge fact consumed by invitation validity.
|
|
type RechargeEvent struct {
|
|
AppCode string
|
|
EventID string
|
|
EventType string
|
|
TransactionID string
|
|
CommandID string
|
|
InvitedUserID int64
|
|
AssetType string
|
|
RechargeCoinAmount int64
|
|
RechargeType string
|
|
OccurredAtMs int64
|
|
PayloadJSON string
|
|
}
|
|
|
|
// RechargeApplyResult summarizes idempotent invitation recharge processing.
|
|
type RechargeApplyResult struct {
|
|
Consumed bool
|
|
Skipped bool
|
|
Valid bool
|
|
Reason string
|
|
}
|
|
|
|
// NormalizeCode trims and uppercases user-provided invite code text.
|
|
func NormalizeCode(code string) string {
|
|
return strings.ToUpper(strings.TrimSpace(code))
|
|
}
|
|
|
|
// ValidCode checks only syntax; ownership and active status are repository facts.
|
|
func ValidCode(code string) bool {
|
|
code = NormalizeCode(code)
|
|
return len(code) >= CodeMinLength && len(code) <= CodeMaxLength && codePattern.MatchString(code)
|
|
}
|