Skip to content

Commit

Permalink
Inespay webhook fix
Browse files Browse the repository at this point in the history
  • Loading branch information
ImSagnik007 committed Jan 15, 2025
1 parent 5f20415 commit a795500
Show file tree
Hide file tree
Showing 3 changed files with 126 additions and 94 deletions.
52 changes: 33 additions & 19 deletions crates/hyperswitch_connectors/src/connectors/inespay.rs
Original file line number Diff line number Diff line change
@@ -1,14 +1,14 @@
pub mod transformers;

use base64::Engine;
use common_utils::{
consts::BASE64_ENGINE,
crypto,
errors::CustomResult,
ext_traits::{ByteSliceExt, BytesExt},
request::{Method, Request, RequestBuilder, RequestContent},
types::{AmountConvertor, StringMinorUnit, StringMinorUnitForConnector},
};
use base64::Engine;
use common_utils::consts::BASE64_ENGINE;
use error_stack::ResultExt;
use hyperswitch_domain_models::{
router_data::{AccessToken, ConnectorAuthType, ErrorResponse, RouterData},
Expand Down Expand Up @@ -40,8 +40,8 @@ use hyperswitch_interfaces::{
webhooks,
};
use masking::{ExposeInterface, Mask, Secret};
use transformers as inespay;
use ring::hmac;
use transformers as inespay;

use crate::{constants::headers, types::ResponseRouterData, utils};

Expand Down Expand Up @@ -571,12 +571,15 @@ impl ConnectorIntegration<RSync, RefundsData, RefundsResponseData> for Inespay {
fn get_webhook_body(
body: &[u8],
) -> CustomResult<inespay::InespayWebhookEventData, errors::ConnectorError> {
let notif_item:inespay::InespayWebhookEvent = serde_urlencoded::from_bytes::<inespay::InespayWebhookEvent>(body)
.change_context(errors::ConnectorError::WebhookBodyDecodingFailed)?;
let notif_item: inespay::InespayWebhookEvent =
serde_urlencoded::from_bytes::<inespay::InespayWebhookEvent>(body)
.change_context(errors::ConnectorError::WebhookBodyDecodingFailed)?;
let encoded_data_return = notif_item.data_return;
let decoded_data_return = BASE64_ENGINE.decode(encoded_data_return)
let decoded_data_return = BASE64_ENGINE
.decode(encoded_data_return)
.change_context(errors::ConnectorError::WebhookBodyDecodingFailed)?;
let data_return:inespay::InespayWebhookEventData = decoded_data_return.parse_struct("inespay InespayWebhookEventData")
let data_return: inespay::InespayWebhookEventData = decoded_data_return
.parse_struct("inespay InespayWebhookEventData")
.change_context(errors::ConnectorError::WebhookBodyDecodingFailed)?;
Ok(data_return)
}
Expand Down Expand Up @@ -609,7 +612,7 @@ impl webhooks::IncomingWebhook for Inespay {
) -> CustomResult<Vec<u8>, errors::ConnectorError> {
let notif_item = serde_urlencoded::from_bytes::<inespay::InespayWebhookEvent>(request.body)
.change_context(errors::ConnectorError::WebhookBodyDecodingFailed)?;

Ok(notif_item.data_return.into_bytes())
}

Expand Down Expand Up @@ -637,7 +640,7 @@ impl webhooks::IncomingWebhook for Inespay {
&connector_webhook_secrets,
)?;
let secret = connector_webhook_secrets.secret;

let signing_key = hmac::Key::new(hmac::HMAC_SHA256, &secret);
let signed_message = hmac::sign(&signing_key, &message);
let computed_signature = hex::encode(signed_message.as_ref());
Expand All @@ -652,12 +655,18 @@ impl webhooks::IncomingWebhook for Inespay {
let data_return = get_webhook_body(request.body)
.change_context(errors::ConnectorError::WebhookBodyDecodingFailed)?;
match data_return {
inespay::InespayWebhookEventData::Payment(data)=> Ok(api_models::webhooks::ObjectReferenceId::PaymentId(
api_models::payments::PaymentIdType::ConnectorTransactionId(data.single_payin_id),
)),
inespay::InespayWebhookEventData::Refund(data)=> Ok(api_models::webhooks::ObjectReferenceId::RefundId(
api_models::webhooks::RefundIdType::ConnectorRefundId(data.refund_id),
))
inespay::InespayWebhookEventData::Payment(data) => {
Ok(api_models::webhooks::ObjectReferenceId::PaymentId(
api_models::payments::PaymentIdType::ConnectorTransactionId(
data.single_payin_id,
),
))
}
inespay::InespayWebhookEventData::Refund(data) => {
Ok(api_models::webhooks::ObjectReferenceId::RefundId(
api_models::webhooks::RefundIdType::ConnectorRefundId(data.refund_id),
))
}
}
}

Expand All @@ -667,7 +676,9 @@ impl webhooks::IncomingWebhook for Inespay {
) -> CustomResult<api_models::webhooks::IncomingWebhookEvent, errors::ConnectorError> {
let data_return = get_webhook_body(request.body)
.change_context(errors::ConnectorError::WebhookBodyDecodingFailed)?;
Ok(api_models::webhooks::IncomingWebhookEvent::from(data_return))
Ok(api_models::webhooks::IncomingWebhookEvent::from(
data_return,
))
}

fn get_webhook_resource_object(
Expand All @@ -677,10 +688,13 @@ impl webhooks::IncomingWebhook for Inespay {
let data_return = get_webhook_body(request.body)
.change_context(errors::ConnectorError::WebhookBodyDecodingFailed)?;
Ok(match data_return {
inespay::InespayWebhookEventData::Payment(payment_webhook_data)=> Box::new(payment_webhook_data),
inespay::InespayWebhookEventData::Refund(refund_webhook_data)=> Box::new(refund_webhook_data),
inespay::InespayWebhookEventData::Payment(payment_webhook_data) => {
Box::new(payment_webhook_data)
}
inespay::InespayWebhookEventData::Refund(refund_webhook_data) => {
Box::new(refund_webhook_data)
}
})

}
}

Expand Down
167 changes: 92 additions & 75 deletions crates/hyperswitch_connectors/src/connectors/inespay/transformers.rs
Original file line number Diff line number Diff line change
@@ -1,9 +1,12 @@
use common_enums::enums;
use common_utils::{request::Method, types::{StringMinorUnit, StringMinorUnitForConnector, MinorUnit}};
use common_utils::{
request::Method,
types::{MinorUnit, StringMinorUnit, StringMinorUnitForConnector},
};
use error_stack::ResultExt;
use hyperswitch_domain_models::{
payment_method_data::{BankDebitData, PaymentMethodData},
router_data::{ErrorResponse, ConnectorAuthType, RouterData},
router_data::{ConnectorAuthType, ErrorResponse, RouterData},
router_flow_types::refunds::{Execute, RSync},
router_request_types::ResponseId,
router_response_types::{PaymentsResponseData, RedirectForm, RefundsResponseData},
Expand Down Expand Up @@ -107,11 +110,11 @@ impl<F, T> TryFrom<ResponseRouterData<F, InespayPaymentsResponse, T, PaymentsRes
item: ResponseRouterData<F, InespayPaymentsResponse, T, PaymentsResponseData>,
) -> Result<Self, Self::Error> {
let (status, response) = match item.response {
InespayPaymentsResponse::InespayPaymentsData(data)=>{
InespayPaymentsResponse::InespayPaymentsData(data) => {
let redirection_url = Url::parse(data.single_payin_link.as_str())
.change_context(errors::ConnectorError::ParsingFailed)?;
.change_context(errors::ConnectorError::ParsingFailed)?;
let redirection_data = RedirectForm::from((redirection_url, Method::Get));

(
common_enums::AttemptStatus::AuthenticationPending,
Ok(PaymentsResponseData::TransactionResponse {
Expand All @@ -125,22 +128,20 @@ impl<F, T> TryFrom<ResponseRouterData<F, InespayPaymentsResponse, T, PaymentsRes
connector_response_reference_id: None,
incremental_authorization_allowed: None,
charge_id: None,
})
)

}
InespayPaymentsResponse::InespayPaymentsError(data)=>{
(common_enums::AttemptStatus::Failure,
Err(ErrorResponse {
code: data.status.clone(),
message: data.status_desc.clone(),
reason: Some(data.status_desc.clone()),
attempt_status: None,
connector_transaction_id: None,
status_code: item.http_code,
})
}),
)
}
InespayPaymentsResponse::InespayPaymentsError(data) => (
common_enums::AttemptStatus::Failure,
Err(ErrorResponse {
code: data.status.clone(),
message: data.status_desc.clone(),
reason: Some(data.status_desc.clone()),
attempt_status: None,
connector_transaction_id: None,
status_code: item.http_code,
}),
),
};
Ok(Self {
status,
Expand Down Expand Up @@ -203,6 +204,7 @@ pub struct InespayPSyncResponseData {
#[serde(untagged)]
pub enum InespayPSyncResponse {
InespayPSyncData(InespayPSyncResponseData),
InespayPSyncWebhook(InespayPaymentWebhookData),
InespayPSyncError(InespayErrorResponse),
}

Expand Down Expand Up @@ -236,21 +238,37 @@ impl<F, T> TryFrom<ResponseRouterData<F, InespayPSyncResponse, T, PaymentsRespon
..item.data
})
}
InespayPSyncResponse::InespayPSyncError(data) => {
InespayPSyncResponse::InespayPSyncWebhook(data) => {
let status = enums::AttemptStatus::from(data.cod_status);
Ok(Self {
response: Err(ErrorResponse {
code: data.status.clone(),
message: data.status_desc.clone(),
reason: Some(data.status_desc.clone()),
attempt_status: None,
connector_transaction_id: None,
status_code: item.http_code,
status,
response: Ok(PaymentsResponseData::TransactionResponse {
resource_id: ResponseId::ConnectorTransactionId(
data.single_payin_id.clone(),
),
redirection_data: Box::new(None),
mandate_reference: Box::new(None),
connector_metadata: None,
network_txn_id: None,
connector_response_reference_id: None,
incremental_authorization_allowed: None,
charge_id: None,
}),
..item.data
})
}
InespayPSyncResponse::InespayPSyncError(data) => Ok(Self {
response: Err(ErrorResponse {
code: data.status.clone(),
message: data.status_desc.clone(),
reason: Some(data.status_desc.clone()),
attempt_status: None,
connector_transaction_id: None,
status_code: item.http_code,
}),
..item.data
}),
}

}
}

Expand Down Expand Up @@ -296,7 +314,7 @@ impl From<InespayRSyncStatus> for enums::RefundStatus {
InespayRSyncStatus::Rejected
| InespayRSyncStatus::Denied
| InespayRSyncStatus::Reversed
| InespayRSyncStatus::Mistake => Self::Failure
| InespayRSyncStatus::Mistake => Self::Failure,
}
}
}
Expand All @@ -316,34 +334,32 @@ pub enum InespayRefundsResponse {
InespayRefundsError(InespayErrorResponse),
}

