fix(connector): [Payme] populate error message in case of 2xx payment failures (#2037)

This commit is contained in:
Arjun Karthik
2023-08-28 22:34:05 +05:30
committed by GitHub
parent f04bee2611
commit aeebc5b525

View File

@ -9,6 +9,7 @@ use crate::{
self, missing_field_err, AddressDetailsData, CardData, PaymentsAuthorizeRequestData,
PaymentsPreProcessingData, PaymentsSyncRequestData, RouterData,
},
consts,
core::errors,
types::{self, api, storage::enums, MandateReference},
};
@ -120,30 +121,61 @@ impl<F, T>
fn try_from(
item: types::ResponseRouterData<F, PaymePaySaleResponse, T, types::PaymentsResponseData>,
) -> Result<Self, Self::Error> {
let response = if item.response.sale_status == SaleStatus::Failed {
// To populate error message in case of failure
Err(types::ErrorResponse::from((&item.response, item.http_code)))
} else {
Ok(types::PaymentsResponseData::try_from(&item.response)?)
};
Ok(Self {
status: enums::AttemptStatus::from(item.response.sale_status),
response: Ok(types::PaymentsResponseData::TransactionResponse {
resource_id: types::ResponseId::ConnectorTransactionId(item.response.payme_sale_id),
redirection_data: None,
mandate_reference: item.response.buyer_key.map(|buyer_key| MandateReference {
connector_mandate_id: Some(buyer_key.expose()),
payment_method_id: None,
}),
connector_metadata: Some(
serde_json::to_value(PaymeMetadata {
payme_transaction_id: item.response.payme_transaction_id,
})
.into_report()
.change_context(errors::ConnectorError::ResponseHandlingFailed)?,
),
network_txn_id: None,
connector_response_reference_id: None,
}),
response,
..item.data
})
}
}
impl From<(&PaymePaySaleResponse, u16)> for types::ErrorResponse {
fn from((pay_sale_response, http_code): (&PaymePaySaleResponse, u16)) -> Self {
let code = pay_sale_response
.status_error_code
.map(|error_code| error_code.to_string())
.unwrap_or(consts::NO_ERROR_CODE.to_string());
Self {
code,
message: pay_sale_response
.status_error_details
.clone()
.unwrap_or(consts::NO_ERROR_MESSAGE.to_string()),
reason: pay_sale_response.status_error_details.to_owned(),
status_code: http_code,
}
}
}
impl TryFrom<&PaymePaySaleResponse> for types::PaymentsResponseData {
type Error = error_stack::Report<errors::ConnectorError>;
fn try_from(value: &PaymePaySaleResponse) -> Result<Self, Self::Error> {
Ok(Self::TransactionResponse {
resource_id: types::ResponseId::ConnectorTransactionId(value.payme_sale_id.clone()),
redirection_data: None,
mandate_reference: value.buyer_key.clone().map(|buyer_key| MandateReference {
connector_mandate_id: Some(buyer_key.expose()),
payment_method_id: None,
}),
connector_metadata: Some(
serde_json::to_value(PaymeMetadata {
payme_transaction_id: value.payme_transaction_id.clone(),
})
.into_report()
.change_context(errors::ConnectorError::ResponseHandlingFailed)?,
),
network_txn_id: None,
connector_response_reference_id: None,
})
}
}
impl<F, T> TryFrom<types::ResponseRouterData<F, SaleQueryResponse, T, types::PaymentsResponseData>>
for types::RouterData<F, T, types::PaymentsResponseData>
{
@ -158,24 +190,54 @@ impl<F, T> TryFrom<types::ResponseRouterData<F, SaleQueryResponse, T, types::Pay
.first()
.cloned()
.ok_or(errors::ConnectorError::ResponseHandlingFailed)?;
let response = if transaction_response.sale_status == SaleStatus::Failed {
// To populate error message in case of failure
Err(types::ErrorResponse::from((
&transaction_response,
item.http_code,
)))
} else {
Ok(types::PaymentsResponseData::from(&transaction_response))
};
Ok(Self {
status: enums::AttemptStatus::from(transaction_response.sale_status),
response: Ok(types::PaymentsResponseData::TransactionResponse {
resource_id: types::ResponseId::ConnectorTransactionId(
transaction_response.sale_payme_id,
),
redirection_data: None,
// mandate reference will be updated with webhooks only. That has been handled with PaymePaySaleResponse struct
mandate_reference: None,
connector_metadata: None,
network_txn_id: None,
connector_response_reference_id: None,
}),
response,
..item.data
})
}
}
impl From<(&SaleQuery, u16)> for types::ErrorResponse {
fn from((sale_query_response, http_code): (&SaleQuery, u16)) -> Self {
Self {
code: sale_query_response
.sale_error_code
.clone()
.unwrap_or(consts::NO_ERROR_CODE.to_string()),
message: sale_query_response
.sale_error_text
.clone()
.unwrap_or(consts::NO_ERROR_MESSAGE.to_string()),
reason: sale_query_response.sale_error_text.clone(),
status_code: http_code,
}
}
}
impl From<&SaleQuery> for types::PaymentsResponseData {
fn from(value: &SaleQuery) -> Self {
Self::TransactionResponse {
resource_id: types::ResponseId::ConnectorTransactionId(value.sale_payme_id.clone()),
redirection_data: None,
// mandate reference will be updated with webhooks only. That has been handled with PaymePaySaleResponse struct
mandate_reference: None,
connector_metadata: None,
network_txn_id: None,
connector_response_reference_id: None,
}
}
}
#[derive(Debug, Serialize)]
#[serde(rename_all = "lowercase")]
pub enum SaleType {
@ -483,7 +545,7 @@ impl TryFrom<&types::PaymentsPreProcessingRouterData> for SaleType {
}
}
#[derive(Clone, Debug, Serialize, Deserialize)]
#[derive(Clone, Debug, Serialize, Deserialize, PartialEq, Eq)]
#[serde(rename_all = "kebab-case")]
pub enum SaleStatus {
Initial,
@ -527,6 +589,8 @@ pub struct SaleQueryResponse {
pub struct SaleQuery {
sale_status: SaleStatus,
sale_payme_id: String,
sale_error_text: Option<String>,
sale_error_code: Option<String>,
}
#[derive(Debug, Serialize, Deserialize)]
@ -535,6 +599,8 @@ pub struct PaymePaySaleResponse {
payme_sale_id: String,
payme_transaction_id: String,
buyer_key: Option<Secret<String>>,
status_error_details: Option<String>,
status_error_code: Option<u32>,
}
#[derive(Serialize, Deserialize)]
@ -673,7 +739,7 @@ pub struct PaymeErrorResponse {
pub status_code: u16,
pub status_error_details: String,
pub status_additional_info: serde_json::Value,
pub status_error_code: u16,
pub status_error_code: u32,
}
#[derive(Debug, Serialize, Deserialize)]
@ -695,6 +761,8 @@ pub struct WebhookEventDataResource {
pub notify_type: NotifyType,
pub payme_sale_id: String,
pub payme_transaction_id: String,
pub status_error_details: Option<String>,
pub status_error_code: Option<u32>,
}
#[derive(Debug, Deserialize)]
@ -715,6 +783,8 @@ impl From<WebhookEventDataResource> for PaymePaySaleResponse {
payme_sale_id: value.payme_sale_id,
payme_transaction_id: value.payme_transaction_id,
buyer_key: value.buyer_key,
status_error_code: value.status_error_code,
status_error_details: value.status_error_details,
}
}
}