Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(connector): [Paybox] Add mandates Flow for Paybox #6378

Merged
merged 2 commits into from
Oct 30, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
57 changes: 52 additions & 5 deletions crates/api_models/src/payments.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1309,12 +1309,59 @@ pub struct NetworkTokenWithNTIRef {

#[derive(Debug, serde::Deserialize, serde::Serialize, Clone, Eq, PartialEq)]
pub struct ConnectorMandateReferenceId {
pub connector_mandate_id: Option<String>,
pub payment_method_id: Option<String>,
pub update_history: Option<Vec<UpdateHistory>>,
pub mandate_metadata: Option<serde_json::Value>,
}
connector_mandate_id: Option<String>,
payment_method_id: Option<String>,
update_history: Option<Vec<UpdateHistory>>,
mandate_metadata: Option<serde_json::Value>,
connector_mandate_request_reference_id: Option<String>,
}

impl ConnectorMandateReferenceId {
pub fn new(
connector_mandate_id: Option<String>,
payment_method_id: Option<String>,
update_history: Option<Vec<UpdateHistory>>,
mandate_metadata: Option<serde_json::Value>,
connector_mandate_request_reference_id: Option<String>,
) -> Self {
Self {
connector_mandate_id,
payment_method_id,
update_history,
mandate_metadata,
connector_mandate_request_reference_id,
}
}

pub fn get_connector_mandate_id(&self) -> Option<String> {
self.connector_mandate_id.clone()
}
pub fn get_payment_method_id(&self) -> Option<String> {
self.payment_method_id.clone()
}
pub fn get_mandate_metadata(&self) -> Option<serde_json::Value> {
self.mandate_metadata.clone()
}
pub fn get_connector_mandate_request_reference_id(&self) -> Option<String> {
self.connector_mandate_request_reference_id.clone()
}

pub fn update(
&mut self,
connector_mandate_id: Option<String>,
payment_method_id: Option<String>,
update_history: Option<Vec<UpdateHistory>>,
mandate_metadata: Option<serde_json::Value>,
connector_mandate_request_reference_id: Option<String>,
) {
self.connector_mandate_id = connector_mandate_id.or(self.connector_mandate_id.clone());
self.payment_method_id = payment_method_id.or(self.payment_method_id.clone());
self.update_history = update_history.or(self.update_history.clone());
self.mandate_metadata = mandate_metadata.or(self.mandate_metadata.clone());
self.connector_mandate_request_reference_id = connector_mandate_request_reference_id
.or(self.connector_mandate_request_reference_id.clone());
}
}
#[derive(serde::Serialize, serde::Deserialize, Debug, Clone, Eq, PartialEq)]
pub struct UpdateHistory {
pub connector_mandate_id: Option<String>,
Expand Down
5 changes: 5 additions & 0 deletions crates/common_utils/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -270,6 +270,11 @@ pub fn generate_time_ordered_id_without_prefix() -> String {
uuid::Uuid::now_v7().as_simple().to_string()
}

/// Generate a nanoid with the specified length
#[inline]
pub fn generate_id_with_len(length: usize) -> String {
nanoid::nanoid!(length, &consts::ALPHABETS)
}
#[allow(missing_docs)]
pub trait DbConnectionParams {
fn get_username(&self) -> &str;
Expand Down
12 changes: 11 additions & 1 deletion crates/diesel_models/src/payment_attempt.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,15 @@ pub struct ConnectorMandateReferenceId {
pub connector_mandate_id: Option<String>,
pub payment_method_id: Option<String>,
pub mandate_metadata: Option<serde_json::Value>,
pub connector_mandate_request_reference_id: Option<String>,
}

impl ConnectorMandateReferenceId {
pub fn get_connector_mandate_request_reference_id(&self) -> Option<String> {
self.connector_mandate_request_reference_id.clone()
}
}

#[cfg(feature = "v2")]
#[derive(
Clone, Debug, Eq, PartialEq, Identifiable, Queryable, Serialize, Deserialize, Selectable,
Expand Down Expand Up @@ -414,6 +422,7 @@ pub enum PaymentAttemptUpdate {
customer_acceptance: Option<pii::SecretSerdeValue>,
shipping_cost: Option<MinorUnit>,
order_tax_amount: Option<MinorUnit>,
connector_mandate_detail: Option<ConnectorMandateReferenceId>,
},
VoidUpdate {
status: storage_enums::AttemptStatus,
Expand Down Expand Up @@ -2158,6 +2167,7 @@ impl From<PaymentAttemptUpdate> for PaymentAttemptUpdateInternal {
customer_acceptance,
shipping_cost,
order_tax_amount,
connector_mandate_detail,
} => Self {
amount: Some(amount),
currency: Some(currency),
Expand Down Expand Up @@ -2209,7 +2219,7 @@ impl From<PaymentAttemptUpdate> for PaymentAttemptUpdateInternal {
shipping_cost,
order_tax_amount,
connector_transaction_data: None,
connector_mandate_detail: None,
connector_mandate_detail,
},
PaymentAttemptUpdate::VoidUpdate {
status,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -176,7 +176,7 @@ impl TryFrom<&DeutschebankRouterData<&PaymentsAuthorizeRouterData>>
}
Some(api_models::payments::MandateReferenceId::ConnectorMandateId(mandate_data)) => {
let mandate_metadata: DeutschebankMandateMetadata = mandate_data
.mandate_metadata
.get_mandate_metadata()
.ok_or(errors::ConnectorError::MissingConnectorMandateMetadata)?
.clone()
.parse_value("DeutschebankMandateMetadata")
Expand Down Expand Up @@ -325,6 +325,7 @@ impl
reference: Secret::from(reference.clone()),
signed_on,
})),
connector_mandate_request_reference_id: None,
}))
} else {
Box::new(None)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -809,6 +809,7 @@ impl<F>
connector_mandate_id: Some(token.clone().expose()),
payment_method_id: None,
mandate_metadata: None,
connector_mandate_request_reference_id: None,
})
});
let status = match non_threeds_data.status.as_str() {
Expand Down Expand Up @@ -1184,6 +1185,7 @@ impl TryFrom<PaymentsSyncResponseRouterData<FiuuPaymentResponse>> for PaymentsSy
connector_mandate_id: Some(token.clone().expose()),
payment_method_id: None,
mandate_metadata: None,
connector_mandate_request_reference_id:None
})
}
Err(err) => {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -360,6 +360,7 @@ impl<F, T> TryFrom<ResponseRouterData<F, NexinetsPreAuthOrDebitResponse, T, Paym
connector_mandate_id: Some(id.expose()),
payment_method_id: None,
mandate_metadata: None,
connector_mandate_request_reference_id: None,
});
Ok(Self {
status: get_status(transaction.status.clone(), item.response.transaction_type),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -374,7 +374,7 @@ impl TryFrom<&NovalnetRouterData<&PaymentsAuthorizeRouterData>> for NovalnetPaym
.into()),
},
Some(api_models::payments::MandateReferenceId::ConnectorMandateId(mandate_data)) => {
let connector_mandate_id = mandate_data.connector_mandate_id.ok_or(
let connector_mandate_id = mandate_data.get_connector_mandate_id().ok_or(
errors::ConnectorError::MissingRequiredField {
field_name: "connector_mandate_id",
},
Expand Down Expand Up @@ -597,6 +597,7 @@ impl<F, T> TryFrom<ResponseRouterData<F, NovalnetPaymentsResponse, T, PaymentsRe
connector_mandate_id: Some(id.clone()),
payment_method_id: None,
mandate_metadata: None,
connector_mandate_request_reference_id: None,
}
})),
connector_metadata: None,
Expand Down Expand Up @@ -998,6 +999,7 @@ impl<F>
connector_mandate_id: Some(id.clone()),
payment_method_id: None,
mandate_metadata: None,
connector_mandate_request_reference_id: None,
}
})),
connector_metadata: None,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -185,7 +185,7 @@ fn get_transaction_type_and_stored_creds(
match mandate_ids.mandate_reference_id.clone() {
Some(api_models::payments::MandateReferenceId::ConnectorMandateId(
connector_mandate_ids,
)) => connector_mandate_ids.connector_mandate_id,
)) => connector_mandate_ids.get_connector_mandate_id(),
_ => None,
}
});
Expand Down Expand Up @@ -420,6 +420,7 @@ impl<F, T> TryFrom<ResponseRouterData<F, PayeezyPaymentsResponse, T, PaymentsRes
connector_mandate_id: Some(id.expose()),
payment_method_id: None,
mandate_metadata: None,
connector_mandate_request_reference_id: None,
});
let status = get_status(
item.response.transaction_status,
Expand Down
2 changes: 1 addition & 1 deletion crates/hyperswitch_connectors/src/utils.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1171,7 +1171,7 @@ impl PaymentsAuthorizeRequestData for PaymentsAuthorizeData {
.as_ref()
.and_then(|mandate_ids| match &mandate_ids.mandate_reference_id {
Some(payments::MandateReferenceId::ConnectorMandateId(connector_mandate_ids)) => {
connector_mandate_ids.connector_mandate_id.clone()
connector_mandate_ids.get_connector_mandate_id()
}
Some(payments::MandateReferenceId::NetworkMandateId(_))
| None
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -787,6 +787,7 @@ pub enum PaymentAttemptUpdate {
client_source: Option<String>,
client_version: Option<String>,
customer_acceptance: Option<pii::SecretSerdeValue>,
connector_mandate_detail: Option<ConnectorMandateReferenceId>,
},
RejectUpdate {
status: storage_enums::AttemptStatus,
Expand Down Expand Up @@ -1027,6 +1028,7 @@ impl PaymentAttemptUpdate {
client_source,
client_version,
customer_acceptance,
connector_mandate_detail,
} => DieselPaymentAttemptUpdate::ConfirmUpdate {
amount: net_amount.get_order_amount(),
currency,
Expand Down Expand Up @@ -1060,6 +1062,7 @@ impl PaymentAttemptUpdate {
customer_acceptance,
shipping_cost: net_amount.get_shipping_cost(),
order_tax_amount: net_amount.get_order_tax_amount(),
connector_mandate_detail,
},
Self::VoidUpdate {
status,
Expand Down
2 changes: 2 additions & 0 deletions crates/hyperswitch_domain_models/src/router_data.rs
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,8 @@ pub struct RouterData<Flow, Request, Response> {
pub additional_merchant_data: Option<api_models::admin::AdditionalMerchantData>,

pub header_payload: Option<payments::HeaderPayload>,

pub connector_mandate_request_reference_id: Option<String>,
}

// Different patterns of authentication.
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
pub mod authentication;
pub mod fraud_check;
use api_models::payments::{Address, RequestSurchargeDetails};
use api_models::payments::{AdditionalPaymentData, Address, RequestSurchargeDetails};
use common_utils::{
consts, errors,
ext_traits::OptionExt,
Expand Down Expand Up @@ -72,6 +72,7 @@ pub struct PaymentsAuthorizeData {
pub merchant_order_reference_id: Option<String>,
pub integrity_object: Option<AuthoriseIntegrityObject>,
pub shipping_cost: Option<MinorUnit>,
pub additional_payment_method_data: Option<AdditionalPaymentData>,
}

#[derive(Debug, Clone)]
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,7 @@ pub struct MandateReference {
pub connector_mandate_id: Option<String>,
pub payment_method_id: Option<String>,
pub mandate_metadata: Option<serde_json::Value>,
pub connector_mandate_request_reference_id: Option<String>,
}

#[derive(Debug, Clone)]
Expand Down
1 change: 1 addition & 0 deletions crates/router/src/connector/aci/transformers.rs
Original file line number Diff line number Diff line change
Expand Up @@ -749,6 +749,7 @@ impl<F, T>
connector_mandate_id: Some(id.expose()),
payment_method_id: None,
mandate_metadata: None,
connector_mandate_request_reference_id: None,
});

Ok(Self {
Expand Down
7 changes: 5 additions & 2 deletions crates/router/src/connector/adyen/transformers.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ use time::{Duration, OffsetDateTime, PrimitiveDateTime};
use crate::{connector::utils::PayoutsData, types::api::payouts, utils::OptionExt};
use crate::{
connector::utils::{
self, AddressDetailsData, BrowserInformationData, CardData, MandateReferenceData,
self, missing_field_err, AddressDetailsData, BrowserInformationData, CardData,
PaymentsAuthorizeRequestData, PhoneDetailsData, RouterData,
},
consts,
Expand Down Expand Up @@ -2573,7 +2573,9 @@ impl<'a>
None => PaymentType::Scheme,
},
stored_payment_method_id: Secret::new(
connector_mandate_ids.get_connector_mandate_id()?,
connector_mandate_ids
.get_connector_mandate_id()
.ok_or_else(missing_field_err("mandate_id"))?,
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Optional change:

There also seems to be a errors::ConnectorError::MissingConnectorMandateID enum variant, confirm with the connector team if that enum variant would have to be raised instead.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@deepanshu-iiitu Can you verify this?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Both can be used

),
};
Ok::<AdyenPaymentMethod<'_>, Self::Error>(AdyenPaymentMethod::Mandate(Box::new(
Expand Down Expand Up @@ -3365,6 +3367,7 @@ pub fn get_adyen_response(
connector_mandate_id: Some(mandate_id.expose()),
payment_method_id: None,
mandate_metadata: None,
connector_mandate_request_reference_id: None,
});
let network_txn_id = response.additional_data.and_then(|additional_data| {
additional_data
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -399,6 +399,7 @@ impl<F, T>
),
payment_method_id: None,
mandate_metadata: None,
connector_mandate_request_reference_id: None,
},
)),
connector_metadata: None,
Expand Down Expand Up @@ -647,7 +648,7 @@ impl
),
) -> Result<Self, Self::Error> {
let mandate_id = connector_mandate_id
.connector_mandate_id
.get_connector_mandate_id()
.ok_or(errors::ConnectorError::MissingConnectorMandateID)?;
Ok(Self {
transaction_type: TransactionType::try_from(item.router_data.request.capture_method)?,
Expand Down Expand Up @@ -1113,6 +1114,7 @@ impl<F, T>
),
payment_method_id: None,
mandate_metadata: None,
connector_mandate_request_reference_id: None,
}
});

Expand Down
2 changes: 2 additions & 0 deletions crates/router/src/connector/bamboraapac/transformers.rs
Original file line number Diff line number Diff line change
Expand Up @@ -281,6 +281,7 @@ impl<F>
connector_mandate_id,
payment_method_id: None,
mandate_metadata: None,
connector_mandate_request_reference_id: None,
})
} else {
None
Expand Down Expand Up @@ -465,6 +466,7 @@ impl<F>
connector_mandate_id: Some(connector_mandate_id),
payment_method_id: None,
mandate_metadata: None,
connector_mandate_request_reference_id: None,
})),
connector_metadata: None,
network_txn_id: None,
Expand Down
2 changes: 2 additions & 0 deletions crates/router/src/connector/bankofamerica/transformers.rs
Original file line number Diff line number Diff line change
Expand Up @@ -362,6 +362,7 @@ impl<F, T>
.map(|payment_instrument| payment_instrument.id.expose()),
payment_method_id: None,
mandate_metadata: None,
connector_mandate_request_reference_id: None,
}
});
let mut mandate_status =
Expand Down Expand Up @@ -1512,6 +1513,7 @@ fn get_payment_response(
.map(|payment_instrument| payment_instrument.id.expose()),
payment_method_id: None,
mandate_metadata: None,
connector_mandate_request_reference_id: None,
});

