tgbot/types/payment/checkout/mod.rs
1use serde::{Deserialize, Serialize};
2
3use crate::{
4 api::{Method, Payload},
5 types::{Integer, OrderInfo, User},
6};
7
8#[cfg(test)]
9mod tests;
10
11/// Represents an incoming pre-checkout query.
12#[serde_with::skip_serializing_none]
13#[derive(Clone, Debug, Deserialize, PartialOrd, PartialEq, Serialize)]
14pub struct PreCheckoutQuery {
15 /// Three-letter ISO 4217 currency code.
16 pub currency: String,
17 /// User who sent the query.
18 pub from: User,
19 /// Unique query identifier.
20 pub id: String,
21 /// Bot specified invoice payload.
22 pub invoice_payload: String,
23 /// Total price in the smallest units of the currency (integer, not float/double).
24 ///
25 /// For example, for a price of US$ 1.45 pass amount = 145.
26 /// See the exp parameter in [currencies.json][1], it shows the number of digits past the
27 /// decimal point for each currency (2 for the majority of currencies).
28 ///
29 /// [1]: https://core.telegram.org/bots/payments/currencies.json
30 pub total_amount: Integer,
31 /// Order info provided by the user.
32 pub order_info: Option<OrderInfo>,
33 /// Identifier of the shipping option chosen by the user.
34 pub shipping_option_id: Option<String>,
35}
36
37impl PreCheckoutQuery {
38 /// Creates a new `PreCheckoutQuery`.
39 ///
40 /// # Arguments
41 ///
42 /// * `currency` - Three-letter ISO 4217 currency code.
43 /// * `from` - User who sent the query.
44 /// * `id` - Unique query identifier.
45 /// * `invoice_payload` - Bot specified invoice payload.
46 /// * `total_amount` - Total price in the smallest units of the currency.
47 pub fn new<A, B, C>(currency: A, from: User, id: B, invoice_payload: C, total_amount: Integer) -> Self
48 where
49 A: Into<String>,
50 B: Into<String>,
51 C: Into<String>,
52 {
53 Self {
54 currency: currency.into(),
55 from,
56 id: id.into(),
57 invoice_payload: invoice_payload.into(),
58 total_amount,
59 order_info: None,
60 shipping_option_id: None,
61 }
62 }
63
64 /// Sets a new order info.
65 ///
66 /// # Arguments
67 ///
68 /// * `value` - Order info.
69 pub fn with_order_info(mut self, value: OrderInfo) -> Self {
70 self.order_info = Some(value);
71 self
72 }
73 /// Sets a new shipping option ID.
74 ///
75 /// # Arguments
76 ///
77 /// * `value` - Shipping option ID.
78 pub fn with_shipping_option_id<T>(mut self, value: T) -> Self
79 where
80 T: Into<String>,
81 {
82 self.shipping_option_id = Some(value.into());
83 self
84 }
85}
86
87/// Responds to a pre-checkout query.
88///
89/// Once the user has confirmed their payment and shipping details,
90/// the Bot API sends the final confirmation in the form of an
91/// [`crate::types::UpdateType::PreCheckoutQuery`].
92///
93/// # Notes
94///
95/// The Bot API must receive an answer within 10 seconds after the pre-checkout query was sent.
96#[serde_with::skip_serializing_none]
97#[derive(Clone, Debug, Serialize)]
98pub struct AnswerPreCheckoutQuery {
99 ok: bool,
100 pre_checkout_query_id: String,
101 error_message: Option<String>,
102}
103
104impl AnswerPreCheckoutQuery {
105 /// Creates a new `AnswerPreCheckoutQuery` with a success answer.
106 ///
107 /// # Arguments
108 ///
109 /// * `id` - Unique identifier of the query to be answered.
110 pub fn ok<T>(id: T) -> Self
111 where
112 T: Into<String>,
113 {
114 Self {
115 pre_checkout_query_id: id.into(),
116 ok: true,
117 error_message: None,
118 }
119 }
120
121 /// Creates a new `AnswerPreCheckoutQuery` with an error answer.
122 ///
123 /// # Arguments
124 ///
125 /// * `id` - Unique identifier of the query to be answered.
126 /// * `message` - Error message in human readable form
127 /// that explains the reason for failure to proceed with the checkout.
128 pub fn error<A, B>(id: A, message: B) -> Self
129 where
130 A: Into<String>,
131 B: Into<String>,
132 {
133 Self {
134 ok: false,
135 pre_checkout_query_id: id.into(),
136 error_message: Some(message.into()),
137 }
138 }
139}
140
141impl Method for AnswerPreCheckoutQuery {
142 type Response = bool;
143
144 fn into_payload(self) -> Payload {
145 Payload::json("answerPreCheckoutQuery", self)
146 }
147}