Issue:
Bug: feat(connector):[Authorizedotnet] Capture flow for Authorizedotnet



Manual Capture Flow for Authorizedotnet

Pull request description:
## Type of Change
<!-- Put an `x` in the boxes that apply -->

- [ ] Bugfix
- [x] New feature
- [ ] Enhancement
- [ ] Refactoring
- [ ] Dependency updates
- [ ] Documentation
- [ ] CI/CD

## Description
<!-- Describe your changes in detail -->
This PR modifies following changes 
1)add capture flow to authorizedotnet
2)add unit tests for authorizedotnet
3)refactor exisiting code for authorizedotnet
4)Payments and refund Webhooks #1176

**Note** :To update the status after authorization, we need to make a synchronous call with the connector, as the response returned in the authorize call doesn't contain sufficient information to map the status to "authorized" or "capture_initiated". The final status of the payment will be updated within one day. Therefore, the status remains as "processing" for capture.

### Additional Changes

- [ ] This PR modifies the API contract
- [ ] This PR modifies the database schema
- [ ] This PR modifies application configuration/environment variables

<!-- 
Provide links to the files with corresponding changes.

Following are the paths where you can find config files:
1. `config`
2. `crates/router/src/configs`
3. `loadtest/config`
-->

## Motivation and Context
<!--
Why is this change required? What problem does it solve?
If it fixes an open issue, please link to the issue here.

If you don't have an issue, we'd recommend starting with one first so the PR
can focus on the implementation (unless its an obvious bug or documentation fix
that will have little conversation).
-->

## How did you test it?
<!--
Did you write an integration/unit/API test to verify the code changes?
Or did you test this change manually (provide relevant screenshots)?
-->

<img width="1311" alt="Screenshot 2023-05-16 at 2 11 42 AM" src="https://github.com/juspay/hyperswitch/assets/121822803/7bd1769a-57a3-4de6-a096-71e410864d05">


## Checklist
<!-- Put an `x` in the boxes that apply -->

- [x] I formatted the code `cargo +nightly fmt --all`
- [x] I addressed lints thrown by `cargo clippy`
- [x] I reviewed submitted code
- [x] I added unit tests for my changes where possible
- [ ] I added a [CHANGELOG](/CHANGELOG.md) entry if applicable


Testing:


<img width="1311" alt="Screenshot 2023-05-16 at 2 11 42 AM" src="https://github.com/juspay/hyperswitch/assets/121822803/7bd1769a-57a3-4de6-a096-71e410864d05">

Patch:
diff --git a/crates/router/src/connector/authorizedotnet.rs b/crates/router/src/connector/authorizedotnet.rs
index 3e443286773..83e96138833 100644
--- a/crates/router/src/connector/authorizedotnet.rs
+++ b/crates/router/src/connector/authorizedotnet.rs
@@ -3,6 +3,7 @@ mod transformers;
 
 use std::fmt::Debug;
 
+use common_utils::{crypto, ext_traits::ByteSliceExt};
 use error_stack::{IntoReport, ResultExt};
 use transformers as authorizedotnet;
 
@@ -10,11 +11,12 @@ use crate::{
     configs::settings,
     consts,
     core::errors::{self, CustomResult},
+    db::StorageInterface,
     headers,
-    services::{self, logger},
+    services::{self, ConnectorIntegration},
     types::{
         self,
-        api::{self, ConnectorCommon},
+        api::{self, ConnectorCommon, ConnectorCommonExt},
     },
     utils::{self, BytesExt},
 };
@@ -22,6 +24,22 @@ use crate::{
 #[derive(Debug, Clone)]
 pub struct Authorizedotnet;
 
+impl<Flow, Request, Response> ConnectorCommonExt<Flow, Request, Response> for Authorizedotnet
+where
+    Self: ConnectorIntegration<Flow, Request, Response>,
+{
+    fn build_headers(
+        &self,
+        _req: &types::RouterData<Flow, Request, Response>,
+        _connectors: &settings::Connectors,
+    ) -> CustomResult<Vec<(String, String)>, errors::ConnectorError> {
+        Ok(vec![(
+            headers::CONTENT_TYPE.to_string(),
+            self.get_content_type().to_string(),
+        )])
+    }
+}
+
 impl ConnectorCommon for Authorizedotnet {
     fn id(&self) -> &'static str {
         "authorizedotnet"
@@ -46,7 +64,7 @@ impl api::ConnectorAccessToken for Authorizedotnet {}
 impl api::PaymentToken for Authorizedotnet {}
 
 impl
-    services::ConnectorIntegration<
+    ConnectorIntegration<
         api::PaymentMethodToken,
         types::PaymentMethodTokenizationData,
         types::PaymentsResponseData,
@@ -55,62 +73,121 @@ impl
     // Not Implemented (R)
 }
 
-impl
-    services::ConnectorIntegration<
-        api::Session,
-        types::PaymentsSessionData,
-        types::PaymentsResponseData,
-    > for Authorizedotnet
+impl ConnectorIntegration<api::Session, types::PaymentsSessionData, types::PaymentsResponseData>
+    for Authorizedotnet
 {
     // Not Implemented (R)
 }
 
-impl
-    services::ConnectorIntegration<
-        api::AccessTokenAuth,
-        types::AccessTokenRequestData,
-        types::AccessToken,
-    > for Authorizedotnet
+impl ConnectorIntegration<api::AccessTokenAuth, types::AccessTokenRequestData, types::AccessToken>
+    for Authorizedotnet
 {
     // Not Implemented (R)
 }
 
 impl api::PreVerify for Authorizedotnet {}
 
-impl
-    services::ConnectorIntegration<
-        api::Verify,
-        types::VerifyRequestData,
-        types::PaymentsResponseData,
-    > for Authorizedotnet
+impl ConnectorIntegration<api::Verify, types::VerifyRequestData, types::PaymentsResponseData>
+    for Authorizedotnet
 {
     // Issue: #173
 }
 
-impl
-    services::ConnectorIntegration<
-        api::Capture,
-        types::PaymentsCaptureData,
-        types::PaymentsResponseData,
-    > for Authorizedotnet
+impl ConnectorIntegration<api::Capture, types::PaymentsCaptureData, types::PaymentsResponseData>
+    for Authorizedotnet
 {
-    // Not Implemented (R)
+    fn get_headers(
+        &self,
+        req: &types::PaymentsCaptureRouterData,
+        connectors: &settings::Connectors,
+    ) -> CustomResult<Vec<(String, String)>, errors::ConnectorError> {
+        self.build_headers(req, connectors)
+    }
+
+    fn get_content_type(&self) -> &'static str {
+        self.common_get_content_type()
+    }
+
+    fn get_url(
+        &self,
+        _req: &types::PaymentsCaptureRouterData,
+        connectors: &settings::Connectors,
+    ) -> CustomResult<String, errors::ConnectorError> {
+        Ok(self.base_url(connectors).to_string())
+    }
+    fn get_request_body(
+        &self,
+        req: &types::PaymentsCaptureRouterData,
+    ) -> CustomResult<Option<String>, errors::ConnectorError> {
+        let connector_req = authorizedotnet::CancelOrCaptureTransactionRequest::try_from(req)?;
+        let authorizedotnet_req =
+            utils::Encode::<authorizedotnet::CancelOrCaptureTransactionRequest>::encode_to_string_of_json(
+                &connector_req,
+            )
+            .change_context(errors::ConnectorError::RequestEncodingFailed)?;
+        Ok(Some(authorizedotnet_req))
+    }
+
+    fn build_request(
+        &self,
+        req: &types::PaymentsCaptureRouterData,
+        connectors: &settings::Connectors,
+    ) -> CustomResult<Option<services::Request>, errors::ConnectorError> {
+        Ok(Some(
+            services::RequestBuilder::new()
+                .method(services::Method::Post)
+                .url(&types::PaymentsCaptureType::get_url(self, req, connectors)?)
+                .attach_default_headers()
+                .headers(types::PaymentsCaptureType::get_headers(
+                    self, req, connectors,
+                )?)
+                .body(types::PaymentsCaptureType::get_request_body(self, req)?)
+                .build(),
+        ))
+    }
+
+    fn handle_response(
+        &self,
+        data: &types::PaymentsCaptureRouterData,
+        res: types::Response,
+    ) -> CustomResult<types::PaymentsCaptureRouterData, errors::ConnectorError> {
+        use bytes::Buf;
+
+        // Handle the case where response bytes contains U+FEFF (BOM) character sent by connector
+        let encoding = encoding_rs::UTF_8;
+        let intermediate_response = encoding.decode_with_bom_removal(res.response.chunk());
+        let intermediate_response =
+            bytes::Bytes::copy_from_slice(intermediate_response.0.as_bytes());
+
+        let response: authorizedotnet::AuthorizedotnetPaymentsResponse = intermediate_response
+            .parse_struct("AuthorizedotnetPaymentsResponse")
+            .change_context(errors::ConnectorError::ResponseDeserializationFailed)?;
+
+        types::RouterData::try_from(types::ResponseRouterData {
+            response,
+            data: data.clone(),
+            http_code: res.status_code,
+        })
+    }
+
+    fn get_error_response(
+        &self,
+        res: types::Response,
+    ) -> CustomResult<types::ErrorResponse, errors::ConnectorError> {
+        get_error_response(res)
+    }
 }
 
