mirror of
https://github.com/juspay/hyperswitch.git
synced 2025-11-02 04:04:43 +08:00
chore: code refinement
This commit is contained in:
@ -934,15 +934,13 @@ async fn call_unified_connector_service_authorize(
|
||||
|
||||
let payment_authorize_response = response.into_inner();
|
||||
|
||||
let (router_data_response, status_code) =
|
||||
handle_unified_connector_service_response_for_payment_authorize(
|
||||
&mut router_data,
|
||||
payment_authorize_response.clone(),
|
||||
)
|
||||
.change_context(ApiErrorResponse::InternalServerError)
|
||||
.attach_printable("Failed to deserialize UCS response")?;
|
||||
let ucs_data = handle_unified_connector_service_response_for_payment_authorize(
|
||||
payment_authorize_response.clone(),
|
||||
)
|
||||
.change_context(ApiErrorResponse::InternalServerError)
|
||||
.attach_printable("Failed to deserialize UCS response")?;
|
||||
|
||||
let router_data_response = router_data_response.map(|(response, status)| {
|
||||
let router_data_response = ucs_data.router_data_response.map(|(response, status)| {
|
||||
router_data.status = status;
|
||||
response
|
||||
});
|
||||
@ -951,7 +949,16 @@ async fn call_unified_connector_service_authorize(
|
||||
.raw_connector_response
|
||||
.clone()
|
||||
.map(|raw_connector_response| raw_connector_response.expose().into());
|
||||
router_data.connector_http_status_code = Some(status_code);
|
||||
router_data.connector_http_status_code = Some(ucs_data.status_code);
|
||||
|
||||
// Populate connector_customer_id if present
|
||||
ucs_data.connector_customer_id.map(|connector_customer_id| {
|
||||
router_data.connector_customer = Some(connector_customer_id);
|
||||
});
|
||||
|
||||
ucs_data.connector_response.map(|customer_response| {
|
||||
router_data.connector_response = Some(customer_response);
|
||||
});
|
||||
|
||||
Ok((router_data, payment_authorize_response))
|
||||
},
|
||||
@ -1028,15 +1035,13 @@ async fn call_unified_connector_service_repeat_payment(
|
||||
|
||||
let payment_repeat_response = response.into_inner();
|
||||
|
||||
let (router_data_response, status_code) =
|
||||
handle_unified_connector_service_response_for_payment_repeat(
|
||||
&mut router_data,
|
||||
payment_repeat_response.clone(),
|
||||
)
|
||||
.change_context(ApiErrorResponse::InternalServerError)
|
||||
.attach_printable("Failed to deserialize UCS response")?;
|
||||
let ucs_data = handle_unified_connector_service_response_for_payment_repeat(
|
||||
payment_repeat_response.clone(),
|
||||
)
|
||||
.change_context(ApiErrorResponse::InternalServerError)
|
||||
.attach_printable("Failed to deserialize UCS response")?;
|
||||
|
||||
let router_data_response = router_data_response.map(|(response, status)| {
|
||||
let router_data_response = ucs_data.router_data_response.map(|(response, status)| {
|
||||
router_data.status = status;
|
||||
response
|
||||
});
|
||||
@ -1045,7 +1050,17 @@ async fn call_unified_connector_service_repeat_payment(
|
||||
.raw_connector_response
|
||||
.clone()
|
||||
.map(|raw_connector_response| raw_connector_response.expose().into());
|
||||
router_data.connector_http_status_code = Some(status_code);
|
||||
router_data.connector_http_status_code = Some(ucs_data.status_code);
|
||||
|
||||
// Populate connector_customer_id if present
|
||||
ucs_data.connector_customer_id.map(|connector_customer_id| {
|
||||
router_data.connector_customer = Some(connector_customer_id);
|
||||
});
|
||||
|
||||
// Populate connector_response if present
|
||||
ucs_data.connector_response.map(|connector_response| {
|
||||
router_data.connector_response = Some(connector_response);
|
||||
});
|
||||
|
||||
Ok((router_data, payment_repeat_response))
|
||||
},
|
||||
|
||||
@ -229,19 +229,19 @@ impl Feature<api::Void, types::PaymentsCancelData>
|
||||
|
||||
let payment_void_response = response.into_inner();
|
||||
|
||||
let (router_data_response, status_code) =
|
||||
handle_unified_connector_service_response_for_payment_cancel(
|
||||
payment_void_response.clone(),
|
||||
)
|
||||
.change_context(ApiErrorResponse::InternalServerError)
|
||||
.attach_printable("Failed to deserialize UCS response")?;
|
||||
let ucs_data = handle_unified_connector_service_response_for_payment_cancel(
|
||||
payment_void_response.clone(),
|
||||
)
|
||||
.change_context(ApiErrorResponse::InternalServerError)
|
||||
.attach_printable("Failed to deserialize UCS response")?;
|
||||
|
||||
let router_data_response = router_data_response.map(|(response, status)| {
|
||||
router_data.status = status;
|
||||
response
|
||||
});
|
||||
let router_data_response =
|
||||
ucs_data.router_data_response.map(|(response, status)| {
|
||||
router_data.status = status;
|
||||
response
|
||||
});
|
||||
router_data.response = router_data_response;
|
||||
router_data.connector_http_status_code = Some(status_code);
|
||||
router_data.connector_http_status_code = Some(ucs_data.status_code);
|
||||
|
||||
Ok((router_data, payment_void_response))
|
||||
},
|
||||
|
||||
@ -239,23 +239,23 @@ impl Feature<api::Capture, types::PaymentsCaptureData>
|
||||
|
||||
let payment_capture_response = response.into_inner();
|
||||
|
||||
let (router_data_response, status_code) =
|
||||
handle_unified_connector_service_response_for_payment_capture(
|
||||
payment_capture_response.clone(),
|
||||
)
|
||||
.change_context(ApiErrorResponse::InternalServerError)
|
||||
.attach_printable("Failed to deserialize UCS response")?;
|
||||
let ucs_data = handle_unified_connector_service_response_for_payment_capture(
|
||||
payment_capture_response.clone(),
|
||||
)
|
||||
.change_context(ApiErrorResponse::InternalServerError)
|
||||
.attach_printable("Failed to deserialize UCS response")?;
|
||||
|
||||
let router_data_response = router_data_response.map(|(response, status)| {
|
||||
router_data.status = status;
|
||||
response
|
||||
});
|
||||
let router_data_response =
|
||||
ucs_data.router_data_response.map(|(response, status)| {
|
||||
router_data.status = status;
|
||||
response
|
||||
});
|
||||
router_data.response = router_data_response;
|
||||
router_data.amount_captured = payment_capture_response.captured_amount;
|
||||
router_data.minor_amount_captured = payment_capture_response
|
||||
.minor_captured_amount
|
||||
.map(MinorUnit::new);
|
||||
router_data.connector_http_status_code = Some(status_code);
|
||||
router_data.connector_http_status_code = Some(ucs_data.status_code);
|
||||
|
||||
Ok((router_data, payment_capture_response))
|
||||
},
|
||||
|
||||
@ -436,15 +436,14 @@ impl Feature<api::ExternalVaultProxy, types::ExternalVaultProxyPaymentsData>
|
||||
|
||||
let payment_authorize_response = response.into_inner();
|
||||
|
||||
let (router_data_response, status_code) =
|
||||
let ucs_data =
|
||||
unified_connector_service::handle_unified_connector_service_response_for_payment_authorize(
|
||||
&mut router_data,
|
||||
payment_authorize_response.clone(),
|
||||
)
|
||||
.change_context(ApiErrorResponse::InternalServerError)
|
||||
.attach_printable("Failed to deserialize UCS response")?;
|
||||
|
||||
let router_data_response = router_data_response.map(|(response, status)|{
|
||||
let router_data_response = ucs_data.router_data_response.map(|(response, status)|{
|
||||
router_data.status = status;
|
||||
response
|
||||
});
|
||||
@ -453,7 +452,7 @@ impl Feature<api::ExternalVaultProxy, types::ExternalVaultProxyPaymentsData>
|
||||
.raw_connector_response
|
||||
.clone()
|
||||
.map(|raw_connector_response| raw_connector_response.expose().into());
|
||||
router_data.connector_http_status_code = Some(status_code);
|
||||
router_data.connector_http_status_code = Some(ucs_data.status_code);
|
||||
|
||||
Ok((router_data, payment_authorize_response))
|
||||
}
|
||||
|
||||
@ -342,20 +342,26 @@ impl Feature<api::SetupMandate, types::SetupMandateRequestData> for types::Setup
|
||||
|
||||
let payment_register_response = response.into_inner();
|
||||
|
||||
let (router_data_response, status_code) =
|
||||
handle_unified_connector_service_response_for_payment_register(
|
||||
&mut router_data,
|
||||
payment_register_response.clone(),
|
||||
)
|
||||
.change_context(ApiErrorResponse::InternalServerError)
|
||||
.attach_printable("Failed to deserialize UCS response")?;
|
||||
let ucs_data = handle_unified_connector_service_response_for_payment_register(
|
||||
payment_register_response.clone(),
|
||||
)
|
||||
.change_context(ApiErrorResponse::InternalServerError)
|
||||
.attach_printable("Failed to deserialize UCS response")?;
|
||||
|
||||
let router_data_response = router_data_response.map(|(response, status)| {
|
||||
router_data.status = status;
|
||||
response
|
||||
});
|
||||
let router_data_response =
|
||||
ucs_data.router_data_response.map(|(response, status)| {
|
||||
router_data.status = status;
|
||||
response
|
||||
});
|
||||
router_data.response = router_data_response;
|
||||
router_data.connector_http_status_code = Some(status_code);
|
||||
router_data.connector_http_status_code = Some(ucs_data.status_code);
|
||||
|
||||
// Populate connector_customer_id if present
|
||||
ucs_data.connector_customer_id.map(|connector_customer_id| {
|
||||
router_data.connector_customer = Some(connector_customer_id);
|
||||
});
|
||||
|
||||
// Note: Register flow doesn't populate connector_response
|
||||
|
||||
Ok((router_data, payment_register_response))
|
||||
},
|
||||
|
||||
@ -7905,18 +7905,17 @@ where
|
||||
/// Helper function to populate connector_customer_id from database before calling UCS
|
||||
/// This checks if a connector_customer_id already exists in the database and populates it into router_data
|
||||
/// Returns true if connector_customer_id was found and populated from DB, false otherwise
|
||||
async fn populate_connector_customer_from_db_before_ucs<F, Req, D>(
|
||||
async fn populate_connector_customer_from_db_before_ucs<D, F>(
|
||||
state: &SessionState,
|
||||
router_data: &mut RouterData<F, Req, PaymentsResponseData>,
|
||||
connector_label: Option<&str>,
|
||||
payment_data: &D,
|
||||
customer: &Option<domain::Customer>,
|
||||
merchant_connector_account: &MerchantConnectorAccountType,
|
||||
) -> RouterResult<bool>
|
||||
) -> RouterResult<Option<String>>
|
||||
where
|
||||
D: OperationSessionGetters<F>,
|
||||
{
|
||||
let mut connector_customer_id_was_populated = false;
|
||||
let mut connector_customer_id_was_populated = None;
|
||||
|
||||
if let (Some(connector_label), Some(connector_name)) = (
|
||||
connector_label,
|
||||
@ -7955,8 +7954,7 @@ where
|
||||
payment_data.get_payment_intent().payment_id.get_string_repr(),
|
||||
connector_label
|
||||
);
|
||||
router_data.connector_customer = Some(connector_customer_id.to_string());
|
||||
connector_customer_id_was_populated = true;
|
||||
connector_customer_id_was_populated = Some(connector_customer_id.to_string());
|
||||
}
|
||||
None => {
|
||||
router_env::logger::info!(
|
||||
@ -7978,14 +7976,14 @@ where
|
||||
async fn save_connector_customer_id_after_ucs<F, Req>(
|
||||
state: &SessionState,
|
||||
router_data: &RouterData<F, Req, PaymentsResponseData>,
|
||||
connector_customer_id_was_populated_from_db: bool,
|
||||
connector_customer_id_was_populated_from_db: Option<String>,
|
||||
connector_label: &Option<String>,
|
||||
customer: &Option<domain::Customer>,
|
||||
merchant_context: &domain::MerchantContext,
|
||||
payment_id: String,
|
||||
) -> RouterResult<()> {
|
||||
// Process only if connector_customer_id was NOT already in DB
|
||||
if !connector_customer_id_was_populated_from_db {
|
||||
if !connector_customer_id_was_populated_from_db.is_some() {
|
||||
// Extract necessary fields and save if both are present
|
||||
match (&router_data.connector_customer, connector_label.as_ref()) {
|
||||
(Some(connector_customer_id), Some(connector_label_str)) => {
|
||||
@ -8019,7 +8017,6 @@ async fn save_connector_customer_id_after_ucs<F, Req>(
|
||||
payment_id
|
||||
);
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
@ -8188,7 +8185,6 @@ where
|
||||
let connector_customer_id_was_populated_from_db =
|
||||
populate_connector_customer_from_db_before_ucs(
|
||||
state,
|
||||
&mut router_data,
|
||||
connector_label.as_deref(),
|
||||
payment_data,
|
||||
customer,
|
||||
@ -8196,6 +8192,12 @@ where
|
||||
)
|
||||
.await?;
|
||||
|
||||
connector_customer_id_was_populated_from_db
|
||||
.as_ref()
|
||||
.map(|id| {
|
||||
router_data.connector_customer = Some(id.clone());
|
||||
});
|
||||
|
||||
// Based on the preprocessing response, decide whether to continue with UCS call
|
||||
if should_continue {
|
||||
router_data
|
||||
@ -8380,17 +8382,20 @@ where
|
||||
// Populate connector_customer_id from database for shadow UCS call
|
||||
// Use the pre-calculated connector_label
|
||||
// Track whether ID was found in DB to avoid redundant save later
|
||||
let _connector_customer_id_was_populated_from_db =
|
||||
let connector_customer_id_was_populated_from_db =
|
||||
populate_connector_customer_from_db_before_ucs(
|
||||
state,
|
||||
&mut unified_connector_service_router_data,
|
||||
unified_connector_service_connector_label.as_deref(),
|
||||
payment_data,
|
||||
customer,
|
||||
&merchant_connector_account,
|
||||
)
|
||||
.await
|
||||
.unwrap_or(false); // Don't fail the main flow if shadow UCS populate fails
|
||||
.unwrap_or_default(); // Don't fail the main flow if shadow UCS populate fails
|
||||
|
||||
connector_customer_id_was_populated_from_db.map(|id| {
|
||||
unified_connector_service_router_data.connector_customer = Some(id);
|
||||
});
|
||||
|
||||
let lineage_ids = grpc_client::LineageIds::new(
|
||||
business_profile.merchant_id.clone(),
|
||||
|
||||
@ -60,7 +60,7 @@ use crate::{
|
||||
events::connector_api_logs::ConnectorEvent,
|
||||
headers::{CONTENT_TYPE, X_REQUEST_ID},
|
||||
routes::SessionState,
|
||||
types::transformers::ForeignTryFrom,
|
||||
types::{transformers::ForeignTryFrom, UcsResponseData},
|
||||
};
|
||||
|
||||
pub mod transformers;
|
||||
@ -69,13 +69,7 @@ pub mod transformers;
|
||||
pub use transformers::{WebhookTransformData, WebhookTransformationStatus};
|
||||
|
||||
/// Type alias for return type used by unified connector service response handlers
|
||||
type UnifiedConnectorServiceResult = CustomResult<
|
||||
(
|
||||
Result<(PaymentsResponseData, AttemptStatus), ErrorResponse>,
|
||||
u16,
|
||||
),
|
||||
UnifiedConnectorServiceError,
|
||||
>;
|
||||
type UnifiedConnectorServiceResult = CustomResult<UcsResponseData, UnifiedConnectorServiceError>;
|
||||
|
||||
/// Checks if the Unified Connector Service (UCS) is available for use
|
||||
async fn check_ucs_availability(state: &SessionState) -> UcsAvailability {
|
||||
@ -759,8 +753,7 @@ pub fn build_unified_connector_service_external_vault_proxy_metadata(
|
||||
}
|
||||
}
|
||||
|
||||
pub fn handle_unified_connector_service_response_for_payment_authorize<F, Req>(
|
||||
router_data: &mut RouterData<F, Req, PaymentsResponseData>,
|
||||
pub fn handle_unified_connector_service_response_for_payment_authorize(
|
||||
response: PaymentServiceAuthorizeResponse,
|
||||
) -> UnifiedConnectorServiceResult {
|
||||
let status_code = transformers::convert_connector_service_status_code(response.status_code)?;
|
||||
@ -770,17 +763,17 @@ pub fn handle_unified_connector_service_response_for_payment_authorize<F, Req>(
|
||||
response.clone(),
|
||||
)?;
|
||||
|
||||
// Populate connector_customer_id from UCS state
|
||||
populate_connector_customer_id_from_ucs_state(router_data, response.state.as_ref());
|
||||
let connector_customer_id =
|
||||
extract_connector_customer_id_from_ucs_state(response.state.as_ref());
|
||||
let connector_response =
|
||||
extract_connector_response_from_ucs(response.connector_response.as_ref());
|
||||
|
||||
// Populate connector_response from UCS response (log errors, don't fail)
|
||||
populate_connector_response_from_ucs(router_data, response.connector_response.as_ref())
|
||||
.inspect_err(|err| {
|
||||
router_env::logger::warn!("Failed to populate connector_response from UCS: {:?}", err);
|
||||
})
|
||||
.ok();
|
||||
|
||||
Ok((router_data_response, status_code))
|
||||
Ok(UcsResponseData {
|
||||
router_data_response,
|
||||
status_code,
|
||||
connector_customer_id,
|
||||
connector_response,
|
||||
})
|
||||
}
|
||||
|
||||
pub fn handle_unified_connector_service_response_for_payment_capture(
|
||||
@ -791,11 +784,15 @@ pub fn handle_unified_connector_service_response_for_payment_capture(
|
||||
let router_data_response =
|
||||
Result::<(PaymentsResponseData, AttemptStatus), ErrorResponse>::foreign_try_from(response)?;
|
||||
|
||||
Ok((router_data_response, status_code))
|
||||
Ok(UcsResponseData {
|
||||
router_data_response,
|
||||
status_code,
|
||||
connector_customer_id: None,
|
||||
connector_response: None,
|
||||
})
|
||||
}
|
||||
|
||||
pub fn handle_unified_connector_service_response_for_payment_register<F, Req>(
|
||||
router_data: &mut RouterData<F, Req, PaymentsResponseData>,
|
||||
pub fn handle_unified_connector_service_response_for_payment_register(
|
||||
response: payments_grpc::PaymentServiceRegisterResponse,
|
||||
) -> UnifiedConnectorServiceResult {
|
||||
let status_code = transformers::convert_connector_service_status_code(response.status_code)?;
|
||||
@ -805,14 +802,18 @@ pub fn handle_unified_connector_service_response_for_payment_register<F, Req>(
|
||||
response.clone(),
|
||||
)?;
|
||||
|
||||
// Populate connector_customer_id from UCS state
|
||||
populate_connector_customer_id_from_ucs_state(router_data, response.state.as_ref());
|
||||
let connector_customer_id =
|
||||
extract_connector_customer_id_from_ucs_state(response.state.as_ref());
|
||||
|
||||
Ok((router_data_response, status_code))
|
||||
Ok(UcsResponseData {
|
||||
router_data_response,
|
||||
status_code,
|
||||
connector_customer_id,
|
||||
connector_response: None, // Register doesn't need connector_response
|
||||
})
|
||||
}
|
||||
|
||||
pub fn handle_unified_connector_service_response_for_payment_repeat<F, Req>(
|
||||
router_data: &mut RouterData<F, Req, PaymentsResponseData>,
|
||||
pub fn handle_unified_connector_service_response_for_payment_repeat(
|
||||
response: payments_grpc::PaymentServiceRepeatEverythingResponse,
|
||||
) -> UnifiedConnectorServiceResult {
|
||||
let status_code = transformers::convert_connector_service_status_code(response.status_code)?;
|
||||
@ -822,45 +823,46 @@ pub fn handle_unified_connector_service_response_for_payment_repeat<F, Req>(
|
||||
response.clone(),
|
||||
)?;
|
||||
|
||||
// Populate connector_customer_id from UCS state
|
||||
populate_connector_customer_id_from_ucs_state(router_data, response.state.as_ref());
|
||||
let connector_customer_id =
|
||||
extract_connector_customer_id_from_ucs_state(response.state.as_ref());
|
||||
let connector_response =
|
||||
extract_connector_response_from_ucs(response.connector_response.as_ref());
|
||||
|
||||
// Populate connector_response from UCS response (log errors, don't fail)
|
||||
populate_connector_response_from_ucs(router_data, response.connector_response.as_ref())
|
||||
.inspect_err(|err| {
|
||||
router_env::logger::warn!("Failed to populate connector_response from UCS: {:?}", err);
|
||||
})
|
||||
.ok();
|
||||
|
||||
Ok((router_data_response, status_code))
|
||||
Ok(UcsResponseData {
|
||||
router_data_response,
|
||||
status_code,
|
||||
connector_customer_id,
|
||||
connector_response,
|
||||
})
|
||||
}
|
||||
|
||||
/// Extracts and populates connector_customer_id from UCS state into router_data
|
||||
pub fn populate_connector_customer_id_from_ucs_state<F, Req, Resp>(
|
||||
router_data: &mut RouterData<F, Req, Resp>,
|
||||
/// Extracts connector_customer_id from UCS state
|
||||
pub fn extract_connector_customer_id_from_ucs_state(
|
||||
ucs_state: Option<&payments_grpc::ConnectorState>,
|
||||
) {
|
||||
ucs_state.map(|state| {
|
||||
) -> Option<String> {
|
||||
ucs_state.and_then(|state| {
|
||||
state
|
||||
.connector_customer_id
|
||||
.as_ref()
|
||||
.map(|id| router_data.connector_customer = Some(id.to_string()));
|
||||
});
|
||||
.map(|id| id.to_string())
|
||||
})
|
||||
}
|
||||
|
||||
/// Extracts and populates connector_response from UCS response into router_data
|
||||
pub fn populate_connector_response_from_ucs<F, Req, Resp>(
|
||||
router_data: &mut RouterData<F, Req, Resp>,
|
||||
/// Extracts connector_response from UCS response
|
||||
pub fn extract_connector_response_from_ucs(
|
||||
connector_response: Option<&payments_grpc::ConnectorResponseData>,
|
||||
) -> RouterResult<()> {
|
||||
router_data.connector_response = connector_response
|
||||
.map(|data| {
|
||||
<hyperswitch_domain_models::router_data::ConnectorResponseData as hyperswitch_interfaces::helpers::ForeignTryFrom<payments_grpc::ConnectorResponseData>>::foreign_try_from(data.clone())
|
||||
})
|
||||
.transpose()
|
||||
.change_context(errors::ApiErrorResponse::InternalServerError)
|
||||
.attach_printable("Failed to deserialize connector_response from UCS")?;
|
||||
Ok(())
|
||||
) -> Option<hyperswitch_domain_models::router_data::ConnectorResponseData> {
|
||||
connector_response.and_then(|data| {
|
||||
<hyperswitch_domain_models::router_data::ConnectorResponseData as hyperswitch_interfaces::helpers::ForeignTryFrom<payments_grpc::ConnectorResponseData>>::foreign_try_from(data.clone())
|
||||
.map_err(|e| {
|
||||
logger::warn!(
|
||||
error=?e,
|
||||
"Failed to deserialize connector_response from UCS"
|
||||
);
|
||||
e
|
||||
})
|
||||
.ok()
|
||||
})
|
||||
}
|
||||
|
||||
pub fn handle_unified_connector_service_response_for_payment_cancel(
|
||||
@ -871,7 +873,12 @@ pub fn handle_unified_connector_service_response_for_payment_cancel(
|
||||
let router_data_response =
|
||||
Result::<(PaymentsResponseData, AttemptStatus), ErrorResponse>::foreign_try_from(response)?;
|
||||
|
||||
Ok((router_data_response, status_code))
|
||||
Ok(UcsResponseData {
|
||||
router_data_response,
|
||||
status_code,
|
||||
connector_customer_id: None,
|
||||
connector_response: None,
|
||||
})
|
||||
}
|
||||
|
||||
pub fn build_webhook_secrets_from_merchant_connector_account(
|
||||
|
||||
@ -721,6 +721,15 @@ pub struct PspTokenResult {
|
||||
pub token: Result<String, ErrorResponse>,
|
||||
}
|
||||
|
||||
/// Data extracted from UCS response
|
||||
pub struct UcsResponseData {
|
||||
pub router_data_response:
|
||||
Result<(PaymentsResponseData, common_enums::AttemptStatus), ErrorResponse>,
|
||||
pub status_code: u16,
|
||||
pub connector_customer_id: Option<String>,
|
||||
pub connector_response: Option<ConnectorResponseData>,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Copy)]
|
||||
pub enum Redirection {
|
||||
Redirect,
|
||||
|
||||
Reference in New Issue
Block a user