Skip to content
23 changes: 17 additions & 6 deletions crates/hyperswitch_connectors/src/connectors/finix.rs
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,9 @@ use crate::{
types::ResponseRouterData, utils,
};

const FINIX_REFERRER_SOURCE_HEADER: &str = "X-Finix-Referrer-Source";
const FINIX_REFERRER_SOURCE_VALUE: &str = "PLUGIN_HYPERSWITCH";

#[derive(Clone)]
pub struct Finix {
amount_converter: &'static (dyn AmountConvertor<Output = MinorUnit> + Sync),
Expand Down Expand Up @@ -268,10 +271,16 @@ where
_connectors: &Connectors,
) -> CustomResult<Vec<(String, hyperswitch_masking::Maskable<String>)>, errors::ConnectorError>
{
let mut header = vec![(
headers::CONTENT_TYPE.to_string(),
self.get_content_type().to_string().into(),
)];
let mut header = vec![
(
headers::CONTENT_TYPE.to_string(),
self.get_content_type().to_string().into(),
),
(
FINIX_REFERRER_SOURCE_HEADER.to_string(),
FINIX_REFERRER_SOURCE_VALUE.to_string().into(),
),
];
let mut api_key = self.get_auth_header(&req.connector_auth_type)?;
header.append(&mut api_key);
Ok(header)
Expand Down Expand Up @@ -1199,14 +1208,16 @@ impl webhooks::IncomingWebhook for Finix {
fn get_dispute_details(
&self,
request: &webhooks::IncomingWebhookRequestDetails<'_>,
_context: Option<&webhooks::WebhookContext>,
context: Option<&webhooks::WebhookContext>,
) -> CustomResult<DisputePayload, errors::ConnectorError> {
let webhook_body: finix::FinixWebhookBody =
request
.body
.parse_struct("FinixWebhookBody")
.change_context(errors::ConnectorError::WebhookBodyDecodingFailed)?;
webhook_body.get_dispute_details()
let payment_currency =
context.and_then(|webhook_context| webhook_context.get_payment_context().currency);
webhook_body.get_dispute_details(payment_currency)
}
fn get_webhook_resource_object(
&self,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -726,6 +726,7 @@ impl FinixErrorResponse {
.unwrap_or(consts::NO_ERROR_MESSAGE.to_string())
}
}

impl FinixWebhookBody {
pub fn get_webhook_object_reference_id(
&self,
Expand All @@ -747,13 +748,19 @@ impl FinixWebhookBody {
RefundIdType::ConnectorRefundId(transfer.id.to_string()),
))
}
// finix platform fee ignored
Some(FinixPaymentType::FEE) => {
Err(ConnectorError::WebhookEventTypeNotFound.into())
Some(FinixPaymentType::DEBIT) => {
Ok(api_models::webhooks::ObjectReferenceId::PaymentId(
PaymentIdType::ConnectorTransactionId(transfer.id.to_string()),
))
}
_ => Ok(api_models::webhooks::ObjectReferenceId::PaymentId(
PaymentIdType::ConnectorTransactionId(transfer.id.to_string()),
)),
Some(FinixPaymentType::DISPUTE)
| Some(FinixPaymentType::ADJUSTMENT)
| Some(FinixPaymentType::FEE)
| Some(FinixPaymentType::CREDIT)
| Some(FinixPaymentType::RESERVE)
| Some(FinixPaymentType::SETTLEMENT)
| Some(FinixPaymentType::UNKNOWN)
| None => Err(ConnectorError::WebhookEventTypeNotFound.into()),
}
}

Expand All @@ -764,6 +771,7 @@ impl FinixWebhookBody {
PaymentIdType::ConnectorTransactionId(dispute.transfer.to_string()),
))
}
FinixEmbedded::Evidences { .. } => Err(ConnectorError::WebhookEventTypeNotFound.into()),
}
}
pub fn get_webhook_event_type(&self) -> CustomResult<IncomingWebhookEvent, ConnectorError> {
Expand Down Expand Up @@ -795,22 +803,32 @@ impl FinixWebhookBody {
FinixEmbedded::Transfers { transfers } => {
let transfers = transfers.get_first_event()?;

if transfers.payment_type == Some(FinixPaymentType::REVERSAL) {
match transfers.state {
match transfers.payment_type {
Some(FinixPaymentType::REVERSAL) => match transfers.state {
FinixState::SUCCEEDED => Ok(IncomingWebhookEvent::RefundSuccess),
FinixState::PENDING => Ok(IncomingWebhookEvent::EventNotSupported),
FinixState::FAILED | FinixState::CANCELED | FinixState::UNKNOWN => {
Ok(IncomingWebhookEvent::RefundFailure)
}
}
} else {
match transfers.state {
},
Some(FinixPaymentType::DEBIT) => match transfers.state {
FinixState::PENDING => Ok(IncomingWebhookEvent::PaymentIntentProcessing),
FinixState::SUCCEEDED => Ok(IncomingWebhookEvent::PaymentIntentSuccess),
FinixState::FAILED | FinixState::CANCELED | FinixState::UNKNOWN => {
FinixState::FAILED | FinixState::CANCELED => {
Ok(IncomingWebhookEvent::PaymentIntentFailure)
}
}

FinixState::UNKNOWN => Ok(IncomingWebhookEvent::EventNotSupported),
},

Some(FinixPaymentType::DISPUTE)
| Some(FinixPaymentType::ADJUSTMENT)
| Some(FinixPaymentType::FEE)
| Some(FinixPaymentType::CREDIT)
| Some(FinixPaymentType::RESERVE)
| Some(FinixPaymentType::SETTLEMENT)
| Some(FinixPaymentType::UNKNOWN)
| None => Ok(IncomingWebhookEvent::EventNotSupported),
}
}
FinixEmbedded::Disputes { disputes } => {
Expand All @@ -823,21 +841,28 @@ impl FinixWebhookBody {
FinixDisputeState::WON => Ok(IncomingWebhookEvent::DisputeWon),
}
}
FinixEmbedded::Evidences { .. } => Ok(IncomingWebhookEvent::EventNotSupported),
}
}

pub fn get_dispute_details(&self) -> CustomResult<DisputePayload, ConnectorError> {
pub fn get_dispute_details(
&self,
payment_currency: Option<enums::Currency>,
) -> CustomResult<DisputePayload, ConnectorError> {
match &self.webhook_embedded {
FinixEmbedded::Disputes { disputes } => {
let dispute = disputes.get_first_event()?;
let currency = payment_currency.ok_or(ConnectorError::MissingRequiredField {
field_name: "currency",
})?;
let amount = utils::convert_amount(
super::Finix::new().amount_converter_webhooks,
dispute.amount,
dispute.currency,
currency,
)?;
Ok(DisputePayload {
amount,
currency: dispute.currency,
currency,
dispute_stage: DisputeStage::Dispute,
connector_status: dispute.state.to_string(),
connector_dispute_id: dispute.id,
Expand All @@ -848,10 +873,10 @@ impl FinixWebhookBody {
updated_at: dispute.updated_at,
})
}
FinixEmbedded::Authorizations { .. } | FinixEmbedded::Transfers { .. } => {
Err(ConnectorError::ResponseDeserializationFailed)
.attach_printable("Expected Dispute webhooks, but found other webhooks")?
}
FinixEmbedded::Authorizations { .. }
| FinixEmbedded::Transfers { .. }
| FinixEmbedded::Evidences { .. } => Err(ConnectorError::ResponseDeserializationFailed)
.attach_printable("Expected Dispute webhooks, but found other webhooks")?,
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ pub struct FinixPaymentsResponse {
pub messages: Option<Vec<String>>,
pub failure_message: Option<String>,
pub transfer: Option<String>,
pub tags: FinixTags,
pub tags: Option<FinixTags>,
#[serde(rename = "type")]
pub payment_type: Option<FinixPaymentType>,
// pub trace_id: String,
Expand Down Expand Up @@ -53,7 +53,9 @@ impl FinixCombinedPaymentResponse {
authorizations.get_first_event()
}
FinixEmbedded::Transfers { transfers } => transfers.get_first_event(),
FinixEmbedded::Disputes { .. } => Err(ConnectorError::ResponseHandlingFailed),
FinixEmbedded::Disputes { .. } | FinixEmbedded::Evidences { .. } => {
Err(ConnectorError::ResponseHandlingFailed)
}
},
}
}
Expand Down Expand Up @@ -124,20 +126,38 @@ pub enum FinixDisputeState {
#[derive(Clone, Debug, Serialize, Deserialize)]

pub struct FinixDisputes {
pub transfer: String,
pub reason: Option<String>,
pub amount: MinorUnit,
pub state: FinixDisputeState,
pub currency: Currency,
pub id: String,
#[serde(default, with = "common_utils::custom_serde::iso8601::option")]
pub created_at: Option<PrimitiveDateTime>,
pub message: Option<String>,
pub tags: Option<FinixTags>,
pub occurred_at: Option<String>,
pub dispute_details: Option<FinixDisputeDetails>,
pub transfer: String,
pub application: Option<String>,
#[serde(default, with = "common_utils::custom_serde::iso8601::option")]
pub updated_at: Option<PrimitiveDateTime>,
pub identity: Option<String>,
pub action: Option<String>,
pub id: String,
pub state: FinixDisputeState,
#[serde(default, with = "common_utils::custom_serde::iso8601::option")]
pub respond_by: Option<PrimitiveDateTime>,
}

#[derive(Clone, Debug, Serialize, Deserialize)]
pub struct FinixDisputeDetails {
pub arn: Option<String>,
}

#[derive(Clone, Debug, Serialize, Deserialize)]
pub struct FinixEvidence {
pub dispute: String,
pub id: String,
pub state: String,
}

#[derive(Clone, Debug, Serialize, Deserialize)]
pub struct SingleEventType<T>(Vec<T>);
impl<T: Clone> SingleEventType<T> {
Expand All @@ -161,6 +181,9 @@ pub enum FinixEmbedded {
Disputes {
disputes: SingleEventType<FinixDisputes>,
},
Evidences {
evidences: SingleEventType<FinixEvidence>,
},
}
#[derive(Clone, Debug, Serialize, Deserialize)]

Expand Down
Loading