mirror of
https://github.com/juspay/hyperswitch.git
synced 2025-10-29 09:07:09 +08:00
refactor: add payment_issuer and payment_experience in pa (#491)
This commit is contained in:
48
Cargo.lock
generated
48
Cargo.lock
generated
@ -1181,6 +1181,41 @@ dependencies = [
|
||||
"typenum",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "darling"
|
||||
version = "0.14.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c0808e1bd8671fb44a113a14e13497557533369847788fa2ae912b6ebfce9fa8"
|
||||
dependencies = [
|
||||
"darling_core",
|
||||
"darling_macro",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "darling_core"
|
||||
version = "0.14.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "001d80444f28e193f30c2f293455da62dcf9a6b29918a4253152ae2b1de592cb"
|
||||
dependencies = [
|
||||
"fnv",
|
||||
"ident_case",
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"strsim",
|
||||
"syn",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "darling_macro"
|
||||
version = "0.14.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b36230598a2d5de7ec1c6f51f72d8a99a9208daff41de2084d06e3fd3ea56685"
|
||||
dependencies = [
|
||||
"darling_core",
|
||||
"quote",
|
||||
"syn",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "dashmap"
|
||||
version = "5.4.0"
|
||||
@ -1893,6 +1928,12 @@ dependencies = [
|
||||
"tokio-native-tls",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "ident_case"
|
||||
version = "1.0.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b9e0384b61958566e926dc50660321d12159025e767c18e043daf26b70104c39"
|
||||
|
||||
[[package]]
|
||||
name = "idna"
|
||||
version = "0.3.0"
|
||||
@ -3094,6 +3135,7 @@ dependencies = [
|
||||
name = "router_derive"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"darling",
|
||||
"diesel",
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
@ -3531,6 +3573,12 @@ dependencies = [
|
||||
"time",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "strsim"
|
||||
version = "0.10.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "73473c0e59e6d5812c5dfe2a064a6444949f089e20eec9a2e5506596494e4623"
|
||||
|
||||
[[package]]
|
||||
name = "strum"
|
||||
version = "0.24.1"
|
||||
|
||||
@ -4,7 +4,7 @@ use serde::{Deserialize, Serialize};
|
||||
use utoipa::ToSchema;
|
||||
|
||||
use super::payments::AddressDetails;
|
||||
use crate::{enums as api_enums, payment_methods};
|
||||
use crate::enums as api_enums;
|
||||
|
||||
#[derive(Clone, Debug, Deserialize, ToSchema)]
|
||||
#[serde(deny_unknown_fields)]
|
||||
@ -325,7 +325,7 @@ pub struct PaymentMethods {
|
||||
pub installment_payment_enabled: bool,
|
||||
/// Type of payment experience enabled with the connector
|
||||
#[schema(value_type = Option<Vec<PaymentExperience>>,example = json!(["redirect_to_url"]))]
|
||||
pub payment_experience: Option<Vec<payment_methods::PaymentExperience>>,
|
||||
pub payment_experience: Option<Vec<api_enums::PaymentExperience>>,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Serialize, Deserialize, ToSchema)]
|
||||
|
||||
@ -343,6 +343,66 @@ pub enum PaymentMethodIssuerCode {
|
||||
JpBacs,
|
||||
}
|
||||
|
||||
#[derive(
|
||||
Clone,
|
||||
Copy,
|
||||
Debug,
|
||||
Eq,
|
||||
Hash,
|
||||
PartialEq,
|
||||
serde::Deserialize,
|
||||
serde::Serialize,
|
||||
frunk::LabelledGeneric,
|
||||
ToSchema,
|
||||
)]
|
||||
#[serde(rename_all = "snake_case")]
|
||||
pub enum PaymentIssuer {
|
||||
Klarna,
|
||||
Affirm,
|
||||
AfterpayClearpay,
|
||||
AmericanExpress,
|
||||
BankOfAmerica,
|
||||
Barclays,
|
||||
CapitalOne,
|
||||
Chase,
|
||||
Citi,
|
||||
Discover,
|
||||
NavyFederalCreditUnion,
|
||||
PentagonFederalCreditUnion,
|
||||
SynchronyBank,
|
||||
WellsFargo,
|
||||
}
|
||||
|
||||
#[derive(
|
||||
Eq,
|
||||
PartialEq,
|
||||
Hash,
|
||||
Copy,
|
||||
Clone,
|
||||
Debug,
|
||||
serde::Serialize,
|
||||
serde::Deserialize,
|
||||
ToSchema,
|
||||
Default,
|
||||
frunk::LabelledGeneric,
|
||||
)]
|
||||
#[serde(rename_all = "snake_case")]
|
||||
pub enum PaymentExperience {
|
||||
/// The URL to which the customer needs to be redirected for completing the payment.
|
||||
#[default]
|
||||
RedirectToUrl,
|
||||
/// Contains the data for invoking the sdk client for completing the payment.
|
||||
InvokeSdkClient,
|
||||
/// The QR code data to be displayed to the customer.
|
||||
DisplayQrCode,
|
||||
/// Contains data to finish one click payment.
|
||||
OneClick,
|
||||
/// Redirect customer to link wallet
|
||||
LinkWallet,
|
||||
/// Contains the data for invoking the sdk client for completing the payment.
|
||||
InvokePaymentApp,
|
||||
}
|
||||
|
||||
#[derive(
|
||||
Clone,
|
||||
Copy,
|
||||
|
||||
@ -122,7 +122,7 @@ pub struct PaymentMethodResponse {
|
||||
|
||||
/// Type of payment experience enabled with the connector
|
||||
#[schema(value_type = Option<Vec<PaymentExperience>>,example = json!(["redirect_to_url"]))]
|
||||
pub payment_experience: Option<Vec<PaymentExperience>>,
|
||||
pub payment_experience: Option<Vec<api_enums::PaymentExperience>>,
|
||||
|
||||
/// 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<Object>,example = json!({ "city": "NY", "unit": "245" }))]
|
||||
@ -348,8 +348,8 @@ pub struct ListPaymentMethod {
|
||||
pub installment_payment_enabled: bool,
|
||||
|
||||
/// Type of payment experience enabled with the connector
|
||||
#[schema(example = json!(["redirect_to_url"]))]
|
||||
pub payment_experience: Option<Vec<PaymentExperience>>,
|
||||
#[schema(value_type = Option<Vec<PaymentExperience>>, example = json!(["redirect_to_url"]))]
|
||||
pub payment_experience: Option<Vec<api_enums::PaymentExperience>>,
|
||||
}
|
||||
|
||||
/// We need a custom serializer to only send relevant fields in ListPaymentMethodResponse
|
||||
@ -447,7 +447,7 @@ pub struct CustomerPaymentMethod {
|
||||
|
||||
/// Type of payment experience enabled with the connector
|
||||
#[schema(value_type = Option<Vec<PaymentExperience>>,example = json!(["redirect_to_url"]))]
|
||||
pub payment_experience: Option<Vec<PaymentExperience>>,
|
||||
pub payment_experience: Option<Vec<api_enums::PaymentExperience>>,
|
||||
|
||||
/// Card details from card locker
|
||||
#[schema(example = json!({"last4": "1142","exp_month": "03","exp_year": "2030"}))]
|
||||
@ -462,26 +462,6 @@ pub struct CustomerPaymentMethod {
|
||||
#[serde(default, with = "common_utils::custom_serde::iso8601::option")]
|
||||
pub created: Option<time::PrimitiveDateTime>,
|
||||
}
|
||||
|
||||
#[derive(Eq, PartialEq, Hash, Clone, Debug, serde::Serialize, serde::Deserialize, ToSchema)]
|
||||
#[serde(rename_all = "snake_case")]
|
||||
#[non_exhaustive]
|
||||
pub enum PaymentExperience {
|
||||
/// The URL to which the customer needs to be redirected for completing the payment.The URL to
|
||||
/// which the customer needs to be redirected for completing the payment.
|
||||
RedirectToUrl,
|
||||
/// Contains the data for invoking the sdk client for completing the payment.
|
||||
InvokeSdkClient,
|
||||
/// The QR code data to be displayed to the customer.
|
||||
DisplayQrCode,
|
||||
/// Contains data to finish one click payment.
|
||||
OneClick,
|
||||
/// Redirect customer to link wallet
|
||||
LinkWallet,
|
||||
/// Contains the data for invoking the sdk client for completing the payment.
|
||||
InvokePaymentApp,
|
||||
}
|
||||
|
||||
#[derive(Debug, serde::Serialize, serde::Deserialize)]
|
||||
pub struct PaymentMethodId {
|
||||
pub payment_method_id: String,
|
||||
|
||||
@ -132,6 +132,12 @@ pub struct PaymentsRequest {
|
||||
"java_script_enabled":true
|
||||
}"#)]
|
||||
pub browser_info: Option<serde_json::Value>,
|
||||
/// Payment Issuser for the current payment
|
||||
#[schema(value_type = Option<PaymentIssuer>, example = "klarna")]
|
||||
pub payment_issuer: Option<api_enums::PaymentIssuer>,
|
||||
/// Payment Experience, works in tandem with payment_issuer
|
||||
#[schema(value_type = Option<PaymentExperience>, example = "redirect_to_url")]
|
||||
pub payment_experience: Option<api_enums::PaymentExperience>,
|
||||
}
|
||||
|
||||
#[derive(Default, Debug, serde::Deserialize, serde::Serialize, Clone, Copy, PartialEq, Eq)]
|
||||
@ -342,35 +348,27 @@ pub enum AfterpayClearpayIssuer {
|
||||
pub enum PayLaterData {
|
||||
/// For KlarnaRedirect as PayLater Option
|
||||
KlarnaRedirect {
|
||||
/// The issuer name of the redirect
|
||||
issuer_name: KlarnaIssuer,
|
||||
/// The billing email
|
||||
billing_email: String,
|
||||
#[schema(value_type = String)]
|
||||
billing_email: Secret<String, pii::Email>,
|
||||
// The billing country code
|
||||
billing_country: String,
|
||||
},
|
||||
/// For Klarna Sdk as PayLater Option
|
||||
KlarnaSdk {
|
||||
/// The issuer name of the sdk
|
||||
issuer_name: KlarnaIssuer,
|
||||
/// The token for the sdk workflow
|
||||
token: String,
|
||||
},
|
||||
/// For Affirm redirect as PayLater Option
|
||||
AffirmRedirect {
|
||||
/// The issuer name of affirm redirect issuer
|
||||
issuer_name: AffirmIssuer,
|
||||
/// The billing email
|
||||
billing_email: String,
|
||||
},
|
||||
AffirmRedirect {},
|
||||
/// For AfterpayClearpay redirect as PayLater Option
|
||||
AfterpayClearpayRedirect {
|
||||
/// The issuer name of afterpayclearpay redirect issuer
|
||||
issuer_name: AfterpayClearpayIssuer,
|
||||
/// The billing email
|
||||
billing_email: String,
|
||||
#[schema(value_type = String)]
|
||||
billing_email: Secret<String, pii::Email>,
|
||||
/// The billing name
|
||||
billing_name: String,
|
||||
#[schema(value_type = String)]
|
||||
billing_name: Secret<String>,
|
||||
},
|
||||
}
|
||||
|
||||
|
||||
@ -86,7 +86,7 @@ pub mod iso8601 {
|
||||
}
|
||||
}
|
||||
|
||||
/// https://github.com/serde-rs/serde/issues/994#issuecomment-316895860
|
||||
/// <https://github.com/serde-rs/serde/issues/994#issuecomment-316895860>
|
||||
|
||||
pub mod json_string {
|
||||
use serde::de::{self, Deserialize, DeserializeOwned, Deserializer};
|
||||
|
||||
@ -216,7 +216,6 @@ impl<F, T>
|
||||
response: Ok(types::PaymentsResponseData::TransactionResponse {
|
||||
resource_id: types::ResponseId::ConnectorTransactionId(item.response.id),
|
||||
redirection_data: None,
|
||||
redirect: false,
|
||||
mandate_reference: None,
|
||||
connector_metadata: None,
|
||||
}),
|
||||
|
||||
@ -672,7 +672,6 @@ impl TryFrom<types::PaymentsCancelResponseRouterData<AdyenCancelResponse>>
|
||||
response: Ok(types::PaymentsResponseData::TransactionResponse {
|
||||
resource_id: types::ResponseId::ConnectorTransactionId(item.response.psp_reference),
|
||||
redirection_data: None,
|
||||
redirect: false,
|
||||
mandate_reference: None,
|
||||
connector_metadata: None,
|
||||
}),
|
||||
@ -722,7 +721,6 @@ pub fn get_adyen_response(
|
||||
let payments_response_data = types::PaymentsResponseData::TransactionResponse {
|
||||
resource_id: types::ResponseId::ConnectorTransactionId(response.psp_reference),
|
||||
redirection_data: None,
|
||||
redirect: false,
|
||||
mandate_reference: None,
|
||||
connector_metadata: None,
|
||||
};
|
||||
@ -783,7 +781,6 @@ pub fn get_redirection_response(
|
||||
let payments_response_data = types::PaymentsResponseData::TransactionResponse {
|
||||
resource_id: types::ResponseId::NoResponseId,
|
||||
redirection_data: Some(redirection_data),
|
||||
redirect: true,
|
||||
mandate_reference: None,
|
||||
connector_metadata: None,
|
||||
};
|
||||
@ -876,7 +873,6 @@ impl TryFrom<types::PaymentsCaptureResponseRouterData<AdyenCaptureResponse>>
|
||||
status,
|
||||
response: Ok(types::PaymentsResponseData::TransactionResponse {
|
||||
resource_id: types::ResponseId::ConnectorTransactionId(item.response.psp_reference),
|
||||
redirect: false,
|
||||
redirection_data: None,
|
||||
mandate_reference: None,
|
||||
connector_metadata: None,
|
||||
|
||||
@ -329,7 +329,6 @@ impl<F, T>
|
||||
item.response.transaction_response.transaction_id,
|
||||
),
|
||||
redirection_data: None,
|
||||
redirect: false,
|
||||
mandate_reference: None,
|
||||
connector_metadata: metadata,
|
||||
}),
|
||||
@ -606,7 +605,6 @@ impl<F, Req>
|
||||
item.response.transaction.transaction_id,
|
||||
),
|
||||
redirection_data: None,
|
||||
redirect: false,
|
||||
mandate_reference: None,
|
||||
connector_metadata: None,
|
||||
}),
|
||||
|
||||
@ -219,7 +219,6 @@ impl<F, T>
|
||||
item.response.transaction.id,
|
||||
),
|
||||
redirection_data: None,
|
||||
redirect: false,
|
||||
mandate_reference: None,
|
||||
connector_metadata: None,
|
||||
}),
|
||||
|
||||
@ -246,7 +246,6 @@ impl TryFrom<types::PaymentsResponseRouterData<PaymentsResponse>>
|
||||
)),
|
||||
response: Ok(types::PaymentsResponseData::TransactionResponse {
|
||||
resource_id: types::ResponseId::ConnectorTransactionId(item.response.id),
|
||||
redirect: redirection_data.is_some(),
|
||||
redirection_data,
|
||||
mandate_reference: None,
|
||||
connector_metadata: None,
|
||||
@ -289,7 +288,6 @@ impl TryFrom<types::PaymentsSyncResponseRouterData<PaymentsResponse>>
|
||||
)),
|
||||
response: Ok(types::PaymentsResponseData::TransactionResponse {
|
||||
resource_id: types::ResponseId::ConnectorTransactionId(item.response.id),
|
||||
redirect: redirection_data.is_some(),
|
||||
redirection_data,
|
||||
mandate_reference: None,
|
||||
connector_metadata: None,
|
||||
@ -332,7 +330,6 @@ impl TryFrom<types::PaymentsCancelResponseRouterData<PaymentVoidResponse>>
|
||||
Ok(Self {
|
||||
response: Ok(types::PaymentsResponseData::TransactionResponse {
|
||||
resource_id: types::ResponseId::ConnectorTransactionId(response.action_id.clone()),
|
||||
redirect: false,
|
||||
redirection_data: None,
|
||||
mandate_reference: None,
|
||||
connector_metadata: None,
|
||||
@ -404,7 +401,6 @@ impl TryFrom<types::PaymentsCaptureResponseRouterData<PaymentCaptureResponse>>
|
||||
resource_id: types::ResponseId::ConnectorTransactionId(
|
||||
item.data.request.connector_transaction_id.to_owned(),
|
||||
),
|
||||
redirect: false,
|
||||
redirection_data: None,
|
||||
mandate_reference: None,
|
||||
connector_metadata: None,
|
||||
|
||||
@ -315,7 +315,6 @@ impl<F, T>
|
||||
_ => Ok(types::PaymentsResponseData::TransactionResponse {
|
||||
resource_id: types::ResponseId::ConnectorTransactionId(item.response.id),
|
||||
redirection_data: None,
|
||||
redirect: false,
|
||||
mandate_reference: None,
|
||||
connector_metadata: None,
|
||||
}),
|
||||
@ -379,7 +378,6 @@ impl<F, T>
|
||||
response: Ok(types::PaymentsResponseData::TransactionResponse {
|
||||
resource_id: types::ResponseId::ConnectorTransactionId(item.response.id),
|
||||
redirection_data: None,
|
||||
redirect: false,
|
||||
mandate_reference: None,
|
||||
connector_metadata: None,
|
||||
}),
|
||||
|
||||
@ -226,7 +226,6 @@ impl<F, T>
|
||||
gateway_resp.transaction_processing_details.transaction_id,
|
||||
),
|
||||
redirection_data: None,
|
||||
redirect: false,
|
||||
mandate_reference: None,
|
||||
connector_metadata: None,
|
||||
}),
|
||||
|
||||
@ -165,7 +165,6 @@ fn get_payment_response(
|
||||
_ => Ok(types::PaymentsResponseData::TransactionResponse {
|
||||
resource_id: types::ResponseId::ConnectorTransactionId(response.id),
|
||||
redirection_data: None,
|
||||
redirect: false,
|
||||
mandate_reference: None,
|
||||
connector_metadata: None,
|
||||
}),
|
||||
|
||||
@ -13,6 +13,7 @@ use crate::{
|
||||
types::{
|
||||
self,
|
||||
api::{self, ConnectorCommon},
|
||||
storage::enums as storage_enums,
|
||||
},
|
||||
utils::{self, BytesExt},
|
||||
};
|
||||
@ -235,12 +236,27 @@ impl
|
||||
match payment_method_data {
|
||||
api_payments::PaymentMethod::PayLater(api_payments::PayLaterData::KlarnaSdk {
|
||||
token,
|
||||
..
|
||||
}) => Ok(format!(
|
||||
"{}payments/v1/authorizations/{}/order",
|
||||
self.base_url(connectors),
|
||||
token
|
||||
)),
|
||||
}) => match (
|
||||
req.request.payment_issuer.as_ref(),
|
||||
req.request.payment_experience.as_ref(),
|
||||
) {
|
||||
(
|
||||
Some(storage_enums::PaymentIssuer::Klarna),
|
||||
Some(storage_enums::PaymentExperience::InvokeSdkClient),
|
||||
) => Ok(format!(
|
||||
"{}payments/v1/authorizations/{}/order",
|
||||
self.base_url(connectors),
|
||||
token
|
||||
)),
|
||||
(None, _) | (_, None) => Err(error_stack::report!(
|
||||
errors::ConnectorError::MissingRequiredField {
|
||||
field_name: "payment_issuer and payment_experience"
|
||||
}
|
||||
)),
|
||||
_ => Err(error_stack::report!(
|
||||
errors::ConnectorError::MismatchedPaymentData
|
||||
)),
|
||||
},
|
||||
_ => Err(error_stack::report!(
|
||||
errors::ConnectorError::NotImplemented(
|
||||
"We only support wallet payments through klarna".to_string(),
|
||||
|
||||
@ -114,7 +114,6 @@ impl TryFrom<types::PaymentsResponseRouterData<KlarnaPaymentsResponse>>
|
||||
Ok(Self {
|
||||
response: Ok(types::PaymentsResponseData::TransactionResponse {
|
||||
resource_id: types::ResponseId::ConnectorTransactionId(item.response.order_id),
|
||||
redirect: false,
|
||||
redirection_data: None,
|
||||
mandate_reference: None,
|
||||
connector_metadata: None,
|
||||
|
||||
@ -207,7 +207,6 @@ impl<F, T>
|
||||
status: enums::AttemptStatus::from(item.response.status.status_code),
|
||||
response: Ok(types::PaymentsResponseData::TransactionResponse {
|
||||
resource_id: types::ResponseId::ConnectorTransactionId(item.response.order_id),
|
||||
redirect: false,
|
||||
redirection_data: None,
|
||||
mandate_reference: None,
|
||||
connector_metadata: None,
|
||||
@ -258,7 +257,6 @@ impl<F, T>
|
||||
status: enums::AttemptStatus::from(item.response.status.status_code.clone()),
|
||||
response: Ok(types::PaymentsResponseData::TransactionResponse {
|
||||
resource_id: types::ResponseId::NoResponseId,
|
||||
redirect: false,
|
||||
redirection_data: None,
|
||||
mandate_reference: None,
|
||||
connector_metadata: None,
|
||||
@ -337,7 +335,6 @@ impl<F, T>
|
||||
status: enums::AttemptStatus::from(item.response.status.status_code.clone()),
|
||||
response: Ok(types::PaymentsResponseData::TransactionResponse {
|
||||
resource_id: types::ResponseId::ConnectorTransactionId(item.response.order_id),
|
||||
redirect: false,
|
||||
redirection_data: None,
|
||||
mandate_reference: None,
|
||||
connector_metadata: None,
|
||||
@ -466,7 +463,6 @@ impl<F, T>
|
||||
status: enums::AttemptStatus::from(order.status.clone()),
|
||||
response: Ok(types::PaymentsResponseData::TransactionResponse {
|
||||
resource_id: types::ResponseId::ConnectorTransactionId(order.order_id.clone()),
|
||||
redirect: false,
|
||||
redirection_data: None,
|
||||
mandate_reference: None,
|
||||
connector_metadata: None,
|
||||
|
||||
@ -414,7 +414,6 @@ impl<F, T>
|
||||
resource_id: types::ResponseId::ConnectorTransactionId(
|
||||
data.id.to_owned(),
|
||||
), //transaction_id is also the field but this id is used to initiate a refund
|
||||
redirect: redirection_data.is_some(),
|
||||
redirection_data,
|
||||
mandate_reference: None,
|
||||
connector_metadata: None,
|
||||
|
||||
@ -154,7 +154,6 @@ impl<F, T>
|
||||
response: Ok(types::PaymentsResponseData::TransactionResponse {
|
||||
resource_id: types::ResponseId::ConnectorTransactionId(item.response.id),
|
||||
redirection_data: None,
|
||||
redirect: false,
|
||||
mandate_reference: None,
|
||||
connector_metadata: None,
|
||||
}),
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
use std::str::FromStr;
|
||||
|
||||
use api_models::{self, payments};
|
||||
use common_utils::fp_utils;
|
||||
use common_utils::{fp_utils, pii::Email};
|
||||
use error_stack::{IntoReport, ResultExt};
|
||||
use masking::ExposeInterface;
|
||||
use serde::{Deserialize, Serialize};
|
||||
@ -80,12 +80,13 @@ pub struct PaymentIntentRequest {
|
||||
pub metadata_txn_uuid: String,
|
||||
pub return_url: String,
|
||||
pub confirm: bool,
|
||||
pub off_session: Option<bool>,
|
||||
pub mandate: Option<String>,
|
||||
pub description: Option<String>,
|
||||
#[serde(flatten)]
|
||||
pub shipping: StripeShippingAddress,
|
||||
#[serde(flatten)]
|
||||
pub billing: StripeBillingAddress,
|
||||
#[serde(flatten)]
|
||||
pub payment_data: Option<StripePaymentMethodData>,
|
||||
pub capture_method: StripeCaptureMethod,
|
||||
}
|
||||
@ -128,27 +129,19 @@ pub struct StripePayLaterData {
|
||||
pub payment_method_types: StripePaymentMethodType,
|
||||
#[serde(rename = "payment_method_data[type]")]
|
||||
pub payment_method_data_type: StripePaymentMethodType,
|
||||
#[serde(rename = "payment_method_data[billing_details][email]")]
|
||||
pub billing_email: String,
|
||||
#[serde(rename = "payment_method_data[billing_details][address][country]")]
|
||||
pub billing_country: Option<String>,
|
||||
#[serde(rename = "payment_method_data[billing_details][name]")]
|
||||
pub billing_name: Option<String>,
|
||||
}
|
||||
|
||||
#[derive(Debug, Eq, PartialEq, Serialize)]
|
||||
#[serde(untagged)]
|
||||
pub enum StripePaymentMethodData {
|
||||
Card(StripeCardData),
|
||||
Klarna(StripePayLaterData),
|
||||
Affirm(StripePayLaterData),
|
||||
AfterpayClearpay(StripePayLaterData),
|
||||
PayLater(StripePayLaterData),
|
||||
Bank,
|
||||
Wallet,
|
||||
Paypal,
|
||||
}
|
||||
|
||||
#[derive(Debug, Eq, PartialEq, Serialize)]
|
||||
#[derive(Debug, Eq, PartialEq, Serialize, Clone)]
|
||||
#[serde(rename_all = "snake_case")]
|
||||
pub enum StripePaymentMethodType {
|
||||
Card,
|
||||
@ -159,63 +152,165 @@ pub enum StripePaymentMethodType {
|
||||
|
||||
fn validate_shipping_address_against_payment_method(
|
||||
shipping_address: &StripeShippingAddress,
|
||||
payment_method: &payments::PaymentMethod,
|
||||
payment_method: &StripePaymentMethodType,
|
||||
) -> Result<(), errors::ConnectorError> {
|
||||
if let payments::PaymentMethod::PayLater(payments::PayLaterData::AfterpayClearpayRedirect {
|
||||
..
|
||||
}) = payment_method
|
||||
{
|
||||
if let StripePaymentMethodType::AfterpayClearpay = payment_method {
|
||||
fp_utils::when(shipping_address.name.is_none(), || {
|
||||
Err(errors::ConnectorError::MissingRequiredField {
|
||||
field_name: "shipping.first_name",
|
||||
field_name: "shipping.address.first_name",
|
||||
})
|
||||
})?;
|
||||
|
||||
fp_utils::when(shipping_address.line1.is_none(), || {
|
||||
Err(errors::ConnectorError::MissingRequiredField {
|
||||
field_name: "shipping.line1",
|
||||
field_name: "shipping.address.line1",
|
||||
})
|
||||
})?;
|
||||
|
||||
fp_utils::when(shipping_address.country.is_none(), || {
|
||||
Err(errors::ConnectorError::MissingRequiredField {
|
||||
field_name: "shipping.country",
|
||||
field_name: "shipping.address.country",
|
||||
})
|
||||
})?;
|
||||
|
||||
fp_utils::when(shipping_address.zip.is_none(), || {
|
||||
Err(errors::ConnectorError::MissingRequiredField {
|
||||
field_name: "shipping.zip",
|
||||
field_name: "shipping.address.zip",
|
||||
})
|
||||
})?;
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn infer_stripe_pay_later_issuer(
|
||||
issuer: &enums::PaymentIssuer,
|
||||
experience: &enums::PaymentExperience,
|
||||
) -> Result<StripePaymentMethodType, errors::ConnectorError> {
|
||||
if &enums::PaymentExperience::RedirectToUrl == experience {
|
||||
match issuer {
|
||||
enums::PaymentIssuer::Klarna => Ok(StripePaymentMethodType::Klarna),
|
||||
enums::PaymentIssuer::Affirm => Ok(StripePaymentMethodType::Affirm),
|
||||
enums::PaymentIssuer::AfterpayClearpay => Ok(StripePaymentMethodType::AfterpayClearpay),
|
||||
_ => Err(errors::ConnectorError::NotSupported {
|
||||
payment_method: format!("{issuer} payments by {experience}"),
|
||||
connector: "stripe",
|
||||
}),
|
||||
}
|
||||
} else {
|
||||
Err(errors::ConnectorError::NotSupported {
|
||||
payment_method: format!("{issuer} payments by {experience}"),
|
||||
connector: "stripe",
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
impl TryFrom<(&api_models::payments::PayLaterData, StripePaymentMethodType)>
|
||||
for StripeBillingAddress
|
||||
{
|
||||
type Error = errors::ConnectorError;
|
||||
|
||||
fn try_from(
|
||||
(pay_later_data, pm_type): (&api_models::payments::PayLaterData, StripePaymentMethodType),
|
||||
) -> Result<Self, Self::Error> {
|
||||
match (pay_later_data, pm_type) {
|
||||
(
|
||||
payments::PayLaterData::KlarnaRedirect {
|
||||
billing_email,
|
||||
billing_country,
|
||||
},
|
||||
StripePaymentMethodType::Klarna,
|
||||
) => Ok(Self {
|
||||
email: Some(billing_email.to_owned()),
|
||||
country: Some(billing_country.to_owned()),
|
||||
..Self::default()
|
||||
}),
|
||||
(payments::PayLaterData::AffirmRedirect {}, StripePaymentMethodType::Affirm) => {
|
||||
Ok(Self::default())
|
||||
}
|
||||
(
|
||||
payments::PayLaterData::AfterpayClearpayRedirect {
|
||||
billing_email,
|
||||
billing_name,
|
||||
},
|
||||
StripePaymentMethodType::AfterpayClearpay,
|
||||
) => Ok(Self {
|
||||
email: Some(billing_email.to_owned()),
|
||||
name: Some(billing_name.to_owned()),
|
||||
..Self::default()
|
||||
}),
|
||||
_ => Err(errors::ConnectorError::MismatchedPaymentData),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn create_stripe_payment_method(
|
||||
issuer: Option<&enums::PaymentIssuer>,
|
||||
experience: Option<&enums::PaymentExperience>,
|
||||
payment_method: &api_models::payments::PaymentMethod,
|
||||
auth_type: enums::AuthenticationType,
|
||||
) -> Result<
|
||||
(
|
||||
StripePaymentMethodData,
|
||||
StripePaymentMethodType,
|
||||
StripeBillingAddress,
|
||||
),
|
||||
errors::ConnectorError,
|
||||
> {
|
||||
match payment_method {
|
||||
payments::PaymentMethod::Card(card_details) => {
|
||||
let payment_method_auth_type = match auth_type {
|
||||
enums::AuthenticationType::ThreeDs => Auth3ds::Any,
|
||||
enums::AuthenticationType::NoThreeDs => Auth3ds::Automatic,
|
||||
};
|
||||
Ok((
|
||||
StripePaymentMethodData::Card(StripeCardData {
|
||||
payment_method_types: StripePaymentMethodType::Card,
|
||||
payment_method_data_type: StripePaymentMethodType::Card,
|
||||
payment_method_data_card_number: card_details.card_number.clone(),
|
||||
payment_method_data_card_exp_month: card_details.card_exp_month.clone(),
|
||||
payment_method_data_card_exp_year: card_details.card_exp_year.clone(),
|
||||
payment_method_data_card_cvc: card_details.card_cvc.clone(),
|
||||
payment_method_auth_type,
|
||||
}),
|
||||
StripePaymentMethodType::Card,
|
||||
StripeBillingAddress::default(),
|
||||
))
|
||||
}
|
||||
payments::PaymentMethod::PayLater(pay_later_data) => {
|
||||
let pm_issuer = issuer.ok_or(errors::ConnectorError::MissingRequiredField {
|
||||
field_name: "payment_issuer",
|
||||
})?;
|
||||
|
||||
let pm_experience = experience.ok_or(errors::ConnectorError::MissingRequiredField {
|
||||
field_name: "payment_experience",
|
||||
})?;
|
||||
|
||||
let pm_type = infer_stripe_pay_later_issuer(pm_issuer, pm_experience)?;
|
||||
|
||||
let billing_address =
|
||||
StripeBillingAddress::try_from((pay_later_data, pm_type.clone()))?;
|
||||
|
||||
Ok((
|
||||
StripePaymentMethodData::PayLater(StripePayLaterData {
|
||||
payment_method_types: pm_type.clone(),
|
||||
payment_method_data_type: pm_type.clone(),
|
||||
}),
|
||||
pm_type,
|
||||
billing_address,
|
||||
))
|
||||
}
|
||||
_ => Err(errors::ConnectorError::NotImplemented(
|
||||
"stripe does not support this payment method".to_string(),
|
||||
)),
|
||||
}
|
||||
}
|
||||
|
||||
impl TryFrom<&types::PaymentsAuthorizeRouterData> for PaymentIntentRequest {
|
||||
type Error = errors::ConnectorError;
|
||||
fn try_from(item: &types::PaymentsAuthorizeRouterData) -> Result<Self, Self::Error> {
|
||||
let metadata_order_id = item.payment_id.to_string();
|
||||
let metadata_txn_id = format!("{}_{}_{}", item.merchant_id, item.payment_id, "1");
|
||||
let metadata_txn_uuid = Uuid::new_v4().to_string(); //Fetch autogenerated txn_uuid from Database.
|
||||
// let api::PaymentMethod::Card(a) = item.payment_method_data;
|
||||
// let api::PaymentMethod::Card(a) = item.payment_method_data;
|
||||
|
||||
let (payment_data, mandate) = {
|
||||
match item
|
||||
.request
|
||||
.mandate_id
|
||||
.clone()
|
||||
.and_then(|mandate_ids| mandate_ids.connector_mandate_id)
|
||||
{
|
||||
None => {
|
||||
let payment_method: StripePaymentMethodData =
|
||||
(item.request.payment_method_data.clone(), item.auth_type).try_into()?;
|
||||
(Some(payment_method), None)
|
||||
}
|
||||
Some(mandate_id) => (None, Some(mandate_id)),
|
||||
}
|
||||
};
|
||||
|
||||
let shipping_address = match item.address.shipping.clone() {
|
||||
Some(mut shipping) => StripeShippingAddress {
|
||||
@ -247,15 +342,32 @@ impl TryFrom<&types::PaymentsAuthorizeRouterData> for PaymentIntentRequest {
|
||||
None => StripeShippingAddress::default(),
|
||||
};
|
||||
|
||||
validate_shipping_address_against_payment_method(
|
||||
&shipping_address,
|
||||
&item.request.payment_method_data,
|
||||
)?;
|
||||
let (payment_data, mandate, billing_address) = {
|
||||
match item
|
||||
.request
|
||||
.mandate_id
|
||||
.clone()
|
||||
.and_then(|mandate_ids| mandate_ids.connector_mandate_id)
|
||||
{
|
||||
None => {
|
||||
let (payment_method_data, payment_method_type, billing_address) =
|
||||
create_stripe_payment_method(
|
||||
item.request.payment_issuer.as_ref(),
|
||||
item.request.payment_experience.as_ref(),
|
||||
&item.request.payment_method_data,
|
||||
item.auth_type,
|
||||
)?;
|
||||
|
||||
let off_session = item
|
||||
.request
|
||||
.off_session
|
||||
.and_then(|value| mandate.as_ref().map(|_| value));
|
||||
validate_shipping_address_against_payment_method(
|
||||
&shipping_address,
|
||||
&payment_method_type,
|
||||
)?;
|
||||
|
||||
(Some(payment_method_data), None, billing_address)
|
||||
}
|
||||
Some(mandate_id) => (None, Some(mandate_id), StripeBillingAddress::default()),
|
||||
}
|
||||
};
|
||||
|
||||
Ok(Self {
|
||||
amount: item.request.amount, //hopefully we don't loose some cents here
|
||||
@ -272,9 +384,9 @@ impl TryFrom<&types::PaymentsAuthorizeRouterData> for PaymentIntentRequest {
|
||||
|
||||
description: item.description.clone(),
|
||||
shipping: shipping_address,
|
||||
billing: billing_address,
|
||||
capture_method: StripeCaptureMethod::from(item.request.capture_method),
|
||||
payment_data,
|
||||
off_session,
|
||||
mandate,
|
||||
})
|
||||
}
|
||||
@ -287,8 +399,13 @@ impl TryFrom<&types::VerifyRouterData> for SetupIntentRequest {
|
||||
let metadata_txn_id = format!("{}_{}_{}", item.merchant_id, item.payment_id, "1");
|
||||
let metadata_txn_uuid = Uuid::new_v4().to_string();
|
||||
|
||||
let payment_data: StripePaymentMethodData =
|
||||
(item.request.payment_method_data.clone(), item.auth_type).try_into()?;
|
||||
//Only cards supported for mandates
|
||||
let pm_type = StripePaymentMethodType::Card;
|
||||
let payment_data = StripePaymentMethodData::try_from((
|
||||
item.request.payment_method_data.clone(),
|
||||
item.auth_type,
|
||||
pm_type,
|
||||
))?;
|
||||
|
||||
Ok(Self {
|
||||
confirm: true,
|
||||
@ -421,7 +538,6 @@ impl<F, T>
|
||||
// three_ds_form,
|
||||
response: Ok(types::PaymentsResponseData::TransactionResponse {
|
||||
resource_id: types::ResponseId::ConnectorTransactionId(item.response.id),
|
||||
redirect: redirection_data.is_some(),
|
||||
redirection_data,
|
||||
mandate_reference,
|
||||
connector_metadata: None,
|
||||
@ -473,7 +589,6 @@ impl<F, T>
|
||||
status: enums::AttemptStatus::from(item.response.status),
|
||||
response: Ok(types::PaymentsResponseData::TransactionResponse {
|
||||
resource_id: types::ResponseId::ConnectorTransactionId(item.response.id),
|
||||
redirect: redirection_data.is_some(),
|
||||
redirection_data,
|
||||
mandate_reference,
|
||||
connector_metadata: None,
|
||||
@ -649,13 +764,23 @@ pub struct StripeShippingAddress {
|
||||
pub phone: Option<Secret<String>>,
|
||||
}
|
||||
|
||||
#[derive(Debug, Default, Eq, PartialEq, Serialize)]
|
||||
pub struct StripeBillingAddress {
|
||||
#[serde(rename = "payment_method_data[billing_details][email]")]
|
||||
pub email: Option<Secret<String, Email>>,
|
||||
#[serde(rename = "payment_method_data[billing_details][address][country]")]
|
||||
pub country: Option<String>,
|
||||
#[serde(rename = "payment_method_data[billing_details][name]")]
|
||||
pub name: Option<Secret<String>>,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, serde::Deserialize, Eq, PartialEq)]
|
||||
pub struct StripeRedirectResponse {
|
||||
pub payment_intent: String,
|
||||
pub payment_intent_client_secret: String,
|
||||
pub source_redirect_slug: Option<String>,
|
||||
pub redirect_status: Option<StripePaymentStatus>,
|
||||
pub source_type: Option<String>,
|
||||
pub source_type: Option<Secret<String>>,
|
||||
}
|
||||
|
||||
#[derive(Debug, Serialize, Clone, Copy)]
|
||||
@ -792,10 +917,20 @@ pub struct StripeWebhookObjectId {
|
||||
pub data: StripeWebhookDataId,
|
||||
}
|
||||
|
||||
impl TryFrom<(api::PaymentMethod, enums::AuthenticationType)> for StripePaymentMethodData {
|
||||
impl
|
||||
TryFrom<(
|
||||
api::PaymentMethod,
|
||||
enums::AuthenticationType,
|
||||
StripePaymentMethodType,
|
||||
)> for StripePaymentMethodData
|
||||
{
|
||||
type Error = errors::ConnectorError;
|
||||
fn try_from(
|
||||
(pm_data, auth_type): (api::PaymentMethod, enums::AuthenticationType),
|
||||
(pm_data, auth_type, pm_type): (
|
||||
api::PaymentMethod,
|
||||
enums::AuthenticationType,
|
||||
StripePaymentMethodType,
|
||||
),
|
||||
) -> Result<Self, Self::Error> {
|
||||
match pm_data {
|
||||
api::PaymentMethod::Card(ref ccard) => Ok(Self::Card({
|
||||
@ -814,42 +949,10 @@ impl TryFrom<(api::PaymentMethod, enums::AuthenticationType)> for StripePaymentM
|
||||
}
|
||||
})),
|
||||
api::PaymentMethod::BankTransfer => Ok(Self::Bank),
|
||||
api::PaymentMethod::PayLater(pay_later_data) => match pay_later_data {
|
||||
api_models::payments::PayLaterData::KlarnaRedirect {
|
||||
billing_email,
|
||||
billing_country,
|
||||
..
|
||||
} => Ok(Self::Klarna(StripePayLaterData {
|
||||
payment_method_types: StripePaymentMethodType::Klarna,
|
||||
payment_method_data_type: StripePaymentMethodType::Klarna,
|
||||
billing_email,
|
||||
billing_country: Some(billing_country),
|
||||
billing_name: None,
|
||||
})),
|
||||
api_models::payments::PayLaterData::AffirmRedirect { billing_email, .. } => {
|
||||
Ok(Self::Affirm(StripePayLaterData {
|
||||
payment_method_types: StripePaymentMethodType::Affirm,
|
||||
payment_method_data_type: StripePaymentMethodType::Affirm,
|
||||
billing_email,
|
||||
billing_country: None,
|
||||
billing_name: None,
|
||||
}))
|
||||
}
|
||||
api_models::payments::PayLaterData::AfterpayClearpayRedirect {
|
||||
billing_email,
|
||||
billing_name,
|
||||
..
|
||||
} => Ok(Self::AfterpayClearpay(StripePayLaterData {
|
||||
payment_method_types: StripePaymentMethodType::AfterpayClearpay,
|
||||
payment_method_data_type: StripePaymentMethodType::AfterpayClearpay,
|
||||
billing_email,
|
||||
billing_country: None,
|
||||
billing_name: Some(billing_name),
|
||||
})),
|
||||
_ => Err(errors::ConnectorError::NotImplemented(String::from(
|
||||
"Stripe does not support payment through provided payment method",
|
||||
))),
|
||||
},
|
||||
api::PaymentMethod::PayLater(_) => Ok(Self::PayLater(StripePayLaterData {
|
||||
payment_method_types: pm_type.clone(),
|
||||
payment_method_data_type: pm_type,
|
||||
})),
|
||||
api::PaymentMethod::Wallet(_) => Ok(Self::Wallet),
|
||||
api::PaymentMethod::Paypal => Ok(Self::Paypal),
|
||||
}
|
||||
|
||||
@ -357,7 +357,6 @@ impl<F, T> TryFrom<types::ResponseRouterData<F, Payment, T, types::PaymentsRespo
|
||||
response: Ok(types::PaymentsResponseData::TransactionResponse {
|
||||
resource_id: types::ResponseId::ConnectorTransactionId(item.response.id),
|
||||
redirection_data: None,
|
||||
redirect: false,
|
||||
mandate_reference: None,
|
||||
connector_metadata: None,
|
||||
}),
|
||||
@ -386,7 +385,6 @@ impl<F, T> TryFrom<types::ResponseRouterData<F, PaymentResponse, T, types::Payme
|
||||
response: Ok(types::PaymentsResponseData::TransactionResponse {
|
||||
resource_id: types::ResponseId::ConnectorTransactionId(item.response.payment.id),
|
||||
redirection_data: None,
|
||||
redirect: false,
|
||||
mandate_reference: None,
|
||||
connector_metadata: None,
|
||||
}),
|
||||
|
||||
@ -160,7 +160,6 @@ impl ConnectorIntegration<api::Void, types::PaymentsCancelData, types::PaymentsR
|
||||
response: Ok(types::PaymentsResponseData::TransactionResponse {
|
||||
resource_id: types::ResponseId::try_from(response.links)?,
|
||||
redirection_data: None,
|
||||
redirect: false,
|
||||
mandate_reference: None,
|
||||
connector_metadata: None,
|
||||
}),
|
||||
@ -256,7 +255,6 @@ impl ConnectorIntegration<api::PSync, types::PaymentsSyncData, types::PaymentsRe
|
||||
response: Ok(types::PaymentsResponseData::TransactionResponse {
|
||||
resource_id: data.request.connector_transaction_id.clone(),
|
||||
redirection_data: None,
|
||||
redirect: false,
|
||||
mandate_reference: None,
|
||||
connector_metadata: None,
|
||||
}),
|
||||
@ -314,7 +312,6 @@ impl ConnectorIntegration<api::Capture, types::PaymentsCaptureData, types::Payme
|
||||
response: Ok(types::PaymentsResponseData::TransactionResponse {
|
||||
resource_id: types::ResponseId::try_from(response.links)?,
|
||||
redirection_data: None,
|
||||
redirect: false,
|
||||
mandate_reference: None,
|
||||
connector_metadata: None,
|
||||
}),
|
||||
|
||||
@ -167,7 +167,6 @@ impl TryFrom<types::PaymentsResponseRouterData<WorldpayPaymentsResponse>>
|
||||
response: Ok(types::PaymentsResponseData::TransactionResponse {
|
||||
resource_id: types::ResponseId::try_from(item.response.links)?,
|
||||
redirection_data: None,
|
||||
redirect: false,
|
||||
mandate_reference: None,
|
||||
connector_metadata: None,
|
||||
}),
|
||||
|
||||
@ -248,6 +248,11 @@ pub enum ConnectorError {
|
||||
FailedToObtainCertificateKey,
|
||||
#[error("This step has not been implemented for: {0}")]
|
||||
NotImplemented(String),
|
||||
#[error("{payment_method} is not supported by {connector}")]
|
||||
NotSupported {
|
||||
payment_method: String,
|
||||
connector: &'static str,
|
||||
},
|
||||
#[error("Missing connector transaction ID")]
|
||||
MissingConnectorTransactionID,
|
||||
#[error("Missing connector refund ID")]
|
||||
@ -270,6 +275,8 @@ pub enum ConnectorError {
|
||||
WebhookResourceObjectNotFound,
|
||||
#[error("Invalid Date/time format")]
|
||||
InvalidDateFormat,
|
||||
#[error("Payment Issuer does not match the Payment Data provided")]
|
||||
MismatchedPaymentData,
|
||||
}
|
||||
|
||||
#[derive(Debug, thiserror::Error)]
|
||||
|
||||
@ -101,6 +101,12 @@ impl ConnectorErrorExt for error_stack::Report<errors::ConnectorError> {
|
||||
),
|
||||
}
|
||||
}
|
||||
errors::ConnectorError::MismatchedPaymentData => {
|
||||
errors::ApiErrorResponse::InvalidDataValue {
|
||||
field_name:
|
||||
"payment_method_data and payment_issuer, payment_experience does not match",
|
||||
}
|
||||
}
|
||||
_ => errors::ApiErrorResponse::InternalServerError,
|
||||
};
|
||||
self.change_context(error)
|
||||
|
||||
@ -85,9 +85,7 @@ pub async fn add_payment_method(
|
||||
payment_method_issuer_code: req.payment_method_issuer_code,
|
||||
recurring_enabled: false, //[#219]
|
||||
installment_payment_enabled: false, //[#219]
|
||||
payment_experience: Some(vec![
|
||||
api_models::payment_methods::PaymentExperience::RedirectToUrl,
|
||||
]), //[#219]
|
||||
payment_experience: Some(vec![api_models::enums::PaymentExperience::RedirectToUrl]), //[#219]
|
||||
})
|
||||
}
|
||||
}
|
||||
@ -635,9 +633,7 @@ pub async fn list_customer_payment_method(
|
||||
.map(ForeignInto::foreign_into),
|
||||
recurring_enabled: false,
|
||||
installment_payment_enabled: false,
|
||||
payment_experience: Some(vec![
|
||||
api_models::payment_methods::PaymentExperience::RedirectToUrl,
|
||||
]),
|
||||
payment_experience: Some(vec![api_models::enums::PaymentExperience::RedirectToUrl]),
|
||||
created: Some(pm.created_at),
|
||||
};
|
||||
vec.push(pma);
|
||||
@ -880,9 +876,7 @@ pub async fn retrieve_payment_method(
|
||||
.map(ForeignInto::foreign_into),
|
||||
recurring_enabled: false, //[#219]
|
||||
installment_payment_enabled: false, //[#219]
|
||||
payment_experience: Some(vec![
|
||||
api_models::payment_methods::PaymentExperience::RedirectToUrl,
|
||||
]), //[#219],
|
||||
payment_experience: Some(vec![api_models::enums::PaymentExperience::RedirectToUrl]), //[#219],
|
||||
},
|
||||
))
|
||||
}
|
||||
|
||||
@ -127,9 +127,7 @@ pub fn mk_add_card_response(
|
||||
payment_method_issuer_code: req.payment_method_issuer_code,
|
||||
recurring_enabled: false, // [#256]
|
||||
installment_payment_enabled: false, // #[#256]
|
||||
payment_experience: Some(vec![
|
||||
api_models::payment_methods::PaymentExperience::RedirectToUrl,
|
||||
]), // [#256]
|
||||
payment_experience: Some(vec![api_models::enums::PaymentExperience::RedirectToUrl]), // [#256]
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -433,6 +433,8 @@ impl PaymentCreate {
|
||||
last_synced,
|
||||
authentication_type: request.authentication_type.map(ForeignInto::foreign_into),
|
||||
browser_info,
|
||||
payment_experience: request.payment_experience.map(ForeignInto::foreign_into),
|
||||
payment_issuer: request.payment_issuer.map(ForeignInto::foreign_into),
|
||||
..storage::PaymentAttemptNew::default()
|
||||
}
|
||||
}
|
||||
|
||||
@ -280,7 +280,6 @@ async fn payment_response_update_tracker<F: Clone, T>(
|
||||
types::PaymentsResponseData::TransactionResponse {
|
||||
resource_id,
|
||||
redirection_data,
|
||||
redirect,
|
||||
connector_metadata,
|
||||
..
|
||||
} => {
|
||||
@ -305,7 +304,6 @@ async fn payment_response_update_tracker<F: Clone, T>(
|
||||
connector_transaction_id: connector_transaction_id.clone(),
|
||||
authentication_type: None,
|
||||
payment_method_id: Some(router_data.payment_method_id),
|
||||
redirect: Some(redirect),
|
||||
mandate_id: payment_data
|
||||
.mandate_id
|
||||
.clone()
|
||||
|
||||
@ -65,7 +65,6 @@ where
|
||||
.map(|id| types::PaymentsResponseData::TransactionResponse {
|
||||
resource_id: types::ResponseId::ConnectorTransactionId(id.to_string()),
|
||||
redirection_data: None,
|
||||
redirect: false,
|
||||
mandate_reference: None,
|
||||
connector_metadata: None,
|
||||
});
|
||||
@ -430,6 +429,8 @@ impl<F: Clone> TryFrom<PaymentData<F>> for types::PaymentsAuthorizeData {
|
||||
currency: payment_data.currency,
|
||||
browser_info,
|
||||
email: payment_data.email,
|
||||
payment_experience: payment_data.payment_attempt.payment_experience,
|
||||
payment_issuer: payment_data.payment_attempt.payment_issuer,
|
||||
order_details,
|
||||
})
|
||||
}
|
||||
|
||||
@ -227,8 +227,6 @@ impl PaymentAttemptInterface for MockDb {
|
||||
tax_amount: payment_attempt.tax_amount,
|
||||
payment_method_id: payment_attempt.payment_method_id,
|
||||
payment_method: payment_attempt.payment_method,
|
||||
payment_flow: payment_attempt.payment_flow,
|
||||
redirect: payment_attempt.redirect,
|
||||
connector_transaction_id: payment_attempt.connector_transaction_id,
|
||||
capture_method: payment_attempt.capture_method,
|
||||
capture_on: payment_attempt.capture_on,
|
||||
@ -244,6 +242,8 @@ impl PaymentAttemptInterface for MockDb {
|
||||
payment_token: None,
|
||||
error_code: payment_attempt.error_code,
|
||||
connector_metadata: None,
|
||||
payment_experience: payment_attempt.payment_experience,
|
||||
payment_issuer: payment_attempt.payment_issuer,
|
||||
};
|
||||
payment_attempts.push(payment_attempt.clone());
|
||||
Ok(payment_attempt)
|
||||
@ -366,8 +366,6 @@ mod storage {
|
||||
tax_amount: payment_attempt.tax_amount,
|
||||
payment_method_id: payment_attempt.payment_method_id.clone(),
|
||||
payment_method: payment_attempt.payment_method,
|
||||
payment_flow: payment_attempt.payment_flow,
|
||||
redirect: payment_attempt.redirect,
|
||||
connector_transaction_id: payment_attempt.connector_transaction_id.clone(),
|
||||
capture_method: payment_attempt.capture_method,
|
||||
capture_on: payment_attempt.capture_on,
|
||||
@ -383,6 +381,8 @@ mod storage {
|
||||
payment_token: payment_attempt.payment_token.clone(),
|
||||
error_code: payment_attempt.error_code.clone(),
|
||||
connector_metadata: payment_attempt.connector_metadata.clone(),
|
||||
payment_experience: payment_attempt.payment_experience.clone(),
|
||||
payment_issuer: payment_attempt.payment_issuer,
|
||||
};
|
||||
|
||||
let field = format!("pa_{}", created_attempt.attempt_id);
|
||||
|
||||
@ -139,6 +139,8 @@ Never share your secret api keys. Keep them guarded and secure.
|
||||
api_models::enums::SupportedWallets,
|
||||
api_models::enums::PaymentMethodIssuerCode,
|
||||
api_models::enums::MandateStatus,
|
||||
api_models::enums::PaymentExperience,
|
||||
api_models::enums::PaymentIssuer,
|
||||
api_models::admin::PaymentConnectorCreate,
|
||||
api_models::admin::PaymentMethods,
|
||||
api_models::payments::AddressDetails,
|
||||
@ -163,7 +165,6 @@ Never share your secret api keys. Keep them guarded and secure.
|
||||
api_models::payments::CustomerAcceptance,
|
||||
api_models::payments::PaymentsRequest,
|
||||
api_models::payments::PaymentsResponse,
|
||||
api_models::payment_methods::PaymentExperience,
|
||||
api_models::payments::PaymentsStartRequest,
|
||||
api_models::payments::PaymentRetrieveBody,
|
||||
api_models::payments::PaymentsRetrieveRequest,
|
||||
|
||||
@ -115,6 +115,8 @@ pub struct PaymentsAuthorizeData {
|
||||
pub setup_mandate_details: Option<payments::MandateData>,
|
||||
pub browser_info: Option<BrowserInformation>,
|
||||
pub order_details: Option<api_models::payments::OrderDetails>,
|
||||
pub payment_issuer: Option<storage_enums::PaymentIssuer>,
|
||||
pub payment_experience: Option<storage_enums::PaymentExperience>,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
@ -181,7 +183,6 @@ pub enum PaymentsResponseData {
|
||||
TransactionResponse {
|
||||
resource_id: ResponseId,
|
||||
redirection_data: Option<services::RedirectForm>,
|
||||
redirect: bool,
|
||||
mandate_reference: Option<String>,
|
||||
connector_metadata: Option<serde_json::Value>,
|
||||
},
|
||||
|
||||
@ -88,18 +88,6 @@ where
|
||||
}
|
||||
}
|
||||
|
||||
impl From<F<api_enums::RoutingAlgorithm>> for F<storage_enums::RoutingAlgorithm> {
|
||||
fn from(algo: F<api_enums::RoutingAlgorithm>) -> Self {
|
||||
Self(frunk::labelled_convert_from(algo.0))
|
||||
}
|
||||
}
|
||||
|
||||
impl From<F<storage_enums::RoutingAlgorithm>> for F<api_enums::RoutingAlgorithm> {
|
||||
fn from(algo: F<storage_enums::RoutingAlgorithm>) -> Self {
|
||||
Self(frunk::labelled_convert_from(algo.0))
|
||||
}
|
||||
}
|
||||
|
||||
impl From<F<api_enums::ConnectorType>> for F<storage_enums::ConnectorType> {
|
||||
fn from(conn: F<api_enums::ConnectorType>) -> Self {
|
||||
Self(frunk::labelled_convert_from(conn.0))
|
||||
@ -158,6 +146,18 @@ impl From<F<storage_enums::PaymentMethodIssuerCode>> for F<api_enums::PaymentMet
|
||||
}
|
||||
}
|
||||
|
||||
impl From<F<api_enums::PaymentIssuer>> for F<storage_enums::PaymentIssuer> {
|
||||
fn from(issuer: F<api_enums::PaymentIssuer>) -> Self {
|
||||
Self(frunk::labelled_convert_from(issuer.0))
|
||||
}
|
||||
}
|
||||
|
||||
impl From<F<api_enums::PaymentExperience>> for F<storage_enums::PaymentExperience> {
|
||||
fn from(experience: F<api_enums::PaymentExperience>) -> Self {
|
||||
Self(frunk::labelled_convert_from(experience.0))
|
||||
}
|
||||
}
|
||||
|
||||
impl From<F<storage_enums::IntentStatus>> for F<api_enums::IntentStatus> {
|
||||
fn from(status: F<storage_enums::IntentStatus>) -> Self {
|
||||
Self(frunk::labelled_convert_from(status.0))
|
||||
|
||||
@ -50,6 +50,8 @@ fn construct_payment_router_data() -> types::PaymentsAuthorizeRouterData {
|
||||
browser_info: None,
|
||||
order_details: None,
|
||||
email: None,
|
||||
payment_experience: None,
|
||||
payment_issuer: None,
|
||||
},
|
||||
response: Err(types::ErrorResponse::default()),
|
||||
payment_method_id: None,
|
||||
|
||||
@ -78,6 +78,8 @@ impl AdyenTest {
|
||||
browser_info: None,
|
||||
order_details: None,
|
||||
email: None,
|
||||
payment_experience: None,
|
||||
payment_issuer: None,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
@ -50,6 +50,8 @@ fn construct_payment_router_data() -> types::PaymentsAuthorizeRouterData {
|
||||
browser_info: None,
|
||||
order_details: None,
|
||||
email: None,
|
||||
payment_experience: None,
|
||||
payment_issuer: None,
|
||||
},
|
||||
payment_method_id: None,
|
||||
response: Err(types::ErrorResponse::default()),
|
||||
|
||||
@ -47,6 +47,8 @@ fn construct_payment_router_data() -> types::PaymentsAuthorizeRouterData {
|
||||
browser_info: None,
|
||||
order_details: None,
|
||||
email: None,
|
||||
payment_experience: None,
|
||||
payment_issuer: None,
|
||||
},
|
||||
response: Err(types::ErrorResponse::default()),
|
||||
payment_method_id: None,
|
||||
|
||||
@ -469,6 +469,8 @@ impl Default for PaymentAuthorizeType {
|
||||
browser_info: Some(BrowserInfoType::default().0),
|
||||
order_details: None,
|
||||
email: None,
|
||||
payment_experience: None,
|
||||
payment_issuer: None,
|
||||
};
|
||||
Self(data)
|
||||
}
|
||||
|
||||
@ -80,6 +80,8 @@ impl WorldlineTest {
|
||||
browser_info: None,
|
||||
order_details: None,
|
||||
email: None,
|
||||
payment_experience: None,
|
||||
payment_issuer: None,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
@ -327,6 +327,8 @@ async fn payments_create_core() {
|
||||
off_session: None,
|
||||
client_secret: None,
|
||||
browser_info: None,
|
||||
payment_experience: None,
|
||||
payment_issuer: None,
|
||||
};
|
||||
|
||||
let expected_response = api::PaymentsResponse {
|
||||
@ -482,6 +484,8 @@ async fn payments_create_core_adyen_no_redirect() {
|
||||
off_session: None,
|
||||
client_secret: None,
|
||||
browser_info: None,
|
||||
payment_experience: None,
|
||||
payment_issuer: None,
|
||||
};
|
||||
|
||||
let expected_response = services::ApplicationResponse::Json(api::PaymentsResponse {
|
||||
|
||||
@ -239,6 +239,8 @@ async fn payments_create_core_adyen_no_redirect() {
|
||||
mandate_id: None,
|
||||
client_secret: None,
|
||||
browser_info: None,
|
||||
payment_experience: None,
|
||||
payment_issuer: None,
|
||||
};
|
||||
|
||||
let expected_response = services::ApplicationResponse::Json(api::PaymentsResponse {
|
||||
|
||||
@ -12,6 +12,7 @@ proc-macro = true
|
||||
doctest = false
|
||||
|
||||
[dependencies]
|
||||
darling = "0.14.3"
|
||||
proc-macro2 = "1.0.50"
|
||||
quote = "1.0.23"
|
||||
syn = { version = "1.0.107", features = ["full", "extra-traits"] } # the full feature does not seem to encompass all the features
|
||||
|
||||
@ -53,13 +53,13 @@ pub fn debug_as_display_derive(input: proc_macro::TokenStream) -> proc_macro::To
|
||||
/// # Example
|
||||
///
|
||||
/// ```
|
||||
/// use router_derive::{DieselEnum, diesel_enum};
|
||||
/// use router_derive::diesel_enum;
|
||||
///
|
||||
/// // Deriving `FromStr` and `ToString` using the `strum` crate, you can also implement it
|
||||
/// // yourself if required.
|
||||
/// #[derive(strum::Display, strum::EnumString)]
|
||||
/// #[derive(Debug, DieselEnum)]
|
||||
/// #[diesel_enum]
|
||||
/// #[derive(Debug)]
|
||||
/// #[diesel_enum(storage_type = "pg_enum")]
|
||||
/// enum Color {
|
||||
/// Red,
|
||||
/// Green,
|
||||
@ -69,32 +69,64 @@ pub fn debug_as_display_derive(input: proc_macro::TokenStream) -> proc_macro::To
|
||||
#[proc_macro_derive(DieselEnum)]
|
||||
pub fn diesel_enum_derive(input: proc_macro::TokenStream) -> proc_macro::TokenStream {
|
||||
let ast = syn::parse_macro_input!(input as syn::DeriveInput);
|
||||
|
||||
let tokens =
|
||||
macros::diesel_enum_derive_inner(&ast).unwrap_or_else(|error| error.to_compile_error());
|
||||
tokens.into()
|
||||
}
|
||||
|
||||
/// Similar to [`DieselEnum`] but uses text when storing in the database, this is to avoid
|
||||
/// making changes to the database when the enum variants are added or modified
|
||||
///
|
||||
/// # Example
|
||||
/// [DieselEnum]: macro@crate::diesel_enum
|
||||
///
|
||||
/// ```
|
||||
/// use router_derive::{diesel_enum};
|
||||
///
|
||||
/// // Deriving `FromStr` and `ToString` using the `strum` crate, you can also implement it
|
||||
/// // yourself if required.
|
||||
/// #[derive(strum::Display, strum::EnumString)]
|
||||
/// #[derive(Debug)]
|
||||
/// #[diesel_enum(storage_type = "text")]
|
||||
/// enum Color {
|
||||
/// Red,
|
||||
/// Green,
|
||||
/// Blue,
|
||||
/// }
|
||||
/// ```
|
||||
#[proc_macro_derive(DieselEnumText)]
|
||||
pub fn diesel_enum_derive_string(input: proc_macro::TokenStream) -> proc_macro::TokenStream {
|
||||
let ast = syn::parse_macro_input!(input as syn::DeriveInput);
|
||||
let tokens = macros::diesel_enum_text_derive_inner(&ast)
|
||||
.unwrap_or_else(|error| error.to_compile_error());
|
||||
tokens.into()
|
||||
}
|
||||
|
||||
/// Derives the boilerplate code required for using an enum with `diesel` and a PostgreSQL database.
|
||||
///
|
||||
/// Works in tandem with the [`DieselEnum`][DieselEnum] derive macro to achieve the desired results.
|
||||
/// Storage Type can either be "text" or "pg_enum"
|
||||
/// Choosing text will store the enum as text in the database, whereas pg_enum will map it to the
|
||||
/// database enum
|
||||
///
|
||||
/// Works in tandem with the [`DieselEnum`][DieselEnum] and [`DieselEnumText`][DieselEnumText] derive macro to achieve the desired results.
|
||||
/// The enum is required to implement (or derive) the [`ToString`][ToString] and the
|
||||
/// [`FromStr`][FromStr] traits for the [`DieselEnum`][DieselEnum] derive macro to be used.
|
||||
///
|
||||
/// [DieselEnum]: crate::DieselEnum
|
||||
/// [DieselEnumText]: crate::DieselEnumText
|
||||
/// [FromStr]: ::core::str::FromStr
|
||||
/// [ToString]: ::std::string::ToString
|
||||
///
|
||||
/// # Example
|
||||
///
|
||||
/// ```
|
||||
/// use router_derive::{DieselEnum, diesel_enum};
|
||||
/// use router_derive::{diesel_enum};
|
||||
///
|
||||
/// // Deriving `FromStr` and `ToString` using the `strum` crate, you can also implement it
|
||||
/// // yourself if required. (Required by the DieselEnum derive macro.)
|
||||
/// #[derive(strum::Display, strum::EnumString)]
|
||||
/// #[derive(Debug, DieselEnum)]
|
||||
/// #[diesel_enum]
|
||||
/// #[derive(Debug)]
|
||||
/// #[diesel_enum(storage_type = "text")]
|
||||
/// enum Color {
|
||||
/// Red,
|
||||
/// Green,
|
||||
|
||||
@ -9,7 +9,9 @@ use syn::DeriveInput;
|
||||
|
||||
pub(crate) use self::{
|
||||
api_error::api_error_derive_inner,
|
||||
diesel::{diesel_enum_attribute_inner, diesel_enum_derive_inner},
|
||||
diesel::{
|
||||
diesel_enum_attribute_inner, diesel_enum_derive_inner, diesel_enum_text_derive_inner,
|
||||
},
|
||||
operation::operation_derive_inner,
|
||||
};
|
||||
|
||||
|
||||
@ -1,9 +1,46 @@
|
||||
use darling::FromMeta;
|
||||
use proc_macro2::{Span, TokenStream};
|
||||
use quote::{format_ident, quote};
|
||||
use syn::{AttributeArgs, Data, DeriveInput, ItemEnum};
|
||||
|
||||
use crate::macros::helpers::non_enum_error;
|
||||
|
||||
pub(crate) fn diesel_enum_text_derive_inner(ast: &DeriveInput) -> syn::Result<TokenStream> {
|
||||
let name = &ast.ident;
|
||||
let (impl_generics, ty_generics, where_clause) = ast.generics.split_for_impl();
|
||||
|
||||
match &ast.data {
|
||||
Data::Enum(_) => (),
|
||||
_ => return Err(non_enum_error()),
|
||||
}
|
||||
|
||||
Ok(quote! {
|
||||
#[automatically_derived]
|
||||
impl #impl_generics ::diesel::serialize::ToSql<::diesel::sql_types::Text, ::diesel::pg::Pg> for #name #ty_generics
|
||||
#where_clause
|
||||
{
|
||||
fn to_sql<'b>(&'b self, out: &mut ::diesel::serialize::Output<'b, '_, ::diesel::pg::Pg>) -> ::diesel::serialize::Result {
|
||||
use ::std::io::Write;
|
||||
|
||||
out.write_all(self.to_string().as_bytes())?;
|
||||
Ok(::diesel::serialize::IsNull::No)
|
||||
}
|
||||
}
|
||||
|
||||
#[automatically_derived]
|
||||
impl #impl_generics ::diesel::deserialize::FromSql<::diesel::sql_types::Text, ::diesel::pg::Pg> for #name #ty_generics
|
||||
#where_clause
|
||||
{
|
||||
fn from_sql(value: ::diesel::pg::PgValue) -> diesel::deserialize::Result<Self> {
|
||||
use ::core::str::FromStr;
|
||||
|
||||
Self::from_str(::core::str::from_utf8(value.as_bytes())?)
|
||||
.map_err(|_| "Unrecognized enum variant".into())
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
pub(crate) fn diesel_enum_derive_inner(ast: &DeriveInput) -> syn::Result<TokenStream> {
|
||||
let name = &ast.ident;
|
||||
let (impl_generics, ty_generics, where_clause) = ast.generics.split_for_impl();
|
||||
@ -50,18 +87,41 @@ pub(crate) fn diesel_enum_attribute_inner(
|
||||
args: &AttributeArgs,
|
||||
item: &ItemEnum,
|
||||
) -> syn::Result<TokenStream> {
|
||||
if !args.is_empty() {
|
||||
return Err(syn::Error::new(
|
||||
Span::call_site(),
|
||||
"This attribute macro does not accept any arguments.",
|
||||
));
|
||||
#[derive(FromMeta, Debug)]
|
||||
enum StorageType {
|
||||
PgEnum,
|
||||
Text,
|
||||
}
|
||||
|
||||
let name = &item.ident;
|
||||
let struct_name = format_ident!("Db{name}");
|
||||
Ok(quote! {
|
||||
#[derive(diesel::AsExpression, diesel::FromSqlRow)]
|
||||
#[diesel(sql_type = #struct_name)]
|
||||
#item
|
||||
})
|
||||
#[derive(FromMeta, Debug)]
|
||||
struct StorageTypeArgs {
|
||||
storage_type: StorageType,
|
||||
}
|
||||
|
||||
let storage_type_args = match StorageTypeArgs::from_list(args) {
|
||||
Ok(v) => v,
|
||||
Err(_) => {
|
||||
return Err(syn::Error::new(
|
||||
Span::call_site(),
|
||||
"Expected storage_type of text or pg_enum",
|
||||
));
|
||||
}
|
||||
};
|
||||
|
||||
match storage_type_args.storage_type {
|
||||
StorageType::PgEnum => {
|
||||
let name = &item.ident;
|
||||
let type_name = format_ident!("Db{name}");
|
||||
Ok(quote! {
|
||||
#[derive(diesel::AsExpression, diesel::FromSqlRow, router_derive::DieselEnum) ]
|
||||
#[diesel(sql_type = #type_name)]
|
||||
#item
|
||||
})
|
||||
}
|
||||
StorageType::Text => Ok(quote! {
|
||||
#[derive(diesel::AsExpression, diesel::FromSqlRow, router_derive::DieselEnumText) ]
|
||||
#[diesel(sql_type = ::diesel::sql_types::Text)]
|
||||
#item
|
||||
}),
|
||||
}
|
||||
}
|
||||
|
||||
@ -6,11 +6,11 @@ pub mod diesel_exports {
|
||||
DbEventClass as EventClass, DbEventObjectType as EventObjectType, DbEventType as EventType,
|
||||
DbFutureUsage as FutureUsage, DbIntentStatus as IntentStatus,
|
||||
DbMandateStatus as MandateStatus, DbMandateType as MandateType,
|
||||
DbMerchantStorageScheme as MerchantStorageScheme, DbPaymentFlow as PaymentFlow,
|
||||
DbMerchantStorageScheme as MerchantStorageScheme,
|
||||
DbPaymentMethodIssuerCode as PaymentMethodIssuerCode,
|
||||
DbPaymentMethodSubType as PaymentMethodSubType, DbPaymentMethodType as PaymentMethodType,
|
||||
DbProcessTrackerStatus as ProcessTrackerStatus, DbRefundStatus as RefundStatus,
|
||||
DbRefundType as RefundType, DbRoutingAlgorithm as RoutingAlgorithm,
|
||||
DbRefundType as RefundType,
|
||||
};
|
||||
}
|
||||
|
||||
@ -25,9 +25,8 @@ pub mod diesel_exports {
|
||||
serde::Serialize,
|
||||
strum::Display,
|
||||
strum::EnumString,
|
||||
router_derive::DieselEnum,
|
||||
)]
|
||||
#[router_derive::diesel_enum]
|
||||
#[router_derive::diesel_enum(storage_type = "pg_enum")]
|
||||
#[serde(rename_all = "snake_case")]
|
||||
#[strum(serialize_all = "snake_case")]
|
||||
pub enum AttemptStatus {
|
||||
@ -66,10 +65,9 @@ pub enum AttemptStatus {
|
||||
serde::Serialize,
|
||||
strum::Display,
|
||||
strum::EnumString,
|
||||
router_derive::DieselEnum,
|
||||
frunk::LabelledGeneric,
|
||||
)]
|
||||
#[router_derive::diesel_enum]
|
||||
#[router_derive::diesel_enum(storage_type = "pg_enum")]
|
||||
#[serde(rename_all = "snake_case")]
|
||||
#[strum(serialize_all = "snake_case")]
|
||||
pub enum AuthenticationType {
|
||||
@ -89,10 +87,9 @@ pub enum AuthenticationType {
|
||||
serde::Serialize,
|
||||
strum::Display,
|
||||
strum::EnumString,
|
||||
router_derive::DieselEnum,
|
||||
frunk::LabelledGeneric,
|
||||
)]
|
||||
#[router_derive::diesel_enum]
|
||||
#[router_derive::diesel_enum(storage_type = "pg_enum")]
|
||||
#[serde(rename_all = "snake_case")]
|
||||
#[strum(serialize_all = "snake_case")]
|
||||
pub enum CaptureMethod {
|
||||
@ -113,10 +110,9 @@ pub enum CaptureMethod {
|
||||
strum::EnumString,
|
||||
serde::Deserialize,
|
||||
serde::Serialize,
|
||||
router_derive::DieselEnum,
|
||||
frunk::LabelledGeneric,
|
||||
)]
|
||||
#[router_derive::diesel_enum]
|
||||
#[router_derive::diesel_enum(storage_type = "pg_enum")]
|
||||
#[strum(serialize_all = "snake_case")]
|
||||
#[serde(rename_all = "snake_case")]
|
||||
pub enum ConnectorType {
|
||||
@ -149,10 +145,9 @@ pub enum ConnectorType {
|
||||
serde::Serialize,
|
||||
strum::Display,
|
||||
strum::EnumString,
|
||||
router_derive::DieselEnum,
|
||||
frunk::LabelledGeneric,
|
||||
)]
|
||||
#[router_derive::diesel_enum]
|
||||
#[router_derive::diesel_enum(storage_type = "pg_enum")]
|
||||
pub enum Currency {
|
||||
AED,
|
||||
ALL,
|
||||
@ -270,9 +265,8 @@ pub enum Currency {
|
||||
serde::Serialize,
|
||||
strum::Display,
|
||||
strum::EnumString,
|
||||
router_derive::DieselEnum,
|
||||
)]
|
||||
#[router_derive::diesel_enum]
|
||||
#[router_derive::diesel_enum(storage_type = "pg_enum")]
|
||||
#[serde(rename_all = "snake_case")]
|
||||
#[strum(serialize_all = "snake_case")]
|
||||
pub enum EventClass {
|
||||
@ -289,9 +283,8 @@ pub enum EventClass {
|
||||
serde::Serialize,
|
||||
strum::Display,
|
||||
strum::EnumString,
|
||||
router_derive::DieselEnum,
|
||||
)]
|
||||
#[router_derive::diesel_enum]
|
||||
#[router_derive::diesel_enum(storage_type = "pg_enum")]
|
||||
#[serde(rename_all = "snake_case")]
|
||||
#[strum(serialize_all = "snake_case")]
|
||||
pub enum EventObjectType {
|
||||
@ -308,10 +301,9 @@ pub enum EventObjectType {
|
||||
serde::Serialize,
|
||||
strum::Display,
|
||||
strum::EnumString,
|
||||
router_derive::DieselEnum,
|
||||
frunk::LabelledGeneric,
|
||||
)]
|
||||
#[router_derive::diesel_enum]
|
||||
#[router_derive::diesel_enum(storage_type = "pg_enum")]
|
||||
#[serde(rename_all = "snake_case")]
|
||||
#[strum(serialize_all = "snake_case")]
|
||||
pub enum EventType {
|
||||
@ -329,10 +321,9 @@ pub enum EventType {
|
||||
serde::Serialize,
|
||||
strum::Display,
|
||||
strum::EnumString,
|
||||
router_derive::DieselEnum,
|
||||
frunk::LabelledGeneric,
|
||||
)]
|
||||
#[router_derive::diesel_enum]
|
||||
#[router_derive::diesel_enum(storage_type = "pg_enum")]
|
||||
#[serde(rename_all = "snake_case")]
|
||||
#[strum(serialize_all = "snake_case")]
|
||||
pub enum IntentStatus {
|
||||
@ -358,10 +349,9 @@ pub enum IntentStatus {
|
||||
serde::Serialize,
|
||||
strum::Display,
|
||||
strum::EnumString,
|
||||
router_derive::DieselEnum,
|
||||
frunk::LabelledGeneric,
|
||||
)]
|
||||
#[router_derive::diesel_enum]
|
||||
#[router_derive::diesel_enum(storage_type = "pg_enum")]
|
||||
#[serde(rename_all = "snake_case")]
|
||||
#[strum(serialize_all = "snake_case")]
|
||||
pub enum FutureUsage {
|
||||
@ -381,9 +371,8 @@ pub enum FutureUsage {
|
||||
serde::Serialize,
|
||||
strum::Display,
|
||||
strum::EnumString,
|
||||
router_derive::DieselEnum,
|
||||
)]
|
||||
#[router_derive::diesel_enum]
|
||||
#[router_derive::diesel_enum(storage_type = "pg_enum")]
|
||||
#[serde(rename_all = "snake_case")]
|
||||
#[strum(serialize_all = "snake_case")]
|
||||
pub enum MerchantStorageScheme {
|
||||
@ -392,30 +381,6 @@ pub enum MerchantStorageScheme {
|
||||
RedisKv,
|
||||
}
|
||||
|
||||
#[derive(
|
||||
Clone,
|
||||
Copy,
|
||||
Debug,
|
||||
Eq,
|
||||
PartialEq,
|
||||
strum::Display,
|
||||
strum::EnumString,
|
||||
serde::Serialize,
|
||||
serde::Deserialize,
|
||||
router_derive::DieselEnum,
|
||||
)]
|
||||
#[router_derive::diesel_enum]
|
||||
#[strum(serialize_all = "snake_case")]
|
||||
pub enum PaymentFlow {
|
||||
Vsc,
|
||||
Emi,
|
||||
Otp,
|
||||
UpiIntent,
|
||||
UpiCollect,
|
||||
UpiScanAndPay,
|
||||
Sdk,
|
||||
}
|
||||
|
||||
#[derive(
|
||||
Clone,
|
||||
Copy,
|
||||
@ -427,10 +392,9 @@ pub enum PaymentFlow {
|
||||
serde::Serialize,
|
||||
strum::Display,
|
||||
strum::EnumString,
|
||||
router_derive::DieselEnum,
|
||||
frunk::LabelledGeneric,
|
||||
)]
|
||||
#[router_derive::diesel_enum]
|
||||
#[router_derive::diesel_enum(storage_type = "pg_enum")]
|
||||
#[strum(serialize_all = "snake_case")]
|
||||
#[serde(rename_all = "snake_case")]
|
||||
pub enum PaymentMethodIssuerCode {
|
||||
@ -457,10 +421,9 @@ pub enum PaymentMethodIssuerCode {
|
||||
serde::Serialize,
|
||||
strum::Display,
|
||||
strum::EnumString,
|
||||
router_derive::DieselEnum,
|
||||
frunk::LabelledGeneric,
|
||||
)]
|
||||
#[router_derive::diesel_enum]
|
||||
#[router_derive::diesel_enum(storage_type = "pg_enum")]
|
||||
#[serde(rename_all = "snake_case")]
|
||||
#[strum(serialize_all = "snake_case")]
|
||||
pub enum PaymentMethodSubType {
|
||||
@ -484,10 +447,9 @@ pub enum PaymentMethodSubType {
|
||||
serde::Serialize,
|
||||
strum::Display,
|
||||
strum::EnumString,
|
||||
router_derive::DieselEnum,
|
||||
frunk::LabelledGeneric,
|
||||
)]
|
||||
#[router_derive::diesel_enum]
|
||||
#[router_derive::diesel_enum(storage_type = "pg_enum")]
|
||||
#[serde(rename_all = "snake_case")]
|
||||
#[strum(serialize_all = "snake_case")]
|
||||
pub enum PaymentMethodType {
|
||||
@ -517,9 +479,8 @@ pub enum PaymentMethodType {
|
||||
serde::Serialize,
|
||||
strum::Display,
|
||||
strum::EnumString,
|
||||
router_derive::DieselEnum,
|
||||
)]
|
||||
#[router_derive::diesel_enum]
|
||||
#[router_derive::diesel_enum(storage_type = "pg_enum")]
|
||||
#[serde(rename_all = "lowercase")]
|
||||
#[strum(serialize_all = "lowercase")]
|
||||
pub enum WalletIssuer {
|
||||
@ -537,9 +498,8 @@ pub enum WalletIssuer {
|
||||
serde::Serialize,
|
||||
strum::Display,
|
||||
strum::EnumString,
|
||||
router_derive::DieselEnum,
|
||||
)]
|
||||
#[router_derive::diesel_enum]
|
||||
#[router_derive::diesel_enum(storage_type = "pg_enum")]
|
||||
#[serde(rename_all = "snake_case")]
|
||||
#[strum(serialize_all = "snake_case")]
|
||||
pub enum ProcessTrackerStatus {
|
||||
@ -566,10 +526,9 @@ pub enum ProcessTrackerStatus {
|
||||
serde::Deserialize,
|
||||
strum::Display,
|
||||
strum::EnumString,
|
||||
router_derive::DieselEnum,
|
||||
frunk::LabelledGeneric,
|
||||
)]
|
||||
#[router_derive::diesel_enum]
|
||||
#[router_derive::diesel_enum(storage_type = "pg_enum")]
|
||||
#[strum(serialize_all = "snake_case")]
|
||||
pub enum RefundStatus {
|
||||
Failure,
|
||||
@ -591,9 +550,8 @@ pub enum RefundStatus {
|
||||
serde::Deserialize,
|
||||
strum::Display,
|
||||
strum::EnumString,
|
||||
router_derive::DieselEnum,
|
||||
)]
|
||||
#[router_derive::diesel_enum]
|
||||
#[router_derive::diesel_enum(storage_type = "pg_enum")]
|
||||
#[strum(serialize_all = "snake_case")]
|
||||
pub enum RefundType {
|
||||
InstantRefund,
|
||||
@ -602,29 +560,6 @@ pub enum RefundType {
|
||||
RetryRefund,
|
||||
}
|
||||
|
||||
#[derive(
|
||||
Clone,
|
||||
Copy,
|
||||
Debug,
|
||||
Eq,
|
||||
PartialEq,
|
||||
serde::Deserialize,
|
||||
serde::Serialize,
|
||||
strum::Display,
|
||||
strum::EnumString,
|
||||
router_derive::DieselEnum,
|
||||
frunk::LabelledGeneric,
|
||||
)]
|
||||
#[serde(rename_all = "snake_case")]
|
||||
#[strum(serialize_all = "snake_case")]
|
||||
#[router_derive::diesel_enum]
|
||||
pub enum RoutingAlgorithm {
|
||||
RoundRobin,
|
||||
MaxConversion,
|
||||
MinCost,
|
||||
Custom,
|
||||
}
|
||||
|
||||
// Mandate
|
||||
#[derive(
|
||||
Clone,
|
||||
@ -637,9 +572,8 @@ pub enum RoutingAlgorithm {
|
||||
serde::Serialize,
|
||||
strum::Display,
|
||||
strum::EnumString,
|
||||
router_derive::DieselEnum,
|
||||
)]
|
||||
#[router_derive::diesel_enum]
|
||||
#[router_derive::diesel_enum(storage_type = "pg_enum")]
|
||||
#[serde(rename_all = "snake_case")]
|
||||
#[strum(serialize_all = "snake_case")]
|
||||
pub enum MandateType {
|
||||
@ -659,10 +593,9 @@ pub enum MandateType {
|
||||
serde::Serialize,
|
||||
strum::Display,
|
||||
strum::EnumString,
|
||||
router_derive::DieselEnum,
|
||||
frunk::LabelledGeneric,
|
||||
)]
|
||||
#[router_derive::diesel_enum]
|
||||
#[router_derive::diesel_enum(storage_type = "pg_enum")]
|
||||
#[serde(rename_all = "snake_case")]
|
||||
#[strum(serialize_all = "snake_case")]
|
||||
pub enum MandateStatus {
|
||||
@ -672,3 +605,62 @@ pub enum MandateStatus {
|
||||
Pending,
|
||||
Revoked,
|
||||
}
|
||||
|
||||
#[derive(
|
||||
Clone,
|
||||
Copy,
|
||||
Debug,
|
||||
Eq,
|
||||
Hash,
|
||||
PartialEq,
|
||||
serde::Deserialize,
|
||||
serde::Serialize,
|
||||
strum::Display,
|
||||
strum::EnumString,
|
||||
frunk::LabelledGeneric,
|
||||
)]
|
||||
#[router_derive::diesel_enum(storage_type = "text")]
|
||||
#[strum(serialize_all = "snake_case")]
|
||||
#[serde(rename_all = "snake_case")]
|
||||
pub enum PaymentIssuer {
|
||||
Klarna,
|
||||
Affirm,
|
||||
AfterpayClearpay,
|
||||
AmericanExpress,
|
||||
BankOfAmerica,
|
||||
Barclays,
|
||||
CapitalOne,
|
||||
Chase,
|
||||
Citi,
|
||||
Discover,
|
||||
NavyFederalCreditUnion,
|
||||
PentagonFederalCreditUnion,
|
||||
SynchronyBank,
|
||||
WellsFargo,
|
||||
}
|
||||
|
||||
#[derive(
|
||||
Eq,
|
||||
PartialEq,
|
||||
Hash,
|
||||
Clone,
|
||||
Debug,
|
||||
serde::Serialize,
|
||||
serde::Deserialize,
|
||||
Default,
|
||||
strum::Display,
|
||||
strum::EnumString,
|
||||
frunk::LabelledGeneric,
|
||||
)]
|
||||
#[router_derive::diesel_enum(storage_type = "text")]
|
||||
#[strum(serialize_all = "snake_case")]
|
||||
#[serde(rename_all = "snake_case")]
|
||||
pub enum PaymentExperience {
|
||||
#[default]
|
||||
RedirectToUrl,
|
||||
InvokeSdkClient,
|
||||
DisplayQrCode,
|
||||
OneClick,
|
||||
LinkWallet,
|
||||
InvokePaymentApp,
|
||||
}
|
||||
|
||||
@ -22,8 +22,6 @@ pub struct PaymentAttempt {
|
||||
pub tax_amount: Option<i64>,
|
||||
pub payment_method_id: Option<String>,
|
||||
pub payment_method: Option<storage_enums::PaymentMethodType>,
|
||||
pub payment_flow: Option<storage_enums::PaymentFlow>,
|
||||
pub redirect: Option<bool>,
|
||||
pub connector_transaction_id: Option<String>,
|
||||
pub capture_method: Option<storage_enums::CaptureMethod>,
|
||||
pub capture_on: Option<PrimitiveDateTime>,
|
||||
@ -39,6 +37,8 @@ pub struct PaymentAttempt {
|
||||
pub error_code: Option<String>,
|
||||
pub payment_token: Option<String>,
|
||||
pub connector_metadata: Option<serde_json::Value>,
|
||||
pub payment_issuer: Option<storage_enums::PaymentIssuer>,
|
||||
pub payment_experience: Option<storage_enums::PaymentExperience>,
|
||||
}
|
||||
|
||||
#[derive(
|
||||
@ -61,8 +61,6 @@ pub struct PaymentAttemptNew {
|
||||
pub tax_amount: Option<i64>,
|
||||
pub payment_method_id: Option<String>,
|
||||
pub payment_method: Option<storage_enums::PaymentMethodType>,
|
||||
pub payment_flow: Option<storage_enums::PaymentFlow>,
|
||||
pub redirect: Option<bool>,
|
||||
pub connector_transaction_id: Option<String>,
|
||||
pub capture_method: Option<storage_enums::CaptureMethod>,
|
||||
pub capture_on: Option<PrimitiveDateTime>,
|
||||
@ -78,6 +76,8 @@ pub struct PaymentAttemptNew {
|
||||
pub payment_token: Option<String>,
|
||||
pub error_code: Option<String>,
|
||||
pub connector_metadata: Option<serde_json::Value>,
|
||||
pub payment_issuer: Option<storage_enums::PaymentIssuer>,
|
||||
pub payment_experience: Option<storage_enums::PaymentExperience>,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||
@ -117,7 +117,6 @@ pub enum PaymentAttemptUpdate {
|
||||
connector_transaction_id: Option<String>,
|
||||
authentication_type: Option<storage_enums::AuthenticationType>,
|
||||
payment_method_id: Option<Option<String>>,
|
||||
redirect: Option<bool>,
|
||||
mandate_id: Option<String>,
|
||||
connector_metadata: Option<serde_json::Value>,
|
||||
},
|
||||
@ -146,7 +145,6 @@ pub struct PaymentAttemptUpdateInternal {
|
||||
payment_method_id: Option<Option<String>>,
|
||||
cancellation_reason: Option<String>,
|
||||
modified_at: Option<PrimitiveDateTime>,
|
||||
redirect: Option<bool>,
|
||||
mandate_id: Option<String>,
|
||||
browser_info: Option<serde_json::Value>,
|
||||
payment_token: Option<String>,
|
||||
@ -243,7 +241,6 @@ impl From<PaymentAttemptUpdate> for PaymentAttemptUpdateInternal {
|
||||
connector_transaction_id,
|
||||
authentication_type,
|
||||
payment_method_id,
|
||||
redirect,
|
||||
mandate_id,
|
||||
connector_metadata,
|
||||
} => Self {
|
||||
@ -253,7 +250,6 @@ impl From<PaymentAttemptUpdate> for PaymentAttemptUpdateInternal {
|
||||
authentication_type,
|
||||
payment_method_id,
|
||||
modified_at: Some(common_utils::date_time::now()),
|
||||
redirect,
|
||||
mandate_id,
|
||||
connector_metadata,
|
||||
..Default::default()
|
||||
|
||||
@ -219,8 +219,6 @@ diesel::table! {
|
||||
tax_amount -> Nullable<Int8>,
|
||||
payment_method_id -> Nullable<Varchar>,
|
||||
payment_method -> Nullable<PaymentMethodType>,
|
||||
payment_flow -> Nullable<PaymentFlow>,
|
||||
redirect -> Nullable<Bool>,
|
||||
connector_transaction_id -> Nullable<Varchar>,
|
||||
capture_method -> Nullable<CaptureMethod>,
|
||||
capture_on -> Nullable<Timestamp>,
|
||||
@ -236,6 +234,8 @@ diesel::table! {
|
||||
error_code -> Nullable<Varchar>,
|
||||
payment_token -> Nullable<Varchar>,
|
||||
connector_metadata -> Nullable<Jsonb>,
|
||||
payment_issuer -> Nullable<Varchar>,
|
||||
payment_experience -> Nullable<Varchar>,
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -0,0 +1,3 @@
|
||||
ALTER TABLE payment_attempt DROP COLUMN IF EXISTS payment_issuer;
|
||||
|
||||
ALTER TABLE payment_attempt DROP COLUMN IF EXISTS payment_experience;
|
||||
@ -0,0 +1,6 @@
|
||||
-- Your SQL goes here
|
||||
ALTER TABLE payment_attempt
|
||||
ADD COLUMN IF NOT EXISTS payment_issuer VARCHAR(50);
|
||||
|
||||
ALTER TABLE payment_attempt
|
||||
ADD COLUMN IF NOT EXISTS payment_experience VARCHAR(50);
|
||||
@ -0,0 +1,15 @@
|
||||
CREATE TYPE "PaymentFlow" AS ENUM (
|
||||
'vsc',
|
||||
'emi',
|
||||
'otp',
|
||||
'upi_intent',
|
||||
'upi_collect',
|
||||
'upi_scan_and_pay',
|
||||
'sdk'
|
||||
);
|
||||
|
||||
ALTER TABLE payment_attempt
|
||||
ADD COLUMN payment_flow "PaymentFlow";
|
||||
|
||||
ALTER TABLE payment_attempt
|
||||
ADD COLUMN redirect BOOLEAN;
|
||||
@ -0,0 +1,5 @@
|
||||
ALTER TABLE payment_attempt DROP COLUMN IF EXISTS redirect;
|
||||
|
||||
ALTER TABLE payment_attempt DROP COLUMN IF EXISTS payment_flow;
|
||||
|
||||
DROP TYPE IF EXISTS "PaymentFlow";
|
||||
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user