mirror of
				https://github.com/juspay/hyperswitch.git
				synced 2025-11-01 02:57:02 +08:00 
			
		
		
		
	feat(documentation): add polymorphic generate_schema macro (#1183)
				
					
				
			Co-authored-by: pixincreate@work <69745008+pixincreate@users.noreply.github.com>
This commit is contained in:
		| @ -321,7 +321,9 @@ impl From<StraightThroughAlgorithm> for StraightThroughAlgorithmSerde { | |||||||
| #[derive(Clone, Debug, Deserialize, ToSchema, Serialize)] | #[derive(Clone, Debug, Deserialize, ToSchema, Serialize)] | ||||||
| #[serde(deny_unknown_fields)] | #[serde(deny_unknown_fields)] | ||||||
| pub struct PrimaryBusinessDetails { | pub struct PrimaryBusinessDetails { | ||||||
|  |     #[schema(value_type = CountryAlpha2)] | ||||||
|     pub country: api_enums::CountryAlpha2, |     pub country: api_enums::CountryAlpha2, | ||||||
|  |     #[schema(example = "food")] | ||||||
|     pub business: String, |     pub business: String, | ||||||
| } | } | ||||||
|  |  | ||||||
| @ -452,10 +454,12 @@ pub struct MerchantConnectorCreate { | |||||||
|     pub frm_configs: Option<FrmConfigs>, |     pub frm_configs: Option<FrmConfigs>, | ||||||
|  |  | ||||||
|     /// Business Country of the connector |     /// Business Country of the connector | ||||||
|     #[schema(value_type = CountryAlpha2, example = "US")] |  | ||||||
|     #[cfg(feature = "multiple_mca")] |     #[cfg(feature = "multiple_mca")] | ||||||
|  |     #[schema(value_type = CountryAlpha2, example = "US")] | ||||||
|     pub business_country: api_enums::CountryAlpha2, |     pub business_country: api_enums::CountryAlpha2, | ||||||
|  |  | ||||||
|     #[cfg(not(feature = "multiple_mca"))] |     #[cfg(not(feature = "multiple_mca"))] | ||||||
|  |     #[schema(value_type = Option<CountryAlpha2>, example = "US")] | ||||||
|     pub business_country: Option<api_enums::CountryAlpha2>, |     pub business_country: Option<api_enums::CountryAlpha2>, | ||||||
|  |  | ||||||
|     ///Business Type of the merchant |     ///Business Type of the merchant | ||||||
| @ -633,7 +637,11 @@ pub struct FrmConfigs { | |||||||
|     pub frm_enabled_pms: Option<Vec<String>>, |     pub frm_enabled_pms: Option<Vec<String>>, | ||||||
|     pub frm_enabled_pm_types: Option<Vec<String>>, |     pub frm_enabled_pm_types: Option<Vec<String>>, | ||||||
|     pub frm_enabled_gateways: Option<Vec<String>>, |     pub frm_enabled_gateways: Option<Vec<String>>, | ||||||
|     pub frm_action: api_enums::FrmAction, //What should be the action if FRM declines the txn (autorefund/cancel txn/manual review) |     /// What should be the action if FRM declines the txn (autorefund/cancel txn/manual review) | ||||||
|  |     #[schema(value_type = FrmAction)] | ||||||
|  |     pub frm_action: api_enums::FrmAction, | ||||||
|  |     /// Whether to make a call to the FRM before or after the payment | ||||||
|  |     #[schema(value_type = FrmPreferredFlowTypes)] | ||||||
|     pub frm_preferred_flow_type: api_enums::FrmPreferredFlowTypes, |     pub frm_preferred_flow_type: api_enums::FrmPreferredFlowTypes, | ||||||
| } | } | ||||||
| /// Details of all the payment methods enabled for the connector for the given merchant account | /// Details of all the payment methods enabled for the connector for the given merchant account | ||||||
| @ -657,7 +665,9 @@ pub struct PaymentMethodsEnabled { | |||||||
|     rename_all = "snake_case" |     rename_all = "snake_case" | ||||||
| )] | )] | ||||||
| pub enum AcceptedCurrencies { | pub enum AcceptedCurrencies { | ||||||
|  |     #[schema(value_type = Vec<Currency>)] | ||||||
|     EnableOnly(Vec<api_enums::Currency>), |     EnableOnly(Vec<api_enums::Currency>), | ||||||
|  |     #[schema(value_type = Vec<Currency>)] | ||||||
|     DisableOnly(Vec<api_enums::Currency>), |     DisableOnly(Vec<api_enums::Currency>), | ||||||
|     AllAccepted, |     AllAccepted, | ||||||
| } | } | ||||||
| @ -670,7 +680,9 @@ pub enum AcceptedCurrencies { | |||||||
|     rename_all = "snake_case" |     rename_all = "snake_case" | ||||||
| )] | )] | ||||||
| pub enum AcceptedCountries { | pub enum AcceptedCountries { | ||||||
|  |     #[schema(value_type = Vec<CountryAlpha2>)] | ||||||
|     EnableOnly(Vec<api_enums::CountryAlpha2>), |     EnableOnly(Vec<api_enums::CountryAlpha2>), | ||||||
|  |     #[schema(value_type = Vec<CountryAlpha2>)] | ||||||
|     DisableOnly(Vec<api_enums::CountryAlpha2>), |     DisableOnly(Vec<api_enums::CountryAlpha2>), | ||||||
|     AllAccepted, |     AllAccepted, | ||||||
| } | } | ||||||
|  | |||||||
| @ -42,7 +42,16 @@ pub struct BankCodeResponse { | |||||||
|     pub eligible_connectors: Vec<String>, |     pub eligible_connectors: Vec<String>, | ||||||
| } | } | ||||||
|  |  | ||||||
| #[derive(Default, Debug, serde::Deserialize, serde::Serialize, Clone, ToSchema)] | #[derive( | ||||||
|  |     Default, | ||||||
|  |     Debug, | ||||||
|  |     serde::Deserialize, | ||||||
|  |     serde::Serialize, | ||||||
|  |     Clone, | ||||||
|  |     ToSchema, | ||||||
|  |     router_derive::PolymorphicSchema, | ||||||
|  | )] | ||||||
|  | #[generate_schemas(PaymentsCreateRequest)] | ||||||
| #[serde(deny_unknown_fields)] | #[serde(deny_unknown_fields)] | ||||||
| pub struct PaymentsRequest { | pub struct PaymentsRequest { | ||||||
|     /// Unique identifier for the payment. This ensures idempotency for multiple payments |     /// Unique identifier for the payment. This ensures idempotency for multiple payments | ||||||
| @ -64,6 +73,8 @@ pub struct PaymentsRequest { | |||||||
|     /// 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., |     /// 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<u64>, example = 6540)] |     #[schema(value_type = Option<u64>, example = 6540)] | ||||||
|     #[serde(default, deserialize_with = "amount::deserialize_option")] |     #[serde(default, deserialize_with = "amount::deserialize_option")] | ||||||
|  |     #[mandatory_in(PaymentsCreateRequest)] | ||||||
|  |     // Makes the field mandatory in PaymentsCreateRequest | ||||||
|     pub amount: Option<Amount>, |     pub amount: Option<Amount>, | ||||||
|  |  | ||||||
|     #[schema(value_type = Option<RoutingAlgorithm>, example = json!({ |     #[schema(value_type = Option<RoutingAlgorithm>, example = json!({ | ||||||
| @ -78,6 +89,7 @@ pub struct PaymentsRequest { | |||||||
|  |  | ||||||
|     /// The currency of the payment request can be specified here |     /// The currency of the payment request can be specified here | ||||||
|     #[schema(value_type = Option<Currency>, example = "USD")] |     #[schema(value_type = Option<Currency>, example = "USD")] | ||||||
|  |     #[mandatory_in(PaymentsCreateRequest)] | ||||||
|     pub currency: Option<api_enums::Currency>, |     pub currency: Option<api_enums::Currency>, | ||||||
|  |  | ||||||
|     /// 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. |     /// 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. | ||||||
| @ -205,7 +217,7 @@ pub struct PaymentsRequest { | |||||||
|     pub payment_method_type: Option<api_enums::PaymentMethodType>, |     pub payment_method_type: Option<api_enums::PaymentMethodType>, | ||||||
|  |  | ||||||
|     /// Business country of the merchant for this payment |     /// Business country of the merchant for this payment | ||||||
|     #[schema(value_type = CountryAlpha2, example = "US")] |     #[schema(value_type = Option<CountryAlpha2>, example = "US")] | ||||||
|     pub business_country: Option<api_enums::CountryAlpha2>, |     pub business_country: Option<api_enums::CountryAlpha2>, | ||||||
|  |  | ||||||
|     /// Business label of the merchant for this payment |     /// Business label of the merchant for this payment | ||||||
| @ -213,6 +225,7 @@ pub struct PaymentsRequest { | |||||||
|     pub business_label: Option<String>, |     pub business_label: Option<String>, | ||||||
|  |  | ||||||
|     /// Merchant connector details used to make payments. |     /// Merchant connector details used to make payments. | ||||||
|  |     #[schema(value_type = Option<MerchantConnectorDetailsWrap>)] | ||||||
|     pub merchant_connector_details: Option<admin::MerchantConnectorDetailsWrap>, |     pub merchant_connector_details: Option<admin::MerchantConnectorDetailsWrap>, | ||||||
|  |  | ||||||
|     /// Allowed Payment Method Types for a given PaymentIntent |     /// Allowed Payment Method Types for a given PaymentIntent | ||||||
| @ -637,7 +650,13 @@ pub enum BankRedirectData { | |||||||
|         /// The billing details for bank redirection |         /// The billing details for bank redirection | ||||||
|         billing_details: BankRedirectBilling, |         billing_details: BankRedirectBilling, | ||||||
|         /// Bank account details for Giropay |         /// Bank account details for Giropay | ||||||
|  |  | ||||||
|  |         #[schema(value_type = Option<String>)] | ||||||
|  |         /// Bank account bic code | ||||||
|         bank_account_bic: Option<Secret<String>>, |         bank_account_bic: Option<Secret<String>>, | ||||||
|  |  | ||||||
|  |         /// Bank account iban | ||||||
|  |         #[schema(value_type = Option<String>)] | ||||||
|         bank_account_iban: Option<Secret<String>>, |         bank_account_iban: Option<Secret<String>>, | ||||||
|     }, |     }, | ||||||
|     Ideal { |     Ideal { | ||||||
| @ -653,26 +672,32 @@ pub enum BankRedirectData { | |||||||
|         #[schema(value_type = CountryAlpha2, example = "US")] |         #[schema(value_type = CountryAlpha2, example = "US")] | ||||||
|         country: api_enums::CountryAlpha2, |         country: api_enums::CountryAlpha2, | ||||||
|  |  | ||||||
|  |         #[schema(value_type = String, example = "john.doe@example.com")] | ||||||
|         email: Email, |         email: Email, | ||||||
|     }, |     }, | ||||||
|     OnlineBankingCzechRepublic { |     OnlineBankingCzechRepublic { | ||||||
|         // Issuer banks |         // Issuer banks | ||||||
|  |         #[schema(value_type = BankNames)] | ||||||
|         issuer: api_enums::BankNames, |         issuer: api_enums::BankNames, | ||||||
|     }, |     }, | ||||||
|     OnlineBankingFinland { |     OnlineBankingFinland { | ||||||
|         // Shopper Email |         // Shopper Email | ||||||
|  |         #[schema(value_type = Option<String>)] | ||||||
|         email: Option<Email>, |         email: Option<Email>, | ||||||
|     }, |     }, | ||||||
|     OnlineBankingPoland { |     OnlineBankingPoland { | ||||||
|         // Issuer banks |         // Issuer banks | ||||||
|  |         #[schema(value_type = BankNames)] | ||||||
|         issuer: api_enums::BankNames, |         issuer: api_enums::BankNames, | ||||||
|     }, |     }, | ||||||
|     OnlineBankingSlovakia { |     OnlineBankingSlovakia { | ||||||
|         // Issuer value corresponds to the bank |         // Issuer value corresponds to the bank | ||||||
|  |         #[schema(value_type = BankNames)] | ||||||
|         issuer: api_enums::BankNames, |         issuer: api_enums::BankNames, | ||||||
|     }, |     }, | ||||||
|     Przelewy24 { |     Przelewy24 { | ||||||
|         //Issuer banks |         //Issuer banks | ||||||
|  |         #[schema(value_type = Option<BankNames>)] | ||||||
|         bank_name: Option<api_enums::BankNames>, |         bank_name: Option<api_enums::BankNames>, | ||||||
|  |  | ||||||
|         // The billing details for bank redirect |         // The billing details for bank redirect | ||||||
| @ -796,6 +821,7 @@ pub struct MobilePayRedirection {} | |||||||
| #[derive(Eq, PartialEq, Clone, Debug, serde::Deserialize, serde::Serialize, ToSchema)] | #[derive(Eq, PartialEq, Clone, Debug, serde::Deserialize, serde::Serialize, ToSchema)] | ||||||
| pub struct MbWayRedirection { | pub struct MbWayRedirection { | ||||||
|     /// Telephone number of the shopper. Should be Portuguese phone number. |     /// Telephone number of the shopper. Should be Portuguese phone number. | ||||||
|  |     #[schema(value_type = String)] | ||||||
|     pub telephone_number: Secret<String>, |     pub telephone_number: Secret<String>, | ||||||
| } | } | ||||||
|  |  | ||||||
| @ -1008,6 +1034,7 @@ pub struct PaymentsCaptureRequest { | |||||||
|     /// Concatenated with the statement descriptor suffix that’s set on the account to form the complete statement descriptor. |     /// Concatenated with the statement descriptor suffix that’s set on the account to form the complete statement descriptor. | ||||||
|     pub statement_descriptor_prefix: Option<String>, |     pub statement_descriptor_prefix: Option<String>, | ||||||
|     /// Merchant connector details used to make payments. |     /// Merchant connector details used to make payments. | ||||||
|  |     #[schema(value_type = Option<MerchantConnectorDetailsWrap>)] | ||||||
|     pub merchant_connector_details: Option<admin::MerchantConnectorDetailsWrap>, |     pub merchant_connector_details: Option<admin::MerchantConnectorDetailsWrap>, | ||||||
| } | } | ||||||
|  |  | ||||||
| @ -1231,6 +1258,7 @@ pub struct PaymentsResponse { | |||||||
|     pub connector_label: Option<String>, |     pub connector_label: Option<String>, | ||||||
|  |  | ||||||
|     /// The business country of merchant for this payment |     /// The business country of merchant for this payment | ||||||
|  |     #[schema(value_type = CountryAlpha2)] | ||||||
|     pub business_country: api_enums::CountryAlpha2, |     pub business_country: api_enums::CountryAlpha2, | ||||||
|  |  | ||||||
|     /// The business label of merchant for this payment |     /// The business label of merchant for this payment | ||||||
| @ -1487,6 +1515,7 @@ pub struct PaymentsRetrieveRequest { | |||||||
|     /// The name of the connector |     /// The name of the connector | ||||||
|     pub connector: Option<String>, |     pub connector: Option<String>, | ||||||
|     /// Merchant connector details used to make payments. |     /// Merchant connector details used to make payments. | ||||||
|  |     #[schema(value_type = Option<MerchantConnectorDetailsWrap>)] | ||||||
|     pub merchant_connector_details: Option<admin::MerchantConnectorDetailsWrap>, |     pub merchant_connector_details: Option<admin::MerchantConnectorDetailsWrap>, | ||||||
| } | } | ||||||
|  |  | ||||||
| @ -1510,7 +1539,9 @@ pub struct Metadata { | |||||||
|     #[schema(value_type = Object, example = r#"{ "city": "NY", "unit": "245" }"#)] |     #[schema(value_type = Object, example = r#"{ "city": "NY", "unit": "245" }"#)] | ||||||
|     #[serde(flatten)] |     #[serde(flatten)] | ||||||
|     pub data: pii::SecretSerdeValue, |     pub data: pii::SecretSerdeValue, | ||||||
|  |  | ||||||
|     /// Payload coming in request as a metadata field |     /// Payload coming in request as a metadata field | ||||||
|  |     #[schema(value_type = Option<Object>)] | ||||||
|     pub payload: Option<pii::SecretSerdeValue>, |     pub payload: Option<pii::SecretSerdeValue>, | ||||||
|  |  | ||||||
|     /// Allowed payment method types for a payment intent |     /// Allowed payment method types for a payment intent | ||||||
| @ -1528,6 +1559,7 @@ pub struct PaymentsSessionRequest { | |||||||
|     #[schema(value_type = Vec<PaymentMethodType>)] |     #[schema(value_type = Vec<PaymentMethodType>)] | ||||||
|     pub wallets: Vec<api_enums::PaymentMethodType>, |     pub wallets: Vec<api_enums::PaymentMethodType>, | ||||||
|     /// Merchant connector details used to make payments. |     /// Merchant connector details used to make payments. | ||||||
|  |     #[schema(value_type = Option<MerchantConnectorDetailsWrap>)] | ||||||
|     pub merchant_connector_details: Option<admin::MerchantConnectorDetailsWrap>, |     pub merchant_connector_details: Option<admin::MerchantConnectorDetailsWrap>, | ||||||
| } | } | ||||||
|  |  | ||||||
| @ -1796,6 +1828,7 @@ pub struct PaymentsCancelRequest { | |||||||
|     /// The reason for the payment cancel |     /// The reason for the payment cancel | ||||||
|     pub cancellation_reason: Option<String>, |     pub cancellation_reason: Option<String>, | ||||||
|     /// Merchant connector details used to make payments. |     /// Merchant connector details used to make payments. | ||||||
|  |     #[schema(value_type = MerchantConnectorDetailsWrap)] | ||||||
|     pub merchant_connector_details: Option<admin::MerchantConnectorDetailsWrap>, |     pub merchant_connector_details: Option<admin::MerchantConnectorDetailsWrap>, | ||||||
| } | } | ||||||
|  |  | ||||||
|  | |||||||
| @ -45,6 +45,7 @@ pub struct RefundRequest { | |||||||
|     pub metadata: Option<pii::SecretSerdeValue>, |     pub metadata: Option<pii::SecretSerdeValue>, | ||||||
|  |  | ||||||
|     /// Merchant connector details used to make payments. |     /// Merchant connector details used to make payments. | ||||||
|  |     #[schema(value_type = Option<MerchantConnectorDetailsWrap>)] | ||||||
|     pub merchant_connector_details: Option<admin::MerchantConnectorDetailsWrap>, |     pub merchant_connector_details: Option<admin::MerchantConnectorDetailsWrap>, | ||||||
| } | } | ||||||
|  |  | ||||||
|  | |||||||
| @ -205,6 +205,7 @@ pub struct CurrencyCountryFlowFilter { | |||||||
|     pub country: Option<HashSet<api_models::enums::CountryAlpha2>>, |     pub country: Option<HashSet<api_models::enums::CountryAlpha2>>, | ||||||
|     pub not_available_flows: Option<NotAvailableFlows>, |     pub not_available_flows: Option<NotAvailableFlows>, | ||||||
| } | } | ||||||
|  |  | ||||||
| #[derive(Debug, Deserialize, Copy, Clone, Default)] | #[derive(Debug, Deserialize, Copy, Clone, Default)] | ||||||
| #[serde(default)] | #[serde(default)] | ||||||
| pub struct NotAvailableFlows { | pub struct NotAvailableFlows { | ||||||
|  | |||||||
| @ -29,7 +29,7 @@ Use the following base URLs when making requests to the APIs: | |||||||
| | Environment   |  Base URL                          | | | Environment   |  Base URL                          | | ||||||
| |---------------|------------------------------------| | |---------------|------------------------------------| | ||||||
| | Sandbox       | <https://sandbox.hyperswitch.io>   | | | Sandbox       | <https://sandbox.hyperswitch.io>   | | ||||||
| | Production    | Coming Soon!                       | | | Production    | <https://api.hyperswitch.io>       | | ||||||
|  |  | ||||||
| ## Authentication | ## Authentication | ||||||
|  |  | ||||||
| @ -39,9 +39,9 @@ You may authenticate all API requests with Hyperswitch server by providing the a | |||||||
| the request Authorization header. | the request Authorization header. | ||||||
|  |  | ||||||
| | Key             |  Description                                                                                  | | | Key             |  Description                                                                                  | | ||||||
| |---------------|-----------------------------------------------------------------------------------------------| | |-----------------|-----------------------------------------------------------------------------------------------| | ||||||
| | Sandbox       | Private key. Used to authenticate all API requests from your merchant server                  | | | api-key         | 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  | | | publishable key | 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. | Never share your secret api keys. Keep them guarded and secure. | ||||||
| "#, | "#, | ||||||
| @ -65,15 +65,16 @@ Never share your secret api keys. Keep them guarded and secure. | |||||||
|         crate::routes::refunds::refunds_retrieve, |         crate::routes::refunds::refunds_retrieve, | ||||||
|         crate::routes::refunds::refunds_update, |         crate::routes::refunds::refunds_update, | ||||||
|         crate::routes::refunds::refunds_list, |         crate::routes::refunds::refunds_list, | ||||||
|         crate::routes::admin::merchant_account_create, |         // Commenting this out as these are admin apis and not to be used by the merchant | ||||||
|         crate::routes::admin::retrieve_merchant_account, |         // crate::routes::admin::merchant_account_create, | ||||||
|         crate::routes::admin::update_merchant_account, |         // crate::routes::admin::retrieve_merchant_account, | ||||||
|         crate::routes::admin::delete_merchant_account, |         // crate::routes::admin::update_merchant_account, | ||||||
|         crate::routes::admin::payment_connector_create, |         // crate::routes::admin::delete_merchant_account, | ||||||
|         crate::routes::admin::payment_connector_retrieve, |         // crate::routes::admin::payment_connector_create, | ||||||
|         crate::routes::admin::payment_connector_list, |         // crate::routes::admin::payment_connector_retrieve, | ||||||
|         crate::routes::admin::payment_connector_update, |         // crate::routes::admin::payment_connector_list, | ||||||
|         crate::routes::admin::payment_connector_delete, |         // crate::routes::admin::payment_connector_update, | ||||||
|  |         // crate::routes::admin::payment_connector_delete, | ||||||
|         crate::routes::mandates::get_mandate, |         crate::routes::mandates::get_mandate, | ||||||
|         crate::routes::mandates::revoke_mandate, |         crate::routes::mandates::revoke_mandate, | ||||||
|         crate::routes::payments::payments_create, |         crate::routes::payments::payments_create, | ||||||
| @ -114,6 +115,7 @@ Never share your secret api keys. Keep them guarded and secure. | |||||||
|         crate::types::api::admin::MerchantAccountUpdate, |         crate::types::api::admin::MerchantAccountUpdate, | ||||||
|         crate::types::api::admin::MerchantAccountDeleteResponse, |         crate::types::api::admin::MerchantAccountDeleteResponse, | ||||||
|         crate::types::api::admin::MerchantConnectorDeleteResponse, |         crate::types::api::admin::MerchantConnectorDeleteResponse, | ||||||
|  |         crate::types::api::admin::MerchantConnectorResponse, | ||||||
|         crate::types::api::customers::CustomerRequest, |         crate::types::api::customers::CustomerRequest, | ||||||
|         crate::types::api::customers::CustomerDeleteResponse, |         crate::types::api::customers::CustomerDeleteResponse, | ||||||
|         crate::types::api::payment_methods::PaymentMethodCreate, |         crate::types::api::payment_methods::PaymentMethodCreate, | ||||||
| @ -148,10 +150,25 @@ Never share your secret api keys. Keep them guarded and secure. | |||||||
|         api_models::enums::DisputeStage, |         api_models::enums::DisputeStage, | ||||||
|         api_models::enums::DisputeStatus, |         api_models::enums::DisputeStatus, | ||||||
|         api_models::enums::CountryAlpha2, |         api_models::enums::CountryAlpha2, | ||||||
|  |         api_models::enums::FrmAction, | ||||||
|  |         api_models::enums::FrmPreferredFlowTypes, | ||||||
|         api_models::admin::MerchantConnectorCreate, |         api_models::admin::MerchantConnectorCreate, | ||||||
|  |         api_models::admin::MerchantConnectorUpdate, | ||||||
|  |         api_models::admin::PrimaryBusinessDetails, | ||||||
|  |         api_models::admin::FrmConfigs, | ||||||
|         api_models::admin::PaymentMethodsEnabled, |         api_models::admin::PaymentMethodsEnabled, | ||||||
|  |         api_models::admin::MerchantConnectorDetailsWrap, | ||||||
|  |         api_models::admin::MerchantConnectorDetails, | ||||||
|         api_models::disputes::DisputeResponse, |         api_models::disputes::DisputeResponse, | ||||||
|  |         api_models::disputes::DisputeResponsePaymentsRetrieve, | ||||||
|         api_models::payments::AddressDetails, |         api_models::payments::AddressDetails, | ||||||
|  |         api_models::payments::BankDebitData, | ||||||
|  |         api_models::payments::AliPayRedirection, | ||||||
|  |         api_models::payments::MbWayRedirection, | ||||||
|  |         api_models::payments::MobilePayRedirection, | ||||||
|  |         api_models::payments::WeChatPayRedirection, | ||||||
|  |         api_models::payments::BankDebitBilling, | ||||||
|  |         api_models::payments::CryptoData, | ||||||
|         api_models::payments::Address, |         api_models::payments::Address, | ||||||
|         api_models::payments::BankRedirectData, |         api_models::payments::BankRedirectData, | ||||||
|         api_models::payments::BankRedirectBilling, |         api_models::payments::BankRedirectBilling, | ||||||
| @ -172,6 +189,7 @@ Never share your secret api keys. Keep them guarded and secure. | |||||||
|         api_models::payments::Card, |         api_models::payments::Card, | ||||||
|         api_models::payments::CustomerAcceptance, |         api_models::payments::CustomerAcceptance, | ||||||
|         api_models::payments::PaymentsRequest, |         api_models::payments::PaymentsRequest, | ||||||
|  |         api_models::payments::PaymentsCreateRequest, | ||||||
|         api_models::payments::PaymentsResponse, |         api_models::payments::PaymentsResponse, | ||||||
|         api_models::payments::PaymentsStartRequest, |         api_models::payments::PaymentsStartRequest, | ||||||
|         api_models::payments::PaymentRetrieveBody, |         api_models::payments::PaymentRetrieveBody, | ||||||
|  | |||||||
| @ -158,9 +158,9 @@ pub async fn delete_merchant_account( | |||||||
| #[utoipa::path( | #[utoipa::path( | ||||||
|     post, |     post, | ||||||
|     path = "/accounts/{account_id}/connectors", |     path = "/accounts/{account_id}/connectors", | ||||||
|     request_body = MerchantConnector, |     request_body = MerchantConnectorCreate, | ||||||
|     responses( |     responses( | ||||||
|         (status = 200, description = "Merchant Connector Created", body = MerchantConnector), |         (status = 200, description = "Merchant Connector Created", body = MerchantConnectorResponse), | ||||||
|         (status = 400, description = "Missing Mandatory fields"), |         (status = 400, description = "Missing Mandatory fields"), | ||||||
|     ), |     ), | ||||||
|     tag = "Merchant Connector Account", |     tag = "Merchant Connector Account", | ||||||
| @ -198,7 +198,7 @@ pub async fn payment_connector_create( | |||||||
|         ("connector_id" = i32, Path, description = "The unique identifier for the Merchant Connector") |         ("connector_id" = i32, Path, description = "The unique identifier for the Merchant Connector") | ||||||
|     ), |     ), | ||||||
|     responses( |     responses( | ||||||
|         (status = 200, description = "Merchant Connector retrieved successfully", body = MerchantConnector), |         (status = 200, description = "Merchant Connector retrieved successfully", body = MerchantConnectorResponse), | ||||||
|         (status = 404, description = "Merchant Connector does not exist in records"), |         (status = 404, description = "Merchant Connector does not exist in records"), | ||||||
|         (status = 401, description = "Unauthorized request") |         (status = 401, description = "Unauthorized request") | ||||||
|     ), |     ), | ||||||
| @ -242,7 +242,7 @@ pub async fn payment_connector_retrieve( | |||||||
|         ("account_id" = String, Path, description = "The unique identifier for the merchant account"), |         ("account_id" = String, Path, description = "The unique identifier for the merchant account"), | ||||||
|     ), |     ), | ||||||
|     responses( |     responses( | ||||||
|         (status = 200, description = "Merchant Connector list retrieved successfully", body = Vec<MerchantConnector>), |         (status = 200, description = "Merchant Connector list retrieved successfully", body = Vec<MerchantConnectorResponse>), | ||||||
|         (status = 404, description = "Merchant Connector does not exist in records"), |         (status = 404, description = "Merchant Connector does not exist in records"), | ||||||
|         (status = 401, description = "Unauthorized request") |         (status = 401, description = "Unauthorized request") | ||||||
|     ), |     ), | ||||||
| @ -275,13 +275,13 @@ pub async fn payment_connector_list( | |||||||
| #[utoipa::path( | #[utoipa::path( | ||||||
|     post, |     post, | ||||||
|     path = "/accounts/{account_id}/connectors/{connector_id}", |     path = "/accounts/{account_id}/connectors/{connector_id}", | ||||||
|     request_body = MerchantConnector, |     request_body = MerchantConnectorUpdate, | ||||||
|     params( |     params( | ||||||
|         ("account_id" = String, Path, description = "The unique identifier for the merchant account"), |         ("account_id" = String, Path, description = "The unique identifier for the merchant account"), | ||||||
|         ("connector_id" = i32, Path, description = "The unique identifier for the Merchant Connector") |         ("connector_id" = i32, Path, description = "The unique identifier for the Merchant Connector") | ||||||
|     ), |     ), | ||||||
|     responses( |     responses( | ||||||
|         (status = 200, description = "Merchant Connector Updated", body = MerchantConnector), |         (status = 200, description = "Merchant Connector Updated", body = MerchantConnectorResponse), | ||||||
|         (status = 404, description = "Merchant Connector does not exist in records"), |         (status = 404, description = "Merchant Connector does not exist in records"), | ||||||
|         (status = 401, description = "Unauthorized request") |         (status = 401, description = "Unauthorized request") | ||||||
|     ), |     ), | ||||||
|  | |||||||
| @ -11,7 +11,7 @@ use crate::{ | |||||||
|     types::api::disputes as dispute_types, |     types::api::disputes as dispute_types, | ||||||
| }; | }; | ||||||
|  |  | ||||||
| /// Diputes - Retrieve Dispute | /// Disputes - Retrieve Dispute | ||||||
| #[utoipa::path( | #[utoipa::path( | ||||||
|     get, |     get, | ||||||
|     path = "/disputes/{dispute_id}", |     path = "/disputes/{dispute_id}", | ||||||
| @ -47,7 +47,7 @@ pub async fn retrieve_dispute( | |||||||
|     .await |     .await | ||||||
| } | } | ||||||
|  |  | ||||||
| /// Diputes - List Disputes | /// Disputes - List Disputes | ||||||
| #[utoipa::path( | #[utoipa::path( | ||||||
|     get, |     get, | ||||||
|     path = "/disputes/list", |     path = "/disputes/list", | ||||||
| @ -90,7 +90,7 @@ pub async fn retrieve_disputes_list( | |||||||
|     .await |     .await | ||||||
| } | } | ||||||
|  |  | ||||||
| /// Diputes - Accept Dispute | /// Disputes - Accept Dispute | ||||||
| #[utoipa::path( | #[utoipa::path( | ||||||
|     get, |     get, | ||||||
|     path = "/disputes/accept/{dispute_id}", |     path = "/disputes/accept/{dispute_id}", | ||||||
| @ -126,7 +126,7 @@ pub async fn accept_dispute( | |||||||
|     .await |     .await | ||||||
| } | } | ||||||
|  |  | ||||||
| /// Diputes - Submit Dispute Evidence | /// Disputes - Submit Dispute Evidence | ||||||
| #[utoipa::path( | #[utoipa::path( | ||||||
|     post, |     post, | ||||||
|     path = "/disputes/evidence", |     path = "/disputes/evidence", | ||||||
|  | |||||||
| @ -48,7 +48,7 @@ pub async fn create_payment_method_api( | |||||||
| /// To filter and list the applicable payment methods for a particular Merchant ID | /// To filter and list the applicable payment methods for a particular Merchant ID | ||||||
| #[utoipa::path( | #[utoipa::path( | ||||||
|     get, |     get, | ||||||
|     path = "/payment_methods/{account_id}", |     path = "/account/payment_methods", | ||||||
|     params ( |     params ( | ||||||
|         ("account_id" = String, Path, description = "The unique identifier for the merchant account"), |         ("account_id" = String, Path, description = "The unique identifier for the merchant account"), | ||||||
|         ("accepted_country" = Vec<String>, Query, description = "The two-letter ISO currency code"), |         ("accepted_country" = Vec<String>, Query, description = "The two-letter ISO currency code"), | ||||||
| @ -96,7 +96,7 @@ pub async fn list_payment_method_api( | |||||||
| /// To filter and list the applicable payment methods for a particular Customer ID | /// To filter and list the applicable payment methods for a particular Customer ID | ||||||
| #[utoipa::path( | #[utoipa::path( | ||||||
|     get, |     get, | ||||||
|     path = "/payment_methods/{customer_id}", |     path = "/customer/{customer_id}/payment_methods", | ||||||
|     params ( |     params ( | ||||||
|         ("customer_id" = String, Path, description = "The unique identifier for the customer account"), |         ("customer_id" = String, Path, description = "The unique identifier for the customer account"), | ||||||
|         ("accepted_country" = Vec<String>, Query, description = "The two-letter ISO currency code"), |         ("accepted_country" = Vec<String>, Query, description = "The two-letter ISO currency code"), | ||||||
|  | |||||||
| @ -18,7 +18,7 @@ use crate::{ | |||||||
| #[utoipa::path( | #[utoipa::path( | ||||||
|     post, |     post, | ||||||
|     path = "/payments", |     path = "/payments", | ||||||
|     request_body=PaymentsRequest, |     request_body=PaymentsCreateRequest, | ||||||
|     responses( |     responses( | ||||||
|         (status = 200, description = "Payment created", body = PaymentsResponse), |         (status = 200, description = "Payment created", body = PaymentsResponse), | ||||||
|         (status = 400, description = "Missing Mandatory fields") |         (status = 400, description = "Missing Mandatory fields") | ||||||
|  | |||||||
| @ -1,9 +1,9 @@ | |||||||
| pub use api_models::admin::{ | pub use api_models::admin::{ | ||||||
|     MerchantAccountCreate, MerchantAccountDeleteResponse, MerchantAccountResponse, |     MerchantAccountCreate, MerchantAccountDeleteResponse, MerchantAccountResponse, | ||||||
|     MerchantAccountUpdate, MerchantConnectorCreate, MerchantConnectorDeleteResponse, |     MerchantAccountUpdate, MerchantConnectorCreate, MerchantConnectorDeleteResponse, | ||||||
|     MerchantConnectorDetails, MerchantConnectorDetailsWrap, MerchantConnectorId, MerchantDetails, |     MerchantConnectorDetails, MerchantConnectorDetailsWrap, MerchantConnectorId, | ||||||
|     MerchantId, PaymentMethodsEnabled, RoutingAlgorithm, StraightThroughAlgorithm, ToggleKVRequest, |     MerchantConnectorResponse, MerchantDetails, MerchantId, PaymentMethodsEnabled, | ||||||
|     ToggleKVResponse, WebhookDetails, |     RoutingAlgorithm, StraightThroughAlgorithm, ToggleKVRequest, ToggleKVResponse, WebhookDetails, | ||||||
| }; | }; | ||||||
| use common_utils::ext_traits::ValueExt; | use common_utils::ext_traits::ValueExt; | ||||||
|  |  | ||||||
|  | |||||||
| @ -462,3 +462,50 @@ pub fn operation_derive(input: proc_macro::TokenStream) -> proc_macro::TokenStre | |||||||
|     let input = syn::parse_macro_input!(input as syn::DeriveInput); |     let input = syn::parse_macro_input!(input as syn::DeriveInput); | ||||||
|     macros::operation_derive_inner(input).unwrap_or_else(|err| err.to_compile_error().into()) |     macros::operation_derive_inner(input).unwrap_or_else(|err| err.to_compile_error().into()) | ||||||
| } | } | ||||||
|  |  | ||||||
|  | /// Generates different schemas with the ability to mark few fields as mandatory for certain schema | ||||||
|  | /// Usage | ||||||
|  | /// ``` | ||||||
|  | /// #[derive(PolymorphicSchema)] | ||||||
|  | /// #[generate_schemas(PaymentsCreateRequest, PaymentsConfirmRequest)] | ||||||
|  | /// struct PaymentsRequest { | ||||||
|  | ///     #[mandatory_in(PaymentsCreateRequest)] | ||||||
|  | ///     amount: Option<u64>, | ||||||
|  | ///     #[mandatory_in(PaymentsCreateRequest)] | ||||||
|  | ///     currency: Option<String>, | ||||||
|  | ///     payment_method: String, | ||||||
|  | /// } | ||||||
|  | /// ``` | ||||||
|  | /// | ||||||
|  | /// This will create two structs `PaymentsCreateRequest` and `PaymentsConfirmRequest` as follows | ||||||
|  | /// It will retain all the other attributes that are used in the original struct, and only consume | ||||||
|  | /// the #[mandatory_in] attribute to generate schemas | ||||||
|  | /// | ||||||
|  | /// ``` | ||||||
|  | /// #[derive(utoipa::ToSchema)] | ||||||
|  | /// struct PaymentsCreateRequest { | ||||||
|  | ///     #[schema(required = true)] | ||||||
|  | ///     amount: Option<u64>, | ||||||
|  | /// | ||||||
|  | ///     #[schema(required = true)] | ||||||
|  | ///     currency: Option<String>, | ||||||
|  | /// | ||||||
|  | ///     payment_method: String, | ||||||
|  | /// } | ||||||
|  | /// | ||||||
|  | /// #[derive(utoipa::ToSchema)] | ||||||
|  | /// struct PaymentsConfirmRequest { | ||||||
|  | ///     amount: Option<u64>, | ||||||
|  | ///     currency: Option<String>, | ||||||
|  | ///     payment_method: String, | ||||||
|  | /// } | ||||||
|  | /// ``` | ||||||
|  |  | ||||||
|  | #[proc_macro_derive(PolymorphicSchema, attributes(mandatory_in, generate_schemas))] | ||||||
|  | pub fn polymorphic_schema(input: proc_macro::TokenStream) -> proc_macro::TokenStream { | ||||||
|  |     let input = syn::parse_macro_input!(input as syn::DeriveInput); | ||||||
|  |  | ||||||
|  |     macros::polymorphic_macro_derive_inner(input) | ||||||
|  |         .unwrap_or_else(|error| error.into_compile_error()) | ||||||
|  |         .into() | ||||||
|  | } | ||||||
|  | |||||||
| @ -1,8 +1,10 @@ | |||||||
| pub(crate) mod api_error; | pub(crate) mod api_error; | ||||||
| pub(crate) mod diesel; | pub(crate) mod diesel; | ||||||
| mod helpers; | pub(crate) mod generate_schema; | ||||||
| pub(crate) mod operation; | pub(crate) mod operation; | ||||||
|  |  | ||||||
|  | mod helpers; | ||||||
|  |  | ||||||
| use proc_macro2::TokenStream; | use proc_macro2::TokenStream; | ||||||
| use quote::quote; | use quote::quote; | ||||||
| use syn::DeriveInput; | use syn::DeriveInput; | ||||||
| @ -12,6 +14,7 @@ pub(crate) use self::{ | |||||||
|     diesel::{ |     diesel::{ | ||||||
|         diesel_enum_attribute_inner, diesel_enum_derive_inner, diesel_enum_text_derive_inner, |         diesel_enum_attribute_inner, diesel_enum_derive_inner, diesel_enum_text_derive_inner, | ||||||
|     }, |     }, | ||||||
|  |     generate_schema::polymorphic_macro_derive_inner, | ||||||
|     operation::operation_derive_inner, |     operation::operation_derive_inner, | ||||||
| }; | }; | ||||||
|  |  | ||||||
|  | |||||||
							
								
								
									
										140
									
								
								crates/router_derive/src/macros/generate_schema.rs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										140
									
								
								crates/router_derive/src/macros/generate_schema.rs
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,140 @@ | |||||||
|  | use std::collections::{HashMap, HashSet}; | ||||||
|  |  | ||||||
|  | use syn::{self, parse_quote, punctuated::Punctuated, Token}; | ||||||
|  |  | ||||||
|  | use crate::macros::helpers; | ||||||
|  |  | ||||||
|  | /// Parse schemas from attribute | ||||||
|  | /// Example | ||||||
|  | /// | ||||||
|  | /// #[mandatory_in(PaymentsCreateRequest, PaymentsUpdateRequest)] | ||||||
|  | /// would return | ||||||
|  | /// | ||||||
|  | /// [PaymentsCreateRequest, PaymentsUpdateRequest] | ||||||
|  | fn get_inner_path_ident(attribute: &syn::Attribute) -> syn::Result<Vec<syn::Ident>> { | ||||||
|  |     Ok(attribute | ||||||
|  |         .parse_args_with(Punctuated::<syn::Ident, Token![,]>::parse_terminated)? | ||||||
|  |         .into_iter() | ||||||
|  |         .collect::<Vec<_>>()) | ||||||
|  | } | ||||||
|  |  | ||||||
|  | fn get_struct_fields(data: syn::Data) -> syn::Result<Punctuated<syn::Field, syn::token::Comma>> { | ||||||
|  |     if let syn::Data::Struct(syn::DataStruct { | ||||||
|  |         fields: syn::Fields::Named(syn::FieldsNamed { ref named, .. }), | ||||||
|  |         .. | ||||||
|  |     }) = data | ||||||
|  |     { | ||||||
|  |         Ok(named.to_owned()) | ||||||
|  |     } else { | ||||||
|  |         Err(syn::Error::new( | ||||||
|  |             proc_macro2::Span::call_site(), | ||||||
|  |             "This macro cannot be used on structs with no fields", | ||||||
|  |         )) | ||||||
|  |     } | ||||||
|  | } | ||||||
|  |  | ||||||
|  | pub fn polymorphic_macro_derive_inner( | ||||||
|  |     input: syn::DeriveInput, | ||||||
|  | ) -> syn::Result<proc_macro2::TokenStream> { | ||||||
|  |     let schemas_to_create = | ||||||
|  |         helpers::get_metadata_inner::<syn::Ident>("generate_schemas", &input.attrs)?; | ||||||
|  |  | ||||||
|  |     let fields = get_struct_fields(input.data) | ||||||
|  |         .map_err(|error| syn::Error::new(proc_macro2::Span::call_site(), error))?; | ||||||
|  |  | ||||||
|  |     // Go through all the fields and create a mapping of required fields for a schema | ||||||
|  |     // PaymentsCreate -> ["amount","currency"] | ||||||
|  |     // This will be stored in a hashset | ||||||
|  |     // mandatory_hashset -> ((PaymentsCreate, amount), (PaymentsCreate,currency)) | ||||||
|  |     let mut mandatory_hashset = HashSet::<(syn::Ident, syn::Ident)>::new(); | ||||||
|  |     let mut other_fields_hm = HashMap::<syn::Field, Vec<syn::Attribute>>::new(); | ||||||
|  |  | ||||||
|  |     fields.iter().for_each(|field| { | ||||||
|  |         // Partition the attributes of a field into two vectors | ||||||
|  |         // One with #[mandatory_in] attributes present | ||||||
|  |         // Rest of the attributes ( include only the schema attribute, serde is not required) | ||||||
|  |         let (mandatory_attribute, other_attributes) = field | ||||||
|  |             .attrs | ||||||
|  |             .iter() | ||||||
|  |             .partition::<Vec<_>, _>(|attribute| attribute.path.is_ident("mandatory_in")); | ||||||
|  |  | ||||||
|  |         // Other attributes ( schema ) are to be printed as is | ||||||
|  |         other_attributes | ||||||
|  |             .iter() | ||||||
|  |             .filter(|attribute| attribute.path.is_ident("schema") || attribute.path.is_ident("doc")) | ||||||
|  |             .for_each(|attribute| { | ||||||
|  |                 // Since attributes will be modified, the field should not contain any attributes | ||||||
|  |                 // So create a field, with previous attributes removed | ||||||
|  |                 let mut field_without_attributes = field.clone(); | ||||||
|  |                 field_without_attributes.attrs.clear(); | ||||||
|  |  | ||||||
|  |                 other_fields_hm | ||||||
|  |                     .entry(field_without_attributes.to_owned()) | ||||||
|  |                     .or_insert(vec![]) | ||||||
|  |                     .push(attribute.to_owned().to_owned()); | ||||||
|  |             }); | ||||||
|  |  | ||||||
|  |         // Mandatory attributes are to be inserted into hashset | ||||||
|  |         // The hashset will store it in this format | ||||||
|  |         // (PaymentsCreateRequest, "amount") | ||||||
|  |         // (PaymentsConfirmRequest, "currency") | ||||||
|  |         // | ||||||
|  |         // For these attributes, we need to later add #[schema(required = true)] attribute | ||||||
|  |         _ = mandatory_attribute | ||||||
|  |             .iter() | ||||||
|  |             // Filter only #[mandatory_in] attributes | ||||||
|  |             .map(|&attribute| get_inner_path_ident(attribute)) | ||||||
|  |             .try_for_each(|schemas| { | ||||||
|  |                 let res = schemas | ||||||
|  |                     .map_err(|error| syn::Error::new(proc_macro2::Span::call_site(), error))? | ||||||
|  |                     .iter() | ||||||
|  |                     .filter_map(|schema| field.ident.to_owned().zip(Some(schema.to_owned()))) | ||||||
|  |                     .collect::<HashSet<_>>(); | ||||||
|  |  | ||||||
|  |                 mandatory_hashset.extend(res); | ||||||
|  |                 Ok::<_, syn::Error>(()) | ||||||
|  |             }); | ||||||
|  |     }); | ||||||
|  |  | ||||||
|  |     let schemas = schemas_to_create | ||||||
|  |         .iter() | ||||||
|  |         .map(|schema| { | ||||||
|  |             let fields = other_fields_hm | ||||||
|  |                 .iter() | ||||||
|  |                 .flat_map(|(field, value)| { | ||||||
|  |                     let mut attributes = value | ||||||
|  |                         .iter() | ||||||
|  |                         .map(|attribute| quote::quote!(#attribute)) | ||||||
|  |                         .collect::<Vec<_>>(); | ||||||
|  |  | ||||||
|  |                     // If the field is required for this schema, then add | ||||||
|  |                     // #[schema(required = true)] for this field | ||||||
|  |                     let required_attribute: syn::Attribute = | ||||||
|  |                         parse_quote!(#[schema(required = true)]); | ||||||
|  |  | ||||||
|  |                     // Can be none, because tuple fields have no ident | ||||||
|  |                     field.ident.to_owned().and_then(|field_ident| { | ||||||
|  |                         mandatory_hashset | ||||||
|  |                             .contains(&(field_ident, schema.to_owned())) | ||||||
|  |                             .then(|| attributes.push(quote::quote!(#required_attribute))) | ||||||
|  |                     }); | ||||||
|  |  | ||||||
|  |                     quote::quote! { | ||||||
|  |                         #(#attributes)* | ||||||
|  |                         #field, | ||||||
|  |                     } | ||||||
|  |                 }) | ||||||
|  |                 .collect::<Vec<_>>(); | ||||||
|  |             quote::quote! { | ||||||
|  |                 #[derive(utoipa::ToSchema)] | ||||||
|  |                 pub struct #schema { | ||||||
|  |                     #(#fields)* | ||||||
|  |                 } | ||||||
|  |             } | ||||||
|  |         }) | ||||||
|  |         .collect::<Vec<_>>(); | ||||||
|  |  | ||||||
|  |     Ok(quote::quote! { | ||||||
|  |         #(#schemas)* | ||||||
|  |     }) | ||||||
|  | } | ||||||
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							
		Reference in New Issue
	
	Block a user
	 Narayan Bhat
					Narayan Bhat