Files
sundynix-agentix/sundynix-gateway/internal/handler/wechat_nickname_test.go
T
Blizzard 0f2afdaac1 feat(admin): 微信用户观测页 + 唯一昵称 + 密钥明文回显(单管理员后台)
按需求四项:
1. 微信新用户昵称改「微信用户_XXXXX」:后缀从 openid 的 sha1 派生(去混淆字母表),
   openid 唯一 → 后缀实际不重复,且同 openid 每次一致(重登不换名)。用户可自行改名。
2. 后台加「平台 → 微信用户」列表:昵称 / openid(点击复制)/ 积分余额 / 加入时间。
   每人仍独立租户与积分(各买各的,确认过不共享积分池),此页只做统一观测。
3. 登录设置的 AppSecret 明文回显(不再只显示"已保存")。
4. 支付配置的 APIv3 密钥明文回显。
   —— 用户明确后台单人使用、RequireAdmin 已拦,接受这一安全降级;密文仍加密入库。

修一个 gorm Scan 坑:WechatUserRow 的 WechatOpenID/BalanceMicro 没加 column tag,
gorm 把 WechatOpenID 断成列名 wechat_open_id,与 SQL alias wechat_openid 对不上 →
openid 静默返回空。教训:Scan 到自定义结构 + SQL 用 alias 时,字段一律显式加 column tag。

本地验证:真库造两个微信用户,列表接口正确返回 openid(修 tag 前是空);
登录设置页 AppSecret 已是可见文本框;nickname 单测覆盖唯一/稳定/去混淆。

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-21 10:36:27 +08:00

38 lines
930 B
Go

package handler
import (
"strings"
"testing"
)
func TestWechatNickname(t *testing.T) {
// 前缀 + 5 位后缀
n := wechatNickname("openid_abc")
if !strings.HasPrefix(n, "微信用户_") {
t.Fatalf("前缀不对: %q", n)
}
suffix := strings.TrimPrefix(n, "微信用户_")
if len([]rune(suffix)) != 5 {
t.Fatalf("后缀应 5 位,得 %q", suffix)
}
// 稳定:同 openid 每次一致(重登不换名)
if wechatNickname("openid_abc") != n {
t.Fatal("同 openid 昵称应稳定")
}
// 去混淆:不含 0/O/1/I/L
for _, c := range suffix {
if strings.ContainsRune("0O1IL", c) {
t.Fatalf("后缀含易混字符: %q", suffix)
}
}
// 不同 openid 后缀基本不同(抽样几个不撞)
seen := map[string]bool{}
for _, o := range []string{"a", "b", "c", "d", "e", "openid_1", "openid_2"} {
s := wechatNickname(o)
if seen[s] {
t.Fatalf("后缀撞了: %q", s)
}
seen[s] = true
}
}