fix(connector): Add network error message support for payment connectors (#7760)

Co-authored-by: Chikke Srujan <chikke.srujan@Chikke-Srujan-N7WRTY72X7.local>
Co-authored-by: hyperswitch-bot[bot] <148525504+hyperswitch-bot[bot]@users.noreply.github.com>
This commit is contained in:
chikke srujan
2025-04-11 15:47:13 +05:30
committed by GitHub
parent 989b2c34e1
commit b83e044b7d
8 changed files with 162 additions and 58 deletions

View File

@ -1598,6 +1598,7 @@ fn get_error_response_if_failure(
if utils::is_payment_failure(status) { if utils::is_payment_failure(status) {
Some(get_error_response( Some(get_error_response(
&info_response.error_information, &info_response.error_information,
&info_response.processor_information,
&info_response.risk_information, &info_response.risk_information,
Some(status), Some(status),
http_code, http_code,
@ -1923,6 +1924,7 @@ impl<F>
Ok(Self { Ok(Self {
response: Err(get_error_response( response: Err(get_error_response(
&item.response.error_information, &item.response.error_information,
&item.response.processor_information,
&risk_info, &risk_info,
Some(status), Some(status),
item.http_code, item.http_code,
@ -2140,6 +2142,7 @@ impl TryFrom<RefundsResponseRouterData<Execute, BankOfAmericaRefundResponse>>
Err(get_error_response( Err(get_error_response(
&item.response.error_information, &item.response.error_information,
&None, &None,
&None,
None, None,
item.http_code, item.http_code,
item.response.id, item.response.id,
@ -2227,6 +2230,7 @@ impl TryFrom<RefundsResponseRouterData<RSync, BankOfAmericaRsyncResponse>>
details: None, details: None,
}), }),
&None, &None,
&None,
None, None,
item.http_code, item.http_code,
item.response.id.clone(), item.response.id.clone(),
@ -2235,6 +2239,7 @@ impl TryFrom<RefundsResponseRouterData<RSync, BankOfAmericaRsyncResponse>>
Err(get_error_response( Err(get_error_response(
&item.response.error_information, &item.response.error_information,
&None, &None,
&None,
None, None,
item.http_code, item.http_code,
item.response.id.clone(), item.response.id.clone(),
@ -2323,6 +2328,7 @@ pub struct AuthenticationErrorInformation {
fn get_error_response( fn get_error_response(
error_data: &Option<BankOfAmericaErrorInformation>, error_data: &Option<BankOfAmericaErrorInformation>,
processor_information: &Option<ClientProcessorInformation>,
risk_information: &Option<ClientRiskInformation>, risk_information: &Option<ClientRiskInformation>,
attempt_status: Option<enums::AttemptStatus>, attempt_status: Option<enums::AttemptStatus>,
status_code: u16, status_code: u16,
@ -2354,6 +2360,14 @@ fn get_error_response(
.join(", ") .join(", ")
}) })
}); });
let network_decline_code = processor_information
.as_ref()
.and_then(|info| info.response_code.clone());
let network_advice_code = processor_information.as_ref().and_then(|info| {
info.merchant_advice
.as_ref()
.and_then(|merchant_advice| merchant_advice.code_raw.clone())
});
let reason = get_error_reason( let reason = get_error_reason(
error_data error_data
@ -2377,8 +2391,8 @@ fn get_error_response(
status_code, status_code,
attempt_status, attempt_status,
connector_transaction_id: Some(transaction_id.clone()), connector_transaction_id: Some(transaction_id.clone()),
network_advice_code: None, network_advice_code,
network_decline_code: None, network_decline_code,
network_error_message: None, network_error_message: None,
} }
} }

View File

@ -2629,6 +2629,15 @@ pub struct ClientProcessorInformation {
network_transaction_id: Option<String>, network_transaction_id: Option<String>,
avs: Option<Avs>, avs: Option<Avs>,
card_verification: Option<CardVerification>, card_verification: Option<CardVerification>,
merchant_advice: Option<MerchantAdvice>,
response_code: Option<String>,
}
#[derive(Debug, Clone, Deserialize, Serialize)]
#[serde(rename_all = "camelCase")]
pub struct MerchantAdvice {
code: Option<String>,
code_raw: Option<String>,
} }
#[derive(Debug, Clone, Deserialize, Serialize)] #[derive(Debug, Clone, Deserialize, Serialize)]
@ -2675,6 +2684,7 @@ fn get_error_response_if_failure(
if utils::is_payment_failure(status) { if utils::is_payment_failure(status) {
Some(get_error_response( Some(get_error_response(
&info_response.error_information, &info_response.error_information,
&info_response.processor_information,
&info_response.risk_information, &info_response.risk_information,
Some(status), Some(status),
http_code, http_code,
@ -3178,6 +3188,7 @@ impl<F>
if utils::is_payment_failure(status) { if utils::is_payment_failure(status) {
let response = Err(get_error_response( let response = Err(get_error_response(
&info_response.error_information, &info_response.error_information,
&None,
&risk_info, &risk_info,
Some(status), Some(status),
item.http_code, item.http_code,
@ -3543,6 +3554,7 @@ impl<F, T>
pub struct CybersourceTransactionResponse { pub struct CybersourceTransactionResponse {
id: String, id: String,
application_information: ApplicationInformation, application_information: ApplicationInformation,
processor_information: Option<ClientProcessorInformation>,
client_reference_information: Option<ClientReferenceInformation>, client_reference_information: Option<ClientReferenceInformation>,
error_information: Option<CybersourceErrorInformation>, error_information: Option<CybersourceErrorInformation>,
} }
@ -3583,6 +3595,7 @@ impl<F>
Ok(Self { Ok(Self {
response: Err(get_error_response( response: Err(get_error_response(
&item.response.error_information, &item.response.error_information,
&item.response.processor_information,
&risk_info, &risk_info,
Some(status), Some(status),
item.http_code, item.http_code,
@ -3701,6 +3714,7 @@ impl TryFrom<RefundsResponseRouterData<Execute, CybersourceRefundResponse>>
Err(get_error_response( Err(get_error_response(
&item.response.error_information, &item.response.error_information,
&None, &None,
&None,
None, None,
item.http_code, item.http_code,
item.response.id.clone(), item.response.id.clone(),
@ -3756,6 +3770,7 @@ impl TryFrom<RefundsResponseRouterData<RSync, CybersourceRsyncResponse>>
details: None, details: None,
}), }),
&None, &None,
&None,
None, None,
item.http_code, item.http_code,
item.response.id.clone(), item.response.id.clone(),
@ -3764,6 +3779,7 @@ impl TryFrom<RefundsResponseRouterData<RSync, CybersourceRsyncResponse>>
Err(get_error_response( Err(get_error_response(
&item.response.error_information, &item.response.error_information,
&None, &None,
&None,
None, None,
item.http_code, item.http_code,
item.response.id.clone(), item.response.id.clone(),
@ -4097,6 +4113,7 @@ pub struct AuthenticationErrorInformation {
pub fn get_error_response( pub fn get_error_response(
error_data: &Option<CybersourceErrorInformation>, error_data: &Option<CybersourceErrorInformation>,
processor_information: &Option<ClientProcessorInformation>,
risk_information: &Option<ClientRiskInformation>, risk_information: &Option<ClientRiskInformation>,
attempt_status: Option<enums::AttemptStatus>, attempt_status: Option<enums::AttemptStatus>,
status_code: u16, status_code: u16,
@ -4128,6 +4145,14 @@ pub fn get_error_response(
.join(", ") .join(", ")
}) })
}); });
let network_decline_code = processor_information
.as_ref()
.and_then(|info| info.response_code.clone());
let network_advice_code = processor_information.as_ref().and_then(|info| {
info.merchant_advice
.as_ref()
.and_then(|merchant_advice| merchant_advice.code_raw.clone())
});
let reason = get_error_reason( let reason = get_error_reason(
error_data error_data
@ -4151,8 +4176,8 @@ pub fn get_error_response(
status_code, status_code,
attempt_status, attempt_status,
connector_transaction_id: Some(transaction_id), connector_transaction_id: Some(transaction_id),
network_advice_code: None, network_advice_code,
network_decline_code: None, network_decline_code,
network_error_message: None, network_error_message: None,
} }
} }

View File

@ -134,6 +134,8 @@ pub struct PaymentMethod {
/// Result message from the payment method provider corresponding to the result code. /// Result message from the payment method provider corresponding to the result code.
pub message: Option<String>, pub message: Option<String>,
/// Result code from the payment method provider. /// Result code from the payment method provider.
/// If a card authorization declines, the payment_method result and message include more detail from the Issuer on why it was declined.
/// For example, 51 - INSUFFICIENT FUNDS. This is generated by the issuing bank, who will provide decline codes in the response back to the authorization platform.
pub result: Option<String>, pub result: Option<String>,
} }

View File

@ -19,7 +19,10 @@ use hyperswitch_domain_models::{
PaymentsSyncRouterData, RefreshTokenRouterData, RefundExecuteRouterData, RefundsRouterData, PaymentsSyncRouterData, RefreshTokenRouterData, RefundExecuteRouterData, RefundsRouterData,
}, },
}; };
use hyperswitch_interfaces::{consts::NO_ERROR_MESSAGE, errors}; use hyperswitch_interfaces::{
consts::{self, NO_ERROR_MESSAGE},
errors,
};
use masking::{ExposeInterface, PeekInterface, Secret}; use masking::{ExposeInterface, PeekInterface, Secret};
use rand::distributions::DistString; use rand::distributions::DistString;
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
@ -279,6 +282,7 @@ fn get_payment_response(
status: common_enums::AttemptStatus, status: common_enums::AttemptStatus,
response: GlobalpayPaymentsResponse, response: GlobalpayPaymentsResponse,
redirection_data: Option<RedirectForm>, redirection_data: Option<RedirectForm>,
status_code: u16,
) -> Result<PaymentsResponseData, Box<ErrorResponse>> { ) -> Result<PaymentsResponseData, Box<ErrorResponse>> {
let mandate_reference = response.payment_method.as_ref().and_then(|pm| { let mandate_reference = response.payment_method.as_ref().and_then(|pm| {
pm.card pm.card
@ -295,12 +299,33 @@ fn get_payment_response(
common_enums::AttemptStatus::Failure => Err(Box::new(ErrorResponse { common_enums::AttemptStatus::Failure => Err(Box::new(ErrorResponse {
message: response message: response
.payment_method .payment_method
.and_then(|pm| pm.message) .as_ref()
.and_then(|payment_method| payment_method.message.clone())
.unwrap_or_else(|| NO_ERROR_MESSAGE.to_string()), .unwrap_or_else(|| NO_ERROR_MESSAGE.to_string()),
..Default::default() code: response
.payment_method
.as_ref()
.and_then(|payment_method| payment_method.result.clone())
.unwrap_or_else(|| consts::NO_ERROR_CODE.to_string()),
reason: response
.payment_method
.as_ref()
.and_then(|payment_method| payment_method.message.clone()),
status_code,
attempt_status: Some(status),
connector_transaction_id: Some(response.id),
network_decline_code: response
.payment_method
.as_ref()
.and_then(|payment_method| payment_method.result.clone()),
network_advice_code: None,
network_error_message: response
.payment_method
.as_ref()
.and_then(|payment_method| payment_method.message.clone()),
})), })),
_ => Ok(PaymentsResponseData::TransactionResponse { _ => Ok(PaymentsResponseData::TransactionResponse {
resource_id: ResponseId::ConnectorTransactionId(response.id), resource_id: ResponseId::ConnectorTransactionId(response.id.clone()),
redirection_data: Box::new(redirection_data), redirection_data: Box::new(redirection_data),
mandate_reference: Box::new(mandate_reference), mandate_reference: Box::new(mandate_reference),
connector_metadata: None, connector_metadata: None,
@ -336,9 +361,10 @@ impl<F, T> TryFrom<ResponseRouterData<F, GlobalpayPaymentsResponse, T, PaymentsR
}) })
.transpose()?; .transpose()?;
let redirection_data = redirect_url.map(|url| RedirectForm::from((url, Method::Get))); let redirection_data = redirect_url.map(|url| RedirectForm::from((url, Method::Get)));
let status_code = item.http_code;
Ok(Self { Ok(Self {
status, status,
response: get_payment_response(status, item.response, redirection_data) response: get_payment_response(status, item.response, redirection_data, status_code)
.map_err(|err| *err), .map_err(|err| *err),
..item.data ..item.data
}) })

View File

@ -65,11 +65,18 @@ pub struct FraudHighRiskResponse {
#[serde(rename_all = "camelCase")] #[serde(rename_all = "camelCase")]
pub struct RefusedResponse { pub struct RefusedResponse {
pub refusal_description: String, pub refusal_description: String,
// Access Worldpay returns a raw response code in the refusalCode field (if enabled) containing the unmodified response code received either directly from the card scheme for Worldpay-acquired transactions, or from third party acquirers.
pub refusal_code: String, pub refusal_code: String,
pub risk_factors: Option<Vec<RiskFactorsInner>>, pub risk_factors: Option<Vec<RiskFactorsInner>>,
pub fraud: Option<Fraud>, pub fraud: Option<Fraud>,
#[serde(rename = "threeDS")] #[serde(rename = "threeDS")]
pub three_ds: Option<ThreeDsResponse>, pub three_ds: Option<ThreeDsResponse>,
pub advice: Option<Advice>,
}
#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
pub struct Advice {
pub code: Option<String>,
} }
#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)] #[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]

View File

@ -748,7 +748,13 @@ impl<F, T>
None, None,
None, None,
None, None,
Some((res.refusal_code.clone(), res.refusal_description.clone())), Some((
res.refusal_code.clone(),
res.refusal_description.clone(),
res.advice
.as_ref()
.and_then(|advice_code| advice_code.code.clone()),
)),
), ),
WorldpayPaymentResponseFields::FraudHighRisk(_) => (None, None, None, None, None), WorldpayPaymentResponseFields::FraudHighRisk(_) => (None, None, None, None, None),
}) })
@ -790,16 +796,18 @@ impl<F, T>
network_decline_code: None, network_decline_code: None,
network_error_message: None, network_error_message: None,
}), }),
(_, Some((code, message))) => Err(ErrorResponse { (_, Some((code, message, advice_code))) => Err(ErrorResponse {
code, code: code.clone(),
message: message.clone(), message: message.clone(),
reason: Some(message), reason: Some(message.clone()),
status_code: router_data.http_code, status_code: router_data.http_code,
attempt_status: Some(status), attempt_status: Some(status),
connector_transaction_id: optional_correlation_id, connector_transaction_id: optional_correlation_id,
network_advice_code: None, network_advice_code: advice_code,
network_decline_code: None, // Access Worldpay returns a raw response code in the refusalCode field (if enabled) containing the unmodified response code received either directly from the card scheme for Worldpay-acquired transactions, or from third party acquirers.
network_error_message: None, // You can use raw response codes to inform your retry logic. A rawCode is only returned if specifically requested.
network_decline_code: Some(code),
network_error_message: Some(message),
}), }),
}; };
Ok(Self { Ok(Self {

View File

@ -128,9 +128,9 @@ impl ConnectorCommon for Stripe {
reason: response.error.message, reason: response.error.message,
attempt_status: None, attempt_status: None,
connector_transaction_id: response.error.payment_intent.map(|pi| pi.id), connector_transaction_id: response.error.payment_intent.map(|pi| pi.id),
network_advice_code: None, network_advice_code: response.error.network_advice_code,
network_decline_code: None, network_decline_code: response.error.network_decline_code,
network_error_message: None, network_error_message: response.error.decline_code.or(response.error.advice_code),
}) })
} }
} }
@ -324,6 +324,7 @@ impl
response response
.error .error
.decline_code .decline_code
.clone()
.map(|decline_code| { .map(|decline_code| {
format!("message - {}, decline_code - {}", message, decline_code) format!("message - {}, decline_code - {}", message, decline_code)
}) })
@ -331,9 +332,9 @@ impl
}), }),
attempt_status: None, attempt_status: None,
connector_transaction_id: response.error.payment_intent.map(|pi| pi.id), connector_transaction_id: response.error.payment_intent.map(|pi| pi.id),
network_advice_code: None, network_advice_code: response.error.network_advice_code,
network_decline_code: None, network_decline_code: response.error.network_decline_code,
network_error_message: None, network_error_message: response.error.decline_code.or(response.error.advice_code),
}) })
} }
} }
@ -455,6 +456,7 @@ impl
response response
.error .error
.decline_code .decline_code
.clone()
.map(|decline_code| { .map(|decline_code| {
format!("message - {}, decline_code - {}", message, decline_code) format!("message - {}, decline_code - {}", message, decline_code)
}) })
@ -462,9 +464,9 @@ impl
}), }),
attempt_status: None, attempt_status: None,
connector_transaction_id: response.error.payment_intent.map(|pi| pi.id), connector_transaction_id: response.error.payment_intent.map(|pi| pi.id),
network_advice_code: None, network_advice_code: response.error.network_advice_code,
network_decline_code: None, network_decline_code: response.error.network_decline_code,
network_error_message: None, network_error_message: response.error.decline_code.or(response.error.advice_code),
}) })
} }
} }
@ -611,6 +613,7 @@ impl
response response
.error .error
.decline_code .decline_code
.clone()
.map(|decline_code| { .map(|decline_code| {
format!("message - {}, decline_code - {}", message, decline_code) format!("message - {}, decline_code - {}", message, decline_code)
}) })
@ -618,9 +621,9 @@ impl
}), }),
attempt_status: None, attempt_status: None,
connector_transaction_id: response.error.payment_intent.map(|pi| pi.id), connector_transaction_id: response.error.payment_intent.map(|pi| pi.id),
network_advice_code: None, network_advice_code: response.error.network_advice_code,
network_decline_code: None, network_decline_code: response.error.network_decline_code,
network_error_message: None, network_error_message: response.error.decline_code.or(response.error.advice_code),
}) })
} }
} }
@ -784,6 +787,7 @@ impl
response response
.error .error
.decline_code .decline_code
.clone()
.map(|decline_code| { .map(|decline_code| {
format!("message - {}, decline_code - {}", message, decline_code) format!("message - {}, decline_code - {}", message, decline_code)
}) })
@ -791,9 +795,9 @@ impl
}), }),
attempt_status: None, attempt_status: None,
connector_transaction_id: response.error.payment_intent.map(|pi| pi.id), connector_transaction_id: response.error.payment_intent.map(|pi| pi.id),
network_advice_code: None, network_advice_code: response.error.network_advice_code,
network_decline_code: None, network_decline_code: response.error.network_decline_code,
network_error_message: None, network_error_message: response.error.decline_code.or(response.error.advice_code),
}) })
} }
} }
@ -952,6 +956,7 @@ impl
response response
.error .error
.decline_code .decline_code
.clone()
.map(|decline_code| { .map(|decline_code| {
format!("message - {}, decline_code - {}", message, decline_code) format!("message - {}, decline_code - {}", message, decline_code)
}) })
@ -959,9 +964,9 @@ impl
}), }),
attempt_status: None, attempt_status: None,
connector_transaction_id: response.error.payment_intent.map(|pi| pi.id), connector_transaction_id: response.error.payment_intent.map(|pi| pi.id),
network_advice_code: None, network_advice_code: response.error.network_advice_code,
network_decline_code: None, network_decline_code: response.error.network_decline_code,
network_error_message: None, network_error_message: response.error.decline_code.or(response.error.advice_code),
}) })
} }
} }
@ -1082,6 +1087,7 @@ impl
response response
.error .error
.decline_code .decline_code
.clone()
.map(|decline_code| { .map(|decline_code| {
format!("message - {}, decline_code - {}", message, decline_code) format!("message - {}, decline_code - {}", message, decline_code)
}) })
@ -1089,9 +1095,9 @@ impl
}), }),
attempt_status: None, attempt_status: None,
connector_transaction_id: response.error.payment_intent.map(|pi| pi.id), connector_transaction_id: response.error.payment_intent.map(|pi| pi.id),
network_advice_code: None, network_advice_code: response.error.network_advice_code,
network_decline_code: None, network_decline_code: response.error.network_decline_code,
network_error_message: None, network_error_message: response.error.decline_code.or(response.error.advice_code),
}) })
} }
} }
@ -1245,6 +1251,7 @@ impl
response response
.error .error
.decline_code .decline_code
.clone()
.map(|decline_code| { .map(|decline_code| {
format!("message - {}, decline_code - {}", message, decline_code) format!("message - {}, decline_code - {}", message, decline_code)
}) })
@ -1252,9 +1259,9 @@ impl
}), }),
attempt_status: None, attempt_status: None,
connector_transaction_id: response.error.payment_intent.map(|pi| pi.id), connector_transaction_id: response.error.payment_intent.map(|pi| pi.id),
network_advice_code: None, network_advice_code: response.error.network_advice_code,
network_decline_code: None, network_decline_code: response.error.network_decline_code,
network_error_message: None, network_error_message: response.error.decline_code.or(response.error.advice_code),
}) })
} }
} }
@ -1417,6 +1424,7 @@ impl services::ConnectorIntegration<api::Execute, types::RefundsData, types::Ref
response response
.error .error
.decline_code .decline_code
.clone()
.map(|decline_code| { .map(|decline_code| {
format!("message - {}, decline_code - {}", message, decline_code) format!("message - {}, decline_code - {}", message, decline_code)
}) })
@ -1424,9 +1432,9 @@ impl services::ConnectorIntegration<api::Execute, types::RefundsData, types::Ref
}), }),
attempt_status: None, attempt_status: None,
connector_transaction_id: response.error.payment_intent.map(|pi| pi.id), connector_transaction_id: response.error.payment_intent.map(|pi| pi.id),
network_advice_code: None, network_advice_code: response.error.network_advice_code,
network_decline_code: None, network_decline_code: response.error.network_decline_code,
network_error_message: None, network_error_message: response.error.decline_code.or(response.error.advice_code),
}) })
} }
} }
@ -1554,6 +1562,7 @@ impl services::ConnectorIntegration<api::RSync, types::RefundsData, types::Refun
response response
.error .error
.decline_code .decline_code
.clone()
.map(|decline_code| { .map(|decline_code| {
format!("message - {}, decline_code - {}", message, decline_code) format!("message - {}, decline_code - {}", message, decline_code)
}) })
@ -1561,9 +1570,9 @@ impl services::ConnectorIntegration<api::RSync, types::RefundsData, types::Refun
}), }),
attempt_status: None, attempt_status: None,
connector_transaction_id: response.error.payment_intent.map(|pi| pi.id), connector_transaction_id: response.error.payment_intent.map(|pi| pi.id),
network_advice_code: None, network_advice_code: response.error.network_advice_code,
network_decline_code: None, network_decline_code: response.error.network_decline_code,
network_error_message: None, network_error_message: response.error.decline_code.or(response.error.advice_code),
}) })
} }
} }
@ -1711,6 +1720,7 @@ impl
response response
.error .error
.decline_code .decline_code
.clone()
.map(|decline_code| { .map(|decline_code| {
format!("message - {}, decline_code - {}", message, decline_code) format!("message - {}, decline_code - {}", message, decline_code)
}) })
@ -1718,9 +1728,9 @@ impl
}), }),
attempt_status: None, attempt_status: None,
connector_transaction_id: response.error.payment_intent.map(|pi| pi.id), connector_transaction_id: response.error.payment_intent.map(|pi| pi.id),
network_advice_code: None, network_advice_code: response.error.network_advice_code,
network_decline_code: None, network_decline_code: response.error.network_decline_code,
network_error_message: None, network_error_message: response.error.decline_code.or(response.error.advice_code),
}) })
} }
} }
@ -1827,6 +1837,7 @@ impl
response response
.error .error
.decline_code .decline_code
.clone()
.map(|decline_code| { .map(|decline_code| {
format!("message - {}, decline_code - {}", message, decline_code) format!("message - {}, decline_code - {}", message, decline_code)
}) })
@ -1834,9 +1845,9 @@ impl
}), }),
attempt_status: None, attempt_status: None,
connector_transaction_id: response.error.payment_intent.map(|pi| pi.id), connector_transaction_id: response.error.payment_intent.map(|pi| pi.id),
network_advice_code: None, network_advice_code: response.error.network_advice_code,
network_decline_code: None, network_decline_code: response.error.network_decline_code,
network_error_message: None, network_error_message: response.error.decline_code.or(response.error.advice_code),
}) })
} }
} }
@ -1961,6 +1972,7 @@ impl
response response
.error .error
.decline_code .decline_code
.clone()
.map(|decline_code| { .map(|decline_code| {
format!("message - {}, decline_code - {}", message, decline_code) format!("message - {}, decline_code - {}", message, decline_code)
}) })
@ -1968,9 +1980,9 @@ impl
}), }),
attempt_status: None, attempt_status: None,
connector_transaction_id: response.error.payment_intent.map(|pi| pi.id), connector_transaction_id: response.error.payment_intent.map(|pi| pi.id),
network_advice_code: None, network_advice_code: response.error.network_advice_code,
network_decline_code: None, network_decline_code: response.error.network_decline_code,
network_error_message: None, network_error_message: response.error.decline_code.or(response.error.advice_code),
}) })
} }
} }

