paystack/models/transaction.rs
1//! Transactions Models
2//! ====================
3
4use derive_builder::Builder;
5use serde::{Deserialize, Serialize};
6
7use crate::{Authorization, Channel, Currency, CustomerResponseData};
8
9/// This struct is used to create a transaction body for creating a transaction using the Paystack API.
10/// This struct is built using the `TransactionRequestBuilder` struct.
11#[derive(Clone, Default, Debug, Serialize, Builder)]
12pub struct TransactionRequest {
13 /// Amount should be in the subunit of the supported currency
14 pub amount: String,
15 /// Customer's email address
16 pub email: String,
17 // optional parameters from here on
18 /// The transaction currency. Defaults to your integration currency.
19 #[builder(setter(strip_option), default)]
20 pub currency: Option<Currency>,
21 /// Unique transaction reference. Only `-`, `.`, `=` and alphanumeric characters allowed.
22 #[builder(setter(strip_option), default)]
23 pub reference: Option<String>,
24 /// Fully qualified url, e.g. https://example.com/ . Use this to override the callback url provided on the dashboard for this transaction
25 #[builder(setter(strip_option), default)]
26 pub callback_url: Option<String>,
27 /// If transaction is to create a subscription to a predefined plan, provide plan code here. This would invalidate the value provided in `amount`
28 #[builder(setter(strip_option), default)]
29 pub plan: Option<String>,
30 /// Number of times to charge customer during subscription to plan
31 #[builder(setter(strip_option), default)]
32 pub invoice_limit: Option<u8>,
33 /// Stringified JSON object of custom data. Kindly check the Metadata page for more information.
34 #[builder(setter(strip_option), default)]
35 pub metadata: Option<String>,
36 /// An array of payment channels to control what channels you want to make available to the user to make a payment with.
37 #[builder(setter(strip_option), default)]
38 pub channel: Option<Vec<Channel>>,
39 /// The split code of the transaction split. e.g. `SPL_98WF13Eb3w`
40 #[builder(setter(strip_option), default)]
41 pub split_code: Option<String>,
42 /// The code for the subaccount that owns the payment. e.g. `ACCT_8f4s1eq7ml6rlzj`
43 #[builder(setter(strip_option), default)]
44 pub subaccount: Option<String>,
45 /// An amount used to override the split configuration for a single split payment.
46 /// If set, the amount specified goes to the main account regardless of the split configuration.
47 #[builder(setter(strip_option), default)]
48 pub transaction_charge: Option<String>,
49 /// Use this param to indicate who bears the transaction charges. Allowed values are: `account` or `subaccount` (defaults to `account`).
50 #[builder(setter(strip_option), default)]
51 pub bearer: Option<String>,
52}
53
54/// This struct is used to create a partial debit transaction body for creating a partial debit using the Paystack API.
55/// This struct should be created using the `PartialDebitTransactionRequestBuilder`
56/// The derive Builder allows for the automatic creation of the BuilderPattern
57#[derive(Debug, Clone, Serialize, Default, Builder)]
58pub struct PartialDebitTransactionRequest {
59 /// Authorization Code
60 authorization_code: String,
61 /// Specify the currency you want to debit. Allowed values are NGN or GHS.
62 currency: Currency,
63 /// Amount should be in the subunit of the supported currency
64 amount: String,
65 /// Customer's email address (attached to the authorization code)
66 email: String,
67 /// Unique transaction reference. Only `-`, `.`, `=` and alphanumeric characters allowed.
68 #[builder(default)]
69 reference: Option<String>,
70 /// Minimum amount to charge
71 #[builder(default)]
72 at_least: Option<String>,
73}
74
75/// This struct represents the data of the transaction response.
76#[derive(Deserialize, Debug, Clone, Default)]
77pub struct TransactionResponseData {
78 /// Generated URL to authorize the transaction.
79 pub authorization_url: String,
80 /// Access code of the transaction.
81 pub access_code: String,
82 /// Reference of the transaction.
83 pub reference: String,
84}
85
86/// This struct represents the data of the transaction status response.
87#[derive(Deserialize, Serialize, Debug, Clone, Default)]
88pub struct TransactionStatusData {
89 /// Id of the Transaction
90 pub id: u64,
91 /// Status of the Transaction. It can be `success`, `abandoned` or `failed`
92 pub status: String,
93 /// Reference of the Transaction
94 pub reference: String,
95 /// Amount of the transaction in the lowest denomination of the currency e.g. Kobo for NGN and cent for USD.
96 pub amount: u32,
97 /// Message from the transaction.
98 pub message: Option<String>,
99 /// Response from the payment gateway.
100 pub gateway_response: String,
101 /// Time the Transaction was completed.
102 pub paid_at: Option<String>,
103 /// Time the Transaction was created.
104 pub created_at: String,
105 /// Transaction channel. It can be `card` or `bank`.
106 pub channel: String,
107 /// Currency code of the Transaction e.g. `NGN for Nigerian Naira` and `USD for US Dollar`.
108 pub currency: String,
109 /// IP address of the computers the Transaction has passed through.
110 pub ip_address: Option<String>,
111 /// Meta data associated with the Transaction.
112 pub metadata: Option<String>,
113 /// Transaction fees to override the default fees specified in the integration.
114 pub fees: Option<i32>,
115 /// Transaction customer data.
116 pub customer: CustomerResponseData,
117 /// Transaction authorization data.
118 pub authorization: Authorization,
119}
120
121/// This struct represents the transaction timeline data.
122#[derive(Deserialize, Serialize, Debug, Clone, Default)]
123pub struct TransactionTimelineData {
124 /// Time spent in carrying out the transaction in ms.
125 pub time_spent: Option<u32>,
126 /// Number of attempts for the transaction.
127 pub attempts: Option<u32>,
128 /// Authentication use for the transaction.
129 pub authentication: Option<String>,
130 /// Number of errors for the transaction.
131 pub errors: Option<u32>,
132 /// Success status of the transaction.
133 pub success: Option<bool>,
134 /// If transaction was carried out with mobile.
135 pub mobile: Option<bool>,
136 /// Transaction inputs i.e. messages associated with the transaction.
137 pub input: Option<String>,
138 /// Transaction channel.
139 pub channel: Option<String>,
140 /// Transaction history.
141 pub history: Option<Vec<TransactionHistoryResponse>>,
142}
143
144/// This struct represents the transaction history data
145#[derive(Deserialize, Serialize, Debug, Clone)]
146pub struct TransactionHistoryResponse {
147 /// Transaction action.
148 #[serde(rename = "type")]
149 pub action_type: String,
150 /// Description of the action.
151 pub message: String,
152 /// Time action was taken in ms.
153 pub time: u32,
154}
155
156/// Transaction total data.
157#[derive(Debug, Deserialize, Serialize, Default)]
158pub struct TransactionTotalData {
159 /// Total number of transactions in the integration.
160 pub total_transactions: Option<u32>,
161 /// Total of unique number of customers in the integration.
162 pub unique_customers: Option<u32>,
163 /// Total volume of transaction in the integration.
164 pub total_volume: Option<u32>,
165 /// Total volume of transaction broken down by currency.
166 pub total_volume_by_currency: Option<Vec<VolumeByCurrency>>,
167 /// Total volume of pending transfers.
168 pub pending_transfers: Option<u32>,
169 /// Total volume of pending transfer broken down by currency.
170 pub pending_transfers_by_currency: Option<Vec<VolumeByCurrency>>,
171}
172
173/// Transaction volume by currency.
174#[derive(Debug, Deserialize, Serialize, Default)]
175pub struct VolumeByCurrency {
176 /// Currency code.
177 pub currency: String,
178 /// Amount in the lowest denomination of the currency.
179 pub amount: u32,
180}
181
182/// Export transaction response data.
183#[derive(Debug, Serialize, Deserialize, Default)]
184pub struct ExportTransactionData {
185 /// Path to download the exported transaction file.
186 pub path: String,
187}
188
189/// Transaction identifier.
190///
191/// It can either be a transaction reference or a transaction ID
192pub enum TransactionIdentifier {
193 Id(u64),
194 Reference(String),
195}
196
197#[cfg(test)]
198mod test {
199 use super::*;
200 use std::error::Error;
201
202 #[test]
203 fn can_create_transaction_body_with_builder() -> Result<(), Box<dyn Error>> {
204 let transaction = TransactionRequestBuilder::default()
205 .amount(String::from("10000"))
206 .email(String::from("email@example.com"))
207 .currency(Currency::NGN)
208 .build()?;
209
210 assert_eq!(transaction.email, "email@example.com");
211 assert_eq!(transaction.amount, "10000");
212 assert_eq!(transaction.currency, Some(Currency::NGN));
213 assert_eq!(transaction.bearer, None);
214
215 Ok(())
216 }
217
218 #[test]
219 fn cannot_create_transaction_body_without_compulsory_field() -> Result<(), Box<dyn Error>> {
220 let transaction = TransactionRequestBuilder::default()
221 .currency(Currency::GHS)
222 .build();
223
224 assert!(transaction.is_err());
225
226 Ok(())
227 }
228}