Add high level support for pre-checkout queries and service messages for successful payments (#67)

* Add high level support for pre-checkout queries

* Add high level support for incoming payments

* Update and fix documentation

---------

Co-authored-by: KurimuzonAkuma <31959970+KurimuzonAkuma@users.noreply.github.com>
This commit is contained in:
coglione 2024-06-01 00:01:22 +02:00 committed by GitHub
parent ff3d53e142
commit a46e4d593b
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
19 changed files with 616 additions and 10 deletions

View File

@ -345,6 +345,7 @@ def pyrogram_api():
set_chat_menu_button
get_chat_menu_button
answer_web_app_query
answer_pre_checkout_query
""",
business="""
Business
@ -507,6 +508,7 @@ def pyrogram_api():
GiveawayResult
GiftCode
CheckedGiftCode
SuccessfulPayment
""",
bot_keyboards="""
Bot keyboards
@ -531,6 +533,9 @@ def pyrogram_api():
RequestChatInfo
RequestUserInfo
RequestPollInfo
PaymentInfo
PreCheckoutQuery
ShippingAddress
""",
bot_commands="""
Bot commands
@ -701,6 +706,10 @@ def pyrogram_api():
InlineQuery
InlineQuery.answer
""",
pre_checkout_query="""
PreCheckoutQuery
PreCheckoutQuery.answer
""",
chat_join_request="""
ChatJoinRequest
ChatJoinRequest.approve

View File

@ -88,6 +88,19 @@ InlineQuery
{inline_query_toctree}
PreCheckoutQuery
-----------
.. hlist::
:columns: 2
{pre_checkout_query_hlist}
.. toctree::
:hidden:
{pre_checkout_query_toctree}
ChatJoinRequest
---------------

View File

@ -27,7 +27,7 @@ from pyrogram import utils
from pyrogram import raw
from pyrogram.handlers import (
CallbackQueryHandler, MessageHandler, EditedMessageHandler, DeletedMessagesHandler,
UserStatusHandler, RawUpdateHandler, InlineQueryHandler, PollHandler,
UserStatusHandler, RawUpdateHandler, InlineQueryHandler, PollHandler, PreCheckoutQueryHandler,
ChosenInlineResultHandler, ChatMemberUpdatedHandler, ChatJoinRequestHandler, StoryHandler
)
from pyrogram.raw.types import (
@ -35,7 +35,7 @@ from pyrogram.raw.types import (
UpdateBotNewBusinessMessage, UpdateBotEditBusinessMessage, UpdateBotDeleteBusinessMessage,
UpdateEditMessage, UpdateEditChannelMessage,
UpdateDeleteMessages, UpdateDeleteChannelMessages,
UpdateBotCallbackQuery, UpdateInlineBotCallbackQuery,
UpdateBotCallbackQuery, UpdateInlineBotCallbackQuery, UpdateBotPrecheckoutQuery,
UpdateUserStatus, UpdateBotInlineQuery, UpdateMessagePoll,
UpdateBotInlineSend, UpdateChatParticipant, UpdateChannelParticipant,
UpdateBotChatInviteRequester, UpdateStory
@ -56,6 +56,7 @@ class Dispatcher:
CHOSEN_INLINE_RESULT_UPDATES = (UpdateBotInlineSend,)
CHAT_JOIN_REQUEST_UPDATES = (UpdateBotChatInviteRequester,)
NEW_STORY_UPDATES = (UpdateStory,)
PRE_CHECKOUT_QUERY_UPDATES = (UpdateBotPrecheckoutQuery,)
def __init__(self, client: "pyrogram.Client"):
self.client = client
@ -144,6 +145,12 @@ class Dispatcher:
StoryHandler
)
async def pre_checkout_query_parser(update, users, chats):
return (
await pyrogram.types.PreCheckoutQuery._parse(self.client, update, users),
PreCheckoutQueryHandler
)
self.update_parsers = {
Dispatcher.NEW_MESSAGE_UPDATES: message_parser,
Dispatcher.EDIT_MESSAGE_UPDATES: edited_message_parser,
@ -155,7 +162,8 @@ class Dispatcher:
Dispatcher.CHOSEN_INLINE_RESULT_UPDATES: chosen_inline_result_parser,
Dispatcher.CHAT_MEMBER_UPDATES: chat_member_updated_parser,
Dispatcher.CHAT_JOIN_REQUEST_UPDATES: chat_join_request_parser,
Dispatcher.NEW_STORY_UPDATES: story_parser
Dispatcher.NEW_STORY_UPDATES: story_parser,
Dispatcher.PRE_CHECKOUT_QUERY_UPDATES: pre_checkout_query_parser
}
self.update_parsers = {key: value for key_tuple, value in self.update_parsers.items() for key in key_tuple}

View File

@ -102,6 +102,9 @@ class MessageServiceType(AutoName):
REQUESTED_CHAT = auto()
"Requested chat"
SUCCESSFUL_PAYMENT = auto()
"Successful payment"
CHAT_TTL_CHANGED = auto()
"Chat TTL changed"

View File

@ -22,7 +22,7 @@ from typing import Callable, Union, List, Pattern
import pyrogram
from pyrogram import enums
from pyrogram.types import Message, CallbackQuery, InlineQuery, InlineKeyboardMarkup, ReplyKeyboardMarkup, Update
from pyrogram.types import Message, CallbackQuery, InlineQuery, PreCheckoutQuery, InlineKeyboardMarkup, ReplyKeyboardMarkup, Update
class Filter:
@ -788,6 +788,17 @@ video_chat_members_invited = create(video_chat_members_invited_filter)
"""Filter messages for voice chat invited members"""
# endregion
# region successful_payment_filter
async def successful_payment_filter(_, __, m: Message):
return bool(m.successful_payment)
successful_payment = create(successful_payment_filter)
"""Filter messages for successful payments"""
# endregion
# region service_filter
@ -801,7 +812,7 @@ service = create(service_filter)
A service message contains any of the following fields set: *left_chat_member*,
*new_chat_title*, *new_chat_photo*, *delete_chat_photo*, *group_chat_created*, *supergroup_chat_created*,
*channel_chat_created*, *migrate_to_chat_id*, *migrate_from_chat_id*, *pinned_message*, *game_score*,
*video_chat_started*, *video_chat_ended*, *video_chat_members_invited*.
*video_chat_started*, *video_chat_ended*, *video_chat_members_invited*, *successful_payment*.
"""
@ -939,6 +950,7 @@ def regex(pattern: Union[str, Pattern], flags: int = 0):
- :obj:`~pyrogram.types.Message`: The filter will match ``text`` or ``caption``.
- :obj:`~pyrogram.types.CallbackQuery`: The filter will match ``data``.
- :obj:`~pyrogram.types.InlineQuery`: The filter will match ``query``.
- :obj:`~pyrogram.types.PreCheckoutQuery`: The filter will match ``payload``.
When a pattern matches, all the `Match Objects <https://docs.python.org/3/library/re.html#match-objects>`_ are
stored in the ``matches`` field of the update object itself.
@ -958,6 +970,8 @@ def regex(pattern: Union[str, Pattern], flags: int = 0):
value = update.data
elif isinstance(update, InlineQuery):
value = update.query
elif isinstance(update, PreCheckoutQuery):
value = update.payload
else:
raise ValueError(f"Regex filter doesn't work with {type(update)}")

View File

@ -26,6 +26,7 @@ from .edited_message_handler import EditedMessageHandler
from .inline_query_handler import InlineQueryHandler
from .message_handler import MessageHandler
from .poll_handler import PollHandler
from .pre_checkout_query_handler import PreCheckoutQueryHandler
from .raw_update_handler import RawUpdateHandler
from .story_handler import StoryHandler
from .user_status_handler import UserStatusHandler

View File

@ -0,0 +1,49 @@
# Pyrogram - Telegram MTProto API Client Library for Python
# Copyright (C) 2017-present Dan <https://github.com/delivrance>
#
# This file is part of Pyrogram.
#
# Pyrogram is free software: you can redistribute it and/or modify
# it under the terms of the GNU Lesser General Public License as published
# by the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# Pyrogram is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU Lesser General Public License for more details.
#
# You should have received a copy of the GNU Lesser General Public License
# along with Pyrogram. If not, see <http://www.gnu.org/licenses/>.
from typing import Callable
from .handler import Handler
class PreCheckoutQueryHandler(Handler):
"""The PreCheckoutQueryHandler handler class. Used to handle pre-checkout queries coming from buy buttons.
It is intended to be used with :meth:`~pyrogram.Client.add_handler`
For a nicer way to register this handler, have a look at the
:meth:`~pyrogram.Client.on_pre_checkout_query` decorator.
Parameters:
callback (``Callable``):
Pass a function that will be called when a new PreCheckoutQuery arrives. It takes *(client, pre_checkout_query)*
as positional arguments (look at the section below for a detailed description).
filters (:obj:`Filters`):
Pass one or more filters to allow only a subset of callback queries to be passed
in your callback function.
Other parameters:
client (:obj:`~pyrogram.Client`):
The Client itself, useful when you want to call other API methods inside the message handler.
pre_checkout_query (:obj:`~pyrogram.types.PreCheckoutQuery`):
The received callback query.
"""
def __init__(self, callback: Callable, filters=None):
super().__init__(callback, filters)

View File

@ -18,6 +18,7 @@
from .answer_callback_query import AnswerCallbackQuery
from .answer_inline_query import AnswerInlineQuery
from .answer_pre_checkout_query import AnswerPreCheckoutQuery
from .answer_web_app_query import AnswerWebAppQuery
from .delete_bot_commands import DeleteBotCommands
from .get_bot_commands import GetBotCommands
@ -50,6 +51,7 @@ class Bots(
GetBotDefaultPrivileges,
SetChatMenuButton,
GetChatMenuButton,
AnswerWebAppQuery
AnswerWebAppQuery,
AnswerPreCheckoutQuery
):
pass

View File

@ -0,0 +1,64 @@
# Pyrogram - Telegram MTProto API Client Library for Python
# Copyright (C) 2017-present Dan <https://github.com/delivrance>
#
# This file is part of Pyrogram.
#
# Pyrogram is free software: you can redistribute it and/or modify
# it under the terms of the GNU Lesser General Public License as published
# by the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# Pyrogram is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU Lesser General Public License for more details.
#
# You should have received a copy of the GNU Lesser General Public License
# along with Pyrogram. If not, see <http://www.gnu.org/licenses/>.
import pyrogram
from pyrogram import raw
class AnswerPreCheckoutQuery:
async def answer_pre_checkout_query(
self: "pyrogram.Client",
pre_checkout_query_id: str,
success: bool = None,
error: str = None
):
"""Send answers to pre-checkout queries.
.. include:: /_includes/usable-by/bots.rst
Parameters:
pre_checkout_query_id (``str``):
Unique identifier for the query to be answered.
success (``bool``, *optional*):
Set this flag if everything is alright (goods are available, etc.) and the bot is ready to proceed with the order.
Otherwise do not set it, and set the error field, instead.
error (``str``, *optional*):
Error message in human readable form that explains the reason for failure to proceed with the checkout.
Required if ``success`` isn't set.
Returns:
``bool``: True, on success.
Example:
.. code-block:: python
# Proceed with the order
await app.answer_pre_checkout_query(query_id, success=True)
# Answer with error message
await app.answer_pre_checkout_query(query_id, error=error)
"""
return await self.invoke(
raw.functions.messages.SetBotPrecheckoutResults(
query_id=int(pre_checkout_query_id),
success=success or None,
error=error or None
)
)

View File

@ -38,7 +38,7 @@ class GetChatMember:
chat_id (``int`` | ``str``):
Unique identifier (int) or username (str) of the target chat.
user_id (``int`` | ``str``)::
user_id (``int`` | ``str``):
Unique identifier (int) or username (str) of the target user.
For you yourself you can simply use "me" or "self".
For a contact that exists in your Telegram address book you can use his phone number (str).

View File

@ -26,6 +26,7 @@ from .on_edited_message import OnEditedMessage
from .on_inline_query import OnInlineQuery
from .on_message import OnMessage
from .on_poll import OnPoll
from .on_pre_checkout_query import OnPreCheckoutQuery
from .on_raw_update import OnRawUpdate
from .on_user_status import OnUserStatus
from .on_story import OnStory
@ -44,6 +45,7 @@ class Decorators(
OnChosenInlineResult,
OnChatMemberUpdated,
OnChatJoinRequest,
OnStory
OnStory,
OnPreCheckoutQuery
):
pass

View File

@ -0,0 +1,61 @@
# Pyrogram - Telegram MTProto API Client Library for Python
# Copyright (C) 2017-present Dan <https://github.com/delivrance>
#
# This file is part of Pyrogram.
#
# Pyrogram is free software: you can redistribute it and/or modify
# it under the terms of the GNU Lesser General Public License as published
# by the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# Pyrogram is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU Lesser General Public License for more details.
#
# You should have received a copy of the GNU Lesser General Public License
# along with Pyrogram. If not, see <http://www.gnu.org/licenses/>.
from typing import Callable, Optional, Union
import pyrogram
from pyrogram.filters import Filter
class OnPreCheckoutQuery:
def on_pre_checkout_query(
self: Union["OnPreCheckoutQuery", Filter, None] = None,
filters: Optional[Filter] = None,
group: int = 0,
) -> Callable:
"""Decorator for handling pre-checkout queries.
This does the same thing as :meth:`~pyrogram.Client.add_handler` using the
:obj:`~pyrogram.handlers.PreCheckoutQueryHandler`.
Parameters:
filters (:obj:`~pyrogram.filters`, *optional*):
Pass one or more filters to allow only a subset of callback queries to be passed
in your function.
group (``int``, *optional*):
The group identifier, defaults to 0.
"""
def decorator(func: Callable) -> Callable:
if isinstance(self, pyrogram.Client):
self.add_handler(pyrogram.handlers.PreCheckoutQueryHandler(func, filters), group)
elif isinstance(self, Filter) or self is None:
if not hasattr(func, "handlers"):
func.handlers = []
func.handlers.append(
(
pyrogram.handlers.PreCheckoutQueryHandler(func, self),
group if filters is None else filters
)
)
return func
return decorator

View File

@ -32,7 +32,7 @@ class UnblockUser:
.. include:: /_includes/usable-by/users.rst
Parameters:
user_id (``int`` | ``str``)::
user_id (``int`` | ``str``):
Unique identifier (int) or username (str) of the target user.
For you yourself you can simply use "me" or "self".
For a contact that exists in your Telegram address book you can use his phone number (str).

View File

@ -37,6 +37,8 @@ from .menu_button import MenuButton
from .menu_button_commands import MenuButtonCommands
from .menu_button_default import MenuButtonDefault
from .menu_button_web_app import MenuButtonWebApp
from .payment_info import PaymentInfo
from .pre_checkout_query import PreCheckoutQuery
from .reply_keyboard_markup import ReplyKeyboardMarkup
from .reply_keyboard_remove import ReplyKeyboardRemove
from .request_channel_info import RequestChannelInfo
@ -45,6 +47,8 @@ from .request_user_info import RequestUserInfo
from .request_poll_info import RequestPollInfo
from .requested_chats import RequestedChats
from .sent_web_app_message import SentWebAppMessage
from .shipping_address import ShippingAddress
from .successful_payment import SuccessfulPayment
from .web_app_info import WebAppInfo
__all__ = [
@ -77,5 +81,9 @@ __all__ = [
"MenuButtonCommands",
"MenuButtonWebApp",
"MenuButtonDefault",
"SentWebAppMessage"
"SentWebAppMessage",
"ShippingAddress",
"PaymentInfo",
"PreCheckoutQuery",
"SuccessfulPayment"
]

View File

@ -0,0 +1,51 @@
# Pyrogram - Telegram MTProto API Client Library for Python
# Copyright (C) 2017-present Dan <https://github.com/delivrance>
#
# This file is part of Pyrogram.
#
# Pyrogram is free software: you can redistribute it and/or modify
# it under the terms of the GNU Lesser General Public License as published
# by the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# Pyrogram is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU Lesser General Public License for more details.
#
# You should have received a copy of the GNU Lesser General Public License
# along with Pyrogram. If not, see <http://www.gnu.org/licenses/>.
from ..object import Object
class PaymentInfo(Object):
"""Contains information about a payment.
Parameters:
name (``str``, *optional*):
User's name.
phone_number (``str``, *optional*):
User's phone number.
email (``str``, *optional*):
User's email.
shipping_address (:obj:`~pyrogram.types.ShippingAddress`, *optional*):
User's shipping address.
"""
def __init__(
self, *,
name: str = None,
phone_number: str = None,
email: str = None,
shipping_address: "types.ShippingAddress" = None
):
super().__init__()
self.name = name
self.phone_number = phone_number
self.email = email
self.shipping_address = shipping_address

View File

@ -0,0 +1,139 @@
# Pyrogram - Telegram MTProto API Client Library for Python
# Copyright (C) 2017-present Dan <https://github.com/delivrance>
#
# This file is part of Pyrogram.
#
# Pyrogram is free software: you can redistribute it and/or modify
# it under the terms of the GNU Lesser General Public License as published
# by the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# Pyrogram is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU Lesser General Public License for more details.
#
# You should have received a copy of the GNU Lesser General Public License
# along with Pyrogram. If not, see <http://www.gnu.org/licenses/>.
from typing import Union, List, Match, Optional
import pyrogram
from pyrogram import raw, enums
from pyrogram import types
from ..object import Object
from ..update import Update
from ... import utils
class PreCheckoutQuery(Object, Update):
"""An incoming pre-checkout query from a buy button in an inline keyboard.
Parameters:
id (``str``):
Unique identifier for this query.
from_user (:obj:`~pyrogram.types.User`):
User who sent the query.
currency (``str``):
Three-letter ISO 4217 currency code.
total_amount (``int``):
Total price in the smallest units of the currency.
payload (``str``):
Bot specified invoice payload.
shipping_option_id (``str``, *optional*):
Identifier of the shipping option chosen by the user.
payment_info (:obj:`~pyrogram.types.PaymentInfo`, *optional*):
Payment information provided by the user.
"""
def __init__(
self,
*,
client: "pyrogram.Client" = None,
id: str,
from_user: "types.User",
currency: str,
total_amount: int,
payload: str,
shipping_option_id: str = None,
payment_info: "types.PaymentInfo" = None
):
super().__init__(client)
self.id = id
self.from_user = from_user
self.currency = currency
self.total_amount = total_amount
self.payload = payload
self.shipping_option_id = shipping_option_id
self.payment_info = payment_info
@staticmethod
async def _parse(client: "pyrogram.Client", pre_checkout_query, users) -> "PreCheckoutQuery":
# Try to decode pre-checkout query payload into string. If that fails, fallback to bytes instead of decoding by
# ignoring/replacing errors, this way, button clicks will still work.
try:
payload = pre_checkout_query.payload.decode()
except (UnicodeDecodeError, AttributeError):
payload = pre_checkout_query.payload
return PreCheckoutQuery(
id=str(pre_checkout_query.query_id),
from_user=types.User._parse(client, users[pre_checkout_query.user_id]),
currency=pre_checkout_query.currency,
total_amount=pre_checkout_query.total_amount,
payload=payload,
shipping_option_id=pre_checkout_query.shipping_option_id,
payment_info=types.PaymentInfo(
name=pre_checkout_query.info.name,
phone_number=pre_checkout_query.info.phone,
email=pre_checkout_query.info.email,
shipping_address=types.ShippingAddress(
street_line1=pre_checkout_query.info.shipping_address.street_line1,
street_line2=pre_checkout_query.info.shipping_address.street_line2,
city=pre_checkout_query.info.shipping_address.city,
state=pre_checkout_query.info.shipping_address.state,
post_code=pre_checkout_query.info.shipping_address.post_code,
country_code=pre_checkout_query.info.shipping_address.country_iso2
)
) if pre_checkout_query.info else None,
client=client
)
async def answer(self, success: bool = None, error: str = None):
"""Bound method *answer* of :obj:`~pyrogram.types.PreCheckoutQuery`.
Use this method as a shortcut for:
.. code-block:: python
await client.answer_pre_checkout_query(
pre_checkout_query.id,
success=True
)
Example:
.. code-block:: python
await pre_checkout_query.answer(success=True)
Parameters:
success (``bool`` *optional*):
If true, an alert will be shown by the client instead of a notification at the top of the chat screen.
Defaults to False.
error (``bool`` *optional*):
If true, an alert will be shown by the client instead of a notification at the top of the chat screen.
Defaults to False.
"""
return await self._client.answer_pre_checkout_query(
pre_checkout_query_id=self.id,
success=success,
error=error
)

View File

@ -0,0 +1,61 @@
# Pyrogram - Telegram MTProto API Client Library for Python
# Copyright (C) 2017-present Dan <https://github.com/delivrance>
#
# This file is part of Pyrogram.
#
# Pyrogram is free software: you can redistribute it and/or modify
# it under the terms of the GNU Lesser General Public License as published
# by the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# Pyrogram is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU Lesser General Public License for more details.
#
# You should have received a copy of the GNU Lesser General Public License
# along with Pyrogram. If not, see <http://www.gnu.org/licenses/>.
from ..object import Object
class ShippingAddress(Object):
"""Contains information about a shipping address.
Parameters:
street_line1 (``str``):
First line for the address.
street_line1 (``str``):
Second line for the address.
city (``str``):
City for the address.
state (``str``):
State for the address, if applicable.
post_code (``str``):
Post code for the address.
country_code (``str``):
Two-letter ISO 3166-1 alpha-2 country code.
"""
def __init__(
self, *,
street_line1: str,
street_line2: str,
city: str,
state: str,
post_code: str,
country_code: str
):
super().__init__()
self.street_line1 = street_line1
self.street_line2 = street_line2
self.city = city
self.state = state
self.post_code = post_code
self.country_code = country_code

View File

@ -0,0 +1,111 @@
# Pyrogram - Telegram MTProto API Client Library for Python
# Copyright (C) 2017-present Dan <https://github.com/delivrance>
#
# This file is part of Pyrogram.
#
# Pyrogram is free software: you can redistribute it and/or modify
# it under the terms of the GNU Lesser General Public License as published
# by the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# Pyrogram is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU Lesser General Public License for more details.
#
# You should have received a copy of the GNU Lesser General Public License
# along with Pyrogram. If not, see <http://www.gnu.org/licenses/>.
from pyrogram import raw
from pyrogram import types
from ..object import Object
class SuccessfulPayment(Object):
"""Contains information about a successful payment.
Parameters:
currency (``str``):
Three-letter ISO 4217 currency code.
total_amount (``int``):
Total price in the smallest units of the currency.
payload (``str``, *optional*):
Bot specified invoice payload. Only available to the bot that received the payment.
telegram_payment_charge_id (``str``, *optional*):
Telegram payment identifier. Only available to the bot that received the payment.
provider_payment_charge_id (``str``, *optional*):
Provider payment identifier. Only available to the bot that received the payment.
shipping_option_id (``str``, *optional*):
Identifier of the shipping option chosen by the user. Only available to the bot that received the payment.
payment_info (:obj:`~pyrogram.types.PaymentInfo`, *optional*):
Payment information provided by the user. Only available to the bot that received the payment.
"""
def __init__(
self, *,
currency: str,
total_amount: str,
payload: str,
telegram_payment_charge_id: str,
provider_payment_charge_id: str,
shipping_option_id: str = None,
payment_info: "types.PaymentInfo" = None
):
super().__init__()
self.currency = currency
self.total_amount = total_amount
self.payload = payload
self.telegram_payment_charge_id = telegram_payment_charge_id
self.provider_payment_charge_id = provider_payment_charge_id
self.shipping_option_id = shipping_option_id
self.payment_info = payment_info
@staticmethod
def _parse(client: "pyrogram.Client", successful_payment) -> "SuccessfulPayment":
payload = None
telegram_payment_charge_id = None
provider_payment_charge_id = None
shipping_option_id = None
payment_info = None
if isinstance(successful_payment, raw.types.MessageActionPaymentSentMe):
# Try to decode invoice payload into string. If that fails, fallback to bytes instead of decoding by
# ignoring/replacing errors, this way, button clicks will still work.
try:
payload = successful_payment.payload.decode()
except (UnicodeDecodeError, AttributeError):
payload = successful_payment.payload
telegram_payment_charge_id = successful_payment.charge.id
provider_payment_charge_id = successful_payment.charge.provider_charge_id
shipping_option_id = successful_payment.shipping_option_id
payment_info = types.PaymentInfo(
name=successful_payment.info.name,
phone_number=successful_payment.info.phone,
email=successful_payment.info.email,
shipping_address=types.ShippingAddress(
street_line1=successful_payment.info.shipping_address.street_line1,
street_line2=successful_payment.info.shipping_address.street_line2,
city=successful_payment.info.shipping_address.city,
state=successful_payment.info.shipping_address.state,
post_code=successful_payment.info.shipping_address.post_code,
country_code=successful_payment.info.shipping_address.country_iso2
)
) if successful_payment.info else None
return SuccessfulPayment(
currency=successful_payment.currency,
total_amount=successful_payment.total_amount,
payload=payload,
telegram_payment_charge_id=telegram_payment_charge_id,
provider_payment_charge_id=shipping_option_id,
shipping_option_id=shipping_option_id,
payment_info=payment_info
)

View File

@ -367,6 +367,9 @@ class Message(Object, Update):
requested_chats (:obj:`~pyrogram.types.RequestedChats`, *optional*):
Service message: requested chats information.
successful_payment (:obj:`~pyrogram.types.SuccessfulPayment`, *optional*):
Service message: successful payment.
giveaway_launched (``bool``, *optional*):
Service message: giveaway launched.
@ -494,6 +497,7 @@ class Message(Object, Update):
web_app_data: "types.WebAppData" = None,
gift_code: "types.GiftCode" = None,
requested_chats: "types.RequestedChats" = None,
successful_payment: "types.SuccessfulPayment" = None,
giveaway_launched: bool = None,
chat_ttl_period: int = None,
boosts_applied: int = None,
@ -602,6 +606,7 @@ class Message(Object, Update):
self.web_app_data = web_app_data
self.gift_code = gift_code
self.requested_chats = requested_chats
self.successful_payment = successful_payment
self.giveaway_launched = giveaway_launched
self.chat_ttl_period = chat_ttl_period
self.boosts_applied = boosts_applied
@ -678,6 +683,7 @@ class Message(Object, Update):
gift_code = None
giveaway_launched = None
requested_chats = None
successful_payment = None
chat_ttl_period = None
boosts_applied = None
join_request_approved = None
@ -762,6 +768,9 @@ class Message(Object, Update):
elif isinstance(action, (raw.types.MessageActionRequestedPeer, raw.types.MessageActionRequestedPeerSentMe)):
requested_chats = types.RequestedChats._parse(client, action)
service_type = enums.MessageServiceType.REQUESTED_CHAT
elif isinstance(action, (raw.types.MessageActionPaymentSent, raw.types.MessageActionPaymentSentMe)):
successful_payment = types.SuccessfulPayment._parse(client, action)
service_type = enums.MessageServiceType.SUCCESSFUL_PAYMENT
elif isinstance(action, raw.types.MessageActionSetMessagesTTL):
chat_ttl_period = action.period
service_type = enums.MessageServiceType.CHAT_TTL_CHANGED
@ -807,6 +816,7 @@ class Message(Object, Update):
giveaway_launched=giveaway_launched,
gift_code=gift_code,
requested_chats=requested_chats,
successful_payment=successful_payment,
chat_ttl_period=chat_ttl_period,
boosts_applied=boosts_applied,
join_request_approved=join_request_approved,