先说我遇到的问题,我按照流程接入了 telegram 登录小部件,在 PC 或者 H5 可以拿到数据(不管是选择回调函数还是回调地址的形式都可以),但是在 telegram mini app 中登录拿不到数据,在 telegram 中 我点击登录的小部件后是在浏览器中打开授权网址,然后授权后回调也是在浏览器中打开一个新标签页,而不是在 telegram 中打开
设置机器人域名
这里我假设你已经有一个机器人了(没有的网上有很多 文章 教怎么创建机器人),在 @BotFather 中输入 /myapps
点击 Edit Web App Url
后输入你的域名地址(这里也可以输入你的开发地址,以 https
开头,但是不能使用 登录小部件 因为你的网址和 telegram-widget.js
生成的 iframe
域名不一致会导致浏览器安全策略问题)
然后再输入 /setdomain
, 同样的选择你的机器人然后输入你的网址
到这一步前置条件已完成。
登录
第一步
设置回调函数
// ...<Scriptid="get-telegramAuth"dangerouslySetInnerHTML={{__html: `function onTelegramAuth(user) {console.log('user =>>>', user)alert('Logged in as ' + user.first_name + ' ' + user.last_name + ' (' + user.id + (user.username ? ', @' + user.username : '') + ')');}
`,}}></Script>
// ...
第二步
这里我是使用 Next
框架编写的代码,在只需要改一下格式在其他框架中也可以使用。
import Script from 'next/script';
export const TGLogin = () => {return <><Script async src='https://telegram.org/js/telegram-widget.js?22' data-telegram-login='<你的机器人用户名>' data-request-access='write' data-size='large' data-radius='10' data-onauth='onTelegramAuth(user)'></Script><div id="my-special-div" onClick={() => {window.location.href = 'https://oauth.telegram.org/auth?bot_id=6889929762&origin=https%3A%2F%2Fwww.telegramloveai.com&embed=1&request_access=write&return_to=https%3A%2F%2Fwww.telegramloveai.com%2Fen%2Flogin'}}>LOGIN</div></>;
};
href
中地址是点击登录小部件进入新标签页的地址
机器人用户名不需要 @
Mini Apps 成功示例
静默登录
引入 js
文件 TG 文档 。
'/api/tg-login'
接口是我自己定义的,里面处理校验数据等逻辑。
'use client';import Script from 'next/script';
import { toast } from 'sonner';export const TGInitScript = () => {let initData = '';const TGWebAppReady = () => {const WebApp = window.Telegram.WebApp;/*** 静默登录*/if (WebApp.initDataUnsafe.user) {console.log(WebApp.initDataUnsafe);initData = `query_id=${WebApp.initDataUnsafe.query_id}&user=${encodeURIComponent(JSON.stringify(WebApp.initDataUnsafe.user))}&auth_date=${WebApp.initDataUnsafe.auth_date}&hash=${WebApp.initDataUnsafe.hash}`;const sendRequest = async () => {try {const { result, code, message } = await (await fetch('/api/tg-login', {method: 'POST',body: JSON.stringify({ initData }),})).json();if (code != '200') {throw new Error(message);}} catch (err: any) {toast(err.message);}};sendRequest();}};return (<><Scriptsrc="https://telegram.org/js/telegram-web-app.js"onReady={TGWebAppReady}></Script></>);
};
api
文件代码
import { NextRequest } from 'next/server';
import { validate } from './check';
import axios from 'axios';const handle = async (req: NextRequest) => {const body = await req.json();const BaseUrl ='';try {// 验证数据完整性validate(body.initData, process.env.NEXT_PUBLIC_TOKEN!);const searchParams = new URLSearchParams(body.initData);const user = JSON.parse(searchParams.get('user')!);// 和后端接口进行交互const { data: ApiData } = await axios(BaseUrl + '/authLogin',{method: 'POST',data: {loginType: 'telegram-mini-apps',email: '',nickname:user.first_name + (user.last_name ? ' ' + user.last_name : ''),openId: user.id,avatarUrl: user.photo_url,loginName: user.username,},});return Response.json(ApiData, {status: 200,});} catch (error: any) {return Response.json({code: '500',message: error.message || '',},{ status: 500 });}
};
export { handle as POST };
check
文件代码是复制的 tma.js
仓库中 文件数据 validate.ts