如何使用 Telegram API 实现授权?

Posted

技术标签:

【中文标题】如何使用 Telegram API 实现授权?【英文标题】:How to implement authorization using a Telegram API? 【发布时间】:2015-08-20 02:46:32 【问题描述】:

我想使用 php 实现多重授权,以便与 Telegram REST API 交互。

我要解决什么任务?嗯,很简单:几十个用户(他们都有一个像这里这样的 carma(+10、-2、+1000 等)以及相关的组分类:网站管理员和客户)在我的网站上有一个用户个人资料。在他们达到一定数量的 carma 并且由于他们在个人资料中获得授权后,他们会加入基于自动为他们生成的 Telegram 的私人聊天。

经过一番研究,我发现它非常复杂,因为:

    我从来没有为硬件绑定的社交网络实现 API 的经验。

    我查看了https://core.telegram.org/api/auth,但完全不清楚如何使用 PHP 或任何其他语言实现这些功能(例如 auth.sendCode)。如果这些命令应该作为 JSON 发送到服务器,那么它看起来不像 JSON:

      auth.sentCode#efed51d9 phone_registered:Bool phone_code_hash:string send_call_timeout:int is_password:Bool = auth.SentCode;
    

    这是什么?是用什么语言写的?

    UPD: 它是用 TL(类型语言)编写的:https://core.telegram.org/mtproto/TL

    我探索了几个客户端(Webgram、Telegram-cli (tg)、tdesktop)的源代码,发现了https://core.telegram.org/mtproto的几个实现

不幸的是,他们都不支持多重授权,经过一些研究,我不知道在哪里更深入地了解更多信息。

