refactor(payment_id): add payment id domain type (#5738)

Co-authored-by: hyperswitch-bot[bot] <148525504+hyperswitch-bot[bot]@users.noreply.github.com>
This commit is contained in:
Narayan Bhat
2024-09-02 09:21:33 +05:30
committed by GitHub
parent 4b0564e0e8
commit 7296cceba3
150 changed files with 880 additions and 803 deletions

View File

@ -20,14 +20,14 @@ pub enum FilterType {
#[serde(tag = "type")]
pub enum QueryType {
Payment {
payment_id: String,
payment_id: common_utils::id_type::PaymentId,
},
Refund {
payment_id: String,
payment_id: common_utils::id_type::PaymentId,
refund_id: String,
},
Dispute {
payment_id: String,
payment_id: common_utils::id_type::PaymentId,
dispute_id: String,
},
}

View File

@ -1,6 +1,6 @@
#[derive(Clone, Debug, serde::Deserialize, serde::Serialize)]
pub struct OutgoingWebhookLogsRequest {
pub payment_id: String,
pub payment_id: common_utils::id_type::PaymentId,
pub event_id: Option<String>,
pub refund_id: Option<String>,
pub dispute_id: Option<String>,

View File

@ -8,7 +8,7 @@ use super::{NameDescription, TimeRange};
#[derive(Clone, Debug, serde::Deserialize, serde::Serialize)]
#[serde(rename_all = "camelCase")]
pub struct SdkEventsRequest {
pub payment_id: String,
pub payment_id: common_utils::id_type::PaymentId,
pub time_range: TimeRange,
}

View File

@ -10,7 +10,8 @@ pub struct DisputeResponse {
/// The identifier for dispute
pub dispute_id: String,
/// The identifier for payment_intent
pub payment_id: String,
#[schema(value_type = String)]
pub payment_id: common_utils::id_type::PaymentId,
/// The identifier for payment_attempt
pub attempt_id: String,
/// The dispute amount

View File

@ -70,7 +70,7 @@ impl<'a> From<&'a ApiErrorResponse> for ErrorResponse<'a> {
#[derive(Debug, serde::Serialize, Default, Clone)]
pub struct Extra {
#[serde(skip_serializing_if = "Option::is_none")]
pub payment_id: Option<String>,
pub payment_id: Option<common_utils::id_type::PaymentId>,
#[serde(skip_serializing_if = "Option::is_none")]
pub data: Option<serde_json::Value>,
#[serde(skip_serializing_if = "Option::is_none")]

View File

@ -68,12 +68,22 @@ pub struct BankCodeResponse {
pub eligible_connectors: Vec<String>,
}
#[derive(Debug, PartialEq)]
#[derive(Debug, PartialEq, Clone)]
pub struct ClientSecret {
pub payment_id: String,
pub payment_id: id_type::PaymentId,
pub secret: String,
}
impl ClientSecret {
pub fn get_client_secret(&self) -> String {
format!(
"{}_secret_{}",
self.payment_id.get_string_repr(),
self.secret
)
}
}
impl<'de> Deserialize<'de> for ClientSecret {
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
where
@ -96,8 +106,12 @@ impl<'de> Deserialize<'de> for ClientSecret {
E::invalid_value(Unexpected::Str(value), &"a string with '_secret_'")
})?;
let payment_id =
id_type::PaymentId::try_from(std::borrow::Cow::Owned(payment_id.to_owned()))
.map_err(de::Error::custom)?;
Ok(ClientSecret {
payment_id: payment_id.to_owned(),
payment_id,
secret: secret.to_owned(),
})
}
@ -112,7 +126,11 @@ impl Serialize for ClientSecret {
where
S: Serializer,
{
let combined = format!("{}_secret_{}", self.payment_id, self.secret);
let combined = format!(
"{}_secret_{}",
self.payment_id.get_string_repr(),
self.secret
);
serializer.serialize_str(&combined)
}
}
@ -120,6 +138,7 @@ impl Serialize for ClientSecret {
#[cfg(test)]
mod client_secret_tests {
#![allow(clippy::expect_used)]
#![allow(clippy::unwrap_used)]
use serde_json;
@ -128,11 +147,17 @@ mod client_secret_tests {
#[test]
fn test_serialize_client_secret() {
let client_secret1 = ClientSecret {
payment_id: "pay_3TgelAms4RQec8xSStjF".to_string(),
payment_id: id_type::PaymentId::try_from(std::borrow::Cow::Borrowed(
"pay_3TgelAms4RQec8xSStjF",
))
.unwrap(),
secret: "fc34taHLw1ekPgNh92qr".to_string(),
};
let client_secret2 = ClientSecret {
payment_id: "pay_3Tgel__Ams4RQ_secret_ec8xSStjF".to_string(),
payment_id: id_type::PaymentId::try_from(std::borrow::Cow::Borrowed(
"pay_3Tgel__Ams4RQ_secret_ec8xSStjF",
))
.unwrap(),
secret: "fc34taHLw1ekPgNh92qr".to_string(),
};
@ -157,15 +182,24 @@ mod client_secret_tests {
r#""pay_3Tgel__Ams4RQ_secret_ec8xSStjF_secret__secret_fc34taHLw1ekPgNh92qr""#;
let expected1 = ClientSecret {
payment_id: "pay_3TgelAms4RQec8xSStjF".to_string(),
payment_id: id_type::PaymentId::try_from(std::borrow::Cow::Borrowed(
"pay_3TgelAms4RQec8xSStjF",
))
.unwrap(),
secret: "fc34taHLw1ekPgNh92qr".to_string(),
};
let expected2 = ClientSecret {
payment_id: "pay_3Tgel__Ams4RQ_secret_ec8xSStjF".to_string(),
payment_id: id_type::PaymentId::try_from(std::borrow::Cow::Borrowed(
"pay_3Tgel__Ams4RQ_secret_ec8xSStjF",
))
.unwrap(),
secret: "fc34taHLw1ekPgNh92qr".to_string(),
};
let expected3 = ClientSecret {
payment_id: "pay_3Tgel__Ams4RQ_secret_ec8xSStjF_secret_".to_string(),
payment_id: id_type::PaymentId::try_from(std::borrow::Cow::Borrowed(
"pay_3Tgel__Ams4RQ_secret_ec8xSStjF_secret_",
))
.unwrap(),
secret: "fc34taHLw1ekPgNh92qr".to_string(),
};
@ -942,7 +976,7 @@ impl From<MinorUnit> for Amount {
#[derive(Default, Debug, serde::Deserialize, serde::Serialize, Clone)]
#[serde(deny_unknown_fields)]
pub struct PaymentsRedirectRequest {
pub payment_id: String,
pub payment_id: id_type::PaymentId,
pub merchant_id: id_type::MerchantId,
pub connector: String,
pub param: String,
@ -999,7 +1033,7 @@ pub struct ConnectorMandateReferenceId {
pub struct UpdateHistory {
pub connector_mandate_id: Option<String>,
pub payment_method_id: String,
pub original_payment_id: Option<String>,
pub original_payment_id: Option<id_type::PaymentId>,
}
impl MandateIds {
@ -3055,7 +3089,7 @@ pub struct PaymentMethodDataResponseWithBilling {
#[derive(Debug, Clone, PartialEq, Eq, serde::Serialize, serde::Deserialize, ToSchema)]
pub enum PaymentIdType {
/// The identifier for payment intent
PaymentIntentId(String),
PaymentIntentId(id_type::PaymentId),
/// The identifier for connector transaction
ConnectorTransactionId(String),
/// The identifier for payment attempt
@ -3068,7 +3102,11 @@ impl fmt::Display for PaymentIdType {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
Self::PaymentIntentId(payment_id) => {
write!(f, "payment_intent_id = \"{payment_id}\"")
write!(
f,
"payment_intent_id = \"{}\"",
payment_id.get_string_repr()
)
}
Self::ConnectorTransactionId(connector_transaction_id) => write!(
f,
@ -3084,20 +3122,6 @@ impl fmt::Display for PaymentIdType {
}
}
impl PaymentIdType {
pub fn and_then<F, E>(self, f: F) -> Result<Self, E>
where
F: FnOnce(String) -> Result<String, E>,
{
match self {
Self::PaymentIntentId(s) => f(s).map(Self::PaymentIntentId),
Self::ConnectorTransactionId(s) => f(s).map(Self::ConnectorTransactionId),
Self::PaymentAttemptId(s) => f(s).map(Self::PaymentAttemptId),
Self::PreprocessingId(s) => f(s).map(Self::PreprocessingId),
}
}
}
impl Default for PaymentIdType {
fn default() -> Self {
Self::PaymentIntentId(Default::default())
@ -3295,7 +3319,7 @@ pub struct PhoneDetails {
pub struct PaymentsCaptureRequest {
/// The unique identifier for the payment
#[serde(skip_deserializing)]
pub payment_id: String,
pub payment_id: id_type::PaymentId,
/// The unique identifier for the merchant
#[schema(value_type = Option<String>)]
pub merchant_id: Option<id_type::MerchantId>,
@ -3571,9 +3595,10 @@ pub struct PaymentsResponse {
#[schema(
min_length = 30,
max_length = 30,
example = "pay_mbabizu24mvu3mela5njyhpit4"
example = "pay_mbabizu24mvu3mela5njyhpit4",
value_type = String,
)]
pub payment_id: String,
pub payment_id: id_type::PaymentId,
/// This is an identifier for the merchant account. This is inferred from the API key
/// provided during the request
@ -3942,12 +3967,12 @@ pub struct PaymentListConstraints {
pub customer_id: Option<id_type::CustomerId>,
/// A cursor for use in pagination, fetch the next list after some object
#[schema(example = "pay_fafa124123")]
pub starting_after: Option<String>,
#[schema(example = "pay_fafa124123", value_type = Option<String>)]
pub starting_after: Option<id_type::PaymentId>,
/// A cursor for use in pagination, fetch the previous list before some object
#[schema(example = "pay_fafa124123")]
pub ending_before: Option<String>,
#[schema(example = "pay_fafa124123", value_type = Option<String>)]
pub ending_before: Option<id_type::PaymentId>,
/// limit on the number of objects to return
#[schema(default = 10, maximum = 100)]
@ -4032,7 +4057,7 @@ pub struct PaymentListResponseV2 {
#[derive(Clone, Debug, serde::Deserialize, serde::Serialize)]
pub struct PaymentListFilterConstraints {
/// The identifier for payment
pub payment_id: Option<String>,
pub payment_id: Option<id_type::PaymentId>,
/// The identifier for business profile
pub profile_id: Option<id_type::ProfileId>,
/// The identifier for customer
@ -4153,7 +4178,7 @@ pub struct TimeRange {
#[derive(Setter, Clone, Default, Debug, PartialEq, serde::Serialize)]
pub struct VerifyResponse {
pub verify_id: Option<String>,
pub verify_id: Option<id_type::PaymentId>,
pub merchant_id: Option<id_type::MerchantId>,
// pub status: enums::VerifyStatus,
pub client_secret: Option<Secret<String>>,
@ -4308,7 +4333,7 @@ impl From<AdditionalPaymentData> for PaymentMethodDataResponse {
#[derive(Debug, Clone, serde::Serialize)]
pub struct PgRedirectResponse {
pub payment_id: String,
pub payment_id: id_type::PaymentId,
pub status: api_enums::IntentStatus,
pub gateway_id: String,
pub customer_id: Option<id_type::CustomerId>,
@ -4335,6 +4360,7 @@ pub struct PaymentsResponseForm {
#[derive(Default, Debug, serde::Deserialize, serde::Serialize, Clone, ToSchema)]
pub struct PaymentsRetrieveRequest {
/// The type of ID (ex: payment intent id, payment attempt id or connector txn id)
#[schema(value_type = String)]
pub resource_id: PaymentIdType,
/// The identifier for the Merchant Account.
#[schema(value_type = Option<String>)]
@ -4429,7 +4455,8 @@ pub struct RedirectResponse {
#[derive(Debug, serde::Deserialize, serde::Serialize, Clone, ToSchema)]
pub struct PaymentsSessionRequest {
/// The identifier for the payment
pub payment_id: String,
#[schema(value_type = String)]
pub payment_id: id_type::PaymentId,
/// This is a token which expires after 15 minutes, used from the client to authenticate and create sessions from the SDK
pub client_secret: String,
/// The list of the supported wallets
@ -4951,7 +4978,8 @@ pub struct ApplepayErrorResponse {
#[derive(Default, Debug, serde::Serialize, Clone, ToSchema)]
pub struct PaymentsSessionResponse {
/// The identifier for the payment
pub payment_id: String,
#[schema(value_type = String)]
pub payment_id: id_type::PaymentId,
/// This is a token which expires after 15 minutes, used from the client to authenticate and create sessions from the SDK
#[schema(value_type = String)]
pub client_secret: Secret<String, pii::ClientSecret>,
@ -4977,7 +5005,7 @@ pub struct PaymentRetrieveBody {
#[derive(Default, Debug, serde::Deserialize, serde::Serialize, Clone, ToSchema)]
pub struct PaymentRetrieveBodyWithCredentials {
/// The identifier for payment.
pub payment_id: String,
pub payment_id: id_type::PaymentId,
/// The identifier for the Merchant Account.
#[schema(value_type = Option<String>)]
pub merchant_id: Option<id_type::MerchantId>,
@ -4991,7 +5019,7 @@ pub struct PaymentRetrieveBodyWithCredentials {
pub struct PaymentsCompleteAuthorizeRequest {
/// The unique identifier for the payment
#[serde(skip_deserializing)]
pub payment_id: String,
pub payment_id: id_type::PaymentId,
/// The shipping address for the payment
pub shipping: Option<Address>,
/// Client Secret
@ -5003,7 +5031,7 @@ pub struct PaymentsCompleteAuthorizeRequest {
pub struct PaymentsCancelRequest {
/// The identifier for the payment
#[serde(skip)]
pub payment_id: String,
pub payment_id: id_type::PaymentId,
/// The reason for the payment cancel
pub cancellation_reason: Option<String>,
/// Merchant connector details used to make payments.
@ -5015,7 +5043,7 @@ pub struct PaymentsCancelRequest {
pub struct PaymentsIncrementalAuthorizationRequest {
/// The identifier for the payment
#[serde(skip)]
pub payment_id: String,
pub payment_id: id_type::PaymentId,
/// The total amount including previously authorized amount and additional amount
#[schema(value_type = i64, example = 6540)]
pub amount: MinorUnit,
@ -5027,7 +5055,7 @@ pub struct PaymentsIncrementalAuthorizationRequest {
pub struct PaymentsExternalAuthenticationRequest {
/// The identifier for the payment
#[serde(skip)]
pub payment_id: String,
pub payment_id: id_type::PaymentId,
/// Client Secret
#[schema(value_type = String)]
pub client_secret: Secret<String>,
@ -5044,7 +5072,7 @@ pub struct PaymentsExternalAuthenticationRequest {
pub struct PaymentsManualUpdateRequest {
/// The identifier for the payment
#[serde(skip)]
pub payment_id: String,
pub payment_id: id_type::PaymentId,
/// The identifier for the payment attempt
pub attempt_id: String,
/// Merchant ID
@ -5065,7 +5093,7 @@ pub struct PaymentsManualUpdateRequest {
#[derive(Debug, serde::Serialize, serde::Deserialize, Clone, ToSchema)]
pub struct PaymentsManualUpdateResponse {
/// The identifier for the payment
pub payment_id: String,
pub payment_id: id_type::PaymentId,
/// The identifier for the payment attempt
pub attempt_id: String,
/// Merchant ID
@ -5148,23 +5176,22 @@ pub struct PaymentsExternalAuthenticationResponse {
pub struct PaymentsApproveRequest {
/// The identifier for the payment
#[serde(skip)]
pub payment_id: String,
pub payment_id: id_type::PaymentId,
}
#[derive(Default, Debug, serde::Deserialize, serde::Serialize, Clone, ToSchema)]
pub struct PaymentsRejectRequest {
/// The identifier for the payment
#[serde(skip)]
pub payment_id: String,
pub payment_id: id_type::PaymentId,
}
#[derive(Default, Debug, serde::Deserialize, serde::Serialize, ToSchema, Clone)]
#[derive(Default, Debug, serde::Deserialize, serde::Serialize, Clone)]
pub struct PaymentsStartRequest {
/// Unique identifier for the payment. This ensures idempotency for multiple payments
/// that have been done by a single merchant. This field is auto generated and is returned in the API response.
pub payment_id: String,
pub payment_id: id_type::PaymentId,
/// The identifier for the Merchant Account.
#[schema(value_type = String)]
pub merchant_id: id_type::MerchantId,
/// The identifier for the payment transaction
pub attempt_id: String,
@ -5195,7 +5222,7 @@ pub struct FrmMessage {
}
mod payment_id_type {
use std::fmt;
use std::{borrow::Cow, fmt};
use serde::{
de::{self, Visitor},
@ -5218,7 +5245,9 @@ mod payment_id_type {
where
E: de::Error,
{
Ok(PaymentIdType::PaymentIntentId(value.to_string()))
common_utils::id_type::PaymentId::try_from(Cow::Owned(value.to_string()))
.map_err(de::Error::custom)
.map(PaymentIdType::PaymentIntentId)
}
}
@ -5412,7 +5441,8 @@ pub struct RetrievePaymentLinkResponse {
pub struct PaymentLinkInitiateRequest {
#[schema(value_type = String)]
pub merchant_id: id_type::MerchantId,
pub payment_id: String,
#[schema(value_type = String)]
pub payment_id: id_type::PaymentId,
}
#[derive(Debug, serde::Serialize)]
@ -5428,7 +5458,7 @@ pub struct PaymentLinkDetails {
pub currency: api_enums::Currency,
pub pub_key: String,
pub client_secret: String,
pub payment_id: String,
pub payment_id: id_type::PaymentId,
#[serde(with = "common_utils::custom_serde::iso8601")]
pub session_expiry: PrimitiveDateTime,
pub merchant_logo: String,
@ -5455,7 +5485,7 @@ pub struct SecurePaymentLinkDetails {
pub struct PaymentLinkStatusDetails {
pub amount: StringMajorUnit,
pub currency: api_enums::Currency,
pub payment_id: String,
pub payment_id: id_type::PaymentId,
pub merchant_logo: String,
pub merchant_name: String,
#[serde(with = "common_utils::custom_serde::iso8601")]

View File

@ -9,8 +9,8 @@ use common_utils::{
pub struct LinkTokenCreateRequest {
pub language: Option<String>, // optional language field to be passed
pub client_secret: Option<String>, // client secret to be passed in req body
pub payment_id: String, // payment_id to be passed in req body for redis pm_auth connector name fetch
pub payment_method: PaymentMethod, // payment_method to be used for filtering pm_auth connector
pub payment_id: id_type::PaymentId, // payment_id to be passed in req body for redis pm_auth connector name fetch
pub payment_method: PaymentMethod, // payment_method to be used for filtering pm_auth connector
pub payment_method_type: PaymentMethodType, // payment_method_type to be used for filtering pm_auth connector
}
@ -26,7 +26,7 @@ pub struct LinkTokenCreateResponse {
pub struct ExchangeTokenCreateRequest {
pub public_token: String,
pub client_secret: Option<String>,
pub payment_id: String,
pub payment_id: id_type::PaymentId,
pub payment_method: PaymentMethod,
pub payment_method_type: PaymentMethodType,
}

View File

@ -19,9 +19,10 @@ pub struct RefundRequest {
#[schema(
max_length = 30,
min_length = 30,
example = "pay_mbabizu24mvu3mela5njyhpit4"
example = "pay_mbabizu24mvu3mela5njyhpit4",
value_type = String,
)]
pub payment_id: String,
pub payment_id: common_utils::id_type::PaymentId,
/// Unique Identifier for the Refund. This is to ensure idempotency for multiple partial refunds initiated against the same payment. If this is not passed by the merchant, this field shall be auto generated and provided in the API response. It is recommended to generate uuid(v4) as the refund_id.
#[schema(
@ -129,7 +130,8 @@ pub struct RefundResponse {
/// Unique Identifier for the refund
pub refund_id: String,
/// The payment id against which refund is initiated
pub payment_id: String,
#[schema(value_type = String)]
pub payment_id: common_utils::id_type::PaymentId,
/// The refund amount, which should be less than or equal to the total payment amount. Amount for the payment in lowest denomination of the currency. (i.e) in cents for USD denomination, in paisa for INR denomination etc
#[schema(value_type = i64 , minimum = 100, example = 6540)]
pub amount: MinorUnit,
@ -169,7 +171,8 @@ pub struct RefundResponse {
#[derive(Debug, Clone, Eq, PartialEq, Deserialize, Serialize, ToSchema)]
pub struct RefundListRequest {
/// The identifier for the payment
pub payment_id: Option<String>,
#[schema(value_type = Option<String>)]
pub payment_id: Option<common_utils::id_type::PaymentId>,
/// The identifier for the refund
pub refund_id: Option<String>,
/// The identifier for business profile

View File

@ -68,7 +68,7 @@ pub struct ConfiguredRouting {
#[derive(Debug, serde::Deserialize, serde::Serialize)]
pub struct TestPayment {
pub payment_id: String,
pub payment_id: id_type::PaymentId,
}
#[derive(Debug, serde::Deserialize, serde::Serialize, Clone)]

View File

@ -77,7 +77,7 @@ pub enum WebhookFlow {
/// This enum tells about the affect a webhook had on an object
pub enum WebhookResponseTracker {
Payment {
payment_id: String,
payment_id: common_utils::id_type::PaymentId,
status: common_enums::IntentStatus,
},
#[cfg(feature = "payouts")]
@ -86,13 +86,13 @@ pub enum WebhookResponseTracker {
status: common_enums::PayoutStatus,
},
Refund {
payment_id: String,
payment_id: common_utils::id_type::PaymentId,
refund_id: String,
status: common_enums::RefundStatus,
},
Dispute {
dispute_id: String,
payment_id: String,
payment_id: common_utils::id_type::PaymentId,
status: common_enums::DisputeStatus,
},
Mandate {
@ -103,11 +103,11 @@ pub enum WebhookResponseTracker {
}
impl WebhookResponseTracker {
pub fn get_payment_id(&self) -> Option<String> {
pub fn get_payment_id(&self) -> Option<common_utils::id_type::PaymentId> {
match self {
Self::Payment { payment_id, .. }
| Self::Refund { payment_id, .. }
| Self::Dispute { payment_id, .. } => Some(payment_id.to_string()),
| Self::Dispute { payment_id, .. } => Some(payment_id.to_owned()),
Self::NoEffect | Self::Mandate { .. } => None,
#[cfg(feature = "payouts")]
Self::Payout { .. } => None,