Skip to content

useInitData ​

获取 Telegram Mini App 的初始化数据,包括用户信息、启动参数等。这是实现 Telegram 认证的核心 Hook。

导入 ​

tsx
import { useInitData } from '@xcloud/ui-telegram'

示例 ​

基础使用 ​

获取当前用户信息:

tsx
import { useInitData } from '@xcloud/ui-telegram'

function Profile() {
  const initData = useInitData()

  if (!initData.isAvailable) {
    return <div>Not in Telegram environment</div>
  }

  if (!initData.isLoaded) {
    return <div>Loading...</div>
  }

  return (
    <div>
      <h1>Hello, {initData.user?.firstName}!</h1>
      <p>ID: {initData.user?.id}</p>
      <p>Username: @{initData.user?.username}</p>
      <p>Language: {initData.user?.languageCode}</p>
    </div>
  )
}

使用启动参数 ​

处理深链接和推荐系统:

tsx
import { useInitData } from '@xcloud/ui-telegram'
import { useEffect } from 'react'

function App() {
  const { startParam } = useInitData()

  useEffect(() => {
    if (startParam) {
      // 处理启动参数
      console.log('Started with param:', startParam)

      // 例如: 推荐系统
      if (startParam.startsWith('ref_')) {
        const referrerId = startParam.replace('ref_', '')
        trackReferral(referrerId)
      }

      // 例如: 深链接
      if (startParam.startsWith('product_')) {
        const productId = startParam.replace('product_', '')
        navigateToProduct(productId)
      }
    }
  }, [startParam])

  return <div>Your App</div>
}

后端认证 ​

发送原始数据到后端进行验证:

tsx
import { useInitData } from '@xcloud/ui-telegram'
import { useEffect } from 'react'

function AuthComponent() {
  const { raw, hash, user, isLoaded } = useInitData()

  useEffect(() => {
    if (isLoaded && raw && hash) {
      // 发送到后端进行验证
      fetch('/api/auth/telegram', {
        method: 'POST',
        headers: {
          'Authorization': `tma ${raw}`,
          'Content-Type': 'application/json',
        },
        body: JSON.stringify({
          userId: user?.id,
          hash: hash,
        }),
      })
        .then(res => res.json())
        .then(data => {
          console.log('Authenticated:', data)
          localStorage.setItem('token', data.token)
        })
    }
  }, [raw, hash, user, isLoaded])

  return <div>Authenticating...</div>
}

用户头像和信息 ​

显示完整的用户信息:

tsx
import { useInitData } from '@xcloud/ui-telegram'

function UserCard() {
  const { user, isLoaded } = useInitData()

  if (!isLoaded || !user) {
    return <div>Loading user info...</div>
  }

  return (
    <div className="user-card">
      {user.photoUrl && (
        <img src={user.photoUrl} alt={user.firstName} />
      )}
      <h2>{user.firstName} {user.lastName}</h2>
      {user.username && <p>@{user.username}</p>}
      <p>User ID: {user.id}</p>
      <p>Language: {user.languageCode}</p>
      {user.isPremium && <span className="badge">Premium</span>}
    </div>
  )
}

Hook API ​

返回值 ​

typescript
interface TelegramInitData {
  // 用户信息
  user: User | undefined
  receiver: User | undefined

  // 聊天信息
  chat: any
  chatType: string | undefined
  chatInstance: string | undefined

  // 认证信息
  authDate: Date | undefined
  hash: string | undefined

  // 启动参数
  startParam: string | undefined

  // 其他
  canSendAfter: number | undefined
  raw: string | undefined  // 原始 initData 字符串(用于后端验证)

  // 状态
  isLoaded: boolean
  isAvailable: boolean
}

User 类型 ​

typescript
interface User {
  id: number
  isBot?: boolean
  firstName: string
  lastName?: string
  username?: string
  languageCode?: string
  isPremium?: boolean
  photoUrl?: string
}