此外,这些实现看起来庞大且复杂(例如,https://github.com/vysheng/tg):

我看到一堆服务器 (./tg/tgl/tgl.h):

#define TG_SERVER_1 "149.154.175.50"
#define TG_SERVER_2 "149.154.167.51"
#define TG_SERVER_3 "149.154.175.100"
#define TG_SERVER_4 "149.154.167.91"
#define TG_SERVER_5 "149.154.171.5"

我发现了几个可能合适的函数 (./tg/tgl/queries.c):

void empty_auth_file (void) 
  if (TLS->test_mode) 
    bl_do_dc_option (TLS, 1, "", 0, TG_SERVER_TEST_1, strlen (TG_SERVER_TEST_1), 443);
    bl_do_dc_option (TLS, 2, "", 0, TG_SERVER_TEST_2, strlen (TG_SERVER_TEST_2), 443);
    bl_do_dc_option (TLS, 3, "", 0, TG_SERVER_TEST_3, strlen (TG_SERVER_TEST_3), 443);
    bl_do_set_working_dc (TLS, TG_SERVER_TEST_DEFAULT);
   else 
    bl_do_dc_option (TLS, 1, "", 0, TG_SERVER_1, strlen (TG_SERVER_1), 443);
    bl_do_dc_option (TLS, 2, "", 0, TG_SERVER_2, strlen (TG_SERVER_2), 443);
    bl_do_dc_option (TLS, 3, "", 0, TG_SERVER_3, strlen (TG_SERVER_3), 443);
    bl_do_dc_option (TLS, 4, "", 0, TG_SERVER_4, strlen (TG_SERVER_4), 443);
    bl_do_dc_option (TLS, 5, "", 0, TG_SERVER_5, strlen (TG_SERVER_5), 443);
    bl_do_set_working_dc (TLS, TG_SERVER_DEFAULT);
  


void bl_do_dc_option (struct tgl_state *TLS, int id, const char *name, int l1, const char *ip, int l2, int port) 
  struct tgl_dc *DC = TLS->DC_list[id];
  if (DC && !strncmp (ip, DC->ip, l2))  return; 

  clear_packet ();
  out_int (CODE_binlog_dc_option);
  out_int (id);
  out_cstring (name, l1);
  out_cstring (ip, l2);
  out_int (port);

  add_log_event (TLS, packet_buffer, 4 * (packet_ptr - packet_buffer));

等等

我应该将哪些文件传输到 PHP 以实现多用户身份验证? 你能帮我知道从哪里开始以及如何使它比现在更容易吗?

提前谢谢你!

【问题讨论】:

您好,我这次尝试将PHP连接到电报没有成功,所以如果您对此案有任何改进,我会很高兴。请告诉我。 【参考方案1】:

到目前为止,我已经能够完全实现电报授权,但不是你要求的语言 - PHP,我使用的是 vb.Net。但是,我认为应该适用相同的逻辑。

创建电报授权密钥

Telegram API 不是在公园里散步。研究现有的 src 代码可能非常艰巨(恕我直言)。因此,我的方法是研究在线 API 文档并实现以下链接中列出的 sample-auth_key。

https://core.telegram.org/mtproto/auth_key

https://core.telegram.org/mtproto/samples-auth_key

这种方法将使您更好地理解和介绍整个 Telegram API 中使用的原语,并可能帮助您开始组织自己的一组函数和例程来处理您在接下来的步骤中需要处理的内容 - 实现其他功能API,因为生成 AuthKey 只是开始。

第 1 步

所有通信均通过 TCP - 一旦您获得唯一的 api_id (https://core.telegram.org/api/obtaining_api_id#obtaining-api-id),您将发现以下 IP 广告用于测试:149.154.167.40:433 不需要 api_id此时用于生成 AuthKey

设置发送/接收 TCP 处理循环的首选方法

我拥有的是一个私有的 SendData,它只是将一个字节发送到一个连接到上面给定 IP 地址的活动套接字

Private Sub SendData(b() As Byte, Optional read As Boolean = False)
    If Not IsConnected() Then
        Log("Connection Closed!", ConsoleColor.DarkRed)
        RaiseEvent Disconneted()
        Exit Sub
    End If
    
    b = TCPPack(b)
    
    Dim arg = New SocketAsyncEventArgs With .RemoteEndPoint = ep
    AddHandler arg.Completed, AddressOf IO_Handler
    arg.SetBuffer(b, 0, b.Length)
    
    Try
        If Not soc.SendAsync(arg) Then
            IO_Handler(soc, arg)
        End If
    
        If read Then
            ReadData()
        End If
    Catch ex As Exception
            Log("SendData: " & ex.ToString, ConsoleColor.Red)
    End Try

End Sub

Private Sub ReadData(Optional wait As Integer = 0)
    If Not IsConnected() Then
        Log("Connection Closed!", ConsoleColor.DarkRed)
        RaiseEvent Disconneted()
        Exit Sub
    End If

    Dim arg = New SocketAsyncEventArgs With .RemoteEndPoint = ep
    AddHandler arg.Completed, AddressOf IO_Handler

    Dim b(BUFFER_SIZE - 1) As Byte
    arg.SetBuffer(b, 0, BUFFER_SIZE)

    Try
        If Not soc.ReceiveAsync(arg) Then
            IO_Handler(soc, arg)
        End If
    Catch ex As Exception
        Log("ReadMessages: " & ex.ToString, ConsoleColor.Red)
    End Try
End Sub

Private Sub IO_Handler(sender As Object, e As SocketAsyncEventArgs)
    Log($"e.LastOperation:e.SocketError:e.BytesTransferred", ConsoleColor.Cyan)

    Select Case e.SocketError
        Case SocketError.Success
            Select Case e.LastOperation
                Case SocketAsyncOperation.Connect 'A socket Connect operation.
                    Log("Connected to " & e.ConnectSocket.RemoteEndPoint.ToString, ConsoleColor.Green)
                    are.Set()

                    Case SocketAsyncOperation.Disconnect, SocketAsyncOperation.Connect
                        RaiseEvent Disconneted()

                Case SocketAsyncOperation.Receive 'A socket Receive operation.
                        HandleData(e)
            End Select

        Case SocketError.ConnectionAborted
                RaiseEvent Disconneted()
    End Select
End Sub

Private Sub HandleData(e As SocketAsyncEventArgs)
    If e.BytesTransferred = 0 Then --no pending data
        Log("The remote end has closed the connection.")
        Exit Sub
    End If

    Dim len As Integer = e.Buffer(0)
    Dim start = 1

    If len = &H7F Then
        len = e.Buffer(1)
        len += e.Buffer(2) << 8
        len += e.Buffer(3) << 16
        start = 4
    End If

    len = 4 * len

    Dim data(len - 1) As Byte
    Array.Copy(e.Buffer, start, data, 0, len)


    ProcessResponse(data)

    ReadData()
End Sub

最后,对于这一步,我们需要一个 TcpPack() 方法,它可以帮助我们以 Telegram 期望的格式填充数据 - 请参见下面的 cmets 代码

Private Function TCPPack(b As Byte()) As Byte()
    Dim a = New List(Of Byte)
    Dim len = CByte(b.Length / 4)

    If efSent = False Then --TCP abridged version
        efSent = True
        a.Add(&HEF)
    End If

    If len >= &H7F Then
        a.Add(&H7F)
        a.AddRange(BitConverter.GetBytes(len))
    Else
        a.Add(len)
    End If

    a.AddRange(b) --only data, no sequence number, no CRC32

    Return a.ToArray
End Function

第 2 步

通过基本的 TCP 发送/接收例程设置,我们可以开始准备要发送到电报的数据包,并使用子例程来处理接收到的特定响应 - ProcessResponse(data)

接下来我们需要了解的是 Telegram 处理两大类消息的事实 -

未加密 - https://core.telegram.org/mtproto/description#unencrypted-message

这些是纯文本消息,其 auth_key_id =0 生成 AuthKey 始终使用这种类型的消息

加密 - https://core.telegram.org/mtproto/description#encrypted-message-encrypted-data

与电报服务器的所有进一步通信都将通过加密消息进行

我选择有两个类来封装这两种消息类型。然后我可以有两个处理每种类型的 Send(m) 方法

Private Sub Send(m As UnencryptedMessage)
    Log(m.ToString, ConsoleColor.DarkYellow, logTime:=False)
    SendData(m.data, True)
End Sub

Private Sub Send(m As EncryptedMessage)
    Log(m.ToString, ConsoleColor.DarkYellow, logTime:=False)
    SendData(m.data, True)
End Sub

目前只需要UnencryptedMessage

Public Class UnencryptedMessage
    Public Property auth_key_id As Int64
    Public Property message_id As Int64
    Public Property data_length As Int32
    Public Property message_data As Byte()
    Public Property message_type As String
    Public Property data As Byte() = 
    
    Sub New(auth_key As Int64, message_id As Int64, data As Byte())
        _auth_key_id = auth_key
        _message_id = message_id
        _data_length = data.Length
        _message_data = data
        message_type = B2Hr(data, 0, 4)
    
        Dim a = New List(Of Byte)
    
        a.AddRange(BitConverter.GetBytes(auth_key_id)) --0, 0, 0, 0, 0, 0, 0, 0
        a.AddRange(BitConverter.GetBytes(message_id))
        a.AddRange(BitConverter.GetBytes(data_length))
        a.AddRange(message_data)
    
        Me.data = a.ToArray
    End Sub
    
    Sub New(b As Byte())
        data = b
    
        Dim skip = 0
    
        _auth_key_id = BitConverter.ToInt64(b, skip) : skip += 8
        _message_id = BitConverter.ToInt64(b, skip) : skip += 8
        _data_length = BitConverter.ToInt32(b, skip) : skip += 4
    
        ReDim _message_data(_data_length - 1)
    
        Array.Copy(b, skip, _message_data, 0, b.Length - skip)
    
        message_type = B2Hr(_message_data, 0, 4)
    End Sub
    
    Public Overrides Function ToString() As String
            Return $"
        raw_data: B2H(data)
     auth_key_id: i2H(auth_key_id)  auth_key_id
      message_id: i2H(message_id)  message_id
     data_length: i2H(data_length)  data_length
    message_data: B2H(message_data)
    message_type: message_type
    "
    End Function
End Class

第 3 步

现在我们按照https://core.telegram.org/mtproto/auth_key中列出的一系列步骤进行操作

https://core.telegram.org/mtproto/auth_key#dh-exchange-initiation
    客户端向服务器发送查询

req_pq#60469778 nonce:int128 = ResPQ 选择nonce的值 由客户端随机(随机数)并识别客户端 在这种交流中。经过这一步,大家都知道了。

    服务器发送表单响应

resPQ#05162463 nonce:int128 server_nonce:int128 pq:string server_public_key_fingerprints:向量长 = ResPQ

我的方法很简单:

Sub RequestPQAuthorization()
    Send(MTProto.req_pq)
End Sub

在一个名为 MTProto 的类中,我实现了交换每个步骤所需的一组共享函数。每种方法都只是简单地构建一个加密数据结构,该数据结构将按上述方式发送到需要的地方

我们从:req_pq

开始
Shared Function req_pq(Optional nonce As Byte() = Nothing) As UnencryptedMessage
    --req_pq#60469778 
    --nonce:int128
    If nonce Is Nothing Then
        ReDim nonce(15)
        RND.NextBytes(nonce)
    End If

    Dim d = New List(Of Byte)
    d.AddRange(120, 151, 70, 96) --60469778
    d.AddRange(nonce)

    Return New UnencryptedMessage(0, CreateMessageId, d.ToArray)
End Function

Private Shared Function CreateMessageId() As Int64
    Return CLng((Date.UtcNow.Ticks - ZERO_TICK) * 429.4967296)
End Function

Public Const ZERO_TICK = 621355968000000000 - 即 1970-01-01T00:00:00Z(1970 年 1 月 1 日凌晨 12:00 UTC)

现在我们的流程响应方法来自步骤 1

Private Sub ProcessResponse(data As Byte())
    Try
        Dim r = New UnencryptedMessage(data)
        Log(r.ToString, ConsoleColor.Yellow, logTime:=False)

        Select Case r.message_type
            Case resPQ.Classid
                RequestDHKeyExchange(New resPQ(r.message_data))
            Case server_DH_params_ok.Classid
                RequestSetDH_params(New server_DH_params_ok(r.message_data), new_nonce)
            Case server_DH_params_fail.Classid
                Log(New server_DH_params_fail(r.message_data).ToString, ConsoleColor.DarkMagenta)
            Case dh_gen_ok.Classid
                Log(New dh_gen_ok(r.message_data).ToString, ConsoleColor.Green)
            Case dh_gen_retry.Classid
                Log(New dh_gen_retry(r.message_data).ToString, ConsoleColor.DarkMagenta)
            Case dh_gen_fail.Classid
                Log(New dh_gen_fail(r.message_data).ToString, ConsoleColor.DarkMagenta)
            Case Else
                Log($"Unhandled type: r.message_type", ConsoleColor.Magenta)
        End Select
    Catch ex As Exception
        Log($"Error: ex.ToString", ConsoleColor.Red)
        Log(B2H(data), ConsoleColor.DarkRed, logTime:=False)
    End Try
End Sub

到目前为止很好,收到的每个响应都有一个 message_type 代码。

我们可以打开它并确定如何处理它们。我们现在需要处理 resPQ。

我所做的是创建一组类,每个类都处理特定的响应类型

''' <summary>
''' resPQ#05162463 
''' nonce:int128 server_nonce:int128 pq:string server_public_key_fingerprints:Vector long = ResPQ
''' </summary>
Public NotInheritable Class resPQ : Inherits TLObject
    Public Shared Shadows ReadOnly Property Classid As String = "05162463"
    Public Property nonce As Byte()
    Public Property server_nonce As Byte()
    Public Property pq As Byte()
    Public Property fingerprints As List(Of UInt64)
    Public Property count As Int32

    Sub New(data As Byte())
        Dim skip = 4
        nonce = Slice(data, skip, 16) : skip += 16
        server_nonce = Slice(data, skip, 16) : skip += 16
        skip += 1 'length of pq:string
        pq = Slice(data, skip, 8) : skip += 8
        skip += 3 'padding to complete the 4-bytes
        skip += 4 '%(Vector long) 1cb5c415
        count = i32r(data, skip) : skip += 4

        fingerprints = New List(Of UInt64)

        For i = 0 To count - 1
            fingerprints.Add(u64r(data, skip))
        Next
    End Sub

    Public Overrides Function ToString() As String
        Return $"
     classid: NameOf(resPQ)#Classid
       nonce: B2H(nonce)
server_nonce: B2H(server_nonce)
          pq: B2H(pq)  u64(pq)
       count: i2H(count)  count
fingerprints: i2H(fingerprints(0))  fingerprints(0)
"
    End Function
End Class

每个都基于这个简单的对象

Public MustInherit Class TLObject
    Public Shared Property ClassId As String
    Public MustOverride Overrides Function ToString() As String
End Class

在此基础上,我们处理步骤 3 和 4

工作量证明 3) 客户将 pq 分解为素数,使得 p

这将启动一轮 Diffie-Hellman 密钥交换。

提交工作证明;服务器认证 4) 客户端发送查询 到服务器

