rain_sdk/models/
cards.rs

1//! Models for card endpoints
2
3use serde::{Deserialize, Serialize};
4use uuid::Uuid;
5
6/// Card status enum
7#[derive(Debug, Clone, Serialize, Deserialize)]
8#[serde(rename_all = "camelCase")]
9pub enum CardStatus {
10    NotActivated,
11    Active,
12    Locked,
13    Canceled,
14}
15
16/// Card type enum
17#[derive(Debug, Clone, Serialize, Deserialize)]
18#[serde(rename_all = "lowercase")]
19pub enum CardType {
20    Physical,
21    Virtual,
22}
23
24/// Limit frequency enum
25#[derive(Debug, Clone, Serialize, Deserialize)]
26#[serde(rename_all = "camelCase")]
27pub enum LimitFrequency {
28    Per24HourPeriod,
29    Per7DayPeriod,
30    Per30DayPeriod,
31    PerYearPeriod,
32    AllTime,
33    PerAuthorization,
34}
35
36/// Card limit
37#[derive(Debug, Clone, Serialize, Deserialize)]
38pub struct CardLimit {
39    pub amount: i64, // Amount in cents
40    pub frequency: LimitFrequency,
41}
42
43/// Card configuration
44#[derive(Debug, Clone, Serialize, Deserialize)]
45pub struct CardConfiguration {
46    #[serde(skip_serializing_if = "Option::is_none")]
47    pub display_name: Option<String>,
48    #[serde(skip_serializing_if = "Option::is_none")]
49    pub product_id: Option<String>,
50    #[serde(skip_serializing_if = "Option::is_none")]
51    pub product_ref: Option<String>,
52    #[serde(skip_serializing_if = "Option::is_none")]
53    pub virtual_card_art: Option<String>,
54}
55
56/// Shipping method enum
57#[derive(Debug, Clone, Serialize, Deserialize)]
58#[serde(rename_all = "camelCase")]
59pub enum ShippingMethod {
60    Standard,
61    Express,
62    International,
63    Apc,
64    UspsInternational,
65}
66
67/// Shipping address for physical cards
68#[derive(Debug, Clone, Serialize, Deserialize)]
69pub struct ShippingAddress {
70    pub line1: String,
71    #[serde(skip_serializing_if = "Option::is_none")]
72    pub line2: Option<String>,
73    pub city: String,
74    #[serde(skip_serializing_if = "Option::is_none")]
75    pub region: Option<String>,
76    pub postal_code: String,
77    pub country_code: String,
78    pub phone_number: String,
79    #[serde(skip_serializing_if = "Option::is_none")]
80    pub method: Option<ShippingMethod>,
81    #[serde(skip_serializing_if = "Option::is_none")]
82    pub first_name: Option<String>,
83    #[serde(skip_serializing_if = "Option::is_none")]
84    pub last_name: Option<String>,
85}
86
87/// Billing address
88#[derive(Debug, Clone, Serialize, Deserialize)]
89pub struct BillingAddress {
90    pub line1: String,
91    #[serde(skip_serializing_if = "Option::is_none")]
92    pub line2: Option<String>,
93    pub city: String,
94    pub region: String,
95    pub postal_code: String,
96    pub country_code: String,
97    #[serde(skip_serializing_if = "Option::is_none")]
98    pub country: Option<String>,
99}
100
101/// Request to create a card for a user
102#[derive(Debug, Clone, Serialize, Deserialize)]
103pub struct CreateCardRequest {
104    pub r#type: CardType,
105    #[serde(skip_serializing_if = "Option::is_none")]
106    pub status: Option<CardStatus>,
107    #[serde(skip_serializing_if = "Option::is_none")]
108    pub limit: Option<CardLimit>,
109    #[serde(skip_serializing_if = "Option::is_none")]
110    pub configuration: Option<CardConfiguration>,
111    #[serde(skip_serializing_if = "Option::is_none")]
112    pub shipping: Option<ShippingAddress>,
113    #[serde(skip_serializing_if = "Option::is_none")]
114    pub bulk_shipping_group_id: Option<Uuid>,
115    #[serde(skip_serializing_if = "Option::is_none")]
116    pub billing: Option<BillingAddress>,
117}
118
119/// Request to update a card
120#[derive(Debug, Clone, Serialize, Deserialize)]
121pub struct UpdateCardRequest {
122    #[serde(skip_serializing_if = "Option::is_none")]
123    pub status: Option<CardStatus>,
124    #[serde(skip_serializing_if = "Option::is_none")]
125    pub limit: Option<CardLimit>,
126    #[serde(skip_serializing_if = "Option::is_none")]
127    pub billing: Option<BillingAddress>,
128    #[serde(skip_serializing_if = "Option::is_none")]
129    pub configuration: Option<CardConfiguration>,
130}
131
132/// Encrypted data structure
133#[derive(Debug, Clone, Serialize, Deserialize)]
134pub struct EncryptedData {
135    pub iv: String,
136    pub data: String,
137}
138
139/// Request to update a card's PIN
140#[derive(Debug, Clone, Serialize, Deserialize)]
141pub struct UpdateCardPinRequest {
142    pub encrypted_pin: EncryptedData,
143}
144
145/// Response for card
146#[derive(Debug, Clone, Serialize, Deserialize)]
147pub struct Card {
148    pub id: Uuid,
149    #[serde(skip_serializing_if = "Option::is_none")]
150    pub company_id: Option<Uuid>,
151    #[serde(skip_serializing_if = "Option::is_none")]
152    pub user_id: Option<Uuid>,
153    pub r#type: CardType,
154    pub status: CardStatus,
155    #[serde(skip_serializing_if = "Option::is_none")]
156    pub limit: Option<CardLimit>,
157    #[serde(skip_serializing_if = "Option::is_none")]
158    pub last4: Option<String>,
159    #[serde(skip_serializing_if = "Option::is_none")]
160    pub expiration_month: Option<String>,
161    #[serde(skip_serializing_if = "Option::is_none")]
162    pub expiration_year: Option<String>,
163    #[serde(skip_serializing_if = "Option::is_none")]
164    pub token_wallets: Option<Vec<String>>,
165}
166
167/// Response for card secrets (encrypted PAN and CVC)
168#[derive(Debug, Clone, Serialize, Deserialize)]
169pub struct CardSecrets {
170    pub encrypted_pan: EncryptedData,
171    pub encrypted_cvc: EncryptedData,
172}
173
174/// Response for card PIN
175#[derive(Debug, Clone, Serialize, Deserialize)]
176pub struct CardPin {
177    pub encrypted_pin: EncryptedData,
178}
179
180/// Response for processor details
181#[derive(Debug, Clone, Serialize, Deserialize)]
182pub struct ProcessorDetails {
183    pub processor_card_id: String,
184    pub time_based_secret: String,
185}
186
187/// Query parameters for listing cards
188#[derive(Debug, Clone, Serialize, Deserialize)]
189pub struct ListCardsParams {
190    pub company_id: Option<Uuid>,
191    pub user_id: Option<Uuid>,
192    pub status: Option<CardStatus>,
193    pub cursor: Option<String>,
194    pub limit: Option<u32>,
195}
196
197/// Response for list of cards (just an array of cards)
198pub type ListCardsResponse = Vec<Card>;