diff --git a/td/generate/scheme/td_api.tl b/td/generate/scheme/td_api.tl index 1b1bfd68a..7a3f6b021 100644 --- a/td/generate/scheme/td_api.tl +++ b/td/generate/scheme/td_api.tl @@ -552,7 +552,7 @@ supergroupMembersFilterBots = SupergroupMembersFilter; //@date Point in time (Unix timestamp) when the link was created //@edit_date Point in time (Unix timestamp) when the link was last edited; 0 if never or unknown //@expire_date Point in time (Unix timestamp) when the link will expire; 0 if never -//@member_limit Maximum number of members, which can join the chat using the link simultaneously; 0 if not limited +//@member_limit The maximum number of members, which can join the chat using the link simultaneously; 0 if not limited //@member_count Number of chat members, which joined the chat using the link //@is_primary True, if the link is primary. Primary invite link can't have expire date or usage limit. There is exactly one primary invite link for each administrator with can_invite_users right at a given time //@is_revoked True, if the link was revoked @@ -1306,14 +1306,17 @@ bankCardInfo title:string actions:vector = BankCardInfo; address country_code:string state:string city:string street_line1:string street_line2:string postal_code:string = Address; -//@description Portion of the price of a product (e.g., "delivery cost", "tax amount") @label Label for this portion of the product price @amount Currency amount in minimal quantity of the currency +//@description Portion of the price of a product (e.g., "delivery cost", "tax amount") @label Label for this portion of the product price @amount Currency amount in the smallest units of the currency labeledPricePart label:string amount:int53 = LabeledPricePart; -//@description Product invoice @currency ISO 4217 currency code @price_parts A list of objects used to calculate the total price of the product @is_test True, if the payment is a test payment +//@description Product invoice @currency ISO 4217 currency code @price_parts A list of objects used to calculate the total price of the product +//@max_tip_amount The maximum allowed amount of tip in the smallest units of the currency +//@suggested_tip_amounts Suggested amounts of tip in the smallest units of the currency +//@is_test True, if the payment is a test payment //@need_name True, if the user's name is needed for payment @need_phone_number True, if the user's phone number is needed for payment @need_email_address True, if the user's email address is needed for payment //@need_shipping_address True, if the user's shipping address is needed for payment @send_phone_number_to_provider True, if the user's phone number will be sent to the provider //@send_email_address_to_provider True, if the user's email address will be sent to the provider @is_flexible True, if the total price depends on the shipping method -invoice currency:string price_parts:vector is_test:Bool need_name:Bool need_phone_number:Bool need_email_address:Bool need_shipping_address:Bool send_phone_number_to_provider:Bool send_email_address_to_provider:Bool is_flexible:Bool = Invoice; +invoice currency:string price_parts:vector max_tip_amount:int53 suggested_tip_amounts:vector is_test:Bool need_name:Bool need_phone_number:Bool need_email_address:Bool need_shipping_address:Bool send_phone_number_to_provider:Bool send_email_address_to_provider:Bool is_flexible:Bool = Invoice; //@description Order information @name Name of the user @phone_number Phone number of the user @email_address Email address of the user @shipping_address Shipping address for this order; may be null orderInfo name:string phone_number:string email_address:string shipping_address:address = OrderInfo; @@ -1667,7 +1670,7 @@ messageGame game:game = MessageContent; //@description A message with a poll @poll The poll description messagePoll poll:poll = MessageContent; -//@description A message with an invoice from a bot @title Product title @param_description Product description @photo Product photo; may be null @currency Currency for the product price @total_amount Product total price in the minimal quantity of the currency +//@description A message with an invoice from a bot @title Product title @param_description Product description @photo Product photo; may be null @currency Currency for the product price @total_amount Product total price in the smallest units of the currency //@start_parameter Unique invoice bot start_parameter. To share an invoice use the URL https://t.me/{bot_username}?start={start_parameter} @is_test True, if the invoice is a test invoice //@need_shipping_address True, if the shipping address should be specified @receipt_message_id The identifier of the message with the receipt, after the product has been purchased messageInvoice title:string description:string photo:photo currency:string total_amount:int53 start_parameter:string is_test:Bool need_shipping_address:Bool receipt_message_id:int53 = MessageContent; @@ -1729,11 +1732,11 @@ messageCustomServiceAction text:string = MessageContent; //@description A new high score was achieved in a game @game_message_id Identifier of the message with the game, can be an identifier of a deleted message @game_id Identifier of the game; may be different from the games presented in the message with the game @score New score messageGameScore game_message_id:int53 game_id:int64 score:int32 = MessageContent; -//@description A payment has been completed @invoice_message_id Identifier of the message with the corresponding invoice; can be an identifier of a deleted message @currency Currency for the price of the product @total_amount Total price for the product, in the minimal quantity of the currency +//@description A payment has been completed @invoice_message_id Identifier of the message with the corresponding invoice; can be an identifier of a deleted message @currency Currency for the price of the product @total_amount Total price for the product, in the smallest units of the currency messagePaymentSuccessful invoice_message_id:int53 currency:string total_amount:int53 = MessageContent; //@description A payment has been completed; for bots only @invoice_message_id Identifier of the message with the corresponding invoice; can be an identifier of a deleted message @currency Currency for price of the product -//@total_amount Total price for the product, in the minimal quantity of the currency @invoice_payload Invoice payload @shipping_option_id Identifier of the shipping option chosen by the user; may be empty if not applicable @order_info Information about the order; may be null +//@total_amount Total price for the product, in the smallest units of the currency @invoice_payload Invoice payload @shipping_option_id Identifier of the shipping option chosen by the user; may be empty if not applicable @order_info Information about the order; may be null //@telegram_payment_charge_id Telegram payment identifier @provider_payment_charge_id Provider payment identifier messagePaymentSuccessfulBot invoice_message_id:int53 currency:string total_amount:int53 invoice_payload:bytes shipping_option_id:string order_info:orderInfo telegram_payment_charge_id:string provider_payment_charge_id:string = MessageContent; @@ -3606,7 +3609,7 @@ updateNewInlineCallbackQuery id:int64 sender_user_id:int32 inline_message_id:str //@description A new incoming shipping query; for bots only. Only for invoices with flexible price @id Unique query identifier @sender_user_id Identifier of the user who sent the query @invoice_payload Invoice payload @shipping_address User shipping address updateNewShippingQuery id:int64 sender_user_id:int32 invoice_payload:string shipping_address:address = Update; -//@description A new incoming pre-checkout query; for bots only. Contains full information about a checkout @id Unique query identifier @sender_user_id Identifier of the user who sent the query @currency Currency for the product price @total_amount Total price for the product, in the minimal quantity of the currency +//@description A new incoming pre-checkout query; for bots only. Contains full information about a checkout @id Unique query identifier @sender_user_id Identifier of the user who sent the query @currency Currency for the product price @total_amount Total price for the product, in the smallest units of the currency //@invoice_payload Invoice payload @shipping_option_id Identifier of a shipping option chosen by the user; may be empty if not applicable @order_info Information about the order; may be null updateNewPreCheckoutQuery id:int64 sender_user_id:int32 currency:string total_amount:int53 invoice_payload:bytes shipping_option_id:string order_info:orderInfo = Update; @@ -4495,14 +4498,14 @@ replacePrimaryChatInviteLink chat_id:int53 = ChatInviteLink; //@description Creates a new invite link for a chat. Available for basic groups, supergroups, and channels. Requires administrator privileges and can_invite_users right in the chat //@chat_id Chat identifier //@expire_date Point in time (Unix timestamp) when the link will expire; pass 0 if never -//@member_limit Maximum number of chat members that can join the chat by the link simultaneously; 0-99999; pass 0 if not limited +//@member_limit The maximum number of chat members that can join the chat by the link simultaneously; 0-99999; pass 0 if not limited createChatInviteLink chat_id:int53 expire_date:int32 member_limit:int32 = ChatInviteLink; //@description Edits a non-primary invite link for a chat. Available for basic groups, supergroups, and channels. Requires administrator privileges and can_invite_users right in the chat for own links and owner privileges for other links //@chat_id Chat identifier //@invite_link Invite link to be edited //@expire_date Point in time (Unix timestamp) when the link will expire; pass 0 if never -//@member_limit Maximum number of chat members that can join the chat by the link simultaneously; 0-99999; pass 0 if not limited +//@member_limit The maximum number of chat members that can join the chat by the link simultaneously; 0-99999; pass 0 if not limited editChatInviteLink chat_id:int53 invite_link:string expire_date:int32 member_limit:int32 = ChatInviteLink; //@description Returns information about an invite link. Requires administrator privileges and can_invite_users right in the chat to get own links and owner privileges to get other links @@ -4519,11 +4522,11 @@ getChatInviteLinkCounts chat_id:int53 = ChatInviteLinkCounts; //@is_revoked Pass true if revoked links needs to be returned instead of active or expired //@offset_date Creation date of an invite link starting after which to return invite links; use 0 to get results from the beginning //@offset_invite_link Invite link starting after which to return invite links; use empty string to get results from the beginning -//@limit Maximum number of invite links to return +//@limit The maximum number of invite links to return getChatInviteLinks chat_id:int53 creator_user_id:int32 is_revoked:Bool offset_date:int32 offset_invite_link:string limit:int32 = ChatInviteLinks; //@description Returns chat members joined a chat by an invite link. Requires administrator privileges and can_invite_users right in the chat for own links and owner privileges for other links @chat_id Chat identifier @invite_link Invite link for which to return chat members -//@offset_member A chat member from which to return next chat members; use null to get results from the beginning @limit Maximum number of chat members to return +//@offset_member A chat member from which to return next chat members; use null to get results from the beginning @limit The maximum number of chat members to return getChatInviteLinkMembers chat_id:int53 invite_link:string offset_member:chatInviteLinkMember limit:int32 = ChatInviteLinkMembers; //@description Revokes invite link for a chat. Available for basic groups, supergroups, and channels. Requires administrator privileges and can_invite_users right in the chat for own links and owner privileges for other links. @@ -4629,7 +4632,7 @@ toggleGroupCallParticipantIsHandRaised group_call_id:int32 participant:MessageSe //@description Loads more group call participants. The loaded participants will be received through updates. Use the field groupCall.loaded_all_participants to check whether all participants has already been loaded //@group_call_id Group call identifier. The group call must be previously received through getGroupCall and must be joined or being joined -//@limit Maximum number of participants to load +//@limit The maximum number of participants to load loadGroupCallParticipants group_call_id:int32 limit:int32 = Ok; //@description Leaves a group call @group_call_id Group call identifier diff --git a/td/telegram/MessageContent.cpp b/td/telegram/MessageContent.cpp index 0321e53e3..f6c5c1cf4 100644 --- a/td/telegram/MessageContent.cpp +++ b/td/telegram/MessageContent.cpp @@ -1875,7 +1875,7 @@ static Result create_input_message_content( } message_invoice->invoice.price_parts.emplace_back(std::move(price->label_), price->amount_); if (price->amount_ < -MAX_AMOUNT || price->amount_ > MAX_AMOUNT) { - return Status::Error(400, "Too big amount of currency specified"); + return Status::Error(400, "Too big amount of the currency specified"); } total_amount += price->amount_; } @@ -1887,6 +1887,17 @@ static Result create_input_message_content( } message_invoice->total_amount = total_amount; + if (input_invoice->invoice_->max_tip_amount_ < 0 || input_invoice->invoice_->max_tip_amount_ > MAX_AMOUNT) { + return Status::Error(400, "Invalid max tip amount of the currency specified"); + } + for (auto tip_amount : input_invoice->invoice_->suggested_tip_amounts_) { + if (tip_amount < 0 || tip_amount > input_invoice->invoice_->max_tip_amount_) { + return Status::Error(400, "Invalid suggested tip amount of the currency specified"); + } + } + + message_invoice->invoice.max_tip_amount = input_invoice->invoice_->max_tip_amount_; + message_invoice->invoice.suggested_tip_amounts = std::move(input_invoice->invoice_->suggested_tip_amounts_); message_invoice->invoice.is_test = input_invoice->invoice_->is_test_; message_invoice->invoice.need_name = input_invoice->invoice_->need_name_; message_invoice->invoice.need_phone_number = input_invoice->invoice_->need_phone_number_; @@ -2295,13 +2306,17 @@ static tl_object_ptr get_input_invoice(const Invoice &inv if (invoice.is_flexible) { flags |= telegram_api::invoice::FLEXIBLE_MASK; } + if (invoice.max_tip_amount != 0) { + flags |= telegram_api::invoice::MAX_TIP_AMOUNT_MASK; + } auto prices = transform(invoice.price_parts, [](const LabeledPricePart &price) { return telegram_api::make_object(price.label, price.amount); }); return make_tl_object( flags, false /*ignored*/, false /*ignored*/, false /*ignored*/, false /*ignored*/, false /*ignored*/, - false /*ignored*/, false /*ignored*/, false /*ignored*/, invoice.currency, std::move(prices), 0, vector()); + false /*ignored*/, false /*ignored*/, false /*ignored*/, invoice.currency, std::move(prices), + invoice.max_tip_amount, vector(invoice.suggested_tip_amounts)); } static tl_object_ptr get_input_web_document(const FileManager *file_manager, diff --git a/td/telegram/Payments.cpp b/td/telegram/Payments.cpp index b56af5cbb..5f7d489df 100644 --- a/td/telegram/Payments.cpp +++ b/td/telegram/Payments.cpp @@ -129,9 +129,10 @@ static tl_object_ptr convert_invoice(tl_object_ptr(std::move(invoice->currency_), std::move(labeled_prices), is_test, need_name, - need_phone_number, need_email_address, need_shipping_address, - send_phone_number_to_provider, send_email_address_to_provider, is_flexible); + return make_tl_object( + std::move(invoice->currency_), std::move(labeled_prices), invoice->max_tip_amount_, + vector(invoice->suggested_tip_amounts_), is_test, need_name, need_phone_number, need_email_address, + need_shipping_address, send_phone_number_to_provider, send_email_address_to_provider, is_flexible); } static tl_object_ptr convert_payment_provider( @@ -574,7 +575,8 @@ bool operator==(const Invoice &lhs, const Invoice &rhs) { lhs.need_shipping_address == rhs.need_shipping_address && lhs.send_phone_number_to_provider == rhs.send_phone_number_to_provider && lhs.send_email_address_to_provider == rhs.send_email_address_to_provider && - lhs.is_flexible == rhs.is_flexible && lhs.currency == rhs.currency && lhs.price_parts == rhs.price_parts; + lhs.is_flexible == rhs.is_flexible && lhs.currency == rhs.currency && lhs.price_parts == rhs.price_parts && + lhs.max_tip_amount == rhs.max_tip_amount && lhs.suggested_tip_amounts == rhs.suggested_tip_amounts; } bool operator!=(const Invoice &lhs, const Invoice &rhs) { @@ -589,7 +591,9 @@ StringBuilder &operator<<(StringBuilder &string_builder, const Invoice &invoice) << (invoice.need_shipping_address ? ", needs shipping address" : "") << (invoice.send_phone_number_to_provider ? ", sends phone number to provider" : "") << (invoice.send_email_address_to_provider ? ", sends email address to provider" : "") << " in " - << invoice.currency << " with price parts " << format::as_array(invoice.price_parts) << "]"; + << invoice.currency << " with price parts " << format::as_array(invoice.price_parts) + << " and suggested tip amounts " << invoice.suggested_tip_amounts << " up to " + << invoice.max_tip_amount << "]"; } bool operator==(const Address &lhs, const Address &rhs) { diff --git a/td/telegram/Payments.h b/td/telegram/Payments.h index 200a4491f..96c6dd854 100644 --- a/td/telegram/Payments.h +++ b/td/telegram/Payments.h @@ -34,6 +34,8 @@ struct LabeledPricePart { struct Invoice { string currency; vector price_parts; + int64 max_tip_amount = 0; + vector suggested_tip_amounts; bool is_test = false; bool need_name = false; bool need_phone_number = false; diff --git a/td/telegram/Payments.hpp b/td/telegram/Payments.hpp index cc45116fb..330a880c2 100644 --- a/td/telegram/Payments.hpp +++ b/td/telegram/Payments.hpp @@ -28,6 +28,7 @@ void parse(LabeledPricePart &labeled_price_part, ParserT &parser) { template void store(const Invoice &invoice, StorerT &storer) { + bool has_tip = invoice.max_tip_amount != 0; BEGIN_STORE_FLAGS(); STORE_FLAG(invoice.is_test); STORE_FLAG(invoice.need_name); @@ -37,13 +38,19 @@ void store(const Invoice &invoice, StorerT &storer) { STORE_FLAG(invoice.is_flexible); STORE_FLAG(invoice.send_phone_number_to_provider); STORE_FLAG(invoice.send_email_address_to_provider); + STORE_FLAG(has_tip); END_STORE_FLAGS(); store(invoice.currency, storer); store(invoice.price_parts, storer); + if (has_tip) { + store(invoice.max_tip_amount, storer); + store(invoice.suggested_tip_amounts, storer); + } } template void parse(Invoice &invoice, ParserT &parser) { + bool has_tip; BEGIN_PARSE_FLAGS(); PARSE_FLAG(invoice.is_test); PARSE_FLAG(invoice.need_name); @@ -53,9 +60,14 @@ void parse(Invoice &invoice, ParserT &parser) { PARSE_FLAG(invoice.is_flexible); PARSE_FLAG(invoice.send_phone_number_to_provider); PARSE_FLAG(invoice.send_email_address_to_provider); + PARSE_FLAG(has_tip); END_PARSE_FLAGS(); parse(invoice.currency, parser); parse(invoice.price_parts, parser); + if (has_tip) { + parse(invoice.max_tip_amount, parser); + parse(invoice.suggested_tip_amounts, parser); + } } template