req_DH_params#d712e4be nonce:int128 server_nonce:int128 p:string q:string public_key_fingerprint:long encrypted_data:string = Server_DH_Params

这是在RequestDHKeyExchange(New resPQ(r.message_data)) 上面我的ProcessResponse 例程中启动的

Sub RequestDHKeyExchange(r As resPQ)
    Log(r.ToString, ConsoleColor.Gray, logTime:=False)

    'decompose prime cofactors
    Dim pp = New PrimeProduct(r.pq)
    Log(pp.ToString, ConsoleColor.Gray, logTime:=False)

    'encrypted_data Generation
    Dim pq = New P_Q_inner_data(r.pq, pp.p, pp.q, r.nonce, r.server_nonce)
    new_nonce = pq.new_nonce

    'The serialization Of P_Q_inner_data produces some String data. This Is followed by encrypted_data
    'data_with_hash := SHA1(data) + data + (any random bytes); such that the length equal 255 
    Dim data_with_hash = New List(Of Byte)

    'SHA1(data) = xxx- 40 =20 bytes
    Using sha1 = New SHA1Managed
        Dim b = pq.ToBytes
        data_with_hash.AddRange(sha1.ComputeHash(b))
        data_with_hash.AddRange(b)
    End Using

    If data_with_hash.Count < 255 Then
        Dim pad(255 - data_with_hash.Count - 1) As Byte
        RND.NextBytes(pad)
        data_with_hash.AddRange(pad)
    End If

    'RSA(data_with_hash, server_public_key) = xxx - 512 = 256 bytes
    Dim key = i2H(r.fingerprints(0)) 'c3b42b026ce86b21
    Dim zb = Crypto.rsaEncrypt(data_with_hash.ToArray, key)
    Send(MTProto.req_DH_params(r.nonce, r.server_nonce, pp.p, pp.q, r.fingerprints(0), zb))
End Sub

您可以使用自己的 Prime-Decomposition 实现来替换这一行 Dim pp = New PrimeProduct(r.pq)

这是我如何使用 PollardBrent 学习的示例(Pollard Rho Brent 整数分解)https://***.com/a/31978350/44080

好的,如果你能跟进这一点,你就会大致了解我是如何逐步分解 AuthKey 实现的。

您应该能够完成剩余的步骤 5-9。我要打字很多......

如果到目前为止这个答案对任何人都有帮助,那么我会花时间整理并发布剩余部分。

我相信您在此过程中建立的例程和知识应该为您提供从头开始理解和实现自己的独立 Telegram API 代码所需的工具。

已完成交互转储

03:33:26.591  Connect:Success:0
03:33:26.593  Connected to 149.154.167.40:443
03:33:26.598
    raw_data: 000000000000000000DC799836FE075614000000789746604479257F6C01C039A3DEAD031BC2D6A4
 auth_key_id: 0000000000000000  0
  message_id: 5607FE369879DC00  6199202922538589184
 data_length: 00000014  20
message_data: 789746604479257F6C01C039A3DEAD031BC2D6A4
message_type: 60469778

03:33:26.600  Send:Success:42
03:33:26.735  Receive:Success:85
03:33:26.737
    raw_data: 0000000000000000015CF64539FE075640000000632416054479257F6C01C039A3DEAD031BC2D6A44F9DB065B36308CF4D9965725DD7153D0818DDCAF407B7CDCD00000015C4B51C01000000216BE86C022BB4C3
 auth_key_id: 0000000000000000  0
  message_id: 5607FE3945F65C01  6199202934039141377
 data_length: 00000040  64
message_data: 632416054479257F6C01C039A3DEAD031BC2D6A44F9DB065B36308CF4D9965725DD7153D0818DDCAF407B7CDCD00000015C4B51C01000000216BE86C022BB4C3
message_type: 05162463

03:33:26.743
     classid: resPQ#05162463
       nonce: 4479257F6C01C039A3DEAD031BC2D6A4
server_nonce: 4F9DB065B36308CF4D9965725DD7153D
          pq: 18DDCAF407B7CDCD  1791811376213642701
       count: 00000001  1
fingerprints: C3B42B026CE86B21  14101943622620965665

03:33:26.810
PQ: 18DDCAF407B7CDCD  1791811376213642701
 P: 45F57B87  1173715847
 Q: 5AFE490B  1526614283

