use std::num::NonZeroI64; use common_utils::pii; use masking::{PeekInterface, Secret}; use router_derive::Setter; use time::PrimitiveDateTime; use utoipa::ToSchema; use crate::{admin, enums as api_enums, refunds}; #[derive(Clone, Copy, Debug, Eq, PartialEq)] pub enum PaymentOp { Create, Update, Confirm, } #[derive(serde::Deserialize)] pub struct BankData { pub payment_method_type: api_enums::PaymentMethodType, pub code_information: Vec, } #[derive(serde::Deserialize)] pub struct BankCodeInformation { pub bank_name: api_enums::BankNames, pub connector_codes: Vec, } #[derive(serde::Deserialize)] pub struct ConnectorCode { pub connector: api_enums::Connector, pub code: String, } #[derive(Debug, Clone, serde::Serialize, serde::Deserialize, ToSchema, PartialEq, Eq)] pub struct BankCodeResponse { pub bank_name: Vec, pub eligible_connectors: Vec, } #[derive(Default, Debug, serde::Deserialize, serde::Serialize, Clone, ToSchema)] #[serde(deny_unknown_fields)] pub struct PaymentsRequest { /// Unique identifier for the payment. This ensures idempotency for multiple payments /// that have been done by a single merchant. This field is auto generated and is returned in the API response. #[schema( value_type = Option, min_length = 30, max_length = 30, example = "pay_mbabizu24mvu3mela5njyhpit4" )] #[serde(default, deserialize_with = "payment_id_type::deserialize_option")] pub payment_id: Option, /// This is an identifier for the merchant account. This is inferred from the API key /// provided during the request #[schema(max_length = 255, example = "merchant_1668273825")] pub merchant_id: Option, /// The payment amount. Amount for the payment in lowest denomination of the currency. (i.e) in cents for USD denomination, in paisa for INR denomination etc., #[schema(value_type = Option, example = 6540)] #[serde(default, deserialize_with = "amount::deserialize_option")] pub amount: Option, #[schema(value_type = Option, example = json!({ "type": "single", "data": "stripe" }))] pub routing: Option, /// This allows the merchant to manually select a connector with which the payment can go through #[schema(value_type = Option>, max_length = 255, example = json!(["stripe", "adyen"]))] pub connector: Option>, /// The currency of the payment request can be specified here #[schema(value_type = Option, example = "USD")] pub currency: Option, /// This is the instruction for capture/ debit the money from the users' card. On the other hand authorization refers to blocking the amount on the users' payment method. #[schema(value_type = Option, example = "PaymentProcessor")] pub capture_method: Option, /// The Amount to be captured/ debited from the users payment method. It shall be in lowest denomination of the currency. (i.e) in cents for USD denomination, in paisa for INR denomination etc., /// If not provided, the default amount_to_capture will be the payment amount. #[schema(example = 6540)] pub amount_to_capture: Option, /// A timestamp (ISO 8601 code) that determines when the payment should be captured. /// Providing this field will automatically set `capture` to true #[schema(example = "2022-09-10T10:11:12Z")] #[serde(default, with = "common_utils::custom_serde::iso8601::option")] pub capture_on: Option, /// Whether to confirm the payment (if applicable) #[schema(default = false, example = true)] pub confirm: Option, /// The identifier for the customer object. If not provided the customer ID will be autogenerated. #[schema(max_length = 255, example = "cus_y3oqhf46pyzuxjbcn2giaqnb44")] pub customer_id: Option, /// description: The customer's email address #[schema(max_length = 255, value_type = Option, example = "johntest@test.com")] pub email: Option>, /// description: The customer's name #[schema(value_type = Option, max_length = 255, example = "John Test")] pub name: Option>, /// The customer's phone number #[schema(value_type = Option, max_length = 255, example = "3141592653")] pub phone: Option>, /// The country code for the customer phone number #[schema(max_length = 255, example = "+1")] pub phone_country_code: Option, /// Set to true to indicate that the customer is not in your checkout flow during this payment, and therefore is unable to authenticate. This parameter is intended for scenarios where you collect card details and charge them later. This parameter can only be used with `confirm: true`. #[schema(example = true)] pub off_session: Option, /// A description of the payment #[schema(example = "It's my first payment request")] pub description: Option, /// The URL to redirect after the completion of the operation #[schema(value_type = Option, example = "https://hyperswitch.io")] pub return_url: Option, /// Indicates that you intend to make future payments with this Payment’s payment method. Providing this parameter will attach the payment method to the Customer, if present, after the Payment is confirmed and any required actions from the user are complete. #[schema(value_type = Option, example = "off_session")] pub setup_future_usage: Option, /// The transaction authentication can be set to undergo payer authentication. #[schema(value_type = Option, example = "no_three_ds", default = "three_ds")] pub authentication_type: Option, /// The payment method information provided for making a payment #[schema(example = "bank_transfer")] pub payment_method_data: Option, /// The payment method that is to be used #[schema(value_type = Option, example = "card")] pub payment_method: Option, /// 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 pub shipping: Option
, /// The billing address for the payment pub billing: Option
, /// For non-card charges, you can use this value as the complete description that appears on your customers’ statements. Must contain at least one letter, maximum 22 characters. #[schema(max_length = 255, example = "Hyperswitch Router")] pub statement_descriptor_name: Option, /// Provides information about a card payment that customers see on their statements. Concatenated with the prefix (shortened descriptor) or statement descriptor that’s set on the account to form the complete statement descriptor. Maximum 22 characters for the concatenated descriptor. #[schema(max_length = 255, example = "Payment for shoes purchase")] pub statement_descriptor_suffix: 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. pub metadata: Option, /// It's a token used for client side verification. #[schema(example = "pay_U42c409qyHwOkWo3vK60_secret_el9ksDkiB8hi6j9N78yo")] pub client_secret: Option, /// Provide mandate information for creating a mandate pub mandate_data: Option, /// A unique identifier to link the payment to a mandate, can be use instead of payment_method_data #[schema(max_length = 255, example = "mandate_iwer89rnjef349dni3")] pub mandate_id: Option, /// Additional details required by 3DS 2.0 #[schema(value_type = Option, example = r#"{ "user_agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/70.0.3538.110 Safari/537.36", "accept_header": "text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8", "language": "nl-NL", "color_depth": 24, "screen_height": 723, "screen_width": 1536, "time_zone": 0, "java_enabled": true, "java_script_enabled":true }"#)] pub browser_info: Option, /// Payment Experience for the current payment #[schema(value_type = Option, example = "redirect_to_url")] pub payment_experience: Option, /// Payment Method Type #[schema(value_type = Option, example = "google_pay")] pub payment_method_type: Option, /// Business country of the merchant for this payment #[schema(value_type = CountryAlpha2, example = "US")] pub business_country: Option, /// Business label of the merchant for this payment #[schema(example = "food")] pub business_label: Option, /// Merchant connector details used to make payments. pub merchant_connector_details: Option, /// Allowed Payment Method Types for a given PaymentIntent #[schema(value_type = Option>)] pub allowed_payment_method_types: Option>, /// Business sub label for the payment pub business_sub_label: Option, } #[derive(Default, Debug, serde::Deserialize, serde::Serialize, Clone, Copy, PartialEq, Eq)] pub enum Amount { Value(NonZeroI64), #[default] Zero, } impl From for i64 { fn from(amount: Amount) -> Self { match amount { Amount::Value(val) => val.get(), Amount::Zero => 0, } } } impl From for Amount { fn from(val: i64) -> Self { NonZeroI64::new(val).map_or(Self::Zero, Amount::Value) } } #[derive(Default, Debug, serde::Deserialize, serde::Serialize, Clone)] #[serde(deny_unknown_fields)] pub struct PaymentsRedirectRequest { pub payment_id: String, pub merchant_id: String, pub connector: String, pub param: String, } #[derive(Default, Debug, serde::Deserialize, serde::Serialize, Clone)] #[serde(deny_unknown_fields)] pub struct VerifyRequest { // The merchant_id is generated through api key // and is later passed in the struct pub merchant_id: Option, pub customer_id: Option, pub email: Option>, pub name: Option>, pub phone: Option>, pub phone_country_code: Option, pub payment_method: Option, pub payment_method_data: Option, pub payment_token: Option, pub mandate_data: Option, pub setup_future_usage: Option, pub off_session: Option, pub client_secret: Option, pub merchant_connector_details: Option, } impl From for VerifyRequest { fn from(item: PaymentsRequest) -> Self { Self { client_secret: item.client_secret, merchant_id: item.merchant_id, customer_id: item.customer_id, email: item.email, name: item.name, phone: item.phone, phone_country_code: item.phone_country_code, payment_method: item.payment_method, payment_method_data: item.payment_method_data, payment_token: item.payment_token, mandate_data: item.mandate_data, setup_future_usage: item.setup_future_usage, off_session: item.off_session, merchant_connector_details: item.merchant_connector_details, } } } #[derive(Clone)] pub enum MandateTxnType { NewMandateTxn, RecurringMandateTxn, } #[derive(Default, Eq, PartialEq, Debug, serde::Deserialize, serde::Serialize, Clone)] pub struct MandateIds { pub mandate_id: String, pub mandate_reference_id: Option, } #[derive(Eq, PartialEq, Debug, serde::Deserialize, serde::Serialize, Clone)] pub enum MandateReferenceId { ConnectorMandateId(String), // mandate_id send by connector NetworkMandateId(String), // network_txns_id send by Issuer to connector, Used for PG agnostic mandate txns } impl MandateIds { pub fn new(mandate_id: String) -> Self { Self { mandate_id, mandate_reference_id: None, } } } #[derive(Default, Eq, PartialEq, Debug, serde::Deserialize, serde::Serialize, Clone, ToSchema)] #[serde(deny_unknown_fields)] pub struct MandateData { /// A concent from the customer to store the payment method pub customer_acceptance: CustomerAcceptance, /// A way to select the type of mandate used pub mandate_type: MandateType, } #[derive(Clone, Eq, PartialEq, Copy, Debug, Default, serde::Serialize, serde::Deserialize)] pub struct SingleUseMandate { pub amount: i64, pub currency: api_enums::Currency, } #[derive(Clone, Eq, PartialEq, Debug, Default, ToSchema, serde::Serialize, serde::Deserialize)] pub struct MandateAmountData { /// The maximum amount to be debited for the mandate transaction #[schema(example = 6540)] pub amount: i64, /// The currency for the transaction #[schema(value_type = Currency, example = "USD")] pub currency: api_enums::Currency, /// Specifying start date of the mandate #[schema(example = "2022-09-10T00:00:00Z")] #[serde(default, with = "common_utils::custom_serde::iso8601::option")] pub start_date: Option, /// Specifying end date of the mandate #[schema(example = "2023-09-10T23:59:59Z")] #[serde(default, with = "common_utils::custom_serde::iso8601::option")] pub end_date: Option, /// Additional details required by mandate #[schema(value_type = Option, example = r#"{ "frequency": "DAILY" }"#)] pub metadata: Option, } #[derive(Eq, PartialEq, Debug, serde::Deserialize, serde::Serialize, Clone, ToSchema)] #[serde(rename_all = "snake_case")] pub enum MandateType { /// If the mandate should only be valid for 1 off-session use SingleUse(MandateAmountData), /// If the mandate should be valid for multiple debits MultiUse(Option), } impl Default for MandateType { fn default() -> Self { Self::MultiUse(None) } } #[derive(Default, Eq, PartialEq, Debug, serde::Deserialize, serde::Serialize, Clone, ToSchema)] #[serde(deny_unknown_fields)] pub struct CustomerAcceptance { /// Type of acceptance provided by the #[schema(example = "online")] pub acceptance_type: AcceptanceType, /// Specifying when the customer acceptance was provided #[schema(example = "2022-09-10T10:11:12Z")] #[serde(default, with = "common_utils::custom_serde::iso8601::option")] pub accepted_at: Option, /// Information required for online mandate generation pub online: Option, } #[derive(Default, Debug, serde::Deserialize, serde::Serialize, PartialEq, Eq, Clone, ToSchema)] #[serde(rename_all = "lowercase")] pub enum AcceptanceType { Online, #[default] Offline, } #[derive(Default, Eq, PartialEq, Debug, serde::Deserialize, serde::Serialize, Clone, ToSchema)] #[serde(deny_unknown_fields)] pub struct OnlineMandate { /// Ip address of the customer machine from which the mandate was created #[schema(value_type = String, example = "123.32.25.123")] pub ip_address: Secret, /// The user-agent of the customer's browser pub user_agent: String, } #[derive(Default, Eq, PartialEq, Clone, Debug, serde::Deserialize, serde::Serialize, ToSchema)] pub struct Card { /// The card number #[schema(value_type = String, example = "4242424242424242")] pub card_number: Secret, /// The card's expiry month #[schema(value_type = String, example = "24")] pub card_exp_month: Secret, /// The card's expiry year #[schema(value_type = String, example = "24")] pub card_exp_year: Secret, /// The card holder's name #[schema(value_type = String, example = "John Test")] pub card_holder_name: Secret, /// The CVC number for the card #[schema(value_type = String, example = "242")] pub card_cvc: Secret, /// The name of the issuer of card #[schema(example = "chase")] pub card_issuer: Option, /// The card network for the card #[schema(value_type = Option, example = "Visa")] pub card_network: Option, } #[derive(Eq, PartialEq, Clone, Debug, serde::Deserialize, serde::Serialize, ToSchema)] #[serde(rename_all = "snake_case")] pub enum PayLaterData { /// For KlarnaRedirect as PayLater Option KlarnaRedirect { /// The billing email #[schema(value_type = String)] billing_email: Secret, // The billing country code #[schema(value_type = CountryAlpha2, example = "US")] billing_country: api_enums::CountryAlpha2, }, /// For Klarna Sdk as PayLater Option KlarnaSdk { /// The token for the sdk workflow token: String, }, /// For Affirm redirect as PayLater Option AffirmRedirect {}, /// For AfterpayClearpay redirect as PayLater Option AfterpayClearpayRedirect { /// The billing email #[schema(value_type = String)] billing_email: Secret, /// The billing name #[schema(value_type = String)] billing_name: Secret, }, PayBright {}, Walley {}, } #[derive(serde::Deserialize, serde::Serialize, Debug, Clone, ToSchema, Eq, PartialEq)] #[serde(rename_all = "snake_case")] pub enum BankDebitData { /// Payment Method data for Ach bank debit AchBankDebit { /// Billing details for bank debit billing_details: BankDebitBilling, /// Account number for ach bank debit payment #[schema(value_type = String, example = "000123456789")] account_number: Secret, /// Routing number for ach bank debit payment #[schema(value_type = String, example = "110000000")] routing_number: Secret, }, SepaBankDebit { /// Billing details for bank debit billing_details: BankDebitBilling, /// International bank account number (iban) for SEPA #[schema(value_type = String, example = "DE89370400440532013000")] iban: Secret, }, BecsBankDebit { /// Billing details for bank debit billing_details: BankDebitBilling, /// Account number for Becs payment method #[schema(value_type = String, example = "000123456")] account_number: Secret, /// Bank-State-Branch (bsb) number #[schema(value_type = String, example = "000000")] bsb_number: Secret, }, BacsBankDebit { /// Billing details for bank debit billing_details: BankDebitBilling, /// Account number for Bacs payment method #[schema(value_type = String, example = "00012345")] account_number: Secret, /// Sort code for Bacs payment method #[schema(value_type = String, example = "108800")] sort_code: Secret, }, } #[derive(Debug, Clone, serde::Deserialize, serde::Serialize, ToSchema)] #[serde(rename_all = "snake_case")] pub enum PaymentMethodData { Card(Card), Wallet(WalletData), PayLater(PayLaterData), BankRedirect(BankRedirectData), BankDebit(BankDebitData), Crypto(CryptoData), } #[derive(Debug, Clone, Eq, PartialEq, serde::Deserialize, serde::Serialize)] #[serde(rename_all = "snake_case")] pub enum AdditionalPaymentData { Card { card_issuer: Option, card_network: Option, }, BankRedirect { bank_name: Option, }, Wallet {}, PayLater {}, Crypto {}, BankDebit {}, } impl From<&PaymentMethodData> for AdditionalPaymentData { fn from(pm_data: &PaymentMethodData) -> Self { match pm_data { PaymentMethodData::Card(card_data) => Self::Card { card_issuer: card_data.card_issuer.to_owned(), card_network: card_data .card_network .as_ref() .map(|card_network| card_network.to_string()), }, PaymentMethodData::BankRedirect(bank_redirect_data) => match bank_redirect_data { BankRedirectData::Eps { bank_name, .. } => Self::BankRedirect { bank_name: Some(bank_name.to_owned()), }, BankRedirectData::Ideal { bank_name, .. } => Self::BankRedirect { bank_name: Some(bank_name.to_owned()), }, _ => Self::BankRedirect { bank_name: None }, }, PaymentMethodData::Wallet(_) => Self::Wallet {}, PaymentMethodData::PayLater(_) => Self::PayLater {}, PaymentMethodData::Crypto(_) => Self::Crypto {}, PaymentMethodData::BankDebit(_) => Self::BankDebit {}, } } } #[derive(Debug, Clone, Eq, PartialEq, serde::Deserialize, serde::Serialize, ToSchema)] #[serde(rename_all = "snake_case")] pub enum BankRedirectData { BancontactCard { /// The card number #[schema(value_type = String, example = "4242424242424242")] card_number: Secret, /// The card's expiry month #[schema(value_type = String, example = "24")] card_exp_month: Secret, /// The card's expiry year #[schema(value_type = String, example = "24")] card_exp_year: Secret, /// The card holder's name #[schema(value_type = String, example = "John Test")] card_holder_name: Secret, }, Blik { // Blik Code blik_code: String, }, Eps { /// The billing details for bank redirection billing_details: BankRedirectBilling, /// The hyperswitch bank code for eps #[schema(value_type = BankNames, example = "triodos_bank")] bank_name: api_enums::BankNames, }, Giropay { /// The billing details for bank redirection billing_details: BankRedirectBilling, /// Bank account details for Giropay bank_account_bic: Option>, bank_account_iban: Option>, }, Ideal { /// The billing details for bank redirection billing_details: BankRedirectBilling, /// The hyperswitch bank code for ideal #[schema(value_type = BankNames, example = "abn_amro")] bank_name: api_enums::BankNames, }, OnlineBankingCzechRepublic { // Issuer banks issuer: api_enums::BankNames, }, OnlineBankingFinland { // Shopper Email email: Option>, }, OnlineBankingPoland { // Issuer banks issuer: api_enums::BankNames, }, OnlineBankingSlovakia { // Issuer value corresponds to the bank issuer: api_enums::BankNames, }, Przelewy24 {}, Sofort { /// The billing details for bank redirection billing_details: BankRedirectBilling, /// The country for bank payment #[schema(value_type = CountryAlpha2, example = "US")] country: api_enums::CountryAlpha2, /// The preferred language #[schema(example = "en")] preferred_language: String, }, Swish {}, Trustly {}, } #[derive(Debug, Clone, Eq, PartialEq, serde::Deserialize, serde::Serialize, ToSchema)] #[serde(rename_all = "snake_case")] pub struct CryptoData {} #[derive(Debug, Clone, Eq, PartialEq, serde::Deserialize, serde::Serialize, ToSchema)] pub struct SofortBilling { /// The country associated with the billing #[schema(value_type = CountryAlpha2, example = "US")] pub billing_country: String, } #[derive(Debug, Clone, Eq, PartialEq, serde::Deserialize, serde::Serialize, ToSchema)] pub struct BankRedirectBilling { /// The name for which billing is issued #[schema(value_type = String, example = "John Doe")] pub billing_name: Secret, } #[derive(serde::Deserialize, serde::Serialize, Debug, Clone, ToSchema, Eq, PartialEq)] pub struct BankDebitBilling { /// The billing name for bank debits #[schema(value_type = String, example = "John Doe")] pub name: Secret, /// The billing email for bank debits #[schema(value_type = String, example = "example@example.com")] pub email: Secret, /// The billing address for bank debits pub address: Option, } #[derive(Eq, PartialEq, Clone, Debug, serde::Deserialize, serde::Serialize, ToSchema)] #[serde(rename_all = "snake_case")] pub enum WalletData { /// The wallet data for Ali Pay redirect AliPay(AliPayRedirection), /// The wallet data for Apple pay ApplePay(ApplePayWalletData), /// The wallet data for Google pay GooglePay(GooglePayWalletData), MbWay(Box), /// The wallet data for MobilePay redirect MobilePay(Box), /// This is for paypal redirection PaypalRedirect(PaypalRedirection), /// The wallet data for Paypal PaypalSdk(PayPalWalletData), /// The wallet data for WeChat Pay Redirection WeChatPayRedirect(Box), } #[derive(Eq, PartialEq, Clone, Debug, serde::Deserialize, serde::Serialize, ToSchema)] #[serde(rename_all(serialize = "camelCase", deserialize = "snake_case"))] pub struct GooglePayWalletData { /// The type of payment method #[serde(rename = "type")] pub pm_type: String, /// User-facing message to describe the payment method that funds this transaction. pub description: String, /// The information of the payment method pub info: GooglePayPaymentMethodInfo, /// The tokenization data of Google pay pub tokenization_data: GpayTokenizationData, } #[derive(Eq, PartialEq, Clone, Debug, serde::Deserialize, serde::Serialize, ToSchema)] pub struct WeChatPayRedirection {} #[derive(Eq, PartialEq, Clone, Debug, serde::Deserialize, serde::Serialize, ToSchema)] pub struct PaypalRedirection {} #[derive(Eq, PartialEq, Clone, Debug, serde::Deserialize, serde::Serialize, ToSchema)] pub struct AliPayRedirection {} #[derive(Eq, PartialEq, Clone, Debug, serde::Deserialize, serde::Serialize, ToSchema)] pub struct MobilePayRedirection {} #[derive(Eq, PartialEq, Clone, Debug, serde::Deserialize, serde::Serialize, ToSchema)] pub struct MbWayRedirection { /// Telephone number of the shopper. Should be Portuguese phone number. pub telephone_number: Secret, } #[derive(Eq, PartialEq, Clone, Debug, serde::Deserialize, serde::Serialize, ToSchema)] #[serde(rename_all(serialize = "camelCase", deserialize = "snake_case"))] pub struct GooglePayPaymentMethodInfo { /// The name of the card network pub card_network: String, /// The details of the card pub card_details: String, } #[derive(Eq, PartialEq, Clone, Debug, serde::Deserialize, serde::Serialize, ToSchema)] pub struct PayPalWalletData { /// Token generated for the Apple pay pub token: String, } #[derive(Eq, PartialEq, Clone, Debug, serde::Deserialize, serde::Serialize, ToSchema)] pub struct GpayTokenizationData { /// The type of the token #[serde(rename = "type")] pub token_type: String, /// Token generated for the wallet pub token: String, } #[derive(Eq, PartialEq, Clone, Debug, serde::Deserialize, serde::Serialize, ToSchema)] pub struct ApplePayWalletData { /// The payment data of Apple pay pub payment_data: String, /// The payment method of Apple pay pub payment_method: ApplepayPaymentMethod, /// The unique identifier for the transaction pub transaction_identifier: String, } #[derive(Eq, PartialEq, Clone, Debug, serde::Deserialize, serde::Serialize, ToSchema)] pub struct ApplepayPaymentMethod { /// The name to be displayed on Apple Pay button pub display_name: String, /// The network of the Apple pay payment method pub network: String, /// The type of the payment method #[serde(rename = "type")] pub pm_type: String, } #[derive(Eq, PartialEq, Clone, Debug, serde::Serialize)] pub struct CardResponse { last4: String, exp_month: String, exp_year: String, } #[derive(Debug, Clone, Eq, PartialEq, serde::Serialize)] pub enum PaymentMethodDataResponse { #[serde(rename = "card")] Card(CardResponse), #[serde(rename(deserialize = "bank_transfer"))] BankTransfer, Wallet(WalletData), PayLater(PayLaterData), Paypal, BankRedirect(BankRedirectData), Crypto(CryptoData), BankDebit(BankDebitData), } #[derive(Debug, Clone, PartialEq, Eq, serde::Serialize, serde::Deserialize, ToSchema)] pub enum PaymentIdType { /// The identifier for payment intent PaymentIntentId(String), /// The identifier for connector transaction ConnectorTransactionId(String), /// The identifier for payment attempt PaymentAttemptId(String), } impl std::fmt::Display for PaymentIdType { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { match self { Self::PaymentIntentId(payment_id) => { write!(f, "payment_intent_id = \"{payment_id}\"") } Self::ConnectorTransactionId(connector_transaction_id) => write!( f, "connector_transaction_id = \"{connector_transaction_id}\"" ), Self::PaymentAttemptId(payment_attempt_id) => { write!(f, "payment_attempt_id = \"{payment_attempt_id}\"") } } } } impl Default for PaymentIdType { fn default() -> Self { Self::PaymentIntentId(Default::default()) } } #[derive( Default, Clone, Debug, Eq, PartialEq, ToSchema, serde::Deserialize, serde::Serialize, frunk::LabelledGeneric, )] #[serde(deny_unknown_fields)] pub struct Address { /// Provide the address details pub address: Option, pub phone: Option, } // used by customers also, could be moved outside #[derive( Clone, Default, Debug, Eq, serde::Deserialize, serde::Serialize, PartialEq, ToSchema, frunk::LabelledGeneric, )] #[serde(deny_unknown_fields)] pub struct AddressDetails { /// The address city #[schema(max_length = 50, example = "New York")] pub city: Option, /// The two-letter ISO country code for the address #[schema(value_type = Option, example = "US")] pub country: Option, /// The first line of the address #[schema(value_type = Option, max_length = 200, example = "123, King Street")] pub line1: Option>, /// The second line of the address #[schema(value_type = Option, max_length = 50, example = "Powelson Avenue")] pub line2: Option>, /// The third line of the address #[schema(value_type = Option, max_length = 50, example = "Bridgewater")] pub line3: Option>, /// The zip/postal code for the address #[schema(value_type = Option, max_length = 50, example = "08807")] pub zip: Option>, /// The address state #[schema(value_type = Option, example = "New York")] pub state: Option>, /// The first name for the address #[schema(value_type = Option, max_length = 255, example = "John")] pub first_name: Option>, /// The last name for the address #[schema(value_type = Option, max_length = 255, example = "Doe")] pub last_name: Option>, } #[derive( Debug, Clone, Default, Eq, PartialEq, ToSchema, serde::Deserialize, serde::Serialize, frunk::LabelledGeneric, )] pub struct PhoneDetails { /// The contact number #[schema(value_type = Option, example = "9999999999")] pub number: Option>, /// The country code attached to the number #[schema(example = "+1")] pub country_code: Option, } #[derive(Debug, Clone, Default, Eq, PartialEq, serde::Deserialize, ToSchema)] pub struct PaymentsCaptureRequest { /// The unique identifier for the payment pub payment_id: Option, /// The unique identifier for the merchant pub merchant_id: Option, /// The Amount to be captured/ debited from the user's payment method. pub amount_to_capture: Option, /// Decider to refund the uncaptured amount pub refund_uncaptured_amount: Option, /// Provides information about a card payment that customers see on their statements. pub statement_descriptor_suffix: Option, /// Concatenated with the statement descriptor suffix that’s set on the account to form the complete statement descriptor. pub statement_descriptor_prefix: Option, /// Merchant connector details used to make payments. pub merchant_connector_details: Option, } #[derive(Default, Clone, Debug, Eq, PartialEq, serde::Serialize)] pub struct UrlDetails { pub url: String, pub method: String, } #[derive(Default, Clone, Debug, Eq, PartialEq, serde::Serialize)] pub struct AuthenticationForStartResponse { pub authentication: UrlDetails, } #[derive(Clone, Debug, Eq, PartialEq, serde::Serialize, ToSchema)] #[serde(rename_all = "snake_case")] pub enum NextActionType { RedirectToUrl, DisplayQrCode, InvokeSdkClient, TriggerApi, } #[derive(Clone, Debug, Eq, PartialEq, serde::Serialize, ToSchema)] pub struct NextAction { /// Specifying the action type to be performed next #[serde(rename = "type")] pub next_action_type: NextActionType, /// Contains the url for redirection flow #[schema(example = "https://router.juspay.io/redirect/fakushdfjlksdfasklhdfj")] pub redirect_to_url: Option, } #[derive(Setter, Clone, Default, Debug, Eq, PartialEq, serde::Serialize, ToSchema)] pub struct PaymentsResponse { /// Unique identifier for the payment. This ensures idempotency for multiple payments /// that have been done by a single merchant. #[schema( min_length = 30, max_length = 30, example = "pay_mbabizu24mvu3mela5njyhpit4" )] pub payment_id: Option, /// This is an identifier for the merchant account. This is inferred from the API key /// provided during the request #[schema(max_length = 255, example = "merchant_1668273825")] pub merchant_id: Option, /// The status of the current payment that was made #[schema(value_type = IntentStatus, example = "failed", default = "requires_confirmation")] pub status: api_enums::IntentStatus, /// The payment amount. Amount for the payment in lowest denomination of the currency. (i.e) in cents for USD denomination, in paisa for INR denomination etc., #[schema(example = 100)] pub amount: i64, /// The maximum amount that could be captured from the payment #[schema(minimum = 100, example = 6540)] pub amount_capturable: Option, /// The amount which is already captured from the payment #[schema(minimum = 100, example = 6540)] pub amount_received: Option, /// The connector used for the payment #[schema(example = "stripe")] pub connector: Option, /// It's a token used for client side verification. #[schema(value_type = Option, example = "pay_U42c409qyHwOkWo3vK60_secret_el9ksDkiB8hi6j9N78yo")] pub client_secret: Option>, /// Time when the payment was created #[schema(example = "2022-09-10T10:11:12Z")] #[serde(with = "common_utils::custom_serde::iso8601::option")] pub created: Option, /// The currency of the amount of the payment #[schema(value_type = Currency, example = "USD")] pub currency: String, /// The identifier for the customer object. If not provided the customer ID will be autogenerated. #[schema(max_length = 255, example = "cus_y3oqhf46pyzuxjbcn2giaqnb44")] pub customer_id: Option, /// A description of the payment #[schema(example = "It's my first payment request")] pub description: Option, /// List of refund that happened on this intent #[schema(value_type = Option>)] pub refunds: Option>, /// A unique identifier to link the payment to a mandate, can be use instead of payment_method_data #[schema(max_length = 255, example = "mandate_iwer89rnjef349dni3")] pub mandate_id: Option, /// Provided mandate information for creating a mandate pub mandate_data: Option, /// Indicates that you intend to make future payments with this Payment’s payment method. Providing this parameter will attach the payment method to the Customer, if present, after the Payment is confirmed and any required actions from the user are complete. #[schema(value_type = Option, example = "off_session")] pub setup_future_usage: Option, /// Set to true to indicate that the customer is not in your checkout flow during this payment, and therefore is unable to authenticate. This parameter is intended for scenarios where you collect card details and charge them later. This parameter can only be used with confirm=true. #[schema(example = true)] pub off_session: Option, /// A timestamp (ISO 8601 code) that determines when the payment should be captured. /// Providing this field will automatically set `capture` to true #[schema(example = "2022-09-10T10:11:12Z")] #[serde(with = "common_utils::custom_serde::iso8601::option")] pub capture_on: Option, /// This is the instruction for capture/ debit the money from the users' card. On the other hand authorization refers to blocking the amount on the users' payment method. #[schema(value_type = Option, example = "PaymentProcessor")] pub capture_method: Option, /// The payment method that is to be used #[schema(value_type = PaymentMethodType, example = "bank_transfer")] #[auth_based] pub payment_method: Option, /// The payment method information provided for making a payment #[schema(value_type = Option, example = "bank_transfer")] #[auth_based] pub payment_method_data: Option, /// Provide a reference to a stored payment method #[schema(example = "187282ab-40ef-47a9-9206-5099ba31e432")] pub payment_token: Option, /// The shipping address for the payment pub shipping: Option
, /// The billing address for the payment pub billing: 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)] pub metadata: Option, /// description: The customer's email address #[schema(max_length = 255, value_type = Option, example = "johntest@test.com")] pub email: Option>, /// description: The customer's name #[schema(value_type = Option, max_length = 255, example = "John Test")] pub name: Option>, /// The customer's phone number #[schema(value_type = Option, max_length = 255, example = "3141592653")] pub phone: Option>, /// The URL to redirect after the completion of the operation #[schema(example = "https://hyperswitch.io")] pub return_url: Option, /// The transaction authentication can be set to undergo payer authentication. By default, the authentication will be marked as NO_THREE_DS #[schema(value_type = Option, example = "no_three_ds", default = "three_ds")] pub authentication_type: Option, /// For non-card charges, you can use this value as the complete description that appears on your customers’ statements. Must contain at least one letter, maximum 22 characters. #[schema(max_length = 255, example = "Hyperswitch Router")] pub statement_descriptor_name: Option, /// Provides information about a card payment that customers see on their statements. Concatenated with the prefix (shortened descriptor) or statement descriptor that’s set on the account to form the complete statement descriptor. Maximum 255 characters for the concatenated descriptor. #[schema(max_length = 255, example = "Payment for shoes purchase")] pub statement_descriptor_suffix: Option, /// Additional information required for redirection pub next_action: Option, /// If the payment was cancelled the reason provided here pub cancellation_reason: Option, /// If there was an error while calling the connectors the code is received here #[schema(example = "E0001")] pub error_code: Option, /// If there was an error while calling the connector the error message is received here #[schema(example = "Failed while verifying the card")] pub error_message: Option, /// Payment Experience for the current payment #[schema(value_type = Option, example = "redirect_to_url")] pub payment_experience: Option, /// Payment Method Type #[schema(value_type = Option, example = "gpay")] pub payment_method_type: Option, /// The connector used for this payment along with the country and business details #[schema(example = "stripe_US_food")] pub connector_label: Option, /// The business country of merchant for this payment pub business_country: api_enums::CountryAlpha2, /// The business label of merchant for this payment pub business_label: String, /// The business_sub_label for this payment pub business_sub_label: Option, /// Allowed Payment Method Types for a given PaymentIntent #[schema(value_type = Option>)] pub allowed_payment_method_types: Option>, } #[derive(Clone, Debug, serde::Deserialize, ToSchema)] #[serde(deny_unknown_fields)] pub struct PaymentListConstraints { /// The identifier for customer #[schema(example = "cus_meowuwunwiuwiwqw")] pub customer_id: Option, /// A cursor for use in pagination, fetch the next list after some object #[schema(example = "pay_fafa124123")] pub starting_after: Option, /// A cursor for use in pagination, fetch the previous list before some object #[schema(example = "pay_fafa124123")] pub ending_before: Option, /// limit on the number of objects to return #[schema(default = 10)] #[serde(default = "default_limit")] pub limit: i64, /// The time at which payment is created #[schema(example = "2022-09-10T10:11:12Z")] #[serde(default, with = "common_utils::custom_serde::iso8601::option")] pub created: Option, /// Time less than the payment created time #[schema(example = "2022-09-10T10:11:12Z")] #[serde( default, with = "common_utils::custom_serde::iso8601::option", rename = "created.lt" )] pub created_lt: Option, /// Time greater than the payment created time #[schema(example = "2022-09-10T10:11:12Z")] #[serde( default, with = "common_utils::custom_serde::iso8601::option", rename = "created.gt" )] pub created_gt: Option, /// Time less than or equals to the payment created time #[schema(example = "2022-09-10T10:11:12Z")] #[serde( default, with = "common_utils::custom_serde::iso8601::option", rename = "created.lte" )] pub created_lte: Option, /// Time greater than or equals to the payment created time #[schema(example = "2022-09-10T10:11:12Z")] #[serde(default, with = "common_utils::custom_serde::iso8601::option")] #[serde(rename = "created.gte")] pub created_gte: Option, } #[derive(Clone, Debug, serde::Serialize, ToSchema)] pub struct PaymentListResponse { /// The number of payments included in the list pub size: usize, // The list of payments response objects pub data: Vec, } #[derive(Setter, Clone, Default, Debug, serde::Serialize)] pub struct VerifyResponse { pub verify_id: Option, pub merchant_id: Option, // pub status: enums::VerifyStatus, pub client_secret: Option>, pub customer_id: Option, pub email: Option>, pub name: Option>, pub phone: Option>, pub mandate_id: Option, #[auth_based] pub payment_method: Option, #[auth_based] pub payment_method_data: Option, pub payment_token: Option, pub error_code: Option, pub error_message: Option, } fn default_limit() -> i64 { 10 } #[derive(Default, Debug, serde::Deserialize, serde::Serialize)] pub struct PaymentsRedirectionResponse { pub redirect_url: String, } pub struct MandateValidationFields { pub mandate_id: Option, pub confirm: Option, pub customer_id: Option, pub mandate_data: Option, pub setup_future_usage: Option, pub off_session: Option, } impl From<&PaymentsRequest> for MandateValidationFields { fn from(req: &PaymentsRequest) -> Self { Self { mandate_id: req.mandate_id.clone(), confirm: req.confirm, customer_id: req.customer_id.clone(), mandate_data: req.mandate_data.clone(), setup_future_usage: req.setup_future_usage, off_session: req.off_session, } } } impl From<&VerifyRequest> for MandateValidationFields { fn from(req: &VerifyRequest) -> Self { Self { mandate_id: None, confirm: Some(true), customer_id: req.customer_id.clone(), mandate_data: req.mandate_data.clone(), off_session: req.off_session, setup_future_usage: req.setup_future_usage, } } } impl From for VerifyResponse { fn from(item: VerifyRequest) -> Self { Self { merchant_id: item.merchant_id, customer_id: item.customer_id, email: item.email, name: item.name, phone: item.phone, payment_method: item.payment_method, payment_method_data: item .payment_method_data .map(PaymentMethodDataResponse::from), payment_token: item.payment_token, ..Default::default() } } } impl From for PaymentsSessionResponse { fn from(item: PaymentsSessionRequest) -> Self { let client_secret: Secret = Secret::new(item.client_secret); Self { session_token: vec![], payment_id: item.payment_id, client_secret, } } } impl From for PaymentsRequest { fn from(item: PaymentsStartRequest) -> Self { Self { payment_id: Some(PaymentIdType::PaymentIntentId(item.payment_id)), merchant_id: Some(item.merchant_id), ..Default::default() } } } 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] .to_string(), exp_month: card.card_exp_month.peek().clone(), exp_year: card.card_exp_year.peek().clone(), } } } impl From for PaymentMethodDataResponse { fn from(payment_method_data: PaymentMethodData) -> Self { match payment_method_data { PaymentMethodData::Card(card) => Self::Card(CardResponse::from(card)), PaymentMethodData::PayLater(pay_later_data) => Self::PayLater(pay_later_data), PaymentMethodData::Wallet(wallet_data) => Self::Wallet(wallet_data), PaymentMethodData::BankRedirect(bank_redirect_data) => { Self::BankRedirect(bank_redirect_data) } PaymentMethodData::Crypto(crpto_data) => Self::Crypto(crpto_data), PaymentMethodData::BankDebit(bank_debit_data) => Self::BankDebit(bank_debit_data), } } } #[derive(Debug, Clone, serde::Serialize)] pub struct PgRedirectResponse { pub payment_id: String, pub status: api_enums::IntentStatus, pub gateway_id: String, pub customer_id: Option, pub amount: Option, } #[derive(Debug, serde::Serialize, PartialEq, Eq, serde::Deserialize)] pub struct RedirectionResponse { pub return_url: String, pub params: Vec<(String, String)>, pub return_url_with_query_params: String, pub http_method: String, pub headers: Vec<(String, String)>, } #[derive(Debug, serde::Deserialize)] pub struct PaymentsResponseForm { pub transaction_id: String, // pub transaction_reference_id: String, pub merchant_id: String, pub order_id: String, } #[derive(Default, Debug, serde::Deserialize, serde::Serialize, Clone, ToSchema)] pub struct PaymentsRetrieveRequest { /// The type of ID (ex: payment intent id, payment attempt id or connector txn id) pub resource_id: PaymentIdType, /// The identifier for the Merchant Account. pub merchant_id: Option, /// Decider to enable or disable the connector call for retrieve request pub force_sync: bool, /// The parameters passed to a retrieve request pub param: Option, /// The name of the connector pub connector: Option, /// Merchant connector details used to make payments. pub merchant_connector_details: Option, } #[derive(Debug, Default, Eq, PartialEq, serde::Deserialize, serde::Serialize, Clone, ToSchema)] pub struct OrderDetails { /// Name of the product that is being purchased #[schema(max_length = 255, example = "shirt")] pub product_name: String, /// The quantity of the product to be purchased #[schema(example = 1)] pub quantity: u16, } #[derive(Default, Debug, Eq, PartialEq, serde::Deserialize, serde::Serialize, Clone, ToSchema)] pub struct Metadata { /// Information about the product and quantity for specific connectors. (e.g. Klarna) pub order_details: Option, /// Any other metadata that is to be provided #[schema(value_type = Object, example = r#"{ "city": "NY", "unit": "245" }"#)] #[serde(flatten)] pub data: pii::SecretSerdeValue, /// Payload coming in request as a metadata field pub payload: Option, /// Allowed payment method types for a payment intent #[schema(value_type = Option>)] pub allowed_payment_method_types: Option>, } #[derive(Debug, serde::Deserialize, serde::Serialize, Clone, ToSchema)] pub struct PaymentsSessionRequest { /// The identifier for the payment pub payment_id: String, /// This is a token which expires after 15 minutes, used from the client to authenticate and create sessions from the SDK pub client_secret: String, /// The list of the supported wallets #[schema(value_type = Vec)] pub wallets: Vec, /// Merchant connector details used to make payments. pub merchant_connector_details: Option, } #[derive(Debug, Clone, serde::Serialize, serde::Deserialize, ToSchema)] pub struct GpayAllowedMethodsParameters { /// The list of allowed auth methods (ex: 3DS, No3DS, PAN_ONLY etc) pub allowed_auth_methods: Vec, /// The list of allowed card networks (ex: AMEX,JCB etc) pub allowed_card_networks: Vec, } #[derive(Debug, Clone, serde::Serialize, serde::Deserialize, ToSchema)] pub struct GpayTokenParameters { /// The name of the connector pub gateway: String, /// The merchant ID registered in the connector associated pub gateway_merchant_id: String, } #[derive(Debug, Clone, serde::Serialize, serde::Deserialize, ToSchema)] pub struct GpayTokenizationSpecification { /// The token specification type(ex: PAYMENT_GATEWAY) #[serde(rename = "type")] pub token_specification_type: String, /// The parameters for the token specification Google Pay pub parameters: GpayTokenParameters, } #[derive(Debug, Clone, serde::Serialize, serde::Deserialize, ToSchema)] pub struct GpayAllowedPaymentMethods { /// The type of payment method #[serde(rename = "type")] pub payment_method_type: String, /// The parameters Google Pay requires pub parameters: GpayAllowedMethodsParameters, /// The tokenization specification for Google Pay pub tokenization_specification: GpayTokenizationSpecification, } #[derive(Debug, Clone, serde::Serialize, serde::Deserialize, ToSchema)] pub struct GpayTransactionInfo { /// The country code #[schema(value_type = CountryAlpha2, example = "US")] pub country_code: api_enums::CountryAlpha2, /// The currency code pub currency_code: String, /// The total price status (ex: 'FINAL') pub total_price_status: String, /// The total price pub total_price: i64, } #[derive(Debug, Clone, serde::Serialize, serde::Deserialize, ToSchema)] pub struct GpayMerchantInfo { /// The name of the merchant pub merchant_name: String, } #[derive(Debug, Clone, serde::Serialize, serde::Deserialize)] pub struct GpayMetaData { pub merchant_info: GpayMerchantInfo, pub allowed_payment_methods: Vec, } #[derive(Debug, Clone, serde::Serialize, serde::Deserialize)] pub struct GpaySessionTokenData { #[serde(rename = "google_pay")] pub data: GpayMetaData, } #[derive(Debug, Clone, serde::Serialize, serde::Deserialize)] #[serde(rename_all = "camelCase")] pub struct ApplepaySessionRequest { pub merchant_identifier: String, pub display_name: String, pub initiative: String, pub initiative_context: String, } #[derive(Debug, Clone, serde::Serialize, serde::Deserialize)] pub struct ApplepaySessionTokenData { #[serde(rename = "apple_pay")] pub data: ApplePayMetadata, } #[derive(Debug, Clone, serde::Serialize, serde::Deserialize)] pub struct ApplePayMetadata { pub payment_request_data: PaymentRequestMetadata, pub session_token_data: SessionTokenInfo, } #[derive(Debug, Clone, serde::Serialize, serde::Deserialize)] pub struct PaymentRequestMetadata { pub supported_networks: Vec, pub merchant_capabilities: Vec, pub label: String, } #[derive(Debug, Clone, serde::Serialize, serde::Deserialize)] pub struct SessionTokenInfo { pub certificate: String, pub certificate_keys: String, pub merchant_identifier: String, pub display_name: String, pub initiative: String, pub initiative_context: String, } #[derive(Debug, Clone, serde::Serialize, ToSchema)] #[serde(tag = "wallet_name")] #[serde(rename_all = "snake_case")] pub enum SessionToken { /// The session response structure for Google Pay GooglePay(Box), /// The session response structure for Klarna Klarna(Box), /// The session response structure for PayPal Paypal(Box), /// The session response structure for Apple Pay ApplePay(Box), } #[derive(Debug, Clone, serde::Serialize, ToSchema)] #[serde(rename_all = "lowercase")] pub struct GpaySessionTokenResponse { /// The merchant info pub merchant_info: GpayMerchantInfo, /// List of the allowed payment meythods pub allowed_payment_methods: Vec, /// The transaction info Google Pay requires pub transaction_info: GpayTransactionInfo, pub connector: String, } #[derive(Debug, Clone, serde::Serialize, ToSchema)] #[serde(rename_all = "lowercase")] pub struct KlarnaSessionTokenResponse { /// The session token for Klarna pub session_token: String, /// The identifier for the session pub session_id: String, } #[derive(Debug, Clone, serde::Serialize, ToSchema)] #[serde(rename_all = "lowercase")] pub struct PaypalSessionTokenResponse { /// The session token for PayPal pub session_token: String, } #[derive(Debug, Clone, serde::Serialize, ToSchema)] #[serde(rename_all = "lowercase")] pub struct ApplepaySessionTokenResponse { /// Session object for Apple Pay pub session_token_data: ApplePaySessionResponse, /// Payment request object for Apple Pay pub payment_request_data: ApplePayPaymentRequest, pub connector: String, } #[derive(Debug, Clone, serde::Serialize, ToSchema, serde::Deserialize)] #[serde(rename_all = "camelCase")] pub struct ApplePaySessionResponse { /// Timestamp at which session is requested pub epoch_timestamp: u64, /// Timestamp at which session expires pub expires_at: u64, /// The identifier for the merchant session pub merchant_session_identifier: String, /// Apple pay generated unique ID (UUID) value pub nonce: String, /// The identifier for the merchant pub merchant_identifier: String, /// The domain name of the merchant which is registered in Apple Pay pub domain_name: String, /// The name to be displayed on Apple Pay button pub display_name: String, /// A string which represents the properties of a payment pub signature: String, /// The identifier for the operational analytics pub operational_analytics_identifier: String, /// The number of retries to get the session response pub retries: u8, /// The identifier for the connector transaction pub psp_id: String, } #[derive(Debug, Clone, serde::Serialize, ToSchema, serde::Deserialize)] pub struct ApplePayPaymentRequest { /// The code for country #[schema(value_type = CountryAlpha2, example = "US")] pub country_code: api_enums::CountryAlpha2, /// The code for currency pub currency_code: String, /// Represents the total for the payment. pub total: AmountInfo, /// The list of merchant capabilities(ex: whether capable of 3ds or no-3ds) pub merchant_capabilities: Vec, /// The list of supported networks pub supported_networks: Vec, pub merchant_identifier: String, } #[derive(Debug, Clone, serde::Serialize, ToSchema, serde::Deserialize)] pub struct AmountInfo { /// The label must be the name of the merchant. pub label: String, /// A value that indicates whether the line item(Ex: total, tax, discount, or grand total) is final or pending. #[serde(rename = "type")] pub total_type: String, /// The total amount for the payment pub amount: String, } #[derive(Debug, Clone, serde::Deserialize)] #[serde(rename_all = "camelCase")] pub struct ApplepayErrorResponse { pub status_code: String, pub status_message: String, } #[derive(Default, Debug, serde::Serialize, Clone, ToSchema)] pub struct PaymentsSessionResponse { /// The identifier for the payment pub payment_id: String, /// This is a token which expires after 15 minutes, used from the client to authenticate and create sessions from the SDK #[schema(value_type = String)] pub client_secret: Secret, /// The list of session token object pub session_token: Vec, } #[derive(Default, Debug, serde::Deserialize, serde::Serialize, Clone, ToSchema)] pub struct PaymentRetrieveBody { /// The identifier for the Merchant Account. pub merchant_id: Option, /// Decider to enable or disable the connector call for retrieve request pub force_sync: Option, } #[derive(Default, Debug, serde::Deserialize, serde::Serialize, Clone, ToSchema)] pub struct PaymentRetrieveBodyWithCredentials { /// The identifier for payment. pub payment_id: String, /// The identifier for the Merchant Account. pub merchant_id: Option, /// Decider to enable or disable the connector call for retrieve request pub force_sync: Option, /// Merchant connector details used to make payments. pub merchant_connector_details: Option, } #[derive(Default, Debug, serde::Deserialize, serde::Serialize, Clone, ToSchema)] pub struct PaymentsCancelRequest { /// The identifier for the payment #[serde(skip)] pub payment_id: String, /// The reason for the payment cancel pub cancellation_reason: Option, /// Merchant connector details used to make payments. pub merchant_connector_details: Option, } #[derive(Default, Debug, serde::Deserialize, serde::Serialize, ToSchema)] pub struct PaymentsStartRequest { /// Unique identifier for the payment. This ensures idempotency for multiple payments /// that have been done by a single merchant. This field is auto generated and is returned in the API response. pub payment_id: String, /// The identifier for the Merchant Account. pub merchant_id: String, /// The identifier for the payment transaction pub attempt_id: String, } mod payment_id_type { use std::fmt; use serde::{ de::{self, Visitor}, Deserializer, }; use super::PaymentIdType; struct PaymentIdVisitor; struct OptionalPaymentIdVisitor; impl<'de> Visitor<'de> for PaymentIdVisitor { type Value = PaymentIdType; fn expecting(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result { formatter.write_str("payment id") } fn visit_str(self, value: &str) -> Result where E: de::Error, { Ok(PaymentIdType::PaymentIntentId(value.to_string())) } } impl<'de> Visitor<'de> for OptionalPaymentIdVisitor { type Value = Option; fn expecting(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result { formatter.write_str("payment id") } fn visit_some(self, deserializer: D) -> Result where D: Deserializer<'de>, { deserializer.deserialize_any(PaymentIdVisitor).map(Some) } fn visit_none(self) -> Result where E: de::Error, { Ok(None) } fn visit_unit(self) -> Result where E: de::Error, { Ok(None) } } #[allow(dead_code)] pub(crate) fn deserialize<'a, D>(deserializer: D) -> Result where D: Deserializer<'a>, { deserializer.deserialize_any(PaymentIdVisitor) } pub(crate) fn deserialize_option<'a, D>( deserializer: D, ) -> Result, D::Error> where D: Deserializer<'a>, { deserializer.deserialize_option(OptionalPaymentIdVisitor) } } mod amount { use serde::de; use super::Amount; struct AmountVisitor; struct OptionalAmountVisitor; // This is defined to provide guarded deserialization of amount // which itself handles zero and non-zero values internally impl<'de> de::Visitor<'de> for AmountVisitor { type Value = Amount; fn expecting(&self, formatter: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { write!(formatter, "amount as integer") } fn visit_u64(self, v: u64) -> Result where E: de::Error, { let v = i64::try_from(v).map_err(|_| { E::custom(format!( "invalid value `{v}`, expected an integer between 0 and {}", i64::MAX )) })?; self.visit_i64(v) } fn visit_i64(self, v: i64) -> Result where E: de::Error, { if v.is_negative() { return Err(E::custom(format!( "invalid value `{v}`, expected a positive integer" ))); } Ok(Amount::from(v)) } } impl<'de> de::Visitor<'de> for OptionalAmountVisitor { type Value = Option; fn expecting(&self, formatter: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { write!(formatter, "option of amount (as integer)") } fn visit_some(self, deserializer: D) -> Result where D: serde::Deserializer<'de>, { deserializer.deserialize_i64(AmountVisitor).map(Some) } fn visit_none(self) -> Result where E: de::Error, { Ok(None) } } #[allow(dead_code)] pub(crate) fn deserialize<'de, D>(deserializer: D) -> Result where D: de::Deserializer<'de>, { deserializer.deserialize_any(AmountVisitor) } pub(crate) fn deserialize_option<'de, D>(deserializer: D) -> Result, D::Error> where D: de::Deserializer<'de>, { deserializer.deserialize_option(OptionalAmountVisitor) } } #[cfg(test)] mod tests { #![allow(clippy::unwrap_used)] use super::*; #[test] fn test_mandate_type() { let mandate_type = MandateType::default(); assert_eq!( serde_json::to_string(&mandate_type).unwrap(), r#"{"multi_use":null}"# ) } }