Skip to content

Commit 8429e48

Browse files
authored
fix(connector): Handle Mollie failed payments with error details from details object (#10824)
1 parent 3a2dd71 commit 8429e48

File tree

1 file changed

+55
-3
lines changed

1 file changed

+55
-3
lines changed

crates/hyperswitch_connectors/src/connectors/mollie/transformers.rs

Lines changed: 55 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,15 +4,15 @@ use common_utils::{pii::Email, request::Method, types::StringMajorUnit};
44
use error_stack::ResultExt;
55
use hyperswitch_domain_models::{
66
payment_method_data::{BankDebitData, BankRedirectData, PaymentMethodData, WalletData},
7-
router_data::{ConnectorAuthType, PaymentMethodToken, RouterData},
7+
router_data::{ConnectorAuthType, ErrorResponse, PaymentMethodToken, RouterData},
88
router_request_types::ResponseId,
99
router_response_types::{
1010
ConnectorCustomerResponseData, MandateReference, PaymentsResponseData, RedirectForm,
1111
RefundsResponseData,
1212
},
1313
types,
1414
};
15-
use hyperswitch_interfaces::errors;
15+
use hyperswitch_interfaces::{consts, errors};
1616
use masking::{ExposeInterface, Secret};
1717
use serde::{Deserialize, Serialize};
1818
use url::Url;
@@ -563,6 +563,15 @@ pub struct MolliePaymentsResponse {
563563
pub links: Links,
564564
pub mandate_id: Option<Secret<String>>,
565565
pub payment_id: Option<String>,
566+
pub details: Option<MolliePaymentDetails>,
567+
}
568+
569+
/// Details object containing failure information for failed payments
570+
#[derive(Debug, Deserialize, Serialize)]
571+
#[serde(rename_all = "camelCase")]
572+
pub struct MolliePaymentDetails {
573+
pub failure_reason: Option<String>,
574+
pub failure_message: Option<String>,
566575
}
567576

568577
#[derive(Debug, Clone, Default, Serialize, Deserialize, PartialEq)]
@@ -670,6 +679,49 @@ impl<F, T> TryFrom<ResponseRouterData<F, MolliePaymentsResponse, T, PaymentsResp
670679
fn try_from(
671680
item: ResponseRouterData<F, MolliePaymentsResponse, T, PaymentsResponseData>,
672681
) -> Result<Self, Self::Error> {
682+
let status = enums::AttemptStatus::from(item.response.status.clone());
683+
684+
// Handle failed payments: extract error details from the details object
685+
// Mollie returns 2xx but with status "failed" when payment fails after 3DS authentication
686+
if crate::utils::is_payment_failure(status) {
687+
let (failure_reason, failure_message) = item
688+
.response
689+
.details
690+
.as_ref()
691+
.map(|details| {
692+
(
693+
details.failure_reason.clone(),
694+
details.failure_message.clone(),
695+
)
696+
})
697+
.unwrap_or((None, None));
698+
699+
let error_code = failure_reason
700+
.clone()
701+
.unwrap_or_else(|| consts::NO_ERROR_CODE.to_string());
702+
let error_message = failure_message
703+
.clone()
704+
.unwrap_or_else(|| consts::NO_ERROR_MESSAGE.to_string());
705+
706+
return Ok(Self {
707+
status,
708+
response: Err(ErrorResponse {
709+
status_code: item.http_code,
710+
code: error_code,
711+
message: error_message.clone(),
712+
reason: Some(error_message),
713+
attempt_status: None,
714+
connector_transaction_id: Some(item.response.id),
715+
network_advice_code: None,
716+
network_decline_code: None,
717+
network_error_message: None,
718+
connector_metadata: None,
719+
connector_response_reference_id: None,
720+
}),
721+
..item.data
722+
});
723+
}
724+
673725
let url = item
674726
.response
675727
.links
@@ -687,7 +739,7 @@ impl<F, T> TryFrom<ResponseRouterData<F, MolliePaymentsResponse, T, PaymentsResp
687739
connector_mandate_request_reference_id: None,
688740
});
689741
Ok(Self {
690-
status: enums::AttemptStatus::from(item.response.status),
742+
status,
691743
response: Ok(PaymentsResponseData::TransactionResponse {
692744
resource_id: ResponseId::ConnectorTransactionId(
693745
item.response

0 commit comments

Comments
 (0)