03:33:26.930
    raw_data: 000000000000000000403CEE36FE075640010000BEE412D74479257F6C01C039A3DEAD031BC2D6A44F9DB065B36308CF4D9965725DD7153D0445F57B87000000045AFE490B000000216BE86C022BB4C3FE0001002DD190DDD93DFFC9EAF14DFAD3018D101E9E3EEC6C3FF4C7C1A067B32FB19AA2FDDFD087094947E793FA9F1A10A36A0B2916609811CFF1F345EE8FD9CDFFBCA4555E33A0446AB4A534500F621D112FCF59CAD4961BC87375F6835460B2E1B3B4088CE79843F7445DC5D87E0ACB0C4A979F68240C06358C4D2F95F86C0535CA643FBE8AF730E70BCBB54191D4F110E50D3244882722605657E808382445FA070A67AED1B2835238C05A00EBE960106838A284BC03D7A01453BA5355F06952F686263DD5B22B66524ED47F843340E9B7FC75BD58B6CC376C0B8B89E7292EDCC08D6CD0F1F9BF8418C2A58BC82B1928B051B3A0C20FA0AB22BA822EFABA6E141508
 auth_key_id: 0000000000000000  0
  message_id: 5607FE36EE3C4000  6199202923977392128
 data_length: 00000140  320
message_data: BEE412D74479257F6C01C039A3DEAD031BC2D6A44F9DB065B36308CF4D9965725DD7153D0445F57B87000000045AFE490B000000216BE86C022BB4C3FE0001002DD190DDD93DFFC9EAF14DFAD3018D101E9E3EEC6C3FF4C7C1A067B32FB19AA2FDDFD087094947E793FA9F1A10A36A0B2916609811CFF1F345EE8FD9CDFFBCA4555E33A0446AB4A534500F621D112FCF59CAD4961BC87375F6835460B2E1B3B4088CE79843F7445DC5D87E0ACB0C4A979F68240C06358C4D2F95F86C0535CA643FBE8AF730E70BCBB54191D4F110E50D3244882722605657E808382445FA070A67AED1B2835238C05A00EBE960106838A284BC03D7A01453BA5355F06952F686263DD5B22B66524ED47F843340E9B7FC75BD58B6CC376C0B8B89E7292EDCC08D6CD0F1F9BF8418C2A58BC82B1928B051B3A0C20FA0AB22BA822EFABA6E141508
message_type: D712E4BE

03:33:26.933  Send:Success:341
03:33:27.217  Receive:Success:656
03:33:27.217
    raw_data: 0000000000000000011C9A9F39FE0756780200005C07E8D04479257F6C01C039A3DEAD031BC2D6A44F9DB065B36308CF4D9965725DD7153DFE500200752C7BDBB6A58D68B76D2E20DCECF611B2837CA34F3688B242192C633FBBC1EC9348880DA6E6AFF42B256D8476A2C432B60E93218F5B84982B0F9800E6EF918AEC4B729AB1A67C82EF2C4D281352D1BEAEB6B9026CAA0CA8FB03F9257E2CA034471EE25CF6E214BB770E233566A67155BE8FB8F9DA0A76964CFD19E9C97D3E57AAA26E7A6C16B12F2B2BFD4C437857032F0A7198567B9CD3A54BD06CE61A1EBACD70D464185719BC8E0381C99E80A5783D389BE73E97166A328CEDB3AA4D722D453EB4CA893299E41DDC81C798BC76CAF070BFF144F6800D8FE5B3B6BCC9A1138E7ADA6DAF3F581AAB0137A6D40E640E76F6539B1450EA30A55E3F56C2C0A8DCC6F9F4D4F185D25AF37B46B9D9B8ED5CA257DD32EDE02FF95C6174C9D4BA1E30035723C7E2DED9EB0794AAA1913073E4EA2D5649C5C491B252AF88FF1D71EFB5E9FFCA921F0F27F72723DD5014359D08101278DF3F9A9A10DDE54B93A386C6844A6D15AF142DA956A3999458D10BBDE4E947BE949199F088B91175EC9EEE3C95AC47C96D802B0DC91AA6DB5B8A03E0985412DD23CD33FD961175CD271E02BF8A05A537E8FE21CDB40EBAAC0C8D4718DA4499D5B5EF935B848F92C25E9CAE76021758EDD1AA202A0D0DC357348B0474069002EB8F5F2760F2C5BEE38C7CEA07737C28864F647F2406BD55ABD58EEED97A4C8E659143441B1F8CB8DEFE457B46B5E76541CAB63FA1CD3626F0A45DB8A37964BF2613A6C64E6E6E478D44A2AF19CAD6C2686FD55EC85CACD645E58C364CBBD09EF1C7FE7420A8EF277982B87CA18D16B97980B14D24747D9BC86563DA81DA
 auth_key_id: 0000000000000000  0
  message_id: 5607FE399F9A1C01  6199202935543045121
 data_length: 00000278  632
message_data: 5C07E8D04479257F6C01C039A3DEAD031BC2D6A44F9DB065B36308CF4D9965725DD7153DFE500200752C7BDBB6A58D68B76D2E20DCECF611B2837CA34F3688B242192C633FBBC1EC9348880DA6E6AFF42B256D8476A2C432B60E93218F5B84982B0F9800E6EF918AEC4B729AB1A67C82EF2C4D281352D1BEAEB6B9026CAA0CA8FB03F9257E2CA034471EE25CF6E214BB770E233566A67155BE8FB8F9DA0A76964CFD19E9C97D3E57AAA26E7A6C16B12F2B2BFD4C437857032F0A7198567B9CD3A54BD06CE61A1EBACD70D464185719BC8E0381C99E80A5783D389BE73E97166A328CEDB3AA4D722D453EB4CA893299E41DDC81C798BC76CAF070BFF144F6800D8FE5B3B6BCC9A1138E7ADA6DAF3F581AAB0137A6D40E640E76F6539B1450EA30A55E3F56C2C0A8DCC6F9F4D4F185D25AF37B46B9D9B8ED5CA257DD32EDE02FF95C6174C9D4BA1E30035723C7E2DED9EB0794AAA1913073E4EA2D5649C5C491B252AF88FF1D71EFB5E9FFCA921F0F27F72723DD5014359D08101278DF3F9A9A10DDE54B93A386C6844A6D15AF142DA956A3999458D10BBDE4E947BE949199F088B91175EC9EEE3C95AC47C96D802B0DC91AA6DB5B8A03E0985412DD23CD33FD961175CD271E02BF8A05A537E8FE21CDB40EBAAC0C8D4718DA4499D5B5EF935B848F92C25E9CAE76021758EDD1AA202A0D0DC357348B0474069002EB8F5F2760F2C5BEE38C7CEA07737C28864F647F2406BD55ABD58EEED97A4C8E659143441B1F8CB8DEFE457B46B5E76541CAB63FA1CD3626F0A45DB8A37964BF2613A6C64E6E6E478D44A2AF19CAD6C2686FD55EC85CACD645E58C364CBBD09EF1C7FE7420A8EF277982B87CA18D16B97980B14D24747D9BC86563DA81DA
message_type: D0E8075C

03:33:27.240
     classid: server_DH_params_ok#D0E8075C
       nonce: 4479257F6C01C039A3DEAD031BC2D6A4