Ok(types::PaymentsResponseData::TransactionResponse {
Expand Down
4 changes: 4 additions & 0 deletions crates/router/src/connector/braintree/transformers.rs
Original file line number Diff line number Diff line change
Expand Up @@ -445,6 +445,7 @@ impl<F>
connector_mandate_id: Some(pm.id.clone().expose()),
payment_method_id: None,
mandate_metadata: None,
connector_mandate_request_reference_id: None,
},
)),
connector_metadata: None,
Expand Down Expand Up @@ -620,6 +621,7 @@ impl<F>
connector_mandate_id: Some(pm.id.clone().expose()),
payment_method_id: None,
mandate_metadata: None,
connector_mandate_request_reference_id: None,
},
)),
connector_metadata: None,
Expand Down Expand Up @@ -702,6 +704,7 @@ impl<F>
connector_mandate_id: Some(pm.id.clone().expose()),
payment_method_id: None,
mandate_metadata: None,
connector_mandate_request_reference_id: None,
},
)),
connector_metadata: None,
Expand Down Expand Up @@ -766,6 +769,7 @@ impl<F>
connector_mandate_id: Some(pm.id.clone().expose()),
payment_method_id: None,
mandate_metadata: None,
connector_mandate_request_reference_id: None,
},
)),
connector_metadata: None,
Expand Down
Loading
Loading