# 手机号 → 账号ID → 角色ID 检索方法 ## 数据关系 ``` 手机号 (明文) │ XXTEA 加密 ▼ tel_encrypt (密文) account_id │ │ ▼ ▼ vala_app_account ──────────► vala_app_character (账号表) 1:N 关联 (角色表) ``` - **一个账号** (`vala_app_account`) 可以有 **多个角色** (`vala_app_character`) - 关联字段:`vala_app_character.account_id = vala_app_account.id` ## 数据库 | 项目 | 值 | |------|-----| | 数据库 | MySQL 线上环境 | | Host | `bj-cdb-dh2fkqa0.sql.tencentcdb.com` | | Port | `27751` | | 库名 | `vala_user` | | 用户 | `read_only` | ## 表结构 ### vala_app_account(账号表) | 字段 | 类型 | 说明 | |------|------|------| | `id` | bigint | 账号ID(主键) | | `tel` | varchar(20) | 手机号(脱敏显示,如 `158****7007`) | | `tel_encrypt` | varchar(100) | 手机号密文(用于精确匹配) | ### vala_app_character(角色表) | 字段 | 类型 | 说明 | |------|------|------| | `id` | bigint | 角色ID(主键) | | `account_id` | bigint | 所属账号ID | | `nickname` | varchar(20) | 角色昵称 | | `gender` | tinyint(1) | 性别 | | `birthday` | varchar(50) | 生日 | | `purchase_season_package` | text | 已购赛季包 | ## 手机号加密方式 手机号在数据库中以密文存储,加密算法为 **XXTEA + Base64 URL-safe**。 ### 加密参数 | 参数 | 值 | |------|-----| | 算法 | XXTEA | | 密钥 | `K1pNOZ5O5+ZqTPSHA2kzPdoNOMOGcv6g` | | 编码 | Base64(标准 → URL-safe:`+`→`-`, `/`→`_`, `=`→`.`) | ### Python 加密代码 ```python import xxtea import base64 KEY = "K1pNOZ5O5+ZqTPSHA2kzPdoNOMOGcv6g" def encrypt_phone(phone: str) -> str: """加密明文手机号,返回与数据库 tel_encrypt 字段一致的密文""" encrypted = xxtea.encrypt(phone.encode(), KEY.encode()) result = base64.b64encode(encrypted).decode() result = result.replace("+", "-").replace("/", "_").replace("=", ".") return result def decrypt_phone(encrypted: str) -> str: """解密 tel_encrypt 还原明文手机号""" restored = encrypted.replace("-", "+").replace("_", "/").replace(".", "=") decrypted = xxtea.decrypt(base64.b64decode(restored), KEY.encode()) return decrypted.decode() ``` ### 加密示例 | 明文手机号 | 密文 (tel_encrypt) | |-----------|-------------------| | `15849377007` | `CxMOc6z56aYjE73r8OSAog..` | ## 查询步骤 ### 步骤 1:加密手机号 ```bash python3 -c " import xxtea, base64 KEY = 'K1pNOZ5O5+ZqTPSHA2kzPdoNOMOGcv6g' phone = '15849377007' encrypted = xxtea.encrypt(phone.encode(), KEY.encode()) result = base64.b64encode(encrypted).decode() print(result.replace('+', '-').replace('/', '_').replace('=', '.')) " # 输出: CxMOc6z56aYjE73r8OSAog.. ``` ### 步骤 2:用密文查询账号和角色 ```sql SELECT a.id AS account_id, a.tel, c.id AS character_id, c.nickname, c.gender, c.birthday, c.purchase_season_package, c.created_at FROM vala_app_account a LEFT JOIN vala_app_character c ON c.account_id = a.id WHERE a.tel_encrypt = 'CxMOc6z56aYjE73r8OSAog..'; ``` ### 步骤 3:解读结果 ``` account_id tel character_id nickname gender birthday purchase_season_package 18279 158****7007 23600 Morris 1 2021-09-09 [16,17,18,19,20] 18279 158****7007 23686 Nathan 1 2018-03-13 [16] ``` - **账号ID**: 18279 - **角色**: 23600 (Morris)、23686 (Nathan) - 一个账号下可能有多个角色(一个孩子一个角色) ## 完整查询脚本 `scripts/phone_encrypt.py` 已封装加密/解密/MD5 功能,可直接使用: ```python from phone_encrypt import encrypt_phone, decrypt_phone, phone_md5 # 加密 cipher = encrypt_phone("15849377007") # → "CxMOc6z56aYjE73r8OSAog.." # 解密 phone = decrypt_phone(cipher) # → "15849377007" # MD5(用于跨系统关联) md5 = phone_md5("15849377007") ``` ## 注意事项 1. **tel 字段是脱敏的**(如 `158****7007`),不能直接用于精确匹配 2. **必须用 tel_encrypt 密文匹配**,密文由 XXTEA 加密生成 3. **一个账号可以有多个角色**,查询结果可能返回多行 4. 测试环境和线上环境的 `tel_encrypt` 值相同(加密算法一致)