impl TryFrom<RefundsResponseRouterData<Execute, InespayRefundsResponse>> for RefundsRouterData<Execute> {
impl TryFrom<RefundsResponseRouterData<Execute, InespayRefundsResponse>>
for RefundsRouterData<Execute>
{
type Error = error_stack::Report<errors::ConnectorError>;
fn try_from(
item: RefundsResponseRouterData<Execute, InespayRefundsResponse>,
) -> Result<Self, Self::Error> {
match item.response {
InespayRefundsResponse::InespayRefundsData(data) => {
Ok(Self {
response: Ok(RefundsResponseData {
connector_refund_id: data.refund_id,
refund_status: enums::RefundStatus::Pending,
}),
..item.data
})
}
InespayRefundsResponse::InespayRefundsError(data) => {
Ok(Self {
response: Err(ErrorResponse {
code: data.status.clone(),
message: data.status_desc.clone(),
reason: Some(data.status_desc.clone()),
attempt_status: None,
connector_transaction_id: None,
status_code: item.http_code,
}),
..item.data
})
}
InespayRefundsResponse::InespayRefundsData(data) => Ok(Self {
response: Ok(RefundsResponseData {
connector_refund_id: data.refund_id,
refund_status: enums::RefundStatus::Pending,
}),
..item.data
}),
InespayRefundsResponse::InespayRefundsError(data) => Ok(Self {
response: Err(ErrorResponse {
code: data.status.clone(),
message: data.status_desc.clone(),
reason: Some(data.status_desc.clone()),
attempt_status: None,
connector_transaction_id: None,
status_code: item.http_code,
}),
..item.data
}),
}
}
}
Expand All @@ -360,6 +376,7 @@ pub struct InespayRSyncResponseData {
#[serde(untagged)]
pub enum InespayRSyncResponse {
InespayRSyncData(InespayRSyncResponseData),
InespayRSyncWebhook(InespayRefundWebhookData),
InespayRSyncError(InespayErrorResponse),
}

Expand All @@ -369,22 +386,22 @@ impl TryFrom<RefundsResponseRouterData<RSync, InespayRSyncResponse>> for Refunds
item: RefundsResponseRouterData<RSync, InespayRSyncResponse>,
) -> Result<Self, Self::Error> {
let response = match item.response {
InespayRSyncResponse::InespayRSyncData(data) => {
Ok(RefundsResponseData {
connector_refund_id: data.refund_id,
refund_status: enums::RefundStatus::from(data.cod_status),
})
}
InespayRSyncResponse::InespayRSyncError(data) => {
Err(ErrorResponse {
code: data.status.clone(),
message: data.status_desc.clone(),
reason: Some(data.status_desc.clone()),
attempt_status: None,
connector_transaction_id: None,
status_code: item.http_code,
})
}
InespayRSyncResponse::InespayRSyncData(data) => Ok(RefundsResponseData {
connector_refund_id: data.refund_id,
refund_status: enums::RefundStatus::from(data.cod_status),
}),
InespayRSyncResponse::InespayRSyncWebhook(data) => Ok(RefundsResponseData {
connector_refund_id: data.refund_id,
refund_status: enums::RefundStatus::from(data.cod_status),
}),
InespayRSyncResponse::InespayRSyncError(data) => Err(ErrorResponse {
code: data.status.clone(),
message: data.status_desc.clone(),
reason: Some(data.status_desc.clone()),
attempt_status: None,
connector_transaction_id: None,
status_code: item.http_code,
}),
};
Ok(Self {
response,
Expand Down Expand Up @@ -443,21 +460,21 @@ impl From<InespayWebhookEventData> for api_models::webhooks::IncomingWebhookEven
fn from(item: InespayWebhookEventData) -> Self {
match item {
InespayWebhookEventData::Payment(payment_data) => match payment_data.cod_status {
InespayPSyncStatus::Ok
| InespayPSyncStatus::Settled => Self::PaymentIntentSuccess,
InespayPSyncStatus::Failed
| InespayPSyncStatus::Rejected => Self::PaymentIntentFailure,
InespayPSyncStatus::Ok | InespayPSyncStatus::Settled => Self::PaymentIntentSuccess,
InespayPSyncStatus::Failed | InespayPSyncStatus::Rejected => {
Self::PaymentIntentFailure
}
InespayPSyncStatus::Created
| InespayPSyncStatus::Opened
| InespayPSyncStatus::BankSelected
| InespayPSyncStatus::Initiated
| InespayPSyncStatus::Pending
| InespayPSyncStatus::Unfinished
| InespayPSyncStatus::PartiallyAccepted => Self::PaymentIntentProcessing,
InespayPSyncStatus::Aborted
InespayPSyncStatus::Aborted
| InespayPSyncStatus::Cancelled
| InespayPSyncStatus::PartRefunded
| InespayPSyncStatus::Refunded => Self::EventNotSupported
| InespayPSyncStatus::PartRefunded
| InespayPSyncStatus::Refunded => Self::EventNotSupported,
},
InespayWebhookEventData::Refund(refund_data) => match refund_data.cod_status {
InespayRSyncStatus::Confirmed => Self::RefundSuccess,
Expand Down
1 change: 1 addition & 0 deletions crates/hyperswitch_connectors/src/connectors/novalnet.rs
Original file line number Diff line number Diff line change
Expand Up @@ -145,6 +145,7 @@ impl ConnectorCommon for Novalnet {

event_builder.map(|i| i.set_response_body(&response));
router_env::logger::info!(connector_response=?response);

Ok(ErrorResponse {
status_code: res.status_code,
code: response.code,
Expand Down

0 comments on commit a795500

Please sign in to comment.