telegram-mini-apps-react
Compare original and translation side by side
🇺🇸
Original
English🇨🇳
Translation
ChineseTelegram Mini Apps with React
基于React开发Telegram Mini Apps
This skill provides comprehensive guidance for building Telegram Mini Apps using React and the package.
@tma.js/sdk-react本指南提供了使用React和包开发Telegram Mini Apps的全面指导。
@tma.js/sdk-reactOverview
概述
Telegram Mini Apps are web applications displayed inside Telegram's WebView. They integrate with Telegram's native UI components (Back Button, Main Button) and have access to user data, theme parameters, and platform-specific features.
Key concepts:
- Mini Apps are add-ons for Telegram Bots
- They run inside Telegram's WebView
- They communicate with Telegram client via events and methods
- They have access to launch parameters, init data, and theme settings
Telegram Mini Apps是运行在Telegram WebView中的Web应用。它们可以集成Telegram原生UI组件(返回按钮、主按钮),并能访问用户数据、主题参数和平台专属功能。
核心概念:
- Mini Apps是Telegram机器人的附加功能
- 运行在Telegram的WebView中
- 通过事件和方法与Telegram客户端通信
- 可访问启动参数、初始化数据和主题设置
Quick Start
快速开始
1. Installation
1. 安装
bash
undefinedbash
undefinedFor React projects, install the React-specific package
针对React项目,安装React专属包
pnpm i @tma.js/sdk-react
pnpm i @tma.js/sdk-react
DO NOT install both @tma.js/sdk and @tma.js/sdk-react - this causes bugs!
请勿同时安装@tma.js/sdk和@tma.js/sdk-react - 这会导致Bug!
> **Important:** The `@tma.js/sdk-react` package fully re-exports `@tma.js/sdk`, so you don't need to install them separately.
> **重要提示:** `@tma.js/sdk-react`包已完整导出`@tma.js/sdk`的所有内容,因此无需单独安装后者。2. Create New Project (Optional)
2. 创建新项目(可选)
bash
pnpm dlx @tma.js/create-mini-app@latestbash
pnpm dlx @tma.js/create-mini-app@latestor
或
npx @tma.js/create-mini-app@latest
This CLI scaffolds a complete project with proper configuration.npx @tma.js/create-mini-app@latest
该CLI工具会快速生成一个配置完善的完整项目。Project Structure
项目结构
A typical Telegram Mini App React project structure:
src/
├── main.tsx # Entry point - SDK initialization
├── init.ts # SDK configuration and component mounting
├── mockEnv.ts # Development environment mocking
├── App.tsx # Main React app with routing
├── components/
│ ├── Page.tsx # Page wrapper with back button handling
│ └── EnvUnsupported.tsx # Fallback for non-TG environments
├── hooks/
│ └── useDeeplink.ts # Deep linking handler
└── services/
└── analytics.ts # Analytics with user data典型的Telegram Mini Apps React项目结构如下:
src/
├── main.tsx # 入口文件 - SDK初始化
├── init.ts # SDK配置与组件挂载
├── mockEnv.ts # 开发环境模拟
├── App.tsx # 带路由的主React应用
├── components/
│ ├── Page.tsx # 包含返回按钮处理的页面封装组件
│ └── EnvUnsupported.tsx # 非Telegram环境下的降级UI
├── hooks/
│ └── useDeeplink.ts # 深度链接处理Hook
└── services/
└── analytics.ts # 基于用户数据的统计服务Core Concepts
核心概念
SDK Initialization
SDK初始化
The SDK must be initialized before using any features. See references/init.md for detailed implementation.
typescript
import {
init as initSDK,
setDebug,
themeParams,
miniApp,
viewport,
backButton,
swipeBehavior,
initData
} from '@tma.js/sdk-react';
export async function init(options: {
debug: boolean;
eruda: boolean;
mockForMacOS: boolean;
}): Promise<void> {
// Enable debug mode for development
setDebug(options.debug);
// Initialize the SDK (REQUIRED before using any features)
initSDK();
// Mount components you'll use in the app
backButton.mount.ifAvailable();
initData.restore();
// Configure swipe behavior
if (swipeBehavior.isSupported()) {
swipeBehavior.mount();
swipeBehavior.disableVertical();
}
// Setup Mini App theming
if (miniApp.mount.isAvailable()) {
themeParams.mount();
miniApp.mount();
themeParams.bindCssVars(); // Binds theme to CSS variables
}
// Configure viewport
if (viewport.mount.isAvailable()) {
viewport.mount().then(() => {
viewport.bindCssVars();
viewport.requestFullscreen();
});
}
}使用任何功能前必须先初始化SDK。详细实现可参考references/init.md。
typescript
import {
init as initSDK,
setDebug,
themeParams,
miniApp,
viewport,
backButton,
swipeBehavior,
initData
} from '@tma.js/sdk-react';
export async function init(options: {
debug: boolean;
eruda: boolean;
mockForMacOS: boolean;
}): Promise<void> {
// Enable debug mode for development
setDebug(options.debug);
// Initialize the SDK (REQUIRED before using any features)
initSDK();
// Mount components you'll use in the app
backButton.mount.ifAvailable();
initData.restore();
// Configure swipe behavior
if (swipeBehavior.isSupported()) {
swipeBehavior.mount();
swipeBehavior.disableVertical();
}
// Setup Mini App theming
if (miniApp.mount.isAvailable()) {
themeParams.mount();
miniApp.mount();
themeParams.bindCssVars(); // Binds theme to CSS variables
}
// Configure viewport
if (viewport.mount.isAvailable()) {
viewport.mount().then(() => {
viewport.bindCssVars();
viewport.requestFullscreen();
});
}
}Entry Point (main.tsx)
入口文件(main.tsx)
typescript
import { StrictMode } from "react";
import ReactDOM from "react-dom/client";
import { retrieveLaunchParams } from '@tma.js/sdk-react';
import { init } from './init';
import App from "./App";
import { EnvUnsupported } from "./components/EnvUnsupported";
// Mock environment for local development
import './mockEnv';
const root = ReactDOM.createRoot(document.getElementById('root')!);
try {
const launchParams = retrieveLaunchParams();
const { tgWebAppPlatform: platform } = launchParams;
const debug = (launchParams.tgWebAppStartParam || '').includes('debug')
|| import.meta.env.DEV;
await init({
debug,
eruda: debug && ['ios', 'android'].includes(platform),
mockForMacOS: platform === 'macos',
}).then(() => {
root.render(
<StrictMode>
<App/>
</StrictMode>,
);
});
} catch (e) {
// Show fallback UI when not in Telegram
root.render(<EnvUnsupported/>);
}typescript
import { StrictMode } from "react";
import ReactDOM from "react-dom/client";
import { retrieveLaunchParams } from '@tma.js/sdk-react';
import { init } from './init';
import App from "./App";
import { EnvUnsupported } from "./components/EnvUnsupported";
// Mock environment for local development
import './mockEnv';
const root = ReactDOM.createRoot(document.getElementById('root')!);
try {
const launchParams = retrieveLaunchParams();
const { tgWebAppPlatform: platform } = launchParams;
const debug = (launchParams.tgWebAppStartParam || '').includes('debug')
|| import.meta.env.DEV;
await init({
debug,
eruda: debug && ['ios', 'android'].includes(platform),
mockForMacOS: platform === 'macos',
}).then(() => {
root.render(
<StrictMode>
<App/>
</StrictMode>,
);
});
} catch (e) {
// Show fallback UI when not in Telegram
root.render(<EnvUnsupported/>);
}Using Back Button
返回按钮的使用
The Back Button is a native Telegram UI element that appears in the header.
typescript
import { useEffect } from 'react';
import { useNavigate, useLocation } from 'react-router-dom';
import { backButton, miniApp } from '@tma.js/sdk-react';
export function Page({ children, back = true }) {
const navigate = useNavigate();
const location = useLocation();
useEffect(() => {
if (back) {
backButton.show();
// onClick returns a cleanup function
return backButton.onClick(() => {
const isDeeplink = location.state?.fromDeeplink;
const isFirstPage = !window.history.state || window.history.state.idx === 0;
if (isDeeplink || isFirstPage) {
miniApp.close(); // Close the Mini App
} else {
navigate(-1); // Go back in history
}
});
}
backButton.hide();
}, [back, navigate, location]);
return <>{children}</>;
}返回按钮是Telegram原生UI元素,会显示在头部区域。
typescript
import { useEffect } from 'react';
import { useNavigate, useLocation } from 'react-router-dom';
import { backButton, miniApp } from '@tma.js/sdk-react';
export function Page({ children, back = true }) {
const navigate = useNavigate();
const location = useLocation();
useEffect(() => {
if (back) {
backButton.show();
// onClick returns a cleanup function
return backButton.onClick(() => {
const isDeeplink = location.state?.fromDeeplink;
const isFirstPage = !window.history.state || window.history.state.idx === 0;
if (isDeeplink || isFirstPage) {
miniApp.close(); // Close the Mini App
} else {
navigate(-1); // Go back in history
}
});
}
backButton.hide();
}, [back, navigate, location]);
return <>{children}</>;
}Using Signals (useSignal Hook)
信号的使用(useSignal Hook)
Signals are reactive values that update automatically. Use to subscribe to them in React:
useSignaltypescript
import { useEffect } from 'react';
import { backButton, useSignal } from '@tma.js/sdk-react';
function BackButtonStatus() {
const isVisible = useSignal(backButton.isVisible);
useEffect(() => {
console.log('Back button is', isVisible ? 'visible' : 'hidden');
}, [isVisible]);
return null;
}信号是可自动更新的响应式值。在React中使用 Hook订阅信号:
useSignaltypescript
import { useEffect } from 'react';
import { backButton, useSignal } from '@tma.js/sdk-react';
function BackButtonStatus() {
const isVisible = useSignal(backButton.isVisible);
useEffect(() => {
console.log('Back button is', isVisible ? 'visible' : 'hidden');
}, [isVisible]);
return null;
}Getting Init Data (User Info)
获取初始化数据(用户信息)
Init data contains user information and can be used for authentication:
typescript
import { initData } from '@tma.js/sdk-react';
function getUserId(): number | undefined {
try {
const user = initData.user();
return user?.id;
} catch (e) {
return undefined;
}
}
// Get start parameter (for deep linking)
const startParam = initData.startParam();初始化数据包含用户信息,可用于身份验证:
typescript
import { initData } from '@tma.js/sdk-react';
function getUserId(): number | undefined {
try {
const user = initData.user();
return user?.id;
} catch (e) {
return undefined;
}
}
// Get start parameter (for deep linking)
const startParam = initData.startParam();Launch Parameters
启动参数
Launch parameters contain platform info, theme, and app data:
typescript
import { retrieveLaunchParams, useLaunchParams } from '@tma.js/sdk-react';
// In component
function Component() {
const launchParams = useLaunchParams();
// launchParams.tgWebAppPlatform - 'ios', 'android', 'macos', 'tdesktop', 'web', 'weba'
// launchParams.tgWebAppVersion - SDK version supported by client
// launchParams.tgWebAppData - init data
// launchParams.tgWebAppThemeParams - theme colors
// launchParams.tgWebAppStartParam - custom start parameter
}
// Outside component
const launchParams = retrieveLaunchParams();启动参数包含平台信息、主题和应用数据:
typescript
import { retrieveLaunchParams, useLaunchParams } from '@tma.js/sdk-react';
// In component
function Component() {
const launchParams = useLaunchParams();
// launchParams.tgWebAppPlatform - 'ios', 'android', 'macos', 'tdesktop', 'web', 'weba'
// launchParams.tgWebAppVersion - SDK version supported by client
// launchParams.tgWebAppData - init data
// launchParams.tgWebAppThemeParams - theme colors
// launchParams.tgWebAppStartParam - custom start parameter
}
// Outside component
const launchParams = retrieveLaunchParams();Theming
主题设置
Theme parameters are automatically provided by Telegram. Bind them to CSS variables:
typescript
import { themeParams, miniApp } from '@tma.js/sdk-react';
// During initialization
if (miniApp.mount.isAvailable()) {
themeParams.mount();
miniApp.mount();
themeParams.bindCssVars(); // Creates CSS variables like --tg-theme-bg-color
}Available CSS variables after binding:
--tg-theme-bg-color--tg-theme-text-color--tg-theme-hint-color--tg-theme-link-color--tg-theme-button-color--tg-theme-button-text-color--tg-theme-secondary-bg-color--tg-theme-header-bg-color--tg-theme-accent-text-color--tg-theme-section-bg-color--tg-theme-section-header-text-color--tg-theme-subtitle-text-color--tg-theme-destructive-text-color
主题参数由Telegram自动提供,可将其绑定到CSS变量:
typescript
import { themeParams, miniApp } from '@tma.js/sdk-react';
// During initialization
if (miniApp.mount.isAvailable()) {
themeParams.mount();
miniApp.mount();
themeParams.bindCssVars(); // Creates CSS variables like --tg-theme-bg-color
}绑定后可用的CSS变量:
--tg-theme-bg-color--tg-theme-text-color--tg-theme-hint-color--tg-theme-link-color--tg-theme-button-color--tg-theme-button-text-color--tg-theme-secondary-bg-color--tg-theme-header-bg-color--tg-theme-accent-text-color--tg-theme-section-bg-color--tg-theme-section-header-text-color--tg-theme-subtitle-text-color--tg-theme-destructive-text-color
Viewport and Safe Areas
视口与安全区域
Handle viewport and safe areas for proper layout:
typescript
import { viewport } from '@tma.js/sdk-react';
if (viewport.mount.isAvailable()) {
viewport.mount().then(() => {
viewport.bindCssVars(); // Binds viewport dimensions to CSS
viewport.requestFullscreen(); // Request fullscreen mode
});
}Available CSS variables:
css
/* Safe area insets */
padding-top: var(--tg-viewport-safe-area-inset-top, 0);
padding-bottom: var(--tg-viewport-safe-area-inset-bottom, 0);
/* Content safe area (for notch, etc.) */
padding-top: var(--tg-viewport-content-safe-area-inset-top, 0);
/* Viewport dimensions */
height: var(--tg-viewport-height);
width: var(--tg-viewport-width);Usage in CSS:
css
.header {
padding-top: max(2rem, calc(var(--tg-viewport-content-safe-area-inset-top, 0) + var(--tg-viewport-safe-area-inset-top, 0)));
}
.footer {
padding-bottom: calc(1rem + var(--tg-viewport-safe-area-inset-bottom, 0));
}处理视口和安全区域以实现合理布局:
typescript
import { viewport } from '@tma.js/sdk-react';
if (viewport.mount.isAvailable()) {
viewport.mount().then(() => {
viewport.bindCssVars(); // Binds viewport dimensions to CSS
viewport.requestFullscreen(); // Request fullscreen mode
});
}可用的CSS变量:
css
/* Safe area insets */
padding-top: var(--tg-viewport-safe-area-inset-top, 0);
padding-bottom: var(--tg-viewport-safe-area-inset-bottom, 0);
/* Content safe area (for notch, etc.) */
padding-top: var(--tg-viewport-content-safe-area-inset-top, 0);
/* Viewport dimensions */
height: var(--tg-viewport-height);
width: var(--tg-viewport-width);CSS中的使用示例:
css
.header {
padding-top: max(2rem, calc(var(--tg-viewport-content-safe-area-inset-top, 0) + var(--tg-viewport-safe-area-inset-top, 0)));
}
.footer {
padding-bottom: calc(1rem + var(--tg-viewport-safe-area-inset-bottom, 0));
}Development Environment Mocking
开发环境模拟
For local development outside Telegram, mock the environment. See references/mock-env.md.
typescript
import { emitEvent, isTMA, mockTelegramEnv } from '@tma.js/sdk-react';
if (import.meta.env.DEV) {
if (!await isTMA('complete')) {
const themeParams = {
accent_text_color: '#6ab2f2',
bg_color: '#17212b',
button_color: '#5288c1',
button_text_color: '#ffffff',
destructive_text_color: '#ec3942',
header_bg_color: '#17212b',
hint_color: '#708499',
link_color: '#6ab3f3',
secondary_bg_color: '#232e3c',
section_bg_color: '#17212b',
section_header_text_color: '#6ab3f3',
subtitle_text_color: '#708499',
text_color: '#f5f5f5',
};
mockTelegramEnv({
onEvent(e) {
if (e.name === 'web_app_request_theme') {
return emitEvent('theme_changed', { theme_params: themeParams });
}
if (e.name === 'web_app_request_viewport') {
return emitEvent('viewport_changed', {
height: window.innerHeight,
width: window.innerWidth,
is_expanded: true,
is_state_stable: true,
});
}
if (e.name === 'web_app_request_safe_area') {
return emitEvent('safe_area_changed', { left: 0, top: 0, right: 0, bottom: 0 });
}
},
launchParams: new URLSearchParams([
['tgWebAppThemeParams', JSON.stringify(themeParams)],
['tgWebAppData', new URLSearchParams([
['auth_date', (Date.now() / 1000 | 0).toString()],
['hash', 'mock-hash'],
['signature', 'mock-signature'],
['user', JSON.stringify({ id: 1, first_name: 'Developer' })],
]).toString()],
['tgWebAppVersion', '8.4'],
['tgWebAppPlatform', 'tdesktop'],
]),
});
console.info('⚠️ Running in mocked Telegram environment');
}
}在Telegram外部进行本地开发时,可模拟Telegram环境。详细内容参考references/mock-env.md。
typescript
import { emitEvent, isTMA, mockTelegramEnv } from '@tma.js/sdk-react';
if (import.meta.env.DEV) {
if (!await isTMA('complete')) {
const themeParams = {
accent_text_color: '#6ab2f2',
bg_color: '#17212b',
button_color: '#5288c1',
button_text_color: '#ffffff',
destructive_text_color: '#ec3942',
header_bg_color: '#17212b',
hint_color: '#708499',
link_color: '#6ab3f3',
secondary_bg_color: '#232e3c',
section_bg_color: '#17212b',
section_header_text_color: '#6ab3f3',
subtitle_text_color: '#708499',
text_color: '#f5f5f5',
};
mockTelegramEnv({
onEvent(e) {
if (e.name === 'web_app_request_theme') {
return emitEvent('theme_changed', { theme_params: themeParams });
}
if (e.name === 'web_app_request_viewport') {
return emitEvent('viewport_changed', {
height: window.innerHeight,
width: window.innerWidth,
is_expanded: true,
is_state_stable: true,
});
}
if (e.name === 'web_app_request_safe_area') {
return emitEvent('safe_area_changed', { left: 0, top: 0, right: 0, bottom: 0 });
}
},
launchParams: new URLSearchParams([
['tgWebAppThemeParams', JSON.stringify(themeParams)],
['tgWebAppData', new URLSearchParams([
['auth_date', (Date.now() / 1000 | 0).toString()],
['hash', 'mock-hash'],
['signature', 'mock-signature'],
['user', JSON.stringify({ id: 1, first_name: 'Developer' })],
]).toString()],
['tgWebAppVersion', '8.4'],
['tgWebAppPlatform', 'tdesktop'],
]),
});
console.info('⚠️ Running in mocked Telegram environment');
}
}Deep Linking
深度链接
Handle start parameters for deep linking. See references/deeplink.md.
typescript
import { useEffect, useRef } from "react";
import { useNavigate } from "react-router-dom";
import { initData } from "@tma.js/sdk-react";
export function useDeeplink() {
const navigate = useNavigate();
const processedRef = useRef(false);
useEffect(() => {
if (processedRef.current) return;
const startParam = initData.startParam();
if (!startParam) return;
processedRef.current = true;
try {
// startParam is base64url encoded
const base64 = startParam.replace(/-/g, '+').replace(/_/g, '/');
const decoded = atob(base64);
const params = new URLSearchParams(decoded);
const route = params.get('route');
if (route) {
navigate(route, { replace: true, state: { fromDeeplink: true } });
}
} catch (e) {
console.error("Failed to parse startParam:", e);
}
}, [navigate]);
}处理启动参数以实现深度链接。详细内容参考references/deeplink.md。
typescript
import { useEffect, useRef } from "react";
import { useNavigate } from "react-router-dom";
import { initData } from "@tma.js/sdk-react";
export function useDeeplink() {
const navigate = useNavigate();
const processedRef = useRef(false);
useEffect(() => {
if (processedRef.current) return;
const startParam = initData.startParam();
if (!startParam) return;
processedRef.current = true;
try {
// startParam is base64url encoded
const base64 = startParam.replace(/-/g, '+').replace(/_/g, '/');
const decoded = atob(base64);
const params = new URLSearchParams(decoded);
const route = params.get('route');
if (route) {
navigate(route, { replace: true, state: { fromDeeplink: true } });
}
} catch (e) {
console.error("Failed to parse startParam:", e);
}
}, [navigate]);
}Best Practices
最佳实践
1. Always Check Availability
1. 始终检查功能可用性
Before using any method, check if it's available:
typescript
import { backButton } from '@tma.js/sdk-react';
// Option 1: Check before calling
if (backButton.show.isAvailable()) {
backButton.show();
}
// Option 2: Call only if available (safer, no-op if unavailable)
backButton.show.ifAvailable();
// Option 3: Mount only if available
backButton.mount.ifAvailable();使用任何方法前,先检查其是否可用:
typescript
import { backButton } from '@tma.js/sdk-react';
// Option 1: Check before calling
if (backButton.show.isAvailable()) {
backButton.show();
}
// Option 2: Call only if available (safer, no-op if unavailable)
backButton.show.ifAvailable();
// Option 3: Mount only if available
backButton.mount.ifAvailable();2. Mount Components Before Use
2. 使用前先挂载组件
Components must be mounted before their methods can be used:
typescript
// ❌ Wrong - will throw error
backButton.show();
// ✅ Correct
backButton.mount();
backButton.show();组件必须先挂载才能使用其方法:
typescript
// ❌ Wrong - will throw error
backButton.show();
// ✅ Correct
backButton.mount();
backButton.show();3. Handle macOS Bugs
3. 处理macOS平台的Bug
Telegram for macOS has known issues:
typescript
if (platform === 'macos') {
mockTelegramEnv({
onEvent(event, next) {
if (event.name === 'web_app_request_theme') {
const tp = themeParams.state() || retrieveLaunchParams().tgWebAppThemeParams;
return emitEvent('theme_changed', { theme_params: tp });
}
if (event.name === 'web_app_request_safe_area') {
return emitEvent('safe_area_changed', { left: 0, top: 0, right: 0, bottom: 0 });
}
next();
},
});
}Telegram for macOS存在一些已知问题:
typescript
if (platform === 'macos') {
mockTelegramEnv({
onEvent(event, next) {
if (event.name === 'web_app_request_theme') {
const tp = themeParams.state() || retrieveLaunchParams().tgWebAppThemeParams;
return emitEvent('theme_changed', { theme_params: tp });
}
if (event.name === 'web_app_request_safe_area') {
return emitEvent('safe_area_changed', { left: 0, top: 0, right: 0, bottom: 0 });
}
next();
},
});
}4. Don't Install Duplicate SDKs
4. 不要重复安装SDK
Never install both and :
@tma.js/sdk@tma.js/sdk-reactjson
// ❌ Wrong - causes bugs
{
"dependencies": {
"@tma.js/sdk": "^3.0.0",
"@tma.js/sdk-react": "^3.0.8"
}
}
// ✅ Correct - only the React package
{
"dependencies": {
"@tma.js/sdk-react": "^3.0.8"
}
}切勿同时安装和:
@tma.js/sdk@tma.js/sdk-reactjson
// ❌ Wrong - causes bugs
{
"dependencies": {
"@tma.js/sdk": "^3.0.0",
"@tma.js/sdk-react": "^3.0.8"
}
}
// ✅ Correct - only the React package
{
"dependencies": {
"@tma.js/sdk-react": "^3.0.8"
}
}5. Disable Swipe When Needed
5. 必要时禁用滑动操作
Prevent accidental navigation:
typescript
if (swipeBehavior.isSupported()) {
swipeBehavior.mount();
swipeBehavior.disableVertical(); // Prevents swipe-to-close
}防止意外导航:
typescript
if (swipeBehavior.isSupported()) {
swipeBehavior.mount();
swipeBehavior.disableVertical(); // Prevents swipe-to-close
}Sending Init Data to Server
将初始化数据发送到服务端
For authentication, send init data to your server:
typescript
import { retrieveRawInitData } from '@tma.js/sdk-react';
const initDataRaw = retrieveRawInitData();
fetch('https://api.example.com/auth', {
method: 'POST',
headers: {
Authorization: `tma ${initDataRaw}`,
},
});Server-side validation:
- Use for Node.js
@tma.js/init-data-node - Validate the hash using your bot token
- Never trust init data without validation
用于身份验证时,可将初始化数据发送到服务端:
typescript
import { retrieveRawInitData } from '@tma.js/sdk-react';
const initDataRaw = retrieveRawInitData();
fetch('https://api.example.com/auth', {
method: 'POST',
headers: {
Authorization: `tma ${initDataRaw}`,
},
});服务端验证:
- Node.js环境可使用包
@tma.js/init-data-node - 使用机器人令牌验证哈希值
- 未经过验证的初始化数据绝不可信
Supported Platforms
支持的平台
Mini Apps work on:
- android - Telegram for Android
- ios - Telegram for iOS
- macos - Telegram for macOS (has some bugs)
- tdesktop - Telegram Desktop
- weba - Telegram Web A
- web - Telegram Web K
Mini Apps可在以下平台运行:
- android - Telegram for Android
- ios - Telegram for iOS
- macos - Telegram for macOS(存在部分Bug)
- tdesktop - Telegram Desktop
- weba - Telegram Web A
- web - Telegram Web K
Common Issues
常见问题
SDK not initialized error
SDK未初始化错误
Make sure to call before using any SDK features.
init()确保在使用任何SDK功能前调用方法。
init()Component not mounted error
组件未挂载错误
Mount the component before calling its methods:
typescript
backButton.mount();
backButton.show();调用组件方法前先挂载组件:
typescript
backButton.mount();
backButton.show();Method not available error
方法不可用错误
Check availability before calling:
typescript
if (backButton.show.isAvailable()) {
backButton.show();
}调用前先检查可用性:
typescript
if (backButton.show.isAvailable()) {
backButton.show();
}App crashes outside Telegram
在Telegram外部运行时应用崩溃
Use environment mocking during development and provide a fallback UI.
开发时使用环境模拟,并提供降级UI。
Additional Resources
额外资源
See Also
相关链接
- references/init.md - Full initialization example
- references/mock-env.md - Environment mocking
- references/deeplink.md - Deep linking implementation
- examples/page-component.tsx - Page wrapper with back button
- references/init.md - 完整初始化示例
- references/mock-env.md - 环境模拟指南
- references/deeplink.md - 深度链接实现
- examples/page-component.tsx - 带返回按钮的页面封装组件