diff --git a/data/corefork.telegram.org/api/datacenter.html b/data/corefork.telegram.org/api/datacenter.html deleted file mode 100644 index 8e9f2cee13..0000000000 --- a/data/corefork.telegram.org/api/datacenter.html +++ /dev/null @@ -1,152 +0,0 @@ - - -
- -The servers are divided into several data centers (hereinafter “DCs”) in different parts of the world. -A complete list of proxy access points for these DCs may be obtained using help.getConfig:
-dcOption#18b7a10d flags:# ipv6:flags.0?true media_only:flags.1?true tcpo_only:flags.2?true cdn:flags.3?true static:flags.4?true id:int ip_address:string port:int secret:flags.10?bytes = DcOption;
-config#330b4067 flags:# phonecalls_enabled:flags.1?true default_p2p_contacts:flags.3?true preload_featured_stickers:flags.4?true ignore_phone_entities:flags.5?true revoke_pm_inbox:flags.6?true blocked_mode:flags.8?true pfs_enabled:flags.13?true date:int expires:int test_mode:Bool this_dc:int dc_options:Vector<DcOption> dc_txt_domain_name:string chat_size_max:int megagroup_size_max:int forwarded_count_max:int online_update_period_ms:int offline_blur_timeout_ms:int offline_idle_timeout_ms:int online_cloud_timeout_ms:int notify_cloud_delay_ms:int notify_default_delay_ms:int push_chat_period_ms:int push_chat_limit:int saved_gifs_limit:int edit_time_limit:int revoke_time_limit:int revoke_pm_time_limit:int rating_e_decay:int stickers_recent_limit:int stickers_faved_limit:int channels_read_media_period:int tmp_sessions:flags.0?int pinned_dialogs_count_max:int pinned_infolder_count_max:int call_receive_timeout_ms:int call_ring_timeout_ms:int call_connect_timeout_ms:int call_packet_timeout_ms:int me_url_prefix:string autoupdate_url_prefix:flags.7?string gif_search_username:flags.9?string venue_search_username:flags.10?string img_search_username:flags.11?string static_maps_provider:flags.12?string caption_length_max:int message_length_max:int webfile_dc_id:int suggested_lang_code:flags.2?string lang_pack_version:flags.2?int base_lang_pack_version:flags.2?int = Config;
----functions---
-help.getConfig#c4f9186b = Config;
-In this context, this_dc is the number of the current DC, dc_options is a list of all DCs available at the moment, each of which has an id, ip, and port for establishing a connection. Please note that ip and port may change frequently, based on proxy server load and the user's current location.
-Typically, each DC has at least one IPv4 and one IPv6 endpoint available.
To optimize client communication with the API, each client must use the connection to the closest access point for its main queries (sending messages, getting contacts, etc.). Therefore, knowing how to select a DC is required before communicating with the API.
-The auth.sendCode method is the basic entry point when registering a new user or authorizing an existing user. 95% of all redirection cases to a different DC will occur when invoking this method.
-The client does not yet know which DC it will be associated with; therefore, it establishes an encrypted connection to a random address and sends its query to that address. -Having received a phone_number from a client, we can find out whether or not it is registered in the system. If it is, then, if necessary, instead of sending a text message, we request that it establish a connection with a different DC first (PHONE_MIGRATE_X error). -If we do not yet have a user with this number, we examine its IP-address. We can use it to identify the closest DC. Again, if necessary, we redirect the user to a different DC (NETWORK_MIGRATE_X error).
-There are reserved phone number prefixes to test the correctness of the application's handling of redirects between DCs. Read more in User Authorization article.
-A file saved by a user with upload.saveFilePart will be available for direct download only from the DC where the query was executed. That is why each file has a dc_id parameter:
-document#1e87342b flags:# id:long access_hash:long file_reference:bytes date:int mime_type:string size:int thumbs:flags.0?Vector<PhotoSize> video_thumbs:flags.1?Vector<VideoSize> dc_id:int attributes:Vector<DocumentAttribute> = Document;
-photo#fb197a65 flags:# has_stickers:flags.0?true id:long access_hash:long file_reference:bytes date:int sizes:Vector<PhotoSize> video_sizes:flags.1?Vector<VideoSize> dc_id:int = Photo;
-
-encryptedFile#4a70994c id:long access_hash:long size:int dc_id:int key_fingerprint:int = EncryptedFile;
-
-userProfilePhoto#82d1f706 flags:# has_video:flags.0?true photo_id:long stripped_thumb:flags.1?bytes dc_id:int = UserProfilePhoto;
-chatPhoto#1c6e1c11 flags:# has_video:flags.0?true photo_id:long stripped_thumb:flags.1?bytes dc_id:int = ChatPhoto;
-To download the file, an encrypted connection to DC dc_id must be established and used to execute the upload.getFile query. -If an attempt is made to download the file over a wrong connection, the FILE_MIGRATE_X error will be returned.
-Please note that encryption keys are not copied between DCs; therefore, the process of establishing an encrypted connection is started from the very beginning for each new DC. An issued auth_key can be associated with the current authorized user by using an authorization transfer.
-During the process of working with the API, user information is accumulated in the DC with which the user is associated. This is the reason a user cannot be associated with a different DC by means of the client. However, in the future, during prolonged communication from an unusual location, we may decide that the user's data must be moved to a different DC. After some time, the data will be copied and the association will be updated. Once this happens, when executing any query transmitted to the old DC, the API will return the USER_MIGRATE_X error. The client will then have to establish a connection with the new DC and repeat the query.
-The following methods can be used to eliminate the need for users to enter the code from a text message every time:
-auth.exportedAuthorization#b434e2b8 id:long bytes:bytes = auth.ExportedAuthorization;
-auth.authorization#33fb7bb8 flags:# setup_password_required:flags.1?true otherwise_relogin_days:flags.1?int tmp_sessions:flags.0?int user:User = auth.Authorization;
----functions---
-auth.importAuthorization#a57a7dad id:long bytes:bytes = auth.Authorization;
-auth.exportAuthorization#e5bfffcd dc_id:int = auth.ExportedAuthorization;
-auth.exportAuthorization must be executed in the current DC (the DC with which a connection has already been established), passing in dc_id as the value for the new DC. The method should return the user identifier and a long string of random data. An import operation can be performed at the new DC by sending it what was received. Queries requiring authorization can then be successfully executed in the new DC.
You can accept payments from Telegram users via Telegram Bots.
---Note: This article is intended for MTProto API developers. If you're looking for a general overview of Telegram Payments, check out the Telegram blog and the bot API payment manual.
-
Telegram bots can accept payments for goods and services from users. -For more info on how payments work, check out the Telegram Blog and the bot API payment manual.
-This page will elaborate on the actions required to work with payments using the MTProto API.
---A simplified version of the process is available only for bots using the bot API.
-
The first step for bots is enable payments as described here ».
-Then, we work with payments as follows.
-inputWebDocument#9bed434d url:string size:int mime_type:string attributes:Vector<DocumentAttribute> = InputWebDocument;
-
-labeledPrice#cb296bf8 label:string amount:long = LabeledPrice;
-
-invoice#cd886e0 flags:# test:flags.0?true name_requested:flags.1?true phone_requested:flags.2?true email_requested:flags.3?true shipping_address_requested:flags.4?true flexible:flags.5?true phone_to_provider:flags.6?true email_to_provider:flags.7?true currency:string prices:Vector<LabeledPrice> max_tip_amount:flags.8?long suggested_tip_amounts:flags.8?Vector<long> = Invoice;
-
-inputMediaInvoice#d9799874 flags:# title:string description:string photo:flags.0?InputWebDocument invoice:Invoice payload:bytes provider:string provider_data:DataJSON start_param:flags.1?string = InputMedia;
-
----functions---
-
-messages.sendMedia#e25ff8e0 flags:# silent:flags.5?true background:flags.6?true clear_draft:flags.7?true noforwards:flags.14?true peer:InputPeer reply_to_msg_id:flags.0?int media:InputMedia message:string random_id:long reply_markup:flags.2?ReplyMarkup entities:flags.3?Vector<MessageEntity> schedule_date:flags.10?int send_as:flags.13?InputPeer = Updates;
-The user contacts the bot and requests to purchase something.
-The bot forms an inputMediaInvoice with an invoice constructor with a description of the goods or service, amount to be paid, as well as requested shipping info.
-The provider
parameter of the inputMediaInvoice constructor is where you put the token value that you've obtained earlier via Botfather. It is possible for one merchant bot to use several different tokens for different users or different goods and services.
Use the messages.sendMedia method to send the invoice.
-You can also attach an inline keyboard to the message using the reply_markup
field: if provided, the first button must be a keyboardButtonBuy button. Otherwise, an inline keyboard will be generated automatically, with a Pay 'total price'
keyboardButtonBuy as only button.
An invoice message with a pay button can only be sent to a private chat with the user. Groups and channels are not supported.
-keyboardButtonBuy#afd93fbb text:string = KeyboardButton;
-
-keyboardButtonRow#77608b83 buttons:Vector<KeyboardButton> = KeyboardButtonRow;
-replyInlineMarkup#48a30254 rows:Vector<KeyboardButtonRow> = ReplyMarkup;
-
-webDocument#1c570ed1 url:string access_hash:long size:int mime_type:string attributes:Vector<DocumentAttribute> = WebDocument;
-webDocumentNoProxy#f9c8bcc6 url:string size:int mime_type:string attributes:Vector<DocumentAttribute> = WebDocument;
-
-messageMediaInvoice#84551347 flags:# shipping_address_requested:flags.1?true test:flags.3?true title:string description:string photo:flags.0?WebDocument receipt_msg_id:flags.2?int currency:string total_amount:long start_param:string = MessageMedia;
-
-message#38116ee0 flags:# out:flags.1?true mentioned:flags.4?true media_unread:flags.5?true silent:flags.13?true post:flags.14?true from_scheduled:flags.18?true legacy:flags.19?true edit_hide:flags.21?true pinned:flags.24?true noforwards:flags.26?true id:int from_id:flags.8?Peer peer_id:Peer fwd_from:flags.2?MessageFwdHeader via_bot_id:flags.11?long reply_to:flags.3?MessageReplyHeader date:int message:string media:flags.9?MessageMedia reply_markup:flags.6?ReplyMarkup entities:flags.7?Vector<MessageEntity> views:flags.10?int forwards:flags.10?int replies:flags.23?MessageReplies edit_date:flags.15?int post_author:flags.16?string grouped_id:flags.17?long reactions:flags.20?MessageReactions restriction_reason:flags.22?Vector<RestrictionReason> ttl_period:flags.25?int = Message;
-
-updateNewMessage#1f2b0afd message:Message pts:int pts_count:int = Update;
-The user receives an updateNewMessage constructor from the bot, containing a messageMediaInvoice constructor with basic info about the product.
-The message will also have a replyInlineMarkup keyboard attached to it. -The the first button of the keyboard will always be a keyboardButtonBuy button.
-invoice#cd886e0 flags:# test:flags.0?true name_requested:flags.1?true phone_requested:flags.2?true email_requested:flags.3?true shipping_address_requested:flags.4?true flexible:flags.5?true phone_to_provider:flags.6?true email_to_provider:flags.7?true currency:string prices:Vector<LabeledPrice> max_tip_amount:flags.8?long suggested_tip_amounts:flags.8?Vector<long> = Invoice;
-
-paymentRequestedInfo#909c3f94 flags:# name:flags.0?string phone:flags.1?string email:flags.2?string shipping_address:flags.3?PostAddress = PaymentRequestedInfo;
-
-paymentSavedCredentialsCard#cdc27a1f id:string title:string = PaymentSavedCredentials;
-
-payments.paymentForm#1694761b flags:# can_save_credentials:flags.2?true password_missing:flags.3?true form_id:long bot_id:long invoice:Invoice provider_id:long url:string native_provider:flags.4?string native_params:flags.4?DataJSON saved_info:flags.0?PaymentRequestedInfo saved_credentials:flags.1?PaymentSavedCredentials users:Vector<User> = payments.PaymentForm;
-
----functions---
-
-payments.getPaymentForm#8a333c8d flags:# peer:InputPeer msg_id:int theme_params:flags.0?DataJSON = payments.PaymentForm;
-If the user clicks on the keyboardButtonBuy button, the client proceeds to call payments.getPaymentForm with the message ID of the invoice preview message to get the payment form.
-The returned form will contain fields that should be passed to the payment provider along with the full invoice. -The payment form also contains info about previously saved payment credentials and order information (name, phone number, email, shipping address & so on).
-The full invoice contains info about the information required for the order, the price and the currency, and whether this is a test
order.
invoice#cd886e0 flags:# test:flags.0?true name_requested:flags.1?true phone_requested:flags.2?true email_requested:flags.3?true shipping_address_requested:flags.4?true flexible:flags.5?true phone_to_provider:flags.6?true email_to_provider:flags.7?true currency:string prices:Vector<LabeledPrice> max_tip_amount:flags.8?long suggested_tip_amounts:flags.8?Vector<long> = Invoice;
-
-postAddress#1e8caaeb street_line1:string street_line2:string city:string state:string country_iso2:string post_code:string = PostAddress;
-
-paymentRequestedInfo#909c3f94 flags:# name:flags.0?string phone:flags.1?string email:flags.2?string shipping_address:flags.3?PostAddress = PaymentRequestedInfo;
-
-payments.validatedRequestedInfo#d1451883 flags:# id:flags.0?string shipping_options:flags.1?Vector<ShippingOption> = payments.ValidatedRequestedInfo;
-
----functions---
-
-payments.validateRequestedInfo#db103170 flags:# save:flags.0?true peer:InputPeer msg_id:int info:PaymentRequestedInfo = payments.ValidatedRequestedInfo;
-If any data at all is requested by the invoice (name_requested
, phone_requested
, email_requested
, shipping_address_requested
), the user must call payments.validateRequestedInfo, providing the required data (as usual, msg_id
is the ID of the invoice message).
-The user can choose to save order information for future use by setting the save
flag.
-Data can be autofilled as described in autofill.
If no errors are found in the submitted info, the response of the method will contain an id
flag, to be used later to complete the payment.
If the flexible
flag of the invoice is set, calling the payments.validateRequestedInfo method will send a shipping query update to the bot, to which the bot will reply with the available shipping options for the specified address as described here ».
-The return value in this case will also contain a shipping_options
field with the available shipping options.
If any errors are found in the submitted data, a service notification will be sent to the user, with a description of the error from the bot.
-payments.savedInfo#fb8fe43c flags:# has_saved_credentials:flags.1?true saved_info:flags.0?PaymentRequestedInfo = payments.SavedInfo;
-
----functions---
-
-payments.getSavedInfo#227d824b = payments.SavedInfo;
-payments.clearSavedInfo#d83d70c1 flags:# credentials:flags.0?true info:flags.1?true = Bool;
-The requested fields can be autofilled with the info provided in the saved_info
field of the payment form, or with the info fetched manually using payments.getSavedInfo.
Saved order information can also be cleared using payments.clearSavedInfo.
-labeledPrice#cb296bf8 label:string amount:long = LabeledPrice;
-
-shippingOption#b6213cdf id:string title:string prices:Vector<LabeledPrice> = ShippingOption;
-
-updateBotShippingQuery#b5aefd7d query_id:long user_id:long payload:bytes shipping_address:PostAddress = Update;
-
----functions---
-
-messages.setBotShippingResults#e5f672fa flags:# query_id:long error:flags.0?string shipping_options:flags.1?Vector<ShippingOption> = Bool;
-If a shipping address was requested and the bot included the parameter flexible
, when the user validates order information the Telegram API will send an updateBotShippingQuery to the bot.
-The bot must respond using messages.setBotShippingResults either with a list of possible delivery options and the relevant delivery prices, or with an error (for example, if delivery to the specified address is not possible).
The returned shipping options or the shipping error will be returned to the user while validating order information.
-inputPaymentCredentialsSaved#c10eb2cf id:string tmp_password:bytes = InputPaymentCredentials;
-inputPaymentCredentials#3417d728 flags:# save:flags.0?true data:DataJSON = InputPaymentCredentials;
-inputPaymentCredentialsApplePay#aa1c39f payment_data:DataJSON = InputPaymentCredentials;
-inputPaymentCredentialsGooglePay#8ac32801 payment_token:DataJSON = InputPaymentCredentials;
-
-
-payments.paymentForm#1694761b flags:# can_save_credentials:flags.2?true password_missing:flags.3?true form_id:long bot_id:long invoice:Invoice provider_id:long url:string native_provider:flags.4?string native_params:flags.4?DataJSON saved_info:flags.0?PaymentRequestedInfo saved_credentials:flags.1?PaymentSavedCredentials users:Vector<User> = payments.PaymentForm;
-inputPaymentCredentials#3417d728 flags:# save:flags.0?true data:DataJSON = InputPaymentCredentials;
-
-payments.paymentForm#1694761b flags:# can_save_credentials:flags.2?true password_missing:flags.3?true form_id:long bot_id:long invoice:Invoice provider_id:long url:string native_provider:flags.4?string native_params:flags.4?DataJSON saved_info:flags.0?PaymentRequestedInfo saved_credentials:flags.1?PaymentSavedCredentials users:Vector<User> = payments.PaymentForm;
-Typically, payment takes place by opening the url
in the specified payment form, which leads to a payment form on the website of the payment gateway.
-Once the user finishes entering their payment credentials, a payment_form_submit
web event is generated by the payment gateway, containing data
and title
JSON fields.
The title
is used by the client app to represent the payment credentials (typically a censored version of credit card information).
-The data
is used to generate an inputPaymentCredentials constructor.
-Eventually, you can set the save
flag to save the credit card info for future use, only if 2FA is enabled.
Telegram does not have access to your card information. Credit card details will be handled only by the payment system.
-inputPaymentCredentials#3417d728 flags:# save:flags.0?true data:DataJSON = InputPaymentCredentials;
-
-payments.paymentForm#1694761b flags:# can_save_credentials:flags.2?true password_missing:flags.3?true form_id:long bot_id:long invoice:Invoice provider_id:long url:string native_provider:flags.4?string native_params:flags.4?DataJSON saved_info:flags.0?PaymentRequestedInfo saved_credentials:flags.1?PaymentSavedCredentials users:Vector<User> = payments.PaymentForm;
-Most telegram apps support working natively with the native APIs of some payment providers, without opening the website of the payment and receiving a JS event.
-This is done using the JSON native_params
parameters field of the payments.paymentForm constructor, which contains an object, which can contain one or more of the following fields:
publishable_key
: Stripe API publishable keyapple_pay_merchant_id
: Apple Pay merchant IDandroid_pay_public_key
: Android Pay public keyandroid_pay_bgcolor
: Android Pay form background colorandroid_pay_inverse
: Whether to use the dark theme in the Android Pay formneed_country
: True, if the user country must be provided,need_zip
: True, if the user ZIP/postal code must be provided,need_cardholder_name
: True, if the cardholder name must be providedThe payment gateway to use is decided based on the value of the native_provider
field.
inputPaymentCredentials#3417d728 flags:# save:flags.0?true data:DataJSON = InputPaymentCredentials;
-
-payments.paymentForm#1694761b flags:# can_save_credentials:flags.2?true password_missing:flags.3?true form_id:long bot_id:long invoice:Invoice provider_id:long url:string native_provider:flags.4?string native_params:flags.4?DataJSON saved_info:flags.0?PaymentRequestedInfo saved_credentials:flags.1?PaymentSavedCredentials users:Vector<User> = payments.PaymentForm;
-If the native_provider
field is set and equal to stripe
, the client can make use of the native Stripe token APIs with the publishable_key
from the native_params
to add a payment method to Stripe, and then use the token type
and id
to generate a JSON object:
{"type":"token.type", "id":"token.id"}"
-The generated JSON object can then be passed to the data
field of the inputPaymentCredentials.
-Eventually, you can set the save
flag to save the credit card info for future use, only if 2FA is enabled.
Telegram does not have access to your card information. Credit card details will be handled only by the payment system.
-Example implementation: Telegram for Android.
-inputPaymentCredentialsApplePay#aa1c39f payment_data:DataJSON = InputPaymentCredentials;
-On iOS devices, Apple Pay can be used to generate payment data, which is then sent using the inputPaymentCredentialsApplePay constructor.
-Example implementation: Telegram for iOS.
-inputPaymentCredentialsGooglePay#8ac32801 payment_token:DataJSON = InputPaymentCredentials;
-On Android devices, Google Pay can be used to generate payment data, which is then sent using the inputPaymentCredentialsGooglePay constructor.
-Example implementation: Telegram for Android.
-inputPaymentCredentialsSaved#c10eb2cf id:string tmp_password:bytes = InputPaymentCredentials;
-
-paymentSavedCredentialsCard#cdc27a1f id:string title:string = PaymentSavedCredentials;
-
-payments.paymentForm#1694761b flags:# can_save_credentials:flags.2?true password_missing:flags.3?true form_id:long bot_id:long invoice:Invoice provider_id:long url:string native_provider:flags.4?string native_params:flags.4?DataJSON saved_info:flags.0?PaymentRequestedInfo saved_credentials:flags.1?PaymentSavedCredentials users:Vector<User> = payments.PaymentForm;
-
-account.tmpPassword#db64fd34 tmp_password:bytes valid_until:int = account.TmpPassword;
-
----functions---
-
-account.getTmpPassword#449e0b51 password:InputCheckPasswordSRP period:int = account.TmpPassword;
-To reuse saved payment methods, the saved_credentials
field of the payment form is used.
-The title
of the paymentSavedCredentialsCard can be used to preview a censored version of credit card info.
-The id
field is provided by the payment provider directly to the Telegram servers when saving the payment method, and identifies the payment method.
-Full credit card info is not saved on Telegram Servers, and cannot be fetched by the user.
In order to use the saved payment method, 2FA must be enabled: the user must verify their identity by entering their 2FA password, which is then used as described in the SRP docs to generate SRP parameters which must be passed to account.getTmpPassword.
-The generated temporary password can then be used to make payments using the saved credentials using the inputPaymentCredentialsSaved constructor.
-id
field is the paymentSavedCredentialsCard id
.tmp_password
is the temporary payment password generated by the server, if the user provided a correct 2FA password.Example implementation: Telegram for Android.
-inputPaymentCredentialsSaved#c10eb2cf id:string tmp_password:bytes = InputPaymentCredentials;
-inputPaymentCredentials#3417d728 flags:# save:flags.0?true data:DataJSON = InputPaymentCredentials;
-inputPaymentCredentialsApplePay#aa1c39f payment_data:DataJSON = InputPaymentCredentials;
-inputPaymentCredentialsGooglePay#8ac32801 payment_token:DataJSON = InputPaymentCredentials;
-
-payments.paymentResult#4e5f810d updates:Updates = payments.PaymentResult;
-payments.paymentVerificationNeeded#d8411139 url:string = payments.PaymentResult;
-
----functions---
-
-payments.sendPaymentForm#30c3bc9d flags:# form_id:long peer:InputPeer msg_id:int requested_info_id:flags.0?string shipping_option_id:flags.1?string credentials:InputPaymentCredentials tip_amount:flags.2?long = payments.PaymentResult;
-After verifying order information, the final step for the client is to call payments.sendPaymentForm, with the following parameters:
-msg_id
is set to the ID of the invoice messagerequested_info_id
is set to the id
of the verified order information, if it was requestedshipping_option_id
is set to the selected delivery option, if shipping was requested.credentials
are the payment credentials generated by the payment provider, required to complete the order.Payment method info can also be saved to the Telegram Servers and reused, by setting the save
flag of inputPaymentCredentials when sending the form.
-This is only possible on accounts with 2FA enabled.
The bot then replies to the received precheckout query, finally the user proceeds to checkout.
-Please note that if the result of the method is a payments.paymentVerificationNeeded, before proceeding to checkout the payment provider requires the user to verify his identity by opening the provided url
and following instructions.
-Once the user finishes working with the webpage, the client can proceed to checkout.
Eventual errors are returned in the form of RPC errors, with the description of the error by the bot contained in service updates.
-paymentRequestedInfo#909c3f94 flags:# name:flags.0?string phone:flags.1?string email:flags.2?string shipping_address:flags.3?PostAddress = PaymentRequestedInfo;
-
-updateBotPrecheckoutQuery#8caa9a96 flags:# query_id:long user_id:long payload:bytes info:flags.0?PaymentRequestedInfo shipping_option_id:flags.1?string currency:string total_amount:long = Update;
-
----functions---
-
-messages.setBotPrecheckoutResults#9c2dd95 flags:# success:flags.1?true query_id:long error:flags.0?string = Bool;
-The user enters their payment information as described above and presses the final pay button. -At this moment the Telegram API sends an updateBotPrecheckoutQuery constructor that contains all the available information about the order to the bot. -The bot must reply using messages.setBotPrecheckoutResults within 10 seconds after receiving this update or the transaction is canceled.
-The bot may return an error if it can't process the order for any reason. We highly recommend specifying a reason for failure to complete the order in human readable form (e.g. "Sorry, we're all out of rubber ducks! Would you be interested in a steel bear instead?"). Telegram will display this reason to the user.
-keyboardButtonBuy#afd93fbb text:string = KeyboardButton;
-
-keyboardButtonRow#77608b83 buttons:Vector<KeyboardButton> = KeyboardButtonRow;
-replyInlineMarkup#48a30254 rows:Vector<KeyboardButtonRow> = ReplyMarkup;
-
-messageMediaInvoice#84551347 flags:# shipping_address_requested:flags.1?true test:flags.3?true title:string description:string photo:flags.0?WebDocument receipt_msg_id:flags.2?int currency:string total_amount:long start_param:string = MessageMedia;
-
-message#38116ee0 flags:# out:flags.1?true mentioned:flags.4?true media_unread:flags.5?true silent:flags.13?true post:flags.14?true from_scheduled:flags.18?true legacy:flags.19?true edit_hide:flags.21?true pinned:flags.24?true noforwards:flags.26?true id:int from_id:flags.8?Peer peer_id:Peer fwd_from:flags.2?MessageFwdHeader via_bot_id:flags.11?long reply_to:flags.3?MessageReplyHeader date:int message:string media:flags.9?MessageMedia reply_markup:flags.6?ReplyMarkup entities:flags.7?Vector<MessageEntity> views:flags.10?int forwards:flags.10?int replies:flags.23?MessageReplies edit_date:flags.15?int post_author:flags.16?string grouped_id:flags.17?long reactions:flags.20?MessageReactions restriction_reason:flags.22?Vector<RestrictionReason> ttl_period:flags.25?int = Message;
-
-updateNewMessage#1f2b0afd message:Message pts:int pts_count:int = Update;
-
-payments.paymentReceipt#70c4fe03 flags:# date:int bot_id:long provider_id:long title:string description:string photo:flags.2?WebDocument invoice:Invoice info:flags.0?PaymentRequestedInfo shipping:flags.1?ShippingOption tip_amount:flags.3?long currency:string total_amount:long credentials_title:string users:Vector<User> = payments.PaymentReceipt;
-
----functions---
-
-payments.getPaymentReceipt#2478d1cc peer:InputPeer msg_id:int = payments.PaymentReceipt;
-In case the bot confirms the order, Telegram requests the payment provider to complete the transaction. If the payment information was entered correctly and the payment goes through, the Telegram API will modify the invoice message and send a service message as described below. Once your bot receives this message, it should proceed with delivering the goods or services purchased by the user.
-If all is OK, the user receives a payments.paymentResult in reply to the payments.sendPaymentForm query, containing info about the updated invoice message in the form of an updateEditMessage.
-The invoice message will be updated as follows: the attached messageMediaInvoice will now have a receipt_msg_id
field.
-Clients should treat invoice messages with a receipt_msg_id
field as receipt messages, locally modifying the label of the keyboardButtonBuy button to a localized version of the word Receipt
.
-From this point, clicking on the Receipt
button should trigger a call to payments.getPaymentReceipt, providing the receipt_msg_id
to the msg_id
field, which will return info about the transaction.
The payment will also generate one service message of type messageActionPaymentSent or messageActionPaymentSentMe, replying to the invoice. -For bots, the service message will be of type messageActionPaymentSentMe, for users it will be a messageActionPaymentSent.
-messageActionPaymentSentMe#8f31b327 flags:# currency:string total_amount:long payload:bytes info:flags.0?PaymentRequestedInfo shipping_option_id:flags.1?string charge:PaymentCharge = MessageAction;
-messageActionPaymentSent#40699cd0 currency:string total_amount:long = MessageAction;
Validated user-provided info
-{schema}
-Name | -Type | -Description | -
---|---|---|
flags | -# | -Flags, see TL conditional fields | -
id | -flags.0?string | -ID | -
shipping_options | -flags.1?Vector<ShippingOption> | -Shipping options | -
--Please feel free to check out our FAQ for the Technically Inclined. -Client developers are required to comply with the Security Guidelines.
-
This page deals with the basic layer of MTProto encryption used for Cloud chats (server-client encryption). See also:
- -The protocol is designed for access to a server API from applications running on mobile devices. It must be emphasized that a web browser is not such an application.
-The protocol is subdivided into three virtually independent components:
---As of version 4.6, major Telegram clients are using MTProto 2.0, described in this article. -MTProto v1.0 (described here for reference) is deprecated and is currently being phased out.
-
From the standpoint of the high-level component, the client and the server exchange messages inside a session. The session is attached to the client device (the application, to be more exact) rather than a specific websocket/http/https/tcp connection. In addition, each session is attached to a user key ID by which authorization is actually accomplished.
-Several connections to a server may be open; messages may be sent in either direction through any of the connections (a response to a query is not necessarily returned through the same connection that carried the original query, although most often, that is the case; however, in no case can a message be returned through a connection belonging to a different session). When the UDP protocol is used, a response might be returned by a different IP address than the one to which the query had been sent.
-There are several types of messages:
-From the standpoint of lower level protocols, a message is a binary data stream aligned along a 4 or 16-byte boundary. The first several fields in the message are fixed and are used by the cryptographic/authorization system.
-Each message, either individual or inside a container, consists of a message identifier (64 bits, see below), a message sequence number within a session (32 bits), the length (of the message body in bytes; 32 bits), and a body (any size which is a multiple of 4 bytes). In addition, when a container or a single message is sent, an internal header is added at the top (see below), then the entire message is encrypted, and an external header is placed at the top of the message (a 64-bit key identifier and a 128-bit message key).
-A message body normally consists of a 32-bit message type followed by type-dependent parameters. In particular, each RPC function has a corresponding message type. For more detail, see Binary Data Serialization, Mobile Protocol: Service Messages.
-All numbers are written as little endian. However, very large numbers (2048-bit) used in RSA and DH are written in the big endian format because that is how the OpenSSL library does it.
-Prior to a message (or a multipart message) being transmitted over a network using a transport protocol, it is encrypted in a certain way, and an external header is added at the top of the message which is: a 64-bit key identifier (that uniquely identifies an authorization key for the server as well as the user) and a 128-bit message key. A user key together with the message key defines an actual 256-bit key which is what encrypts the message using AES-256 encryption. Note that the initial part of the message to be encrypted contains variable data (session, message ID, sequence number, server salt) that obviously influences the message key (and thus the AES key and iv). The message key is defined as the 128 middle bits of the SHA256 of the message body (including session, message ID, etc.), including the padding bytes, prepended by 32 bytes taken from the authorization key. Multipart messages are encrypted as a single message.
---For a technical specification, see Mobile Protocol: Detailed Description
-
The first thing a client application must do is create an authorization key which is normally generated when it is first run and almost never changes.
-The protocol's principal drawback is that an intruder passively intercepting messages and then somehow appropriating the authorization key (for example, by stealing a device) will be able to decrypt all the intercepted messages post factum. This probably is not too much of a problem (by stealing a device, one could also gain access to all the information cached on the device without decrypting anything); however, the following steps could be taken to overcome this weakness:
-If client time diverges widely from server time, a server may start ignoring client messages, or vice versa, because of an invalid message identifier (which is closely related to creation time). Under these circumstances, the server will send the client a special message containing the correct time and a certain 128-bit salt (either explicitly provided by the client in a special RPC synchronization request or equal to the key of the latest message received from the client during the current session). This message could be the first one in a container that includes other messages (if the time discrepancy is significant but does not as yet result in the client's messages being ignored).
-Having received such a message or a container holding it, the client first performs a time synchronization (in effect, simply storing the difference between the server's time and its own to be able to compute the “correct” time in the future) and then verifies that the message identifiers for correctness.
-Where a correction has been neglected, the client will have to generate a new session to assure the monotonicity of message identifiers.
-Before being sent using the selected transport protocol, the payload has to be wrapped in a secondary protocol header, defined by the appropriate MTProto transport protocol.
- -The server recognizes these different protocols (and distinguishes them from HTTP, too) by the header. -Additionally, the following transport features can be used:
- -Example implementations for these protocols can be seen in tdlib and MadelineProto.
-Enables the delivery of encrypted containers together with the external header (hereinafter, Payload) from client to server and back. -Multiple transport protocols are defined:
-(We shall examine only the first five types.)
-To recap, using the ISO/OSI stack as comparison:
---This document describes MTProto v1.0, its status is DEPRECATED.
-
For information on encryption used in up-to-date Telegram clients, kindly see this document.
This page deals with the basic layer of MTProto encryption used for Cloud chats (server-client encryption). See also:
- -The protocol is designed for access to a server API from applications running on mobile devices. It must be emphasized that a web browser is not such an application.
-The protocol is subdivided into three virtually independent components:
---Got questions about this setup? — Check out the Advanced FAQ!
-
Each plaintext message to be encrypted in MTProto always contains the following data to be checked upon decryption in order to make the system robust against known problems with the components:
-See additional comments on our use of IGE, SHA-1 and message authentication.
-Telegram's End-to-end encrypted Secret Chats are using an additional layer of encryption on top of the described above. See Secret Chats, End-to-End encryption for details.
-From the standpoint of the high-level component, the client and the server exchange messages inside a session. The session is attached to the client device (the application, to be more exact) rather than a specific http/https/tcp connection. In addition, each session is attached to a user key ID by which authorization is actually accomplished.
-Several connections to a server may be open; messages may be sent in either direction through any of the connections (a response to a query is not necessarily returned through the same connection that carried the original query, although most often, that is the case; however, in no case can a message be returned through a connection belonging to a different session). When the UDP protocol is used, a response might be returned by a different IP address than the one to which the query had been sent.
-There are several types of messages:
-From the standpoint of lower level protocols, a message is a binary data stream aligned along a 4 or 16-byte boundary. The first several fields in the message are fixed and are used by the cryptographic/authorization system.
-Each message, either individual or inside a container, consists of a message identifier (64 bits, see below), a message sequence number within a session (32 bits), the length (of the message body in bytes; 32 bits), and a body (any size which is a multiple of 4 bytes). In addition, when a container or a single message is sent, an internal header is added at the top (see below), then the entire message is encrypted, and an external header is placed at the top of the message (a 64-bit key identifier and a 128-bit message key).
-A message body normally consists of a 32-bit message type followed by type-dependent parameters. In particular, each RPC function has a corresponding message type. For more detail, see Binary Data Serialization, Mobile Protocol: Service Messages.
-All numbers are written as little endian. However, very large numbers (2048-bit) used in RSA and DH are written in the big endian format because that is what the OpenSSL library does.
-Prior to a message (or a multipart message) being transmitted over a network using a transport protocol, it is encrypted in a certain way, and an external header is added at the top of the message which is: a 64-bit key identifier (that uniquely identifies an authorization key for the server as well as the user) and a 128-bit message key. A user key together with the message key defines an actual 256-bit key which is what encrypts the message using AES-256 encryption. Note that the initial part of the message to be encrypted contains variable data (session, message ID, sequence number, server salt) that obviously influences the message key (and thus the AES key and iv). The message key is defined as the 128 lower-order bits of the SHA1 of the message body (including session, message ID, etc.). Multipart messages are encrypted as a single message.
-For a technical specification, see Mobile Protocol: Detailed Description
The first thing a client application must do is create an authorization key which is normally generated when it is first run and almost never changes.
The protocol’s principal drawback is that an intruder passively intercepting messages and then somehow appropriating the authorization key (for example, by stealing a device) will be able to decrypt all the intercepted messages post factum. This probably is not too much of a problem (by stealing a device, one could also gain access to all the information cached on the device without decrypting anything); however, the following steps could be taken to overcome this weakness:
-If client time diverges widely from server time, a server may start ignoring client messages, or vice versa, because of an invalid message identifier (which is closely related to creation time). Under these circumstances, the server will send the client a special message containing the correct time and a certain 128-bit salt (either explicitly provided by the client in a special RPC synchronization request or equal to the key of the latest message received from the client during the current session). This message could be the first one in a container that includes other messages (if the time discrepancy is significant but does not as yet result in the client’s messages being ignored).
-Having received such a message or a container holding it, the client first performs a time synchronization (in effect, simply storing the difference between the server’s time and its own to be able to compute the “correct” time in the future) and then verifies that the message identifiers for correctness.
-Where a correction has been neglected, the client will have to generate a new session to assure the monotonicity of message identifiers.
-Enables the delivery of encrypted containers together with the external header (hereinafter, Payload) from client to server and back. There are three types of transport:
-We shall examine the first two types.
-Implemented over HTTP/1.1 (with keepalive) running over the traditional TCP Port 80. HTTPS is not used; the above encryption method is used instead.
-An HTTP connection is attached to a session (or rather, to session + key identifier) specified in the most recent user query received; normally, the session is the same in all queries, but crafty HTTP proxies may corrupt that. A server may not return a message into an HTTP connection unless it belongs to the same session, and unless it is the server’s turn (an HTTP request had been received from the client to which a response has not been sent yet).
-The overall arrangement is as follows. The client opens one or more keepalive HTTP connections to the server. If one or more messages need to be sent, they are made into a payload which is followed by a POST request to the URL/api to which the payload is transmitted as data. In addition, Content-Length
, Keepalive
, and Host
are valid HTTP headers.
Having received the query, the server may either wait a little while (if the query requires a response following a short timeout) or immediately return a dummy response (only acknowledging the receipt of the container). In any case, the response may contain any number of messages. The server may at the same time send out any other messages it might be holding for the session.
-In addition, there exists a special long poll RPC query (valid for HTTP connections only) which transmits maximum timeout T. If the server has messages for the session, they are returned immediately; otherwise, a wait state is entered until such time as the server has a message for the client or T seconds have elapsed. If no events occur in the span of T seconds, a dummy response is returned (special message).
-If a server needs to send a message to a client, it checks for an HTTP connection that belongs to the required session and is in the “answering an HTTP request” state (including long poll) whereupon the message is added to the response container for the connection and sent to the user. In a typical case, there is some additional wait time (50 milliseconds) against the eventuality that the server will soon have more messages for the session.
-If no suitable HTTP connection is available, the messages are placed in the current session’s send queue. However, they find their way there anyway until receipt is explicitly or indirectly confirmed by the client. For the HTTP protocol, sending the next query into the same HTTP connection is regarded as an implicit acknowledgment (not any more, the HTTP protocol also requires that explicit acknowledgments be sent); in other cases, the client must return an explicit acknowledgment within a reasonable time (it can be added to a container for the following request).
-Important: if the acknowledgment fails to arrive on time, the message can be resent (possibly, in a different container). The parties must autonomously be ready for this and must store the identifiers of the most recent messages received (and ignore such duplicates rather than repeat actions). In order not to have the identifiers stored forever, there exist special garbage collection messages that take advantage of message identifier monotonicity.
-If the send queue overflows or if messages stay in the queue for over 10 minutes, the server forgets them (or sends them to swap, no genius required). This may happen even faster, if the server is running out of buffer space (for example, because of serious network issues resulting in a large number of connections becoming severed).
-This is very similar to the HTTP transport. May also be implemented over Port 80 (to penetrate all firewalls) and even use the same server IP addresses. In this situation, the server understands whether HTTP or TCP protocol must be used for the connection, based on the first four incoming bytes (for HTTP, it is POST).
-When a TCP connection is created, it is assigned to the session (and the authorization key) transmitted in the first user message, and subsequently used exclusively for this session (multiplexing arrangements are not allowed).
-If a payload (packet) needs to be transmitted from server to client or from client to server, it is encapsulated as follows: 4 length bytes are added at the front (to include the length, the sequence number, and CRC32; always divisible by 4) and 4 bytes with the packet sequence number within this TCP connection (the first packet sent is numbered 0, the next one 1, etc.), and 4 CRC32 bytes at the end (length, sequence number, and payload together).
-There is an abridged version of the same protocol: if the client sends 0xef
as the first byte (important: only prior to the very first data packet), then packet length is encoded by a single byte (0x01..0x7e
= data length divided by 4; or 0x7f
followed by 3 length bytes (little endian) divided by 4) followed by the data themselves (sequence number and CRC32 not added). In this case, server responses look the same (the server does not send 0xef
as the first byte).
In case 4-byte data alignment is needed, an intermediate version of the original protocol may be used: if the client sends 0xeeeeeeee
as the first int (four bytes), then packet length is encoded always by four bytes as in the original version, but the sequence number and CRC32 are omitted, thus decreasing total packet size by 8 bytes.
The full, the intermediate and the abridged versions of the protocol have support for quick acknowledgment. In this case, the client sets the highest-order length bit in the query packet, and the server responds with a special 4 bytes as a separate packet. They are the 32 higher-order SHA1 bits of the encrypted portion of the packet with the most significant bit set to make clear that this is not the length of a regular server response packet; if the abridged version is used, bswap is applied to these four bytes.
-There are no implicit acknowledgments for the TCP transport: all messages must be acknowledged explicitly. Most frequently, acknowledgments are placed in a container with the next query or response if it is transmitted in short order. For example, this is almost always the case for client messages containing RPC queries: the acknowledgment normally arrives with the RPC response.
-In the event of an error, the server may send a packet whose payload consists of 4 bytes as the error code. For example, Error Code 403 corresponds to situations where the corresponding HTTP error would have been returned by the HTTP protocol.
-Below you will find the current MTProto TL-schema. More details on TL »
-See also the detailed schema in JSON »
-int ? = Int;
-long ? = Long;
-double ? = Double;
-string ? = String;
-
-vector {t:Type} # [ t ] = Vector t;
-
-int128 4*[ int ] = Int128;
-int256 8*[ int ] = Int256;
-
-resPQ#05162463 nonce:int128 server_nonce:int128 pq:bytes server_public_key_fingerprints:Vector<long> = ResPQ;
-
-p_q_inner_data_dc#a9f55f95 pq:bytes p:bytes q:bytes nonce:int128 server_nonce:int128 new_nonce:int256 dc:int = P_Q_inner_data;
-p_q_inner_data_temp_dc#56fddf88 pq:bytes p:bytes q:bytes nonce:int128 server_nonce:int128 new_nonce:int256 dc:int expires_in:int = P_Q_inner_data;
-
-server_DH_params_ok#d0e8075c nonce:int128 server_nonce:int128 encrypted_answer:bytes = Server_DH_Params;
-
-server_DH_inner_data#b5890dba nonce:int128 server_nonce:int128 g:int dh_prime:bytes g_a:bytes server_time:int = Server_DH_inner_data;
-
-client_DH_inner_data#6643b654 nonce:int128 server_nonce:int128 retry_id:long g_b:bytes = Client_DH_Inner_Data;
-
-dh_gen_ok#3bcbf734 nonce:int128 server_nonce:int128 new_nonce_hash1:int128 = Set_client_DH_params_answer;
-dh_gen_retry#46dc1fb9 nonce:int128 server_nonce:int128 new_nonce_hash2:int128 = Set_client_DH_params_answer;
-dh_gen_fail#a69dae02 nonce:int128 server_nonce:int128 new_nonce_hash3:int128 = Set_client_DH_params_answer;
-
-bind_auth_key_inner#75a3f765 nonce:long temp_auth_key_id:long perm_auth_key_id:long temp_session_id:long expires_at:int = BindAuthKeyInner;
-
-rpc_result#f35c6d01 req_msg_id:long result:Object = RpcResult;
-rpc_error#2144ca19 error_code:int error_message:string = RpcError;
-
-rpc_answer_unknown#5e2ad36e = RpcDropAnswer;
-rpc_answer_dropped_running#cd78e586 = RpcDropAnswer;
-rpc_answer_dropped#a43ad8b7 msg_id:long seq_no:int bytes:int = RpcDropAnswer;
-
-future_salt#0949d9dc valid_since:int valid_until:int salt:long = FutureSalt;
-future_salts#ae500895 req_msg_id:long now:int salts:vector<future_salt> = FutureSalts;
-
-pong#347773c5 msg_id:long ping_id:long = Pong;
-
-destroy_session_ok#e22045fc session_id:long = DestroySessionRes;
-destroy_session_none#62d350c9 session_id:long = DestroySessionRes;
-
-new_session_created#9ec20908 first_msg_id:long unique_id:long server_salt:long = NewSession;
-
-msg_container#73f1f8dc messages:vector<%Message> = MessageContainer;
-message msg_id:long seqno:int bytes:int body:Object = Message;
-msg_copy#e06046b2 orig_message:Message = MessageCopy;
-
-gzip_packed#3072cfa1 packed_data:bytes = Object;
-
-msgs_ack#62d6b459 msg_ids:Vector<long> = MsgsAck;
-
-bad_msg_notification#a7eff811 bad_msg_id:long bad_msg_seqno:int error_code:int = BadMsgNotification;
-bad_server_salt#edab447b bad_msg_id:long bad_msg_seqno:int error_code:int new_server_salt:long = BadMsgNotification;
-
-msg_resend_req#7d861a08 msg_ids:Vector<long> = MsgResendReq;
-msgs_state_req#da69fb52 msg_ids:Vector<long> = MsgsStateReq;
-msgs_state_info#04deb57d req_msg_id:long info:bytes = MsgsStateInfo;
-msgs_all_info#8cc0d131 msg_ids:Vector<long> info:bytes = MsgsAllInfo;
-msg_detailed_info#276d3ec6 msg_id:long answer_msg_id:long bytes:int status:int = MsgDetailedInfo;
-msg_new_detailed_info#809db6df answer_msg_id:long bytes:int status:int = MsgDetailedInfo;
-
-destroy_auth_key_ok#f660e1d4 = DestroyAuthKeyRes;
-destroy_auth_key_none#0a9f2259 = DestroyAuthKeyRes;
-destroy_auth_key_fail#ea109b13 = DestroyAuthKeyRes;
-
----functions---
-
-req_pq_multi#be7e8ef1 nonce:int128 = ResPQ;
-
-req_DH_params#d712e4be nonce:int128 server_nonce:int128 p:bytes q:bytes public_key_fingerprint:long encrypted_data:bytes = Server_DH_Params;
-
-set_client_DH_params#f5045f1f nonce:int128 server_nonce:int128 encrypted_data:bytes = Set_client_DH_params_answer;
-
-rpc_drop_answer#58e4a740 req_msg_id:long = RpcDropAnswer;
-get_future_salts#b921bd04 num:int = FutureSalts;
-ping#7abe77ec ping_id:long = Pong;
-ping_delay_disconnect#f3427b8c ping_id:long disconnect_delay:int = Pong;
-destroy_session#e7512126 session_id:long = DestroySessionRes;
-
-http_wait#9299359f max_delay:int wait_after:int max_wait:int = HttpWait;
-
-destroy_auth_key#d1435160 = DestroyAuthKeyRes;