mirror of
https://github.com/juspay/hyperswitch.git
synced 2025-10-29 00:49:42 +08:00
fix(connector): [Payme] populate error message in case of 2xx payment failures (#2037)
This commit is contained in:
@ -9,6 +9,7 @@ use crate::{
|
|||||||
self, missing_field_err, AddressDetailsData, CardData, PaymentsAuthorizeRequestData,
|
self, missing_field_err, AddressDetailsData, CardData, PaymentsAuthorizeRequestData,
|
||||||
PaymentsPreProcessingData, PaymentsSyncRequestData, RouterData,
|
PaymentsPreProcessingData, PaymentsSyncRequestData, RouterData,
|
||||||
},
|
},
|
||||||
|
consts,
|
||||||
core::errors,
|
core::errors,
|
||||||
types::{self, api, storage::enums, MandateReference},
|
types::{self, api, storage::enums, MandateReference},
|
||||||
};
|
};
|
||||||
@ -120,30 +121,61 @@ impl<F, T>
|
|||||||
fn try_from(
|
fn try_from(
|
||||||
item: types::ResponseRouterData<F, PaymePaySaleResponse, T, types::PaymentsResponseData>,
|
item: types::ResponseRouterData<F, PaymePaySaleResponse, T, types::PaymentsResponseData>,
|
||||||
) -> Result<Self, Self::Error> {
|
) -> 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 {
|
Ok(Self {
|
||||||
status: enums::AttemptStatus::from(item.response.sale_status),
|
status: enums::AttemptStatus::from(item.response.sale_status),
|
||||||
response: Ok(types::PaymentsResponseData::TransactionResponse {
|
response,
|
||||||
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,
|
|
||||||
}),
|
|
||||||
..item.data
|
..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>>
|
impl<F, T> TryFrom<types::ResponseRouterData<F, SaleQueryResponse, T, types::PaymentsResponseData>>
|
||||||
for types::RouterData<F, 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()
|
.first()
|
||||||
.cloned()
|
.cloned()
|
||||||
.ok_or(errors::ConnectorError::ResponseHandlingFailed)?;
|
.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 {
|
Ok(Self {
|
||||||
status: enums::AttemptStatus::from(transaction_response.sale_status),
|
status: enums::AttemptStatus::from(transaction_response.sale_status),
|
||||||
response: Ok(types::PaymentsResponseData::TransactionResponse {
|
response,
|
||||||
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,
|
|
||||||
}),
|
|
||||||
..item.data
|
..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)]
|
#[derive(Debug, Serialize)]
|
||||||
#[serde(rename_all = "lowercase")]
|
#[serde(rename_all = "lowercase")]
|
||||||
pub enum SaleType {
|
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")]
|
#[serde(rename_all = "kebab-case")]
|
||||||
pub enum SaleStatus {
|
pub enum SaleStatus {
|
||||||
Initial,
|
Initial,
|
||||||
@ -527,6 +589,8 @@ pub struct SaleQueryResponse {
|
|||||||
pub struct SaleQuery {
|
pub struct SaleQuery {
|
||||||
sale_status: SaleStatus,
|
sale_status: SaleStatus,
|
||||||
sale_payme_id: String,
|
sale_payme_id: String,
|
||||||
|
sale_error_text: Option<String>,
|
||||||
|
sale_error_code: Option<String>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Serialize, Deserialize)]
|
#[derive(Debug, Serialize, Deserialize)]
|
||||||
@ -535,6 +599,8 @@ pub struct PaymePaySaleResponse {
|
|||||||
payme_sale_id: String,
|
payme_sale_id: String,
|
||||||
payme_transaction_id: String,
|
payme_transaction_id: String,
|
||||||
buyer_key: Option<Secret<String>>,
|
buyer_key: Option<Secret<String>>,
|
||||||
|
status_error_details: Option<String>,
|
||||||
|
status_error_code: Option<u32>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Serialize, Deserialize)]
|
#[derive(Serialize, Deserialize)]
|
||||||
@ -673,7 +739,7 @@ pub struct PaymeErrorResponse {
|
|||||||
pub status_code: u16,
|
pub status_code: u16,
|
||||||
pub status_error_details: String,
|
pub status_error_details: String,
|
||||||
pub status_additional_info: serde_json::Value,
|
pub status_additional_info: serde_json::Value,
|
||||||
pub status_error_code: u16,
|
pub status_error_code: u32,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Serialize, Deserialize)]
|
#[derive(Debug, Serialize, Deserialize)]
|
||||||
@ -695,6 +761,8 @@ pub struct WebhookEventDataResource {
|
|||||||
pub notify_type: NotifyType,
|
pub notify_type: NotifyType,
|
||||||
pub payme_sale_id: String,
|
pub payme_sale_id: String,
|
||||||
pub payme_transaction_id: String,
|
pub payme_transaction_id: String,
|
||||||
|
pub status_error_details: Option<String>,
|
||||||
|
pub status_error_code: Option<u32>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Deserialize)]
|
#[derive(Debug, Deserialize)]
|
||||||
@ -715,6 +783,8 @@ impl From<WebhookEventDataResource> for PaymePaySaleResponse {
|
|||||||
payme_sale_id: value.payme_sale_id,
|
payme_sale_id: value.payme_sale_id,
|
||||||
payme_transaction_id: value.payme_transaction_id,
|
payme_transaction_id: value.payme_transaction_id,
|
||||||
buyer_key: value.buyer_key,
|
buyer_key: value.buyer_key,
|
||||||
|
status_error_code: value.status_error_code,
|
||||||
|
status_error_details: value.status_error_details,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user