fix(update_metadata): Update Metadata for any connectors other than stripe gives 500 error (#7984)

This commit is contained in:
Nithin N
2025-05-08 16:37:30 +05:30
committed by GitHub
parent 1933722637
commit fafe4d9928
2 changed files with 201 additions and 13 deletions

View File

@ -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
}

View File

@ -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,