Skip to content

Commit

Permalink
feat: add a domain type for customer_id (#4705)
Browse files Browse the repository at this point in the history
Co-authored-by: hyperswitch-bot[bot] <148525504+hyperswitch-bot[bot]@users.noreply.github.com>
  • Loading branch information
Narayanbhat166 and hyperswitch-bot[bot] authored May 30, 2024
1 parent f192fa3 commit 93d61d1
Show file tree
Hide file tree
Showing 106 changed files with 1,150 additions and 490 deletions.
27 changes: 11 additions & 16 deletions crates/api_models/src/customers.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
use common_utils::{consts, crypto, custom_serde, pii};
use common_utils::{crypto, custom_serde, id_type, pii};
use masking::Secret;
use serde::{Deserialize, Serialize};
use utoipa::ToSchema;
Expand All @@ -9,9 +9,8 @@ use crate::payments;
#[derive(Debug, Default, Clone, Deserialize, Serialize, ToSchema)]
pub struct CustomerRequest {
/// The identifier for the customer object. If not provided the customer ID will be autogenerated.
#[schema(max_length = 255, example = "cus_y3oqhf46pyzuxjbcn2giaqnb44")]
#[serde(default = "generate_customer_id")]
pub customer_id: String,
#[schema(value_type = Option<String>, max_length = 64, min_length = 1, example = "cus_y3oqhf46pyzuxjbcn2giaqnb44")]
pub customer_id: Option<id_type::CustomerId>,
/// The identifier for the Merchant Account
#[schema(max_length = 255, example = "y3oqhf46pyzuxjbcn2giaqnb44")]
#[serde(default = "unknown_merchant", skip)]
Expand Down Expand Up @@ -43,9 +42,9 @@ pub struct CustomerRequest {

#[derive(Debug, Clone, Serialize, ToSchema)]
pub struct CustomerResponse {
/// The identifier for the customer object. If not provided the customer ID will be autogenerated.
#[schema(max_length = 255, example = "cus_y3oqhf46pyzuxjbcn2giaqnb44")]
pub customer_id: String,
/// The identifier for the customer object
#[schema(value_type = String, max_length = 64, min_length = 1, example = "cus_y3oqhf46pyzuxjbcn2giaqnb44")]
pub customer_id: id_type::CustomerId,
/// The customer's name
#[schema(max_length = 255, value_type = Option<String>, example = "Jon Test")]
pub name: crypto::OptionalEncryptableName,
Expand Down Expand Up @@ -78,16 +77,16 @@ pub struct CustomerResponse {
pub default_payment_method_id: Option<String>,
}

#[derive(Default, Clone, Debug, Deserialize, Serialize)]
#[derive(Clone, Debug, Deserialize, Serialize)]
pub struct CustomerId {
pub customer_id: String,
pub customer_id: id_type::CustomerId,
}

#[derive(Default, Debug, Deserialize, Serialize, ToSchema)]
#[derive(Debug, Deserialize, Serialize, ToSchema)]
pub struct CustomerDeleteResponse {
/// The identifier for the customer object
#[schema(max_length = 255, example = "cus_y3oqhf46pyzuxjbcn2giaqnb44")]
pub customer_id: String,
#[schema(value_type = String, max_length = 255, example = "cus_y3oqhf46pyzuxjbcn2giaqnb44")]
pub customer_id: id_type::CustomerId,
/// Whether customer was deleted or not
#[schema(example = false)]
pub customer_deleted: bool,
Expand All @@ -99,10 +98,6 @@ pub struct CustomerDeleteResponse {
pub payment_methods_deleted: bool,
}

pub fn generate_customer_id() -> String {
common_utils::generate_id(consts::ID_LENGTH, "cus")
}

fn unknown_merchant() -> String {
String::from("merchant_unknown")
}
4 changes: 3 additions & 1 deletion crates/api_models/src/ephemeral_key.rs
Original file line number Diff line number Diff line change
@@ -1,10 +1,12 @@
use common_utils::id_type;
use serde;
use utoipa::ToSchema;

#[derive(Debug, serde::Serialize, serde::Deserialize, Clone, Eq, PartialEq, ToSchema)]
pub struct EphemeralKeyCreateResponse {
/// customer_id to which this ephemeral key belongs to
pub customer_id: String,
#[schema(value_type = String, max_length = 64, min_length = 1, example = "cus_y3oqhf46pyzuxjbcn2giaqnb44")]
pub customer_id: id_type::CustomerId,
/// time at which this ephemeral key was created
pub created_at: i64,
/// time at which this ephemeral key would expire
Expand Down
6 changes: 3 additions & 3 deletions crates/api_models/src/events/customer.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,9 +12,9 @@ impl ApiEventMetric for CustomerDeleteResponse {

impl ApiEventMetric for CustomerRequest {
fn get_api_event_type(&self) -> Option<ApiEventsType> {
Some(ApiEventsType::Customer {
customer_id: self.customer_id.clone(),
})
self.customer_id
.clone()
.map(|customer_id| ApiEventsType::Customer { customer_id })
}
}

Expand Down
29 changes: 15 additions & 14 deletions crates/api_models/src/payment_methods.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ use cards::CardNumber;
use common_utils::{
consts::SURCHARGE_PERCENTAGE_PRECISION_LENGTH,
crypto::OptionalEncryptableName,
pii,
id_type, pii,
types::{MinorUnit, Percentage, Surcharge},
};
use serde::de;
Expand Down Expand Up @@ -49,8 +49,8 @@ pub struct PaymentMethodCreate {
pub metadata: Option<pii::SecretSerdeValue>,

/// The unique identifier of the customer.
#[schema(example = "cus_meowerunwiuwiwqw")]
pub customer_id: Option<String>,
#[schema(value_type = Option<String>, max_length = 64, min_length = 1, example = "cus_y3oqhf46pyzuxjbcn2giaqnb44")]
pub customer_id: Option<id_type::CustomerId>,

/// The card network
#[schema(example = "Visa")]
Expand Down Expand Up @@ -194,8 +194,8 @@ pub struct PaymentMethodResponse {
pub merchant_id: String,

/// The unique identifier of the customer.
#[schema(example = "cus_meowerunwiuwiwqw")]
pub customer_id: Option<String>,
#[schema(value_type = Option<String>, max_length = 64, min_length = 1, example = "cus_y3oqhf46pyzuxjbcn2giaqnb44")]
pub customer_id: Option<id_type::CustomerId>,

/// The unique identifier of the Payment method
#[schema(example = "card_rGK4Vi5iSW70MY7J2mIg")]
Expand Down Expand Up @@ -846,8 +846,8 @@ pub struct CustomerDefaultPaymentMethodResponse {
#[schema(example = "card_rGK4Vi5iSW70MY7J2mIg")]
pub default_payment_method_id: Option<String>,
/// The unique identifier of the customer.
#[schema(example = "cus_meowerunwiuwiwqw")]
pub customer_id: String,
#[schema(value_type = String, max_length = 64, min_length = 1, example = "cus_y3oqhf46pyzuxjbcn2giaqnb44")]
pub customer_id: id_type::CustomerId,
/// The type of payment method use for the payment.
#[schema(value_type = PaymentMethod,example = "card")]
pub payment_method: api_enums::PaymentMethod,
Expand All @@ -866,8 +866,8 @@ pub struct CustomerPaymentMethod {
pub payment_method_id: String,

/// The unique identifier of the customer.
#[schema(example = "cus_meowerunwiuwiwqw")]
pub customer_id: String,
#[schema(value_type = String, max_length = 64, min_length = 1, example = "cus_y3oqhf46pyzuxjbcn2giaqnb44")]
pub customer_id: id_type::CustomerId,

/// The type of payment method use for the payment.
#[schema(value_type = PaymentMethod,example = "card")]
Expand Down Expand Up @@ -952,7 +952,8 @@ pub struct PaymentMethodId {

#[derive(Debug, serde::Serialize, serde::Deserialize, Clone, ToSchema)]
pub struct DefaultPaymentMethod {
pub customer_id: String,
#[schema(value_type = String, max_length = 64, min_length = 1, example = "cus_y3oqhf46pyzuxjbcn2giaqnb44")]
pub customer_id: id_type::CustomerId,
pub payment_method_id: String,
}
//------------------------------------------------TokenizeService------------------------------------------------
Expand Down Expand Up @@ -1034,7 +1035,7 @@ pub struct TokenizedCardValue2 {
pub card_security_code: Option<String>,
pub card_fingerprint: Option<String>,
pub external_id: Option<String>,
pub customer_id: Option<String>,
pub customer_id: Option<id_type::CustomerId>,
pub payment_method_id: Option<String>,
}

Expand All @@ -1045,7 +1046,7 @@ pub struct TokenizedWalletValue1 {

#[derive(Debug, serde::Serialize, serde::Deserialize)]
pub struct TokenizedWalletValue2 {
pub customer_id: Option<String>,
pub customer_id: Option<id_type::CustomerId>,
}

#[derive(Debug, serde::Serialize, serde::Deserialize)]
Expand All @@ -1055,7 +1056,7 @@ pub struct TokenizedBankTransferValue1 {

#[derive(Debug, serde::Serialize, serde::Deserialize)]
pub struct TokenizedBankTransferValue2 {
pub customer_id: Option<String>,
pub customer_id: Option<id_type::CustomerId>,
}

#[derive(Debug, serde::Serialize, serde::Deserialize)]
Expand All @@ -1065,5 +1066,5 @@ pub struct TokenizedBankRedirectValue1 {

#[derive(Debug, serde::Serialize, serde::Deserialize)]
pub struct TokenizedBankRedirectValue2 {
pub customer_id: Option<String>,
pub customer_id: Option<id_type::CustomerId>,
}
64 changes: 48 additions & 16 deletions crates/api_models/src/payments.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ use common_utils::{
consts::default_payments_list_limit,
crypto,
ext_traits::{ConfigExt, Encode},
id_type,
pii::{self, Email},
types::MinorUnit,
};
Expand Down Expand Up @@ -177,10 +178,34 @@ mod client_secret_tests {
}
}

#[derive(Default, Debug, serde::Deserialize, serde::Serialize, Clone, ToSchema, PartialEq)]
#[derive(Debug, serde::Deserialize, serde::Serialize, Clone, ToSchema, PartialEq)]
pub struct CustomerDetails {
/// The identifier for the customer.
pub id: String,
#[schema(value_type = String, max_length = 64, min_length = 1, example = "cus_y3oqhf46pyzuxjbcn2giaqnb44")]
pub id: id_type::CustomerId,

/// The customer's name
#[schema(max_length = 255, value_type = Option<String>, example = "John Doe")]
pub name: Option<Secret<String>>,

/// The customer's email address
#[schema(max_length = 255, value_type = Option<String>, example = "[email protected]")]
pub email: Option<Email>,

/// The customer's phone number
#[schema(value_type = Option<String>, max_length = 10, example = "3141592653")]
pub phone: Option<Secret<String>>,

/// The country code for the customer's phone number
#[schema(max_length = 2, example = "+1")]
pub phone_country_code: Option<String>,
}

#[derive(Debug, serde::Serialize, Clone, ToSchema, PartialEq)]
pub struct CustomerDetailsResponse {
/// The identifier for the customer.
#[schema(value_type = String, max_length = 64, min_length = 1, example = "cus_y3oqhf46pyzuxjbcn2giaqnb44")]
pub id: id_type::CustomerId,

/// The customer's name
#[schema(max_length = 255, value_type = Option<String>, example = "John Doe")]
Expand Down Expand Up @@ -277,9 +302,9 @@ pub struct PaymentsRequest {
/// Passing this object creates a new customer or attaches an existing customer to the payment
pub customer: Option<CustomerDetails>,

/// The identifier for the customer object.
#[schema(max_length = 255, example = "cus_y3oqhf46pyzuxjbcn2giaqnb44")]
pub customer_id: Option<String>,
/// The identifier for the customer
#[schema(value_type = Option<String>, max_length = 64, min_length = 1, example = "cus_y3oqhf46pyzuxjbcn2giaqnb44")]
pub customer_id: Option<id_type::CustomerId>,

/// The customer's email address.
/// This field will be deprecated soon, use the customer object instead
Expand Down Expand Up @@ -762,7 +787,7 @@ pub struct VerifyRequest {
// The merchant_id is generated through api key
// and is later passed in the struct
pub merchant_id: Option<String>,
pub customer_id: Option<String>,
pub customer_id: Option<id_type::CustomerId>,
pub email: Option<Email>,
pub name: Option<Secret<String>>,
pub phone: Option<Secret<String>>,
Expand Down Expand Up @@ -3239,14 +3264,16 @@ pub struct PaymentsResponse {
/// The identifier for the customer object. If not provided the customer ID will be autogenerated.
/// This field will be deprecated soon. Please refer to `customer.id`
#[schema(
max_length = 255,
max_length = 64,
min_length = 1,
example = "cus_y3oqhf46pyzuxjbcn2giaqnb44",
deprecated
deprecated,
value_type = Option<String>,
)]
pub customer_id: Option<String>,
pub customer_id: Option<id_type::CustomerId>,

/// Details of customer attached to this payment
pub customer: Option<CustomerDetails>,
pub customer: Option<CustomerDetailsResponse>,

/// A description of the payment
#[schema(example = "It's my first payment request")]
Expand Down Expand Up @@ -3534,8 +3561,13 @@ pub struct ExternalAuthenticationDetailsResponse {
#[serde(deny_unknown_fields)]
pub struct PaymentListConstraints {
/// The identifier for customer
#[schema(example = "cus_meowuwunwiuwiwqw")]
pub customer_id: Option<String>,
#[schema(
max_length = 64,
min_length = 1,
example = "cus_y3oqhf46pyzuxjbcn2giaqnb44",
value_type = Option<String>,
)]
pub customer_id: Option<id_type::CustomerId>,

/// A cursor for use in pagination, fetch the next list after some object
#[schema(example = "pay_fafa124123")]
Expand Down Expand Up @@ -3632,7 +3664,7 @@ pub struct PaymentListFilterConstraints {
/// The identifier for business profile
pub profile_id: Option<String>,
/// The identifier for customer
pub customer_id: Option<String>,
pub customer_id: Option<id_type::CustomerId>,
/// The limit on the number of objects. The default limit is 10 and max limit is 20
#[serde(default = "default_payments_list_limit")]
pub limit: u32,
Expand Down Expand Up @@ -3716,7 +3748,7 @@ pub struct VerifyResponse {
pub merchant_id: Option<String>,
// pub status: enums::VerifyStatus,
pub client_secret: Option<Secret<String>>,
pub customer_id: Option<String>,
pub customer_id: Option<id_type::CustomerId>,
pub email: crypto::OptionalEncryptableEmail,
pub name: crypto::OptionalEncryptableName,
pub phone: crypto::OptionalEncryptablePhone,
Expand All @@ -3738,7 +3770,7 @@ pub struct PaymentsRedirectionResponse {
pub struct MandateValidationFields {
pub recurring_details: Option<RecurringDetails>,
pub confirm: Option<bool>,
pub customer_id: Option<String>,
pub customer_id: Option<id_type::CustomerId>,
pub mandate_data: Option<MandateData>,
pub setup_future_usage: Option<api_enums::FutureUsage>,
pub off_session: Option<bool>,
Expand Down Expand Up @@ -3847,7 +3879,7 @@ pub struct PgRedirectResponse {
pub payment_id: String,
pub status: api_enums::IntentStatus,
pub gateway_id: String,
pub customer_id: Option<String>,
pub customer_id: Option<id_type::CustomerId>,
pub amount: Option<MinorUnit>,
}

Expand Down
18 changes: 9 additions & 9 deletions crates/api_models/src/payouts.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
use cards::CardNumber;
use common_utils::{
consts::default_payouts_list_limit,
crypto,
crypto, id_type,
pii::{self, Email},
};
use masking::Secret;
Expand Down Expand Up @@ -86,8 +86,8 @@ pub struct PayoutCreateRequest {
pub billing: Option<payments::Address>,

/// The identifier for the customer object. If not provided the customer ID will be autogenerated.
#[schema(value_type = String, max_length = 255, example = "cus_y3oqhf46pyzuxjbcn2giaqnb44")]
pub customer_id: Option<String>,
#[schema(value_type = Option<String>, max_length = 255, example = "cus_y3oqhf46pyzuxjbcn2giaqnb44")]
pub customer_id: Option<id_type::CustomerId>,

/// Set to true to confirm the payout without review, no further action required
#[schema(value_type = bool, example = true, default = false)]
Expand Down Expand Up @@ -314,7 +314,7 @@ pub struct Venmo {
pub telephone_number: Option<Secret<String>>,
}

#[derive(Debug, Default, ToSchema, Clone, Serialize)]
#[derive(Debug, ToSchema, Clone, Serialize)]
#[serde(deny_unknown_fields)]
pub struct PayoutCreateResponse {
/// Unique identifier for the payout. This ensures idempotency for multiple payouts
Expand Down Expand Up @@ -367,7 +367,7 @@ pub struct PayoutCreateResponse {

/// The identifier for the customer object. If not provided the customer ID will be autogenerated.
#[schema(value_type = String, max_length = 255, example = "cus_y3oqhf46pyzuxjbcn2giaqnb44")]
pub customer_id: String,
pub customer_id: id_type::CustomerId,

/// Set to true to confirm the payout without review, no further action required
#[schema(value_type = bool, example = true, default = false)]
Expand Down Expand Up @@ -564,8 +564,8 @@ pub struct PayoutIndividualDetails {
#[serde(deny_unknown_fields)]
pub struct PayoutListConstraints {
/// The identifier for customer
#[schema(example = "cus_y3oqhf46pyzuxjbcn2giaqnb44")]
pub customer_id: Option<String>,
#[schema(value_type = Option<String>, example = "cus_y3oqhf46pyzuxjbcn2giaqnb44")]
pub customer_id: Option<id_type::CustomerId>,

/// A cursor for use in pagination, fetch the next list after some object
#[schema(example = "pay_fafa124123")]
Expand Down Expand Up @@ -605,8 +605,8 @@ pub struct PayoutListFilterConstraints {
/// The identifier for business profile
pub profile_id: Option<String>,
/// The identifier for customer
#[schema(example = "cus_y3oqhf46pyzuxjbcn2giaqnb44")]
pub customer_id: Option<String>,
#[schema(value_type = Option<String>,example = "cus_y3oqhf46pyzuxjbcn2giaqnb44")]
pub customer_id: Option<id_type::CustomerId>,
/// The limit on the number of objects. The default limit is 10 and max limit is 20
#[serde(default = "default_payouts_list_limit")]
pub limit: u32,
Expand Down
2 changes: 1 addition & 1 deletion crates/cards/tests/basic.rs
Original file line number Diff line number Diff line change
Expand Up @@ -78,7 +78,7 @@ fn test_card_expiration() {
// will panic on unwrap
let invalid_card_exp = CardExpiration::try_from((13, curr_year));

assert_eq!(*card_exp.get_month().peek(), 3);
assert_eq!(*card_exp.get_month().peek(), curr_month);
assert_eq!(*card_exp.get_year().peek(), curr_year);
assert!(!card_exp.is_expired().unwrap());

Expand Down
Loading

0 comments on commit 93d61d1

Please sign in to comment.