package useridinput import ( "context" "strconv" "strings" userv1 "hyapp.local/api/proto/user/v1" "hyapp/pkg/xerr" ) type DisplayResolver interface { ResolveDisplayUserID(ctx context.Context, req *userv1.ResolveDisplayUserIDRequest) (*userv1.ResolveDisplayUserIDResponse, error) } // Resolve 把 H5、后台、运营入口里用户手填的“用户标识”统一转换成服务内部 user_id。 // 解析顺序必须先查 active display_user_id:靓号、当前短号、数字短号都属于 display 体系,优先级高于纯数字 user_id。 // 只有 user-service 明确返回 DISPLAY_USER_ID_NOT_FOUND,或者旧 fake 返回空 identity 时,纯数字输入才回退成 user_id。 // 非 NOT_FOUND 错误不能被兜底吞掉,否则 user-service 抖动时会把请求错误地路由到同名数字 user_id。 func Resolve(ctx context.Context, resolver DisplayResolver, meta *userv1.RequestMeta, raw string) (int64, error) { input := strings.TrimSpace(raw) if input == "" { return 0, xerr.New(xerr.InvalidArgument, "user identifier is required") } if resolver == nil { return 0, xerr.New(xerr.Unavailable, "user identity resolver is not configured") } resp, err := resolver.ResolveDisplayUserID(ctx, &userv1.ResolveDisplayUserIDRequest{ Meta: meta, DisplayUserId: input, }) if err == nil { if userID := resp.GetIdentity().GetUserId(); userID > 0 { return userID, nil } if userID, ok := numericUserID(input); ok { return userID, nil } return 0, xerr.New(xerr.DisplayUserIDNotFound, "not found") } if !xerr.IsCode(err, xerr.DisplayUserIDNotFound) { return 0, err } if userID, ok := numericUserID(input); ok { return userID, nil } return 0, err } func numericUserID(value string) (int64, bool) { userID, err := strconv.ParseInt(strings.TrimSpace(value), 10, 64) if err != nil || userID <= 0 { return 0, false } return userID, true }