server_nonce: 4F9DB065B36308CF4D9965725DD7153D
  enc_answer: 752C7BDBB6A58D68B76D2E20DCECF611B2837CA34F3688B242192C633FBBC1EC9348880DA6E6AFF42B256D8476A2C432B60E93218F5B84982B0F9800E6EF918AEC4B729AB1A67C82EF2C4D281352D1BEAEB6B9026CAA0CA8FB03F9257E2CA034471EE25CF6E214BB770E233566A67155BE8FB8F9DA0A76964CFD19E9C97D3E57AAA26E7A6C16B12F2B2BFD4C437857032F0A7198567B9CD3A54BD06CE61A1EBACD70D464185719BC8E0381C99E80A5783D389BE73E97166A328CEDB3AA4D722D453EB4CA893299E41DDC81C798BC76CAF070BFF144F6800D8FE5B3B6BCC9A1138E7ADA6DAF3F581AAB0137A6D40E640E76F6539B1450EA30A55E3F56C2C0A8DCC6F9F4D4F185D25AF37B46B9D9B8ED5CA257DD32EDE02FF95C6174C9D4BA1E30035723C7E2DED9EB0794AAA1913073E4EA2D5649C5C491B252AF88FF1D71EFB5E9FFCA921F0F27F72723DD5014359D08101278DF3F9A9A10DDE54B93A386C6844A6D15AF142DA956A3999458D10BBDE4E947BE949199F088B91175EC9EEE3C95AC47C96D802B0DC91AA6DB5B8A03E0985412DD23CD33FD961175CD271E02BF8A05A537E8FE21CDB40EBAAC0C8D4718DA4499D5B5EF935B848F92C25E9CAE76021758EDD1AA202A0D0DC357348B0474069002EB8F5F2760F2C5BEE38C7CEA07737C28864F647F2406BD55ABD58EEED97A4C8E659143441B1F8CB8DEFE457B46B5E76541CAB63FA1CD3626F0A45DB8A37964BF2613A6C64E6E6E478D44A2AF19CAD6C2686FD55EC85CACD645E58C364CBBD09EF1C7FE7420A8EF277982B87CA18D16B97980B14D24747D9BC86563DA81DA

tmp_aes_key: 297CB750FF0052B67515B3F11B45F11F15D106BC25ED0027570D5B9D83102BFA
 tmp_aes_iv: CBDCF40A77B6A1C7CE74A1F8EC8E091A49FAD3B9A2499BFFFD084D537A53B36D
     answer: BA0D89B54479257F6C01C039A3DEAD031BC2D6A44F9DB065B36308CF4D9965725DD7153D03000000FE000100C71CAEB9C6B1C9048E6C522F70F13F73980D40238E3E21C14934D037563D930F48198A0AA7C14058229493D22530F4DBFA336F6E0AC925139543AED44CCE7C3720FD51F69458705AC68CD4FE6B6B13ABDC9746512969328454F18FAF8C595F642477FE96BB2A941D5BCD1D4AC8CC49880708FA9B378E3C4F3A9060BEE67CF9A4A4A695811051907E162753B56B0F6B410DBA74D8A84B2A14B3144E0EF1284754FD17ED950D5965B4B9DD46582DB1178D169C6BC465B0D6FF9CA3928FEF5B9AE4E418FC15E83EBEA0F87FA9FF5EED70050DED2849F47BF959D956850CE929851F0D8115F635B105EE2E4E15D04B2454BF6F4FADF034B10403119CD8E3B92FCC5BFE000100C49E858CA0107FF9B51DC88236370866BE4A69DDC2193930769C11722D2884CE5017AF60712B6BAC17F79DBA8701A25AAA901FDCB483C56A246C1CA7705FAA87F0AFD68EAC8FC5EC88307298DAF7252DD6D8630BF819D65F9E4B5624B6A05149B35B8509A63C2F2D05417F38DD0A90727F5D12CC4D213B5974C732FB261F6AC01426F2B7269C17230442AA8C9AFCCD927463C4EC8465F841D969F0C47FC270D8EC23B1F5D861EB6A5602CF6F87A02A56A4094E06509503CACE935461086668AC32E8C69A90EB19C3232B20635DFADFC6E4EDC11FA34A3E2E2BBA28DDCEF422120077D3A171A6A5B65744113AF0D0A1FC566D31DBBDB43F5DE35A7CE5F0BB0ECD39FE0756646CF781176C3EAC

     classid: Server_DH_inner_data#B5890DBA
       nonce: 4479257F6C01C039A3DEAD031BC2D6A4
server_nonce: 4F9DB065B36308CF4D9965725DD7153D
           g: 00000003  3
    dh_prime: C71CAEB9C6B1C9048E6C522F70F13F73980D40238E3E21C14934D037563D930F48198A0AA7C14058229493D22530F4DBFA336F6E0AC925139543AED44CCE7C3720FD51F69458705AC68CD4FE6B6B13ABDC9746512969328454F18FAF8C595F642477FE96BB2A941D5BCD1D4AC8CC49880708FA9B378E3C4F3A9060BEE67CF9A4A4A695811051907E162753B56B0F6B410DBA74D8A84B2A14B3144E0EF1284754FD17ED950D5965B4B9DD46582DB1178D169C6BC465B0D6FF9CA3928FEF5B9AE4E418FC15E83EBEA0F87FA9FF5EED70050DED2849F47BF959D956850CE929851F0D8115F635B105EE2E4E15D04B2454BF6F4FADF034B10403119CD8E3B92FCC5B
         g_a: C49E858CA0107FF9B51DC88236370866BE4A69DDC2193930769C11722D2884CE5017AF60712B6BAC17F79DBA8701A25AAA901FDCB483C56A246C1CA7705FAA87F0AFD68EAC8FC5EC88307298DAF7252DD6D8630BF819D65F9E4B5624B6A05149B35B8509A63C2F2D05417F38DD0A90727F5D12CC4D213B5974C732FB261F6AC01426F2B7269C17230442AA8C9AFCCD927463C4EC8465F841D969F0C47FC270D8EC23B1F5D861EB6A5602CF6F87A02A56A4094E06509503CACE935461086668AC32E8C69A90EB19C3232B20635DFADFC6E4EDC11FA34A3E2E2BBA28DDCEF422120077D3A171A6A5B65744113AF0D0A1FC566D31DBBDB43F5DE35A7CE5F0BB0ECD
 server_time: 5607FE39  1443364409
 client_time: 5607FE37  1443364407
     padding: 646CF781176C3EAC

DH_Prime is Safe? = True

     classid: Client_DH_Inner_Data#6643B654
       nonce: 4479257F6C01C039A3DEAD031BC2D6A4