View File

@ -3305,6 +3305,9 @@ pub struct ErrorDetails {
pub param: Option<String>, pub param: Option<String>,
pub decline_code: Option<String>, pub decline_code: Option<String>,
pub payment_intent: Option<PaymentIntentErrorResponse>, pub payment_intent: Option<PaymentIntentErrorResponse>,
pub network_advice_code: Option<String>,
pub network_decline_code: Option<String>,
pub advice_code: Option<String>,
} }
#[derive(Clone, Debug, Default, Eq, PartialEq, Deserialize, Serialize)] #[derive(Clone, Debug, Default, Eq, PartialEq, Deserialize, Serialize)]
@ -3719,6 +3722,7 @@ pub struct WebhookEventObjectData {
pub evidence_details: Option<EvidenceDetails>, pub evidence_details: Option<EvidenceDetails>,
pub status: Option<WebhookEventStatus>, pub status: Option<WebhookEventStatus>,
pub metadata: Option<StripeMetadata>, pub metadata: Option<StripeMetadata>,
pub last_payment_error: Option<ErrorDetails>,
} }
#[derive(Debug, Clone, Serialize, Deserialize, strum::Display)] #[derive(Debug, Clone, Serialize, Deserialize, strum::Display)]
@ -4178,9 +4182,15 @@ impl ForeignTryFrom<(&Option<ErrorDetails>, u16, String)> for types::PaymentsRes
status_code: http_code, status_code: http_code,
attempt_status: None, attempt_status: None,
connector_transaction_id: Some(response_id), connector_transaction_id: Some(response_id),
network_advice_code: None, network_advice_code: response
network_decline_code: None, .as_ref()
network_error_message: None, .and_then(|res| res.network_advice_code.clone()),
network_decline_code: response
.as_ref()
.and_then(|res| res.network_decline_code.clone()),
network_error_message: response
.as_ref()
.and_then(|res| res.decline_code.clone().or(res.advice_code.clone())),
}) })
} }
} }