如何使用 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 实现授权?的主要内容,如果未能解决你的问题,请参考以下文章