mirror of
https://github.com/juspay/hyperswitch.git
synced 2025-11-02 12:06:56 +08:00
feat(connector): [Gocardless] Implement mandate flow (#2461)
Co-authored-by: prajjwalkumar17 <prajjwal.kumar@juspay.in>
This commit is contained in:
@ -309,89 +309,6 @@ impl
|
||||
types::PaymentsResponseData,
|
||||
> for Gocardless
|
||||
{
|
||||
fn get_headers(
|
||||
&self,
|
||||
req: &types::PaymentsPreProcessingRouterData,
|
||||
connectors: &settings::Connectors,
|
||||
) -> CustomResult<Vec<(String, request::Maskable<String>)>, errors::ConnectorError> {
|
||||
self.build_headers(req, connectors)
|
||||
}
|
||||
|
||||
fn get_url(
|
||||
&self,
|
||||
_req: &types::PaymentsPreProcessingRouterData,
|
||||
connectors: &settings::Connectors,
|
||||
) -> CustomResult<String, errors::ConnectorError> {
|
||||
Ok(format!("{}/mandates", self.base_url(connectors)))
|
||||
}
|
||||
|
||||
fn get_request_body(
|
||||
&self,
|
||||
req: &types::PaymentsPreProcessingRouterData,
|
||||
) -> CustomResult<Option<types::RequestBody>, errors::ConnectorError> {
|
||||
let req_obj = gocardless::GocardlessMandateRequest::try_from(req)?;
|
||||
let gocardless_req = types::RequestBody::log_and_get_request_body(
|
||||
&req_obj,
|
||||
utils::Encode::<gocardless::GocardlessMandateRequest>::encode_to_string_of_json,
|
||||
)
|
||||
.change_context(errors::ConnectorError::RequestEncodingFailed)?;
|
||||
Ok(Some(gocardless_req))
|
||||
}
|
||||
|
||||
fn build_request(
|
||||
&self,
|
||||
req: &types::PaymentsPreProcessingRouterData,
|
||||
connectors: &settings::Connectors,
|
||||
) -> CustomResult<Option<common_utils::request::Request>, errors::ConnectorError> {
|
||||
// Preprocessing flow is to create mandate, which should to be called only in case of First mandate
|
||||
if req.request.setup_mandate_details.is_some() {
|
||||
Ok(Some(
|
||||
services::RequestBuilder::new()
|
||||
.method(services::Method::Post)
|
||||
.url(&types::PaymentsPreProcessingType::get_url(
|
||||
self, req, connectors,
|
||||
)?)
|
||||
.attach_default_headers()
|
||||
.headers(types::PaymentsPreProcessingType::get_headers(
|
||||
self, req, connectors,
|
||||
)?)
|
||||
.body(types::PaymentsPreProcessingType::get_request_body(
|
||||
self, req,
|
||||
)?)
|
||||
.build(),
|
||||
))
|
||||
} else {
|
||||
Ok(None)
|
||||
}
|
||||
}
|
||||
|
||||
fn handle_response(
|
||||
&self,
|
||||
data: &types::PaymentsPreProcessingRouterData,
|
||||
res: Response,
|
||||
) -> CustomResult<types::PaymentsPreProcessingRouterData, errors::ConnectorError>
|
||||
where
|
||||
api::PreProcessing: Clone,
|
||||
types::PaymentsPreProcessingData: Clone,
|
||||
types::PaymentsResponseData: Clone,
|
||||
{
|
||||
let response: gocardless::GocardlessMandateResponse = res
|
||||
.response
|
||||
.parse_struct("GocardlessMandateResponse")
|
||||
.change_context(errors::ConnectorError::ResponseDeserializationFailed)?;
|
||||
types::RouterData::try_from(types::ResponseRouterData {
|
||||
response,
|
||||
data: data.clone(),
|
||||
http_code: res.status_code,
|
||||
})
|
||||
}
|
||||
|
||||
fn get_error_response(
|
||||
&self,
|
||||
res: Response,
|
||||
) -> CustomResult<ErrorResponse, errors::ConnectorError> {
|
||||
self.build_error_response(res)
|
||||
}
|
||||
}
|
||||
|
||||
impl ConnectorValidation for Gocardless {
|
||||
@ -429,6 +346,78 @@ impl
|
||||
types::PaymentsResponseData,
|
||||
> for Gocardless
|
||||
{
|
||||
fn get_headers(
|
||||
&self,
|
||||
req: &types::SetupMandateRouterData,
|
||||
connectors: &settings::Connectors,
|
||||
) -> CustomResult<Vec<(String, request::Maskable<String>)>, errors::ConnectorError> {
|
||||
self.build_headers(req, connectors)
|
||||
}
|
||||
|
||||
fn get_url(
|
||||
&self,
|
||||
_req: &types::SetupMandateRouterData,
|
||||
connectors: &settings::Connectors,
|
||||
) -> CustomResult<String, errors::ConnectorError> {
|
||||
Ok(format!("{}/mandates", self.base_url(connectors)))
|
||||
}
|
||||
|
||||
fn get_request_body(
|
||||
&self,
|
||||
req: &types::SetupMandateRouterData,
|
||||
) -> CustomResult<Option<types::RequestBody>, errors::ConnectorError> {
|
||||
let req_obj = gocardless::GocardlessMandateRequest::try_from(req)?;
|
||||
let gocardless_req = types::RequestBody::log_and_get_request_body(
|
||||
&req_obj,
|
||||
utils::Encode::<gocardless::GocardlessMandateRequest>::encode_to_string_of_json,
|
||||
)
|
||||
.change_context(errors::ConnectorError::RequestEncodingFailed)?;
|
||||
Ok(Some(gocardless_req))
|
||||
}
|
||||
|
||||
fn build_request(
|
||||
&self,
|
||||
req: &types::SetupMandateRouterData,
|
||||
connectors: &settings::Connectors,
|
||||
) -> CustomResult<Option<common_utils::request::Request>, errors::ConnectorError> {
|
||||
// Preprocessing flow is to create mandate, which should to be called only in case of First mandate
|
||||
if req.request.setup_mandate_details.is_some() {
|
||||
Ok(Some(
|
||||
services::RequestBuilder::new()
|
||||
.method(services::Method::Post)
|
||||
.url(&types::SetupMandateType::get_url(self, req, connectors)?)
|
||||
.attach_default_headers()
|
||||
.headers(types::SetupMandateType::get_headers(self, req, connectors)?)
|
||||
.body(types::SetupMandateType::get_request_body(self, req)?)
|
||||
.build(),
|
||||
))
|
||||
} else {
|
||||
Ok(None)
|
||||
}
|
||||
}
|
||||
|
||||
fn handle_response(
|
||||
&self,
|
||||
data: &types::SetupMandateRouterData,
|
||||
res: Response,
|
||||
) -> CustomResult<types::SetupMandateRouterData, errors::ConnectorError> {
|
||||
let response: gocardless::GocardlessMandateResponse = res
|
||||
.response
|
||||
.parse_struct("GocardlessMandateResponse")
|
||||
.change_context(errors::ConnectorError::ResponseDeserializationFailed)?;
|
||||
types::RouterData::try_from(types::ResponseRouterData {
|
||||
response,
|
||||
data: data.clone(),
|
||||
http_code: res.status_code,
|
||||
})
|
||||
}
|
||||
|
||||
fn get_error_response(
|
||||
&self,
|
||||
res: Response,
|
||||
) -> CustomResult<ErrorResponse, errors::ConnectorError> {
|
||||
self.build_error_response(res)
|
||||
}
|
||||
}
|
||||
|
||||
impl ConnectorIntegration<api::Authorize, types::PaymentsAuthorizeData, types::PaymentsResponseData>
|
||||
|
||||
@ -9,10 +9,12 @@ use serde::{Deserialize, Serialize};
|
||||
use crate::{
|
||||
connector::utils::{
|
||||
self, AddressDetailsData, BankDirectDebitBillingData, BrowserInformationData,
|
||||
ConnectorCustomerData, PaymentsAuthorizeRequestData, PaymentsPreProcessingData, RouterData,
|
||||
ConnectorCustomerData, PaymentsAuthorizeRequestData, RouterData, SetupMandateRequestData,
|
||||
},
|
||||
core::errors,
|
||||
types::{self, api, storage::enums, transformers::ForeignTryFrom, MandateReference},
|
||||
types::{
|
||||
self, api, storage::enums, transformers::ForeignTryFrom, MandateReference, ResponseId,
|
||||
},
|
||||
};
|
||||
|
||||
pub struct GocardlessRouterData<T> {
|
||||
@ -75,18 +77,68 @@ impl TryFrom<&types::ConnectorCustomerRouterData> for GocardlessCustomerRequest
|
||||
type Error = error_stack::Report<errors::ConnectorError>;
|
||||
fn try_from(item: &types::ConnectorCustomerRouterData) -> Result<Self, Self::Error> {
|
||||
let email = item.request.get_email()?;
|
||||
let billing_address = item.get_billing_address()?;
|
||||
let given_name = billing_address.get_first_name()?.to_owned();
|
||||
let family_name = billing_address.get_last_name()?.to_owned();
|
||||
let billing_details = match &item.request.payment_method_data {
|
||||
api_models::payments::PaymentMethodData::BankDebit(bank_debit_data) => {
|
||||
match bank_debit_data.clone() {
|
||||
BankDebitData::AchBankDebit {
|
||||
billing_details, ..
|
||||
} => Ok(billing_details),
|
||||
BankDebitData::SepaBankDebit {
|
||||
billing_details, ..
|
||||
} => Ok(billing_details),
|
||||
BankDebitData::BecsBankDebit {
|
||||
billing_details, ..
|
||||
} => Ok(billing_details),
|
||||
BankDebitData::BacsBankDebit { .. } => {
|
||||
Err(errors::ConnectorError::NotImplemented(
|
||||
utils::get_unimplemented_payment_method_error_message("Gocardless"),
|
||||
))
|
||||
}
|
||||
}
|
||||
}
|
||||
api_models::payments::PaymentMethodData::Card(_)
|
||||
| api_models::payments::PaymentMethodData::CardRedirect(_)
|
||||
| api_models::payments::PaymentMethodData::Wallet(_)
|
||||
| api_models::payments::PaymentMethodData::PayLater(_)
|
||||
| api_models::payments::PaymentMethodData::BankRedirect(_)
|
||||
| api_models::payments::PaymentMethodData::BankTransfer(_)
|
||||
| api_models::payments::PaymentMethodData::Crypto(_)
|
||||
| api_models::payments::PaymentMethodData::MandatePayment
|
||||
| api_models::payments::PaymentMethodData::Reward
|
||||
| api_models::payments::PaymentMethodData::Upi(_)
|
||||
| api_models::payments::PaymentMethodData::Voucher(_)
|
||||
| api_models::payments::PaymentMethodData::GiftCard(_) => {
|
||||
Err(errors::ConnectorError::NotImplemented(
|
||||
utils::get_unimplemented_payment_method_error_message("Gocardless"),
|
||||
))
|
||||
}
|
||||
}?;
|
||||
|
||||
let billing_details_name = billing_details.name.expose();
|
||||
|
||||
if billing_details_name.is_empty() {
|
||||
Err(errors::ConnectorError::MissingRequiredField {
|
||||
field_name: "billing_details.name",
|
||||
})?
|
||||
}
|
||||
let (given_name, family_name) = billing_details_name
|
||||
.trim()
|
||||
.rsplit_once(' ')
|
||||
.unwrap_or((&billing_details_name, &billing_details_name));
|
||||
|
||||
let billing_address = billing_details
|
||||
.address
|
||||
.ok_or_else(utils::missing_field_err("billing_details.address"))?;
|
||||
|
||||
let metadata = CustomerMetaData {
|
||||
crm_id: item.customer_id.clone().map(Secret::new),
|
||||
};
|
||||
let region = get_region(billing_address)?;
|
||||
let region = get_region(&billing_address)?;
|
||||
Ok(Self {
|
||||
customers: GocardlessCustomer {
|
||||
email,
|
||||
given_name,
|
||||
family_name,
|
||||
given_name: Secret::new(given_name.to_string()),
|
||||
family_name: Secret::new(family_name.to_string()),
|
||||
metadata,
|
||||
address_line1: billing_address.line1.to_owned(),
|
||||
address_line2: billing_address.line2.to_owned(),
|
||||
@ -98,7 +150,7 @@ impl TryFrom<&types::ConnectorCustomerRouterData> for GocardlessCustomerRequest
|
||||
postal_code: billing_address.zip.to_owned(),
|
||||
// Should be populated based on the billing country
|
||||
swedish_identity_number: None,
|
||||
city: billing_address.city.clone().map(Secret::new),
|
||||
city: billing_address.city.map(Secret::new),
|
||||
},
|
||||
})
|
||||
}
|
||||
@ -259,34 +311,26 @@ impl TryFrom<&BankDebitData> for CustomerBankAccount {
|
||||
fn try_from(item: &BankDebitData) -> Result<Self, Self::Error> {
|
||||
match item {
|
||||
BankDebitData::AchBankDebit {
|
||||
//billing_details,
|
||||
billing_details,
|
||||
account_number,
|
||||
routing_number,
|
||||
// bank_type,
|
||||
//bank_account_holder_name,
|
||||
card_holder_name,
|
||||
bank_type,
|
||||
bank_account_holder_name,
|
||||
..
|
||||
} => {
|
||||
//let bank_type = bank_type.ok_or_else(utils::missing_field_err("bank_type"))?;
|
||||
//let country_code = billing_details.get_billing_country()?;
|
||||
//let account_holder_name =
|
||||
// bank_account_holder_name
|
||||
// .clone()
|
||||
// .ok_or_else(utils::missing_field_err(
|
||||
// "payment_method_data.bank_debit.ach_bank_debit.bank_account_holder_name",
|
||||
//))?;
|
||||
let bank_type = bank_type.ok_or_else(utils::missing_field_err("bank_type"))?;
|
||||
let country_code = billing_details.get_billing_country()?;
|
||||
let account_holder_name =
|
||||
card_holder_name
|
||||
bank_account_holder_name
|
||||
.clone()
|
||||
.ok_or_else(utils::missing_field_err(
|
||||
"payment_method_data.bank_debit.ach_bank_debit.card_holder_name",
|
||||
))?;
|
||||
"payment_method_data.bank_debit.ach_bank_debit.bank_account_holder_name",
|
||||
))?;
|
||||
let us_bank_account = USBankAccount {
|
||||
country_code: CountryAlpha2::US,
|
||||
country_code,
|
||||
account_number: account_number.clone(),
|
||||
bank_code: routing_number.clone(),
|
||||
//account_type: AccountType::from(bank_type),
|
||||
account_type: AccountType::Checking,
|
||||
account_type: AccountType::from(bank_type),
|
||||
account_holder_name,
|
||||
};
|
||||
Ok(Self::USBankAccount(us_bank_account))
|
||||
@ -416,46 +460,40 @@ pub struct MandateLink {
|
||||
customer_bank_account: Secret<String>,
|
||||
}
|
||||
|
||||
impl TryFrom<&types::PaymentsPreProcessingRouterData> for GocardlessMandateRequest {
|
||||
impl TryFrom<&types::SetupMandateRouterData> for GocardlessMandateRequest {
|
||||
type Error = error_stack::Report<errors::ConnectorError>;
|
||||
fn try_from(item: &types::PaymentsPreProcessingRouterData) -> Result<Self, Self::Error> {
|
||||
fn try_from(item: &types::SetupMandateRouterData) -> Result<Self, Self::Error> {
|
||||
let (scheme, payer_ip_address) = match &item.request.payment_method_data {
|
||||
Some(payment_method_data) => match payment_method_data {
|
||||
api_models::payments::PaymentMethodData::BankDebit(bank_debit_data) => {
|
||||
let payer_ip_address = get_ip_if_required(bank_debit_data, item)?;
|
||||
Ok((
|
||||
GocardlessScheme::try_from(bank_debit_data)?,
|
||||
payer_ip_address,
|
||||
))
|
||||
}
|
||||
api_models::payments::PaymentMethodData::Card(_)
|
||||
| api_models::payments::PaymentMethodData::CardRedirect(_)
|
||||
| api_models::payments::PaymentMethodData::Wallet(_)
|
||||
| api_models::payments::PaymentMethodData::PayLater(_)
|
||||
| api_models::payments::PaymentMethodData::BankRedirect(_)
|
||||
| api_models::payments::PaymentMethodData::BankTransfer(_)
|
||||
| api_models::payments::PaymentMethodData::Crypto(_)
|
||||
| api_models::payments::PaymentMethodData::MandatePayment
|
||||
| api_models::payments::PaymentMethodData::Reward
|
||||
| api_models::payments::PaymentMethodData::Upi(_)
|
||||
| api_models::payments::PaymentMethodData::Voucher(_)
|
||||
| api_models::payments::PaymentMethodData::GiftCard(_) => {
|
||||
Err(errors::ConnectorError::NotImplemented(
|
||||
"Preprocessing flow for selected payment method through Gocardless"
|
||||
.to_string(),
|
||||
))
|
||||
}
|
||||
},
|
||||
None => Err(errors::ConnectorError::NotImplemented(
|
||||
"Preprocessing flow for selected payment method through Gocardless".to_string(),
|
||||
)),
|
||||
api_models::payments::PaymentMethodData::BankDebit(bank_debit_data) => {
|
||||
let payer_ip_address = get_ip_if_required(bank_debit_data, item)?;
|
||||
Ok((
|
||||
GocardlessScheme::try_from(bank_debit_data)?,
|
||||
payer_ip_address,
|
||||
))
|
||||
}
|
||||
api_models::payments::PaymentMethodData::Card(_)
|
||||
| api_models::payments::PaymentMethodData::CardRedirect(_)
|
||||
| api_models::payments::PaymentMethodData::Wallet(_)
|
||||
| api_models::payments::PaymentMethodData::PayLater(_)
|
||||
| api_models::payments::PaymentMethodData::BankRedirect(_)
|
||||
| api_models::payments::PaymentMethodData::BankTransfer(_)
|
||||
| api_models::payments::PaymentMethodData::Crypto(_)
|
||||
| api_models::payments::PaymentMethodData::MandatePayment
|
||||
| api_models::payments::PaymentMethodData::Reward
|
||||
| api_models::payments::PaymentMethodData::Upi(_)
|
||||
| api_models::payments::PaymentMethodData::Voucher(_)
|
||||
| api_models::payments::PaymentMethodData::GiftCard(_) => {
|
||||
Err(errors::ConnectorError::NotImplemented(
|
||||
"Setup Mandate flow for selected payment method through Gocardless".to_string(),
|
||||
))
|
||||
}
|
||||
}?;
|
||||
let payment_method_token = item.get_payment_method_token()?;
|
||||
let customer_bank_account = match payment_method_token {
|
||||
types::PaymentMethodToken::Token(token) => Ok(token),
|
||||
types::PaymentMethodToken::ApplePayDecrypt(_) => {
|
||||
Err(errors::ConnectorError::NotImplemented(
|
||||
"Preprocessing flow for selected payment method through Gocardless".to_string(),
|
||||
"Setup Mandate flow for selected payment method through Gocardless".to_string(),
|
||||
))
|
||||
}
|
||||
}?;
|
||||
@ -476,7 +514,7 @@ impl TryFrom<&types::PaymentsPreProcessingRouterData> for GocardlessMandateReque
|
||||
|
||||
fn get_ip_if_required(
|
||||
bank_debit_data: &BankDebitData,
|
||||
item: &types::PaymentsPreProcessingRouterData,
|
||||
item: &types::SetupMandateRouterData,
|
||||
) -> Result<Option<Secret<String, IpAddress>>, error_stack::Report<errors::ConnectorError>> {
|
||||
let ip_address = item.request.get_browser_info()?.get_ip_address()?;
|
||||
match bank_debit_data {
|
||||
@ -495,7 +533,7 @@ impl TryFrom<&BankDebitData> for GocardlessScheme {
|
||||
BankDebitData::SepaBankDebit { .. } => Ok(Self::SepaCore),
|
||||
BankDebitData::BecsBankDebit { .. } => Ok(Self::Becs),
|
||||
BankDebitData::BacsBankDebit { .. } => Err(errors::ConnectorError::NotImplemented(
|
||||
"Preprocessing flow for selected payment method through Gocardless".to_string(),
|
||||
"Setup Mandate flow for selected payment method through Gocardless".to_string(),
|
||||
)
|
||||
.into()),
|
||||
}
|
||||
@ -517,29 +555,32 @@ impl<F>
|
||||
types::ResponseRouterData<
|
||||
F,
|
||||
GocardlessMandateResponse,
|
||||
types::PaymentsPreProcessingData,
|
||||
types::SetupMandateRequestData,
|
||||
types::PaymentsResponseData,
|
||||
>,
|
||||
> for types::RouterData<F, types::PaymentsPreProcessingData, types::PaymentsResponseData>
|
||||
> for types::RouterData<F, types::SetupMandateRequestData, types::PaymentsResponseData>
|
||||
{
|
||||
type Error = error_stack::Report<errors::ConnectorError>;
|
||||
fn try_from(
|
||||
item: types::ResponseRouterData<
|
||||
F,
|
||||
GocardlessMandateResponse,
|
||||
types::PaymentsPreProcessingData,
|
||||
types::SetupMandateRequestData,
|
||||
types::PaymentsResponseData,
|
||||
>,
|
||||
) -> Result<Self, Self::Error> {
|
||||
let mandate_reference = Some(MandateReference {
|
||||
connector_mandate_id: Some(item.response.mandates.id.clone()),
|
||||
payment_method_id: None,
|
||||
});
|
||||
Ok(Self {
|
||||
preprocessing_id: Some(item.response.mandates.id.clone()),
|
||||
response: Ok(types::PaymentsResponseData::PreProcessingResponse {
|
||||
pre_processing_id: types::PreprocessingResponseId::PreProcessingId(
|
||||
item.response.mandates.id,
|
||||
),
|
||||
response: Ok(types::PaymentsResponseData::TransactionResponse {
|
||||
connector_metadata: None,
|
||||
session_token: None,
|
||||
connector_response_reference_id: None,
|
||||
resource_id: ResponseId::NoResponseId,
|
||||
redirection_data: None,
|
||||
mandate_reference,
|
||||
network_txn_id: None,
|
||||
}),
|
||||
status: enums::AttemptStatus::Pending,
|
||||
..item.data
|
||||
@ -579,14 +620,10 @@ impl TryFrom<&GocardlessRouterData<&types::PaymentsAuthorizeRouterData>>
|
||||
item: &GocardlessRouterData<&types::PaymentsAuthorizeRouterData>,
|
||||
) -> Result<Self, Self::Error> {
|
||||
let mandate_id = if item.router_data.request.is_mandate_payment() {
|
||||
if item.router_data.request.setup_future_usage.is_some() {
|
||||
item.router_data.get_preprocessing_id()
|
||||
} else {
|
||||
item.router_data
|
||||
.request
|
||||
.connector_mandate_id()
|
||||
.ok_or_else(utils::missing_field_err("preprocessing_id"))
|
||||
}
|
||||
item.router_data
|
||||
.request
|
||||
.connector_mandate_id()
|
||||
.ok_or_else(utils::missing_field_err("mandate_id"))
|
||||
} else {
|
||||
Err(errors::ConnectorError::NotImplemented(
|
||||
utils::get_unimplemented_payment_method_error_message("gocardless"),
|
||||
@ -682,13 +719,8 @@ impl<F>
|
||||
types::PaymentsResponseData,
|
||||
>,
|
||||
) -> Result<Self, Self::Error> {
|
||||
let connector_mandate_id = if item.data.request.setup_mandate_details.is_some() {
|
||||
item.data.get_preprocessing_id()?
|
||||
} else {
|
||||
item.data.request.get_connector_mandate_id()?
|
||||
};
|
||||
let mandate_reference = MandateReference {
|
||||
connector_mandate_id: Some(connector_mandate_id),
|
||||
connector_mandate_id: Some(item.data.request.get_connector_mandate_id()?),
|
||||
payment_method_id: None,
|
||||
};
|
||||
Ok(Self {
|
||||
|
||||
@ -256,6 +256,17 @@ impl PaymentsCaptureRequestData for types::PaymentsCaptureData {
|
||||
}
|
||||
}
|
||||
|
||||
pub trait SetupMandateRequestData {
|
||||
fn get_browser_info(&self) -> Result<types::BrowserInformation, Error>;
|
||||
}
|
||||
|
||||
impl SetupMandateRequestData for types::SetupMandateRequestData {
|
||||
fn get_browser_info(&self) -> Result<types::BrowserInformation, Error> {
|
||||
self.browser_info
|
||||
.clone()
|
||||
.ok_or_else(missing_field_err("browser_info"))
|
||||
}
|
||||
}
|
||||
pub trait PaymentsAuthorizeRequestData {
|
||||
fn is_auto_capture(&self) -> Result<bool, Error>;
|
||||
fn get_email(&self) -> Result<Email, Error>;
|
||||
|
||||
@ -342,6 +342,7 @@ impl<F> TryFrom<&types::RouterData<F, types::PaymentsAuthorizeData, types::Payme
|
||||
) -> Result<Self, Self::Error> {
|
||||
Ok(Self {
|
||||
email: data.request.email.clone(),
|
||||
payment_method_data: data.request.payment_method_data.clone(),
|
||||
description: None,
|
||||
phone: None,
|
||||
name: None,
|
||||
|
||||
@ -161,6 +161,7 @@ impl TryFrom<types::SetupMandateRequestData> for types::ConnectorCustomerData {
|
||||
fn try_from(data: types::SetupMandateRequestData) -> Result<Self, Self::Error> {
|
||||
Ok(Self {
|
||||
email: data.email,
|
||||
payment_method_data: data.payment_method_data,
|
||||
description: None,
|
||||
phone: None,
|
||||
name: None,
|
||||
|
||||
@ -230,7 +230,7 @@ impl<F: Send + Clone> GetTracker<F, PaymentData<F>, api::PaymentsRequest> for Pa
|
||||
token,
|
||||
payment_method,
|
||||
payment_method_type,
|
||||
setup_mandate,
|
||||
mut setup_mandate,
|
||||
recurring_mandate_payment_data,
|
||||
mandate_connector,
|
||||
) = mandate_details;
|
||||
@ -318,7 +318,10 @@ impl<F: Send + Clone> GetTracker<F, PaymentData<F>, api::PaymentsRequest> for Pa
|
||||
.or(payment_attempt.business_sub_label);
|
||||
|
||||
// The operation merges mandate data from both request and payment_attempt
|
||||
let setup_mandate = setup_mandate.map(Into::into);
|
||||
setup_mandate = setup_mandate.map(|mut sm| {
|
||||
sm.mandate_type = payment_attempt.mandate_details.clone().or(sm.mandate_type);
|
||||
sm
|
||||
});
|
||||
|
||||
Ok((
|
||||
Box::new(self),
|
||||
|
||||
@ -414,6 +414,7 @@ pub struct ConnectorCustomerData {
|
||||
pub phone: Option<Secret<String>>,
|
||||
pub name: Option<String>,
|
||||
pub preprocessing_id: Option<String>,
|
||||
pub payment_method_data: payments::PaymentMethodData,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
@ -993,6 +994,7 @@ impl From<&&mut PaymentsAuthorizeRouterData> for ConnectorCustomerData {
|
||||
Self {
|
||||
email: data.request.email.to_owned(),
|
||||
preprocessing_id: data.preprocessing_id.to_owned(),
|
||||
payment_method_data: data.request.payment_method_data.to_owned(),
|
||||
description: None,
|
||||
phone: None,
|
||||
name: None,
|
||||
|
||||
@ -966,6 +966,7 @@ impl Default for PaymentRefundType {
|
||||
impl Default for CustomerType {
|
||||
fn default() -> Self {
|
||||
let data = types::ConnectorCustomerData {
|
||||
payment_method_data: types::api::PaymentMethodData::Card(CCardType::default().0),
|
||||
description: None,
|
||||
email: Some(Email::from(Secret::new("test@juspay.in".to_string()))),
|
||||
phone: None,
|
||||
|
||||
Reference in New Issue
Block a user