diff --git a/crates/api_models/src/admin.rs b/crates/api_models/src/admin.rs index 2d193c9b3b..7bf8e743b3 100644 --- a/crates/api_models/src/admin.rs +++ b/crates/api_models/src/admin.rs @@ -211,7 +211,7 @@ pub struct WebhookDetails { } #[derive(Debug, Serialize, ToSchema)] -pub struct DeleteResponse { +pub struct DeleteMerchantAccountResponse { /// The identifier for the Merchant Account #[schema(max_length = 255, example = "y3oqhf46pyzuxjbcn2giaqnb44")] pub merchant_id: String, diff --git a/crates/api_models/src/enums.rs b/crates/api_models/src/enums.rs index dc8666b10b..e6c2201145 100644 --- a/crates/api_models/src/enums.rs +++ b/crates/api_models/src/enums.rs @@ -326,6 +326,7 @@ pub enum FutureUsage { strum::Display, strum::EnumString, frunk::LabelledGeneric, + ToSchema, )] #[strum(serialize_all = "snake_case")] #[serde(rename_all = "snake_case")] @@ -467,6 +468,7 @@ pub enum RoutingAlgorithm { Custom, } +/// The status of the mandate, which indicates whether it can be used to initiate a payment #[derive( Clone, Copy, @@ -479,6 +481,7 @@ pub enum RoutingAlgorithm { strum::Display, strum::EnumString, frunk::LabelledGeneric, + ToSchema, )] #[serde(rename_all = "snake_case")] #[strum(serialize_all = "snake_case")] diff --git a/crates/api_models/src/mandates.rs b/crates/api_models/src/mandates.rs index 5d6462fa94..a5283b375e 100644 --- a/crates/api_models/src/mandates.rs +++ b/crates/api_models/src/mandates.rs @@ -1,5 +1,6 @@ use masking::Secret; use serde::{Deserialize, Serialize}; +use utoipa::ToSchema; use crate::{enums as api_enums, payments}; @@ -8,30 +9,54 @@ pub struct MandateId { pub mandate_id: String, } -#[derive(Default, Debug, Deserialize, Serialize)] +#[derive(Default, Debug, Deserialize, Serialize, ToSchema)] pub struct MandateRevokedResponse { + /// The identifier for mandate pub mandate_id: String, + /// The status for mandates + #[schema(value_type = MandateStatus)] pub status: api_enums::MandateStatus, } -#[derive(Default, Debug, Deserialize, Serialize)] +#[derive(Default, Debug, Deserialize, Serialize, ToSchema)] pub struct MandateResponse { + /// The identifier for mandate pub mandate_id: String, + /// The status for mandates + #[schema(value_type = MandateStatus)] pub status: api_enums::MandateStatus, + /// The identifier for payment method pub payment_method_id: String, + /// The payment method pub payment_method: String, + /// The card details for mandate pub card: Option, + /// Details about the customer’s acceptance + #[schema(value_type = Option)] pub customer_acceptance: Option, } -#[derive(Default, Debug, Deserialize, Serialize)] +#[derive(Default, Debug, Deserialize, Serialize, ToSchema)] pub struct MandateCardDetails { + /// The last 4 digits of card pub last4_digits: Option, + /// The expiry month of card + #[schema(value_type = Option)] pub card_exp_month: Option>, + /// The expiry year of card + #[schema(value_type = Option)] pub card_exp_year: Option>, + /// The card holder name + #[schema(value_type = Option)] pub card_holder_name: Option>, + /// The token from card locker + #[schema(value_type = Option)] pub card_token: Option>, + /// The card scheme network for the particular card pub scheme: Option, + /// The country code in in which the card was issued pub issuer_country: Option, + #[schema(value_type = Option)] + /// A unique identifier alias to identify a particular card pub card_fingerprint: Option>, } diff --git a/crates/api_models/src/payment_methods.rs b/crates/api_models/src/payment_methods.rs index 755aa24f9c..4d0f484f3b 100644 --- a/crates/api_models/src/payment_methods.rs +++ b/crates/api_models/src/payment_methods.rs @@ -6,76 +6,185 @@ use utoipa::ToSchema; use crate::enums as api_enums; -#[derive(Debug, serde::Deserialize, serde::Serialize, Clone)] +#[derive(Debug, serde::Deserialize, serde::Serialize, Clone, ToSchema)] #[serde(deny_unknown_fields)] pub struct CreatePaymentMethod { + /// The type of payment method use for the payment. + #[schema(value_type = PaymentMethodType,example = "card")] pub payment_method: api_enums::PaymentMethodType, + + /// This is a sub-category of payment method. + #[schema(value_type = Option,example = "credit_card")] pub payment_method_type: Option, + + /// The name of the bank/ provider issuing the payment method to the end user + #[schema(example = "Citibank")] pub payment_method_issuer: Option, + + /// A standard code representing the issuer of payment method + #[schema(value_type = Option,example = "jp_applepay")] pub payment_method_issuer_code: Option, + + /// Card Details + #[schema(example = json!({ + "card_number": "4111111145551142", + "card_exp_month": "10", + "card_exp_year": "25", + "card_holder_name": "John Doe"}))] pub card: Option, + + /// You can specify up to 50 keys, with key names up to 40 characters long and values up to 500 characters long. Metadata is useful for storing additional, structured information on an object. + #[schema(value_type = Option,example = json!({ "city": "NY", "unit": "245" }))] pub metadata: Option, + + /// The unique identifier of the customer. + #[schema(example = "cus_meowerunwiuwiwqw")] pub customer_id: Option, } -#[derive(Debug, serde::Deserialize, serde::Serialize, Clone)] +#[derive(Debug, serde::Deserialize, serde::Serialize, Clone, ToSchema)] #[serde(deny_unknown_fields)] pub struct UpdatePaymentMethod { + /// Card Details + #[schema(example = json!({ + "card_number": "4111111145551142", + "card_exp_month": "10", + "card_exp_year": "25", + "card_holder_name": "John Doe"}))] pub card: Option, - // Add more payment method update field in future + + /// You can specify up to 50 keys, with key names up to 40 characters long and values up to 500 characters long. Metadata is useful for storing additional, structured information on an object. + #[schema(value_type = Option,example = json!({ "city": "NY", "unit": "245" }))] pub metadata: Option, } -#[derive(Debug, serde::Deserialize, serde::Serialize, Clone)] +#[derive(Debug, serde::Deserialize, serde::Serialize, Clone, ToSchema)] #[serde(deny_unknown_fields)] pub struct CardDetail { + /// Card Number + #[schema(value_type = String,example = "4111111145551142")] pub card_number: masking::Secret, + + /// Card Expiry Month + #[schema(value_type = String,example = "10")] pub card_exp_month: masking::Secret, + + /// Card Expiry Year + #[schema(value_type = String,example = "25")] pub card_exp_year: masking::Secret, + + /// Card Holder Name + #[schema(value_type = String,example = "John Doe")] pub card_holder_name: Option>, } -#[derive(Debug, serde::Deserialize, serde::Serialize)] +#[derive(Debug, serde::Deserialize, serde::Serialize, ToSchema)] pub struct PaymentMethodResponse { + /// Unique identifier for a merchant + #[schema(example = "merchant_1671528864")] pub merchant_id: String, + + /// The unique identifier of the customer. + #[schema(example = "cus_meowerunwiuwiwqw")] pub customer_id: Option, + + /// The unique identifier of the Payment method + #[schema(example = "card_rGK4Vi5iSW70MY7J2mIy")] pub payment_method_id: String, + + /// The type of payment method use for the payment. + #[schema(value_type = PaymentMethodType,example = "card")] pub payment_method: api_enums::PaymentMethodType, + + /// This is a sub-category of payment method. + #[schema(value_type = Option,example = "credit_card")] pub payment_method_type: Option, + + /// The name of the bank/ provider issuing the payment method to the end user + #[schema(example = "Citibank")] pub payment_method_issuer: Option, + + /// A standard code representing the issuer of payment method + #[schema(value_type = Option,example = "jp_applepay")] pub payment_method_issuer_code: Option, + + /// Card details from card locker + #[schema(example = json!({"last4": "1142","exp_month": "03","exp_year": "2030"}))] pub card: Option, + + /// Indicates whether the payment method is eligible for recurring payments + #[schema(example = true)] pub recurring_enabled: bool, + + /// Indicates whether the payment method is eligible for installment payments + #[schema(example = true)] pub installment_payment_enabled: bool, + + /// Type of payment experience enabled with the connector + #[schema(value_type = Option>,example = json!(["redirect_to_url"]))] pub payment_experience: Option>, + + /// You can specify up to 50 keys, with key names up to 40 characters long and values up to 500 characters long. Metadata is useful for storing additional, structured information on an object. + #[schema(value_type = Option,example = json!({ "city": "NY", "unit": "245" }))] pub metadata: Option, + + /// A timestamp (ISO 8601 code) that determines when the customer was created + #[schema(value_type = Option,example = "2023-01-18T11:04:09.922Z")] #[serde(default, with = "common_utils::custom_serde::iso8601::option")] pub created: Option, } -#[derive(Debug, serde::Deserialize, serde::Serialize, Clone)] +#[derive(Debug, serde::Deserialize, serde::Serialize, Clone, ToSchema)] pub struct CardDetailFromLocker { pub scheme: Option, pub issuer_country: Option, pub last4_digits: Option, #[serde(skip)] + #[schema(value_type=Option)] pub card_number: Option>, + + #[schema(value_type=Option)] pub expiry_month: Option>, + + #[schema(value_type=Option)] pub expiry_year: Option>, + + #[schema(value_type=Option)] pub card_token: Option>, + + #[schema(value_type=Option)] pub card_holder_name: Option>, + + #[schema(value_type=Option)] pub card_fingerprint: Option>, } //List Payment Method -#[derive(Debug, serde::Serialize, Default)] +#[derive(Debug, serde::Serialize, Default, ToSchema)] #[serde(deny_unknown_fields)] pub struct ListPaymentMethodRequest { + /// This is a 15 minute expiry token which shall be used from the client to authenticate and perform sessions from the SDK + #[schema(max_length = 30, min_length = 30, example = "secret_k2uj3he2893ein2d")] pub client_secret: Option, + + /// The two-letter ISO currency code + #[schema(example = json!(["US", "UK", "IN"]))] pub accepted_countries: Option>, + + /// The three-letter ISO currency code + #[schema(value_type = Option>,example = json!(["USD", "EUR"]))] pub accepted_currencies: Option>, + + /// Filter by amount + #[schema(example = 60)] pub amount: Option, + + /// Indicates whether the payment method is eligible for recurring payments + #[schema(example = true)] pub recurring_enabled: Option, + + /// Indicates whether the payment method is eligible for installment payments + #[schema(example = true)] pub installment_payment_enabled: Option, } @@ -168,25 +277,78 @@ fn set_or_reject_duplicate( } } -#[derive(Debug, serde::Serialize)] +#[derive(Debug, serde::Serialize, ToSchema)] pub struct ListPaymentMethodResponse { + /// Redirect URL of the merchant + #[schema(example = "https://www.google.com")] pub redirect_url: Option, + + /// Information about the payment method + #[schema(value_type = Vec,example = json!( + [ + { + "payment_method": "wallet", + "payment_experience": null, + "payment_method_issuers": [ + "labore magna ipsum", + "aute" + ] + } + ] + ))] pub payment_methods: HashSet, } -#[derive(Eq, PartialEq, Hash, Debug, serde::Deserialize)] +#[derive(Eq, PartialEq, Hash, Debug, serde::Deserialize, ToSchema)] pub struct ListPaymentMethod { + /// The type of payment method use for the payment. + #[schema(value_type = PaymentMethodType,example = "card")] pub payment_method: api_enums::PaymentMethodType, + + /// This is a sub-category of payment method. + #[schema(value_type = Option>,example = json!(["credit_card"]))] pub payment_method_types: Option>, + + /// The name of the bank/ provider issuing the payment method to the end user + #[schema(example = json!(["Citibank"]))] pub payment_method_issuers: Option>, + + /// A standard code representing the issuer of payment method + #[schema(value_type = Option>,example = json!(["jp_applepay"]))] pub payment_method_issuer_code: Option>, + + /// List of payment schemes accepted or has the processing capabilities of the processor + #[schema(example = json!(["MASTER", "VISA", "DINERS"]))] pub payment_schemes: Option>, + + /// List of Countries accepted or has the processing capabilities of the processor + #[schema(example = json!(["US", "UK", "IN"]))] pub accepted_countries: Option>, + + /// List of currencies accepted or has the processing capabilities of the processor + #[schema(value_type = Option>,example = json!(["USD", "EUR"]))] pub accepted_currencies: Option>, + + /// Minimum amount supported by the processor. To be represented in the lowest denomination of + /// the target currency (For example, for USD it should be in cents) + #[schema(example = 60000)] pub minimum_amount: Option, + + /// Maximum amount supported by the processor. To be represented in the lowest denomination of + /// the target currency (For example, for USD it should be in cents) + #[schema(example = 1)] pub maximum_amount: Option, + + /// Boolean to enable recurring payments / mandates. Default is true. + #[schema(example = true)] pub recurring_enabled: bool, + + /// Boolean to enable installment / EMI / BNPL payments. Default is true. + #[schema(example = true)] pub installment_payment_enabled: bool, + + /// Type of payment experience enabled with the connector + #[schema(example = json!(["redirect_to_url"]))] pub payment_experience: Option>, } @@ -217,31 +379,86 @@ impl serde::Serialize for ListPaymentMethod { } } -#[derive(Debug, serde::Serialize)] +#[derive(Debug, serde::Serialize, ToSchema)] pub struct ListCustomerPaymentMethodsResponse { + /// List of enabled payment methods for a customer + #[schema(value_type = Vec,example = json!( + [ + { + "payment_method": "wallet", + "payment_experience": null, + "payment_method_issuers": [ + "labore magna ipsum", + "aute" + ] + } + ] + ))] pub enabled_payment_methods: HashSet, + + /// List of payment methods for customer pub customer_payment_methods: Vec, } -#[derive(Debug, serde::Serialize)] +#[derive(Debug, serde::Serialize, ToSchema)] pub struct DeletePaymentMethodResponse { + /// The unique identifier of the Payment method + #[schema(example = "card_rGK4Vi5iSW70MY7J2mIy")] pub payment_method_id: String, + + /// Whether payment method was deleted or not + #[schema(example = true)] pub deleted: bool, } -#[derive(Debug, serde::Serialize)] +#[derive(Debug, serde::Serialize, ToSchema)] pub struct CustomerPaymentMethod { + /// Token for payment method in temporary card locker which gets refreshed often + #[schema(example = "7ebf443f-a050-4067-84e5-e6f6d4800aef")] pub payment_token: String, + + /// The unique identifier of the customer. + #[schema(example = "cus_meowerunwiuwiwqw")] pub customer_id: String, + + /// The type of payment method use for the payment. + #[schema(value_type = PaymentMethodType,example = "card")] pub payment_method: api_enums::PaymentMethodType, + + /// This is a sub-category of payment method. + #[schema(value_type = Option,example = "credit_card")] pub payment_method_type: Option, + + /// The name of the bank/ provider issuing the payment method to the end user + #[schema(example = "Citibank")] pub payment_method_issuer: Option, + + /// A standard code representing the issuer of payment method + #[schema(value_type = Option,example = "jp_applepay")] pub payment_method_issuer_code: Option, + + /// Indicates whether the payment method is eligible for recurring payments + #[schema(example = true)] pub recurring_enabled: bool, + + /// Indicates whether the payment method is eligible for installment payments + #[schema(example = true)] pub installment_payment_enabled: bool, + + /// Type of payment experience enabled with the connector + #[schema(value_type = Option>,example = json!(["redirect_to_url"]))] pub payment_experience: Option>, + + /// Card details from card locker + #[schema(example = json!({"last4": "1142","exp_month": "03","exp_year": "2030"}))] pub card: Option, + + /// You can specify up to 50 keys, with key names up to 40 characters long and values up to 500 characters long. Metadata is useful for storing additional, structured information on an object. + #[schema(value_type = Option,example = json!({ "city": "NY", "unit": "245" }))] pub metadata: Option, + + /// A timestamp (ISO 8601 code) that determines when the customer was created + #[schema(value_type = Option,example = "2023-01-18T11:04:09.922Z")] #[serde(default, with = "common_utils::custom_serde::iso8601::option")] pub created: Option, } diff --git a/crates/api_models/src/payments.rs b/crates/api_models/src/payments.rs index fc761d2851..b28736c980 100644 --- a/crates/api_models/src/payments.rs +++ b/crates/api_models/src/payments.rs @@ -96,7 +96,7 @@ pub struct PaymentsRequest { /// Provide a reference to a stored payment method #[schema(example = "187282ab-40ef-47a9-9206-5099ba31e432")] pub payment_token: Option, - + /// This is used when payment is to be confirmed and the card is not saved #[schema(value_type = Option)] pub card_cvc: Option>, /// The shipping address for the payment @@ -301,7 +301,7 @@ pub struct OnlineMandate { } #[derive(Default, Eq, PartialEq, Clone, Debug, serde::Deserialize, serde::Serialize, ToSchema)] -pub struct CCard { +pub struct Card { /// The card number #[schema(value_type = String, example = "4242424242424242")] pub card_number: Secret, @@ -375,17 +375,13 @@ pub enum PayLaterData { } #[derive(Debug, Clone, Eq, PartialEq, Default, serde::Deserialize, serde::Serialize, ToSchema)] +#[serde(rename_all = "snake_case")] pub enum PaymentMethod { - #[serde(rename(deserialize = "card"))] - Card(CCard), + Card(Card), #[default] - #[serde(rename(deserialize = "bank_transfer"))] BankTransfer, - #[serde(rename(deserialize = "wallet"))] Wallet(WalletData), - #[serde(rename(deserialize = "pay_later"))] PayLater(PayLaterData), - #[serde(rename(deserialize = "paypal"))] Paypal, } @@ -399,7 +395,7 @@ pub struct WalletData { } #[derive(Eq, PartialEq, Clone, Debug, serde::Serialize)] -pub struct CCardResponse { +pub struct CardResponse { last4: String, exp_month: String, exp_year: String, @@ -408,7 +404,7 @@ pub struct CCardResponse { #[derive(Debug, Clone, Eq, PartialEq, serde::Serialize)] pub enum PaymentMethodDataResponse { #[serde(rename = "card")] - Card(CCardResponse), + Card(CardResponse), #[serde(rename(deserialize = "bank_transfer"))] BankTransfer, Wallet(WalletData), @@ -936,8 +932,8 @@ impl From for PaymentsResponse { } } -impl From for CCardResponse { - fn from(card: CCard) -> Self { +impl From for CardResponse { + fn from(card: Card) -> Self { let card_number_length = card.card_number.peek().clone().len(); Self { last4: card.card_number.peek().clone()[card_number_length - 4..card_number_length] @@ -951,7 +947,7 @@ impl From for CCardResponse { impl From for PaymentMethodDataResponse { fn from(payment_method_data: PaymentMethod) -> Self { match payment_method_data { - PaymentMethod::Card(card) => Self::Card(CCardResponse::from(card)), + PaymentMethod::Card(card) => Self::Card(CardResponse::from(card)), PaymentMethod::BankTransfer => Self::BankTransfer, PaymentMethod::PayLater(pay_later_data) => Self::PayLater(pay_later_data), PaymentMethod::Wallet(wallet_data) => Self::Wallet(wallet_data), diff --git a/crates/api_models/src/refunds.rs b/crates/api_models/src/refunds.rs index ffa1c781a8..976b52557e 100644 --- a/crates/api_models/src/refunds.rs +++ b/crates/api_models/src/refunds.rs @@ -67,18 +67,29 @@ pub enum RefundType { #[derive(Debug, Clone, Eq, PartialEq, Deserialize, Serialize, ToSchema)] pub struct RefundResponse { + /// The identifier for refund pub refund_id: String, + /// The identifier for payment pub payment_id: String, + /// 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 pub amount: i64, + /// The three-letter ISO currency code pub currency: String, + /// An arbitrary string attached to the object. Often useful for displaying to users and your customer support executive pub reason: Option, + /// The status for refund pub status: RefundStatus, + /// You can specify up to 50 keys, with key names up to 40 characters long and values up to 500 characters long. Metadata is useful for storing additional, structured information on an object #[schema(value_type = Option)] pub metadata: Option, + /// The error message pub error_message: Option, + /// The code for the error pub error_code: Option, + /// The timestamp at which refund is created #[serde(with = "common_utils::custom_serde::iso8601::option")] pub created_at: Option, + /// The timestamp at which refund is updated #[serde(with = "common_utils::custom_serde::iso8601::option")] pub updated_at: Option, } @@ -114,11 +125,13 @@ pub struct RefundListRequest { pub created_gte: Option, } -#[derive(Debug, Clone, Eq, PartialEq, Deserialize, Serialize)] +#[derive(Debug, Clone, Eq, PartialEq, Deserialize, Serialize, ToSchema)] pub struct RefundListResponse { + /// The list of refund response pub data: Vec, } +/// The status for refunds #[derive(Debug, Eq, Clone, PartialEq, Default, Deserialize, Serialize, ToSchema)] #[serde(rename_all = "snake_case")] pub enum RefundStatus { diff --git a/crates/router/Cargo.toml b/crates/router/Cargo.toml index efbda28704..9a0888d53e 100644 --- a/crates/router/Cargo.toml +++ b/crates/router/Cargo.toml @@ -19,6 +19,7 @@ olap = [] oltp = [] production = [] kv_store = [] +openapi = ["olap", "oltp"] [dependencies] diff --git a/crates/router/src/bin/router.rs b/crates/router/src/bin/router.rs index bebb4698b6..ef1be47c45 100644 --- a/crates/router/src/bin/router.rs +++ b/crates/router/src/bin/router.rs @@ -1,5 +1,5 @@ use router::{ - configs::settings::{CmdLineConf, Settings, Subcommand}, + configs::settings::{CmdLineConf, Settings}, core::errors::{ApplicationError, ApplicationResult}, logger, }; @@ -8,18 +8,23 @@ use router::{ async fn main() -> ApplicationResult<()> { // get commandline config before initializing config let cmd_line = ::parse(); - if let Some(Subcommand::GenerateOpenapiSpec) = cmd_line.subcommand { - let file_path = "openapi/generated.json"; - #[allow(clippy::expect_used)] - std::fs::write( - file_path, - ::openapi() - .to_pretty_json() - .expect("Failed to generate serialize OpenAPI specification as JSON"), - ) - .expect("Failed to write OpenAPI specification to file"); - println!("Successfully saved OpenAPI specification file at '{file_path}'"); - return Ok(()); + + #[cfg(feature = "openapi")] + { + use router::configs::settings::Subcommand; + if let Some(Subcommand::GenerateOpenapiSpec) = cmd_line.subcommand { + let file_path = "openapi/generated.json"; + #[allow(clippy::expect_used)] + std::fs::write( + file_path, + ::openapi() + .to_pretty_json() + .expect("Failed to generate serialize OpenAPI specification as JSON"), + ) + .expect("Failed to write OpenAPI specification to file"); + println!("Successfully saved OpenAPI specification file at '{file_path}'"); + return Ok(()); + } } #[allow(clippy::expect_used)] diff --git a/crates/router/src/compatibility/stripe/payment_intents/types.rs b/crates/router/src/compatibility/stripe/payment_intents/types.rs index 437d18cfcf..ee98ccc81b 100644 --- a/crates/router/src/compatibility/stripe/payment_intents/types.rs +++ b/crates/router/src/compatibility/stripe/payment_intents/types.rs @@ -73,7 +73,7 @@ pub enum StripePaymentMethodDetails { BankTransfer, } -impl From for payments::CCard { +impl From for payments::Card { fn from(card: StripeCard) -> Self { Self { card_number: card.number, @@ -87,7 +87,7 @@ impl From for payments::CCard { impl From for payments::PaymentMethod { fn from(item: StripePaymentMethodDetails) -> Self { match item { - StripePaymentMethodDetails::Card(card) => Self::Card(payments::CCard::from(card)), + StripePaymentMethodDetails::Card(card) => Self::Card(payments::Card::from(card)), StripePaymentMethodDetails::BankTransfer => Self::BankTransfer, } } diff --git a/crates/router/src/compatibility/stripe/setup_intents/types.rs b/crates/router/src/compatibility/stripe/setup_intents/types.rs index 996af6c29f..f296e06826 100644 --- a/crates/router/src/compatibility/stripe/setup_intents/types.rs +++ b/crates/router/src/compatibility/stripe/setup_intents/types.rs @@ -69,7 +69,7 @@ pub enum StripePaymentMethodDetails { BankTransfer, } -impl From for payments::CCard { +impl From for payments::Card { fn from(card: StripeCard) -> Self { Self { card_number: card.number, @@ -83,7 +83,7 @@ impl From for payments::CCard { impl From for payments::PaymentMethod { fn from(item: StripePaymentMethodDetails) -> Self { match item { - StripePaymentMethodDetails::Card(card) => Self::Card(payments::CCard::from(card)), + StripePaymentMethodDetails::Card(card) => Self::Card(payments::Card::from(card)), StripePaymentMethodDetails::BankTransfer => Self::BankTransfer, } } diff --git a/crates/router/src/configs/settings.rs b/crates/router/src/configs/settings.rs index b21f102801..fb3e69c691 100644 --- a/crates/router/src/configs/settings.rs +++ b/crates/router/src/configs/settings.rs @@ -25,6 +25,7 @@ pub struct CmdLineConf { #[derive(clap::Parser)] pub enum Subcommand { + #[cfg(feature = "openapi")] /// Generate the OpenAPI specification file from code. GenerateOpenapiSpec, } diff --git a/crates/router/src/connector/utils.rs b/crates/router/src/connector/utils.rs index 952e788da6..a8ea25e785 100644 --- a/crates/router/src/connector/utils.rs +++ b/crates/router/src/connector/utils.rs @@ -37,7 +37,7 @@ pub trait PaymentsRequestData { fn get_billing(&self) -> Result<&api::Address, Error>; fn get_billing_country(&self) -> Result; fn get_billing_phone(&self) -> Result<&api::PhoneDetails, Error>; - fn get_card(&self) -> Result; + fn get_card(&self) -> Result; } impl PaymentsRequestData for types::PaymentsAuthorizeRouterData { @@ -56,7 +56,7 @@ impl PaymentsRequestData for types::PaymentsAuthorizeRouterData { .ok_or_else(missing_field_err("billing.address.country")) } - fn get_card(&self) -> Result { + fn get_card(&self) -> Result { match self.request.payment_method_data.clone() { api::PaymentMethod::Card(card) => Ok(card), _ => Err(missing_field_err("card")()), @@ -86,7 +86,7 @@ pub trait CardData { fn get_card_cvc(&self) -> String; } -impl CardData for api::CCard { +impl CardData for api::Card { fn get_card_number(&self) -> String { self.card_number.peek().clone() } diff --git a/crates/router/src/connector/worldline/transformers.rs b/crates/router/src/connector/worldline/transformers.rs index 825014c537..7c363f4a90 100644 --- a/crates/router/src/connector/worldline/transformers.rs +++ b/crates/router/src/connector/worldline/transformers.rs @@ -133,7 +133,7 @@ impl TryFrom<&types::PaymentsAuthorizeRouterData> for PaymentsRequest { fn make_card_request( address: &types::PaymentAddress, req: &types::PaymentsAuthorizeData, - ccard: &api_models::CCard, + ccard: &api_models::Card, ) -> Result> { let card_number = ccard.card_number.peek().as_ref(); let expiry_year = ccard.card_exp_year.peek().clone(); diff --git a/crates/router/src/core/admin.rs b/crates/router/src/core/admin.rs index c9ba3319fb..23b1c82761 100644 --- a/crates/router/src/core/admin.rs +++ b/crates/router/src/core/admin.rs @@ -198,14 +198,14 @@ pub async fn merchant_account_update( pub async fn merchant_account_delete( db: &dyn StorageInterface, merchant_id: String, -) -> RouterResponse { +) -> RouterResponse { let is_deleted = db .delete_merchant_account_by_merchant_id(&merchant_id) .await .map_err(|error| { error.to_not_found_response(errors::ApiErrorResponse::MerchantAccountNotFound) })?; - let response = api::DeleteResponse { + let response = api::DeleteMerchantAccountResponse { merchant_id, deleted: is_deleted, }; diff --git a/crates/router/src/core/payment_methods/vault.rs b/crates/router/src/core/payment_methods/vault.rs index 3532761ad5..2cb010ec15 100644 --- a/crates/router/src/core/payment_methods/vault.rs +++ b/crates/router/src/core/payment_methods/vault.rs @@ -36,7 +36,7 @@ pub trait Vaultable: Sized { ) -> CustomResult<(Self, SupplementaryVaultData), errors::VaultError>; } -impl Vaultable for api::CCard { +impl Vaultable for api::Card { fn get_value1(&self, _customer_id: Option) -> CustomResult { let value1 = api::TokenizedCardValue1 { card_number: self.card_number.peek().clone(), @@ -201,7 +201,7 @@ impl Vaultable for api::PaymentMethod { match (value1, value2) { (VaultPaymentMethod::Card(mvalue1), VaultPaymentMethod::Card(mvalue2)) => { - let (card, supp_data) = api::CCard::from_values(mvalue1, mvalue2)?; + let (card, supp_data) = api::Card::from_values(mvalue1, mvalue2)?; Ok((Self::Card(card), supp_data)) } (VaultPaymentMethod::Wallet(mvalue1), VaultPaymentMethod::Wallet(mvalue2)) => { diff --git a/crates/router/src/lib.rs b/crates/router/src/lib.rs index a2ba872f11..9b2174b294 100644 --- a/crates/router/src/lib.rs +++ b/crates/router/src/lib.rs @@ -16,6 +16,7 @@ pub mod routes; pub mod scheduler; mod middleware; +#[cfg(feature = "openapi")] pub mod openapi; pub mod services; pub mod types; diff --git a/crates/router/src/openapi.rs b/crates/router/src/openapi.rs index cd3329c526..5711e433ef 100644 --- a/crates/router/src/openapi.rs +++ b/crates/router/src/openapi.rs @@ -1,51 +1,97 @@ #[derive(utoipa::OpenApi)] #[openapi( info( - title = "Juspay Router - API Documentation", + title = "Hyperswitch - API Documentation", contact( - name = "Juspay Support", - url = "https://juspay.io", - email = "support@juspay.in" + name = "Hyperswitch Support", + url = "https://hyperswitch.io", + email = "hyperswitch@juspay.in" ), // terms_of_service = "https://www.juspay.io/terms", description = r#" ## Get started -Juspay Router provides a collection of APIs that enable you to process and manage payments. +Hyperswitch provides a collection of APIs that enable you to process and manage payments. Our APIs accept and return JSON in the HTTP body, and return standard HTTP response codes. You can consume the APIs directly using your favorite HTTP/REST library. We have a testing environment referred to "sandbox", which you can setup to test API calls without -affecting production data. +affecting production data. Currently, our sandbox environment is live while our production environment is under development and will be available soon. You can sign up on our Dashboard to get API keys to access Hyperswitch API. -### Base URLs +### Environment Use the following base URLs when making requests to the APIs: -| Environment | Base URL | -|---------------|------------------------------------------------------| -| Sandbox | | -| Production | | +| Environment | Base URL | +|---------------|------------------------------------| +| Sandbox | | +| Production | Coming Soon! | ## Authentication When you sign up on our [dashboard](https://app.hyperswitch.io) and create a merchant -account, you are given a secret key (also referred as api-key). -You may authenticate all API requests with Juspay server by providing the appropriate key in the +account, you are given a secret key (also referred as api-key) and a publishable key. +You may authenticate all API requests with Hyperswitch server by providing the appropriate key in the request Authorization header. +| Key | Description | +|---------------|-----------------------------------------------------------------------------------------------| +| Sandbox | Private key. Used to authenticate all API requests from your merchant server | +| Production | Unique identifier for your account. Used to authenticate API requests from your app’s client | + Never share your secret api keys. Keep them guarded and secure. "#, ), servers( - (url = "https://sandbox.hyperswitch.io", description = "Sandbox Environment"), - (url = "https://router.juspay.io", description = "Production Environment") + (url = "https://sandbox.hyperswitch.io", description = "Sandbox Environment") + ), + tags( + (name = "Merchant Account"),// , description = "Create and manage merchant accounts"), + (name = "Merchant Connector Account"),// , description = "Create and manage merchant connector accounts"), + (name = "Payments"),// , description = "Create and manage one-time payments, recurring payments and mandates"), + (name = "Refunds"),// , description = "Create and manage refunds for successful payments"), + (name = "Mandates"),// , description = "Manage mandates"), + (name = "Customers"),// , description = "Create and manage customers"), + (name = "Payment Methods")// , description = "Create and manage payment methods of customers") ), paths( + crate::routes::refunds::refunds_create, + crate::routes::refunds::refunds_retrieve, + crate::routes::refunds::refunds_update, + crate::routes::refunds::refunds_list, crate::routes::refunds::refunds_create, crate::routes::admin::merchant_account_create, - crate::routes::payments::payments_create + crate::routes::admin::retrieve_merchant_account, + crate::routes::admin::update_merchant_account, + crate::routes::admin::delete_merchant_account, + crate::routes::admin::payment_connector_create, + crate::routes::admin::payment_connector_retrieve, + crate::routes::admin::payment_connector_list, + crate::routes::admin::payment_connector_update, + crate::routes::admin::payment_connector_delete, + crate::routes::mandates::get_mandate, + crate::routes::mandates::revoke_mandate, + crate::routes::payments::payments_create, + // crate::routes::payments::payments_start, + crate::routes::payments::payments_retrieve, + crate::routes::payments::payments_update, + crate::routes::payments::payments_confirm, + crate::routes::payments::payments_capture, + crate::routes::payments::payments_connector_session, + // crate::routes::payments::payments_redirect_response, + crate::routes::payments::payments_cancel, + crate::routes::payments::payments_list, + crate::routes::payment_methods::create_payment_method_api, + crate::routes::payment_methods::list_payment_method_api, + crate::routes::payment_methods::list_customer_payment_method_api, + crate::routes::payment_methods::payment_method_retrieve_api, + crate::routes::payment_methods::payment_method_update_api, + crate::routes::payment_methods::payment_method_delete_api, + crate::routes::customers::customers_create, + crate::routes::customers::customers_retrieve, + crate::routes::customers::customers_update, + crate::routes::customers::customers_delete, ), components(schemas( crate::types::api::refunds::RefundRequest, @@ -54,10 +100,20 @@ Never share your secret api keys. Keep them guarded and secure. crate::types::api::refunds::RefundStatus, crate::types::api::refunds::RefundUpdateRequest, crate::types::api::admin::CreateMerchantAccount, - crate::types::api::admin::DeleteResponse, + crate::types::api::admin::DeleteMerchantAccountResponse, crate::types::api::admin::DeleteMcaResponse, crate::types::api::customers::CustomerRequest, crate::types::api::customers::CustomerDeleteResponse, + crate::types::api::payment_methods::CreatePaymentMethod, + crate::types::api::payment_methods::PaymentMethodResponse, + crate::types::api::payment_methods::ListPaymentMethod, + crate::types::api::payment_methods::CustomerPaymentMethod, + crate::types::api::payment_methods::ListPaymentMethodResponse, + crate::types::api::payment_methods::ListCustomerPaymentMethodsResponse, + crate::types::api::payment_methods::DeletePaymentMethodResponse, + crate::types::api::payment_methods::UpdatePaymentMethod, + crate::types::api::payment_methods::CardDetailFromLocker, + crate::types::api::payment_methods::CardDetail, api_models::customers::CustomerResponse, api_models::enums::RoutingAlgorithm, api_models::enums::PaymentMethodType, @@ -72,6 +128,8 @@ Never share your secret api keys. Keep them guarded and secure. api_models::enums::Connector, api_models::enums::PaymentMethodType, api_models::enums::SupportedWallets, + api_models::enums::PaymentMethodIssuerCode, + api_models::enums::MandateStatus, api_models::admin::PaymentConnectorCreate, api_models::admin::PaymentMethods, api_models::payments::AddressDetails, @@ -92,7 +150,7 @@ Never share your secret api keys. Keep them guarded and secure. api_models::payments::AcceptanceType, api_models::payments::MandateAmountData, api_models::payments::OnlineMandate, - api_models::payments::CCard, + api_models::payments::Card, api_models::payments::CustomerAcceptance, api_models::payments::PaymentsRequest, api_models::payments::PaymentsResponse, @@ -115,6 +173,10 @@ Never share your secret api keys. Keep them guarded and secure. api_models::payments::PaymentListConstraints, api_models::payments::PaymentListResponse, api_models::refunds::RefundListRequest, + api_models::refunds::RefundListResponse, + api_models::mandates::MandateRevokedResponse, + api_models::mandates::MandateResponse, + api_models::mandates::MandateCardDetails, crate::types::api::admin::MerchantAccountResponse, crate::types::api::admin::MerchantConnectorId, crate::types::api::admin::MerchantDetails, diff --git a/crates/router/src/routes/admin.rs b/crates/router/src/routes/admin.rs index e406fc28f6..e40d74c6c0 100644 --- a/crates/router/src/routes/admin.rs +++ b/crates/router/src/routes/admin.rs @@ -8,17 +8,20 @@ use crate::{ types::api::admin, }; -/// Merchant Account - Create +// ### Merchant Account - Create + /// /// Create a new account for a merchant and the merchant could be a seller or retailer or client who likes to receive and send payments. #[utoipa::path( post, - path = "/account", + path = "/accounts", request_body= CreateMerchantAccount, responses( (status = 200, description = "Merchant Account Created", body = MerchantAccountResponse), (status = 400, description = "Invalid data") - ) + ), + tag = "Merchant Account", + operation_id = "Create a Merchant Account" )] #[instrument(skip_all, fields(flow = ?Flow::MerchantsAccountCreate))] pub async fn merchant_account_create( @@ -36,16 +39,20 @@ pub async fn merchant_account_create( .await } -/// Merchant Account - Retrieve +// Merchant Account - Retrieve + +/// /// Retrieve a merchant account details. #[utoipa::path( get, - path = "/account/{account_id}", + path = "/accounts/{account_id}", params (("account_id" = String, Path, description = "The unique identifier for the merchant account")), responses( (status = 200, description = "Merchant Account Retrieved", body = MerchantAccountResponse), (status = 404, description = "Merchant account not found") - ) + ), + tag = "Merchant Account", + operation_id = "Retrieve a Merchant Account" )] #[instrument(skip_all, fields(flow = ?Flow::MerchantsAccountRetrieve))] pub async fn retrieve_merchant_account( @@ -67,17 +74,21 @@ pub async fn retrieve_merchant_account( .await } -/// Merchant Account - Update -/// Update a merchant account details. +// Merchant Account - Update + +/// +/// To update an existing merchant account. Helpful in updating merchant details such as email, contact details, or other configuration details like webhook, routing algorithm etc #[utoipa::path( post, - path = "/account/{account_id}", + path = "/accounts/{account_id}", request_body = CreateMerchantAccount, params (("account_id" = String, Path, description = "The unique identifier for the merchant account")), responses( (status = 200, description = "Merchant Account Updated", body = MerchantAccountResponse), (status = 404, description = "Merchant account not found") - ) + ), + tag = "Merchant Account", + operation_id = "Update a Merchant Account" )] #[instrument(skip_all, fields(flow = ?Flow::MerchantsAccountUpdate))] pub async fn update_merchant_account( @@ -97,16 +108,20 @@ pub async fn update_merchant_account( .await } -/// Merchant Account - Delete -/// Delete a merchant account details. +// Merchant Account - Delete + +/// +/// To delete a merchant account #[utoipa::path( delete, - path = "/account/{account_id}", + path = "/accounts/{account_id}", params (("account_id" = String, Path, description = "The unique identifier for the merchant account")), responses( - (status = 200, description = "Merchant Account Deleted", body = DeleteResponse), + (status = 200, description = "Merchant Account Deleted", body = DeleteMerchantAccountResponse), (status = 404, description = "Merchant account not found") - ) + ), + tag = "Merchant Account", + operation_id = "Delete a Merchant Account" )] #[instrument(skip_all, fields(flow = ?Flow::MerchantsAccountDelete))] // #[delete("/{id}")] @@ -129,17 +144,20 @@ pub async fn delete_merchant_account( .await } -/// PaymentsConnectors - Create +// PaymentsConnectors - Create + /// /// Create a new Payment Connector for the merchant account. The connector could be a payment processor / facilitator / acquirer or specialized services like Fraud / Accounting etc." #[utoipa::path( post, - path = "/account/{account_id}/connectors", + path = "/accounts/{account_id}/connectors", request_body = PaymentConnectorCreate, responses( (status = 200, description = "Payment Connector Created", body = PaymentConnectorCreate), - (status = 400, description = "Missing Mandatory fields") - ) + (status = 400, description = "Missing Mandatory fields"), + ), + tag = "Merchant Connector Account", + operation_id = "Create a Merchant Connector" )] #[instrument(skip_all, fields(flow = ?Flow::PaymentConnectorsCreate))] pub async fn payment_connector_create( @@ -159,12 +177,13 @@ pub async fn payment_connector_create( .await } -/// Payment Connector - Retrieve +// Payment Connector - Retrieve + /// /// Retrieve Payment Connector Details #[utoipa::path( get, - path = "/account/{account_id}/connectors/{connector_id}", + path = "/accounts/{account_id}/connectors/{connector_id}", params( ("account_id" = String, Path, description = "The unique identifier for the merchant account"), ("connector_id" = i32, Path, description = "The unique identifier for the payment connector") @@ -173,7 +192,9 @@ pub async fn payment_connector_create( (status = 200, description = "Payment Connector retrieved successfully", body = PaymentConnectorCreate), (status = 404, description = "Payment Connector does not exist in records"), (status = 401, description = "Unauthorized request") - ) + ), + tag = "Merchant Connector Account", + operation_id = "Retrieve a Merchant Connector" )] #[instrument(skip_all, fields(flow = ?Flow::PaymentConnectorsRetrieve))] pub async fn payment_connector_retrieve( @@ -199,12 +220,13 @@ pub async fn payment_connector_retrieve( .await } -/// Payment Connector - List +// Payment Connector - List + /// /// List Payment Connector Details for the merchant #[utoipa::path( get, - path = "/account/{account_id}/connectors", + path = "/accounts/{account_id}/connectors", params( ("account_id" = String, Path, description = "The unique identifier for the merchant account"), ), @@ -212,7 +234,9 @@ pub async fn payment_connector_retrieve( (status = 200, description = "Payment Connector list retrieved successfully", body = Vec), (status = 404, description = "Payment Connector does not exist in records"), (status = 401, description = "Unauthorized request") - ) + ), + tag = "Merchant Connector Account", + operation_id = "List all Merchant Connectors" )] #[instrument(skip_all, fields(flow = ?Flow::PaymentConnectorsList))] pub async fn payment_connector_list( @@ -231,12 +255,13 @@ pub async fn payment_connector_list( .await } -/// Payment Connector - Update +// Payment Connector - Update + /// -/// To update an existing Payment Connector. Helpful in enabling / disabling different payment methods and other settings for the connector etc +/// To update an existing Payment Connector. Helpful in enabling / disabling different payment methods and other settings for the connector etc. #[utoipa::path( post, - path = "/account/{account_id}/connectors/{connector_id}", + path = "/accounts/{account_id}/connectors/{connector_id}", request_body = PaymentConnectorCreate, params( ("account_id" = String, Path, description = "The unique identifier for the merchant account"), @@ -246,7 +271,9 @@ pub async fn payment_connector_list( (status = 200, description = "Payment Connector Updated", body = PaymentConnectorCreate), (status = 404, description = "Payment Connector does not exist in records"), (status = 401, description = "Unauthorized request") - ) + ), + tag = "Merchant Connector Account", + operation_id = "Update a Merchant Connector" )] #[instrument(skip_all, fields(flow = ?Flow::PaymentConnectorsUpdate))] pub async fn payment_connector_update( @@ -268,11 +295,13 @@ pub async fn payment_connector_update( .await } -/// Payment Connector - Delete +// Payment Connector - Delete + +/// /// Delete or Detach a Payment Connector from Merchant Account #[utoipa::path( delete, - path = "/account/{account_id}/connectors/{connector_id}", + path = "/accounts/{account_id}/connectors/{connector_id}", params( ("account_id" = String, Path, description = "The unique identifier for the merchant account"), ("connector_id" = i32, Path, description = "The unique identifier for the payment connector") @@ -281,7 +310,9 @@ pub async fn payment_connector_update( (status = 200, description = "Payment Connector Deleted", body = DeleteMcaResponse), (status = 404, description = "Payment Connector does not exist in records"), (status = 401, description = "Unauthorized request") - ) + ), + tag = "Merchant Connector Account", + operation_id = "Delete a Merchant Connector" )] #[instrument(skip_all, fields(flow = ?Flow::PaymentConnectorsDelete))] pub async fn payment_connector_delete( diff --git a/crates/router/src/routes/app.rs b/crates/router/src/routes/app.rs index 1139259b93..575691292d 100644 --- a/crates/router/src/routes/app.rs +++ b/crates/router/src/routes/app.rs @@ -92,7 +92,7 @@ impl Payments { ) .service( web::resource("/{payment_id}/{merchant_id}/response/{connector}") - .route(web::get().to(payments_response)), + .route(web::get().to(payments_redirect_response)), ); } route diff --git a/crates/router/src/routes/customers.rs b/crates/router/src/routes/customers.rs index 64e73e9697..8a355f3aab 100644 --- a/crates/router/src/routes/customers.rs +++ b/crates/router/src/routes/customers.rs @@ -8,7 +8,8 @@ use crate::{ types::api::customers, }; -/// Create Customer +// Create Customer + /// /// Create a customer object and store the customer details to be reused for future payments. Incase the customer already exists in the system, this API will respond with the customer details. #[utoipa::path( @@ -18,7 +19,9 @@ use crate::{ responses( (status = 200, description = "Customer Created", body = CustomerResponse), (status = 400, description = "Invalid data") - ) + ), + tag = "Customers", + operation_id = "Create a Customer" )] #[instrument(skip_all, fields(flow = ?Flow::CustomersCreate))] pub async fn customers_create( @@ -36,7 +39,8 @@ pub async fn customers_create( .await } -/// Retrieve Customer +// Retrieve Customer + /// /// Retrieve a customer's details. #[utoipa::path( @@ -46,7 +50,9 @@ pub async fn customers_create( responses( (status = 200, description = "Customer Retrieved", body = CustomerResponse), (status = 404, description = "Customer was not found") - ) + ), + tag = "Customers", + operation_id = "Retrieve a Customer" )] #[instrument(skip_all, fields(flow = ?Flow::CustomersRetrieve))] pub async fn customers_retrieve( @@ -75,7 +81,8 @@ pub async fn customers_retrieve( .await } -/// Update Customer +// Update Customer + /// /// Updates the customer's details in a customer object. #[utoipa::path( @@ -86,7 +93,9 @@ pub async fn customers_retrieve( responses( (status = 200, description = "Customer was Updated", body = CustomerResponse), (status = 404, description = "Customer was not found") - ) + ), + tag = "Customers", + operation_id = "Update a Customer" )] #[instrument(skip_all, fields(flow = ?Flow::CustomersUpdate))] pub async fn customers_update( @@ -107,7 +116,8 @@ pub async fn customers_update( .await } -/// Delete Customer +// Delete Customer + /// /// Delete a customer record. #[utoipa::path( @@ -117,7 +127,9 @@ pub async fn customers_update( responses( (status = 200, description = "Customer was Deleted", body = CustomerDeleteResponse), (status = 404, description = "Customer was not found") - ) + ), + tag = "Customers", + operation_id = "Delete a Customer" )] #[instrument(skip_all, fields(flow = ?Flow::CustomersDelete))] pub async fn customers_delete( diff --git a/crates/router/src/routes/mandates.rs b/crates/router/src/routes/mandates.rs index 8ae978a0db..4fa32170c1 100644 --- a/crates/router/src/routes/mandates.rs +++ b/crates/router/src/routes/mandates.rs @@ -8,6 +8,23 @@ use crate::{ types::api::mandates, }; +// Mandates - Retrieve Mandate + +/// +/// Retrieve a mandate +#[utoipa::path( + get, + path = "/mandates/{mandate_id}", + params( + ("mandate_id" = String, Path, description = "The identifier for mandate") + ), + responses( + (status = 200, description = "The mandate was retrieved successfully", body = MandateResponse), + (status = 404, description = "Mandate does not exist in our records") + ), + tag = "Mandates", + operation_id = "Retrieve a Mandate" +)] #[instrument(skip_all, fields(flow = ?Flow::MandatesRetrieve))] // #[get("/{id}")] pub async fn get_mandate( @@ -28,6 +45,23 @@ pub async fn get_mandate( .await } +// Mandates - Revoke Mandate + +/// +/// Revoke a mandate +#[utoipa::path( + post, + path = "/mandates/revoke/{mandate_id}", + params( + ("mandate_id" = String, Path, description = "The identifier for mandate") + ), + responses( + (status = 200, description = "The mandate was revoked successfully", body = MandateRevokedResponse), + (status = 400, description = "Mandate does not exist in our records") + ), + tag = "Mandates", + operation_id = "Revoke a Mandate" +)] #[instrument(skip_all, fields(flow = ?Flow::MandatesRevoke))] // #[post("/revoke/{id}")] pub async fn revoke_mandate( diff --git a/crates/router/src/routes/payment_methods.rs b/crates/router/src/routes/payment_methods.rs index d21d584c1e..7ddc2d4b19 100644 --- a/crates/router/src/routes/payment_methods.rs +++ b/crates/router/src/routes/payment_methods.rs @@ -8,8 +8,22 @@ use crate::{ types::api::payment_methods::{self, PaymentMethodId}, }; +// PaymentMethods - Create + +/// +/// To create a payment method against a customer object. In case of cards, this API could be used only by PCI compliant merchants +#[utoipa::path( + post, + path = "/payment_methods", + request_body = CreatePaymentMethod, + responses( + (status = 200, description = "Payment Method Created", body = PaymentMethodResponse), + (status = 400, description = "Invalid Data") + ), + tag = "Payment Methods", + operation_id = "Create a Payment Method" +)] #[instrument(skip_all, fields(flow = ?Flow::PaymentMethodsCreate))] -// #[post("")] pub async fn create_payment_method_api( state: web::Data, req: HttpRequest, @@ -27,8 +41,31 @@ pub async fn create_payment_method_api( .await } +// List payment methods for a Merchant + +/// +/// To filter and list the applicable payment methods for a particular Merchant ID +#[utoipa::path( + get, + path = "/payment_methods/{account_id}", + params ( + ("account_id" = String, Path, description = "The unique identifier for the merchant account"), + ("accepted_country" = Vec, Query, description = "The two-letter ISO currency code"), + ("accepted_currency" = Vec, Path, description = "The three-letter ISO currency code"), + ("minimum_amount" = i64, Query, description = "The minimum amount accepted for processing by the particular payment method."), + ("maximum_amount" = i64, Query, description = "The maximum amount amount accepted for processing by the particular payment method."), + ("recurring_payment_enabled" = bool, Query, description = "Indicates whether the payment method is eligible for recurring payments"), + ("installment_payment_enabled" = bool, Query, description = "Indicates whether the payment method is eligible for installment payments"), + ), + responses( + (status = 200, description = "Payment Methods retrieved", body = ListPaymentMethodResponse), + (status = 400, description = "Invalid Data"), + (status = 404, description = "Payment Methods does not exist in records") + ), + tag = "Payment Methods", + operation_id = "List all Payment Methods for a Merchant" +)] #[instrument(skip_all, fields(flow = ?Flow::PaymentMethodsList))] -//#[get("{merchant_id}")] pub async fn list_payment_method_api( state: web::Data, req: HttpRequest, @@ -53,8 +90,31 @@ pub async fn list_payment_method_api( .await } +// List payment methods for a Customer + +/// +/// To filter and list the applicable payment methods for a particular Customer ID +#[utoipa::path( + get, + path = "/payment_methods/{customer_id}", + params ( + ("customer_id" = String, Path, description = "The unique identifier for the customer account"), + ("accepted_country" = Vec, Query, description = "The two-letter ISO currency code"), + ("accepted_currency" = Vec, Path, description = "The three-letter ISO currency code"), + ("minimum_amount" = i64, Query, description = "The minimum amount accepted for processing by the particular payment method."), + ("maximum_amount" = i64, Query, description = "The maximum amount amount accepted for processing by the particular payment method."), + ("recurring_payment_enabled" = bool, Query, description = "Indicates whether the payment method is eligible for recurring payments"), + ("installment_payment_enabled" = bool, Query, description = "Indicates whether the payment method is eligible for installment payments"), + ), + responses( + (status = 200, description = "Payment Methods retrieved", body = ListCustomerPaymentMethodsResponse), + (status = 400, description = "Invalid Data"), + (status = 404, description = "Payment Methods does not exist in records") + ), + tag = "Payment Methods", + operation_id = "List all Payment Methods for a Customer" +)] #[instrument(skip_all, fields(flow = ?Flow::CustomerPaymentMethodsList))] -// #[get("/{customer_id}/payment_methods")] pub async fn list_customer_payment_method_api( state: web::Data, customer_id: web::Path<(String,)>, @@ -81,8 +141,24 @@ pub async fn list_customer_payment_method_api( .await } +// Payment Method - Retrieve + +/// +/// To retrieve a payment method +#[utoipa::path( + get, + path = "/payment_methods/{method_id}", + params ( + ("method_id" = String, Path, description = "The unique identifier for the Payment Method"), + ), + responses( + (status = 200, description = "Payment Method retrieved", body = PaymentMethodResponse), + (status = 404, description = "Payment Method does not exist in records") + ), + tag = "Payment Methods", + operation_id = "Retrieve a Payment method" +)] #[instrument(skip_all, fields(flow = ?Flow::PaymentMethodsRetrieve))] -// #[get("/{payment_method_id}")] pub async fn payment_method_retrieve_api( state: web::Data, req: HttpRequest, @@ -103,6 +179,24 @@ pub async fn payment_method_retrieve_api( .await } +// Payment Method - Update + +/// +/// To update an existing payment method attached to a customer object. This API is useful for use cases such as updating the card number for expired cards to prevent discontinuity in recurring payments +#[utoipa::path( + post, + path = "/payment_methods/{method_id}", + params ( + ("method_id" = String, Path, description = "The unique identifier for the Payment Method"), + ), + request_body = UpdatePaymentMethod, + responses( + (status = 200, description = "Payment Method updated", body = PaymentMethodResponse), + (status = 404, description = "Payment Method does not exist in records") + ), + tag = "Payment Methods", + operation_id = "Update a Payment method" +)] #[instrument(skip_all, fields(flow = ?Flow::PaymentMethodsUpdate))] pub async fn payment_method_update_api( state: web::Data, @@ -129,8 +223,24 @@ pub async fn payment_method_update_api( .await } +// Payment Method - Delete + +/// +/// Delete payment method +#[utoipa::path( + delete, + path = "/payment_methods/{method_id}", + params ( + ("method_id" = String, Path, description = "The unique identifier for the Payment Method"), + ), + responses( + (status = 200, description = "Payment Method deleted", body = DeletePaymentMethodResponse), + (status = 404, description = "Payment Method does not exist in records") + ), + tag = "Payment Methods", + operation_id = "Delete a Payment method" +)] #[instrument(skip_all, fields(flow = ?Flow::PaymentMethodsDelete))] -// #[post("/{payment_method_id}/detach")] pub async fn payment_method_delete_api( state: web::Data, req: HttpRequest, diff --git a/crates/router/src/routes/payments.rs b/crates/router/src/routes/payments.rs index d84e4704c6..a3c557d054 100644 --- a/crates/router/src/routes/payments.rs +++ b/crates/router/src/routes/payments.rs @@ -9,9 +9,10 @@ use crate::{ types::api::{self as api_types, enums as api_enums, payments as payment_types}, }; -/// Payments - Create +// Payments - Create + /// -/// To create a new payment, against a merchant API key +/// To process a payment you will have to create a payment, attach a payment method and confirm. Depending on the user journey you wish to achieve, you may opt to all the steps in a single request or in a sequence of API request using following APIs: (i) Payments - Update, (ii) Payments - Confirm, and (iii) Payments - Capture #[utoipa::path( post, path = "/payments", @@ -19,7 +20,9 @@ use crate::{ responses( (status = 200, description = "Payment created", body = PaymentsResponse), (status = 400, description = "Missing Mandatory fields") - ) + ), + tag = "Payments", + operation_id = "Create a Payment" )] #[instrument(skip_all, fields(flow = ?Flow::PaymentsCreate))] // #[post("")] @@ -52,6 +55,24 @@ pub async fn payments_create( .await } +// /// Payments - Start +// /// +// /// The entry point for a payment which involves the redirection flow. This redirects the user to the authentication page +// #[utoipa::path( +// get, +// path = "/payments/start/{payment_id}/{merchant_id}/{attempt_id}", +// params( +// ("payment_id" = String, Path, description = "The identifier for payment"), +// ("merchant_id" = String, Path, description = "The identifier for merchant"), +// ("attempt_id" = String, Path, description = "The identifier for transaction") +// ), +// responses( +// (status = 200, description = "Redirects to the authentication page"), +// (status = 404, description = "No redirection found") +// ), +// tag = "Payments", +// operation_id = "Start a Redirection Payment" +// )] #[instrument(skip(state), fields(flow = ?Flow::PaymentsStart))] pub async fn payments_start( state: web::Data, @@ -83,6 +104,24 @@ pub async fn payments_start( .await } +// Payments - Retrieve + +/// +/// To retrieve the properties of a Payment. This may be used to get the status of a previously initiated payment or next action for an ongoing payment +#[utoipa::path( + get, + path = "/payments/{payment_id}", + params( + ("payment_id" = String, Path, description = "The identifier for payment") + ), + request_body=PaymentRetrieveBody, + responses( + (status = 200, description = "Gets the payment with final status", body = PaymentsResponse), + (status = 404, description = "No payment found") + ), + tag = "Payments", + operation_id = "Retrieve a Payment" +)] #[instrument(skip(state), fields(flow = ?Flow::PaymentsRetrieve))] // #[get("/{payment_id}")] pub async fn payments_retrieve( @@ -122,6 +161,24 @@ pub async fn payments_retrieve( .await } +// Payments - Update + +/// +/// To update the properties of a PaymentIntent object. This may include attaching a payment method, or attaching customer object or metadata fields after the Payment is created +#[utoipa::path( + post, + path = "/payments/{payment_id}", + params( + ("payment_id" = String, Path, description = "The identifier for payment") + ), + request_body=PaymentsRequest, + responses( + (status = 200, description = "Payment updated", body = PaymentsResponse), + (status = 400, description = "Missing mandatory fields") + ), + tag = "Payments", + operation_id = "Update a Payment" +)] #[instrument(skip_all, fields(flow = ?Flow::PaymentsUpdate))] // #[post("/{payment_id}")] pub async fn payments_update( @@ -163,6 +220,24 @@ pub async fn payments_update( .await } +// Payments - Confirm + +/// +/// This API is to confirm the payment request and forward payment to the payment processor. This API provides more granular control upon when the API is forwarded to the payment processor. Alternatively you can confirm the payment within the Payments Create API +#[utoipa::path( + post, + path = "/payments/{payment_id}/confirm", + params( + ("payment_id" = String, Path, description = "The identifier for payment") + ), + request_body=PaymentsRequest, + responses( + (status = 200, description = "Payment confirmed", body = PaymentsResponse), + (status = 400, description = "Missing mandatory fields") + ), + tag = "Payments", + operation_id = "Confirm a Payment" +)] #[instrument(skip_all, fields(flow = ?Flow::PaymentsConfirm))] // #[post("/{payment_id}/confirm")] pub async fn payments_confirm( @@ -205,6 +280,24 @@ pub async fn payments_confirm( .await } +// Payments - Capture + +/// +/// To capture the funds for an uncaptured payment +#[utoipa::path( + post, + path = "/payments/{payment_id}/capture", + params( + ("payment_id" = String, Path, description = "The identifier for payment") + ), + request_body=PaymentsCaptureRequest, + responses( + (status = 200, description = "Payment captured", body = PaymentsResponse), + (status = 400, description = "Missing mandatory fields") + ), + tag = "Payments", + operation_id = "Capture a Payment" +)] #[instrument(skip_all, fields(flow = ?Flow::PaymentsCapture))] // #[post("/{payment_id}/capture")] pub async fn payments_capture( @@ -237,6 +330,21 @@ pub async fn payments_capture( .await } +// Payments - Session token + +/// +/// To create the session object or to get session token for wallets +#[utoipa::path( + post, + path = "/payments/session_tokens", + request_body=PaymentsSessionRequest, + responses( + (status = 200, description = "Payment session object created or session token was retrieved from wallets", body = PaymentsSessionResponse), + (status = 400, description = "Missing mandatory fields") + ), + tag = "Payments", + operation_id = "Create Session tokens for a Payment" +)] #[instrument(skip_all, fields(flow = ?Flow::PaymentsSessionToken))] pub async fn payments_connector_session( state: web::Data, @@ -270,8 +378,26 @@ pub async fn payments_connector_session( .await } +// /// Payments - Redirect response +// /// +// /// To get the payment response for redirect flows +// #[utoipa::path( +// post, +// path = "/payments/{payment_id}/{merchant_id}/response/{connector}", +// params( +// ("payment_id" = String, Path, description = "The identifier for payment"), +// ("merchant_id" = String, Path, description = "The identifier for merchant"), +// ("connector" = String, Path, description = "The name of the connector") +// ), +// responses( +// (status = 302, description = "Received payment redirect response"), +// (status = 400, description = "Missing mandatory fields") +// ), +// tag = "Payments", +// operation_id = "Get Redirect Response for a Payment" +// )] #[instrument(skip_all)] -pub async fn payments_response( +pub async fn payments_redirect_response( state: web::Data, req: actix_web::HttpRequest, path: web::Path<(String, String, String)>, @@ -302,6 +428,24 @@ pub async fn payments_response( .await } +// Payments - Cancel + +/// +/// A Payment could can be cancelled when it is in one of these statuses: requires_payment_method, requires_capture, requires_confirmation, requires_customer_action +#[utoipa::path( + post, + path = "/payments/{payment_id}/cancel", + request_body=PaymentsCancelRequest, + params( + ("payment_id" = String, Path, description = "The identifier for payment") + ), + responses( + (status = 200, description = "Payment canceled"), + (status = 400, description = "Missing mandatory fields") + ), + tag = "Payments", + operation_id = "Cancel a Payment" +)] #[instrument(skip_all, fields(flow = ?Flow::PaymentsCancel))] // #[post("/{payment_id}/cancel")] pub async fn payments_cancel( @@ -333,6 +477,31 @@ pub async fn payments_cancel( .await } +// Payments - List + +/// +/// To list the payments +#[utoipa::path( + get, + path = "/payments/list", + params( + ("customer_id" = String, Query, description = "The identifier for the customer"), + ("starting_after" = String, Query, description = "A cursor for use in pagination, fetch the next list after some object"), + ("ending_before" = String, Query, description = "A cursor for use in pagination, fetch the previous list before some object"), + ("limit" = i64, Query, description = "Limit on the number of objects to return"), + ("created" = PrimitiveDateTime, Query, description = "The time at which payment is created"), + ("created_lt" = PrimitiveDateTime, Query, description = "Time less than the payment created time"), + ("created_gt" = PrimitiveDateTime, Query, description = "Time greater than the payment created time"), + ("created_lte" = PrimitiveDateTime, Query, description = "Time less than or equals to the payment created time"), + ("created_gte" = PrimitiveDateTime, Query, description = "Time greater than or equals to the payment created time") + ), + responses( + (status = 200, description = "Received payment list"), + (status = 404, description = "No payments found") + ), + tag = "Payments", + operation_id = "List all Payments" +)] #[instrument(skip_all, fields(flow = ?Flow::PaymentsList))] #[cfg(feature = "olap")] // #[get("/list")] diff --git a/crates/router/src/routes/refunds.rs b/crates/router/src/routes/refunds.rs index 04d6abe22b..f362555611 100644 --- a/crates/router/src/routes/refunds.rs +++ b/crates/router/src/routes/refunds.rs @@ -8,7 +8,8 @@ use crate::{ types::api::refunds, }; -/// Refunds - Create +// Refunds - Create + /// /// To create a refund against an already processed payment #[utoipa::path( @@ -18,7 +19,9 @@ use crate::{ responses( (status = 200, description = "Refund created", body = RefundResponse), (status = 400, description = "Missing Mandatory fields") - ) + ), + tag = "Refunds", + operation_id = "Create a Refund" )] #[instrument(skip_all, fields(flow = ?Flow::RefundsCreate))] // #[post("")] @@ -37,9 +40,10 @@ pub async fn refunds_create( .await } -/// Refunds - Retrieve +// Refunds - Retrieve + /// -/// To retrieve a refund against an already processed payment +/// To retrieve the properties of a Refund. This may be used to get the status of a previously initiated payment or next action for an ongoing payment #[utoipa::path( get, path = "/refunds/{refund_id}", @@ -49,7 +53,9 @@ pub async fn refunds_create( responses( (status = 200, description = "Refund retrieved", body = RefundResponse), (status = 404, description = "Refund does not exist in our records") - ) + ), + tag = "Refunds", + operation_id = "Retrieve a Refund" )] #[instrument(skip_all, fields(flow = ?Flow::RefundsRetrieve))] // #[get("/{id}")] @@ -72,9 +78,10 @@ pub async fn refunds_retrieve( .await } -/// Refunds - Update +// Refunds - Update + /// -/// To update a refund against an already processed payment +/// To update the properties of a Refund object. This may include attaching a reason for the refund or metadata fields #[utoipa::path( post, path = "/refunds/{refund_id}", @@ -85,7 +92,9 @@ pub async fn refunds_retrieve( responses( (status = 200, description = "Refund updated", body = RefundResponse), (status = 400, description = "Missing Mandatory fields") - ) + ), + tag = "Refunds", + operation_id = "Update a Refund" )] #[instrument(skip_all, fields(flow = ?Flow::RefundsUpdate))] // #[post("/{id}")] @@ -108,7 +117,8 @@ pub async fn refunds_update( .await } -/// Refunds - List +// Refunds - List + /// /// To list the refunds associated with a payment_id or with the merchant, if payment_id is not provided #[utoipa::path( @@ -126,7 +136,9 @@ pub async fn refunds_update( responses( (status = 200, description = "List of refunds", body = RefundListResponse), (status = 404, description = "Refund does not exist in our records") - ) + ), + tag = "Refunds", + operation_id = "List all Refunds" )] #[instrument(skip_all, fields(flow = ?Flow::RefundsList))] #[cfg(feature = "olap")] diff --git a/crates/router/src/types/api/admin.rs b/crates/router/src/types/api/admin.rs index ee33c8d317..b9fd8de43b 100644 --- a/crates/router/src/types/api/admin.rs +++ b/crates/router/src/types/api/admin.rs @@ -1,7 +1,7 @@ pub use api_models::admin::{ - CreateMerchantAccount, DeleteMcaResponse, DeleteResponse, MerchantAccountResponse, - MerchantConnectorId, MerchantDetails, MerchantId, PaymentConnectorCreate, PaymentMethods, - RoutingAlgorithm, WebhookDetails, + CreateMerchantAccount, DeleteMcaResponse, DeleteMerchantAccountResponse, + MerchantAccountResponse, MerchantConnectorId, MerchantDetails, MerchantId, + PaymentConnectorCreate, PaymentMethods, RoutingAlgorithm, WebhookDetails, }; use crate::types::{storage, transformers::Foreign}; diff --git a/crates/router/src/types/api/payments.rs b/crates/router/src/types/api/payments.rs index 661746e819..7e808c2e52 100644 --- a/crates/router/src/types/api/payments.rs +++ b/crates/router/src/types/api/payments.rs @@ -1,5 +1,5 @@ pub use api_models::payments::{ - AcceptanceType, Address, AddressDetails, Amount, AuthenticationForStartResponse, CCard, + AcceptanceType, Address, AddressDetails, Amount, AuthenticationForStartResponse, Card, CustomerAcceptance, MandateData, MandateTxnType, MandateType, MandateValidationFields, NextAction, NextActionType, OnlineMandate, PayLaterData, PaymentIdType, PaymentListConstraints, PaymentListResponse, PaymentMethod, PaymentMethodDataResponse, PaymentOp, PaymentRetrieveBody, @@ -182,8 +182,8 @@ mod payments_test { use super::*; #[allow(dead_code)] - fn card() -> CCard { - CCard { + fn card() -> Card { + Card { card_number: "1234432112344321".to_string().into(), card_exp_month: "12".to_string().into(), card_exp_year: "99".to_string().into(), diff --git a/crates/router/tests/connectors/aci.rs b/crates/router/tests/connectors/aci.rs index c7e2a6f11b..115d4af308 100644 --- a/crates/router/tests/connectors/aci.rs +++ b/crates/router/tests/connectors/aci.rs @@ -33,7 +33,7 @@ fn construct_payment_router_data() -> types::PaymentsAuthorizeRouterData { request: types::PaymentsAuthorizeData { amount: 1000, currency: enums::Currency::USD, - payment_method_data: types::api::PaymentMethod::Card(types::api::CCard { + payment_method_data: types::api::PaymentMethod::Card(types::api::Card { card_number: Secret::new("4200000000000000".to_string()), card_exp_month: Secret::new("10".to_string()), card_exp_year: Secret::new("2025".to_string()), @@ -150,7 +150,7 @@ async fn payments_create_failure() { types::PaymentsResponseData, > = connector.connector.get_connector_integration(); let mut request = construct_payment_router_data(); - request.request.payment_method_data = types::api::PaymentMethod::Card(types::api::CCard { + request.request.payment_method_data = types::api::PaymentMethod::Card(types::api::Card { card_number: Secret::new("420000000000000000".to_string()), card_exp_month: Secret::new("10".to_string()), card_exp_year: Secret::new("2025".to_string()), diff --git a/crates/router/tests/connectors/authorizedotnet.rs b/crates/router/tests/connectors/authorizedotnet.rs index e551047330..5068e1d46c 100644 --- a/crates/router/tests/connectors/authorizedotnet.rs +++ b/crates/router/tests/connectors/authorizedotnet.rs @@ -33,7 +33,7 @@ fn construct_payment_router_data() -> types::PaymentsAuthorizeRouterData { request: types::PaymentsAuthorizeData { amount: 100, currency: enums::Currency::USD, - payment_method_data: types::api::PaymentMethod::Card(types::api::CCard { + payment_method_data: types::api::PaymentMethod::Card(types::api::Card { card_number: Secret::new("5424000000000015".to_string()), card_exp_month: Secret::new("10".to_string()), card_exp_year: Secret::new("2025".to_string()), @@ -153,7 +153,7 @@ async fn payments_create_failure() { > = connector.connector.get_connector_integration(); let mut request = construct_payment_router_data(); - request.request.payment_method_data = types::api::PaymentMethod::Card(types::api::CCard { + request.request.payment_method_data = types::api::PaymentMethod::Card(types::api::Card { card_number: Secret::new("542400000000001".to_string()), card_exp_month: Secret::new("10".to_string()), card_exp_year: Secret::new("2025".to_string()), diff --git a/crates/router/tests/connectors/checkout.rs b/crates/router/tests/connectors/checkout.rs index e8e254fe4d..a75caff6c1 100644 --- a/crates/router/tests/connectors/checkout.rs +++ b/crates/router/tests/connectors/checkout.rs @@ -30,7 +30,7 @@ fn construct_payment_router_data() -> types::PaymentsAuthorizeRouterData { request: types::PaymentsAuthorizeData { amount: 100, currency: enums::Currency::USD, - payment_method_data: types::api::PaymentMethod::Card(api::CCard { + payment_method_data: types::api::PaymentMethod::Card(api::Card { card_number: "4242424242424242".to_string().into(), card_exp_month: "10".to_string().into(), card_exp_year: "35".to_string().into(), diff --git a/crates/router/tests/connectors/cybersource.rs b/crates/router/tests/connectors/cybersource.rs index 779be0afd9..51ba6e3973 100644 --- a/crates/router/tests/connectors/cybersource.rs +++ b/crates/router/tests/connectors/cybersource.rs @@ -214,7 +214,7 @@ async fn should_fail_payment_for_incorrect_card_number() { let response = Cybersource {} .make_payment( Some(types::PaymentsAuthorizeData { - payment_method_data: types::api::PaymentMethod::Card(api::CCard { + payment_method_data: types::api::PaymentMethod::Card(api::Card { card_number: Secret::new("424242442424242".to_string()), ..utils::CCardType::default().0 }), @@ -234,7 +234,7 @@ async fn should_fail_payment_for_incorrect_exp_month() { let response = Cybersource {} .make_payment( Some(types::PaymentsAuthorizeData { - payment_method_data: types::api::PaymentMethod::Card(api::CCard { + payment_method_data: types::api::PaymentMethod::Card(api::Card { card_number: Secret::new("4242424242424242".to_string()), card_exp_month: Secret::new("101".to_string()), ..utils::CCardType::default().0 diff --git a/crates/router/tests/connectors/fiserv.rs b/crates/router/tests/connectors/fiserv.rs index fb7a4ce5b8..25d2539fa6 100644 --- a/crates/router/tests/connectors/fiserv.rs +++ b/crates/router/tests/connectors/fiserv.rs @@ -43,7 +43,7 @@ async fn should_only_authorize_payment() { let response = Fiserv {} .authorize_payment( Some(types::PaymentsAuthorizeData { - payment_method_data: types::api::PaymentMethod::Card(api::CCard { + payment_method_data: types::api::PaymentMethod::Card(api::Card { card_number: Secret::new("4005550000000019".to_string()), card_exp_month: Secret::new("02".to_string()), card_exp_year: Secret::new("2035".to_string()), @@ -65,7 +65,7 @@ async fn should_authorize_and_capture_payment() { let response = Fiserv {} .make_payment( Some(types::PaymentsAuthorizeData { - payment_method_data: types::api::PaymentMethod::Card(api::CCard { + payment_method_data: types::api::PaymentMethod::Card(api::Card { card_number: Secret::new("4005550000000019".to_string()), card_exp_month: Secret::new("02".to_string()), card_exp_year: Secret::new("2035".to_string()), @@ -86,7 +86,7 @@ async fn should_capture_already_authorized_payment() { let authorize_response = connector .authorize_payment( Some(types::PaymentsAuthorizeData { - payment_method_data: types::api::PaymentMethod::Card(api::CCard { + payment_method_data: types::api::PaymentMethod::Card(api::Card { card_number: Secret::new("4005550000000019".to_string()), card_exp_month: Secret::new("02".to_string()), card_exp_year: Secret::new("2035".to_string()), @@ -119,7 +119,7 @@ async fn should_fail_payment_for_missing_cvc() { let response = Fiserv {} .make_payment( Some(types::PaymentsAuthorizeData { - payment_method_data: types::api::PaymentMethod::Card(api::CCard { + payment_method_data: types::api::PaymentMethod::Card(api::Card { card_number: Secret::new("4005550000000019".to_string()), card_exp_month: Secret::new("02".to_string()), card_exp_year: Secret::new("2035".to_string()), diff --git a/crates/router/tests/connectors/globalpay.rs b/crates/router/tests/connectors/globalpay.rs index 31104d9aeb..3f8330b4e1 100644 --- a/crates/router/tests/connectors/globalpay.rs +++ b/crates/router/tests/connectors/globalpay.rs @@ -129,7 +129,7 @@ async fn should_fail_payment_for_incorrect_cvc() { let response = Globalpay {} .make_payment( Some(types::PaymentsAuthorizeData { - payment_method_data: types::api::PaymentMethod::Card(api::CCard { + payment_method_data: types::api::PaymentMethod::Card(api::Card { card_number: Secret::new("4024007134364842".to_string()), ..utils::CCardType::default().0 }), diff --git a/crates/router/tests/connectors/rapyd.rs b/crates/router/tests/connectors/rapyd.rs index a86bf9c57e..c17a0be577 100644 --- a/crates/router/tests/connectors/rapyd.rs +++ b/crates/router/tests/connectors/rapyd.rs @@ -38,7 +38,7 @@ async fn should_only_authorize_payment() { let response = Rapyd {} .authorize_payment( Some(types::PaymentsAuthorizeData { - payment_method_data: types::api::PaymentMethod::Card(api::CCard { + payment_method_data: types::api::PaymentMethod::Card(api::Card { card_number: Secret::new("4111111111111111".to_string()), card_exp_month: Secret::new("02".to_string()), card_exp_year: Secret::new("2024".to_string()), @@ -60,7 +60,7 @@ async fn should_authorize_and_capture_payment() { let response = Rapyd {} .make_payment( Some(types::PaymentsAuthorizeData { - payment_method_data: types::api::PaymentMethod::Card(api::CCard { + payment_method_data: types::api::PaymentMethod::Card(api::Card { card_number: Secret::new("4111111111111111".to_string()), card_exp_month: Secret::new("02".to_string()), card_exp_year: Secret::new("2024".to_string()), @@ -137,7 +137,7 @@ async fn should_fail_payment_for_incorrect_card_number() { let response = Rapyd {} .make_payment( Some(types::PaymentsAuthorizeData { - payment_method_data: types::api::PaymentMethod::Card(api::CCard { + payment_method_data: types::api::PaymentMethod::Card(api::Card { card_number: Secret::new("0000000000000000".to_string()), ..utils::CCardType::default().0 }), diff --git a/crates/router/tests/connectors/shift4.rs b/crates/router/tests/connectors/shift4.rs index 7cbfe29820..35209ebdf6 100644 --- a/crates/router/tests/connectors/shift4.rs +++ b/crates/router/tests/connectors/shift4.rs @@ -67,7 +67,7 @@ async fn should_fail_payment_for_incorrect_cvc() { let response = Shift4 {} .make_payment( Some(types::PaymentsAuthorizeData { - payment_method_data: types::api::PaymentMethod::Card(api::CCard { + payment_method_data: types::api::PaymentMethod::Card(api::Card { card_number: Secret::new("4024007134364842".to_string()), ..utils::CCardType::default().0 }), diff --git a/crates/router/tests/connectors/stripe.rs b/crates/router/tests/connectors/stripe.rs index 612086bc0e..0537ac45c0 100644 --- a/crates/router/tests/connectors/stripe.rs +++ b/crates/router/tests/connectors/stripe.rs @@ -35,7 +35,7 @@ impl utils::Connector for Stripe { fn get_payment_authorize_data() -> Option { Some(types::PaymentsAuthorizeData { - payment_method_data: types::api::PaymentMethod::Card(api::CCard { + payment_method_data: types::api::PaymentMethod::Card(api::Card { card_number: Secret::new("4242424242424242".to_string()), ..utils::CCardType::default().0 }), @@ -132,7 +132,7 @@ async fn should_fail_payment_for_incorrect_card_number() { let response = Stripe {} .make_payment( Some(types::PaymentsAuthorizeData { - payment_method_data: types::api::PaymentMethod::Card(api::CCard { + payment_method_data: types::api::PaymentMethod::Card(api::Card { card_number: Secret::new("4024007134364842".to_string()), ..utils::CCardType::default().0 }), @@ -154,7 +154,7 @@ async fn should_fail_payment_for_no_card_number() { let response = Stripe {} .make_payment( Some(types::PaymentsAuthorizeData { - payment_method_data: types::api::PaymentMethod::Card(api::CCard { + payment_method_data: types::api::PaymentMethod::Card(api::Card { card_number: Secret::new("".to_string()), ..utils::CCardType::default().0 }), @@ -176,7 +176,7 @@ async fn should_fail_payment_for_invalid_exp_month() { let response = Stripe {} .make_payment( Some(types::PaymentsAuthorizeData { - payment_method_data: types::api::PaymentMethod::Card(api::CCard { + payment_method_data: types::api::PaymentMethod::Card(api::Card { card_exp_month: Secret::new("13".to_string()), ..utils::CCardType::default().0 }), @@ -195,7 +195,7 @@ async fn should_fail_payment_for_invalid_exp_year() { let response = Stripe {} .make_payment( Some(types::PaymentsAuthorizeData { - payment_method_data: types::api::PaymentMethod::Card(api::CCard { + payment_method_data: types::api::PaymentMethod::Card(api::Card { card_exp_year: Secret::new("2022".to_string()), ..utils::CCardType::default().0 }), @@ -214,7 +214,7 @@ async fn should_fail_payment_for_invalid_card_cvc() { let response = Stripe {} .make_payment( Some(types::PaymentsAuthorizeData { - payment_method_data: types::api::PaymentMethod::Card(api::CCard { + payment_method_data: types::api::PaymentMethod::Card(api::Card { card_cvc: Secret::new("12".to_string()), ..utils::CCardType::default().0 }), diff --git a/crates/router/tests/connectors/utils.rs b/crates/router/tests/connectors/utils.rs index e1cee6bd41..1ffd970fd9 100644 --- a/crates/router/tests/connectors/utils.rs +++ b/crates/router/tests/connectors/utils.rs @@ -377,12 +377,12 @@ pub struct PaymentCaptureType(pub types::PaymentsCaptureData); pub struct PaymentCancelType(pub types::PaymentsCancelData); pub struct PaymentSyncType(pub types::PaymentsSyncData); pub struct PaymentRefundType(pub types::RefundsData); -pub struct CCardType(pub api::CCard); +pub struct CCardType(pub api::Card); pub struct BrowserInfoType(pub types::BrowserInformation); impl Default for CCardType { fn default() -> Self { - Self(api::CCard { + Self(api::Card { card_number: Secret::new("4200000000000000".to_string()), card_exp_month: Secret::new("10".to_string()), card_exp_year: Secret::new("2025".to_string()), diff --git a/crates/router/tests/connectors/worldline.rs b/crates/router/tests/connectors/worldline.rs index 1509201881..05a7294f37 100644 --- a/crates/router/tests/connectors/worldline.rs +++ b/crates/router/tests/connectors/worldline.rs @@ -64,7 +64,7 @@ impl WorldlineTest { Some(types::PaymentsAuthorizeData { amount: 3500, currency: enums::Currency::USD, - payment_method_data: types::api::PaymentMethod::Card(types::api::CCard { + payment_method_data: types::api::PaymentMethod::Card(types::api::Card { card_number: Secret::new(card_number.to_string()), card_exp_month: Secret::new(card_exp_month.to_string()), card_exp_year: Secret::new(card_exp_year.to_string()), diff --git a/crates/router/tests/payments.rs b/crates/router/tests/payments.rs index 506db90362..b27a100d76 100644 --- a/crates/router/tests/payments.rs +++ b/crates/router/tests/payments.rs @@ -299,7 +299,7 @@ async fn payments_create_core() { return_url: Some("http://example.com/payments".to_string()), setup_future_usage: Some(api_enums::FutureUsage::OnSession), authentication_type: Some(api_enums::AuthenticationType::NoThreeDs), - payment_method_data: Some(api::PaymentMethod::Card(api::CCard { + payment_method_data: Some(api::PaymentMethod::Card(api::Card { card_number: "4242424242424242".to_string().into(), card_exp_month: "10".to_string().into(), card_exp_year: "35".to_string().into(), @@ -452,7 +452,7 @@ async fn payments_create_core_adyen_no_redirect() { return_url: Some("http://example.com/payments".to_string()), setup_future_usage: Some(api_enums::FutureUsage::OnSession), authentication_type: Some(api_enums::AuthenticationType::NoThreeDs), - payment_method_data: Some(api::PaymentMethod::Card(api::CCard { + payment_method_data: Some(api::PaymentMethod::Card(api::Card { card_number: "5555 3412 4444 1115".to_string().into(), card_exp_month: "03".to_string().into(), card_exp_year: "2030".to_string().into(), diff --git a/crates/router/tests/payments2.rs b/crates/router/tests/payments2.rs index fd7b5e27a5..a4e9e498cc 100644 --- a/crates/router/tests/payments2.rs +++ b/crates/router/tests/payments2.rs @@ -59,7 +59,7 @@ async fn payments_create_core() { return_url: Some("http://example.com/payments".to_string()), setup_future_usage: None, authentication_type: Some(api_enums::AuthenticationType::NoThreeDs), - payment_method_data: Some(api::PaymentMethod::Card(api::CCard { + payment_method_data: Some(api::PaymentMethod::Card(api::Card { card_number: "4242424242424242".to_string().into(), card_exp_month: "10".to_string().into(), card_exp_year: "35".to_string().into(), @@ -209,7 +209,7 @@ async fn payments_create_core_adyen_no_redirect() { return_url: Some("http://example.com/payments".to_string()), setup_future_usage: Some(api_enums::FutureUsage::OffSession), authentication_type: Some(api_enums::AuthenticationType::NoThreeDs), - payment_method_data: Some(api::PaymentMethod::Card(api::CCard { + payment_method_data: Some(api::PaymentMethod::Card(api::Card { card_number: "5555 3412 4444 1115".to_string().into(), card_exp_month: "03".to_string().into(), card_exp_year: "2030".to_string().into(), diff --git a/openapi/generated.json b/openapi/generated.json index 5c30411af9..d09ec556f1 100644 --- a/openapi/generated.json +++ b/openapi/generated.json @@ -1,12 +1,12 @@ { "openapi": "3.0.3", "info": { - "title": "Juspay Router - API Documentation", - "description": "\n## Get started\n\nJuspay Router provides a collection of APIs that enable you to process and manage payments.\nOur APIs accept and return JSON in the HTTP body, and return standard HTTP response codes.\n\nYou can consume the APIs directly using your favorite HTTP/REST library.\n\nWe have a testing environment referred to \"sandbox\", which you can setup to test API calls without\naffecting production data.\n\n### Base URLs\n\nUse the following base URLs when making requests to the APIs:\n\n| Environment | Base URL |\n|---------------|------------------------------------------------------|\n| Sandbox | |\n| Production | |\n\n## Authentication\n\nWhen you sign up on our [dashboard](https://app.hyperswitch.io) and create a merchant\naccount, you are given a secret key (also referred as api-key).\nYou may authenticate all API requests with Juspay server by providing the appropriate key in the\nrequest Authorization header.\n\nNever share your secret api keys. Keep them guarded and secure.\n", + "title": "Hyperswitch - API Documentation", + "description": "\n## Get started\n\nHyperswitch provides a collection of APIs that enable you to process and manage payments.\nOur APIs accept and return JSON in the HTTP body, and return standard HTTP response codes.\n\nYou can consume the APIs directly using your favorite HTTP/REST library.\n\nWe have a testing environment referred to \"sandbox\", which you can setup to test API calls without\naffecting production data. Currently, our sandbox environment is live while our production environment is under development and will be available soon. You can sign up on our Dashboard to get API keys to access Hyperswitch API.\n\n### Environment\n\nUse the following base URLs when making requests to the APIs:\n\n| Environment | Base URL |\n|---------------|------------------------------------|\n| Sandbox | |\n| Production | Coming Soon! |\n\n## Authentication\n\nWhen you sign up on our [dashboard](https://app.hyperswitch.io) and create a merchant\naccount, you are given a secret key (also referred as api-key) and a publishable key.\nYou may authenticate all API requests with Hyperswitch server by providing the appropriate key in the\nrequest Authorization header.\n\n| Key | Description |\n|---------------|-----------------------------------------------------------------------------------------------|\n| Sandbox | Private key. Used to authenticate all API requests from your merchant server |\n| Production | Unique identifier for your account. Used to authenticate API requests from your app’s client |\n\nNever share your secret api keys. Keep them guarded and secure.\n", "contact": { - "name": "Juspay Support", - "url": "https://juspay.io", - "email": "support@juspay.in" + "name": "Hyperswitch Support", + "url": "https://hyperswitch.io", + "email": "hyperswitch@juspay.in" }, "license": { "name": "Apache-2.0" @@ -17,19 +17,17 @@ { "url": "https://sandbox.hyperswitch.io", "description": "Sandbox Environment" - }, - { - "url": "https://router.juspay.io", - "description": "Production Environment" } ], "paths": { - "/account": { + "/accounts": { "post": { - "tags": ["crate::routes::admin"], - "summary": "Merchant Account - Create", - "description": "Merchant Account - Create\n\nCreate a new account for a merchant and the merchant could be a seller or retailer or client who likes to receive and send payments.", - "operationId": "merchant_account_create", + "tags": [ + "Merchant Account" + ], + "summary": "", + "description": "\nCreate a new account for a merchant and the merchant could be a seller or retailer or client who likes to receive and send payments.", + "operationId": "Create a Merchant Account", "requestBody": { "content": { "application/json": { @@ -58,12 +56,980 @@ "deprecated": false } }, + "/accounts/{account_id}": { + "get": { + "tags": [ + "Merchant Account" + ], + "summary": "", + "description": "\nRetrieve a merchant account details.", + "operationId": "Retrieve a Merchant Account", + "parameters": [ + { + "name": "account_id", + "in": "path", + "description": "The unique identifier for the merchant account", + "required": true, + "deprecated": false, + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "Merchant Account Retrieved", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/MerchantAccountResponse" + } + } + } + }, + "404": { + "description": "Merchant account not found" + } + }, + "deprecated": false + }, + "post": { + "tags": [ + "Merchant Account" + ], + "summary": "", + "description": "\nTo update an existing merchant account. Helpful in updating merchant details such as email, contact details, or other configuration details like webhook, routing algorithm etc", + "operationId": "Update a Merchant Account", + "parameters": [ + { + "name": "account_id", + "in": "path", + "description": "The unique identifier for the merchant account", + "required": true, + "deprecated": false, + "schema": { + "type": "string" + } + } + ], + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/CreateMerchantAccount" + } + } + }, + "required": true + }, + "responses": { + "200": { + "description": "Merchant Account Updated", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/MerchantAccountResponse" + } + } + } + }, + "404": { + "description": "Merchant account not found" + } + }, + "deprecated": false + }, + "delete": { + "tags": [ + "Merchant Account" + ], + "summary": "", + "description": "\nTo delete a merchant account", + "operationId": "Delete a Merchant Account", + "parameters": [ + { + "name": "account_id", + "in": "path", + "description": "The unique identifier for the merchant account", + "required": true, + "deprecated": false, + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "Merchant Account Deleted", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/DeleteMerchantAccountResponse" + } + } + } + }, + "404": { + "description": "Merchant account not found" + } + }, + "deprecated": false + } + }, + "/accounts/{account_id}/connectors": { + "get": { + "tags": [ + "Merchant Connector Account" + ], + "summary": "", + "description": "\nList Payment Connector Details for the merchant", + "operationId": "List all Merchant Connectors", + "parameters": [ + { + "name": "account_id", + "in": "path", + "description": "The unique identifier for the merchant account", + "required": true, + "deprecated": false, + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "Payment Connector list retrieved successfully", + "content": { + "application/json": { + "schema": { + "type": "array", + "items": { + "$ref": "#/components/schemas/PaymentConnectorCreate" + } + } + } + } + }, + "401": { + "description": "Unauthorized request" + }, + "404": { + "description": "Payment Connector does not exist in records" + } + }, + "deprecated": false + }, + "post": { + "tags": [ + "Merchant Connector Account" + ], + "summary": "", + "description": "\nCreate a new Payment Connector for the merchant account. The connector could be a payment processor / facilitator / acquirer or specialized services like Fraud / Accounting etc.\"", + "operationId": "Create a Merchant Connector", + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PaymentConnectorCreate" + } + } + }, + "required": true + }, + "responses": { + "200": { + "description": "Payment Connector Created", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PaymentConnectorCreate" + } + } + } + }, + "400": { + "description": "Missing Mandatory fields" + } + }, + "deprecated": false + } + }, + "/accounts/{account_id}/connectors/{connector_id}": { + "get": { + "tags": [ + "Merchant Connector Account" + ], + "summary": "", + "description": "\nRetrieve Payment Connector Details", + "operationId": "Retrieve a Merchant Connector", + "parameters": [ + { + "name": "account_id", + "in": "path", + "description": "The unique identifier for the merchant account", + "required": true, + "deprecated": false, + "schema": { + "type": "string" + } + }, + { + "name": "connector_id", + "in": "path", + "description": "The unique identifier for the payment connector", + "required": true, + "deprecated": false, + "schema": { + "type": "integer", + "format": "int32" + } + } + ], + "responses": { + "200": { + "description": "Payment Connector retrieved successfully", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PaymentConnectorCreate" + } + } + } + }, + "401": { + "description": "Unauthorized request" + }, + "404": { + "description": "Payment Connector does not exist in records" + } + }, + "deprecated": false + }, + "post": { + "tags": [ + "Merchant Connector Account" + ], + "summary": "", + "description": "\nTo update an existing Payment Connector. Helpful in enabling / disabling different payment methods and other settings for the connector etc.", + "operationId": "Update a Merchant Connector", + "parameters": [ + { + "name": "account_id", + "in": "path", + "description": "The unique identifier for the merchant account", + "required": true, + "deprecated": false, + "schema": { + "type": "string" + } + }, + { + "name": "connector_id", + "in": "path", + "description": "The unique identifier for the payment connector", + "required": true, + "deprecated": false, + "schema": { + "type": "integer", + "format": "int32" + } + } + ], + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PaymentConnectorCreate" + } + } + }, + "required": true + }, + "responses": { + "200": { + "description": "Payment Connector Updated", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PaymentConnectorCreate" + } + } + } + }, + "401": { + "description": "Unauthorized request" + }, + "404": { + "description": "Payment Connector does not exist in records" + } + }, + "deprecated": false + }, + "delete": { + "tags": [ + "Merchant Connector Account" + ], + "summary": "", + "description": "\nDelete or Detach a Payment Connector from Merchant Account", + "operationId": "Delete a Merchant Connector", + "parameters": [ + { + "name": "account_id", + "in": "path", + "description": "The unique identifier for the merchant account", + "required": true, + "deprecated": false, + "schema": { + "type": "string" + } + }, + { + "name": "connector_id", + "in": "path", + "description": "The unique identifier for the payment connector", + "required": true, + "deprecated": false, + "schema": { + "type": "integer", + "format": "int32" + } + } + ], + "responses": { + "200": { + "description": "Payment Connector Deleted", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/DeleteMcaResponse" + } + } + } + }, + "401": { + "description": "Unauthorized request" + }, + "404": { + "description": "Payment Connector does not exist in records" + } + }, + "deprecated": false + } + }, + "/customers": { + "post": { + "tags": [ + "Customers" + ], + "summary": "", + "description": "\nCreate a customer object and store the customer details to be reused for future payments. Incase the customer already exists in the system, this API will respond with the customer details.", + "operationId": "Create a Customer", + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/CustomerRequest" + } + } + }, + "required": true + }, + "responses": { + "200": { + "description": "Customer Created", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/CustomerResponse" + } + } + } + }, + "400": { + "description": "Invalid data" + } + }, + "deprecated": false + } + }, + "/customers/{customer_id}": { + "get": { + "tags": [ + "Customers" + ], + "summary": "", + "description": "\nRetrieve a customer's details.", + "operationId": "Retrieve a Customer", + "parameters": [ + { + "name": "customer_id", + "in": "path", + "description": "The unique identifier for the Customer", + "required": true, + "deprecated": false, + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "Customer Retrieved", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/CustomerResponse" + } + } + } + }, + "404": { + "description": "Customer was not found" + } + }, + "deprecated": false + }, + "post": { + "tags": [ + "Customers" + ], + "summary": "", + "description": "\nUpdates the customer's details in a customer object.", + "operationId": "Update a Customer", + "parameters": [ + { + "name": "customer_id", + "in": "path", + "description": "The unique identifier for the Customer", + "required": true, + "deprecated": false, + "schema": { + "type": "string" + } + } + ], + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/CustomerRequest" + } + } + }, + "required": true + }, + "responses": { + "200": { + "description": "Customer was Updated", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/CustomerResponse" + } + } + } + }, + "404": { + "description": "Customer was not found" + } + }, + "deprecated": false + }, + "delete": { + "tags": [ + "Customers" + ], + "summary": "", + "description": "\nDelete a customer record.", + "operationId": "Delete a Customer", + "parameters": [ + { + "name": "customer_id", + "in": "path", + "description": "The unique identifier for the Customer", + "required": true, + "deprecated": false, + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "Customer was Deleted", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/CustomerDeleteResponse" + } + } + } + }, + "404": { + "description": "Customer was not found" + } + }, + "deprecated": false + } + }, + "/mandates/revoke/{mandate_id}": { + "post": { + "tags": [ + "Mandates" + ], + "summary": "", + "description": "\nRevoke a mandate", + "operationId": "Revoke a Mandate", + "parameters": [ + { + "name": "mandate_id", + "in": "path", + "description": "The identifier for mandate", + "required": true, + "deprecated": false, + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "The mandate was revoked successfully", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/MandateRevokedResponse" + } + } + } + }, + "400": { + "description": "Mandate does not exist in our records" + } + }, + "deprecated": false + } + }, + "/mandates/{mandate_id}": { + "get": { + "tags": [ + "Mandates" + ], + "summary": "", + "description": "\nRetrieve a mandate", + "operationId": "Retrieve a Mandate", + "parameters": [ + { + "name": "mandate_id", + "in": "path", + "description": "The identifier for mandate", + "required": true, + "deprecated": false, + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "The mandate was retrieved successfully", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/MandateResponse" + } + } + } + }, + "404": { + "description": "Mandate does not exist in our records" + } + }, + "deprecated": false + } + }, + "/payment_methods": { + "post": { + "tags": [ + "Payment Methods" + ], + "summary": "", + "description": "\nTo create a payment method against a customer object. In case of cards, this API could be used only by PCI compliant merchants", + "operationId": "Create a Payment Method", + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/CreatePaymentMethod" + } + } + }, + "required": true + }, + "responses": { + "200": { + "description": "Payment Method Created", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PaymentMethodResponse" + } + } + } + }, + "400": { + "description": "Invalid Data" + } + }, + "deprecated": false + } + }, + "/payment_methods/{account_id}": { + "get": { + "tags": [ + "Payment Methods" + ], + "summary": "", + "description": "\nTo filter and list the applicable payment methods for a particular Merchant ID", + "operationId": "List all Payment Methods for a Merchant", + "parameters": [ + { + "name": "account_id", + "in": "path", + "description": "The unique identifier for the merchant account", + "required": true, + "deprecated": false, + "schema": { + "type": "string" + } + }, + { + "name": "accepted_country", + "in": "query", + "description": "The two-letter ISO currency code", + "required": true, + "deprecated": false, + "schema": { + "type": "array", + "items": { + "type": "string" + } + } + }, + { + "name": "accepted_currency", + "in": "path", + "description": "The three-letter ISO currency code", + "required": true, + "deprecated": false, + "schema": { + "type": "array", + "items": { + "$ref": "#/components/schemas/Currency" + } + } + }, + { + "name": "minimum_amount", + "in": "query", + "description": "The minimum amount accepted for processing by the particular payment method.", + "required": true, + "deprecated": false, + "schema": { + "type": "integer", + "format": "int64" + } + }, + { + "name": "maximum_amount", + "in": "query", + "description": "The maximum amount amount accepted for processing by the particular payment method.", + "required": true, + "deprecated": false, + "schema": { + "type": "integer", + "format": "int64" + } + }, + { + "name": "recurring_payment_enabled", + "in": "query", + "description": "Indicates whether the payment method is eligible for recurring payments", + "required": true, + "deprecated": false, + "schema": { + "type": "boolean" + } + }, + { + "name": "installment_payment_enabled", + "in": "query", + "description": "Indicates whether the payment method is eligible for installment payments", + "required": true, + "deprecated": false, + "schema": { + "type": "boolean" + } + } + ], + "responses": { + "200": { + "description": "Payment Methods retrieved", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ListPaymentMethodResponse" + } + } + } + }, + "400": { + "description": "Invalid Data" + }, + "404": { + "description": "Payment Methods does not exist in records" + } + }, + "deprecated": false + } + }, + "/payment_methods/{customer_id}": { + "get": { + "tags": [ + "Payment Methods" + ], + "summary": "", + "description": "\nTo filter and list the applicable payment methods for a particular Customer ID", + "operationId": "List all Payment Methods for a Customer", + "parameters": [ + { + "name": "customer_id", + "in": "path", + "description": "The unique identifier for the customer account", + "required": true, + "deprecated": false, + "schema": { + "type": "string" + } + }, + { + "name": "accepted_country", + "in": "query", + "description": "The two-letter ISO currency code", + "required": true, + "deprecated": false, + "schema": { + "type": "array", + "items": { + "type": "string" + } + } + }, + { + "name": "accepted_currency", + "in": "path", + "description": "The three-letter ISO currency code", + "required": true, + "deprecated": false, + "schema": { + "type": "array", + "items": { + "$ref": "#/components/schemas/Currency" + } + } + }, + { + "name": "minimum_amount", + "in": "query", + "description": "The minimum amount accepted for processing by the particular payment method.", + "required": true, + "deprecated": false, + "schema": { + "type": "integer", + "format": "int64" + } + }, + { + "name": "maximum_amount", + "in": "query", + "description": "The maximum amount amount accepted for processing by the particular payment method.", + "required": true, + "deprecated": false, + "schema": { + "type": "integer", + "format": "int64" + } + }, + { + "name": "recurring_payment_enabled", + "in": "query", + "description": "Indicates whether the payment method is eligible for recurring payments", + "required": true, + "deprecated": false, + "schema": { + "type": "boolean" + } + }, + { + "name": "installment_payment_enabled", + "in": "query", + "description": "Indicates whether the payment method is eligible for installment payments", + "required": true, + "deprecated": false, + "schema": { + "type": "boolean" + } + } + ], + "responses": { + "200": { + "description": "Payment Methods retrieved", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ListCustomerPaymentMethodsResponse" + } + } + } + }, + "400": { + "description": "Invalid Data" + }, + "404": { + "description": "Payment Methods does not exist in records" + } + }, + "deprecated": false + } + }, + "/payment_methods/{method_id}": { + "get": { + "tags": [ + "Payment Methods" + ], + "summary": "", + "description": "\nTo retrieve a payment method", + "operationId": "Retrieve a Payment method", + "parameters": [ + { + "name": "method_id", + "in": "path", + "description": "The unique identifier for the Payment Method", + "required": true, + "deprecated": false, + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "Payment Method retrieved", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PaymentMethodResponse" + } + } + } + }, + "404": { + "description": "Payment Method does not exist in records" + } + }, + "deprecated": false + }, + "post": { + "tags": [ + "Payment Methods" + ], + "summary": "", + "description": "\nTo update an existing payment method attached to a customer object. This API is useful for use cases such as updating the card number for expired cards to prevent discontinuity in recurring payments", + "operationId": "Update a Payment method", + "parameters": [ + { + "name": "method_id", + "in": "path", + "description": "The unique identifier for the Payment Method", + "required": true, + "deprecated": false, + "schema": { + "type": "string" + } + } + ], + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/UpdatePaymentMethod" + } + } + }, + "required": true + }, + "responses": { + "200": { + "description": "Payment Method updated", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PaymentMethodResponse" + } + } + } + }, + "404": { + "description": "Payment Method does not exist in records" + } + }, + "deprecated": false + }, + "delete": { + "tags": [ + "Payment Methods" + ], + "summary": "", + "description": "\nDelete payment method", + "operationId": "Delete a Payment method", + "parameters": [ + { + "name": "method_id", + "in": "path", + "description": "The unique identifier for the Payment Method", + "required": true, + "deprecated": false, + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "Payment Method deleted", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/DeletePaymentMethodResponse" + } + } + } + }, + "404": { + "description": "Payment Method does not exist in records" + } + }, + "deprecated": false + } + }, "/payments": { "post": { - "tags": ["crate::routes::payments"], - "summary": "Payments - Create", - "description": "Payments - Create\n\nTo create a new payment, against a merchant API key", - "operationId": "payments_create", + "tags": [ + "Payments" + ], + "summary": "", + "description": "\nTo process a payment you will have to create a payment, attach a payment method and confirm. Depending on the user journey you wish to achieve, you may opt to all the steps in a single request or in a sequence of API request using following APIs: (i) Payments - Update, (ii) Payments - Confirm, and (iii) Payments - Capture", + "operationId": "Create a Payment", "requestBody": { "content": { "application/json": { @@ -92,12 +1058,398 @@ "deprecated": false } }, + "/payments/list": { + "get": { + "tags": [ + "Payments" + ], + "summary": "", + "description": "\nTo list the payments", + "operationId": "List all Payments", + "parameters": [ + { + "name": "customer_id", + "in": "query", + "description": "The identifier for the customer", + "required": true, + "deprecated": false, + "schema": { + "type": "string" + } + }, + { + "name": "starting_after", + "in": "query", + "description": "A cursor for use in pagination, fetch the next list after some object", + "required": true, + "deprecated": false, + "schema": { + "type": "string" + } + }, + { + "name": "ending_before", + "in": "query", + "description": "A cursor for use in pagination, fetch the previous list before some object", + "required": true, + "deprecated": false, + "schema": { + "type": "string" + } + }, + { + "name": "limit", + "in": "query", + "description": "Limit on the number of objects to return", + "required": true, + "deprecated": false, + "schema": { + "type": "integer", + "format": "int64" + } + }, + { + "name": "created", + "in": "query", + "description": "The time at which payment is created", + "required": true, + "deprecated": false, + "schema": { + "type": "string", + "format": "date-time" + } + }, + { + "name": "created_lt", + "in": "query", + "description": "Time less than the payment created time", + "required": true, + "deprecated": false, + "schema": { + "type": "string", + "format": "date-time" + } + }, + { + "name": "created_gt", + "in": "query", + "description": "Time greater than the payment created time", + "required": true, + "deprecated": false, + "schema": { + "type": "string", + "format": "date-time" + } + }, + { + "name": "created_lte", + "in": "query", + "description": "Time less than or equals to the payment created time", + "required": true, + "deprecated": false, + "schema": { + "type": "string", + "format": "date-time" + } + }, + { + "name": "created_gte", + "in": "query", + "description": "Time greater than or equals to the payment created time", + "required": true, + "deprecated": false, + "schema": { + "type": "string", + "format": "date-time" + } + } + ], + "responses": { + "200": { + "description": "Received payment list" + }, + "404": { + "description": "No payments found" + } + }, + "deprecated": false + } + }, + "/payments/session_tokens": { + "post": { + "tags": [ + "Payments" + ], + "summary": "", + "description": "\nTo create the session object or to get session token for wallets", + "operationId": "Create Session tokens for a Payment", + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PaymentsSessionRequest" + } + } + }, + "required": true + }, + "responses": { + "200": { + "description": "Payment session object created or session token was retrieved from wallets", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PaymentsSessionResponse" + } + } + } + }, + "400": { + "description": "Missing mandatory fields" + } + }, + "deprecated": false + } + }, + "/payments/{payment_id}": { + "get": { + "tags": [ + "Payments" + ], + "summary": "", + "description": "\nTo retrieve the properties of a Payment. This may be used to get the status of a previously initiated payment or next action for an ongoing payment", + "operationId": "Retrieve a Payment", + "parameters": [ + { + "name": "payment_id", + "in": "path", + "description": "The identifier for payment", + "required": true, + "deprecated": false, + "schema": { + "type": "string" + } + } + ], + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PaymentRetrieveBody" + } + } + }, + "required": true + }, + "responses": { + "200": { + "description": "Gets the payment with final status", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PaymentsResponse" + } + } + } + }, + "404": { + "description": "No payment found" + } + }, + "deprecated": false + }, + "post": { + "tags": [ + "Payments" + ], + "summary": "", + "description": "\nTo update the properties of a PaymentIntent object. This may include attaching a payment method, or attaching customer object or metadata fields after the Payment is created", + "operationId": "Update a Payment", + "parameters": [ + { + "name": "payment_id", + "in": "path", + "description": "The identifier for payment", + "required": true, + "deprecated": false, + "schema": { + "type": "string" + } + } + ], + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PaymentsRequest" + } + } + }, + "required": true + }, + "responses": { + "200": { + "description": "Payment updated", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PaymentsResponse" + } + } + } + }, + "400": { + "description": "Missing mandatory fields" + } + }, + "deprecated": false + } + }, + "/payments/{payment_id}/cancel": { + "post": { + "tags": [ + "Payments" + ], + "summary": "", + "description": "\nA Payment could can be cancelled when it is in one of these statuses: requires_payment_method, requires_capture, requires_confirmation, requires_customer_action", + "operationId": "Cancel a Payment", + "parameters": [ + { + "name": "payment_id", + "in": "path", + "description": "The identifier for payment", + "required": true, + "deprecated": false, + "schema": { + "type": "string" + } + } + ], + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PaymentsCancelRequest" + } + } + }, + "required": true + }, + "responses": { + "200": { + "description": "Payment canceled" + }, + "400": { + "description": "Missing mandatory fields" + } + }, + "deprecated": false + } + }, + "/payments/{payment_id}/capture": { + "post": { + "tags": [ + "Payments" + ], + "summary": "", + "description": "\nTo capture the funds for an uncaptured payment", + "operationId": "Capture a Payment", + "parameters": [ + { + "name": "payment_id", + "in": "path", + "description": "The identifier for payment", + "required": true, + "deprecated": false, + "schema": { + "type": "string" + } + } + ], + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PaymentsCaptureRequest" + } + } + }, + "required": true + }, + "responses": { + "200": { + "description": "Payment captured", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PaymentsResponse" + } + } + } + }, + "400": { + "description": "Missing mandatory fields" + } + }, + "deprecated": false + } + }, + "/payments/{payment_id}/confirm": { + "post": { + "tags": [ + "Payments" + ], + "summary": "", + "description": "\nThis API is to confirm the payment request and forward payment to the payment processor. This API provides more granular control upon when the API is forwarded to the payment processor. Alternatively you can confirm the payment within the Payments Create API", + "operationId": "Confirm a Payment", + "parameters": [ + { + "name": "payment_id", + "in": "path", + "description": "The identifier for payment", + "required": true, + "deprecated": false, + "schema": { + "type": "string" + } + } + ], + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PaymentsRequest" + } + } + }, + "required": true + }, + "responses": { + "200": { + "description": "Payment confirmed", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PaymentsResponse" + } + } + } + }, + "400": { + "description": "Missing mandatory fields" + } + }, + "deprecated": false + } + }, "/refunds": { "post": { - "tags": ["crate::routes::refunds"], - "summary": "Refunds - Create", - "description": "Refunds - Create\n\nTo create a refund against an already processed payment", - "operationId": "refunds_create", + "tags": [ + "Refunds" + ], + "summary": "", + "description": "\nTo create a refund against an already processed payment", + "operationId": "Create a Refund", "requestBody": { "content": { "application/json": { @@ -125,13 +1477,204 @@ }, "deprecated": false } + }, + "/refunds/list": { + "get": { + "tags": [ + "Refunds" + ], + "summary": "", + "description": "\nTo list the refunds associated with a payment_id or with the merchant, if payment_id is not provided", + "operationId": "List all Refunds", + "parameters": [ + { + "name": "payment_id", + "in": "query", + "description": "The identifier for the payment", + "required": true, + "deprecated": false, + "schema": { + "type": "string" + } + }, + { + "name": "limit", + "in": "query", + "description": "Limit on the number of objects to return", + "required": true, + "deprecated": false, + "schema": { + "type": "integer", + "format": "int64" + } + }, + { + "name": "created", + "in": "query", + "description": "The time at which refund is created", + "required": true, + "deprecated": false, + "schema": { + "type": "string", + "format": "date-time" + } + }, + { + "name": "created_lt", + "in": "query", + "description": "Time less than the refund created time", + "required": true, + "deprecated": false, + "schema": { + "type": "string", + "format": "date-time" + } + }, + { + "name": "created_gt", + "in": "query", + "description": "Time greater than the refund created time", + "required": true, + "deprecated": false, + "schema": { + "type": "string", + "format": "date-time" + } + }, + { + "name": "created_lte", + "in": "query", + "description": "Time less than or equals to the refund created time", + "required": true, + "deprecated": false, + "schema": { + "type": "string", + "format": "date-time" + } + }, + { + "name": "created_gte", + "in": "query", + "description": "Time greater than or equals to the refund created time", + "required": true, + "deprecated": false, + "schema": { + "type": "string", + "format": "date-time" + } + } + ], + "responses": { + "200": { + "description": "List of refunds", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/RefundListResponse" + } + } + } + }, + "404": { + "description": "Refund does not exist in our records" + } + }, + "deprecated": false + } + }, + "/refunds/{refund_id}": { + "get": { + "tags": [ + "Refunds" + ], + "summary": "", + "description": "\nTo retrieve the properties of a Refund. This may be used to get the status of a previously initiated payment or next action for an ongoing payment", + "operationId": "Retrieve a Refund", + "parameters": [ + { + "name": "refund_id", + "in": "path", + "description": "The identifier for refund", + "required": true, + "deprecated": false, + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "Refund retrieved", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/RefundResponse" + } + } + } + }, + "404": { + "description": "Refund does not exist in our records" + } + }, + "deprecated": false + }, + "post": { + "tags": [ + "Refunds" + ], + "summary": "", + "description": "\nTo update the properties of a Refund object. This may include attaching a reason for the refund or metadata fields", + "operationId": "Update a Refund", + "parameters": [ + { + "name": "refund_id", + "in": "path", + "description": "The identifier for refund", + "required": true, + "deprecated": false, + "schema": { + "type": "string" + } + } + ], + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/RefundUpdateRequest" + } + } + }, + "required": true + }, + "responses": { + "200": { + "description": "Refund updated", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/RefundResponse" + } + } + } + }, + "400": { + "description": "Missing Mandatory fields" + } + }, + "deprecated": false + } } }, "components": { "schemas": { "AcceptanceType": { "type": "string", - "enum": ["online", "offline"] + "enum": [ + "online", + "offline" + ] }, "Address": { "type": "object", @@ -205,17 +1748,33 @@ }, "AffirmIssuer": { "type": "string", - "enum": ["affirm"] + "enum": [ + "affirm" + ] }, "AfterpayClearpayIssuer": { "type": "string", - "enum": ["afterpay_clearpay"] + "enum": [ + "afterpay_clearpay" + ] }, "AuthenticationType": { "type": "string", - "enum": ["three_ds", "no_three_ds"] + "enum": [ + "three_ds", + "no_three_ds" + ] }, - "CCard": { + "CaptureMethod": { + "type": "string", + "enum": [ + "automatic", + "manual", + "manual_multiple", + "scheduled" + ] + }, + "Card": { "type": "object", "required": [ "card_number", @@ -252,9 +1811,65 @@ } } }, - "CaptureMethod": { - "type": "string", - "enum": ["automatic", "manual", "manual_multiple", "scheduled"] + "CardDetail": { + "type": "object", + "required": [ + "card_number", + "card_exp_month", + "card_exp_year", + "card_holder_name" + ], + "properties": { + "card_number": { + "type": "string", + "description": "Card Number", + "example": "4111111145551142" + }, + "card_exp_month": { + "type": "string", + "description": "Card Expiry Month", + "example": "10" + }, + "card_exp_year": { + "type": "string", + "description": "Card Expiry Year", + "example": "25" + }, + "card_holder_name": { + "type": "string", + "description": "Card Holder Name", + "example": "John Doe" + } + } + }, + "CardDetailFromLocker": { + "type": "object", + "properties": { + "scheme": { + "type": "string" + }, + "issuer_country": { + "type": "string" + }, + "last4_digits": { + "type": "string" + }, + "expiry_month": { + "type": "string" + }, + "expiry_year": { + "type": "string" + }, + "card_token": { + "type": "string" + }, + "card_holder_name": { + "type": "string" + }, + "card_fingerprint": { + "type": "string" + } + } }, "Connector": { "type": "string", @@ -292,7 +1907,9 @@ }, "CreateMerchantAccount": { "type": "object", - "required": ["merchant_id"], + "required": [ + "merchant_id" + ], "properties": { "merchant_id": { "type": "string", @@ -368,6 +1985,39 @@ } } }, + "CreatePaymentMethod": { + "type": "object", + "required": [ + "payment_method" + ], + "properties": { + "payment_method": { + "$ref": "#/components/schemas/PaymentMethodType" + }, + "payment_method_type": { + "$ref": "#/components/schemas/PaymentMethodSubType" + }, + "payment_method_issuer": { + "type": "string", + "description": "The name of the bank/ provider issuing the payment method to the end user", + "example": "Citibank" + }, + "payment_method_issuer_code": { + "$ref": "#/components/schemas/PaymentMethodIssuerCode" + }, + "card": { + "$ref": "#/components/schemas/CardDetail" + }, + "metadata": { + "type": "object" + }, + "customer_id": { + "type": "string", + "description": "The unique identifier of the customer.", + "example": "cus_meowerunwiuwiwqw" + } + } + }, "Currency": { "type": "string", "enum": [ @@ -478,7 +2128,9 @@ }, "CustomerAcceptance": { "type": "object", - "required": ["acceptance_type"], + "required": [ + "acceptance_type" + ], "properties": { "acceptance_type": { "$ref": "#/components/schemas/AcceptanceType" @@ -526,6 +2178,73 @@ } } }, + "CustomerPaymentMethod": { + "type": "object", + "required": [ + "payment_token", + "customer_id", + "payment_method", + "recurring_enabled", + "installment_payment_enabled" + ], + "properties": { + "payment_token": { + "type": "string", + "description": "Token for payment method in temporary card locker which gets refreshed often", + "example": "7ebf443f-a050-4067-84e5-e6f6d4800aef" + }, + "customer_id": { + "type": "string", + "description": "The unique identifier of the customer.", + "example": "cus_meowerunwiuwiwqw" + }, + "payment_method": { + "$ref": "#/components/schemas/PaymentMethodType" + }, + "payment_method_type": { + "$ref": "#/components/schemas/PaymentMethodSubType" + }, + "payment_method_issuer": { + "type": "string", + "description": "The name of the bank/ provider issuing the payment method to the end user", + "example": "Citibank" + }, + "payment_method_issuer_code": { + "$ref": "#/components/schemas/PaymentMethodIssuerCode" + }, + "recurring_enabled": { + "type": "boolean", + "description": "Indicates whether the payment method is eligible for recurring payments", + "example": true + }, + "installment_payment_enabled": { + "type": "boolean", + "description": "Indicates whether the payment method is eligible for installment payments", + "example": true + }, + "payment_experience": { + "type": "array", + "items": { + "$ref": "#/components/schemas/PaymentExperience" + }, + "example": [ + "redirect_to_url" + ] + }, + "card": { + "$ref": "#/components/schemas/CardDetailFromLocker" + }, + "metadata": { + "type": "object" + }, + "created": { + "type": "string", + "format": "date-time", + "description": "A timestamp (ISO 8601 code) that determines when the customer was created", + "example": "2023-01-18T11:04:09.922Z" + } + } + }, "CustomerRequest": { "type": "object", "description": "The customer details", @@ -576,7 +2295,10 @@ }, "CustomerResponse": { "type": "object", - "required": ["customer_id", "created_at"], + "required": [ + "customer_id", + "created_at" + ], "properties": { "customer_id": { "type": "string", @@ -630,7 +2352,11 @@ }, "DeleteMcaResponse": { "type": "object", - "required": ["merchant_id", "merchant_connector_id", "deleted"], + "required": [ + "merchant_id", + "merchant_connector_id", + "deleted" + ], "properties": { "merchant_id": { "type": "string", @@ -651,9 +2377,12 @@ } } }, - "DeleteResponse": { + "DeleteMerchantAccountResponse": { "type": "object", - "required": ["merchant_id", "deleted"], + "required": [ + "merchant_id", + "deleted" + ], "properties": { "merchant_id": { "type": "string", @@ -668,13 +2397,38 @@ } } }, + "DeletePaymentMethodResponse": { + "type": "object", + "required": [ + "payment_method_id", + "deleted" + ], + "properties": { + "payment_method_id": { + "type": "string", + "description": "The unique identifier of the Payment method", + "example": "card_rGK4Vi5iSW70MY7J2mIy" + }, + "deleted": { + "type": "boolean", + "description": "Whether payment method was deleted or not", + "example": true + } + } + }, "FutureUsage": { "type": "string", - "enum": ["off_session", "on_session"] + "enum": [ + "off_session", + "on_session" + ] }, "GpayAllowedMethodsParameters": { "type": "object", - "required": ["allowed_auth_methods", "allowed_card_networks"], + "required": [ + "allowed_auth_methods", + "allowed_card_networks" + ], "properties": { "allowed_auth_methods": { "type": "array", @@ -694,7 +2448,11 @@ }, "GpayAllowedPaymentMethods": { "type": "object", - "required": ["type", "parameters", "tokenization_specification"], + "required": [ + "type", + "parameters", + "tokenization_specification" + ], "properties": { "type": { "type": "string", @@ -710,7 +2468,9 @@ }, "GpayMerchantInfo": { "type": "object", - "required": ["merchant_name"], + "required": [ + "merchant_name" + ], "properties": { "merchant_name": { "type": "string", @@ -720,7 +2480,10 @@ }, "GpayTokenParameters": { "type": "object", - "required": ["gateway", "gateway_merchant_id"], + "required": [ + "gateway", + "gateway_merchant_id" + ], "properties": { "gateway": { "type": "string", @@ -734,7 +2497,10 @@ }, "GpayTokenizationSpecification": { "type": "object", - "required": ["type", "parameters"], + "required": [ + "type", + "parameters" + ], "properties": { "type": { "type": "string", @@ -788,11 +2554,182 @@ }, "KlarnaIssuer": { "type": "string", - "enum": ["klarna"] + "enum": [ + "klarna" + ] + }, + "ListCustomerPaymentMethodsResponse": { + "type": "object", + "required": [ + "enabled_payment_methods", + "customer_payment_methods" + ], + "properties": { + "enabled_payment_methods": { + "type": "array", + "items": { + "$ref": "#/components/schemas/ListPaymentMethod" + }, + "example": [ + { + "payment_method": "wallet", + "payment_experience": null, + "payment_method_issuers": [ + "labore magna ipsum", + "aute" + ] + } + ] + }, + "customer_payment_methods": { + "type": "array", + "items": { + "$ref": "#/components/schemas/CustomerPaymentMethod" + } + } + } + }, + "ListPaymentMethod": { + "type": "object", + "required": [ + "payment_method", + "recurring_enabled", + "installment_payment_enabled" + ], + "properties": { + "payment_method": { + "$ref": "#/components/schemas/PaymentMethodType" + }, + "payment_method_types": { + "type": "array", + "items": { + "$ref": "#/components/schemas/PaymentMethodSubType" + }, + "example": [ + "credit_card" + ] + }, + "payment_method_issuers": { + "type": "array", + "items": { + "type": "string", + "description": "The name of the bank/ provider issuing the payment method to the end user" + }, + "example": [ + "Citibank" + ] + }, + "payment_method_issuer_code": { + "type": "array", + "items": { + "$ref": "#/components/schemas/PaymentMethodIssuerCode" + }, + "example": [ + "jp_applepay" + ] + }, + "payment_schemes": { + "type": "array", + "items": { + "type": "string", + "description": "List of payment schemes accepted or has the processing capabilities of the processor" + }, + "example": [ + "MASTER", + "VISA", + "DINERS" + ] + }, + "accepted_countries": { + "type": "array", + "items": { + "type": "string", + "description": "List of Countries accepted or has the processing capabilities of the processor" + }, + "example": [ + "US", + "UK", + "IN" + ] + }, + "accepted_currencies": { + "type": "array", + "items": { + "$ref": "#/components/schemas/Currency" + }, + "example": [ + "USD", + "EUR" + ] + }, + "minimum_amount": { + "type": "integer", + "format": "int64", + "description": "Minimum amount supported by the processor. To be represented in the lowest denomination of\nthe target currency (For example, for USD it should be in cents)", + "example": 60000 + }, + "maximum_amount": { + "type": "integer", + "format": "int64", + "description": "Maximum amount supported by the processor. To be represented in the lowest denomination of\nthe target currency (For example, for USD it should be in cents)", + "example": 1 + }, + "recurring_enabled": { + "type": "boolean", + "description": "Boolean to enable recurring payments / mandates. Default is true.", + "example": true + }, + "installment_payment_enabled": { + "type": "boolean", + "description": "Boolean to enable installment / EMI / BNPL payments. Default is true.", + "example": true + }, + "payment_experience": { + "type": "array", + "items": { + "$ref": "#/components/schemas/PaymentExperience" + }, + "example": [ + "redirect_to_url" + ] + } + } + }, + "ListPaymentMethodResponse": { + "type": "object", + "required": [ + "payment_methods" + ], + "properties": { + "redirect_url": { + "type": "string", + "description": "Redirect URL of the merchant", + "example": "https://www.google.com" + }, + "payment_methods": { + "type": "array", + "items": { + "$ref": "#/components/schemas/ListPaymentMethod" + }, + "example": [ + { + "payment_method": "wallet", + "payment_experience": null, + "payment_method_issuers": [ + "labore magna ipsum", + "aute" + ] + } + ] + } + } }, "MandateAmountData": { "type": "object", - "required": ["amount", "currency"], + "required": [ + "amount", + "currency" + ], "properties": { "amount": { "type": "integer", @@ -805,9 +2742,49 @@ } } }, + "MandateCardDetails": { + "type": "object", + "properties": { + "last4_digits": { + "type": "string", + "description": "The last 4 digits of card" + }, + "card_exp_month": { + "type": "string", + "description": "The expiry month of card" + }, + "card_exp_year": { + "type": "string", + "description": "The expiry year of card" + }, + "card_holder_name": { + "type": "string", + "description": "The card holder name" + }, + "card_token": { + "type": "string", + "description": "The token from card locker" + }, + "scheme": { + "type": "string", + "description": "The card scheme network for the particular card" + }, + "issuer_country": { + "type": "string", + "description": "The country code in in which the card was issued" + }, + "card_fingerprint": { + "type": "string", + "description": "A unique identifier alias to identify a particular card" + } + } + }, "MandateData": { "type": "object", - "required": ["customer_acceptance", "mandate_type"], + "required": [ + "customer_acceptance", + "mandate_type" + ], "properties": { "customer_acceptance": { "$ref": "#/components/schemas/CustomerAcceptance" @@ -817,11 +2794,71 @@ } } }, + "MandateResponse": { + "type": "object", + "required": [ + "mandate_id", + "status", + "payment_method_id", + "payment_method" + ], + "properties": { + "mandate_id": { + "type": "string", + "description": "The identifier for mandate" + }, + "status": { + "$ref": "#/components/schemas/MandateStatus" + }, + "payment_method_id": { + "type": "string", + "description": "The identifier for payment method" + }, + "payment_method": { + "type": "string", + "description": "The payment method" + }, + "card": { + "$ref": "#/components/schemas/MandateCardDetails" + }, + "customer_acceptance": { + "$ref": "#/components/schemas/CustomerAcceptance" + } + } + }, + "MandateRevokedResponse": { + "type": "object", + "required": [ + "mandate_id", + "status" + ], + "properties": { + "mandate_id": { + "type": "string", + "description": "The identifier for mandate" + }, + "status": { + "$ref": "#/components/schemas/MandateStatus" + } + } + }, + "MandateStatus": { + "type": "string", + "description": "The status of the mandate, which indicates whether it can be used to initiate a payment", + "enum": [ + "active", + "inactive", + "pending", + "revoked" + ] + }, "MandateType": { "oneOf": [ { "type": "object", - "required": ["single_use"], + "required": [ + "single_use" + ], "properties": { "single_use": { "$ref": "#/components/schemas/MandateAmountData" @@ -830,7 +2867,9 @@ }, { "type": "object", - "required": ["multi_use"], + "required": [ + "multi_use" + ], "properties": { "multi_use": { "$ref": "#/components/schemas/MandateAmountData" @@ -925,7 +2964,10 @@ }, "MerchantConnectorId": { "type": "object", - "required": ["merchant_id", "merchant_connector_id"], + "required": [ + "merchant_id", + "merchant_connector_id" + ], "properties": { "merchant_id": { "type": "string" @@ -1009,7 +3051,9 @@ }, "NextAction": { "type": "object", - "required": ["type"], + "required": [ + "type" + ], "properties": { "type": { "$ref": "#/components/schemas/NextActionType" @@ -1032,7 +3076,10 @@ }, "OnlineMandate": { "type": "object", - "required": ["ip_address", "user_agent"], + "required": [ + "ip_address", + "user_agent" + ], "properties": { "ip_address": { "type": "string", @@ -1047,7 +3094,10 @@ }, "OrderDetails": { "type": "object", - "required": ["product_name", "quantity"], + "required": [ + "product_name", + "quantity" + ], "properties": { "product_name": { "type": "string", @@ -1067,12 +3117,18 @@ "oneOf": [ { "type": "object", - "required": ["klarna_redirect"], + "required": [ + "klarna_redirect" + ], "properties": { "klarna_redirect": { "type": "object", "description": "For KlarnaRedirect as PayLater Option", - "required": ["issuer_name", "billing_email", "billing_country"], + "required": [ + "issuer_name", + "billing_email", + "billing_country" + ], "properties": { "issuer_name": { "$ref": "#/components/schemas/KlarnaIssuer" @@ -1090,12 +3146,17 @@ }, { "type": "object", - "required": ["klarna_sdk"], + "required": [ + "klarna_sdk" + ], "properties": { "klarna_sdk": { "type": "object", "description": "For Klarna Sdk as PayLater Option", - "required": ["issuer_name", "token"], + "required": [ + "issuer_name", + "token" + ], "properties": { "issuer_name": { "$ref": "#/components/schemas/KlarnaIssuer" @@ -1110,12 +3171,17 @@ }, { "type": "object", - "required": ["affirm_redirect"], + "required": [ + "affirm_redirect" + ], "properties": { "affirm_redirect": { "type": "object", "description": "For Affirm redirect as PayLater Option", - "required": ["issuer_name", "billing_email"], + "required": [ + "issuer_name", + "billing_email" + ], "properties": { "issuer_name": { "$ref": "#/components/schemas/AffirmIssuer" @@ -1130,12 +3196,18 @@ }, { "type": "object", - "required": ["afterpay_clearpay_redirect"], + "required": [ + "afterpay_clearpay_redirect" + ], "properties": { "afterpay_clearpay_redirect": { "type": "object", "description": "For AfterpayClearpay redirect as PayLater Option", - "required": ["issuer_name", "billing_email", "billing_name"], + "required": [ + "issuer_name", + "billing_email", + "billing_name" + ], "properties": { "issuer_name": { "$ref": "#/components/schemas/AfterpayClearpayIssuer" @@ -1157,7 +3229,10 @@ "PaymentConnectorCreate": { "type": "object", "description": "Create a new Payment Connector for the merchant account. The connector could be a payment processor / facilitator / acquirer or specialized services like Fraud / Accounting etc.\"", - "required": ["connector_type", "connector_name"], + "required": [ + "connector_type", + "connector_name" + ], "properties": { "connector_type": { "$ref": "#/components/schemas/ConnectorType" @@ -1196,11 +3271,26 @@ "example": [ { "payment_method": "wallet", - "payment_method_types": ["upi_collect", "upi_intent"], - "payment_method_issuers": ["labore magna ipsum", "aute"], - "payment_schemes": ["Discover", "Discover"], - "accepted_currencies": ["AED", "AED"], - "accepted_countries": ["in", "us"], + "payment_method_types": [ + "upi_collect", + "upi_intent" + ], + "payment_method_issuers": [ + "labore magna ipsum", + "aute" + ], + "payment_schemes": [ + "Discover", + "Discover" + ], + "accepted_currencies": [ + "AED", + "AED" + ], + "accepted_countries": [ + "in", + "us" + ], "minimum_amount": 1, "maximum_amount": 68607706, "recurring_enabled": true, @@ -1228,7 +3318,9 @@ "oneOf": [ { "type": "object", - "required": ["PaymentIntentId"], + "required": [ + "PaymentIntentId" + ], "properties": { "PaymentIntentId": { "type": "string", @@ -1238,7 +3330,9 @@ }, { "type": "object", - "required": ["ConnectorTransactionId"], + "required": [ + "ConnectorTransactionId" + ], "properties": { "ConnectorTransactionId": { "type": "string", @@ -1248,7 +3342,9 @@ }, { "type": "object", - "required": ["PaymentAttemptId"], + "required": [ + "PaymentAttemptId" + ], "properties": { "PaymentAttemptId": { "type": "string", @@ -1307,7 +3403,10 @@ }, "PaymentListResponse": { "type": "object", - "required": ["size", "data"], + "required": [ + "size", + "data" + ], "properties": { "size": { "type": "integer", @@ -1325,41 +3424,138 @@ "oneOf": [ { "type": "object", - "required": ["Card"], + "required": [ + "card" + ], "properties": { - "Card": { - "$ref": "#/components/schemas/CCard" + "card": { + "$ref": "#/components/schemas/Card" } } }, { "type": "string", - "enum": ["BankTransfer"] + "enum": [ + "bank_transfer" + ] }, { "type": "object", - "required": ["Wallet"], + "required": [ + "wallet" + ], "properties": { - "Wallet": { + "wallet": { "$ref": "#/components/schemas/WalletData" } } }, { "type": "object", - "required": ["PayLater"], + "required": [ + "pay_later" + ], "properties": { - "PayLater": { + "pay_later": { "$ref": "#/components/schemas/PayLaterData" } } }, { "type": "string", - "enum": ["Paypal"] + "enum": [ + "paypal" + ] } ] }, + "PaymentMethodIssuerCode": { + "type": "string", + "enum": [ + "jp_hdfc", + "jp_icici", + "jp_googlepay", + "jp_applepay", + "jp_phonepay", + "jp_wechat", + "jp_sofort", + "jp_giropay", + "jp_sepa", + "jp_bacs" + ] + }, + "PaymentMethodResponse": { + "type": "object", + "required": [ + "merchant_id", + "payment_method_id", + "payment_method", + "recurring_enabled", + "installment_payment_enabled" + ], + "properties": { + "merchant_id": { + "type": "string", + "description": "Unique identifier for a merchant", + "example": "merchant_1671528864" + }, + "customer_id": { + "type": "string", + "description": "The unique identifier of the customer.", + "example": "cus_meowerunwiuwiwqw" + }, + "payment_method_id": { + "type": "string", + "description": "The unique identifier of the Payment method", + "example": "card_rGK4Vi5iSW70MY7J2mIy" + }, + "payment_method": { + "$ref": "#/components/schemas/PaymentMethodType" + }, + "payment_method_type": { + "$ref": "#/components/schemas/PaymentMethodSubType" + }, + "payment_method_issuer": { + "type": "string", + "description": "The name of the bank/ provider issuing the payment method to the end user", + "example": "Citibank" + }, + "payment_method_issuer_code": { + "$ref": "#/components/schemas/PaymentMethodIssuerCode" + }, + "card": { + "$ref": "#/components/schemas/CardDetailFromLocker" + }, + "recurring_enabled": { + "type": "boolean", + "description": "Indicates whether the payment method is eligible for recurring payments", + "example": true + }, + "installment_payment_enabled": { + "type": "boolean", + "description": "Indicates whether the payment method is eligible for installment payments", + "example": true + }, + "payment_experience": { + "type": "array", + "items": { + "$ref": "#/components/schemas/PaymentExperience" + }, + "example": [ + "redirect_to_url" + ] + }, + "metadata": { + "type": "object" + }, + "created": { + "type": "string", + "format": "date-time", + "description": "A timestamp (ISO 8601 code) that determines when the customer was created", + "example": "2023-01-18T11:04:09.922Z" + } + } + }, "PaymentMethodSubType": { "type": "string", "enum": [ @@ -1405,7 +3601,9 @@ "items": { "$ref": "#/components/schemas/PaymentMethodSubType" }, - "example": ["credit"] + "example": [ + "credit" + ] }, "payment_method_issuers": { "type": "array", @@ -1413,7 +3611,9 @@ "type": "string", "description": "List of payment method issuers to be enabled for this payment method" }, - "example": ["HDFC"] + "example": [ + "HDFC" + ] }, "payment_schemes": { "type": "array", @@ -1421,14 +3621,22 @@ "type": "string", "description": "List of payment schemes accepted or has the processing capabilities of the processor" }, - "example": ["MASTER", "VISA", "DINERS"] + "example": [ + "MASTER", + "VISA", + "DINERS" + ] }, "accepted_currencies": { "type": "array", "items": { "$ref": "#/components/schemas/Currency" }, - "example": ["USD", "EUR", "AED"] + "example": [ + "USD", + "EUR", + "AED" + ] }, "accepted_countries": { "type": "array", @@ -1436,7 +3644,10 @@ "type": "string", "description": "List of Countries accepted or has the processing capabilities of the processor" }, - "example": ["US", "IN"] + "example": [ + "US", + "IN" + ] }, "minimum_amount": { "type": "integer", @@ -1467,7 +3678,9 @@ "items": { "$ref": "#/components/schemas/PaymentExperience" }, - "example": ["redirect_to_url"] + "example": [ + "redirect_to_url" + ] } } }, @@ -1635,7 +3848,8 @@ "example": "187282ab-40ef-47a9-9206-5099ba31e432" }, "card_cvc": { - "type": "string" + "type": "string", + "description": "This is used when payment is to be confirmed and the card is not saved" }, "shipping": { "$ref": "#/components/schemas/Address" @@ -1679,7 +3893,12 @@ }, "PaymentsResponse": { "type": "object", - "required": ["status", "amount", "currency", "payment_method"], + "required": [ + "status", + "amount", + "currency", + "payment_method" + ], "properties": { "payment_id": { "type": "string", @@ -1858,7 +4077,10 @@ }, "PaymentsRetrieveRequest": { "type": "object", - "required": ["resource_id", "force_sync"], + "required": [ + "resource_id", + "force_sync" + ], "properties": { "resource_id": { "$ref": "#/components/schemas/PaymentIdType" @@ -1883,7 +4105,11 @@ }, "PaymentsSessionRequest": { "type": "object", - "required": ["payment_id", "client_secret", "wallets"], + "required": [ + "payment_id", + "client_secret", + "wallets" + ], "properties": { "payment_id": { "type": "string", @@ -1903,7 +4129,11 @@ }, "PaymentsSessionResponse": { "type": "object", - "required": ["payment_id", "client_secret", "session_token"], + "required": [ + "payment_id", + "client_secret", + "session_token" + ], "properties": { "payment_id": { "type": "string", @@ -1923,7 +4153,11 @@ }, "PaymentsStartRequest": { "type": "object", - "required": ["payment_id", "merchant_id", "attempt_id"], + "required": [ + "payment_id", + "merchant_id", + "attempt_id" + ], "properties": { "payment_id": { "type": "string", @@ -1993,9 +4227,25 @@ } } }, + "RefundListResponse": { + "type": "object", + "required": [ + "data" + ], + "properties": { + "data": { + "type": "array", + "items": { + "$ref": "#/components/schemas/RefundResponse" + } + } + } + }, "RefundRequest": { "type": "object", - "required": ["payment_id"], + "required": [ + "payment_id" + ], "properties": { "refund_id": { "type": "string", @@ -2040,23 +4290,34 @@ }, "RefundResponse": { "type": "object", - "required": ["refund_id", "payment_id", "amount", "currency", "status"], + "required": [ + "refund_id", + "payment_id", + "amount", + "currency", + "status" + ], "properties": { "refund_id": { - "type": "string" + "type": "string", + "description": "The identifier for refund" }, "payment_id": { - "type": "string" + "type": "string", + "description": "The identifier for payment" }, "amount": { "type": "integer", - "format": "int64" + "format": "int64", + "description": "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" }, "currency": { - "type": "string" + "type": "string", + "description": "The three-letter ISO currency code" }, "reason": { - "type": "string" + "type": "string", + "description": "An arbitrary string attached to the object. Often useful for displaying to users and your customer support executive" }, "status": { "$ref": "#/components/schemas/RefundStatus" @@ -2065,28 +4326,41 @@ "type": "object" }, "error_message": { - "type": "string" + "type": "string", + "description": "The error message" }, "error_code": { - "type": "string" + "type": "string", + "description": "The code for the error" }, "created_at": { "type": "string", - "format": "date-time" + "format": "date-time", + "description": "The timestamp at which refund is created" }, "updated_at": { "type": "string", - "format": "date-time" + "format": "date-time", + "description": "The timestamp at which refund is updated" } } }, "RefundStatus": { "type": "string", - "enum": ["succeeded", "failed", "pending", "review"] + "description": "The status for refunds", + "enum": [ + "succeeded", + "failed", + "pending", + "review" + ] }, "RefundType": { "type": "string", - "enum": ["scheduled", "instant"] + "enum": [ + "scheduled", + "instant" + ] }, "RefundUpdateRequest": { "type": "object", @@ -2105,7 +4379,12 @@ "RoutingAlgorithm": { "type": "string", "description": "The routing algorithm to be used to process the incoming request from merchant to outgoing payment processor or payment method. The default is 'Custom'", - "enum": ["round_robin", "max_conversion", "min_cost", "custom"], + "enum": [ + "round_robin", + "max_conversion", + "min_cost", + "custom" + ], "example": "custom" }, "SessionToken": { @@ -2134,14 +4413,20 @@ }, "wallet_name": { "type": "string", - "enum": ["gpay"] + "enum": [ + "gpay" + ] } } }, { "type": "object", "description": "The session response structure for Klarna", - "required": ["session_token", "session_id", "wallet_name"], + "required": [ + "session_token", + "session_id", + "wallet_name" + ], "properties": { "session_token": { "type": "string", @@ -2153,14 +4438,19 @@ }, "wallet_name": { "type": "string", - "enum": ["klarna"] + "enum": [ + "klarna" + ] } } }, { "type": "object", "description": "The session response structure for PayPal", - "required": ["session_token", "wallet_name"], + "required": [ + "session_token", + "wallet_name" + ], "properties": { "session_token": { "type": "string", @@ -2168,7 +4458,9 @@ }, "wallet_name": { "type": "string", - "enum": ["paypal"] + "enum": [ + "paypal" + ] } } }, @@ -2239,7 +4531,9 @@ }, "wallet_name": { "type": "string", - "enum": ["applepay"] + "enum": [ + "applepay" + ] } } } @@ -2251,11 +4545,29 @@ "SupportedWallets": { "type": "string", "description": "Wallets which support obtaining session object", - "enum": ["paypal", "apple_pay", "klarna", "gpay"] + "enum": [ + "paypal", + "apple_pay", + "klarna", + "gpay" + ] + }, + "UpdatePaymentMethod": { + "type": "object", + "properties": { + "card": { + "$ref": "#/components/schemas/CardDetail" + }, + "metadata": { + "type": "object" + } + } }, "WalletData": { "type": "object", - "required": ["issuer_name"], + "required": [ + "issuer_name" + ], "properties": { "issuer_name": { "$ref": "#/components/schemas/WalletIssuer" @@ -2268,7 +4580,11 @@ }, "WalletIssuer": { "type": "string", - "enum": ["googlepay", "applepay", "paypal"] + "enum": [ + "googlepay", + "applepay", + "paypal" + ] }, "WebhookDetails": { "type": "object", @@ -2314,5 +4630,28 @@ } } } - } -} + }, + "tags": [ + { + "name": "Merchant Account" + }, + { + "name": "Merchant Connector Account" + }, + { + "name": "Payments" + }, + { + "name": "Refunds" + }, + { + "name": "Mandates" + }, + { + "name": "Customers" + }, + { + "name": "Payment Methods" + } + ] +} \ No newline at end of file