-impl
-    services::ConnectorIntegration<api::PSync, types::PaymentsSyncData, types::PaymentsResponseData>
+impl ConnectorIntegration<api::PSync, types::PaymentsSyncData, types::PaymentsResponseData>
     for Authorizedotnet
 {
     fn get_headers(
         &self,
-        _req: &types::PaymentsSyncRouterData,
-        _connectors: &settings::Connectors,
+        req: &types::PaymentsSyncRouterData,
+        connectors: &settings::Connectors,
     ) -> CustomResult<Vec<(String, String)>, errors::ConnectorError> {
         // This connector does not require an auth header, the authentication details are sent in the request body
-        Ok(vec![(
-            headers::CONTENT_TYPE.to_string(),
-            types::PaymentsSyncType::get_content_type(self).to_string(),
-        )])
+        self.build_headers(req, connectors)
     }
 
     fn get_content_type(&self) -> &'static str {
@@ -175,7 +252,6 @@ impl
             data: data.clone(),
             http_code: res.status_code,
         })
-        .change_context(errors::ConnectorError::ResponseHandlingFailed)
     }
 
     fn get_error_response(
@@ -186,23 +262,16 @@ impl
     }
 }
 
-impl
-    services::ConnectorIntegration<
-        api::Authorize,
-        types::PaymentsAuthorizeData,
-        types::PaymentsResponseData,
-    > for Authorizedotnet
+impl ConnectorIntegration<api::Authorize, types::PaymentsAuthorizeData, types::PaymentsResponseData>
+    for Authorizedotnet
 {
     fn get_headers(
         &self,
-        _req: &types::PaymentsAuthorizeRouterData,
-        _connectors: &settings::Connectors,
+        req: &types::PaymentsAuthorizeRouterData,
+        connectors: &settings::Connectors,
     ) -> CustomResult<Vec<(String, String)>, errors::ConnectorError> {
         // This connector does not require an auth header, the authentication details are sent in the request body
-        Ok(vec![(
-            headers::CONTENT_TYPE.to_string(),
-            types::PaymentsAuthorizeType::get_content_type(self).to_string(),
-        )])
+        self.build_headers(req, connectors)
     }
 
     fn get_content_type(&self) -> &'static str {
@@ -221,7 +290,6 @@ impl
         &self,
         req: &types::PaymentsAuthorizeRouterData,
     ) -> CustomResult<Option<String>, errors::ConnectorError> {
-        logger::debug!(request=?req);
         let connector_req = authorizedotnet::CreateTransactionRequest::try_from(req)?;
         let authorizedotnet_req =
             utils::Encode::<authorizedotnet::CreateTransactionRequest>::encode_to_string_of_json(
@@ -261,7 +329,6 @@ impl
         res: types::Response,
     ) -> CustomResult<types::PaymentsAuthorizeRouterData, errors::ConnectorError> {
         use bytes::Buf;
-        logger::debug!(authorizedotnetpayments_create_response=?res);
 
         // Handle the case where response bytes contains U+FEFF (BOM) character sent by connector
         let encoding = encoding_rs::UTF_8;
@@ -272,40 +339,30 @@ impl
         let response: authorizedotnet::AuthorizedotnetPaymentsResponse = intermediate_response
             .parse_struct("AuthorizedotnetPaymentsResponse")
             .change_context(errors::ConnectorError::ResponseDeserializationFailed)?;
-
         types::RouterData::try_from(types::ResponseRouterData {
             response,
             data: data.clone(),
             http_code: res.status_code,
         })
-        .change_context(errors::ConnectorError::ResponseDeserializationFailed)
     }
 
     fn get_error_response(
         &self,
         res: types::Response,
     ) -> CustomResult<types::ErrorResponse, errors::ConnectorError> {
-        logger::debug!(authorizedotnetpayments_create_error_response=?res);
         get_error_response(res)
     }
 }
 
