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    pub company_id: Uuid,
157    pub user_id: Uuid,
158    pub r#type: CardType,
159    pub status: CardStatus,
160    #[serde(skip_serializing_if = "Option::is_none")]
161    pub limit: Option<CardLimit>,
162    pub last4: String,
163    pub expiration_month: String,
164    pub expiration_year: String,
165    #[serde(skip_serializing_if = "Option::is_none")]
166    pub token_wallets: Option<Vec<String>>,
167}
168
169/// Response for card secrets (encrypted PAN and CVC)
170#[derive(Debug, Clone, Serialize, Deserialize)]
171#[serde(rename_all = "camelCase")]
172pub struct CardSecrets {
173    pub encrypted_pan: EncryptedData,
174    pub encrypted_cvc: EncryptedData,
175}
176
177/// Response for card PIN
178#[derive(Debug, Clone, Serialize, Deserialize)]
179#[serde(rename_all = "camelCase")]
180pub struct CardPin {
181    pub encrypted_pin: EncryptedData,
182}
183
184/// Response for processor details
185#[derive(Debug, Clone, Serialize, Deserialize)]
186#[serde(rename_all = "camelCase")]
187pub struct ProcessorDetails {
188    pub processor_card_id: String,
189    #[serde(skip_serializing_if = "Option::is_none")]
190    pub time_based_secret: Option<String>,
191}
192
193/// Query parameters for listing cards
194#[derive(Debug, Clone, Serialize, Deserialize)]
195#[serde(rename_all = "camelCase")]
196pub struct ListCardsParams {
197    #[serde(skip_serializing_if = "Option::is_none")]
198    pub company_id: Option<Uuid>,
199    #[serde(skip_serializing_if = "Option::is_none")]
200    pub user_id: Option<Uuid>,
201    #[serde(skip_serializing_if = "Option::is_none")]
202    pub status: Option<CardStatus>,
203    #[serde(skip_serializing_if = "Option::is_none")]
204    pub cursor: Option<String>,
205    #[serde(skip_serializing_if = "Option::is_none")]
206    pub limit: Option<u32>,
207}
208
209/// Response for list of cards (just an array of cards)
210pub type ListCardsResponse = Vec<Card>;