1. 什么是 WebApp.initData
- 定义:
WebApp.initData是 Telegram WebApp SDK 提供的一个字符串,包含用户在 Mini App 环境中的认证信息(URL 编码格式)。 - 内容:包括
user对象(JSON 格式,含id、first_name、username、auth_date等)和hash(用于验证数据完整性)。 - 用途:前端获取
WebApp.initData后,通过调用/auth/telegram/callback传递给后端,后端验证签名并完成用户认证。 - 格式示例:
user=%7B%22id%22%3A123456789%2C%22first_name%22%3A%22John%22%2C%22username%22%3A%22john_doe%22%2C%22auth_date%22%3A1697059200%2C%22hash%22%3A%22abc123...%22%7D解码后:json { "user": { "id": 123456789, "first_name": "John", "username": "john_doe", "auth_date": 1697059200, "hash": "abc123..." } }
2. 如何获取 WebApp.initData
获取 WebApp.initData 需要使用 Telegram 的 WebApp SDK,只有在 Telegram Mini App 环境中运行时有效(即通过 @battletgmini_bot 打开的页面)。以下是具体步骤和代码:
2.1 引入 Telegram WebApp SDK
- 在前端项目中引入 Telegram 的 WebApp SDK。
- 方法:在 HTML 文件中添加
<script>标签,或在 JavaScript 模块中导入。 - 示例(HTML):
```html
- 示例(JavaScript 模块,如 React/Vue):javascript
import WebApp from '@twa-dev/sdk';
```
2.2 初始化 WebApp
- 调用
WebApp.ready()确保 SDK 初始化完成。 - 获取
WebApp.initData: ```javascript import WebApp from '@twa-dev/sdk';
// 初始化 WebApp WebApp.ready();
// 获取 initData
const initData = WebApp.initData;
console.log('initData:', initData);
``
- **说明**:
-WebApp.initData是一个字符串,包含 URL 编码的用户数据。
- 如果initData为空,可能是因为代码未在 Telegram Mini App 环境中运行(需通过@battletgmini_bot` 打开页面)。
2.3 检查用户数据(可选)
- 可通过
WebApp.initDataUnsafe获取解析后的用户数据(仅用于调试或展示):javascript const user = WebApp.initDataUnsafe.user; console.log('User:', user); // { id: 123456789, first_name: 'John', username: 'john_doe', ... } - 注意:
initDataUnsafe不应直接用于认证,需将原始initData传递给后端,由后端验证签名。
3. 结合授权登录流程调用 WebApp.initData
根据你的 AuthController 和之前的流程,获取 WebApp.initData 后需配合 /auth/telegram/init 和 /auth/telegram/callback 完成静默登录。以下是完整流程和代码:
3.1 流程图(Mini App 静默登录)
[用户打开 Mini App (@battletgmini_bot)]
↓
[前端调用 /auth/telegram/init?source=miniapp&inviteCode=xxx] → [后端返回 botUsername, inviteCode]
↓
[前端调用 WebApp.ready() 和 WebApp.initData]
↓
[前端调用 /auth/telegram/callback, 传 initData, inviteCode] → [后端验证, 返回 JWT token]
↓
[前端保存 token, 显示用户界面]
3.2 代码示例
以下是简要的前端代码,展示如何获取 WebApp.initData 并完成登录:
import WebApp from '@twa-dev/sdk';
// 初始化 WebApp
WebApp.ready();
// 步骤 1: 调用 /auth/telegram/init
async function initMiniAppAuth(inviteCode) {
try {
const response = await fetch(`https://desigee.vip/auth/telegram/init?source=miniapp&inviteCode=${inviteCode}`);
const data = await response.json();
if (data.code !== 200) throw new Error(data.message);
localStorage.setItem('inviteCode', data.inviteCode);
return data.botUsername; // @battletgmini_bot
} catch (error) {
console.error('Init failed:', error.message);
throw error;
}
}
// 步骤 2: 获取 initData 并调用 /auth/telegram/callback
async function handleMiniAppCallback() {
try {
const initData = WebApp.initData; // 获取 initData
if (!initData) throw new Error('initData is empty. Ensure running in Mini App.');
const inviteCode = localStorage.getItem('inviteCode');
const response = await fetch('https://desigee.vip/auth/telegram/callback', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ initData, inviteCode })
});
const data = await response.json();
if (data.code !== 200) throw new Error(data.message);
localStorage.setItem('token', data.data.token);
console.log('Login success:', data.data.user);
} catch (error) {
console.error('Callback failed:', error.message);
throw error;
}
}
// 执行登录
async function login() {
try {
await initMiniAppAuth('abc12345');
await handleMiniAppCallback();
} catch (error) {
console.error('Login failed:', error.message);
}
}
// 触发登录
login();
4. 注意事项
- 环境要求:
WebApp.initData仅在 Telegram Mini App 环境中有效(通过@battletgmini_bot打开的页面)。- 如果在普通浏览器中运行,
initData会为空,导致错误。 - 测试时,确保通过 Telegram 客户端打开 Mini App(
https://t.me/battletgmini_bot)。 - 调试方法:
- 检查
initData是否为空:javascript console.log('initData:', WebApp.initData); - 如果为空,确认页面是否通过 Mini App 打开,或检查 SDK 引入是否正确。
- 后端验证:
- 你的
AuthController已实现initData的签名验证(使用 HMAC-SHA256 和botToken)。 - 确保
application.yml配置正确:yaml telegram: bot: id: "@battletgmini_bot" token: "your_new_bot_token" # 更换泄露的 Token domain: https://desigee.vip - 安全:
- 立即更换 Bot Token(之前泄露的
8388393478:AAHR5JLBt_UfTLYOJa5v1LyWhIH1TrZiAls),在@BotFather生成新 Token。 - 确保
https://desigee.vip已配置 SSL(certbot --nginx -d desigee.vip)。 - 错误处理:
- 如果
/callback返回Invalid Telegram data,检查initData是否正确传递。 - 如果返回
AUTH_DATA_EXPIRED,确保auth_date在 24 小时内(由后端验证)。
5. Markdown 文档(补充 WebApp.initData 使用说明)
以下是更新后的 Markdown 文档,包含获取 WebApp.initData 的说明,聚焦 Mini App 模式(因为静默登录更常见于你的 @battletgmini_bot)。
# Telegram 授权登录接口文档(Mini App 模式)
**基地址**: `https://desigee.vip`
**认证方式**: 匿名访问,无需 JWT token。
## 获取 WebApp.initData
- **描述**: `WebApp.initData` 是 Telegram Mini App 提供的用户认证数据,用于静默登录。
- **步骤**:
1. 引入 Telegram WebApp SDK:
```html
<script src="https://telegram.org/js/telegram-web-app.js"></script>
```
或:
```javascript
import WebApp from '@twa-dev/sdk';
```
2. 初始化 WebApp 并获取 `initData`:
```javascript
WebApp.ready();
const initData = WebApp.initData; // 字符串,如 "user=%7B%22id%22%3A123456789..."
```
3. 确保在 Telegram Mini App 环境中运行(通过 `@battletgmini_bot` 打开)。
- **注意**:
- `initData` 仅在 Mini App 环境中有效,普通浏览器返回空。
- 使用 `initData` 调用 `/auth/telegram/callback`,不要直接解析 `WebApp.initDataUnsafe`。
## 1. 初始化 Telegram 认证
- **URL**: `/auth/telegram/init`
- **Method**: `GET`
- **描述**: 初始化 Mini App 登录,返回机器人用户名和邀请码。
- **请求参数**:
| 参数名 | 类型 | 必填 | 描述 | 示例 |
|------------|--------|------|------------------|------------|
| source | String | 是 | 填 `miniapp` | `miniapp` |
| inviteCode | String | 否 | 邀请码 | `abc12345` |
- **请求示例**:
```bash
GET https://desigee.vip/auth/telegram/init?source=miniapp&inviteCode=abc12345
```
- **响应示例**:
```json
{ "code": 200, "botUsername": "@battletgmini_bot", "inviteCode": "abc12345" }
```
- 错误: `{ "code": 400, "message": "Invalid source" }`
- **操作步骤**:
1. 调用接口,传入 `source=miniapp` 和可选 `inviteCode`。
2. 保存 `inviteCode`(localStorage)。
## 2. Telegram 认证回调
- **URL**: `/auth/telegram/callback`
- **Method**: `POST`
- **描述**: 验证 `initData`,返回 JWT token。
- **请求头**: `Content-Type: application/json`
- **请求体**:
```json
{
"initData": "user=%7B%22id%22%3A123456789%2C%22first_name%22%3A%22John%22%2C%22auth_date%22%3A1697059200%2C%22hash%22%3A%22abc123...%22%7D",
"inviteCode": "abc12345"
}
```
- **请求示例**:
```javascript
fetch('https://desigee.vip/auth/telegram/callback', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ initData: WebApp.initData, inviteCode: 'abc12345' })
})
```
- **响应示例**:
```json
{
"code": 200,
"data": {
"token": "Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...",
"user": { "username": "tg_123456789", "nickName": "John", "sparksBalance": 0 }
}
}
```
- 错误: `{ "code": 400, "message": "Invalid Telegram data" }`
- **操作步骤**:
1. 获取 `WebApp.initData`。
2. 发送 POST 请求,传入 `initData` 和 `inviteCode`。
3. 保存 `token`(localStorage)。
## 前端操作流程
1. 引入并初始化 WebApp:
```javascript
import WebApp from '@twa-dev/sdk';
WebApp.ready();
```
2. 调用 `/init`:
```javascript
fetch('https://desigee.vip/auth/telegram/init?source=miniapp&inviteCode=abc12345')
.then(res => res.json())
.then(data => localStorage.setItem('inviteCode', data.inviteCode));
```
3. 获取 `initData` 并调用 `/callback`:
```javascript
const initData = WebApp.initData;
fetch('https://desigee.vip/auth/telegram/callback', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ initData, inviteCode: localStorage.getItem('inviteCode') })
})
.then(res => res.json())
.then(data => localStorage.setItem('token', data.data.token));
```
6. 最终建议
- 获取
WebApp.initData: - 确保在 Mini App 环境中运行(通过
@battletgmini_bot打开)。 - 使用
WebApp.ready()初始化,获取WebApp.initData。 - 后端配置:
- 验证
application.yml:yaml telegram: bot: id: "@battletgmini_bot" token: "your_new_bot_token" # 更换泄露的 Token domain: https://desigee.vip - 确保
https://desigee.vip已配置 SSL。 - 测试:
- 在 Telegram 中打开
@battletgmini_bot,测试登录流程。 - 检查
initData是否正确传递,验证/callback返回的token。