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)]
45#[serde(rename_all = "camelCase")]
46pub struct CardConfiguration {
47    #[serde(skip_serializing_if = "Option::is_none")]
48    pub display_name: Option<String>,
49    #[serde(skip_serializing_if = "Option::is_none")]
50    pub product_id: Option<String>,
51    #[serde(skip_serializing_if = "Option::is_none")]
52    pub product_ref: Option<String>,
53    #[serde(skip_serializing_if = "Option::is_none")]
54    pub virtual_card_art: Option<String>,
55}
56
57/// Shipping method enum
58#[derive(Debug, Clone, Serialize, Deserialize)]
59#[serde(rename_all = "camelCase")]
60pub enum ShippingMethod {
61    Standard,
62    Express,
63    International,
64    Apc,
65    UspsInternational,
66}
67
68/// Shipping address for physical cards
69#[derive(Debug, Clone, Serialize, Deserialize)]
70#[serde(rename_all = "camelCase")]
71pub struct ShippingAddress {
72    pub line1: String,
73    #[serde(skip_serializing_if = "Option::is_none")]
74    pub line2: Option<String>,
75    pub city: String,
76    #[serde(skip_serializing_if = "Option::is_none")]
77    pub region: Option<String>,
78    pub postal_code: String,
79    pub country_code: String,
80    pub phone_number: String,
81    #[serde(skip_serializing_if = "Option::is_none")]
82    pub method: Option<ShippingMethod>,
83    #[serde(skip_serializing_if = "Option::is_none")]
84    pub first_name: Option<String>,
85    #[serde(skip_serializing_if = "Option::is_none")]
86    pub last_name: Option<String>,
87}
88
89/// Billing address
90#[derive(Debug, Clone, Serialize, Deserialize)]
91#[serde(rename_all = "camelCase")]
92pub struct BillingAddress {
93    pub line1: String,
94    #[serde(skip_serializing_if = "Option::is_none")]
95    pub line2: Option<String>,
96    pub city: String,
97    pub region: String,
98    pub postal_code: String,
99    pub country_code: String,
100    #[serde(skip_serializing_if = "Option::is_none")]
101    pub country: Option<String>,
102}
103
104/// Request to create a card for a user
105#[derive(Debug, Clone, Serialize, Deserialize)]
106#[serde(rename_all = "camelCase")]
107pub struct CreateCardRequest {
108    pub r#type: CardType,
109    #[serde(skip_serializing_if = "Option::is_none")]
110    pub status: Option<CardStatus>,
111    #[serde(skip_serializing_if = "Option::is_none")]
112    pub limit: Option<CardLimit>,
113    #[serde(skip_serializing_if = "Option::is_none")]
114    pub configuration: Option<CardConfiguration>,
115    #[serde(skip_serializing_if = "Option::is_none")]
116    pub shipping: Option<ShippingAddress>,
117    #[serde(skip_serializing_if = "Option::is_none")]
118    pub bulk_shipping_group_id: Option<Uuid>,
119    #[serde(skip_serializing_if = "Option::is_none")]
120    pub billing: Option<BillingAddress>,
121}
122
123/// Request to update a card
124#[derive(Debug, Clone, Serialize, Deserialize)]
125#[serde(rename_all = "camelCase")]
126pub struct UpdateCardRequest {
127    #[serde(skip_serializing_if = "Option::is_none")]
128    pub status: Option<CardStatus>,
129    #[serde(skip_serializing_if = "Option::is_none")]
130    pub limit: Option<CardLimit>,
131    #[serde(skip_serializing_if = "Option::is_none")]
132    pub billing: Option<BillingAddress>,
133    #[serde(skip_serializing_if = "Option::is_none")]
134    pub configuration: Option<CardConfiguration>,
135}
136
137/// Encrypted data structure
138#[derive(Debug, Clone, Serialize, Deserialize)]
139pub struct EncryptedData {
140    pub iv: String,
141    pub data: String,
142}
143
144/// Request to update a card's PIN
145#[derive(Debug, Clone, Serialize, Deserialize)]
146#[serde(rename_all = "camelCase")]
147pub struct UpdateCardPinRequest {
148    pub encrypted_pin: EncryptedData,
149}
150
151/// Response for card
152#[derive(Debug, Clone, Serialize, Deserialize)]
153#[serde(rename_all = "camelCase")]
154pub struct Card {
155    pub id: Uuid,
156    #[serde(skip_serializing_if = "Option::is_none")]
157    pub company_id: Option<Uuid>,
158    pub user_id: Uuid,
159    pub r#type: CardType,
160    pub status: CardStatus,
161    #[serde(skip_serializing_if = "Option::is_none")]
162    pub limit: Option<CardLimit>,
163    pub last4: String,
164    pub expiration_month: String,
165    pub expiration_year: String,
166    #[serde(skip_serializing_if = "Option::is_none")]
167    pub token_wallets: Option<Vec<String>>,
168}
169
170/// Response for card secrets (encrypted PAN and CVC)
171#[derive(Debug, Clone, Serialize, Deserialize)]
172#[serde(rename_all = "camelCase")]
173pub struct CardSecrets {
174    pub encrypted_pan: EncryptedData,
175    pub encrypted_cvc: EncryptedData,
176}
177
178/// Response for card PIN
179#[derive(Debug, Clone, Serialize, Deserialize)]
180#[serde(rename_all = "camelCase")]
181pub struct CardPin {
182    pub encrypted_pin: EncryptedData,
183}
184
185/// Response for processor details
186#[derive(Debug, Clone, Serialize, Deserialize)]
187#[serde(rename_all = "camelCase")]
188pub struct ProcessorDetails {
189    pub processor_card_id: String,
190    #[serde(skip_serializing_if = "Option::is_none")]
191    pub time_based_secret: Option<String>,
192}
193
194/// Query parameters for listing cards
195#[derive(Debug, Clone, Serialize, Deserialize)]
196#[serde(rename_all = "camelCase")]
197pub struct ListCardsParams {
198    #[serde(skip_serializing_if = "Option::is_none")]
199    pub company_id: Option<Uuid>,
200    #[serde(skip_serializing_if = "Option::is_none")]
201    pub user_id: Option<Uuid>,
202    #[serde(skip_serializing_if = "Option::is_none")]
203    pub status: Option<CardStatus>,
204    #[serde(skip_serializing_if = "Option::is_none")]
205    pub cursor: Option<String>,
206    #[serde(skip_serializing_if = "Option::is_none")]
207    pub limit: Option<u32>,
208}
209
210/// Response for list of cards (just an array of cards)
211pub type ListCardsResponse = Vec<Card>;