数据说明 ​

user ​

当前用户信息,包含用户 ID、姓名、用户名等基本信息。

receiver ​

接收消息的用户(仅在通过 attachment menu 打开时存在)。

chat ​

聊天信息(如果从聊天中打开)。

authDate ​

认证时间(Unix 时间戳),可用于验证数据有效期。

hash ​

认证哈希值,用于后端验证数据完整性。

startParam ​

启动参数,可用于深链接、推荐系统等场景。

raw ​

原始的 initData 字符串,必须发送到后端进行签名验证。

isLoaded ​

数据是否已加载完成。

isAvailable ​

是否在 Telegram 环境中(非 Telegram 环境返回 false)。

常见场景 ​

检查是否为高级用户 ​

tsx
function PremiumFeature() {
  const { user } = useInitData()

  if (!user?.isPremium) {
    return (
      <div>
        <h3>Premium Feature</h3>
        <p>This feature is only available for Telegram Premium users.</p>
        <button>Upgrade to Premium</button>
      </div>
    )
  }

  return <div>Welcome, Premium User! 🌟</div>
}

多语言支持 ​

tsx
import { useInitData } from '@xcloud/ui-telegram'
import { useEffect } from 'react'
import i18n from './i18n'

function App() {
  const { user } = useInitData()

  useEffect(() => {
    if (user?.languageCode) {
      // 根据用户的 Telegram 语言设置切换应用语言
      i18n.changeLanguage(user.languageCode)
    }
  }, [user?.languageCode])

  return <div>{/* Your app */}</div>
}

验证数据有效期 ​

tsx
import { useInitData } from '@xcloud/ui-telegram'
import { useEffect } from 'react'

function SecurityCheck() {
  const { authDate, isLoaded } = useInitData()

  useEffect(() => {
    if (isLoaded && authDate) {
      const now = new Date()
      const ageInHours = (now.getTime() - authDate.getTime()) / (1000 * 60 * 60)

      if (ageInHours > 1) {
        console.warn('Init data is older than 1 hour, may be invalid')
        // 重新加载或提示用户
      }
    }
  }, [authDate, isLoaded])

  return <div>Security check...</div>
}

注意事项 ​

  1. 必须在 TelegramProvider 中使用: 确保应用被 TelegramProvider 包裹
  2. 数据只读: initData 在应用生命周期内不会改变
  3. 异步加载: 使用 isLoaded 判断数据是否已加载
  4. 环境检查: 使用 isAvailable 检查是否在 Telegram 环境
  5. 安全性: 后端必须验证 hash 和 authDate,不能仅信任客户端数据
  6. 有效期: Telegram 建议 initData 的有效期为 1 小时

最佳实践 ​

完整的认证流程 ​

tsx
import { useInitData } from '@xcloud/ui-telegram'
import { useState, useEffect } from 'react'

function AuthFlow() {
  const initData = useInitData()
  const [authState, setAuthState] = useState<'loading' | 'success' | 'error'>('loading')

  useEffect(() => {
    async function authenticate() {
      if (!initData.isLoaded) return

      if (!initData.isAvailable) {
        setAuthState('error')
        return
      }

      try {
        const response = await fetch('/api/auth', {
          method: 'POST',
          headers: {
            'Authorization': `tma ${initData.raw}`,
            'Content-Type': 'application/json',
          },
        })

        if (response.ok) {
          const data = await response.json()
          localStorage.setItem('token', data.token)
          setAuthState('success')
        } else {
          setAuthState('error')
        }
      } catch (error) {
        setAuthState('error')
      }
    }

    authenticate()
  }, [initData.isLoaded, initData.isAvailable, initData.raw])

  if (authState === 'loading') return <div>Authenticating...</div>
  if (authState === 'error') return <div>Authentication failed</div>

  return <div>Welcome, {initData.user?.firstName}!</div>
}

相关链接 ​

基于 MIT 许可发布