tgbot/types/payment/transaction/
mod.rs

1use serde::{Deserialize, Serialize};
2
3use crate::{
4    api::{Method, Payload},
5    types::{Chat, Gift, Integer, PaidMedia, User},
6};
7
8#[cfg(test)]
9mod tests;
10
11/// Contains a list of Telegram Star transactions.
12#[derive(Clone, Debug, Deserialize, PartialEq, Serialize)]
13pub struct StarTransactions {
14    /// The list of transactions.
15    pub transactions: Vec<StarTransaction>,
16}
17
18impl<T> From<T> for StarTransactions
19where
20    T: IntoIterator<Item = StarTransaction>,
21{
22    fn from(value: T) -> Self {
23        Self {
24            transactions: value.into_iter().collect(),
25        }
26    }
27}
28
29/// Describes a Telegram Star transaction.
30#[serde_with::skip_serializing_none]
31#[derive(Clone, Debug, Deserialize, PartialEq, Serialize)]
32pub struct StarTransaction {
33    amount: Integer,
34    date: Integer,
35    id: String,
36    nanostar_amount: Option<Integer>,
37    source: Option<TransactionPartner>,
38    receiver: Option<TransactionPartner>,
39}
40
41impl StarTransaction {
42    /// Creates a new `StarTransaction`.
43    ///
44    /// # Arguments
45    ///
46    /// * `amount` - Number of Telegram Stars transferred by the transaction.
47    /// * `date` - Date the transaction was created in Unix time.
48    /// * `id` -  Unique identifier of the transaction;
49    ///   coincides with the identifer of the original transaction for refund transactions;
50    ///   coincides with `telegram_payment_charge_id` of [`crate::types::SuccessfulPayment`]
51    ///   for successful incoming payments from users.
52    pub fn new<T>(amount: Integer, date: Integer, id: T) -> Self
53    where
54        T: Into<String>,
55    {
56        Self {
57            amount,
58            date,
59            id: id.into(),
60            nanostar_amount: None,
61            source: None,
62            receiver: None,
63        }
64    }
65
66    /// Sets a new nanostar amount.
67    ///
68    /// # Arguments
69    ///
70    /// * `value` - The number of 1/1000000000 shares of Telegram Stars transferred by the transaction;
71    ///   from 0 to 999999999.
72    pub fn with_nanostar_amount(mut self, value: Integer) -> Self {
73        self.nanostar_amount = Some(value);
74        self
75    }
76
77    /// Sets a new source.
78    ///
79    /// # Arguments
80    ///
81    /// * `value` - Source of an incoming transaction.
82    ///   E.g., a user purchasing goods or services, Fragment refunding a failed withdrawal.
83    ///   Only for incoming transactions.
84    pub fn with_source(mut self, value: TransactionPartner) -> Self {
85        self.source = Some(value);
86        self
87    }
88
89    /// Sets a new receiver.
90    ///
91    /// # Arguments
92    ///
93    /// * `value` - Receiver of an outgoing transaction.
94    ///   E.g., a user for a purchase refund, Fragment for a withdrawal.
95    ///   Only for outgoing transactions.
96    pub fn with_receiver(mut self, value: TransactionPartner) -> Self {
97        self.receiver = Some(value);
98        self
99    }
100}
101
102/// Describes the affiliate program that issued the affiliate commission received via this transaction.
103#[serde_with::skip_serializing_none]
104#[derive(Clone, Debug, Deserialize, PartialEq, PartialOrd, Serialize)]
105pub struct TransactionPartnerAffiliateProgramParameters {
106    /// The number of Telegram Stars received by the bot for each 1000 Telegram Stars
107    /// received by the affiliate program sponsor from referred users.
108    pub commission_per_mille: Integer,
109    /// Information about the bot that sponsored the affiliate program
110    pub sponsor_user: Option<User>,
111}
112
113impl TransactionPartnerAffiliateProgramParameters {
114    /// Creates a new `TransactionPartnerAffiliateProgramParameters`.
115    ///
116    /// # Arguments
117    ///
118    /// * `commission_per_mille` - The number of Telegram Stars received by the bot.
119    pub fn new(commission_per_mille: Integer) -> Self {
120        Self {
121            commission_per_mille,
122            sponsor_user: None,
123        }
124    }
125
126    /// Sets a new sponsor user.
127    ///
128    /// # Arguments
129    ///
130    /// * `value` - Information about the bot that sponsored the affiliate program.
131    pub fn with_sponsor_user(mut self, value: User) -> Self {
132        self.sponsor_user = Some(value);
133        self
134    }
135}
136
137/// Contains information about the affiliate that received a commission via this transaction.
138#[serde_with::skip_serializing_none]
139#[derive(Clone, Debug, Deserialize, PartialEq, Serialize)]
140pub struct AffiliateInfo {
141    /// Integer amount of Telegram Stars received by the affiliate from the transaction,
142    /// rounded to 0; can be negative for refunds.
143    pub amount: Integer,
144    /// The number of Telegram Stars received by the affiliate for each 1000 Telegram Stars
145    /// received by the bot from referred users.
146    pub commission_per_mille: Integer,
147    /// The chat that received an affiliate commission if it was received by a chat.
148    pub affiliate_chat: Option<Chat>,
149    /// The bot or the user that received an affiliate commission if it was received by a bot or a user.
150    pub affiliate_user: Option<User>,
151    /// The number of 1/1000000000 shares of Telegram Stars received by the affiliate;
152    /// from -999999999 to 999999999; can be negative for refunds.
153    pub nanostar_amount: Option<Integer>,
154}
155
156impl AffiliateInfo {
157    /// Creates a new `AffiliateInfo`.
158    ///
159    /// # Arguments
160    ///
161    /// * `amount` - Integer amount of Telegram Stars received by the affiliate from the transaction
162    /// * `comission_per_mille` - The number of Telegram Stars received by the affiliate for each 1000 Telegram Stars
163    pub fn new(amount: Integer, commission_per_mille: Integer) -> Self {
164        Self {
165            amount,
166            commission_per_mille,
167            affiliate_chat: None,
168            affiliate_user: None,
169            nanostar_amount: None,
170        }
171    }
172
173    /// Sets a new affiliate chat.
174    ///
175    /// # Arguments
176    ///
177    /// * `value` - The chat that received an affiliate commission if it was received by a chat.
178    pub fn with_affiliate_chat<T>(mut self, value: T) -> Self
179    where
180        T: Into<Chat>,
181    {
182        self.affiliate_chat = Some(value.into());
183        self
184    }
185
186    /// Sets a new affiliate user.
187    ///
188    /// # Arguments
189    ///
190    /// * `value` - The bot or the user that received an affiliate commission if it was received by a bot or a user.
191    pub fn with_affiliate_user(mut self, value: User) -> Self {
192        self.affiliate_user = Some(value);
193        self
194    }
195
196    /// Sets a new nanostar amount.
197    ///
198    /// # Arguments
199    ///
200    /// * `value` - The number of 1/1000000000 shares of Telegram Stars received by the affiliate.
201    pub fn with_nanostar_amount(mut self, value: Integer) -> Self {
202        self.nanostar_amount = Some(value);
203        self
204    }
205}
206
207/// Describes a transaction with a chat.
208#[serde_with::skip_serializing_none]
209#[derive(Clone, Debug, Deserialize, PartialEq, Serialize)]
210pub struct TransactionPartnerChatParameters {
211    /// Information about the chat.
212    pub chat: Chat,
213    /// The gift sent to the chat by the bot.
214    pub gift: Option<Gift>,
215}
216
217impl TransactionPartnerChatParameters {
218    /// Creates a new `TransactionPartnerChatParameters`.
219    ///
220    /// # Arguments
221    ///
222    /// * `chat` - Information about the chat.
223    pub fn new<T>(chat: T) -> Self
224    where
225        T: Into<Chat>,
226    {
227        Self {
228            chat: chat.into(),
229            gift: None,
230        }
231    }
232
233    /// Sets a new gift
234    ///
235    /// # Arguments
236    ///
237    /// * `value` - The gift sent to the chat by the bot.
238    pub fn with_gift(mut self, value: Gift) -> Self {
239        self.gift = Some(value);
240        self
241    }
242}
243
244/// Type of the partner user transaction.
245#[derive(Clone, Copy, Debug, Deserialize, PartialEq, Serialize)]
246#[serde(rename_all = "snake_case")]
247pub enum TransactionPartnerUserType {
248    /// For direct transfers from managed business accounts.
249    BusinessAccountTransfer,
250    /// For gifts sent by the bot.
251    GiftPurchase,
252    /// For payments via invoices.
253    InvoicePayment,
254    /// For payments for paid media.
255    PaidMediaPayment,
256    /// For Telegram Premium subscriptions gifted by the bot.
257    PremiumPurchase,
258}
259
260/// Describes a transaction with a user.
261#[serde_with::skip_serializing_none]
262#[derive(Clone, Debug, Deserialize, PartialEq, Serialize)]
263pub struct TransactionPartnerUserParameters {
264    /// Type of the transaction.
265    pub transaction_type: TransactionPartnerUserType,
266    /// Information about the user.
267    pub user: User,
268    /// Information about the affiliate that received a commission via this transaction.
269    pub affiliate: Option<AffiliateInfo>,
270    /// The gift sent to the user by the bot.
271    pub gift: Option<String>,
272    /// Bot-specified invoice payload.
273    pub invoice_payload: Option<String>,
274    /// Information about the paid media bought by the user.
275    pub paid_media: Option<Vec<PaidMedia>>,
276    /// Bot-specified paid media payload.
277    pub paid_media_payload: Option<String>,
278    /// Number of months the gifted Telegram Premium subscription will be active for;
279    /// for “premium_purchase” transactions only.
280    pub premium_subscription_duration: Option<Integer>,
281    /// The duration of the paid subscription.
282    pub subscription_period: Option<Integer>,
283}
284
285impl TransactionPartnerUserParameters {
286    /// Creates a new `TransactionPartnerUserParameters`.
287    ///
288    /// # Arguments
289    ///
290    /// * `transaction_type` - Type of the transaction.
291    /// * `user` - Information about the user.
292    pub fn new(transaction_type: TransactionPartnerUserType, user: User) -> Self {
293        Self {
294            transaction_type,
295            user,
296            affiliate: None,
297            gift: None,
298            invoice_payload: None,
299            paid_media: None,
300            paid_media_payload: None,
301            premium_subscription_duration: None,
302            subscription_period: None,
303        }
304    }
305
306    /// Sets a new affiliate.
307    ///
308    /// # Arguments
309    ///
310    /// * `value` - Information about the affiliate that received a commission via this transaction.
311    pub fn with_affiliate(mut self, value: AffiliateInfo) -> Self {
312        self.affiliate = Some(value);
313        self
314    }
315
316    /// Sets a new gift.
317    ///
318    /// # Arguments
319    ///
320    /// * `value` - The gift sent to the user by the bot.
321    pub fn with_gift<T>(mut self, value: T) -> Self
322    where
323        T: Into<String>,
324    {
325        self.gift = Some(value.into());
326        self
327    }
328
329    /// Sets a new invoice payload.
330    ///
331    /// # Arguments
332    ///
333    /// * `value` - Bot-specified invoice payload.
334    pub fn with_invoice_payload<T>(mut self, value: T) -> Self
335    where
336        T: Into<String>,
337    {
338        self.invoice_payload = Some(value.into());
339        self
340    }
341
342    /// Sets a new paid media.
343    ///
344    /// # Arguments
345    ///
346    /// * `value` - Information about the paid media bought by the user.
347    pub fn with_paid_media<T>(mut self, value: T) -> Self
348    where
349        T: IntoIterator<Item = PaidMedia>,
350    {
351        self.paid_media = Some(value.into_iter().collect());
352        self
353    }
354
355    /// Sets a new paid media payload.
356    ///
357    /// # Arguments
358    ///
359    /// * `value` - Bot-specified paid media payload.
360    pub fn with_paid_media_payload<T>(mut self, value: T) -> Self
361    where
362        T: Into<String>,
363    {
364        self.paid_media_payload = Some(value.into());
365        self
366    }
367
368    /// Sets a new premium subscription duration.
369    ///
370    /// # Arguments
371    ///
372    /// * `value` - Number of months the gifted Telegram Premium subscription will be active for;
373    ///   for “premium_purchase” transactions only.
374    pub fn with_premium_subscription_duration(mut self, value: Integer) -> Self {
375        self.premium_subscription_duration = Some(value);
376        self
377    }
378
379    /// Sets a new subscription period.
380    ///
381    /// # Arguments
382    ///
383    /// * `value` - The duration of the paid subscription.
384    pub fn with_subscription_period(mut self, value: Integer) -> Self {
385        self.subscription_period = Some(value);
386        self
387    }
388}
389
390/// Describes the source of a transaction, or its recipient for outgoing transactions.
391#[derive(Clone, Debug, Deserialize, PartialEq, Serialize)]
392#[serde(from = "RawTransactionPartner", into = "RawTransactionPartner")]
393#[allow(clippy::large_enum_variant)]
394pub enum TransactionPartner {
395    /// Describes the affiliate program that issued the affiliate commission received via this transaction.
396    AffiliateProgram(TransactionPartnerAffiliateProgramParameters),
397    /// Describes a transaction with a chat.
398    Chat(TransactionPartnerChatParameters),
399    /// Describes a withdrawal transaction with Fragment.
400    Fragment(Option<RevenueWithdrawalState>),
401    /// Describes a transaction with an unknown source or recipient.
402    Other,
403    /// Describes a withdrawal transaction to the Telegram Ads platform.
404    TelegramAds,
405    /// Describes a transaction with payment for paid broadcasting.
406    TelegramApi {
407        /// The number of successful requests that exceeded regular limits and were therefore billed.
408        request_count: Integer,
409    },
410    /// Describes a transaction with a user.
411    User(TransactionPartnerUserParameters),
412}
413
414#[serde_with::skip_serializing_none]
415#[derive(Clone, Debug, Deserialize, PartialEq, Serialize)]
416#[serde(tag = "type", rename_all = "snake_case")]
417#[allow(clippy::large_enum_variant)]
418enum RawTransactionPartner {
419    AffiliateProgram(TransactionPartnerAffiliateProgramParameters),
420    Chat(TransactionPartnerChatParameters),
421    Fragment {
422        withdrawal_state: Option<RevenueWithdrawalState>,
423    },
424    Other {},
425    TelegramAds {},
426    TelegramApi {
427        request_count: Integer,
428    },
429    User(TransactionPartnerUserParameters),
430}
431
432impl From<RawTransactionPartner> for TransactionPartner {
433    fn from(value: RawTransactionPartner) -> Self {
434        match value {
435            RawTransactionPartner::AffiliateProgram(parameters) => Self::AffiliateProgram(parameters),
436            RawTransactionPartner::Chat(parameters) => Self::Chat(parameters),
437            RawTransactionPartner::Fragment { withdrawal_state } => Self::Fragment(withdrawal_state),
438            RawTransactionPartner::Other {} => Self::Other,
439            RawTransactionPartner::TelegramAds {} => Self::TelegramAds,
440            RawTransactionPartner::TelegramApi { request_count } => Self::TelegramApi { request_count },
441            RawTransactionPartner::User(parameters) => Self::User(parameters),
442        }
443    }
444}
445
446impl From<TransactionPartner> for RawTransactionPartner {
447    fn from(value: TransactionPartner) -> Self {
448        match value {
449            TransactionPartner::AffiliateProgram(parameters) => Self::AffiliateProgram(parameters),
450            TransactionPartner::Chat(parameters) => Self::Chat(parameters),
451            TransactionPartner::Fragment(withdrawal_state) => Self::Fragment { withdrawal_state },
452            TransactionPartner::Other => Self::Other {},
453            TransactionPartner::TelegramAds => Self::TelegramAds {},
454            TransactionPartner::TelegramApi { request_count } => Self::TelegramApi { request_count },
455            TransactionPartner::User(parameters) => Self::User(parameters),
456        }
457    }
458}
459
460/// Describes the state of a revenue withdrawal operation.
461#[derive(Clone, Debug, Deserialize, PartialEq, PartialOrd, Serialize)]
462#[serde(from = "RawRevenueWithdrawalState", into = "RawRevenueWithdrawalState")]
463pub enum RevenueWithdrawalState {
464    /// The withdrawal failed and the transaction was refunded.
465    Failed,
466    /// The withdrawal is in progress.
467    Pending,
468    /// The withdrawal succeeded.
469    Succeeded {
470        /// Date the withdrawal was completed in Unix time.
471        date: Integer,
472        /// An HTTPS URL that can be used to see transaction details.
473        url: String,
474    },
475}
476
477#[derive(Clone, Debug, Deserialize, PartialEq, PartialOrd, Serialize)]
478#[serde(tag = "type", rename_all = "snake_case")]
479enum RawRevenueWithdrawalState {
480    Failed {},
481    Pending {},
482    Succeeded { date: Integer, url: String },
483}
484
485impl From<RawRevenueWithdrawalState> for RevenueWithdrawalState {
486    fn from(value: RawRevenueWithdrawalState) -> Self {
487        use self::RawRevenueWithdrawalState::*;
488        match value {
489            Failed {} => Self::Failed,
490            Pending {} => Self::Pending,
491            Succeeded { date, url } => Self::Succeeded { date, url },
492        }
493    }
494}
495
496impl From<RevenueWithdrawalState> for RawRevenueWithdrawalState {
497    fn from(value: RevenueWithdrawalState) -> Self {
498        use self::RevenueWithdrawalState::*;
499        match value {
500            Failed => Self::Failed {},
501            Pending => Self::Pending {},
502            Succeeded { date, url } => Self::Succeeded { date, url },
503        }
504    }
505}
506
507/// Returns the bot's Telegram Star transactions in chronological order.
508#[serde_with::skip_serializing_none]
509#[derive(Clone, Copy, Debug, Default, Serialize)]
510pub struct GetStarTransactions {
511    offset: Option<Integer>,
512    limit: Option<Integer>,
513}
514
515impl GetStarTransactions {
516    /// Sets a new offset.
517    ///
518    /// # Arguments
519    ///
520    /// * `value` - Number of transactions to skip in the response.
521    pub fn with_offset(mut self, value: Integer) -> Self {
522        self.offset = Some(value);
523        self
524    }
525
526    /// Sets a new limit.
527    ///
528    /// # Arguments
529    ///
530    /// * `value` - The maximum number of transactions to be retrieved.
531    ///
532    /// Values between 1-100 are accepted.
533    /// Defaults to 100.
534    pub fn with_limit(mut self, value: Integer) -> Self {
535        self.limit = Some(value);
536        self
537    }
538}
539
540impl Method for GetStarTransactions {
541    type Response = StarTransactions;
542
543    fn into_payload(self) -> Payload {
544        Payload::json("getStarTransactions", self)
545    }
546}