server_nonce: 4F9DB065B36308CF4D9965725DD7153D
    retry_id: 0000000000000000  0
         g_b: 923A21384FE0318D569B2F2BEA667D1A999050A0A1B5AFDA39F2B890DEE45F9ED08E319C8243CD1496269CCF956DFA6C98633BDC2E26B1675C15D7904417EC2A74C687E682ED14182178BC0BD189F6E020131C87FD42A24798FCCD2416348EE0AAF534B652175BAC33E89C82874A8C3E8562815DDA213610167B10153EFC1BD1A0CFBACFEA22E3E8D80917F262D2C67BF1327A245CF7FE0E299F7517EE6A2F65568630A6191FEB0C1254F260A6554ED2BEE19E94AAB693E58DD032C26B9CAFEB0482F12DE2573B6E6D2816AC37ADDF3B99525FDBAF94690926320CC67ABF35D3EA6EC6CC7211BAF11FBDD6897959F6F1E3D4335B89B3024C1B3C0066246B5DCD

03:33:27.590  enc_data: 0A974C499344B093ADF321597858B1A6179E2A6C21F5FF9EB5DE687CDB57F8059509482FF9846FBE99D9411C13A645B26F73960424A13337D87DA879864FCA9D0883B643CF8EB594446038E0B6C4FD606D0CB77F1E00CCA6291DD65733F6A60217C7F366AD88972F107C381FD375F49DB57A2AB96988EC916629CD6F58B53F65DF4909AA773CCA43CE43671CA313528190213CF28A3B29BE26865BE22EB0C41E89CBD698C96CBC1B7B7F1586FBD61B422693859843F7D32083E3AB23D607FC4B874DB849F430F74483969ABA4603B483C94BCEB38F8EC90EEB58B338B325A8E37B57813CEC7E795B1B5517D732227856955C53BA18F52E55C6BCD8F1419D43D46DF2C2560B74BA7AA961BB4BDD09ABBC95E4F57AC4B8C89A67C7C5453A3EFB635D3977E0C3F0067C1F4D255F1F87E74A8E7E4272DFDEB9B85ABBEFA4953B2E0ECAA15C3C77773155C4013955BAB0D85F
03:33:27.810  auth_Key: 87A801A14AD6426E6AD56B638B315DF9F5B66F77333DC8C0FAADB77A1D51E71B68F5BB9B21DB275F2C4CA495E6440DDEACBDB199C52C327F7E2E9D78921E0D632CCA63DB6384FAF387E9D41717899EE5D54609C2F88573BBE8128FB5864CB62BC7F0ED250CBB57929AA5198FE568FC76FB846262A505B42D04BCB87C9EB24007CE9F9BDEB79391E7E9425F3A3D5028410E129C078EB8644EAB770F8705D8228CFAEAA4478A0D8E326971C7C2223074C4302C1F1DE5D08AC00CBEBEE41981B57A4248B517386DE68A51D01087F0E58D75A4C0FD2D031BC5BFC08651C4133494B572150EDD1C486153E8F51F99771DD57F55B3A5BBAE1874F25E69150C4E3C1397
03:33:27.813
    raw_data: 0000000000000000009C48D037FE0756780100001F5F04F54479257F6C01C039A3DEAD031BC2D6A44F9DB065B36308CF4D9965725DD7153DFE5001000A974C499344B093ADF321597858B1A6179E2A6C21F5FF9EB5DE687CDB57F8059509482FF9846FBE99D9411C13A645B26F73960424A13337D87DA879864FCA9D0883B643CF8EB594446038E0B6C4FD606D0CB77F1E00CCA6291DD65733F6A60217C7F366AD88972F107C381FD375F49DB57A2AB96988EC916629CD6F58B53F65DF4909AA773CCA43CE43671CA313528190213CF28A3B29BE26865BE22EB0C41E89CBD698C96CBC1B7B7F1586FBD61B422693859843F7D32083E3AB23D607FC4B874DB849F430F74483969ABA4603B483C94BCEB38F8EC90EEB58B338B325A8E37B57813CEC7E795B1B5517D732227856955C53BA18F52E55C6BCD8F1419D43D46DF2C2560B74BA7AA961BB4BDD09ABBC95E4F57AC4B8C89A67C7C5453A3EFB635D3977E0C3F0067C1F4D255F1F87E74A8E7E4272DFDEB9B85ABBEFA4953B2E0ECAA15C3C77773155C4013955BAB0D85F
 auth_key_id: 0000000000000000  0
  message_id: 5607FE37D0489C00  6199202927769852928
 data_length: 00000178  376
message_data: 1F5F04F54479257F6C01C039A3DEAD031BC2D6A44F9DB065B36308CF4D9965725DD7153DFE5001000A974C499344B093ADF321597858B1A6179E2A6C21F5FF9EB5DE687CDB57F8059509482FF9846FBE99D9411C13A645B26F73960424A13337D87DA879864FCA9D0883B643CF8EB594446038E0B6C4FD606D0CB77F1E00CCA6291DD65733F6A60217C7F366AD88972F107C381FD375F49DB57A2AB96988EC916629CD6F58B53F65DF4909AA773CCA43CE43671CA313528190213CF28A3B29BE26865BE22EB0C41E89CBD698C96CBC1B7B7F1586FBD61B422693859843F7D32083E3AB23D607FC4B874DB849F430F74483969ABA4603B483C94BCEB38F8EC90EEB58B338B325A8E37B57813CEC7E795B1B5517D732227856955C53BA18F52E55C6BCD8F1419D43D46DF2C2560B74BA7AA961BB4BDD09ABBC95E4F57AC4B8C89A67C7C5453A3EFB635D3977E0C3F0067C1F4D255F1F87E74A8E7E4272DFDEB9B85ABBEFA4953B2E0ECAA15C3C77773155C4013955BAB0D85F
message_type: F5045F1F

03:33:27.823  Send:Success:397
03:33:27.983  Receive:Success:73
03:33:27.985

....

问候。

【讨论】:

我实际上赞成你的回答。但我希望很多东西。我希望您使用一种更全球认可的语言(至少来自 C 系列),以使您的代码对于种子答案的人来说更加熟悉和可读。我也希望 Telegram 的 API 更容易学习和实现。它似乎有一个很大的学习曲线。 @SaeedNamati 对不起,vb.net 对我来说很自然。是的,电报的文档很难。这需要一些工作才能完成。 @RezaSh 嗨,我还没说完。这段时间一直在忙其他事情。但我可以发布完整的 AuthKey Generation。我会找时间上传到 Github @CharlesOkwuagwu 谢谢人,现在tg api文档很烂 也许像 C 系列语言或 python 这样的知名语言可能是更好的选择。无论如何谢谢你【参考方案2】:

作为我原始帖子的后续,一旦您完成了 auth_key 步骤,以下内容将有助于您快速了解电报其余部分的工作方式。

1) 下载学习Webogram的源码,基本都是javascript

2) 运行使用 console.logs 修改的 Webogram 的本地副本,以逐步清楚地向您展示“工作电报客户端”和电报服务器之间发生的交互。这将为您提供电报客户端和电报如何真正工作的工作流程。

3) 使用您最熟悉的任何开发语言来构建您自己的协议解析器实现,用于将二进制流转换为 TL 类型,反之亦然

编写这一步代码实际上很有趣。我刚刚在 Elixir

中构建了一个简单的协议解析器

4) 这是 Webogram 修改副本的示例日志。

它显示了成功生成 Auth_key 后要采取的步骤

你甚至可以看到它必须在哪里生成一个新的 Auth_key,因为它将经过验证的你切换到正确的数据中心,重新创建他的会话,新的 server_salts 等(未显示)

