• Telegram mini app 登录小部件 | 自定义登录按钮 或 静默登录


    先说我遇到的问题,我按照流程接入了 telegram 登录小部件,在 PC 或者 H5 可以拿到数据(不管是选择回调函数还是回调地址的形式都可以),但是在 telegram mini app 中登录拿不到数据,在 telegram 中 我点击登录的小部件后是在浏览器中打开授权网址,然后授权后回调也是在浏览器中打开一个新标签页,而不是在 telegram 中打开

    设置机器人域名

    这里我假设你已经有一个机器人了(没有的网上有很多 文章 教怎么创建机器人),在 @BotFather 中输入 /myapps

    image.png

    image.png

    点击 Edit Web App Url 后输入你的域名地址(这里也可以输入你的开发地址,以 https 开头,但是不能使用 登录小部件 因为你的网址和 telegram-widget.js 生成的 iframe 域名不一致会导致浏览器安全策略问题)

    然后再输入 /setdomain, 同样的选择你的机器人然后输入你的网址

    image.png

    到这一步前置条件已完成。

    登录

    第一步

    设置回调函数

    // ...
          <Script
            id="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>
    // ...
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13

    第二步

    这里我是使用 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>
      </>;
    };
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12

    href 中地址是点击登录小部件进入新标签页的地址

    image.png

    机器人用户名不需要 @

    image.png

    Mini Apps 成功示例

    image.png

    静默登录

    引入 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 (
        <>
          <Script
            src="https://telegram.org/js/telegram-web-app.js"
            onReady={TGWebAppReady}
          ></Script>
        </>
      );
    };
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54

    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 };
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49

    check 文件代码是复制的 tma.js 仓库中 文件数据 validate.ts

  • 相关阅读:
    金融数据合规管理研究
    git log 统计自己代码提交量报错 awk No such file or directory
    python3.11教程1:python基础语法、程序控制、函数
    【Linux】gdb调试
    java毕业生设计在线考试系统演示录像2021计算机源码+系统+mysql+调试部署+lw
    前端程序员需要了解的MySQL
    远程连接centos 7 图形化桌面
    R语言统计与绘图:生存曲线的两两比较
    VR全景如何助力乡村振兴,VR全景推动农业发展
    在TX2平台编译安装飞桨Paddlepaddle
  • 原文地址:https://blog.csdn.net/qq_45032714/article/details/138158704