Skip to content
Closed
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
50 changes: 41 additions & 9 deletions crates/grpc-server/grpc-server/src/server/payments.rs
Original file line number Diff line number Diff line change
Expand Up @@ -889,14 +889,25 @@ impl PaymentService for Payments {
// Convert proto request to intermediate type
let payload: AuthorizationRequest = proto_payload.clone().into();

let payment_method_data_action = PaymentMethodDataAction::get_payment_method_data_action(proto_payload.payment_method.clone().ok_or(ucs_env::error::GrpcError::from(IntegrationError::MissingRequiredField { field_name: "payment_method", context: domain_types::errors::IntegrationErrorContext::default() }))?)
.map_err(|err| {
tracing::error!("PAYMENT_AUTHORIZE_FLOW: failed to get payment method data action - error: {:?}", err);
ucs_env::error::GrpcError::from(IntegrationError::InvalidDataFormat { field_name: "payment_method", context: domain_types::errors::IntegrationErrorContext::default() })
})?;
// `payment_method` is required for an ordinary authorization, but not for the
// second leg of a redirect-based one: connectors that finalise 3DS through
// Authorize are re-invoked after the ACS posts back to `TermUrl`, and the
// caller no longer holds the raw instrument at that point. That leg is
// identified by `redirection_response`, exactly as the connectors themselves
// identify it (`request.redirect_response.is_some()`), and it is the only case
// in which an absent `payment_method` is accepted.
let payment_method_data_action = match proto_payload.payment_method.clone() {
Some(payment_method) => Some(PaymentMethodDataAction::get_payment_method_data_action(payment_method)
.map_err(|err| {
tracing::error!("PAYMENT_AUTHORIZE_FLOW: failed to get payment method data action - error: {:?}", err);
ucs_env::error::GrpcError::from(IntegrationError::InvalidDataFormat { field_name: "payment_method", context: domain_types::errors::IntegrationErrorContext::default() })
})?),
None if proto_payload.redirection_response.is_some() => None,
None => Err(ucs_env::error::GrpcError::from(IntegrationError::MissingRequiredField { field_name: "payment_method", context: domain_types::errors::IntegrationErrorContext::default() }))?,
};

let authorize_response = match payment_method_data_action {
PaymentMethodDataAction::CardProxy(proxy_card_details) => {
Some(PaymentMethodDataAction::CardProxy(proxy_card_details)) => {
let token_data = proxy_card_details.to_token_data();
let payment_method_data = payment_method_data::PaymentMethodData::Card(payment_method_data::Card::<VaultTokenHolder>::foreign_try_from(proxy_card_details).map_err(|err| {
tracing::error!("PAYMENT_AUTHORIZE_FLOW: failed to get payment method data action - error: {:?}", err);
Expand All @@ -917,7 +928,7 @@ impl PaymentService for Payments {
))
.await?
}
PaymentMethodDataAction::Card(card_details) => {
Some(PaymentMethodDataAction::Card(card_details)) => {
tracing::info!("REGULAR: Processing regular payment authorization (no injector)");
let payment_method_data = payment_method_data::PaymentMethodData::Card(payment_method_data::Card::<DefaultPCIHolder>::foreign_try_from(card_details).map_err(|err| {
tracing::error!("PAYMENT_AUTHORIZE_FLOW: failed to get payment method data action - error: {:?}", err);
Expand All @@ -938,7 +949,7 @@ impl PaymentService for Payments {
))
.await?
}
PaymentMethodDataAction::Default => {
Some(PaymentMethodDataAction::Default) => {
let payment_method_data = payment_method_data::PaymentMethodData::convert_to_domain_model_for_non_card_payment_methods(proto_payload.payment_method.clone().ok_or(ucs_env::error::GrpcError::from(IntegrationError::MissingRequiredField { field_name: "payment_method", context: domain_types::errors::IntegrationErrorContext::default() }))?)
.map_err(|err| {
tracing::error!("Failed to convert payment method data: {:?}", err);
Expand All @@ -959,7 +970,7 @@ impl PaymentService for Payments {
))
.await?
}
PaymentMethodDataAction::CardWithNoCvc(card_details) => {
Some(PaymentMethodDataAction::CardWithNoCvc(card_details)) => {
tracing::info!("REGULAR: Processing payment authorization with CardWithNoCvc");
let payment_method_data = payment_method_data::PaymentMethodData::CardWithNoCvc(
payment_method_data::CardWithNoCvc::foreign_try_from(card_details).map_err(|err| {
Expand All @@ -981,6 +992,27 @@ impl PaymentService for Payments {
))
.await?
}
// Redirect-return leg: no instrument was sent (guarded above by
// `redirection_response` being present). The connector finalises from the
// redirect payload and its own transaction reference; connectors that
// cannot do so reject `NoInstrumentAfterRedirect` rather than mistaking it
// for a payable instrument.
None => {
tracing::info!("REDIRECT_COMPLETION: authorization re-entered after redirect without payment method data");
Box::pin(self.process_authorization_internal::<DefaultPCIHolder>(
&config,
payload,
metadata_payload.connector.clone(),
metadata_payload.connector_config.clone(),
metadata,
&metadata_payload,
&service_name,
&metadata_payload.request_id,
None,
payment_method_data::PaymentMethodData::NoInstrumentAfterRedirect,
))
.await?
}
};

Ok(tonic::Response::new(authorize_response))
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -762,7 +762,8 @@ impl<T: PaymentMethodDataTypes + Debug + Sync + Send + 'static + Serialize>
| PaymentMethodData::OpenBanking(_)
| PaymentMethodData::PaymentMethodToken(_)
| PaymentMethodData::DecryptedWalletTokenDetailsForNetworkTransactionId(_)
| PaymentMethodData::CardDetailsForNetworkTransactionId(_) => {
| PaymentMethodData::CardDetailsForNetworkTransactionId(_)
| PaymentMethodData::NoInstrumentAfterRedirect => {
Err(IntegrationError::NotImplemented(
utils::get_unimplemented_payment_method_error_message("Aci"),
Default::default(),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3905,11 +3905,11 @@ impl<T: PaymentMethodDataTypes + std::fmt::Debug + Sync + Send + 'static + Seria
| PaymentMethodData::CardDetailsForNetworkTransactionId(_)
| PaymentMethodData::DecryptedWalletTokenDetailsForNetworkTransactionId(_)
| PaymentMethodData::CardWithNoCvc(_)
| PaymentMethodData::MobilePayment(_) => Err(IntegrationError::NotImplemented(
("payment method").into(),
Default::default(),
)
.into()),
| PaymentMethodData::MobilePayment(_)
| PaymentMethodData::NoInstrumentAfterRedirect => Err(
IntegrationError::NotImplemented(("payment method").into(), Default::default())
.into(),
),
},
}
}
Expand Down Expand Up @@ -6525,7 +6525,8 @@ impl<T: PaymentMethodDataTypes + std::fmt::Debug + Sync + Send + 'static + Seria
| PaymentMethodData::NetworkToken(_)
| PaymentMethodData::CardWithNoCvc(_)
| PaymentMethodData::MobilePayment(_)
| PaymentMethodData::PaymentMethodToken(_) => Err(
| PaymentMethodData::PaymentMethodToken(_)
| PaymentMethodData::NoInstrumentAfterRedirect => Err(
IntegrationError::NotImplemented(("payment method").into(), Default::default())
.into(),
),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -298,7 +298,8 @@ impl<T: PaymentMethodDataTypes>
| PaymentMethodData::MobilePayment(_)
| PaymentMethodData::OpenBanking(_)
| PaymentMethodData::DecryptedWalletTokenDetailsForNetworkTransactionId(_)
| PaymentMethodData::CardDetailsForNetworkTransactionId(_) => {
| PaymentMethodData::CardDetailsForNetworkTransactionId(_)
| PaymentMethodData::NoInstrumentAfterRedirect => {
return Err(IntegrationError::NotSupported {
message: "Selected payment method".to_string(),
connector: "bambora",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -767,7 +767,8 @@ impl<T: PaymentMethodDataTypes + std::fmt::Debug + Sync + Send + 'static + Seria
| PaymentMethodData::PaymentMethodToken(_)
| PaymentMethodData::NetworkToken(_)
| PaymentMethodData::DecryptedWalletTokenDetailsForNetworkTransactionId(_)
| PaymentMethodData::CardDetailsForNetworkTransactionId(_) => {
| PaymentMethodData::CardDetailsForNetworkTransactionId(_)
| PaymentMethodData::NoInstrumentAfterRedirect => {
Err(IntegrationError::NotImplemented(
domain_types::utils::get_unimplemented_payment_method_error_message(
"Bank of America",
Expand Down Expand Up @@ -2061,7 +2062,8 @@ impl<T: PaymentMethodDataTypes + std::fmt::Debug + Sync + Send + 'static + Seria
| PaymentMethodData::PaymentMethodToken(_)
| PaymentMethodData::NetworkToken(_)
| PaymentMethodData::DecryptedWalletTokenDetailsForNetworkTransactionId(_)
| PaymentMethodData::CardDetailsForNetworkTransactionId(_) => {
| PaymentMethodData::CardDetailsForNetworkTransactionId(_)
| PaymentMethodData::NoInstrumentAfterRedirect => {
Err(IntegrationError::NotImplemented(
utils::get_unimplemented_payment_method_error_message("BankOfAmerica"),
Default::default(),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -157,6 +157,7 @@ fn payment_method_data_label<T: PaymentMethodDataTypes>(
PaymentMethodData::NetworkToken(_) => "network_token",
PaymentMethodData::CardWithNoCvc(_) => "card_with_no_cvc",
PaymentMethodData::MobilePayment(_) => "mobile_payment",
PaymentMethodData::NoInstrumentAfterRedirect => "no_instrument_after_redirect",
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -240,7 +240,8 @@ impl<T: PaymentMethodDataTypes + std::fmt::Debug + Sync + Send + 'static + Seria
| PaymentMethodData::PaymentMethodToken(_)
| PaymentMethodData::NetworkToken(_)
| PaymentMethodData::DecryptedWalletTokenDetailsForNetworkTransactionId(_)
| PaymentMethodData::CardDetailsForNetworkTransactionId(_) => {
| PaymentMethodData::CardDetailsForNetworkTransactionId(_)
| PaymentMethodData::NoInstrumentAfterRedirect => {
Err(IntegrationError::NotImplemented(
utils::get_unimplemented_payment_method_error_message("billwerk"),
Default::default(),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -633,7 +633,8 @@ impl<T: PaymentMethodDataTypes + std::fmt::Debug + Sync + Send + 'static + Seria
| PaymentMethodData::PaymentMethodToken(_)
| PaymentMethodData::NetworkToken(_)
| PaymentMethodData::DecryptedWalletTokenDetailsForNetworkTransactionId(_)
| PaymentMethodData::CardDetailsForNetworkTransactionId(_) => {
| PaymentMethodData::CardDetailsForNetworkTransactionId(_)
| PaymentMethodData::NoInstrumentAfterRedirect => {
Err(error_stack::report!(IntegrationError::NotSupported {
message: utils::get_unimplemented_payment_method_error_message("braintree"),
connector: "Braintree",
Expand Down Expand Up @@ -1647,7 +1648,8 @@ impl<T: PaymentMethodDataTypes + std::fmt::Debug + Sync + Send + 'static + Seria
| PaymentMethodData::PaymentMethodToken(_)
| PaymentMethodData::NetworkToken(_)
| PaymentMethodData::DecryptedWalletTokenDetailsForNetworkTransactionId(_)
| PaymentMethodData::CardDetailsForNetworkTransactionId(_) => {
| PaymentMethodData::CardDetailsForNetworkTransactionId(_)
| PaymentMethodData::NoInstrumentAfterRedirect => {
Err(error_stack::report!(IntegrationError::NotSupported {
message: utils::get_unimplemented_payment_method_error_message("braintree"),
connector: "Braintree",
Expand Down Expand Up @@ -2684,7 +2686,8 @@ fn get_braintree_redirect_form<
| PaymentMethodData::PaymentMethodToken(_)
| PaymentMethodData::NetworkToken(_)
| PaymentMethodData::DecryptedWalletTokenDetailsForNetworkTransactionId(_)
| PaymentMethodData::CardDetailsForNetworkTransactionId(_) => {
| PaymentMethodData::CardDetailsForNetworkTransactionId(_)
| PaymentMethodData::NoInstrumentAfterRedirect => {
return Err(ConnectorError::unexpected_response_error_http_status_unknown().into());
}
},
Expand Down Expand Up @@ -3014,7 +3017,8 @@ impl<T: PaymentMethodDataTypes + std::fmt::Debug + Sync + Send + 'static + Seria
| PaymentMethodData::PaymentMethodToken(_)
| PaymentMethodData::NetworkToken(_)
| PaymentMethodData::DecryptedWalletTokenDetailsForNetworkTransactionId(_)
| PaymentMethodData::CardDetailsForNetworkTransactionId(_) => {
| PaymentMethodData::CardDetailsForNetworkTransactionId(_)
| PaymentMethodData::NoInstrumentAfterRedirect => {
Err(error_stack::report!(IntegrationError::NotSupported {
message: utils::get_unimplemented_payment_method_error_message("braintree"),
connector: "Braintree",
Expand Down Expand Up @@ -3375,7 +3379,8 @@ impl<T: PaymentMethodDataTypes + std::fmt::Debug + Sync + Send + 'static + Seria
| PaymentMethodData::PaymentMethodToken(_)
| PaymentMethodData::NetworkToken(_)
| PaymentMethodData::DecryptedWalletTokenDetailsForNetworkTransactionId(_)
| PaymentMethodData::CardDetailsForNetworkTransactionId(_) => {
| PaymentMethodData::CardDetailsForNetworkTransactionId(_)
| PaymentMethodData::NoInstrumentAfterRedirect => {
Err(error_stack::report!(IntegrationError::NotSupported {
message: utils::get_unimplemented_payment_method_error_message("braintree"),
connector: "Braintree",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -111,7 +111,8 @@ impl<T: PaymentMethodDataTypes + std::fmt::Debug + Sync + Send + 'static + Seria
| PaymentMethodData::PaymentMethodToken(_)
| PaymentMethodData::NetworkToken(_)
| PaymentMethodData::DecryptedWalletTokenDetailsForNetworkTransactionId(_)
| PaymentMethodData::CardDetailsForNetworkTransactionId(_) => {
| PaymentMethodData::CardDetailsForNetworkTransactionId(_)
| PaymentMethodData::NoInstrumentAfterRedirect => {
Err(error_stack::report!(IntegrationError::NotSupported {
message: get_unimplemented_payment_method_error_message("CryptoPay"),
connector: "Cryptopay",
Expand Down
Loading
Loading