Skip to content
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
25 changes: 12 additions & 13 deletions crates/router/src/core/payments/flows/update_metadata_flow.rs
Original file line number Diff line number Diff line change
Expand Up @@ -30,19 +30,18 @@ impl
merchant_recipient_data: Option<types::MerchantRecipientData>,
header_payload: Option<hyperswitch_domain_models::payments::HeaderPayload>,
) -> RouterResult<types::PaymentsUpdateMetadataRouterData> {
Box::pin(transformers::construct_payment_router_data::<
api::UpdateMetadata,
types::PaymentsUpdateMetadataData,
>(
state,
self.clone(),
connector_id,
merchant_context,
customer,
merchant_connector_account,
merchant_recipient_data,
header_payload,
))
Box::pin(
transformers::construct_payment_router_data_for_update_metadata(
state,
self.clone(),
connector_id,
merchant_context,
customer,
merchant_connector_account,
merchant_recipient_data,
header_payload,
),
)
.await
}

Expand Down
189 changes: 189 additions & 0 deletions crates/router/src/core/payments/transformers.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1247,6 +1247,195 @@ where
Ok(router_data)
}

#[cfg(all(any(feature = "v1", feature = "v2"), not(feature = "customer_v2")))]
#[instrument(skip_all)]
#[allow(clippy::too_many_arguments)]
pub async fn construct_payment_router_data_for_update_metadata<'a>(
state: &'a SessionState,
payment_data: PaymentData<api::UpdateMetadata>,
connector_id: &str,
merchant_context: &domain::MerchantContext,
customer: &'a Option<domain::Customer>,
merchant_connector_account: &helpers::MerchantConnectorAccountType,
merchant_recipient_data: Option<types::MerchantRecipientData>,
header_payload: Option<hyperswitch_domain_models::payments::HeaderPayload>,
) -> RouterResult<
types::RouterData<
api::UpdateMetadata,
types::PaymentsUpdateMetadataData,
types::PaymentsResponseData,
>,
> {
let (payment_method, router_data);

fp_utils::when(merchant_connector_account.is_disabled(), || {
Err(errors::ApiErrorResponse::MerchantConnectorAccountDisabled)
})?;

let test_mode = merchant_connector_account.is_test_mode_on();

let auth_type: types::ConnectorAuthType = merchant_connector_account
.get_connector_account_details()
.parse_value("ConnectorAuthType")
.change_context(errors::ApiErrorResponse::InternalServerError)
.attach_printable("Failed while parsing value for ConnectorAuthType")?;

payment_method = payment_data
.payment_attempt
.payment_method
.or(payment_data.payment_attempt.payment_method)
.get_required_value("payment_method_type")?;

// [#44]: why should response be filled during request
let response = Err(hyperswitch_domain_models::router_data::ErrorResponse {
code: "IR_20".to_string(),
message: "Update metadata is not implemented for this connector".to_string(),
reason: None,
status_code: http::StatusCode::BAD_REQUEST.as_u16(),
attempt_status: None,
connector_transaction_id: None,
network_decline_code: None,
network_advice_code: None,
network_error_message: None,
});

let additional_data = PaymentAdditionalData {
router_base_url: state.base_url.clone(),
connector_name: connector_id.to_string(),
payment_data: payment_data.clone(),
state,
customer_data: customer,
};

let customer_id = customer.to_owned().map(|customer| customer.customer_id);

let supported_connector = &state
.conf
.multiple_api_version_supported_connectors
.supported_connectors;
let connector_enum = api_models::enums::Connector::from_str(connector_id)
.change_context(errors::ConnectorError::InvalidConnectorName)
.change_context(errors::ApiErrorResponse::InvalidDataValue {
field_name: "connector",
})
.attach_printable_lazy(|| format!("unable to parse connector name {connector_id:?}"))?;

let connector_api_version = if supported_connector.contains(&connector_enum) {
state
.store
.find_config_by_key(&format!("connector_api_version_{connector_id}"))
.await
.map(|value| value.config)
.ok()
} else {
None
};

let apple_pay_flow = payments::decide_apple_pay_flow(
state,
payment_data.payment_attempt.payment_method_type,
Some(merchant_connector_account),
);

let unified_address = if let Some(payment_method_info) =
payment_data.payment_method_info.clone()
{
let payment_method_billing = payment_method_info
.payment_method_billing_address
.map(|decrypted_data| decrypted_data.into_inner().expose())
.map(|decrypted_value| decrypted_value.parse_value("payment_method_billing_address"))
.transpose()
.change_context(errors::ApiErrorResponse::InternalServerError)
.attach_printable("unable to parse payment_method_billing_address")?;
payment_data
.address
.clone()
.unify_with_payment_data_billing(payment_method_billing)
} else {
payment_data.address
};
let connector_mandate_request_reference_id = payment_data
.payment_attempt
.connector_mandate_detail
.as_ref()
.and_then(|detail| detail.get_connector_mandate_request_reference_id());

crate::logger::debug!("unified address details {:?}", unified_address);

router_data = types::RouterData {
flow: PhantomData,
merchant_id: merchant_context.get_merchant_account().get_id().clone(),
customer_id,
tenant_id: state.tenant.tenant_id.clone(),
connector: connector_id.to_owned(),
payment_id: payment_data
.payment_attempt
.payment_id
.get_string_repr()
.to_owned(),
attempt_id: payment_data.payment_attempt.attempt_id.clone(),
status: payment_data.payment_attempt.status,
payment_method,
connector_auth_type: auth_type,
description: payment_data.payment_intent.description.clone(),
address: unified_address,
auth_type: payment_data
.payment_attempt
.authentication_type
.unwrap_or_default(),
connector_meta_data: merchant_connector_account.get_metadata(),
connector_wallets_details: merchant_connector_account.get_connector_wallets_details(),
request: types::PaymentsUpdateMetadataData::try_from(additional_data)?,
response,
amount_captured: payment_data
.payment_intent
.amount_captured
.map(|amt| amt.get_amount_as_i64()),
minor_amount_captured: payment_data.payment_intent.amount_captured,
access_token: None,
session_token: None,
reference_id: None,
payment_method_status: payment_data.payment_method_info.map(|info| info.status),
payment_method_token: payment_data
.pm_token
.map(|token| types::PaymentMethodToken::Token(Secret::new(token))),
connector_customer: payment_data.connector_customer_id,
recurring_mandate_payment_data: payment_data.recurring_mandate_payment_data,
connector_request_reference_id: core_utils::get_connector_request_reference_id(
&state.conf,
merchant_context.get_merchant_account().get_id(),
&payment_data.payment_attempt,
),
preprocessing_id: payment_data.payment_attempt.preprocessing_step_id,
#[cfg(feature = "payouts")]
payout_method_data: None,
#[cfg(feature = "payouts")]
quote_id: None,
test_mode,
payment_method_balance: None,
connector_api_version,
connector_http_status_code: None,
external_latency: None,
apple_pay_flow,
frm_metadata: None,
refund_id: None,
dispute_id: None,
connector_response: None,
integrity_check: Ok(()),
additional_merchant_data: merchant_recipient_data.map(|data| {
api_models::admin::AdditionalMerchantData::foreign_from(
types::AdditionalMerchantData::OpenBankingRecipientData(data),
)
}),
header_payload,
connector_mandate_request_reference_id,
authentication_id: None,
psd2_sca_exemption_type: payment_data.payment_intent.psd2_sca_exemption_type,
};

Ok(router_data)
}

pub trait ToResponse<F, D, Op>
where
Self: Sized,
Expand Down
Loading