问候。

ID  time    info    log
121 12:26:35.318    new Auth    Auth successfull! dc= 2 mtproto.js:479:15
127 12:26:35.325    CALL    =>> API call help.getNearestDc Object    Object  dcID: 2, createNetworker: true  mtproto.js:749:4
128 12:26:35.327    enc-START   [invokeWithLayer] 45 mtproto.js:753:7
168 12:26:35.551    SEND    POST XHR http://149.154.167.51/apiw1 [HTTP/1.1 200 OK 708ms]
189 12:26:36.522    msg-r   <<=m [msg_container] Object  _: "msg_container", messages: Array[2]  mtproto.js:1452:5
190 12:26:36.523    msg-r   <<=m [message] Object  _: "message", msg_id: "6242200678614200321", seqno: 1, bytes: 28, body: Object  mtproto.js:1452:5
191 12:26:36.525    msg-r   <<=m [new_session_created] Object  _: "new_session_created", first_msg_id: "6242200671500883244", unique_id: "645797764649391412", server_salt: "17212767594123551779"  mtproto.js:1452:5
192 12:26:36.526    msg-r   <<=m [message] Object  _: "message", msg_id: "6242200678630513665", seqno: 3, bytes: 28, body: Object  mtproto.js:1452:5
193 12:26:36.528    msg-r   <<=m [rpc_result] Object  _: "rpc_result", req_msg_id: "6242200671500883244", result: Object  mtproto.js:1452:5
257 12:26:39.239    new Auth    Auth successfull! dc= 4 mtproto.js:479:15
270 12:26:59.606    CALL    =>> API call auth.sendCode Object  phone_number: "2348022002298", sms_type: 5, api_id: 38665, api_hash: "880c7847a517fc455d7d54731e90ad4e", lang_code: "en-US"  Object  dcID: 2, createNetworker: true  mtproto.js:749:4
321 12:27:00.048    SEND    POST XHR http://149.154.167.51/apiw1 [HTTP/1.1 200 OK 422ms]
328 12:27:00.981    msg-r   <<=m [rpc_result] Object  _: "rpc_result", req_msg_id: "6242200779464550396", result: Object  mtproto.js:1452:5
331 12:27:00.986    CALL    =>> API call auth.sendCode Object  phone_number: "2348022002298", sms_type: 5, api_id: 38665, api_hash: "880c7847a517fc455d7d54731e90ad4e", lang_code: "en-US"  Object  dcID: "4", createNetworker: true, resultType: "auth.SentCode", messageID: "6242200779464550396"  mtproto.js:749:4
332 12:27:00.987    enc-START   [invokeWithLayer] 45 mtproto.js:753:7
377 12:27:01.288    SEND    POST XHR http://149.154.167.91/apiw1 [HTTP/1.1 200 OK 321ms]
398 12:27:02.170    msg-r   <<=m [msg_container] Object  _: "msg_container", messages: Array[2]  mtproto.js:1452:5
399 12:27:02.171    msg-r   <<=m [message] Object  _: "message", msg_id: "6242200787684582401", seqno: 1, bytes: 28, body: Object  mtproto.js:1452:5
400 12:27:02.172    msg-r   <<=m [new_session_created] Object  _: "new_session_created", first_msg_id: "6242200784556418516", unique_id: "13396961033572361155", server_salt: "7076519506215495914"  mtproto.js:1452:5
401 12:27:02.173    msg-r   <<=m [message] Object  _: "message", msg_id: "6242200787775901697", seqno: 3, bytes: 48, body: Object  mtproto.js:1452:5
402 12:27:02.174    msg-r   <<=m [rpc_result] Object  _: "rpc_result", req_msg_id: "6242200784556418516", result: Object  mtproto.js:1452:5
407 12:27:02.344    SEND    POST XHR http://149.154.167.91/apiw1 [HTTP/1.1 200 OK 25154ms]
414 12:27:03.068    msg-r   <<=m [rpc_result] Object  _: "rpc_result", req_msg_id: "6242200779464550396"  mtproto.js:1452:5
420 12:27:15.639    CALL    =>> API call auth.sendSms Object  phone_number: "2348022002298", phone_code_hash: "696b5befd8e809de81"  Object  dcID: "4", createNetworker: true, resultType: "auth.SentCode", messageID: "6242200784556418516"  mtproto.js:749:4
468 12:27:15.924    SEND    POST XHR http://149.154.167.91/apiw1 [HTTP/1.1 200 OK 457ms]
475 12:27:17.154    msg-r   <<=m [rpc_result] Object  _: "rpc_result", req_msg_id: "6242200848242727644", result: true  mtproto.js:1452:5
482 12:27:27.511    msg-r   <<=m [rpc_result] Object  _: "rpc_result", req_msg_id: "6242200848242727644"  mtproto.js:1452:5
505 12:27:31.003    SEND    POST XHR http://149.154.167.51/apiw1 [HTTP/1.1 200 OK 25161ms]
511 12:27:40.133    CALL    =>> API call auth.signIn Object  phone_number: "2348022002298", phone_code_hash: "696b5befd8e809de81", phone_code: "26914"  Object  dcID: "4", createNetworker: true, resultType: "Bool", messageID: "6242200848242727644"  mtproto.js:749:4
560 12:27:40.454    SEND    POST XHR http://149.154.167.91/apiw1 [HTTP/1.1 200 OK 756ms]
567 12:27:41.223    msg-r   <<=m [msg_container] Object  _: "msg_container", messages: Array[2]  mtproto.js:1452:5
568 12:27:41.224    msg-r   <<=m [message] Object  _: "message", msg_id: "6242200956100910081", seqno: 7, bytes: 80, body: Object  mtproto.js:1452:5
569 12:27:41.225    msg-r   <<=m [rpc_result] Object  _: "rpc_result", req_msg_id: "6242200954555850604", result: Object  mtproto.js:1452:5
570 12:27:41.226    msg-r   <<=m [message] Object  _: "message", msg_id: "6242200956751929345", seqno: 9, bytes: 88, body: Object  mtproto.js:1452:5
571 12:27:41.227    msg-r   <<=m [updates] Object  _: "updates", updates: Array[1], users: Array[0], chats: Array[0], date: 1453375666, seq: 2  mtproto.js:1452:5
579 12:27:41.758    CALL    =>> API call updates.getState Object    Object  noErrorBox: true  mtproto.js:749:4
586 12:27:41.842    CALL    =>> API call account.updateStatus Object  offline: false  Object  noErrorBox: true  mtproto.js:749:4
594 12:27:41.850    CALL    =>> API call messages.getDialogs Object  offset_date: 0, offset_id: 0, offset_peer: Object, limit: 20  Object  timeout: 300  mtproto.js:749:4
655 12:27:42.965    CALL    =>> API call messages.getAllStickers Object  hash: ""  Object    mtproto.js:749:4
696 12:27:43.920    SEND    POST XHR http://149.154.167.91/apiw1 [HTTP/1.1 200 OK 908ms]
712 12:27:44.613    SEND    POST XHR http://149.154.167.91/apiw1 [HTTP/1.1 200 OK 303ms]
727 12:27:46.488    msg-r   <<=m [msg_container] Object  _: "msg_container", messages: Array[3]  mtproto.js:1452:5
728 12:27:46.489    msg-r   <<=m [message] Object  _: "message", msg_id: "6242200970862778369", seqno: 11, bytes: 36, body: Object  mtproto.js:1452:5
729 12:27:46.489    msg-r   <<=m [rpc_result] Object  _: "rpc_result", req_msg_id: "6242200960159395644", result: Object  mtproto.js:1452:5
730 12:27:46.490    msg-r   <<=m [message] Object  _: "message", msg_id: "6242200970891641857", seqno: 13, bytes: 776, body: Object  mtproto.js:1452:5
731 12:27:46.492    msg-r   <<=m [rpc_result] Object  _: "rpc_result", req_msg_id: "6242200960356118244", result: Object  mtproto.js:1452:5
732 12:27:46.494    msg-r   <<=m [message] Object  _: "message", msg_id: "6242200970897958913", seqno: 15, bytes: 16, body: Object  mtproto.js:1452:5
733 12:27:46.495    msg-r   <<=m [rpc_result] Object  _: "rpc_result", req_msg_id: "6242200960337591900", result: true  mtproto.js:1452:5
740 12:27:46.567    msg-r   <<=m [msg_container] Object  _: "msg_container", messages: Array[4]  mtproto.js:1452:5
741 12:27:46.568    msg-r   <<=m [message] Object  _: "message", msg_id: "6242200970862778369", seqno: 11, bytes: 36, body: Object  mtproto.js:1452:5
742 12:27:46.569    msg-r   <<=m [rpc_result] Object  _: "rpc_result", req_msg_id: "6242200960159395644"  mtproto.js:1452:5
743 12:27:46.569    msg-r   <<=m [message] Object  _: "message", msg_id: "6242200970891641857", seqno: 13, bytes: 776, body: Object  mtproto.js:1452:5
744 12:27:46.570    msg-r   <<=m [rpc_result] Object  _: "rpc_result", req_msg_id: "6242200960356118244"  mtproto.js:1452:5
745 12:27:46.571    msg-r   <<=m [message] Object  _: "message", msg_id: "6242200970897958913", seqno: 15, bytes: 16, body: Object  mtproto.js:1452:5
746 12:27:46.572    msg-r   <<=m [rpc_result] Object  _: "rpc_result", req_msg_id: "6242200960337591900"  mtproto.js:1452:5
747 12:27:46.573    msg-r   <<=m [message] Object  _: "message", msg_id: "6242200973791209473", seqno: 17, bytes: 76, body: Object  mtproto.js:1452:5
748 12:27:46.574    msg-r   <<=m [rpc_result] Object  _: "rpc_result", req_msg_id: "6242200964892679524", result: Object  mtproto.js:1452:5
754 12:27:46.584    CALL    =>> API call messages.getStickerSet Object  stickerset: Object  Object    mtproto.js:749:4
811 12:27:47.346    SEND    POST XHR http://149.154.167.91/apiw1 [HTTP/1.1 200 OK 539ms]
818 12:27:48.175    msg-r   <<=m [rpc_result] Object  _: "rpc_result", req_msg_id: "6242200981275507620", result: Object  mtproto.js:1452:5
857 12:27:49.351    SEND    POST XHR http://149.154.167.91/apiw1 [HTTP/1.1 200 OK 25141ms]
864 12:27:57.219    msg-r   <<=m [msgs_ack] Object  _: "msgs_ack", msg_ids: Array[0]  mtproto.js:1452:5
870 12:28:04.673    CALL    =>> API call messages.readHistory Object  peer: Object, max_id: 0  Object    mtproto.js:749:4
908 12:28:04.860    CALL    =>> API call messages.getHistory Object  peer: Object, offset_id: 16, add_offset: 0, limit: 20  Object  timeout: 300, noErrorBox: true  mtproto.js:749:4
922 12:28:05.713    SEND    POST XHR http://149.154.167.91/apiw1 [HTTP/1.1 200 OK 367ms]
929 12:28:06.096    msg-r   <<=m [rpc_result] Object  _: "rpc_result", req_msg_id: "6242201058769372356", result: Object  mtproto.js:1452:5
936 12:28:15.702    msg-r   <<=m [rpc_result] Object  _: "rpc_result", req_msg_id: "6242201058769372356"  mtproto.js:1452:5
977 12:28:16.122    SEND    POST XHR http://149.154.167.91/apiw1 [HTTP/1.1 200 OK 25170ms]
983 12:28:26.637    CALL    =>> API call account.updateStatus Object  offline: true  Object  noErrorBox: true  mtproto.js:749:4
1016    12:28:26.660    SEND    POST XHR http://149.154.167.91/apiw1 [HTTP/1.1 200 OK 302ms]
1023    12:28:27.062    msg-r   <<=m [rpc_result] Object  _: "rpc_result", req_msg_id: "6242201153183272948", result: true  mtproto.js:1452:5
1030    12:28:41.985    msg-r   <<=m [rpc_result] Object  _: "rpc_result", req_msg_id: "6242201153183272948"  mtproto.js:1452:5
1071    12:28:42.421    SEND    POST XHR http://149.154.167.91/apiw1 [HTTP/1.1 200 OK 25165ms]

