Skip to content

Commit b11fcfe

Browse files
authored
Invoice high-level support (#33)
* by stealing without authorship some of the commits from KurimuzonAkuma/kurigram#67 and pyrogram/pyrogram#535.
1 parent faea755 commit b11fcfe

21 files changed

+1216
-7
lines changed

compiler/docs/compiler.py

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -372,8 +372,11 @@ def get_title_list(s: str) -> list:
372372
""",
373373
business="""
374374
Telegram Business & Fragment
375+
answer_pre_checkout_query
375376
get_business_connection
376377
get_collectible_item_info
378+
refund_star_payment
379+
send_invoice
377380
""",
378381
)
379382

@@ -564,6 +567,11 @@ def get_title_list(s: str) -> list:
564567
BusinessOpeningHoursInterval
565568
CollectibleItemInfo
566569
Invoice
570+
LabeledPrice
571+
OrderInfo
572+
PreCheckoutQuery
573+
ShippingAddress
574+
SuccessfulPayment
567575
""",
568576
users_chats="""
569577
Users & Chats
@@ -705,6 +713,10 @@ def get_title_list(s: str) -> list:
705713
InlineQuery
706714
InlineQuery.answer
707715
""",
716+
pre_checkout_query="""
717+
PreCheckoutQuery
718+
PreCheckoutQuery.answer
719+
""",
708720
chat_join_request="""
709721
ChatJoinRequest
710722
ChatJoinRequest.approve

compiler/docs/template/bound-methods.rst

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -88,6 +88,19 @@ InlineQuery
8888

8989
{inline_query_toctree}
9090

91+
PreCheckoutQuery
92+
-----------
93+
94+
.. hlist::
95+
:columns: 2
96+
97+
{pre_checkout_query_hlist}
98+
99+
.. toctree::
100+
:hidden:
101+
102+
{pre_checkout_query_toctree}
103+
91104
ChatJoinRequest
92105
---------------
93106

docs/source/releases/changes-in-this-fork.rst

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,9 @@ If you found any issue or have any suggestions, feel free to make `an issue <htt
1414
| Scheme layer used: 181 |
1515
+------------------------+
1616

17+
- Added the types :obj:`~pyrogram.types.LabeledPrice`, :obj:`~pyrogram.types.OrderInfo`, :obj:`~pyrogram.types.PreCheckoutQuery`, :obj:`~pyrogram.types.ShippingAddress`, :obj:`~pyrogram.types.SuccessfulPayment`, :obj:`~pyrogram.types.`.
18+
- Added the ``successful_payment`` parameter to the :obj:`~pyrogram.types.Message`. Added the filter :obj:`~pyrogram.filters.successful_payment` to detect service messages of Successful Payment type.
19+
- Added the methods :meth:`~pyrogram.Client.send_invoice`, :meth:`~pyrogram.Client.answer_pre_checkout_query` (:meth:`~pyrogram.types.PreCheckoutQuery.answer`), :meth:`~pyrogram.Client.refund_star_payment`.
1720
- Added the :meth:`~pyrogram.Client.send_web_app_custom_request`.
1821
- Added the :meth:`~pyrogram.Client.search_public_hashtag_messages` and :meth:`~pyrogram.Client.search_public_hashtag_messages_count`.
1922
- Added the ``fetch_replies`` parameter to :obj:`~pyrogram.Client`.

pyrogram/dispatcher.py

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@
3333
ChosenInlineResultHandler,
3434
CallbackQueryHandler,
3535

36-
36+
PreCheckoutQueryHandler,
3737
PollHandler,
3838

3939

@@ -57,7 +57,8 @@
5757
UpdateBotMessageReactions,
5858
UpdateBotNewBusinessMessage,
5959
UpdateBotEditBusinessMessage,
60-
UpdateBotDeleteBusinessMessage
60+
UpdateBotDeleteBusinessMessage,
61+
UpdateBotPrecheckoutQuery
6162
)
6263

6364
log = logging.getLogger(__name__)
@@ -76,6 +77,7 @@ class Dispatcher:
7677
CHAT_JOIN_REQUEST_UPDATES = (UpdateBotChatInviteRequester,)
7778
MESSAGE_BOT_NA_REACTION_UPDATES = (UpdateBotMessageReaction,)
7879
MESSAGE_BOT_A_REACTION_UPDATES = (UpdateBotMessageReactions,)
80+
PRE_CHECKOUT_QUERY_UPDATES = (UpdateBotPrecheckoutQuery,)
7981

8082
def __init__(self, client: "pyrogram.Client"):
8183
self.client = client
@@ -173,6 +175,12 @@ async def message_bot_a_reaction_parser(update, users, chats):
173175
MessageReactionCountUpdatedHandler
174176
)
175177

178+
async def pre_checkout_query_parser(update, users, chats):
179+
return (
180+
await pyrogram.types.PreCheckoutQuery._parse(self.client, update, users),
181+
PreCheckoutQueryHandler
182+
)
183+
176184
self.update_parsers = {
177185
Dispatcher.NEW_MESSAGE_UPDATES: message_parser,
178186
Dispatcher.EDIT_MESSAGE_UPDATES: edited_message_parser,
@@ -185,7 +193,8 @@ async def message_bot_a_reaction_parser(update, users, chats):
185193
Dispatcher.CHAT_MEMBER_UPDATES: chat_member_updated_parser,
186194
Dispatcher.CHAT_JOIN_REQUEST_UPDATES: chat_join_request_parser,
187195
Dispatcher.MESSAGE_BOT_NA_REACTION_UPDATES: message_bot_na_reaction_parser,
188-
Dispatcher.MESSAGE_BOT_A_REACTION_UPDATES: message_bot_a_reaction_parser
196+
Dispatcher.MESSAGE_BOT_A_REACTION_UPDATES: message_bot_a_reaction_parser,
197+
Dispatcher.PRE_CHECKOUT_QUERY_UPDATES: pre_checkout_query_parser
189198
}
190199

191200
self.update_parsers = {key: value for key_tuple, value in self.update_parsers.items() for key in key_tuple}

pyrogram/enums/message_service_type.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -119,3 +119,6 @@ class MessageServiceType(AutoName):
119119

120120
GENERAL_FORUM_TOPIC_UNHIDDEN = auto()
121121
"a forum general topic unhidden in the chat"
122+
123+
SUCCESSFUL_PAYMENT = auto()
124+
"Successful payment"

pyrogram/filters.py

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@
2727
CallbackQuery,
2828
InlineQuery,
2929
InlineKeyboardMarkup,
30+
PreCheckoutQuery,
3031
ReplyKeyboardMarkup,
3132
Update,
3233
)
@@ -757,6 +758,16 @@ async def video_chat_participants_invited_filter(_, __, m: Message) -> bool:
757758

758759
# endregion
759760

761+
# region successful_payment_filter
762+
async def successful_payment_filter(_, __, m: Message):
763+
return bool(m.successful_payment)
764+
765+
766+
successful_payment = create(successful_payment_filter)
767+
"""Filter messages for successful payments"""
768+
769+
770+
# endregion
760771

761772
# region service_filter
762773
async def service_filter(_, __, m: Message) -> bool:
@@ -769,7 +780,7 @@ async def service_filter(_, __, m: Message) -> bool:
769780
A service message contains any of the following fields set: *left_chat_member*,
770781
*new_chat_title*, *new_chat_photo*, *delete_chat_photo*, *group_chat_created*, *supergroup_chat_created*,
771782
*channel_chat_created*, *migrate_to_chat_id*, *migrate_from_chat_id*, *pinned_message*, *game_score*,
772-
*video_chat_started*, *video_chat_ended*, *video_chat_participants_invited*.
783+
*video_chat_started*, *video_chat_ended*, *video_chat_participants_invited*, *successful_payment*.
773784
"""
774785

775786

@@ -958,6 +969,7 @@ def regex(pattern: Union[str, Pattern], flags: int = 0) -> Filter:
958969
- :obj:`~pyrogram.types.Message`: The filter will match ``text`` or ``caption``.
959970
- :obj:`~pyrogram.types.CallbackQuery`: The filter will match ``data``.
960971
- :obj:`~pyrogram.types.InlineQuery`: The filter will match ``query``.
972+
- :obj:`~pyrogram.types.PreCheckoutQuery`: The filter will match ``payload``.
961973
962974
When a pattern matches, all the `Match Objects <https://docs.python.org/3/library/re.html#match-objects>`_ are
963975
stored in the ``matches`` field of the update object itself.
@@ -977,6 +989,8 @@ async def func(flt, _, update: Update) -> bool:
977989
value: str | bytes = update.data
978990
elif isinstance(update, InlineQuery):
979991
value: str = update.query
992+
elif isinstance(update, PreCheckoutQuery):
993+
value: str = update.payload
980994
else:
981995
raise ValueError(f"Regex filter doesn't work with {type(update)}")
982996

pyrogram/handlers/__init__.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,3 +30,4 @@
3030
from .user_status_handler import UserStatusHandler
3131
from .message_reaction_updated_handler import MessageReactionUpdatedHandler
3232
from .message_reaction_count_updated_handler import MessageReactionCountUpdatedHandler
33+
from .pre_checkout_query_handler import PreCheckoutQueryHandler
Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
# Pyrogram - Telegram MTProto API Client Library for Python
2+
# Copyright (C) 2017-present Dan <https://github.com/delivrance>
3+
#
4+
# This file is part of Pyrogram.
5+
#
6+
# Pyrogram is free software: you can redistribute it and/or modify
7+
# it under the terms of the GNU Lesser General Public License as published
8+
# by the Free Software Foundation, either version 3 of the License, or
9+
# (at your option) any later version.
10+
#
11+
# Pyrogram is distributed in the hope that it will be useful,
12+
# but WITHOUT ANY WARRANTY; without even the implied warranty of
13+
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14+
# GNU Lesser General Public License for more details.
15+
#
16+
# You should have received a copy of the GNU Lesser General Public License
17+
# along with Pyrogram. If not, see <http://www.gnu.org/licenses/>.
18+
19+
from typing import Callable
20+
21+
from .handler import Handler
22+
23+
24+
class PreCheckoutQueryHandler(Handler):
25+
"""The PreCheckoutQueryHandler handler class. Used to handle pre-checkout queries coming from invoice buttons.
26+
27+
It is intended to be used with :meth:`~pyrogram.Client.add_handler`
28+
29+
For a nicer way to register this handler, have a look at the
30+
:meth:`~pyrogram.Client.on_pre_checkout_query` decorator.
31+
32+
Parameters:
33+
callback (``Callable``):
34+
Pass a function that will be called when a new PreCheckoutQuery arrives. It takes *(client, pre_checkout_query)*
35+
as positional arguments (look at the section below for a detailed description).
36+
37+
filters (:obj:`Filters`):
38+
Pass one or more filters to allow only a subset of callback queries to be passed
39+
in your callback function.
40+
41+
Other parameters:
42+
client (:obj:`~pyrogram.Client`):
43+
The Client itself, useful when you want to call other API methods inside the message handler.
44+
45+
pre_checkout_query (:obj:`~pyrogram.types.PreCheckoutQuery`):
46+
The received callback query.
47+
48+
"""
49+
50+
def __init__(self, callback: Callable, filters=None):
51+
super().__init__(callback, filters)

pyrogram/methods/business/__init__.py

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,12 +16,18 @@
1616
# You should have received a copy of the GNU Lesser General Public License
1717
# along with Pyrogram. If not, see <http://www.gnu.org/licenses/>.
1818

19+
from .answer_pre_checkout_query import AnswerPreCheckoutQuery
1920
from .get_business_connection import GetBusinessConnection
2021
from .get_collectible_item_info import GetCollectibleItemInfo
22+
from .refund_star_payment import RefundStarPayment
23+
from .send_invoice import SendInvoice
2124

2225

2326
class TelegramBusiness(
27+
AnswerPreCheckoutQuery,
2428
GetBusinessConnection,
2529
GetCollectibleItemInfo,
30+
RefundStarPayment,
31+
SendInvoice,
2632
):
2733
pass
Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,67 @@
1+
# Pyrogram - Telegram MTProto API Client Library for Python
2+
# Copyright (C) 2017-present Dan <https://github.com/delivrance>
3+
#
4+
# This file is part of Pyrogram.
5+
#
6+
# Pyrogram is free software: you can redistribute it and/or modify
7+
# it under the terms of the GNU Lesser General Public License as published
8+
# by the Free Software Foundation, either version 3 of the License, or
9+
# (at your option) any later version.
10+
#
11+
# Pyrogram is distributed in the hope that it will be useful,
12+
# but WITHOUT ANY WARRANTY; without even the implied warranty of
13+
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14+
# GNU Lesser General Public License for more details.
15+
#
16+
# You should have received a copy of the GNU Lesser General Public License
17+
# along with Pyrogram. If not, see <http://www.gnu.org/licenses/>.
18+
19+
import pyrogram
20+
from pyrogram import raw
21+
22+
23+
class AnswerPreCheckoutQuery:
24+
async def answer_pre_checkout_query(
25+
self: "pyrogram.Client",
26+
pre_checkout_query_id: str,
27+
ok: bool,
28+
error_message: str = None
29+
):
30+
"""Once the user has confirmed their payment and shipping details, the API sends the final confirmation in the form of an :obj:`~pyrogram.handlers.PreCheckoutQueryHandler`.
31+
32+
Use this method to respond to such pre-checkout queries.
33+
34+
**Note**: The API must receive an answer within 10 seconds after the pre-checkout query was sent.
35+
36+
.. include:: /_includes/usable-by/bots.rst
37+
38+
Parameters:
39+
pre_checkout_query_id (``str``):
40+
Unique identifier for the query to be answered.
41+
42+
ok (``bool``):
43+
Specify True if everything is alright (goods are available, etc.) and the bot is ready to proceed with the order. Use False if there are any problems.
44+
45+
error_message (``str``, *optional*):
46+
Required if ok is False. Error message in human readable form that explains the reason for failure to proceed with the checkout (e.g. "Sorry, somebody just bought the last of our amazing black T-shirts while you were busy filling out your payment details. Please choose a different color or garment!"). Telegram will display this message to the user.
47+
48+
Returns:
49+
``bool``: True, on success.
50+
51+
Example:
52+
.. code-block:: python
53+
54+
# Proceed with the order
55+
await app.answer_pre_checkout_query(query_id, ok=True)
56+
57+
# Answer with error message
58+
await app.answer_pre_checkout_query(query_id, ok=False, error_message="Error Message displayed to the user")
59+
60+
"""
61+
return await self.invoke(
62+
raw.functions.messages.SetBotPrecheckoutResults(
63+
query_id=int(pre_checkout_query_id),
64+
success=ok or None,
65+
error=error_message or None
66+
)
67+
)

0 commit comments

Comments
 (0)