mirror of
https://github.com/juspay/hyperswitch.git
synced 2025-12-05 18:46:43 -06:00
feat(connector): [WorldpayWPG] Implement cards and apple pay decrypt payout (#10545)
Co-authored-by: Vani Gupta <vani.gupta@juspay.in> Co-authored-by: hyperswitch-bot[bot] <148525504+hyperswitch-bot[bot]@users.noreply.github.com>
This commit is contained in:
@@ -34,7 +34,10 @@ use hyperswitch_domain_models::{
|
||||
};
|
||||
#[cfg(feature = "payouts")]
|
||||
use hyperswitch_domain_models::{
|
||||
router_flow_types::payouts::{PoCancel, PoFulfill},
|
||||
router_flow_types::{
|
||||
payouts::{PoCancel, PoFulfill},
|
||||
PoSync,
|
||||
},
|
||||
router_request_types::PayoutsData,
|
||||
router_response_types::PayoutsResponseData,
|
||||
types::PayoutsRouterData,
|
||||
@@ -53,7 +56,11 @@ use hyperswitch_interfaces::{
|
||||
use masking::{ExposeInterface, Mask};
|
||||
use transformers as worldpayxml;
|
||||
|
||||
use crate::{constants::headers, types::ResponseRouterData, utils};
|
||||
use crate::{
|
||||
constants::headers,
|
||||
types::ResponseRouterData,
|
||||
utils::{self},
|
||||
};
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct Worldpayxml {
|
||||
@@ -772,6 +779,8 @@ impl api::Payouts for Worldpayxml {}
|
||||
impl api::PayoutFulfill for Worldpayxml {}
|
||||
#[cfg(feature = "payouts")]
|
||||
impl api::PayoutCancel for Worldpayxml {}
|
||||
#[cfg(feature = "payouts")]
|
||||
impl api::PayoutSync for Worldpayxml {}
|
||||
|
||||
#[async_trait::async_trait]
|
||||
#[cfg(feature = "payouts")]
|
||||
@@ -875,6 +884,97 @@ impl ConnectorIntegration<PoFulfill, PayoutsData, PayoutsResponseData> for World
|
||||
}
|
||||
}
|
||||
|
||||
#[async_trait::async_trait]
|
||||
#[cfg(feature = "payouts")]
|
||||
impl ConnectorIntegration<PoSync, PayoutsData, PayoutsResponseData> for Worldpayxml {
|
||||
fn get_url(
|
||||
&self,
|
||||
_req: &PayoutsRouterData<PoSync>,
|
||||
connectors: &Connectors,
|
||||
) -> CustomResult<String, errors::ConnectorError> {
|
||||
Ok(self.base_url(connectors).to_owned())
|
||||
}
|
||||
|
||||
fn get_headers(
|
||||
&self,
|
||||
req: &PayoutsRouterData<PoSync>,
|
||||
connectors: &Connectors,
|
||||
) -> CustomResult<Vec<(String, masking::Maskable<String>)>, errors::ConnectorError> {
|
||||
self.build_headers(req, connectors)
|
||||
}
|
||||
|
||||
fn get_content_type(&self) -> &'static str {
|
||||
self.common_get_content_type()
|
||||
}
|
||||
|
||||
fn get_request_body(
|
||||
&self,
|
||||
req: &PayoutsRouterData<PoSync>,
|
||||
_connectors: &Connectors,
|
||||
) -> CustomResult<RequestContent, errors::ConnectorError> {
|
||||
let connector_req_object = worldpayxml::PaymentService::try_from(req)?;
|
||||
let connector_req = utils::XmlSerializer::serialize_to_xml_bytes(
|
||||
&connector_req_object,
|
||||
worldpayxml::worldpayxml_constants::XML_VERSION,
|
||||
Some(worldpayxml::worldpayxml_constants::XML_ENCODING),
|
||||
None,
|
||||
Some(worldpayxml::worldpayxml_constants::WORLDPAYXML_DOC_TYPE),
|
||||
)?;
|
||||
Ok(RequestContent::RawBytes(connector_req))
|
||||
}
|
||||
|
||||
fn build_request(
|
||||
&self,
|
||||
req: &PayoutsRouterData<PoSync>,
|
||||
connectors: &Connectors,
|
||||
) -> CustomResult<Option<Request>, errors::ConnectorError> {
|
||||
let request = RequestBuilder::new()
|
||||
.method(Method::Post)
|
||||
.url(&types::PayoutSyncType::get_url(self, req, connectors)?)
|
||||
.attach_default_headers()
|
||||
.headers(types::PayoutSyncType::get_headers(self, req, connectors)?)
|
||||
.set_body(types::PayoutSyncType::get_request_body(
|
||||
self, req, connectors,
|
||||
)?)
|
||||
.build();
|
||||
Ok(Some(request))
|
||||
}
|
||||
|
||||
fn handle_response(
|
||||
&self,
|
||||
data: &PayoutsRouterData<PoSync>,
|
||||
event_builder: Option<&mut ConnectorEvent>,
|
||||
res: Response,
|
||||
) -> CustomResult<PayoutsRouterData<PoSync>, errors::ConnectorError> {
|
||||
let response: worldpayxml::PaymentService =
|
||||
utils::deserialize_xml_to_struct(&res.response)?;
|
||||
event_builder.map(|i| i.set_response_body(&response));
|
||||
router_env::logger::info!(connector_response=?response);
|
||||
RouterData::try_from(ResponseRouterData {
|
||||
response,
|
||||
data: data.clone(),
|
||||
http_code: res.status_code,
|
||||
})
|
||||
.change_context(errors::ConnectorError::ResponseHandlingFailed)
|
||||
}
|
||||
|
||||
fn get_error_response(
|
||||
&self,
|
||||
res: Response,
|
||||
event_builder: Option<&mut ConnectorEvent>,
|
||||
) -> CustomResult<ErrorResponse, errors::ConnectorError> {
|
||||
self.build_error_response(res, event_builder)
|
||||
}
|
||||
|
||||
fn get_5xx_error_response(
|
||||
&self,
|
||||
res: Response,
|
||||
event_builder: Option<&mut ConnectorEvent>,
|
||||
) -> CustomResult<ErrorResponse, errors::ConnectorError> {
|
||||
self.build_error_response(res, event_builder)
|
||||
}
|
||||
}
|
||||
|
||||
#[async_trait::async_trait]
|
||||
#[cfg(feature = "payouts")]
|
||||
impl ConnectorIntegration<PoCancel, PayoutsData, PayoutsResponseData> for Worldpayxml {
|
||||
|
||||
@@ -10,7 +10,7 @@ use error_stack::ResultExt;
|
||||
#[cfg(feature = "payouts")]
|
||||
use hyperswitch_domain_models::{
|
||||
address::Address,
|
||||
router_flow_types::payouts::{PoCancel, PoFulfill},
|
||||
router_flow_types::payouts::{PoCancel, PoFulfill, PoSync},
|
||||
router_response_types::PayoutsResponseData,
|
||||
types::PayoutsRouterData,
|
||||
};
|
||||
@@ -144,21 +144,22 @@ pub struct Reply {
|
||||
#[derive(Debug, Deserialize, Serialize)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
pub struct PayoutResponse {
|
||||
pub reply: PayoutReply,
|
||||
reply: PayoutReply,
|
||||
}
|
||||
|
||||
#[cfg(feature = "payouts")]
|
||||
#[derive(Debug, Deserialize, Serialize)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
pub struct PayoutReply {
|
||||
pub ok: Option<OkPayoutResponse>,
|
||||
pub error: Option<WorldpayXmlErrorResponse>,
|
||||
struct PayoutReply {
|
||||
ok: Option<OkPayoutResponse>,
|
||||
order_status: Option<OrderStatus>,
|
||||
error: Option<WorldpayXmlErrorResponse>,
|
||||
}
|
||||
|
||||
#[cfg(feature = "payouts")]
|
||||
#[derive(Debug, Deserialize, Serialize)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
pub struct OkPayoutResponse {
|
||||
struct OkPayoutResponse {
|
||||
refund_received: Option<ModifyRequestReceived>,
|
||||
cancel_received: Option<ModifyRequestReceived>,
|
||||
}
|
||||
@@ -285,6 +286,10 @@ pub enum LastEvent {
|
||||
RefundRequested,
|
||||
RefundFailed,
|
||||
RefundedByMerchant,
|
||||
Error,
|
||||
QueryRequired,
|
||||
CancelReceived,
|
||||
RefundReceived,
|
||||
}
|
||||
|
||||
#[derive(Debug, Deserialize, Serialize)]
|
||||
@@ -474,24 +479,18 @@ struct GooglePayData {
|
||||
}
|
||||
|
||||
#[cfg(feature = "payouts")]
|
||||
#[derive(Clone, Debug, Serialize, Deserialize)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
pub enum PayoutOutcome {
|
||||
RefundReceived,
|
||||
Refused,
|
||||
Error,
|
||||
QueryRequired,
|
||||
CancelReceived,
|
||||
}
|
||||
|
||||
#[cfg(feature = "payouts")]
|
||||
impl From<PayoutOutcome> for enums::PayoutStatus {
|
||||
fn from(item: PayoutOutcome) -> Self {
|
||||
impl TryFrom<LastEvent> for enums::PayoutStatus {
|
||||
type Error = errors::ConnectorError;
|
||||
fn try_from(item: LastEvent) -> Result<Self, Self::Error> {
|
||||
match item {
|
||||
PayoutOutcome::RefundReceived => Self::Initiated,
|
||||
PayoutOutcome::Error | PayoutOutcome::Refused => Self::Failed,
|
||||
PayoutOutcome::QueryRequired => Self::Pending,
|
||||
PayoutOutcome::CancelReceived => Self::Cancelled,
|
||||
LastEvent::SentForRefund | LastEvent::RefundReceived => Ok(Self::Initiated),
|
||||
LastEvent::Error | LastEvent::Refused => Ok(Self::Failed),
|
||||
LastEvent::QueryRequired => Ok(Self::Pending),
|
||||
LastEvent::CancelReceived => Ok(Self::Cancelled),
|
||||
LastEvent::RefundedByMerchant => Ok(Self::Success),
|
||||
_ => Err(errors::ConnectorError::UnexpectedResponseError(
|
||||
bytes::Bytes::from("Invalid LastEvent".to_string()),
|
||||
)),
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -961,12 +960,7 @@ fn get_attempt_status(
|
||||
LastEvent::Cancelled => Ok(common_enums::AttemptStatus::Voided),
|
||||
LastEvent::Captured | LastEvent::Settled => Ok(common_enums::AttemptStatus::Charged),
|
||||
LastEvent::SentForAuthorisation => Ok(common_enums::AttemptStatus::Authorizing),
|
||||
LastEvent::Refunded
|
||||
| LastEvent::SentForRefund
|
||||
| LastEvent::RefundRequested
|
||||
| LastEvent::SentForFastRefund
|
||||
| LastEvent::RefundedByMerchant
|
||||
| LastEvent::RefundFailed => Err(errors::ConnectorError::UnexpectedResponseError(
|
||||
_ => Err(errors::ConnectorError::UnexpectedResponseError(
|
||||
bytes::Bytes::from("Invalid LastEvent".to_string()),
|
||||
)),
|
||||
}
|
||||
@@ -981,10 +975,7 @@ fn get_refund_status(last_event: LastEvent) -> Result<enums::RefundStatus, error
|
||||
| LastEvent::RefundedByMerchant => Ok(enums::RefundStatus::Pending),
|
||||
LastEvent::RefundFailed => Ok(enums::RefundStatus::Failure),
|
||||
LastEvent::Captured | LastEvent::Settled => Ok(enums::RefundStatus::Pending),
|
||||
LastEvent::Authorised
|
||||
| LastEvent::Refused
|
||||
| LastEvent::Cancelled
|
||||
| LastEvent::SentForAuthorisation => Err(errors::ConnectorError::UnexpectedResponseError(
|
||||
_ => Err(errors::ConnectorError::UnexpectedResponseError(
|
||||
bytes::Bytes::from("Invalid LastEvent".to_string()),
|
||||
)),
|
||||
}
|
||||
@@ -1495,7 +1486,7 @@ impl TryFrom<&RefundSyncRouterData> for PaymentService {
|
||||
|
||||
#[cfg(feature = "payouts")]
|
||||
impl TryFrom<(ApplePayDecrypt, Option<CardAddress>, Option<String>)> for PaymentDetails {
|
||||
type Error = error_stack::Report<errors::ConnectorError>;
|
||||
type Error = errors::ConnectorError;
|
||||
fn try_from(
|
||||
(apple_pay_decrypted_data, address, purpose_of_payment): (
|
||||
ApplePayDecrypt,
|
||||
@@ -1514,22 +1505,22 @@ impl TryFrom<(ApplePayDecrypt, Option<CardAddress>, Option<String>)> for Payment
|
||||
card_holder_name: apple_pay_decrypted_data.card_holder_name.clone(),
|
||||
cvc: None,
|
||||
card_address: address,
|
||||
purpose_of_payment_code: None,
|
||||
purpose_of_payment_code: purpose_of_payment,
|
||||
};
|
||||
|
||||
let payment_method = match apple_pay_decrypted_data.card_network {
|
||||
Some(CardNetwork::Visa) => PaymentMethod::VisaSSL(CardSSL {
|
||||
purpose_of_payment_code: purpose_of_payment.clone(),
|
||||
..card_data
|
||||
}),
|
||||
Some(CardNetwork::Mastercard) => PaymentMethod::EcmcSSL(CardSSL {
|
||||
purpose_of_payment_code: purpose_of_payment.clone(),
|
||||
..card_data
|
||||
}),
|
||||
_ => PaymentMethod::CardSSL(CardSSL {
|
||||
purpose_of_payment_code: None,
|
||||
..card_data
|
||||
}),
|
||||
let card_network = apple_pay_decrypted_data.card_network.ok_or(
|
||||
errors::ConnectorError::MissingRequiredField {
|
||||
field_name: "card_network",
|
||||
},
|
||||
)?;
|
||||
|
||||
let payment_method = match card_network {
|
||||
CardNetwork::Visa => PaymentMethod::VisaSSL(CardSSL { ..card_data }),
|
||||
CardNetwork::Mastercard => PaymentMethod::EcmcSSL(CardSSL { ..card_data }),
|
||||
_ => Err(errors::ConnectorError::NotSupported {
|
||||
message: format!("{} card network is not supported", card_network).to_string(),
|
||||
connector: "WorldpayWPG Payout",
|
||||
})?,
|
||||
};
|
||||
|
||||
Ok(Self {
|
||||
@@ -1560,22 +1551,23 @@ impl TryFrom<(CardPayout, Option<CardAddress>, Option<String>)> for PaymentDetai
|
||||
card_holder_name: card_payout.card_holder_name.to_owned(),
|
||||
cvc: None,
|
||||
card_address: address,
|
||||
purpose_of_payment_code: None,
|
||||
purpose_of_payment_code: purpose_of_payment,
|
||||
};
|
||||
|
||||
let payment_method = match card_payout.card_network {
|
||||
Some(CardNetwork::Visa) => PaymentMethod::VisaSSL(CardSSL {
|
||||
purpose_of_payment_code: purpose_of_payment.clone(),
|
||||
..card_data
|
||||
}),
|
||||
Some(CardNetwork::Mastercard) => PaymentMethod::EcmcSSL(CardSSL {
|
||||
purpose_of_payment_code: purpose_of_payment.clone(),
|
||||
..card_data
|
||||
}),
|
||||
_ => PaymentMethod::CardSSL(CardSSL {
|
||||
purpose_of_payment_code: None,
|
||||
..card_data
|
||||
}),
|
||||
let card_network =
|
||||
card_payout
|
||||
.card_network
|
||||
.ok_or(errors::ConnectorError::MissingRequiredField {
|
||||
field_name: "card_network",
|
||||
})?;
|
||||
|
||||
let payment_method = match card_network {
|
||||
CardNetwork::Visa => PaymentMethod::VisaSSL(CardSSL { ..card_data }),
|
||||
CardNetwork::Mastercard => PaymentMethod::EcmcSSL(CardSSL { ..card_data }),
|
||||
_ => Err(errors::ConnectorError::NotSupported {
|
||||
message: format!("{} card network is not supported", card_network).to_string(),
|
||||
connector: "WorldpayWPG Payout",
|
||||
})?,
|
||||
};
|
||||
|
||||
Ok(Self {
|
||||
@@ -1713,35 +1705,184 @@ impl TryFrom<PayoutsResponseRouterData<PoFulfill, PayoutResponse>>
|
||||
) -> Result<Self, Self::Error> {
|
||||
let reply = item.response.reply;
|
||||
|
||||
match (reply.error, reply.ok) {
|
||||
(Some(error), None) => Ok(Self {
|
||||
match (reply.error, reply.order_status, reply.ok) {
|
||||
(Some(error), None, None) => Ok(Self {
|
||||
status: common_enums::AttemptStatus::Failure,
|
||||
response: Ok(PayoutsResponseData {
|
||||
status: Some(enums::PayoutStatus::from(PayoutOutcome::Error)),
|
||||
connector_payout_id: None,
|
||||
payout_eligible: None,
|
||||
should_add_next_step_to_process_tracker: false,
|
||||
error_code: Some(error.code),
|
||||
error_message: Some(error.message),
|
||||
payout_connector_metadata: None,
|
||||
}),
|
||||
..item.data
|
||||
}),
|
||||
(None, Some(ok_status)) => Ok(Self {
|
||||
response: Ok(PayoutsResponseData {
|
||||
status: Some(enums::PayoutStatus::from(PayoutOutcome::RefundReceived)),
|
||||
connector_payout_id: ok_status.refund_received.map(|id| id.order_code),
|
||||
payout_eligible: None,
|
||||
should_add_next_step_to_process_tracker: false,
|
||||
error_code: None,
|
||||
error_message: None,
|
||||
payout_connector_metadata: None,
|
||||
response: Err(ErrorResponse {
|
||||
code: error.code,
|
||||
message: error.message.clone(),
|
||||
reason: Some(error.message.clone()),
|
||||
status_code: item.http_code,
|
||||
attempt_status: None,
|
||||
connector_transaction_id: None,
|
||||
network_advice_code: None,
|
||||
network_decline_code: None,
|
||||
network_error_message: None,
|
||||
connector_metadata: None,
|
||||
}),
|
||||
..item.data
|
||||
}),
|
||||
(None, Some(order_status), None) => {
|
||||
match (order_status.payment, order_status.error) {
|
||||
(Some(payment), None) => Ok(Self {
|
||||
response: Ok(PayoutsResponseData {
|
||||
status: Some(enums::PayoutStatus::try_from(payment.last_event)?),
|
||||
connector_payout_id: Some(order_status.order_code),
|
||||
payout_eligible: None,
|
||||
should_add_next_step_to_process_tracker: false,
|
||||
error_code: None,
|
||||
error_message: None,
|
||||
payout_connector_metadata: None,
|
||||
}),
|
||||
..item.data
|
||||
}),
|
||||
(None, Some(error)) => Ok(Self {
|
||||
status: common_enums::AttemptStatus::Failure,
|
||||
response: Ok(PayoutsResponseData {
|
||||
status: Some(enums::PayoutStatus::try_from(LastEvent::Error)?),
|
||||
connector_payout_id: Some(order_status.order_code),
|
||||
payout_eligible: None,
|
||||
should_add_next_step_to_process_tracker: false,
|
||||
error_code: Some(error.code),
|
||||
error_message: Some(error.message),
|
||||
payout_connector_metadata: None,
|
||||
}),
|
||||
..item.data
|
||||
}),
|
||||
_ => Err(
|
||||
errors::ConnectorError::UnexpectedResponseError(bytes::Bytes::from(
|
||||
"Either order_status.error or order_status.payment must be present in the response",
|
||||
))
|
||||
.into(),
|
||||
),
|
||||
}
|
||||
},
|
||||
(None, None, Some(ok_response)) => {
|
||||
let response = ok_response.refund_received.ok_or(
|
||||
errors::ConnectorError::UnexpectedResponseError(bytes::Bytes::from(
|
||||
"ok.refund_received must be present in the response",
|
||||
)),
|
||||
)?;
|
||||
|
||||
Ok(Self {
|
||||
response: Ok(PayoutsResponseData {
|
||||
status: Some(enums::PayoutStatus::try_from(LastEvent::RefundReceived)?),
|
||||
connector_payout_id: Some(response.order_code),
|
||||
payout_eligible: None,
|
||||
should_add_next_step_to_process_tracker: false,
|
||||
error_code: None,
|
||||
error_message: None,
|
||||
payout_connector_metadata: None,
|
||||
}),
|
||||
..item.data
|
||||
})
|
||||
}
|
||||
_ => Err(
|
||||
errors::ConnectorError::UnexpectedResponseError(bytes::Bytes::from(
|
||||
"Either reply.error or reply.ok must be present in the response",
|
||||
"Either reply.error or reply.order_status must be present in the response",
|
||||
))
|
||||
.into(),
|
||||
),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "payouts")]
|
||||
impl TryFrom<&PayoutsRouterData<PoSync>> for PaymentService {
|
||||
type Error = error_stack::Report<errors::ConnectorError>;
|
||||
fn try_from(item: &PayoutsRouterData<PoSync>) -> Result<Self, Self::Error> {
|
||||
let order_code = item.request.connector_payout_id.to_owned().ok_or(
|
||||
errors::ConnectorError::MissingRequiredField {
|
||||
field_name: "order_code",
|
||||
},
|
||||
)?;
|
||||
|
||||
let auth = WorldpayxmlAuthType::try_from(&item.connector_auth_type)
|
||||
.change_context(errors::ConnectorError::FailedToObtainAuthType)?;
|
||||
|
||||
let inquiry = Some(Inquiry {
|
||||
order_inquiry: OrderInquiry { order_code },
|
||||
});
|
||||
|
||||
Ok(Self {
|
||||
version: worldpayxml_constants::WORLDPAYXML_VERSION.to_string(),
|
||||
merchant_code: auth.merchant_code.clone(),
|
||||
submit: None,
|
||||
reply: None,
|
||||
inquiry,
|
||||
modify: None,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "payouts")]
|
||||
impl TryFrom<PayoutsResponseRouterData<PoSync, PaymentService>> for PayoutsRouterData<PoSync> {
|
||||
type Error = error_stack::Report<errors::ConnectorError>;
|
||||
fn try_from(
|
||||
item: PayoutsResponseRouterData<PoSync, PaymentService>,
|
||||
) -> Result<Self, Self::Error> {
|
||||
let reply = item
|
||||
.response
|
||||
.reply
|
||||
.ok_or(errors::ConnectorError::UnexpectedResponseError(
|
||||
bytes::Bytes::from("Missing reply data".to_string()),
|
||||
))?;
|
||||
|
||||
match (reply.error, reply.order_status) {
|
||||
(Some(error), None) => Ok(Self {
|
||||
status: common_enums::AttemptStatus::Failure,
|
||||
response: Err(ErrorResponse {
|
||||
code: error.code,
|
||||
message: error.message.clone(),
|
||||
reason: Some(error.message.clone()),
|
||||
status_code: item.http_code,
|
||||
attempt_status: None,
|
||||
connector_transaction_id: None,
|
||||
network_advice_code: None,
|
||||
network_decline_code: None,
|
||||
network_error_message: None,
|
||||
connector_metadata: None,
|
||||
}),
|
||||
..item.data
|
||||
}),
|
||||
(None, Some(order_status)) => {
|
||||
match (order_status.payment, order_status.error) {
|
||||
(Some(payment), None) => Ok(Self {
|
||||
response: Ok(PayoutsResponseData {
|
||||
status: Some(enums::PayoutStatus::try_from(payment.last_event)?),
|
||||
connector_payout_id: Some(order_status.order_code),
|
||||
payout_eligible: None,
|
||||
should_add_next_step_to_process_tracker: false,
|
||||
error_code: None,
|
||||
error_message: None,
|
||||
payout_connector_metadata: None,
|
||||
}),
|
||||
..item.data
|
||||
}),
|
||||
(None, Some(_error)) => Ok(Self {
|
||||
status: item.data.status,
|
||||
response: Ok(PayoutsResponseData {
|
||||
status: None,
|
||||
connector_payout_id: Some(order_status.order_code),
|
||||
payout_eligible: None,
|
||||
should_add_next_step_to_process_tracker: false,
|
||||
error_code: None,
|
||||
error_message: None,
|
||||
payout_connector_metadata: None,
|
||||
}),
|
||||
..item.data
|
||||
}),
|
||||
_ => Err(
|
||||
errors::ConnectorError::UnexpectedResponseError(bytes::Bytes::from(
|
||||
"Either order_status.error or order_status.payment must be present in the response",
|
||||
))
|
||||
.into(),
|
||||
),
|
||||
}
|
||||
},
|
||||
_ => Err(
|
||||
errors::ConnectorError::UnexpectedResponseError(bytes::Bytes::from(
|
||||
"Either reply.error or reply.order_status must be present in the response",
|
||||
))
|
||||
.into(),
|
||||
),
|
||||
@@ -1793,7 +1934,7 @@ impl TryFrom<PayoutsResponseRouterData<PoCancel, PayoutResponse>> for PayoutsRou
|
||||
(Some(error), None) => Ok(Self {
|
||||
status: common_enums::AttemptStatus::Failure,
|
||||
response: Ok(PayoutsResponseData {
|
||||
status: Some(enums::PayoutStatus::from(PayoutOutcome::Error)),
|
||||
status: Some(enums::PayoutStatus::try_from(LastEvent::Error)?),
|
||||
connector_payout_id: None,
|
||||
payout_eligible: None,
|
||||
should_add_next_step_to_process_tracker: false,
|
||||
@@ -1803,18 +1944,26 @@ impl TryFrom<PayoutsResponseRouterData<PoCancel, PayoutResponse>> for PayoutsRou
|
||||
}),
|
||||
..item.data
|
||||
}),
|
||||
(None, Some(ok_status)) => Ok(Self {
|
||||
response: Ok(PayoutsResponseData {
|
||||
status: Some(enums::PayoutStatus::from(PayoutOutcome::CancelReceived)),
|
||||
connector_payout_id: ok_status.refund_received.map(|id| id.order_code),
|
||||
payout_eligible: None,
|
||||
should_add_next_step_to_process_tracker: false,
|
||||
error_code: None,
|
||||
error_message: None,
|
||||
payout_connector_metadata: None,
|
||||
}),
|
||||
..item.data
|
||||
}),
|
||||
(None, Some(ok_status)) => {
|
||||
let response = ok_status.cancel_received.ok_or(
|
||||
errors::ConnectorError::UnexpectedResponseError(bytes::Bytes::from(
|
||||
"ok.cancel_received must be present in the response",
|
||||
)),
|
||||
)?;
|
||||
|
||||
Ok(Self {
|
||||
response: Ok(PayoutsResponseData {
|
||||
status: Some(enums::PayoutStatus::try_from(LastEvent::CancelReceived)?),
|
||||
connector_payout_id: Some(response.order_code),
|
||||
payout_eligible: None,
|
||||
should_add_next_step_to_process_tracker: false,
|
||||
error_code: None,
|
||||
error_message: None,
|
||||
payout_connector_metadata: None,
|
||||
}),
|
||||
..item.data
|
||||
})
|
||||
}
|
||||
_ => Err(
|
||||
errors::ConnectorError::UnexpectedResponseError(bytes::Bytes::from(
|
||||
"Either reply.error or reply.ok must be present in the response",
|
||||
@@ -1985,12 +2134,7 @@ pub fn get_payout_webhook_event(status: LastEvent) -> api_models::webhooks::Inco
|
||||
LastEvent::Refused | LastEvent::RefundFailed => {
|
||||
api_models::webhooks::IncomingWebhookEvent::PayoutFailure
|
||||
}
|
||||
LastEvent::Authorised
|
||||
| LastEvent::Settled
|
||||
| LastEvent::Captured
|
||||
| LastEvent::SentForAuthorisation => {
|
||||
api_models::webhooks::IncomingWebhookEvent::EventNotSupported
|
||||
}
|
||||
_ => api_models::webhooks::IncomingWebhookEvent::EventNotSupported,
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -4447,7 +4447,6 @@ default_imp_for_payouts_retrieve!(
|
||||
connectors::Worldline,
|
||||
connectors::Worldpay,
|
||||
connectors::Worldpayvantiv,
|
||||
connectors::Worldpayxml,
|
||||
connectors::Wellsfargo,
|
||||
connectors::Wellsfargopayout,
|
||||
connectors::Volt,
|
||||
@@ -4889,7 +4888,6 @@ default_imp_for_payouts_cancel!(
|
||||
connectors::Worldline,
|
||||
connectors::Worldpay,
|
||||
connectors::Worldpayvantiv,
|
||||
// connectors::Worldpayxml,
|
||||
connectors::Wellsfargo,
|
||||
connectors::Wellsfargopayout,
|
||||
connectors::Volt,
|
||||
|
||||
Reference in New Issue
Block a user