【讨论】:

【参考方案3】:

我已经编写了一个 mtproto 的 PHP 实现,目前我已经成功实现了 TL 序列化/反序列化、tcp abridged/intermediate/full 连接、http/https 连接。

我已经为所有 mtproto 方法实现了 OOP 包装器、基于 Python/wolfram alpha/php 的素数生成模块、支持提及的 html/Markdown 解析、机器人 API 文件 ID 支持、使用回调或 getupdates 进行更新处理、机器人 API MTProto 对象转换、上传/下载包装器、机器人/用户的登录包装器(支持 2FA)、简单的错误处理、内部对等管理(您可以在 tg 中提供简单的机器人 API 聊天 ID、用户名或对等 ID -cli 格式来发送消息或调用其他 mtproto 方法),我目前正在开发一个不错的 Lua 包装器,以允许使用带有 MadelineProto 的 td-cli/tg-cli 机器人。

我还编写了一个类来为所有 mtproto 方法/构造函数/类型生成文档(可在https://daniil.it/MadelineProto/API_docs 获得)。 MadelineProto 可以序列化为文件,以便轻松存储会话。

如果有人感兴趣,或者想贡献,这里是github repo的链接:https://github.com/danog/MadelineProto

【讨论】:

这是唯一的实现。我要试一试:)【参考方案4】:

从 2018 年 2 月起,您可以在您的网站上使用官方 Telegram Login Widget。

【讨论】:

以上是关于如何使用 Telegram API 实现授权?的主要内容,如果未能解决你的问题,请参考以下文章

如何与 Telegram API 交互

如何使用 Telegram API 接收图像?

通过 API 自动将消息发布到 Telegram 频道

如何使用 Telegram Bot API 发送表情符号?

如何在 C# 中使用 Telegram API 发送消息

如何通过 Telegram Bot API 在消息中发送嵌入图像和文本