flutterwave_v3_models/charge/direct_charge/
mod.rs

1use crate::{
2    common::{charge_res_data::ChargeResData, payload::Payload},
3    fwcall::{FwCall, ToFwCall},
4};
5use chrono::NaiveDateTime;
6use serde::{Deserialize, Serialize};
7use std::{borrow::Cow, collections::HashMap};
8use validator::Validate;
9
10#[derive(Debug, Serialize, Deserialize, Validate)]
11pub struct CardChargeReq {
12    #[validate(credit_card)]
13    pub card_number: String,
14    #[validate(length(min = 3, max = 4))]
15    pub cvv: String,
16    #[validate(length(min = 2, max = 2))]
17    pub expiry_month: String,
18    #[validate(length(min = 2, max = 2))]
19    pub expiry_year: String,
20    #[validate(length(min = 3, max = 3))]
21    pub currency: Option<String>,
22    pub amount: String,
23    #[validate(email, length(max = 100))]
24    pub email: String,
25    pub fullname: Option<String>,
26    #[validate(phone, length(max = 50))]
27    pub phone_number: Option<String>,
28    #[validate(length(max = 100))]
29    pub tx_ref: String,
30    pub preauthorize: Option<bool>,
31    #[validate(url)]
32    pub redirect_url: Option<String>,
33    pub client_ip: Option<String>,
34    pub device_fingerprint: Option<String>,
35    pub payment_plan: Option<String>,
36    pub a_statusreasoncode: String,
37    pub is_custom_3ds_enabled: bool,
38    pub a_time: NaiveDateTime,
39    pub meta: HashMap<String, String>,
40    pub subaccounts: Vec<SubAccount>,
41}
42
43impl<'a> ToFwCall<'a> for CardChargeReq {
44    type ApiRequest = Self;
45
46    type ApiResponse = CardChargeRes;
47
48    fn get_call(self) -> FwCall<'a, Self::ApiRequest, Self::ApiResponse> {
49        FwCall::new(
50            Cow::Borrowed("/v3/charges?type=card_charge"),
51            reqwest::Method::POST,
52            Some(Payload::ToEncrypt(self)),
53        )
54    }
55}
56
57#[derive(Debug)]
58pub enum SubAccountChargeType {
59    Flat,
60    Percentage,
61    FlatSubAccount,
62}
63
64impl<'de> serde::Deserialize<'de> for SubAccountChargeType {
65    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
66    where
67        D: serde::Deserializer<'de>,
68    {
69        struct SubAccountChargeTypeVisitor;
70
71        impl serde::de::Visitor<'_> for SubAccountChargeTypeVisitor {
72            type Value = SubAccountChargeType;
73
74            fn expecting(&self, formatter: &mut std::fmt::Formatter) -> std::fmt::Result {
75                formatter.write_str("Expecting one of flat, percentage or flatsubaccount!")
76            }
77            fn visit_str<E>(self, v: &str) -> Result<Self::Value, E>
78            where
79                E: serde::de::Error,
80            {
81                match v.to_ascii_lowercase().as_str() {
82                    "flat" => Ok(SubAccountChargeType::Flat),
83                    "percentage" => Ok(SubAccountChargeType::Percentage),
84                    "flat_subaccount" => Ok(SubAccountChargeType::FlatSubAccount),
85                    _ => Err(serde::de::Error::custom("Invalid Charge Type!")),
86                }
87            }
88
89            fn visit_string<E>(self, v: String) -> Result<Self::Value, E>
90            where
91                E: serde::de::Error,
92            {
93                match v.as_str() {
94                    "flat" => Ok(SubAccountChargeType::Flat),
95                    "percentage" => Ok(SubAccountChargeType::Percentage),
96                    "flat_subaccount" => Ok(SubAccountChargeType::FlatSubAccount),
97                    _ => Err(serde::de::Error::custom("Invalid Charge Type!")),
98                }
99            }
100        }
101        deserializer.deserialize_str(SubAccountChargeTypeVisitor)
102    }
103}
104
105impl serde::Serialize for SubAccountChargeType {
106    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
107    where
108        S: serde::Serializer,
109    {
110        match self {
111            SubAccountChargeType::Flat => serializer.serialize_str("flat"),
112            SubAccountChargeType::Percentage => serializer.serialize_str("percentage"),
113            SubAccountChargeType::FlatSubAccount => serializer.serialize_str("flat_subaccount"),
114        }
115    }
116}
117
118#[derive(Debug, Serialize, Deserialize)]
119pub struct SubAccount {
120    pub id: String,
121    pub transaction_split_ratio: u8,
122    pub transaction_charge_type: SubAccountChargeType,
123    pub transaction_charge: u64,
124}
125
126#[derive(Serialize, Deserialize)]
127pub struct CardChargeRes {
128    pub status: String,
129    pub message: String,
130    pub data: ChargeResData,
131    pub meta: Meta,
132}
133
134#[derive(Serialize, Deserialize)]
135pub struct Meta {
136    pub authorization: Authorization,
137}
138
139#[derive(Serialize, Deserialize)]
140pub struct Authorization {
141    pub mode: String,
142    pub pin: i32,
143    pub city: String,
144    pub address: String,
145    pub state: String,
146    pub country: String,
147    pub zipcode: i32,
148    pub endpoint: String,
149}