mirror of
https://github.com/juspay/hyperswitch.git
synced 2025-10-28 04:04:55 +08:00
fix: [CYBERSOURCE] Fix Status Mapping (#3144)
Co-authored-by: hyperswitch-bot[bot] <148525504+hyperswitch-bot[bot]@users.noreply.github.com>
This commit is contained in:
@ -418,15 +418,11 @@ impl ConnectorIntegration<api::Capture, types::PaymentsCaptureData, types::Payme
|
||||
.response
|
||||
.parse_struct("Cybersource PaymentResponse")
|
||||
.change_context(errors::ConnectorError::ResponseDeserializationFailed)?;
|
||||
types::RouterData::try_from((
|
||||
types::ResponseRouterData {
|
||||
response,
|
||||
data: data.clone(),
|
||||
http_code: res.status_code,
|
||||
},
|
||||
true,
|
||||
))
|
||||
.change_context(errors::ConnectorError::ResponseHandlingFailed)
|
||||
types::RouterData::try_from(types::ResponseRouterData {
|
||||
response,
|
||||
data: data.clone(),
|
||||
http_code: res.status_code,
|
||||
})
|
||||
}
|
||||
fn get_error_response(
|
||||
&self,
|
||||
@ -496,17 +492,11 @@ impl ConnectorIntegration<api::PSync, types::PaymentsSyncData, types::PaymentsRe
|
||||
.response
|
||||
.parse_struct("Cybersource PaymentSyncResponse")
|
||||
.change_context(errors::ConnectorError::ResponseDeserializationFailed)?;
|
||||
let is_auto_capture =
|
||||
data.request.capture_method == Some(diesel_models::enums::CaptureMethod::Automatic);
|
||||
types::RouterData::try_from((
|
||||
types::ResponseRouterData {
|
||||
response,
|
||||
data: data.clone(),
|
||||
http_code: res.status_code,
|
||||
},
|
||||
is_auto_capture,
|
||||
))
|
||||
.change_context(errors::ConnectorError::ResponseHandlingFailed)
|
||||
types::RouterData::try_from(types::ResponseRouterData {
|
||||
response,
|
||||
data: data.clone(),
|
||||
http_code: res.status_code,
|
||||
})
|
||||
}
|
||||
fn get_error_response(
|
||||
&self,
|
||||
@ -587,17 +577,11 @@ impl ConnectorIntegration<api::Authorize, types::PaymentsAuthorizeData, types::P
|
||||
.response
|
||||
.parse_struct("Cybersource PaymentResponse")
|
||||
.change_context(errors::ConnectorError::ResponseDeserializationFailed)?;
|
||||
let is_auto_capture =
|
||||
data.request.capture_method == Some(diesel_models::enums::CaptureMethod::Automatic);
|
||||
types::RouterData::try_from((
|
||||
types::ResponseRouterData {
|
||||
response,
|
||||
data: data.clone(),
|
||||
http_code: res.status_code,
|
||||
},
|
||||
is_auto_capture,
|
||||
))
|
||||
.change_context(errors::ConnectorError::ResponseHandlingFailed)
|
||||
types::RouterData::try_from(types::ResponseRouterData {
|
||||
response,
|
||||
data: data.clone(),
|
||||
http_code: res.status_code,
|
||||
})
|
||||
}
|
||||
|
||||
fn get_error_response(
|
||||
@ -669,15 +653,11 @@ impl ConnectorIntegration<api::Void, types::PaymentsCancelData, types::PaymentsR
|
||||
.response
|
||||
.parse_struct("Cybersource PaymentResponse")
|
||||
.change_context(errors::ConnectorError::ResponseDeserializationFailed)?;
|
||||
types::RouterData::try_from((
|
||||
types::ResponseRouterData {
|
||||
response,
|
||||
data: data.clone(),
|
||||
http_code: res.status_code,
|
||||
},
|
||||
false,
|
||||
))
|
||||
.change_context(errors::ConnectorError::ResponseHandlingFailed)
|
||||
types::RouterData::try_from(types::ResponseRouterData {
|
||||
response,
|
||||
data: data.clone(),
|
||||
http_code: res.status_code,
|
||||
})
|
||||
}
|
||||
|
||||
fn get_error_response(
|
||||
@ -759,16 +739,15 @@ impl ConnectorIntegration<api::Execute, types::RefundsData, types::RefundsRespon
|
||||
data: &types::RefundExecuteRouterData,
|
||||
res: types::Response,
|
||||
) -> CustomResult<types::RefundExecuteRouterData, errors::ConnectorError> {
|
||||
let response: cybersource::CybersourcePaymentsResponse = res
|
||||
let response: cybersource::CybersourceRefundResponse = res
|
||||
.response
|
||||
.parse_struct("Cybersource PaymentResponse")
|
||||
.parse_struct("Cybersource RefundResponse")
|
||||
.change_context(errors::ConnectorError::ResponseDeserializationFailed)?;
|
||||
types::RouterData::try_from(types::ResponseRouterData {
|
||||
response,
|
||||
data: data.clone(),
|
||||
http_code: res.status_code,
|
||||
})
|
||||
.change_context(errors::ConnectorError::ResponseHandlingFailed)
|
||||
}
|
||||
fn get_error_response(
|
||||
&self,
|
||||
@ -826,17 +805,15 @@ impl ConnectorIntegration<api::RSync, types::RefundsData, types::RefundsResponse
|
||||
data: &types::RefundSyncRouterData,
|
||||
res: types::Response,
|
||||
) -> CustomResult<types::RefundSyncRouterData, errors::ConnectorError> {
|
||||
let response: cybersource::CybersourceTransactionResponse = res
|
||||
let response: cybersource::CybersourceRsyncResponse = res
|
||||
.response
|
||||
.parse_struct("Cybersource RefundsSyncResponse")
|
||||
.parse_struct("Cybersource RefundSyncResponse")
|
||||
.change_context(errors::ConnectorError::ResponseDeserializationFailed)?;
|
||||
types::ResponseRouterData {
|
||||
types::RouterData::try_from(types::ResponseRouterData {
|
||||
response,
|
||||
data: data.clone(),
|
||||
http_code: res.status_code,
|
||||
}
|
||||
.try_into()
|
||||
.change_context(errors::ConnectorError::ResponseHandlingFailed)
|
||||
})
|
||||
}
|
||||
fn get_error_response(
|
||||
&self,
|
||||
|
||||
@ -7,7 +7,7 @@ use serde::{Deserialize, Serialize};
|
||||
use crate::{
|
||||
connector::utils::{
|
||||
self, AddressDetailsData, CardData, PaymentsAuthorizeRequestData,
|
||||
PaymentsSetupMandateRequestData, RouterData,
|
||||
PaymentsSetupMandateRequestData, PaymentsSyncRequestData, RouterData,
|
||||
},
|
||||
consts,
|
||||
core::errors,
|
||||
@ -15,6 +15,7 @@ use crate::{
|
||||
self,
|
||||
api::{self, enums as api_enums},
|
||||
storage::enums,
|
||||
transformers::ForeignFrom,
|
||||
},
|
||||
};
|
||||
|
||||
@ -684,7 +685,8 @@ impl TryFrom<&types::ConnectorAuthType> for CybersourceAuthType {
|
||||
}
|
||||
}
|
||||
}
|
||||
#[derive(Debug, Default, Clone, Deserialize)]
|
||||
|
||||
#[derive(Debug, Clone, Deserialize)]
|
||||
#[serde(rename_all = "SCREAMING_SNAKE_CASE")]
|
||||
pub enum CybersourcePaymentStatus {
|
||||
Authorized,
|
||||
@ -696,8 +698,6 @@ pub enum CybersourcePaymentStatus {
|
||||
Declined,
|
||||
AuthorizedPendingReview,
|
||||
Transmitted,
|
||||
#[default]
|
||||
Processing,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Deserialize)]
|
||||
@ -708,18 +708,30 @@ pub enum CybersourceIncrementalAuthorizationStatus {
|
||||
AuthorizedPendingReview,
|
||||
}
|
||||
|
||||
impl From<CybersourcePaymentStatus> for enums::AttemptStatus {
|
||||
fn from(item: CybersourcePaymentStatus) -> Self {
|
||||
match item {
|
||||
impl ForeignFrom<(CybersourcePaymentStatus, bool)> for enums::AttemptStatus {
|
||||
fn foreign_from((status, capture): (CybersourcePaymentStatus, bool)) -> Self {
|
||||
match status {
|
||||
CybersourcePaymentStatus::Authorized
|
||||
| CybersourcePaymentStatus::AuthorizedPendingReview => Self::Authorized,
|
||||
| CybersourcePaymentStatus::AuthorizedPendingReview => {
|
||||
if capture {
|
||||
// Because Cybersource will return Payment Status as Authorized even in AutoCapture Payment
|
||||
Self::Charged
|
||||
} else {
|
||||
Self::Authorized
|
||||
}
|
||||
}
|
||||
CybersourcePaymentStatus::Pending => {
|
||||
if capture {
|
||||
Self::Charged
|
||||
} else {
|
||||
Self::Pending
|
||||
}
|
||||
}
|
||||
CybersourcePaymentStatus::Succeeded | CybersourcePaymentStatus::Transmitted => {
|
||||
Self::Charged
|
||||
}
|
||||
CybersourcePaymentStatus::Voided | CybersourcePaymentStatus::Reversed => Self::Voided,
|
||||
CybersourcePaymentStatus::Failed | CybersourcePaymentStatus::Declined => Self::Failure,
|
||||
CybersourcePaymentStatus::Processing => Self::Authorizing,
|
||||
CybersourcePaymentStatus::Pending => Self::Pending,
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -746,16 +758,29 @@ impl From<CybersourcePaymentStatus> for enums::RefundStatus {
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Deserialize)]
|
||||
#[derive(Debug, Deserialize)]
|
||||
#[serde(untagged)]
|
||||
pub enum CybersourcePaymentsResponse {
|
||||
ClientReferenceInformation(CybersourceClientReferenceResponse),
|
||||
ErrorInformation(CybersourceErrorInformationResponse),
|
||||
}
|
||||
|
||||
#[derive(Debug, Deserialize)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
pub struct CybersourcePaymentsResponse {
|
||||
pub struct CybersourceClientReferenceResponse {
|
||||
id: String,
|
||||
status: CybersourcePaymentStatus,
|
||||
error_information: Option<CybersourceErrorInformation>,
|
||||
client_reference_information: Option<ClientReferenceInformation>,
|
||||
client_reference_information: ClientReferenceInformation,
|
||||
token_information: Option<CybersourceTokenInformation>,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Deserialize)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
pub struct CybersourceErrorInformationResponse {
|
||||
id: String,
|
||||
error_information: CybersourceErrorInformation,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Deserialize)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
pub struct CybersourcePaymentsIncrementalAuthorizationResponse {
|
||||
@ -787,69 +812,201 @@ pub struct CybersourceTokenInformation {
|
||||
|
||||
#[derive(Debug, Clone, Deserialize)]
|
||||
pub struct CybersourceErrorInformation {
|
||||
reason: String,
|
||||
message: String,
|
||||
reason: Option<String>,
|
||||
message: Option<String>,
|
||||
}
|
||||
|
||||
impl<F, T>
|
||||
TryFrom<(
|
||||
From<(
|
||||
&CybersourceErrorInformationResponse,
|
||||
types::ResponseRouterData<F, CybersourcePaymentsResponse, T, types::PaymentsResponseData>,
|
||||
bool,
|
||||
)> for types::RouterData<F, T, types::PaymentsResponseData>
|
||||
{
|
||||
type Error = error_stack::Report<errors::ConnectorError>;
|
||||
fn try_from(
|
||||
data: (
|
||||
fn from(
|
||||
(error_response, item): (
|
||||
&CybersourceErrorInformationResponse,
|
||||
types::ResponseRouterData<
|
||||
F,
|
||||
CybersourcePaymentsResponse,
|
||||
T,
|
||||
types::PaymentsResponseData,
|
||||
>,
|
||||
bool,
|
||||
),
|
||||
) -> Result<Self, Self::Error> {
|
||||
let item = data.0;
|
||||
let is_capture = data.1;
|
||||
let mandate_reference =
|
||||
item.response
|
||||
.token_information
|
||||
.map(|token_info| types::MandateReference {
|
||||
connector_mandate_id: Some(token_info.instrument_identifier.id),
|
||||
payment_method_id: None,
|
||||
});
|
||||
let status = get_payment_status(is_capture, item.response.status.into());
|
||||
Ok(Self {
|
||||
status,
|
||||
response: match item.response.error_information {
|
||||
Some(error) => Err(types::ErrorResponse {
|
||||
code: consts::NO_ERROR_CODE.to_string(),
|
||||
message: error.message,
|
||||
reason: Some(error.reason),
|
||||
status_code: item.http_code,
|
||||
attempt_status: None,
|
||||
connector_transaction_id: Some(item.response.id),
|
||||
}),
|
||||
_ => Ok(types::PaymentsResponseData::TransactionResponse {
|
||||
resource_id: types::ResponseId::ConnectorTransactionId(
|
||||
item.response.id.clone(),
|
||||
),
|
||||
redirection_data: None,
|
||||
mandate_reference,
|
||||
connector_metadata: None,
|
||||
network_txn_id: None,
|
||||
connector_response_reference_id: item
|
||||
.response
|
||||
.client_reference_information
|
||||
.map(|cref| cref.code)
|
||||
.unwrap_or(Some(item.response.id)),
|
||||
incremental_authorization_allowed: Some(
|
||||
status == enums::AttemptStatus::Authorized,
|
||||
),
|
||||
}),
|
||||
},
|
||||
) -> Self {
|
||||
Self {
|
||||
response: Err(types::ErrorResponse {
|
||||
code: consts::NO_ERROR_CODE.to_string(),
|
||||
message: error_response
|
||||
.error_information
|
||||
.message
|
||||
.clone()
|
||||
.unwrap_or(consts::NO_ERROR_MESSAGE.to_string()),
|
||||
reason: error_response.error_information.reason.clone(),
|
||||
status_code: item.http_code,
|
||||
attempt_status: None,
|
||||
connector_transaction_id: None,
|
||||
}),
|
||||
..item.data
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<F>
|
||||
TryFrom<
|
||||
types::ResponseRouterData<
|
||||
F,
|
||||
CybersourcePaymentsResponse,
|
||||
types::PaymentsAuthorizeData,
|
||||
types::PaymentsResponseData,
|
||||
>,
|
||||
> for types::RouterData<F, types::PaymentsAuthorizeData, types::PaymentsResponseData>
|
||||
{
|
||||
type Error = error_stack::Report<errors::ConnectorError>;
|
||||
fn try_from(
|
||||
item: types::ResponseRouterData<
|
||||
F,
|
||||
CybersourcePaymentsResponse,
|
||||
types::PaymentsAuthorizeData,
|
||||
types::PaymentsResponseData,
|
||||
>,
|
||||
) -> Result<Self, Self::Error> {
|
||||
match item.response {
|
||||
CybersourcePaymentsResponse::ClientReferenceInformation(info_response) => {
|
||||
let status = enums::AttemptStatus::foreign_from((
|
||||
info_response.status,
|
||||
item.data.request.is_auto_capture()?,
|
||||
));
|
||||
let incremental_authorization_allowed =
|
||||
Some(status == enums::AttemptStatus::Authorized);
|
||||
let mandate_reference =
|
||||
info_response
|
||||
.token_information
|
||||
.map(|token_info| types::MandateReference {
|
||||
connector_mandate_id: Some(token_info.instrument_identifier.id),
|
||||
payment_method_id: None,
|
||||
});
|
||||
let connector_response_reference_id = Some(
|
||||
info_response
|
||||
.client_reference_information
|
||||
.code
|
||||
.unwrap_or(info_response.id.clone()),
|
||||
);
|
||||
Ok(Self {
|
||||
status,
|
||||
response: Ok(types::PaymentsResponseData::TransactionResponse {
|
||||
resource_id: types::ResponseId::ConnectorTransactionId(info_response.id),
|
||||
redirection_data: None,
|
||||
mandate_reference,
|
||||
connector_metadata: None,
|
||||
network_txn_id: None,
|
||||
connector_response_reference_id,
|
||||
incremental_authorization_allowed,
|
||||
}),
|
||||
..item.data
|
||||
})
|
||||
}
|
||||
CybersourcePaymentsResponse::ErrorInformation(ref error_response) => {
|
||||
Ok(Self::from((&error_response.clone(), item)))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<F>
|
||||
TryFrom<
|
||||
types::ResponseRouterData<
|
||||
F,
|
||||
CybersourcePaymentsResponse,
|
||||
types::PaymentsCaptureData,
|
||||
types::PaymentsResponseData,
|
||||
>,
|
||||
> for types::RouterData<F, types::PaymentsCaptureData, types::PaymentsResponseData>
|
||||
{
|
||||
type Error = error_stack::Report<errors::ConnectorError>;
|
||||
fn try_from(
|
||||
item: types::ResponseRouterData<
|
||||
F,
|
||||
CybersourcePaymentsResponse,
|
||||
types::PaymentsCaptureData,
|
||||
types::PaymentsResponseData,
|
||||
>,
|
||||
) -> Result<Self, Self::Error> {
|
||||
match item.response {
|
||||
CybersourcePaymentsResponse::ClientReferenceInformation(info_response) => {
|
||||
let status = enums::AttemptStatus::foreign_from((info_response.status, true));
|
||||
let connector_response_reference_id = Some(
|
||||
info_response
|
||||
.client_reference_information
|
||||
.code
|
||||
.unwrap_or(info_response.id.clone()),
|
||||
);
|
||||
Ok(Self {
|
||||
status,
|
||||
response: Ok(types::PaymentsResponseData::TransactionResponse {
|
||||
resource_id: types::ResponseId::ConnectorTransactionId(info_response.id),
|
||||
redirection_data: None,
|
||||
mandate_reference: None,
|
||||
connector_metadata: None,
|
||||
network_txn_id: None,
|
||||
connector_response_reference_id,
|
||||
incremental_authorization_allowed: None,
|
||||
}),
|
||||
..item.data
|
||||
})
|
||||
}
|
||||
CybersourcePaymentsResponse::ErrorInformation(ref error_response) => {
|
||||
Ok(Self::from((&error_response.clone(), item)))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<F>
|
||||
TryFrom<
|
||||
types::ResponseRouterData<
|
||||
F,
|
||||
CybersourcePaymentsResponse,
|
||||
types::PaymentsCancelData,
|
||||
types::PaymentsResponseData,
|
||||
>,
|
||||
> for types::RouterData<F, types::PaymentsCancelData, types::PaymentsResponseData>
|
||||
{
|
||||
type Error = error_stack::Report<errors::ConnectorError>;
|
||||
fn try_from(
|
||||
item: types::ResponseRouterData<
|
||||
F,
|
||||
CybersourcePaymentsResponse,
|
||||
types::PaymentsCancelData,
|
||||
types::PaymentsResponseData,
|
||||
>,
|
||||
) -> Result<Self, Self::Error> {
|
||||
match item.response {
|
||||
CybersourcePaymentsResponse::ClientReferenceInformation(info_response) => {
|
||||
let status = enums::AttemptStatus::foreign_from((info_response.status, false));
|
||||
let connector_response_reference_id = Some(
|
||||
info_response
|
||||
.client_reference_information
|
||||
.code
|
||||
.unwrap_or(info_response.id.clone()),
|
||||
);
|
||||
Ok(Self {
|
||||
status,
|
||||
response: Ok(types::PaymentsResponseData::TransactionResponse {
|
||||
resource_id: types::ResponseId::ConnectorTransactionId(info_response.id),
|
||||
redirection_data: None,
|
||||
mandate_reference: None,
|
||||
connector_metadata: None,
|
||||
network_txn_id: None,
|
||||
connector_response_reference_id,
|
||||
incremental_authorization_allowed: None,
|
||||
}),
|
||||
..item.data
|
||||
})
|
||||
}
|
||||
CybersourcePaymentsResponse::ErrorInformation(ref error_response) => {
|
||||
Ok(Self::from((&error_response.clone(), item)))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -879,7 +1036,7 @@ impl<F, T>
|
||||
connector_mandate_id: Some(token_info.instrument_identifier.id),
|
||||
payment_method_id: None,
|
||||
});
|
||||
let mut mandate_status: enums::AttemptStatus = item.response.status.into();
|
||||
let mut mandate_status = enums::AttemptStatus::foreign_from((item.response.status, false));
|
||||
if matches!(mandate_status, enums::AttemptStatus::Authorized) {
|
||||
//In case of zero auth mandates we want to make the payment reach the terminal status so we are converting the authorized status to charged as well.
|
||||
mandate_status = enums::AttemptStatus::Charged
|
||||
@ -889,8 +1046,10 @@ impl<F, T>
|
||||
response: match item.response.error_information {
|
||||
Some(error) => Err(types::ErrorResponse {
|
||||
code: consts::NO_ERROR_CODE.to_string(),
|
||||
message: error.message,
|
||||
reason: Some(error.reason),
|
||||
message: error
|
||||
.message
|
||||
.unwrap_or(consts::NO_ERROR_MESSAGE.to_string()),
|
||||
reason: error.reason,
|
||||
status_code: item.http_code,
|
||||
attempt_status: None,
|
||||
connector_transaction_id: Some(item.response.id),
|
||||
@ -947,8 +1106,8 @@ impl<F, T>
|
||||
Some(error) => Ok(
|
||||
types::PaymentsResponseData::IncrementalAuthorizationResponse {
|
||||
status: common_enums::AuthorizationStatus::Failure,
|
||||
error_code: Some(error.reason),
|
||||
error_message: Some(error.message),
|
||||
error_code: error.reason,
|
||||
error_message: error.message,
|
||||
connector_authorization_id: None,
|
||||
},
|
||||
),
|
||||
@ -966,9 +1125,16 @@ impl<F, T>
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Deserialize)]
|
||||
#[serde(untagged)]
|
||||
pub enum CybersourceTransactionResponse {
|
||||
ApplicationInformation(CybersourceApplicationInfoResponse),
|
||||
ErrorInformation(CybersourceErrorInformationResponse),
|
||||
}
|
||||
|
||||
#[derive(Debug, Deserialize)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
pub struct CybersourceTransactionResponse {
|
||||
pub struct CybersourceApplicationInfoResponse {
|
||||
id: String,
|
||||
application_information: ApplicationInformation,
|
||||
client_reference_information: Option<ClientReferenceInformation>,
|
||||
@ -980,61 +1146,68 @@ pub struct ApplicationInformation {
|
||||
status: CybersourcePaymentStatus,
|
||||
}
|
||||
|
||||
fn get_payment_status(is_capture: bool, status: enums::AttemptStatus) -> enums::AttemptStatus {
|
||||
let is_authorized = matches!(status, enums::AttemptStatus::Authorized);
|
||||
let is_pending = matches!(status, enums::AttemptStatus::Pending);
|
||||
if is_capture && (is_authorized || is_pending) {
|
||||
return enums::AttemptStatus::Charged;
|
||||
}
|
||||
status
|
||||
}
|
||||
|
||||
impl<F, T>
|
||||
TryFrom<(
|
||||
impl<F>
|
||||
TryFrom<
|
||||
types::ResponseRouterData<
|
||||
F,
|
||||
CybersourceTransactionResponse,
|
||||
T,
|
||||
types::PaymentsSyncData,
|
||||
types::PaymentsResponseData,
|
||||
>,
|
||||
bool,
|
||||
)> for types::RouterData<F, T, types::PaymentsResponseData>
|
||||
> for types::RouterData<F, types::PaymentsSyncData, types::PaymentsResponseData>
|
||||
{
|
||||
type Error = error_stack::Report<errors::ConnectorError>;
|
||||
fn try_from(
|
||||
data: (
|
||||
types::ResponseRouterData<
|
||||
F,
|
||||
CybersourceTransactionResponse,
|
||||
T,
|
||||
types::PaymentsResponseData,
|
||||
>,
|
||||
bool,
|
||||
),
|
||||
item: types::ResponseRouterData<
|
||||
F,
|
||||
CybersourceTransactionResponse,
|
||||
types::PaymentsSyncData,
|
||||
types::PaymentsResponseData,
|
||||
>,
|
||||
) -> Result<Self, Self::Error> {
|
||||
let item = data.0;
|
||||
let is_capture = data.1;
|
||||
let status = get_payment_status(
|
||||
is_capture,
|
||||
item.response.application_information.status.into(),
|
||||
);
|
||||
Ok(Self {
|
||||
status,
|
||||
response: Ok(types::PaymentsResponseData::TransactionResponse {
|
||||
resource_id: types::ResponseId::ConnectorTransactionId(item.response.id.clone()),
|
||||
redirection_data: None,
|
||||
mandate_reference: None,
|
||||
connector_metadata: None,
|
||||
network_txn_id: None,
|
||||
connector_response_reference_id: item
|
||||
.response
|
||||
.client_reference_information
|
||||
.map(|cref| cref.code)
|
||||
.unwrap_or(Some(item.response.id)),
|
||||
incremental_authorization_allowed: Some(status == enums::AttemptStatus::Authorized),
|
||||
match item.response {
|
||||
CybersourceTransactionResponse::ApplicationInformation(app_response) => {
|
||||
let status = enums::AttemptStatus::foreign_from((
|
||||
app_response.application_information.status,
|
||||
item.data.request.is_auto_capture()?,
|
||||
));
|
||||
let incremental_authorization_allowed =
|
||||
Some(status == enums::AttemptStatus::Authorized);
|
||||
Ok(Self {
|
||||
status,
|
||||
response: Ok(types::PaymentsResponseData::TransactionResponse {
|
||||
resource_id: types::ResponseId::ConnectorTransactionId(
|
||||
app_response.id.clone(),
|
||||
),
|
||||
redirection_data: None,
|
||||
mandate_reference: None,
|
||||
connector_metadata: None,
|
||||
network_txn_id: None,
|
||||
incremental_authorization_allowed,
|
||||
connector_response_reference_id: app_response
|
||||
.client_reference_information
|
||||
.map(|cref| cref.code)
|
||||
.unwrap_or(Some(app_response.id)),
|
||||
}),
|
||||
..item.data
|
||||
})
|
||||
}
|
||||
CybersourceTransactionResponse::ErrorInformation(error_response) => Ok(Self {
|
||||
status: item.data.status,
|
||||
response: Ok(types::PaymentsResponseData::TransactionResponse {
|
||||
resource_id: types::ResponseId::ConnectorTransactionId(
|
||||
error_response.id.clone(),
|
||||
),
|
||||
redirection_data: None,
|
||||
mandate_reference: None,
|
||||
connector_metadata: None,
|
||||
network_txn_id: None,
|
||||
connector_response_reference_id: Some(error_response.id),
|
||||
incremental_authorization_allowed: None,
|
||||
}),
|
||||
..item.data
|
||||
}),
|
||||
..item.data
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -1103,30 +1276,71 @@ impl<F> TryFrom<&CybersourceRouterData<&types::RefundsRouterData<F>>> for Cybers
|
||||
}
|
||||
}
|
||||
|
||||
impl TryFrom<types::RefundsResponseRouterData<api::Execute, CybersourcePaymentsResponse>>
|
||||
impl From<CybersourceRefundStatus> for enums::RefundStatus {
|
||||
fn from(item: CybersourceRefundStatus) -> Self {
|
||||
match item {
|
||||
CybersourceRefundStatus::Succeeded | CybersourceRefundStatus::Transmitted => {
|
||||
Self::Success
|
||||
}
|
||||
CybersourceRefundStatus::Failed | CybersourceRefundStatus::Voided => Self::Failure,
|
||||
CybersourceRefundStatus::Pending => Self::Pending,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Deserialize)]
|
||||
#[serde(rename_all = "SCREAMING_SNAKE_CASE")]
|
||||
pub enum CybersourceRefundStatus {
|
||||
Succeeded,
|
||||
Transmitted,
|
||||
Failed,
|
||||
Pending,
|
||||
Voided,
|
||||
}
|
||||
|
||||
#[derive(Debug, Deserialize)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
pub struct CybersourceRefundResponse {
|
||||
id: String,
|
||||
status: CybersourceRefundStatus,
|
||||
}
|
||||
|
||||
impl TryFrom<types::RefundsResponseRouterData<api::Execute, CybersourceRefundResponse>>
|
||||
for types::RefundsRouterData<api::Execute>
|
||||
{
|
||||
type Error = error_stack::Report<errors::ConnectorError>;
|
||||
fn try_from(
|
||||
item: types::RefundsResponseRouterData<api::Execute, CybersourcePaymentsResponse>,
|
||||
item: types::RefundsResponseRouterData<api::Execute, CybersourceRefundResponse>,
|
||||
) -> Result<Self, Self::Error> {
|
||||
let refund_status = enums::RefundStatus::from(item.response.status);
|
||||
Ok(Self {
|
||||
response: Ok(types::RefundsResponseData {
|
||||
connector_refund_id: item.response.id,
|
||||
refund_status,
|
||||
refund_status: enums::RefundStatus::from(item.response.status),
|
||||
}),
|
||||
..item.data
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
impl TryFrom<types::RefundsResponseRouterData<api::RSync, CybersourceTransactionResponse>>
|
||||
#[derive(Debug, Deserialize)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
pub struct RsyncApplicationInformation {
|
||||
status: CybersourceRefundStatus,
|
||||
}
|
||||
|
||||
#[derive(Debug, Deserialize)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
pub struct CybersourceRsyncResponse {
|
||||
id: String,
|
||||
application_information: RsyncApplicationInformation,
|
||||
}
|
||||
|
||||
impl TryFrom<types::RefundsResponseRouterData<api::RSync, CybersourceRsyncResponse>>
|
||||
for types::RefundsRouterData<api::RSync>
|
||||
{
|
||||
type Error = error_stack::Report<errors::ConnectorError>;
|
||||
fn try_from(
|
||||
item: types::RefundsResponseRouterData<api::RSync, CybersourceTransactionResponse>,
|
||||
item: types::RefundsResponseRouterData<api::RSync, CybersourceRsyncResponse>,
|
||||
) -> Result<Self, Self::Error> {
|
||||
Ok(Self {
|
||||
response: Ok(types::RefundsResponseData {
|
||||
|
||||
Reference in New Issue
Block a user