-impl
-    services::ConnectorIntegration<
-        api::Void,
-        types::PaymentsCancelData,
-        types::PaymentsResponseData,
-    > for Authorizedotnet
+impl ConnectorIntegration<api::Void, types::PaymentsCancelData, types::PaymentsResponseData>
+    for Authorizedotnet
 {
     fn get_headers(
         &self,
-        _req: &types::PaymentsCancelRouterData,
-        _connectors: &settings::Connectors,
+        req: &types::PaymentsCancelRouterData,
+        connectors: &settings::Connectors,
     ) -> CustomResult<Vec<(String, String)>, errors::ConnectorError> {
-        Ok(vec![(
-            headers::CONTENT_TYPE.to_string(),
-            types::PaymentsAuthorizeType::get_content_type(self).to_string(),
-        )])
+        self.build_headers(req, connectors)
     }
 
     fn get_content_type(&self) -> &'static str {
@@ -324,9 +381,9 @@ impl
         &self,
         req: &types::PaymentsCancelRouterData,
     ) -> CustomResult<Option<String>, errors::ConnectorError> {
-        let connector_req = authorizedotnet::CancelTransactionRequest::try_from(req)?;
+        let connector_req = authorizedotnet::CancelOrCaptureTransactionRequest::try_from(req)?;
         let authorizedotnet_req =
-            utils::Encode::<authorizedotnet::CancelTransactionRequest>::encode_to_string_of_json(
+            utils::Encode::<authorizedotnet::CancelOrCaptureTransactionRequest>::encode_to_string_of_json(
                 &connector_req,
             )
             .change_context(errors::ConnectorError::RequestEncodingFailed)?;
@@ -361,17 +418,15 @@ impl
         let intermediate_response =
             bytes::Bytes::copy_from_slice(intermediate_response.0.as_bytes());
 
-        let response: authorizedotnet::AuthorizedotnetPaymentsResponse = intermediate_response
+        let response: authorizedotnet::AuthorizedotnetVoidResponse = intermediate_response
             .parse_struct("AuthorizedotnetPaymentsResponse")
             .change_context(errors::ConnectorError::ResponseDeserializationFailed)?;
-        logger::debug!(authorizedotnetpayments_create_response=?response);
 
         types::RouterData::try_from(types::ResponseRouterData {
             response,
             data: data.clone(),
             http_code: res.status_code,
         })
-        .change_context(errors::ConnectorError::ResponseDeserializationFailed)
     }
 
     fn get_error_response(
@@ -386,19 +441,16 @@ impl api::Refund for Authorizedotnet {}
 impl api::RefundExecute for Authorizedotnet {}
 impl api::RefundSync for Authorizedotnet {}
 
-impl services::ConnectorIntegration<api::Execute, types::RefundsData, types::RefundsResponseData>
+impl ConnectorIntegration<api::Execute, types::RefundsData, types::RefundsResponseData>
     for Authorizedotnet
 {
     fn get_headers(
         &self,
-        _req: &types::RefundsRouterData<api::Execute>,
-        _connectors: &settings::Connectors,
+        req: &types::RefundsRouterData<api::Execute>,
+        connectors: &settings::Connectors,
     ) -> CustomResult<Vec<(String, String)>, errors::ConnectorError> {
         // This connector does not require an auth header, the authentication details are sent in the request body
-        Ok(vec![(
-            headers::CONTENT_TYPE.to_string(),
-            types::PaymentsAuthorizeType::get_content_type(self).to_string(),
-        )])
+        self.build_headers(req, connectors)
     }
 
     fn get_content_type(&self) -> &'static str {
@@ -417,7 +469,6 @@ impl services::ConnectorIntegration<api::Execute, types::RefundsData, types::Ref
         &self,
         req: &types::RefundsRouterData<api::Execute>,
     ) -> CustomResult<Option<String>, errors::ConnectorError> {
-        logger::debug!(refund_request=?req);
         let connector_req = authorizedotnet::CreateRefundRequest::try_from(req)?;
         let authorizedotnet_req =
             utils::Encode::<authorizedotnet::CreateRefundRequest>::encode_to_string_of_json(
@@ -450,7 +501,6 @@ impl services::ConnectorIntegration<api::Execute, types::RefundsData, types::Ref
         res: types::Response,
     ) -> CustomResult<types::RefundsRouterData<api::Execute>, errors::ConnectorError> {
         use bytes::Buf;
-        logger::debug!(response=?res);
 
         // Handle the case where response bytes contains U+FEFF (BOM) character sent by connector
         let encoding = encoding_rs::UTF_8;
@@ -461,14 +511,12 @@ impl services::ConnectorIntegration<api::Execute, types::RefundsData, types::Ref
         let response: authorizedotnet::AuthorizedotnetRefundResponse = intermediate_response
             .parse_struct("AuthorizedotnetRefundResponse")
             .change_context(errors::ConnectorError::ResponseDeserializationFailed)?;
-        logger::info!(response=?res);
 
         types::RouterData::try_from(types::ResponseRouterData {
             response,
             data: data.clone(),
             http_code: res.status_code,
         })
-        .change_context(errors::ConnectorError::ResponseHandlingFailed)
     }
 
     fn get_error_response(
@@ -479,19 +527,16 @@ impl services::ConnectorIntegration<api::Execute, types::RefundsData, types::Ref
     }
 }
 
-impl services::ConnectorIntegration<api::RSync, types::RefundsData, types::RefundsResponseData>
+impl ConnectorIntegration<api::RSync, types::RefundsData, types::RefundsResponseData>
     for Authorizedotnet
 {
     fn get_headers(
         &self,
-        _req: &types::RefundsRouterData<api::RSync>,
-        _connectors: &settings::Connectors,
+        req: &types::RefundsRouterData<api::RSync>,
+        connectors: &settings::Connectors,
     ) -> CustomResult<Vec<(String, String)>, errors::ConnectorError> {
         // This connector does not require an auth header, the authentication details are sent in the request body
-        Ok(vec![(
-            headers::CONTENT_TYPE.to_string(),
-            types::RefundSyncType::get_content_type(self).to_string(),
-        )])
+        self.build_headers(req, connectors)
     }
 
     fn get_content_type(&self) -> &'static str {
@@ -556,7 +601,6 @@ impl services::ConnectorIntegration<api::RSync, types::RefundsData, types::Refun
             data: data.clone(),
             http_code: res.status_code,
         })
-        .change_context(errors::ConnectorError::ResponseHandlingFailed)
     }
 
     fn get_error_response(
@@ -569,25 +613,109 @@ impl services::ConnectorIntegration<api::RSync, types::RefundsData, types::Refun
 
 #[async_trait::async_trait]
 impl api::IncomingWebhook for Authorizedotnet {
-    fn get_webhook_object_reference_id(
+    fn get_webhook_source_verification_algorithm(
         &self,
         _request: &api::IncomingWebhookRequestDetails<'_>,
+    ) -> CustomResult<Box<dyn crypto::VerifySignature + Send>, errors::ConnectorError> {
+        Ok(Box::new(crypto::HmacSha512))
+    }
+
+    fn get_webhook_source_verification_signature(
+        &self,
+        request: &api::IncomingWebhookRequestDetails<'_>,
+    ) -> CustomResult<Vec<u8>, errors::ConnectorError> {
+        let security_header = request
+            .headers
+            .get("X-ANET-Signature")
+            .map(|header_value| {
+                header_value
+                    .to_str()
+                    .map(String::from)
+                    .map_err(|_| errors::ConnectorError::WebhookSignatureNotFound)
+                    .into_report()
+            })
+            .ok_or(errors::ConnectorError::WebhookSignatureNotFound)
+            .into_report()??
+            .to_lowercase();
+        let (_, sig_value) = security_header
+            .split_once('=')
+            .ok_or(errors::ConnectorError::WebhookSourceVerificationFailed)
+            .into_report()?;
+        hex::decode(sig_value)
+            .into_report()
+            .change_context(errors::ConnectorError::WebhookSignatureNotFound)
+    }
+
+    fn get_webhook_source_verification_message(
+        &self,
+        request: &api::IncomingWebhookRequestDetails<'_>,
+        _merchant_id: &str,
+        _secret: &[u8],
+    ) -> CustomResult<Vec<u8>, errors::ConnectorError> {
+        Ok(request.body.to_vec())
+    }
+
+    fn get_webhook_object_reference_id(
+        &self,
+        request: &api::IncomingWebhookRequestDetails<'_>,
     ) -> CustomResult<api_models::webhooks::ObjectReferenceId, errors::ConnectorError> {
-        Err(errors::ConnectorError::WebhooksNotImplemented).into_report()
+        let details: authorizedotnet::AuthorizedotnetWebhookObjectId = request
+            .body
+            .parse_struct("AuthorizedotnetWebhookObjectId")
+            .change_context(errors::ConnectorError::WebhookReferenceIdNotFound)?;
+        match details.event_type {
+            authorizedotnet::AuthorizedotnetWebhookEvent::RefundCreated => {
+                Ok(api_models::webhooks::ObjectReferenceId::RefundId(
+                    api_models::webhooks::RefundIdType::ConnectorRefundId(
+                        authorizedotnet::get_trans_id(details)?,
+                    ),
+                ))
+            }
+            _ => Ok(api_models::webhooks::ObjectReferenceId::PaymentId(
+                api_models::payments::PaymentIdType::ConnectorTransactionId(
+                    authorizedotnet::get_trans_id(details)?,
+                ),
+            )),
+        }
+    }
+
+    async fn get_webhook_source_verification_merchant_secret(
+        &self,
+        db: &dyn StorageInterface,
+        merchant_id: &str,
+    ) -> CustomResult<Vec<u8>, errors::ConnectorError> {
+        let key = format!("whsec_verification_{}_{}", self.id(), merchant_id);
+        let secret = match db.find_config_by_key(&key).await {
+            Ok(config) => Some(config),
+            Err(e) => {
+                crate::logger::warn!("Unable to fetch merchant webhook secret from DB: {:#?}", e);
+                None
+            }
+        };
+        Ok(secret
+            .map(|conf| conf.config.into_bytes())
+            .unwrap_or_default())
     }
 
     fn get_webhook_event_type(
         &self,
-        _request: &api::IncomingWebhookRequestDetails<'_>,
+        request: &api::IncomingWebhookRequestDetails<'_>,
     ) -> CustomResult<api::IncomingWebhookEvent, errors::ConnectorError> {
-        Err(errors::ConnectorError::WebhooksNotImplemented).into_report()
+        let details: authorizedotnet::AuthorizedotnetWebhookEventType = request
+            .body
+            .parse_struct("AuthorizedotnetWebhookEventType")
+            .change_context(errors::ConnectorError::WebhookEventTypeNotFound)?;
+        Ok(api::IncomingWebhookEvent::from(details.event_type))
     }
 
     fn get_webhook_resource_object(
         &self,
-        _request: &api::IncomingWebhookRequestDetails<'_>,
+        request: &api::IncomingWebhookRequestDetails<'_>,
     ) -> CustomResult<serde_json::Value, errors::ConnectorError> {
-        Err(errors::ConnectorError::WebhooksNotImplemented).into_report()
+        let payload = serde_json::to_value(request.body)
+            .into_report()
+            .change_context(errors::ConnectorError::WebhookResourceObjectNotFound)?;
+        Ok(payload)
     }
 }
 
@@ -603,23 +731,33 @@ fn get_error_response(
         .parse_struct("AuthorizedotnetPaymentsResponse")
         .change_context(errors::ConnectorError::ResponseDeserializationFailed)?;
 
-    logger::info!(response=?response);
-
-    Ok(response
-        .transaction_response
-        .errors
-        .and_then(|errors| {
-            errors.into_iter().next().map(|error| types::ErrorResponse {
-                code: error.error_code,
-                message: error.error_text,
+    match response.transaction_response {
+        Some(transaction_response) => Ok({
+            transaction_response
+                .errors
+                .and_then(|errors| {
+                    errors.into_iter().next().map(|error| types::ErrorResponse {
+                        code: error.error_code,
+                        message: error.error_text,
+                        reason: None,
+                        status_code,
+                    })
+                })
+                .unwrap_or_else(|| types::ErrorResponse {
+                    code: consts::NO_ERROR_CODE.to_string(),
+                    message: consts::NO_ERROR_MESSAGE.to_string(),
+                    reason: None,
+                    status_code,
+                })
+        }),
+        None => {
+            let message = &response.messages.message[0].text;
+            Ok(types::ErrorResponse {
+                code: consts::NO_ERROR_CODE.to_string(),
+                message: message.to_string(),
                 reason: None,
                 status_code,
             })
-        })
-        .unwrap_or_else(|| types::ErrorResponse {
-            code: consts::NO_ERROR_CODE.to_string(),
-            message: consts::NO_ERROR_MESSAGE.to_string(),
-            reason: None,
-            status_code,
-        }))
+        }
+    }
 }
diff --git a/crates/router/src/connector/authorizedotnet/transformers.rs b/crates/router/src/connector/authorizedotnet/transformers.rs
index 75f5dfc192b..0ff92ca196a 100644
--- a/crates/router/src/connector/authorizedotnet/transformers.rs
+++ b/crates/router/src/connector/authorizedotnet/transformers.rs
@@ -3,7 +3,7 @@ use error_stack::ResultExt;
 use serde::{Deserialize, Serialize};
 
 use crate::{
-    connector::utils::{CardData, RefundsRequestData},
+    connector::utils::{CardData, PaymentsSyncRequestData, RefundsRequestData},
     core::errors,
     types::{self, api, storage::enums},
     utils::OptionExt,
@@ -13,6 +13,10 @@ use crate::{
 pub enum TransactionType {
     #[serde(rename = "authCaptureTransaction")]
     Payment,
+    #[serde(rename = "authOnlyTransaction")]
+    Authorization,
+    #[serde(rename = "priorAuthCaptureTransaction")]
+    Capture,
     #[serde(rename = "refundTransaction")]
     Refund,
     #[serde(rename = "voidTransaction")]
@@ -191,8 +195,9 @@ struct AuthorizationIndicator {
 
 #[derive(Debug, Serialize, PartialEq)]
 #[serde(rename_all = "camelCase")]
-struct TransactionVoidRequest {
+struct TransactionVoidOrCaptureRequest {
     transaction_type: TransactionType,
+    amount: Option<i64>,
     ref_trans_id: String,
 }
 
@@ -205,9 +210,9 @@ pub struct AuthorizedotnetPaymentsRequest {
 
 #[derive(Debug, Serialize, PartialEq)]
 #[serde(rename_all = "camelCase")]
-pub struct AuthorizedotnetPaymentCancelRequest {
+pub struct AuthorizedotnetPaymentCancelOrCaptureRequest {
     merchant_authentication: MerchantAuthentication,
-    transaction_request: TransactionVoidRequest,
+    transaction_request: TransactionVoidOrCaptureRequest,
 }
 
 #[derive(Debug, Serialize, PartialEq)]
@@ -219,8 +224,8 @@ pub struct CreateTransactionRequest {
 
 #[derive(Debug, Serialize, PartialEq)]
 #[serde(rename_all = "camelCase")]
-pub struct CancelTransactionRequest {
-    create_transaction_request: AuthorizedotnetPaymentCancelRequest,
+pub struct CancelOrCaptureTransactionRequest {
+    create_transaction_request: AuthorizedotnetPaymentCancelOrCaptureRequest,
 }
 
 #[derive(Debug, Serialize, PartialEq, Eq)]
@@ -249,7 +254,7 @@ impl TryFrom<&types::PaymentsAuthorizeRouterData> for CreateTransactionRequest {
                 authorization_indicator: c.into(),
             });
         let transaction_request = TransactionRequest {
-            transaction_type: TransactionType::Payment,
+            transaction_type: TransactionType::from(item.request.capture_method),
             amount: item.request.amount,
             payment: payment_details,
             currency_code: item.request.currency.to_string(),
@@ -269,10 +274,11 @@ impl TryFrom<&types::PaymentsAuthorizeRouterData> for CreateTransactionRequest {
     }
 }
 
-impl TryFrom<&types::PaymentsCancelRouterData> for CancelTransactionRequest {
+impl TryFrom<&types::PaymentsCancelRouterData> for CancelOrCaptureTransactionRequest {
     type Error = error_stack::Report<errors::ConnectorError>;
     fn try_from(item: &types::PaymentsCancelRouterData) -> Result<Self, Self::Error> {
-        let transaction_request = TransactionVoidRequest {
+        let transaction_request = TransactionVoidOrCaptureRequest {
+            amount: item.request.amount,
             transaction_type: TransactionType::Void,
             ref_trans_id: item.request.connector_transaction_id.to_string(),
         };
@@ -280,7 +286,27 @@ impl TryFrom<&types::PaymentsCancelRouterData> for CancelTransactionRequest {
         let merchant_authentication = MerchantAuthentication::try_from(&item.connector_auth_type)?;
 
         Ok(Self {
-            create_transaction_request: AuthorizedotnetPaymentCancelRequest {
+            create_transaction_request: AuthorizedotnetPaymentCancelOrCaptureRequest {
+                merchant_authentication,
+                transaction_request,
+            },
+        })
+    }
+}
+
+impl TryFrom<&types::PaymentsCaptureRouterData> for CancelOrCaptureTransactionRequest {
+    type Error = error_stack::Report<errors::ConnectorError>;
+    fn try_from(item: &types::PaymentsCaptureRouterData) -> Result<Self, Self::Error> {
+        let transaction_request = TransactionVoidOrCaptureRequest {
+            amount: Some(item.request.amount_to_capture),
+            transaction_type: TransactionType::Capture,
+            ref_trans_id: item.request.connector_transaction_id.to_string(),
+        };
+
+        let merchant_authentication = MerchantAuthentication::try_from(&item.connector_auth_type)?;
+
+        Ok(Self {
+            create_transaction_request: AuthorizedotnetPaymentCancelOrCaptureRequest {
                 merchant_authentication,
                 transaction_request,
             },
@@ -306,7 +332,7 @@ pub type AuthorizedotnetRefundStatus = AuthorizedotnetPaymentStatus;
 impl From<AuthorizedotnetPaymentStatus> for enums::AttemptStatus {
     fn from(item: AuthorizedotnetPaymentStatus) -> Self {
         match item {
-            AuthorizedotnetPaymentStatus::Approved => Self::Charged,
+            AuthorizedotnetPaymentStatus::Approved => Self::Pending,
             AuthorizedotnetPaymentStatus::Declined | AuthorizedotnetPaymentStatus::Error => {
                 Self::Failure
             }
@@ -316,9 +342,9 @@ impl From<AuthorizedotnetPaymentStatus> for enums::AttemptStatus {
 }
 
 #[derive(Debug, Clone, Deserialize, PartialEq)]
-struct ResponseMessage {
+pub struct ResponseMessage {
     code: String,
-    text: String,
+    pub text: String,
 }
 
 #[derive(Debug, Clone, Deserialize, PartialEq)]
@@ -331,14 +357,14 @@ enum ResultCode {
 #[serde(rename_all = "camelCase")]
 pub struct ResponseMessages {
     result_code: ResultCode,
-    message: Vec<ResponseMessage>,
+    pub message: Vec<ResponseMessage>,
 }
 
 #[derive(Debug, Clone, Deserialize, PartialEq, Eq)]
 #[serde(rename_all = "camelCase")]
-pub(super) struct ErrorMessage {
-    pub(super) error_code: String,
-    pub(super) error_text: String,
+pub struct ErrorMessage {
+    pub error_code: String,
+    pub error_text: String,
 }
 
 #[derive(Debug, Clone, Deserialize, PartialEq, Eq)]
@@ -356,10 +382,51 @@ pub struct TransactionResponse {
 #[derive(Debug, Clone, Deserialize, PartialEq)]
 #[serde(rename_all = "camelCase")]
 pub struct AuthorizedotnetPaymentsResponse {
-    pub transaction_response: TransactionResponse,
+    pub transaction_response: Option<TransactionResponse>,
+    pub messages: ResponseMessages,
+}
+
+#[derive(Debug, Clone, Deserialize)]
+#[serde(rename_all = "camelCase")]
+pub struct AuthorizedotnetVoidResponse {
+    pub transaction_response: Option<VoidResponse>,
     pub messages: ResponseMessages,
 }
 
+#[derive(Debug, Clone, Deserialize)]
+#[serde(rename_all = "camelCase")]
+pub struct VoidResponse {
+    response_code: AuthorizedotnetVoidStatus,
+    auth_code: String,
+    #[serde(rename = "transId")]
+    transaction_id: String,
+    network_trans_id: Option<String>,
+    pub account_number: Option<String>,
+    pub errors: Option<Vec<ErrorMessage>>,
+}
+
+#[derive(Debug, Clone, Deserialize)]
+pub enum AuthorizedotnetVoidStatus {
+    #[serde(rename = "1")]
+    Approved,
+    #[serde(rename = "2")]
+    Declined,
+    #[serde(rename = "3")]
+    Error,
+    #[serde(rename = "4")]
+    HeldForReview,
+}
+
+impl From<AuthorizedotnetVoidStatus> for enums::AttemptStatus {
+    fn from(item: AuthorizedotnetVoidStatus) -> Self {
+        match item {
+            AuthorizedotnetVoidStatus::Approved => Self::VoidInitiated,
+            AuthorizedotnetVoidStatus::Declined | AuthorizedotnetVoidStatus::Error => Self::Failure,
+            AuthorizedotnetVoidStatus::HeldForReview => Self::Pending,
+        }
+    }
+}
+
 impl<F, T>
     TryFrom<
         types::ResponseRouterData<
@@ -379,50 +446,115 @@ impl<F, T>
             types::PaymentsResponseData,
         >,
     ) -> Result<Self, Self::Error> {
-        let status = enums::AttemptStatus::from(item.response.transaction_response.response_code);
-        let error = item
-            .response
-            .transaction_response
-            .errors
-            .and_then(|errors| {
-                errors.into_iter().next().map(|error| types::ErrorResponse {
-                    code: error.error_code,
-                    message: error.error_text,
-                    reason: None,
-                    status_code: item.http_code,
+        match &item.response.transaction_response {
+            Some(transaction_response) => {
+                let status = enums::AttemptStatus::from(transaction_response.response_code.clone());
+                let error = transaction_response.errors.as_ref().and_then(|errors| {
+                    errors.iter().next().map(|error| types::ErrorResponse {
+                        code: error.error_code.clone(),
+                        message: error.error_text.clone(),
+                        reason: None,
+                        status_code: item.http_code,
+                    })
+                });
+                let metadata = transaction_response
+                    .account_number
+                    .as_ref()
+                    .map(|acc_no| {
+                        Encode::<'_, PaymentDetails>::encode_to_value(
+                            &construct_refund_payment_details(acc_no.clone()),
+                        )
+                    })
+                    .transpose()
+                    .change_context(errors::ConnectorError::MissingRequiredField {
+                        field_name: "connector_metadata",
+                    })?;
+                Ok(Self {
+                    status,
+                    response: match error {
+                        Some(err) => Err(err),
+                        None => Ok(types::PaymentsResponseData::TransactionResponse {
+                            resource_id: types::ResponseId::ConnectorTransactionId(
+                                transaction_response.transaction_id.clone(),
+                            ),
+                            redirection_data: None,
+                            mandate_reference: None,
+                            connector_metadata: metadata,
+                            network_txn_id: transaction_response.network_trans_id.clone(),
+                        }),
+                    },
+                    ..item.data
                 })
-            });
-
-        let metadata = item
-            .response
-            .transaction_response
-            .account_number
-            .map(|acc_no| {
-                Encode::<'_, PaymentDetails>::encode_to_value(&construct_refund_payment_details(
-                    acc_no,
-                ))
-            })
-            .transpose()
-            .change_context(errors::ConnectorError::MissingRequiredField {
-                field_name: "connector_metadata",
-            })?;
+            }
+            None => Ok(Self {
+                status: enums::AttemptStatus::Failure,
+                response: Err(get_err_response(item.http_code, item.response.messages)),
+                ..item.data
+            }),
+        }
+    }
+}
 
-        Ok(Self {
-            status,
-            response: match error {
-                Some(err) => Err(err),
-                None => Ok(types::PaymentsResponseData::TransactionResponse {
-                    resource_id: types::ResponseId::ConnectorTransactionId(
-                        item.response.transaction_response.transaction_id,
-                    ),
-                    redirection_data: None,
-                    mandate_reference: None,
-                    connector_metadata: metadata,
-                    network_txn_id: item.response.transaction_response.network_trans_id,
-                }),
-            },
-            ..item.data
-        })
+impl<F, T>
+    TryFrom<
+        types::ResponseRouterData<F, AuthorizedotnetVoidResponse, T, types::PaymentsResponseData>,
+    > for types::RouterData<F, T, types::PaymentsResponseData>
+{
+    type Error = error_stack::Report<errors::ConnectorError>;
+    fn try_from(
+        item: types::ResponseRouterData<
+            F,
+            AuthorizedotnetVoidResponse,
+            T,
+            types::PaymentsResponseData,
+        >,
+    ) -> Result<Self, Self::Error> {
+        match &item.response.transaction_response {
+            Some(transaction_response) => {
+                let status = enums::AttemptStatus::from(transaction_response.response_code.clone());
+                let error = transaction_response.errors.as_ref().and_then(|errors| {
+                    errors.iter().next().map(|error| types::ErrorResponse {
+                        code: error.error_code.clone(),
+                        message: error.error_text.clone(),
+                        reason: None,
+                        status_code: item.http_code,
+                    })
+                });
+                let metadata = transaction_response
+                    .account_number
+                    .as_ref()
+                    .map(|acc_no| {
+                        Encode::<'_, PaymentDetails>::encode_to_value(
+                            &construct_refund_payment_details(acc_no.clone()),
+                        )
+                    })
+                    .transpose()
+                    .change_context(errors::ConnectorError::MissingRequiredField {
+                        field_name: "connector_metadata",
+                    })?;
+                Ok(Self {
+                    status,
+                    response: match error {
+                        Some(err) => Err(err),
+                        None => Ok(types::PaymentsResponseData::TransactionResponse {
+                            resource_id: types::ResponseId::ConnectorTransactionId(
+                                transaction_response.transaction_id.clone(),
+                            ),
+                            redirection_data: None,
+                            mandate_reference: None,
+                            connector_metadata: metadata,
+                            network_txn_id: transaction_response.network_trans_id.clone(),
+                        }),
+                    },
+                    ..item.data
+                })
+            }
+            None => Ok(Self {
+                status: enums::AttemptStatus::Failure,
+                response: Err(get_err_response(item.http_code, item.response.messages)),
+                ..item.data
+            }),
+        }
     }
 }
 
@@ -571,22 +703,11 @@ impl TryFrom<&types::PaymentsSyncRouterData> for AuthorizedotnetCreateSyncReques
     type Error = error_stack::Report<errors::ConnectorError>;
 
     fn try_from(item: &types::PaymentsSyncRouterData) -> Result<Self, Self::Error> {
-        let transaction_id = item
-            .response
-            .as_ref()
-            .ok()
-            .map(|payment_response_data| match payment_response_data {
-                types::PaymentsResponseData::TransactionResponse { resource_id, .. } => {
-                    resource_id.get_connector_transaction_id()
-                }
-                _ => Err(error_stack::report!(
-                    errors::ValidationError::MissingRequiredField {
-                        field_name: "transaction_id".to_string()
-                    }
-                )),
-            })
-            .transpose()
-            .change_context(errors::ConnectorError::ResponseHandlingFailed)?;
+        let transaction_id = Some(
+            item.request
+                .get_connector_transaction_id()
+                .change_context(errors::ConnectorError::MissingConnectorTransactionID)?,
+        );
 
         let merchant_authentication = MerchantAuthentication::try_from(&item.connector_auth_type)?;
 
@@ -612,6 +733,8 @@ pub enum SyncStatus {
     Voided,
     CouldNotVoid,
     GeneralError,
+    #[serde(rename = "FDSPendingReview")]
+    FDSPendingReview,
 }
 #[derive(Debug, Deserialize)]
 #[serde(rename_all = "camelCase")]
@@ -623,7 +746,8 @@ pub struct SyncTransactionResponse {
 
 #[derive(Debug, Deserialize)]
 pub struct AuthorizedotnetSyncResponse {
-    transaction: SyncTransactionResponse,
+    transaction: Option<SyncTransactionResponse>,
+    messages: ResponseMessages,
 }
 
 impl From<SyncStatus> for enums::RefundStatus {
@@ -639,9 +763,9 @@ impl From<SyncStatus> for enums::RefundStatus {
 impl From<SyncStatus> for enums::AttemptStatus {
     fn from(transaction_status: SyncStatus) -> Self {
         match transaction_status {
-            SyncStatus::SettledSuccessfully | SyncStatus::CapturedPendingSettlement => {
-                Self::Charged
-            }
+            SyncStatus::SettledSuccessfully => Self::Charged,
+            SyncStatus::CapturedPendingSettlement => Self::CaptureInitiated,
+            SyncStatus::AuthorizedPendingCapture => Self::Authorized,
             SyncStatus::Declined => Self::AuthenticationFailed,
             SyncStatus::Voided => Self::Voided,
             SyncStatus::CouldNotVoid => Self::VoidFailed,
@@ -659,14 +783,22 @@ impl TryFrom<types::RefundsResponseRouterData<api::RSync, AuthorizedotnetSyncRes
     fn try_from(
         item: types::RefundsResponseRouterData<api::RSync, AuthorizedotnetSyncResponse>,
     ) -> Result<Self, Self::Error> {
-        let refund_status = enums::RefundStatus::from(item.response.transaction.transaction_status);
-        Ok(Self {
-            response: Ok(types::RefundsResponseData {
-                connector_refund_id: item.response.transaction.transaction_id.clone(),
-                refund_status,
+        match item.response.transaction {
+            Some(transaction) => {
+                let refund_status = enums::RefundStatus::from(transaction.transaction_status);
+                Ok(Self {
+                    response: Ok(types::RefundsResponseData {
+                        connector_refund_id: transaction.transaction_id,
+                        refund_status,
+                    }),
+                    ..item.data
+                })
+            }
+            None => Ok(Self {
+                response: Err(get_err_response(item.http_code, item.response.messages)),
+                ..item.data
             }),
-            ..item.data
-        })
+        }
     }
 }
 
@@ -685,21 +817,28 @@ impl<F, Req>
             types::PaymentsResponseData,
         >,
     ) -> Result<Self, Self::Error> {
-        let payment_status =
-            enums::AttemptStatus::from(item.response.transaction.transaction_status);
-        Ok(Self {
-            response: Ok(types::PaymentsResponseData::TransactionResponse {
-                resource_id: types::ResponseId::ConnectorTransactionId(
-                    item.response.transaction.transaction_id,
-                ),
-                redirection_data: None,
-                mandate_reference: None,
-                connector_metadata: None,
-                network_txn_id: None,
+        match item.response.transaction {
+            Some(transaction) => {
+                let payment_status = enums::AttemptStatus::from(transaction.transaction_status);
+                Ok(Self {
+                    response: Ok(types::PaymentsResponseData::TransactionResponse {
+                        resource_id: types::ResponseId::ConnectorTransactionId(
+                            transaction.transaction_id,
+                        ),
+                        redirection_data: None,
+                        mandate_reference: None,
+                        connector_metadata: None,
+                        network_txn_id: None,
+                    }),
+                    status: payment_status,
+                    ..item.data
+                })
+            }
+            None => Ok(Self {
+                response: Err(get_err_response(item.http_code, item.response.messages)),
+                ..item.data
             }),
-            status: payment_status,
-            ..item.data
-        })
+        }
     }
 }
 
@@ -724,3 +863,78 @@ fn construct_refund_payment_details(masked_number: String) -> PaymentDetails {
         card_code: None,
     })
 }
+
+impl From<Option<enums::CaptureMethod>> for TransactionType {
+    fn from(capture_method: Option<enums::CaptureMethod>) -> Self {
+        match capture_method {
+            Some(enums::CaptureMethod::Manual) => Self::Authorization,
+            _ => Self::Payment,
+        }
+    }
+}
+
+fn get_err_response(status_code: u16, message: ResponseMessages) -> types::ErrorResponse {
+    types::ErrorResponse {
+        code: message.message[0].code.clone(),
+        message: message.message[0].text.clone(),
+        reason: None,
+        status_code,
+    }
+}
+
+#[derive(Debug, Deserialize)]
+#[serde(rename_all = "camelCase")]
+pub struct AuthorizedotnetWebhookObjectId {
+    pub webhook_id: String,
+    pub event_type: AuthorizedotnetWebhookEvent,
+    pub payload: AuthorizedotnetWebhookPayload,
+}
+
+#[derive(Debug, Deserialize)]
+pub struct AuthorizedotnetWebhookPayload {
+    pub id: Option<String>,
+}
+
+#[derive(Debug, Deserialize)]
+#[serde(rename_all = "camelCase")]
+pub struct AuthorizedotnetWebhookEventType {
+    pub event_type: AuthorizedotnetWebhookEvent,
+}
+
+#[derive(Debug, Deserialize)]
+pub enum AuthorizedotnetWebhookEvent {
+    #[serde(rename = "net.authorize.payment.authorization.created")]
+    AuthorizationCreated,
+    #[serde(rename = "net.authorize.payment.priorAuthCapture.created")]
+    PriorAuthCapture,
+    #[serde(rename = "net.authorize.payment.authcapture.created")]
+    AuthCapCreated,
+    #[serde(rename = "net.authorize.payment.capture.created")]
+    CaptureCreated,
+    #[serde(rename = "net.authorize.payment.void.created")]
+    VoidCreated,
+    #[serde(rename = "net.authorize.payment.refund.created")]
+    RefundCreated,
+}
+
+impl From<AuthorizedotnetWebhookEvent> for api::IncomingWebhookEvent {
+    fn from(event_type: AuthorizedotnetWebhookEvent) -> Self {
+        match event_type {
+            AuthorizedotnetWebhookEvent::AuthorizationCreated
+            | AuthorizedotnetWebhookEvent::PriorAuthCapture
+            | AuthorizedotnetWebhookEvent::AuthCapCreated
+            | AuthorizedotnetWebhookEvent::CaptureCreated
+            | AuthorizedotnetWebhookEvent::VoidCreated => Self::PaymentIntentSuccess,
+            AuthorizedotnetWebhookEvent::RefundCreated => Self::RefundSuccess,
+        }
+    }
+}
+
+pub fn get_trans_id(
+    details: AuthorizedotnetWebhookObjectId,
+) -> Result<String, errors::ConnectorError> {
+    details
+        .payload
+        .id
+        .ok_or(errors::ConnectorError::WebhookReferenceIdNotFound)
+}
diff --git a/crates/router/tests/connectors/authorizedotnet.rs b/crates/router/tests/connectors/authorizedotnet.rs
index f209d1bdecd..6892fc16f4a 100644
--- a/crates/router/tests/connectors/authorizedotnet.rs
+++ b/crates/router/tests/connectors/authorizedotnet.rs
@@ -1,283 +1,543 @@
-use std::{marker::PhantomData, str::FromStr};
+use std::str::FromStr;
 
 use masking::Secret;
-use router::{
-    configs::settings::Settings,
-    connector::Authorizedotnet,
-    core::payments,
-    db::StorageImpl,
-    routes, services,
-    types::{self, storage::enums, PaymentAddress},
+use router::types::{self, api, storage::enums};
+
+use crate::{
+    connector_auth,
+    utils::{self, ConnectorActions},
 };
-use tokio::sync::oneshot;
 
-use crate::connector_auth::ConnectorAuthentication;
+#[derive(Clone, Copy)]
+struct AuthorizedotnetTest;
+impl ConnectorActions for AuthorizedotnetTest {}
+impl utils::Connector for AuthorizedotnetTest {
+    fn get_data(&self) -> types::api::ConnectorData {
+        use router::connector::Authorizedotnet;
+        types::api::ConnectorData {
+            connector: Box::new(&Authorizedotnet),
+            connector_name: types::Connector::Authorizedotnet,
+            get_token: types::api::GetToken::Connector,
+        }
+    }
 
-fn construct_payment_router_data() -> types::PaymentsAuthorizeRouterData {
-    let auth = ConnectorAuthentication::new()
-        .authorizedotnet
-        .expect("Missing Authorize.net connector authentication configuration");
+    fn get_auth_token(&self) -> types::ConnectorAuthType {
+        types::ConnectorAuthType::from(
+            connector_auth::ConnectorAuthentication::new()
+                .authorizedotnet
+                .expect("Missing connector authentication configuration"),
+        )
+    }
 
-    types::RouterData {
-        flow: PhantomData,
-        merchant_id: String::from("authorizedotnet"),
-        customer_id: Some(String::from("authorizedotnet")),
-        connector: "authorizedotnet".to_string(),
-        payment_id: uuid::Uuid::new_v4().to_string(),
-        attempt_id: uuid::Uuid::new_v4().to_string(),
-        status: enums::AttemptStatus::default(),
-        payment_method: enums::PaymentMethod::Card,
-        connector_auth_type: auth.into(),
-        auth_type: enums::AuthenticationType::NoThreeDs,
-        description: Some("This is a test".to_string()),
-        return_url: None,
-        request: types::PaymentsAuthorizeData {
-            amount: 100,
-            currency: enums::Currency::USD,
-            payment_method_data: types::api::PaymentMethodData::Card(types::api::Card {
-                card_number: cards::CardNumber::from_str("5424000000000015").unwrap(),
-                card_exp_month: Secret::new("10".to_string()),
-                card_exp_year: Secret::new("2025".to_string()),
-                card_holder_name: Secret::new("John Doe".to_string()),
-                card_cvc: Secret::new("999".to_string()),
-                card_issuer: None,
-                card_network: None,
-            }),
-            confirm: true,
-            statement_descriptor_suffix: None,
-            statement_descriptor: None,
-            setup_future_usage: None,
-            mandate_id: None,
-            off_session: None,
-            setup_mandate_details: None,
-            capture_method: None,
-            browser_info: None,
-            order_details: None,
-            email: None,
-            session_token: None,
-            enrolled_for_3ds: false,
-            related_transaction_id: None,
-            payment_experience: None,
-            payment_method_type: None,
-            router_return_url: None,
-            webhook_url: None,
-            complete_authorize_url: None,
-        },
-        payment_method_id: None,
-        response: Err(types::ErrorResponse::default()),
-        address: PaymentAddress::default(),
-        connector_meta_data: None,
-        amount_captured: None,
-        access_token: None,
-        session_token: None,
-        reference_id: None,
-        payment_method_token: None,
-        connector_customer: None,
+    fn get_name(&self) -> String {
+        "authorizedotnet".to_string()
     }
 }
+static CONNECTOR: AuthorizedotnetTest = AuthorizedotnetTest {};
 
-fn construct_refund_router_data<F>() -> types::RefundsRouterData<F> {
-    let auth = ConnectorAuthentication::new()
-        .authorizedotnet
-        .expect("Missing Authorize.net connector authentication configuration");
-
-    types::RouterData {
-        flow: PhantomData,
-        connector_meta_data: None,
-        merchant_id: String::from("authorizedotnet"),
-        customer_id: Some(String::from("authorizedotnet")),
-        connector: "authorizedotnet".to_string(),
-        payment_id: uuid::Uuid::new_v4().to_string(),
-        attempt_id: uuid::Uuid::new_v4().to_string(),
-        status: enums::AttemptStatus::default(),
-        auth_type: enums::AuthenticationType::NoThreeDs,
-        payment_method: enums::PaymentMethod::Card,
-        connector_auth_type: auth.into(),
-        description: Some("This is a test".to_string()),
-        return_url: None,
-        request: router::types::RefundsData {
-            amount: 100,
-            currency: enums::Currency::USD,
-            refund_id: uuid::Uuid::new_v4().to_string(),
-            connector_transaction_id: String::new(),
-            refund_amount: 1,
-            webhook_url: None,
-            connector_metadata: None,
-            reason: None,
-            connector_refund_id: None,
-        },
-        response: Err(types::ErrorResponse::default()),
-        payment_method_id: None,
-        address: PaymentAddress::default(),
-        amount_captured: None,
-        access_token: None,
-        session_token: None,
-        reference_id: None,
-        payment_method_token: None,
-        connector_customer: None,
+fn get_payment_method_data() -> api::Card {
+    api::Card {
+        card_number: cards::CardNumber::from_str("5424000000000015").unwrap(),
+        card_exp_month: Secret::new("02".to_string()),
+        card_exp_year: Secret::new("2035".to_string()),
+        card_holder_name: Secret::new("John Doe".to_string()),
+        card_cvc: Secret::new("123".to_string()),
+        ..Default::default()
     }
 }
 
+// Cards Positive Tests
+// Creates a payment using the manual capture flow (Non 3DS).
 #[actix_web::test]
-#[ignore]
-async fn payments_create_success() {
-    let conf = Settings::new().unwrap();
-    let tx: oneshot::Sender<()> = oneshot::channel().0;
-    let state = routes::AppState::with_storage(conf, StorageImpl::PostgresqlTest, tx).await;
-    static CV: Authorizedotnet = Authorizedotnet;
-    let connector = types::api::ConnectorData {
-        connector: Box::new(&CV),
-        connector_name: types::Connector::Authorizedotnet,
-        get_token: types::api::GetToken::Connector,
-    };
-    let connector_integration: services::BoxedConnectorIntegration<
-        '_,
-        types::api::Authorize,
-        types::PaymentsAuthorizeData,
-        types::PaymentsResponseData,
-    > = connector.connector.get_connector_integration();
-    let request = construct_payment_router_data();
+async fn should_only_authorize_payment() {
+    let authorize_response = CONNECTOR
+        .authorize_payment(
+            Some(types::PaymentsAuthorizeData {
+                amount: 300,
+                payment_method_data: types::api::PaymentMethodData::Card(get_payment_method_data()),
+                capture_method: Some(storage_models::enums::CaptureMethod::Manual),
+                ..utils::PaymentAuthorizeType::default().0
+            }),
+            None,
+        )
+        .await
+        .expect("Authorize payment response");
+    assert_eq!(authorize_response.status, enums::AttemptStatus::Pending);
+    let txn_id =
+        utils::get_connector_transaction_id(authorize_response.response).unwrap_or_default();
+    let psync_response = CONNECTOR
+        .psync_retry_till_status_matches(
+            enums::AttemptStatus::Authorized,
+            Some(types::PaymentsSyncData {
+                connector_transaction_id: router::types::ResponseId::ConnectorTransactionId(txn_id),
+                encoded_data: None,
+                capture_method: None,
+                ..Default::default()
+            }),
+            None,
+        )
+        .await
+        .expect("PSync response");
 
-    let response = services::api::execute_connector_processing_step(
-        &state,
-        connector_integration,
-        &request,
-        payments::CallConnectorAction::Trigger,
-    )
-    .await
-    .unwrap();
+    assert_eq!(psync_response.status, enums::AttemptStatus::Authorized);
+}
 
-    println!("{response:?}");
+// Captures a payment using the manual capture flow (Non 3DS).
+#[actix_web::test]
+async fn should_capture_authorized_payment() {
+    let authorize_response = CONNECTOR
+        .authorize_payment(
+            Some(types::PaymentsAuthorizeData {
+                amount: 301,
+                payment_method_data: types::api::PaymentMethodData::Card(get_payment_method_data()),
+                capture_method: Some(storage_models::enums::CaptureMethod::Manual),
+                ..utils::PaymentAuthorizeType::default().0
+            }),
+            None,
+        )
+        .await
+        .expect("Authorize payment response");
+    assert_eq!(authorize_response.status, enums::AttemptStatus::Pending);
+    let txn_id =
+        utils::get_connector_transaction_id(authorize_response.response).unwrap_or_default();
+    let psync_response = CONNECTOR
+        .psync_retry_till_status_matches(
+            enums::AttemptStatus::Authorized,
+            Some(types::PaymentsSyncData {
+                connector_transaction_id: router::types::ResponseId::ConnectorTransactionId(
+                    txn_id.clone(),
+                ),
+                encoded_data: None,
+                capture_method: None,
+                ..Default::default()
+            }),
+            None,
+        )
+        .await
+        .expect("PSync response");
+    assert_eq!(psync_response.status, enums::AttemptStatus::Authorized);
+    let cap_response = CONNECTOR
+        .capture_payment(
+            txn_id.clone(),
+            Some(types::PaymentsCaptureData {
+                amount_to_capture: 301,
+                ..utils::PaymentCaptureType::default().0
+            }),
+            None,
+        )
+        .await
+        .expect("Capture payment response");
+    assert_eq!(cap_response.status, enums::AttemptStatus::Pending);
+    let response = CONNECTOR
+        .psync_retry_till_status_matches(
+            enums::AttemptStatus::CaptureInitiated,
+            Some(types::PaymentsSyncData {
+                connector_transaction_id: router::types::ResponseId::ConnectorTransactionId(txn_id),
+                encoded_data: None,
+                capture_method: None,
+                ..Default::default()
+            }),
+            None,
+        )
+        .await
+        .expect("PSync response");
+    assert_eq!(response.status, enums::AttemptStatus::CaptureInitiated);
+}
 
-    assert!(
-        response.status == enums::AttemptStatus::Charged,
-        "The payment failed"
-    );
+// Partially captures a payment using the manual capture flow (Non 3DS).
+#[actix_web::test]
+async fn should_partially_capture_authorized_payment() {
+    let authorize_response = CONNECTOR
+        .authorize_payment(
+            Some(types::PaymentsAuthorizeData {
+                amount: 302,
+                payment_method_data: types::api::PaymentMethodData::Card(get_payment_method_data()),
+                capture_method: Some(storage_models::enums::CaptureMethod::Manual),
+                ..utils::PaymentAuthorizeType::default().0
+            }),
+            None,
+        )
+        .await
+        .expect("Authorize payment response");
+    assert_eq!(authorize_response.status, enums::AttemptStatus::Pending);
+    let txn_id =
+        utils::get_connector_transaction_id(authorize_response.response).unwrap_or_default();
+    let psync_response = CONNECTOR
+        .psync_retry_till_status_matches(
+            enums::AttemptStatus::Authorized,
+            Some(types::PaymentsSyncData {
+                connector_transaction_id: router::types::ResponseId::ConnectorTransactionId(
+                    txn_id.clone(),
+                ),
+                encoded_data: None,
+                capture_method: None,
+                ..Default::default()
+            }),
+            None,
+        )
+        .await
+        .expect("PSync response");
+    assert_eq!(psync_response.status, enums::AttemptStatus::Authorized);
+    let cap_response = CONNECTOR
+        .capture_payment(
+            txn_id.clone(),
+            Some(types::PaymentsCaptureData {
+                amount_to_capture: 150,
+                ..utils::PaymentCaptureType::default().0
+            }),
+            None,
+        )
+        .await
+        .expect("Capture payment response");
+    assert_eq!(cap_response.status, enums::AttemptStatus::Pending);
+    let response = CONNECTOR
+        .psync_retry_till_status_matches(
+            enums::AttemptStatus::CaptureInitiated,
+            Some(types::PaymentsSyncData {
+                connector_transaction_id: router::types::ResponseId::ConnectorTransactionId(txn_id),
+                encoded_data: None,
+                capture_method: None,
+                ..Default::default()
+            }),
+            None,
+        )
+        .await
+        .expect("PSync response");
+    assert_eq!(response.status, enums::AttemptStatus::CaptureInitiated);
 }
 
+// Synchronizes a payment using the manual capture flow (Non 3DS).
 #[actix_web::test]
-#[ignore]
-async fn payments_create_failure() {
-    {
-        let conf = Settings::new().unwrap();
-        static CV: Authorizedotnet = Authorizedotnet;
-        let connector = types::api::ConnectorData {
-            connector: Box::new(&CV),
-            connector_name: types::Connector::Authorizedotnet,
-            get_token: types::api::GetToken::Connector,
-        };
-        let tx: oneshot::Sender<()> = oneshot::channel().0;
-        let state = routes::AppState::with_storage(conf, StorageImpl::PostgresqlTest, tx).await;
-        let connector_integration: services::BoxedConnectorIntegration<
-            '_,
-            types::api::Authorize,
-            types::PaymentsAuthorizeData,
-            types::PaymentsResponseData,
-        > = connector.connector.get_connector_integration();
-        let mut request = construct_payment_router_data();
+async fn should_sync_authorized_payment() {
+    let authorize_response = CONNECTOR
+        .authorize_payment(
+            Some(types::PaymentsAuthorizeData {
+                amount: 303,
+                payment_method_data: types::api::PaymentMethodData::Card(get_payment_method_data()),
+                capture_method: Some(storage_models::enums::CaptureMethod::Manual),
+                ..utils::PaymentAuthorizeType::default().0
+            }),
+            None,
+        )
+        .await
+        .expect("Authorize payment response");
+    assert_eq!(authorize_response.status, enums::AttemptStatus::Pending);
+    let txn_id =
+        utils::get_connector_transaction_id(authorize_response.response).unwrap_or_default();
+    let response = CONNECTOR
+        .psync_retry_till_status_matches(
+            enums::AttemptStatus::Authorized,
+            Some(types::PaymentsSyncData {
+                connector_transaction_id: router::types::ResponseId::ConnectorTransactionId(txn_id),
+                encoded_data: None,
+                capture_method: None,
+                ..Default::default()
+            }),
+            None,
+        )
+        .await
+        .expect("PSync response");
+    assert_eq!(response.status, enums::AttemptStatus::Authorized,);
+}
 
-        request.request.payment_method_data =
-            types::api::PaymentMethodData::Card(types::api::Card {
-                card_number: cards::CardNumber::from_str("5424000000000015").unwrap(),
-                card_exp_month: Secret::new("10".to_string()),
-                card_exp_year: Secret::new("2025".to_string()),
-                card_holder_name: Secret::new("John Doe".to_string()),
-                card_cvc: Secret::new("999".to_string()),
-                card_issuer: None,
-                card_network: None,
-            });
+// Voids a payment using the manual capture flow (Non 3DS).x
+#[actix_web::test]
+async fn should_void_authorized_payment() {
+    let authorize_response = CONNECTOR
+        .authorize_payment(
+            Some(types::PaymentsAuthorizeData {
+                amount: 304,
+                payment_method_data: types::api::PaymentMethodData::Card(get_payment_method_data()),
+                capture_method: Some(storage_models::enums::CaptureMethod::Manual),
+                ..utils::PaymentAuthorizeType::default().0
+            }),
+            None,
+        )
+        .await
+        .expect("Authorize payment response");
+    assert_eq!(authorize_response.status, enums::AttemptStatus::Pending);
+    let txn_id =
+        utils::get_connector_transaction_id(authorize_response.response).unwrap_or_default();
+    let psync_response = CONNECTOR
+        .psync_retry_till_status_matches(
+            enums::AttemptStatus::Authorized,
+            Some(types::PaymentsSyncData {
+                connector_transaction_id: router::types::ResponseId::ConnectorTransactionId(
+                    txn_id.clone(),
+                ),
+                encoded_data: None,
+                capture_method: None,
+                ..Default::default()
+            }),
+            None,
+        )
+        .await
+        .expect("PSync response");
 
-        let response = services::api::execute_connector_processing_step(
-            &state,
-            connector_integration,
-            &request,
-            payments::CallConnectorAction::Trigger,
+    assert_eq!(psync_response.status, enums::AttemptStatus::Authorized);
+    let void_response = CONNECTOR
+        .void_payment(
+            txn_id,
+            Some(types::PaymentsCancelData {
+                amount: Some(304),
+                ..utils::PaymentCancelType::default().0
+            }),
+            None,
+        )
+        .await
+        .expect("Void response");
+    assert_eq!(void_response.status, enums::AttemptStatus::VoidInitiated)
+}
+
+// Creates a payment using the automatic capture flow (Non 3DS).
+#[actix_web::test]
+async fn should_make_payment() {
+    let cap_response = CONNECTOR
+        .make_payment(
+            Some(types::PaymentsAuthorizeData {
+                amount: 310,
+                payment_method_data: types::api::PaymentMethodData::Card(get_payment_method_data()),
+                capture_method: Some(storage_models::enums::CaptureMethod::Manual),
+                ..utils::PaymentAuthorizeType::default().0
+            }),
+            None,
         )
         .await
         .unwrap();
+    assert_eq!(cap_response.status, enums::AttemptStatus::Pending);
+    let txn_id = utils::get_connector_transaction_id(cap_response.response).unwrap_or_default();
+    let psync_response = CONNECTOR
+        .psync_retry_till_status_matches(
+            enums::AttemptStatus::CaptureInitiated,
+            Some(types::PaymentsSyncData {
+                connector_transaction_id: router::types::ResponseId::ConnectorTransactionId(
+                    txn_id.clone(),
+                ),
+                encoded_data: None,
+                capture_method: None,
+                ..Default::default()
+            }),
+            None,
+        )
+        .await
+        .expect("PSync response");
+    assert_eq!(
+        psync_response.status,
+        enums::AttemptStatus::CaptureInitiated
+    );
+}
 
-        println!("{response:?}");
+// Synchronizes a payment using the automatic capture flow (Non 3DS).
+#[actix_web::test]
+async fn should_sync_auto_captured_payment() {
+    let authorize_response = CONNECTOR
+        .make_payment(
+            Some(types::PaymentsAuthorizeData {
+                amount: 311,
+                payment_method_data: types::api::PaymentMethodData::Card(get_payment_method_data()),
+                capture_method: Some(storage_models::enums::CaptureMethod::Manual),
+                ..utils::PaymentAuthorizeType::default().0
+            }),
+            None,
+        )
+        .await
+        .unwrap();
+    assert_eq!(authorize_response.status, enums::AttemptStatus::Pending);
+    let txn_id = utils::get_connector_transaction_id(authorize_response.response);
+    assert_ne!(txn_id, None, "Empty connector transaction id");
+    let response = CONNECTOR
+        .psync_retry_till_status_matches(
+            enums::AttemptStatus::Pending,
+            Some(types::PaymentsSyncData {
+                connector_transaction_id: router::types::ResponseId::ConnectorTransactionId(
+                    txn_id.unwrap(),
+                ),
+                encoded_data: None,
+                capture_method: None,
+                ..Default::default()
+            }),
+            None,
+        )
+        .await
+        .unwrap();
+    assert_eq!(response.status, enums::AttemptStatus::CaptureInitiated);
+}
 
-        assert!(
-            response.status == enums::AttemptStatus::Failure,
-            "The payment was intended to fail but it passed"
-        );
-    }
+// Synchronizes a refund using the automatic capture flow (Non 3DS).
+#[actix_web::test]
+async fn should_sync_refund() {
+    let response = CONNECTOR
+        .rsync_retry_till_status_matches(
+            enums::RefundStatus::Success,
+            "60217566768".to_string(),
+            None,
+            None,
+        )
+        .await
+        .unwrap();
+    assert_eq!(
+        response.response.unwrap().refund_status,
+        enums::RefundStatus::Success,
+    );
 }
 
+// Creates a payment with empty card number.
 #[actix_web::test]
-#[ignore]
-async fn refunds_create_success() {
-    let conf = Settings::new().unwrap();
-    static CV: Authorizedotnet = Authorizedotnet;
-    let connector = types::api::ConnectorData {
-        connector: Box::new(&CV),
-        connector_name: types::Connector::Authorizedotnet,
-        get_token: types::api::GetToken::Connector,
-    };
-    let tx: oneshot::Sender<()> = oneshot::channel().0;
-    let state = routes::AppState::with_storage(conf, StorageImpl::PostgresqlTest, tx).await;
-    let connector_integration: services::BoxedConnectorIntegration<
-        '_,
-        types::api::Execute,
-        types::RefundsData,
-        types::RefundsResponseData,
-    > = connector.connector.get_connector_integration();
+async fn should_fail_payment_for_empty_card_number() {
+    let response = CONNECTOR
+        .make_payment(
+            Some(types::PaymentsAuthorizeData {
+                payment_method_data: types::api::PaymentMethodData::Card(api::Card {
+                    card_number: cards::CardNumber::from_str("").unwrap(),
+                    ..utils::CCardType::default().0
+                }),
+                ..utils::PaymentAuthorizeType::default().0
+            }),
+            None,
+        )
+        .await
+        .unwrap();
+    let x = response.response.unwrap_err();
+    assert_eq!(
+        x.message,
+        "The 'AnetApi/xml/v1/schema/AnetApiSchema.xsd:cardNumber' element is invalid - The value XX is invalid according to its datatype 'String' - The actual length is less than the MinLength value.",
+    );
+}
 
-    let mut request = construct_refund_router_data();
-    request.request.connector_transaction_id = "abfbc35c-4825-4dd4-ab2d-fae0acc22389".to_string();
+// Creates a payment with incorrect CVC.
+#[actix_web::test]
+async fn should_fail_payment_for_incorrect_cvc() {
+    let response = CONNECTOR
+        .make_payment(
+            Some(types::PaymentsAuthorizeData {
+                payment_method_data: types::api::PaymentMethodData::Card(api::Card {
+                    card_cvc: Secret::new("12345".to_string()),
+                    ..utils::CCardType::default().0
+                }),
+                ..utils::PaymentAuthorizeType::default().0
+            }),
+            None,
+        )
+        .await
+        .unwrap();
+    assert_eq!(
+        response.response.unwrap_err().message,
+        "The 'AnetApi/xml/v1/schema/AnetApiSchema.xsd:cardCode' element is invalid - The value XXXXXXX is invalid according to its datatype 'AnetApi/xml/v1/schema/AnetApiSchema.xsd:cardCode' - The actual length is greater than the MaxLength value.".to_string(),
+    );
+}
+// todo()
 
-    let response = services::api::execute_connector_processing_step(
-        &state,
-        connector_integration,
-        &request,
-        payments::CallConnectorAction::Trigger,
-    )
-    .await
-    .unwrap();
+// Creates a payment with incorrect expiry month.
+#[actix_web::test]
+async fn should_fail_payment_for_invalid_exp_month() {
+    let response = CONNECTOR
+        .make_payment(
+            Some(types::PaymentsAuthorizeData {
+                payment_method_data: types::api::PaymentMethodData::Card(api::Card {
+                    card_exp_month: Secret::new("20".to_string()),
+                    ..utils::CCardType::default().0
+                }),
+                ..utils::PaymentAuthorizeType::default().0
+            }),
+            None,
+        )
+        .await
+        .unwrap();
+    assert_eq!(
+        response.response.unwrap_err().message,
+        "Credit card expiration date is invalid.".to_string(),
+    );
+}
 
-    println!("{response:?}");
+// Creates a payment with incorrect expiry year.
+#[actix_web::test]
+async fn should_fail_payment_for_incorrect_expiry_year() {
+    let response = CONNECTOR
+        .make_payment(
+            Some(types::PaymentsAuthorizeData {
+                payment_method_data: types::api::PaymentMethodData::Card(api::Card {
+                    card_exp_year: Secret::new("2000".to_string()),
+                    ..utils::CCardType::default().0
+                }),
+                ..utils::PaymentAuthorizeType::default().0
+            }),
+            None,
+        )
+        .await
+        .unwrap();
+    assert_eq!(
+        response.response.unwrap_err().message,
+        "The credit card has expired.".to_string(),
+    );
+}
+
+// Voids a payment using automatic capture flow (Non 3DS).
+#[actix_web::test]
+async fn should_fail_void_payment_for_auto_capture() {
+    let authorize_response = CONNECTOR
+        .make_payment(
+            Some(types::PaymentsAuthorizeData {
+                amount: 307,
+                payment_method_data: types::api::PaymentMethodData::Card(get_payment_method_data()),
+                capture_method: Some(storage_models::enums::CaptureMethod::Manual),
+                ..utils::PaymentAuthorizeType::default().0
+            }),
+            None,
+        )
+        .await
+        .unwrap();
+    let txn_id = utils::get_connector_transaction_id(authorize_response.response);
+    let void_response = CONNECTOR
+        .void_payment(txn_id.unwrap(), None, None)
+        .await
+        .unwrap();
+    assert_eq!(
+        void_response.response.unwrap_err().message,
+        "The 'AnetApi/xml/v1/schema/AnetApiSchema.xsd:amount' element is invalid - The value &#39;&#39; is invalid according to its datatype 'http://www.w3.org/2001/XMLSchema:decimal' - The string &#39;&#39; is not a valid Decimal value."
+    );
+}
 
-    assert!(
-        response.response.unwrap().refund_status == enums::RefundStatus::Success,
-        "The refund transaction failed"
+// Captures a payment using invalid connector payment id.
+#[actix_web::test]
+async fn should_fail_capture_for_invalid_payment() {
+    let capture_response = CONNECTOR
+        .capture_payment("123456789".to_string(), None, None)
+        .await
+        .unwrap();
+    assert_eq!(
+        capture_response.response.unwrap_err().message,
+        "The transaction cannot be found."
     );
 }
 
 #[actix_web::test]
-async fn refunds_create_failure() {
-    let conf = Settings::new().unwrap();
-    static CV: Authorizedotnet = Authorizedotnet;
-    let connector = types::api::ConnectorData {
-        connector: Box::new(&CV),
-        connector_name: types::Connector::Authorizedotnet,
-        get_token: types::api::GetToken::Connector,
-    };
-    let tx: oneshot::Sender<()> = oneshot::channel().0;
-    let state = routes::AppState::with_storage(conf, StorageImpl::PostgresqlTest, tx).await;
-    let connector_integration: services::BoxedConnectorIntegration<
-        '_,
-        types::api::Execute,
-        types::RefundsData,
-        types::RefundsResponseData,
-    > = connector.connector.get_connector_integration();
+#[ignore = "refunds tests are ignored for this connector becuase it takes one day for a payment to be settled."]
+async fn should_partially_refund_manually_captured_payment() {}
 
-    let mut request = construct_refund_router_data();
-    request.request.connector_transaction_id = "1234".to_string();
+#[actix_web::test]
+#[ignore = "refunds tests are ignored for this connector becuase it takes one day for a payment to be settled."]
+async fn should_refund_manually_captured_payment() {}
 
-    let response = services::api::execute_connector_processing_step(
-        &state,
-        connector_integration,
-        &request,
-        payments::CallConnectorAction::Trigger,
-    )
-    .await
-    .unwrap();
+#[actix_web::test]
+#[ignore = "refunds tests are ignored for this connector becuase it takes one day for a payment to be settled."]
+async fn should_sync_manually_captured_refund() {}
 
-    println!("{response:?}");
+#[actix_web::test]
+#[ignore = "refunds tests are ignored for this connector becuase it takes one day for a payment to be settled."]
+async fn should_refund_auto_captured_payment() {}
 
-    assert!(
-        response.response.unwrap().refund_status == enums::RefundStatus::Failure,
-        "The test was intended to fail but it passed"
-    );
-}
+#[actix_web::test]
+#[ignore = "refunds tests are ignored for this connector becuase it takes one day for a payment to be settled."]
+async fn should_partially_refund_succeeded_payment() {}
+
+#[actix_web::test]
+#[ignore = "refunds tests are ignored for this connector becuase it takes one day for a payment to be settled."]
+async fn should_refund_succeeded_payment_multiple_times() {}
+
+#[actix_web::test]
+#[ignore = "refunds tests are ignored for this connector becuase it takes one day for a payment to be settled."]
+async fn should_fail_for_refund_amount_higher_than_payment_amount() {}
+
+// Connector dependent test cases goes here
+
+// [#478]: add unit tests for non 3DS, wallets & webhooks in connector tests