Bug: [FEATURE] Create a dummy connector for internal and external testing of payments and refunds flows



### Feature Description

A dummy test connector needs to be created with the ability to process all the payment methods available on Hyperswitch. This dummy connector will be useful for internal and external testing and it will be used extensively by those trying to test or integrate Hyperswitch without setting up any active accounts with any of the processors. 

The dummy test connector will be able to simulate most basic scenarios (success/failure/pending) for all the available payment methods by having separate test payment method data for each of these flows. Payment failure can include further breakdown in scenarios according to the payment methods. 

For example, there should be separate test card numbers for simulating success, failure, pending statuses of 3DS and Non 3DS flows. Under failure, different test card numbers should enable simulating errors like invalid card info, insufficient funds, declined by gateway, declined by issuing bank, declines due to bad fraud score, etc. 

### Possible Implementation

We would need to create a dummy connector to test all the payment flows, refund flows, webhooks, etc.

The two major tasks are:
1. Server implementation for dummy connector for the following endpoints
a. payments #980
b. refunds #1071 
c. webhooks 

2. Integrating Hyperswitch with the dummy connector for the following endpoints
a. payments #1084 
b. refunds #1084 
c. webhooks 

3. Enable Dummy Connector and make it default

**Cards:**
Non- 3DS payments flow https://github.com/juspay/hyperswitch/issues/727


### Have you spent some time to check if this feature request has been raised before?

- [X] I checked and didn't find similar issue

### Have you read the Contributing Guidelines?

- [X] I have read the [Contributing Guidelines](https://github.com/juspay/hyperswitch/blob/main/docs/CONTRIBUTING.md)

### Are you willing to submit a PR?

No, but I'm happy to collaborate on a PR with someone else
diff --git a/crates/api_models/src/enums.rs b/crates/api_models/src/enums.rs
index ae13a34d103..f391f3a3a60 100644
--- a/crates/api_models/src/enums.rs
+++ b/crates/api_models/src/enums.rs
@@ -596,9 +596,17 @@ pub enum Connector {
     Dummy,
     Iatapay,
     #[cfg(feature = "dummy_connector")]
-    #[serde(rename = "dummyconnector")]
-    #[strum(serialize = "dummyconnector")]
-    DummyConnector,
+    #[serde(rename = "dummyconnector1")]
+    #[strum(serialize = "dummyconnector1")]
+    DummyConnector1,
+    #[cfg(feature = "dummy_connector")]
+    #[serde(rename = "dummyconnector2")]
+    #[strum(serialize = "dummyconnector2")]
+    DummyConnector2,
+    #[cfg(feature = "dummy_connector")]
+    #[serde(rename = "dummyconnector3")]
+    #[strum(serialize = "dummyconnector3")]
+    DummyConnector3,
     Opennode,
     Bambora,
     Dlocal,
@@ -659,9 +667,17 @@ impl Connector {
 #[strum(serialize_all = "snake_case")]
 pub enum RoutableConnectors {
     #[cfg(feature = "dummy_connector")]
-    #[serde(rename = "dummyconnector")]
-    #[strum(serialize = "dummyconnector")]
-    DummyConnector,
+    #[serde(rename = "dummyconnector1")]
+    #[strum(serialize = "dummyconnector1")]
+    DummyConnector1,
+    #[cfg(feature = "dummy_connector")]
+    #[serde(rename = "dummyconnector2")]
+    #[strum(serialize = "dummyconnector2")]
+    DummyConnector2,
+    #[cfg(feature = "dummy_connector")]
+    #[serde(rename = "dummyconnector3")]
+    #[strum(serialize = "dummyconnector3")]
+    DummyConnector3,
     Aci,
     Adyen,
     Airwallex,
diff --git a/crates/router/Cargo.toml b/crates/router/Cargo.toml
index 88fcf92d38b..df0ec834610 100644
--- a/crates/router/Cargo.toml
+++ b/crates/router/Cargo.toml
@@ -10,7 +10,7 @@ license = "Apache-2.0"
 build = "src/build.rs"
 
 [features]
-default = ["kv_store", "stripe", "oltp", "olap", "accounts_cache"]
+default = ["kv_store", "stripe", "oltp", "olap", "accounts_cache", "dummy_connector"]
 s3 = ["dep:aws-sdk-s3","dep:aws-config"]
 kms = ["external_services/kms","dep:aws-config"]
 basilisk = ["kms"]
diff --git a/crates/router/src/connector/dummyconnector.rs b/crates/router/src/connector/dummyconnector.rs
index b7928a18c06..75565174836 100644
--- a/crates/router/src/connector/dummyconnector.rs
+++ b/crates/router/src/connector/dummyconnector.rs
@@ -21,32 +21,33 @@ use crate::{
 };
 
 #[derive(Debug, Clone)]
-pub struct DummyConnector;
-
-impl api::Payment for DummyConnector {}
-impl api::PaymentSession for DummyConnector {}
-impl api::ConnectorAccessToken for DummyConnector {}
-impl api::PreVerify for DummyConnector {}
-impl api::PaymentAuthorize for DummyConnector {}
-impl api::PaymentSync for DummyConnector {}
-impl api::PaymentCapture for DummyConnector {}
-impl api::PaymentVoid for DummyConnector {}
-impl api::Refund for DummyConnector {}
-impl api::RefundExecute for DummyConnector {}
-impl api::RefundSync for DummyConnector {}
-impl api::PaymentToken for DummyConnector {}
-
-impl
+pub struct DummyConnector<const T: u8>;
+
+impl<const T: u8> api::Payment for DummyConnector<T> {}
+impl<const T: u8> api::PaymentSession for DummyConnector<T> {}
+impl<const T: u8> api::ConnectorAccessToken for DummyConnector<T> {}
+impl<const T: u8> api::PreVerify for DummyConnector<T> {}
+impl<const T: u8> api::PaymentAuthorize for DummyConnector<T> {}
+impl<const T: u8> api::PaymentSync for DummyConnector<T> {}
+impl<const T: u8> api::PaymentCapture for DummyConnector<T> {}
+impl<const T: u8> api::PaymentVoid for DummyConnector<T> {}
+impl<const T: u8> api::Refund for DummyConnector<T> {}
+impl<const T: u8> api::RefundExecute for DummyConnector<T> {}
+impl<const T: u8> api::RefundSync for DummyConnector<T> {}
+impl<const T: u8> api::PaymentToken for DummyConnector<T> {}
+
+impl<const T: u8>
     ConnectorIntegration<
         api::PaymentMethodToken,
         types::PaymentMethodTokenizationData,
         types::PaymentsResponseData,
-    > for DummyConnector
+    > for DummyConnector<T>
 {
     // Not Implemented (R)
 }
 
-impl<Flow, Request, Response> ConnectorCommonExt<Flow, Request, Response> for DummyConnector
+impl<const T: u8, Flow, Request, Response> ConnectorCommonExt<Flow, Request, Response>
+    for DummyConnector<T>
 where
     Self: ConnectorIntegration<Flow, Request, Response>,
 {
@@ -65,9 +66,14 @@ where
     }
 }
 
-impl ConnectorCommon for DummyConnector {
+impl<const T: u8> ConnectorCommon for DummyConnector<T> {
     fn id(&self) -> &'static str {
-        "dummyconnector"
+        match T {
+            1 => "dummyconnector1",
+            2 => "dummyconnector2",
+            3 => "dummyconnector3",
+            _ => "dummyconnector",
+        }
     }
 
     fn common_get_content_type(&self) -> &'static str {
@@ -105,24 +111,28 @@ impl ConnectorCommon for DummyConnector {
     }
 }
 
-impl ConnectorIntegration<api::Session, types::PaymentsSessionData, types::PaymentsResponseData>
-    for DummyConnector
+impl<const T: u8>
+    ConnectorIntegration<api::Session, types::PaymentsSessionData, types::PaymentsResponseData>
+    for DummyConnector<T>
 {
     //TODO: implement sessions flow
 }
 
-impl ConnectorIntegration<api::AccessTokenAuth, types::AccessTokenRequestData, types::AccessToken>
-    for DummyConnector
+impl<const T: u8>
+    ConnectorIntegration<api::AccessTokenAuth, types::AccessTokenRequestData, types::AccessToken>
+    for DummyConnector<T>
 {
 }
 
-impl ConnectorIntegration<api::Verify, types::VerifyRequestData, types::PaymentsResponseData>
-    for DummyConnector
+impl<const T: u8>
+    ConnectorIntegration<api::Verify, types::VerifyRequestData, types::PaymentsResponseData>
+    for DummyConnector<T>
 {
 }
 
-impl ConnectorIntegration<api::Authorize, types::PaymentsAuthorizeData, types::PaymentsResponseData>
-    for DummyConnector
+impl<const T: u8>
+    ConnectorIntegration<api::Authorize, types::PaymentsAuthorizeData, types::PaymentsResponseData>
+    for DummyConnector<T>
 {
     fn get_headers(
         &self,
@@ -214,8 +224,9 @@ impl ConnectorIntegration<api::Authorize, types::PaymentsAuthorizeData, types::P
     }
 }
 
-impl ConnectorIntegration<api::PSync, types::PaymentsSyncData, types::PaymentsResponseData>
-    for DummyConnector
+impl<const T: u8>
+    ConnectorIntegration<api::PSync, types::PaymentsSyncData, types::PaymentsResponseData>
+    for DummyConnector<T>
 {
     fn get_headers(
         &self,
@@ -290,8 +301,9 @@ impl ConnectorIntegration<api::PSync, types::PaymentsSyncData, types::PaymentsRe
     }
 }
 
-impl ConnectorIntegration<api::Capture, types::PaymentsCaptureData, types::PaymentsResponseData>
-    for DummyConnector
+impl<const T: u8>
+    ConnectorIntegration<api::Capture, types::PaymentsCaptureData, types::PaymentsResponseData>
+    for DummyConnector<T>
 {
     fn get_headers(
         &self,
@@ -362,13 +374,14 @@ impl ConnectorIntegration<api::Capture, types::PaymentsCaptureData, types::Payme
     }
 }
 
-impl ConnectorIntegration<api::Void, types::PaymentsCancelData, types::PaymentsResponseData>
-    for DummyConnector
+impl<const T: u8>
+    ConnectorIntegration<api::Void, types::PaymentsCancelData, types::PaymentsResponseData>
+    for DummyConnector<T>
 {
 }
 
-impl ConnectorIntegration<api::Execute, types::RefundsData, types::RefundsResponseData>
-    for DummyConnector
+impl<const T: u8> ConnectorIntegration<api::Execute, types::RefundsData, types::RefundsResponseData>
+    for DummyConnector<T>
 {
     fn get_headers(
         &self,
@@ -449,8 +462,8 @@ impl ConnectorIntegration<api::Execute, types::RefundsData, types::RefundsRespon
     }
 }
 
-impl ConnectorIntegration<api::RSync, types::RefundsData, types::RefundsResponseData>
-    for DummyConnector
+impl<const T: u8> ConnectorIntegration<api::RSync, types::RefundsData, types::RefundsResponseData>
+    for DummyConnector<T>
 {
     fn get_headers(
         &self,
@@ -519,7 +532,7 @@ impl ConnectorIntegration<api::RSync, types::RefundsData, types::RefundsResponse
 }
 
 #[async_trait::async_trait]
-impl api::IncomingWebhook for DummyConnector {
+impl<const T: u8> api::IncomingWebhook for DummyConnector<T> {
     fn get_webhook_object_reference_id(
         &self,
         _request: &api::IncomingWebhookRequestDetails<'_>,
diff --git a/crates/router/src/core/payments/flows.rs b/crates/router/src/core/payments/flows.rs
index 0a1be35c6c1..fa765c3ac8b 100644
--- a/crates/router/src/core/payments/flows.rs
+++ b/crates/router/src/core/payments/flows.rs
@@ -101,7 +101,16 @@ macro_rules! default_imp_for_complete_authorize{
 }
 
 #[cfg(feature = "dummy_connector")]
-default_imp_for_complete_authorize!(connector::DummyConnector);
+impl<const T: u8> api::PaymentsCompleteAuthorize for connector::DummyConnector<T> {}
+#[cfg(feature = "dummy_connector")]
+impl<const T: u8>
+    services::ConnectorIntegration<
+        api::CompleteAuthorize,
+        types::CompleteAuthorizeData,
+        types::PaymentsResponseData,
+    > for connector::DummyConnector<T>
+{
+}
 
 default_imp_for_complete_authorize!(
     connector::Aci,
@@ -147,7 +156,16 @@ macro_rules! default_imp_for_create_customer{
 }
 
 #[cfg(feature = "dummy_connector")]
-default_imp_for_create_customer!(connector::DummyConnector);
+impl<const T: u8> api::ConnectorCustomer for connector::DummyConnector<T> {}
+#[cfg(feature = "dummy_connector")]
+impl<const T: u8>
+    services::ConnectorIntegration<
+        api::CreateConnectorCustomer,
+        types::ConnectorCustomerData,
+        types::PaymentsResponseData,
+    > for connector::DummyConnector<T>
+{
+}
 
 default_imp_for_create_customer!(
     connector::Aci,
@@ -201,7 +219,16 @@ macro_rules! default_imp_for_connector_redirect_response{
 }
 
 #[cfg(feature = "dummy_connector")]
-default_imp_for_connector_redirect_response!(connector::DummyConnector);
+impl<const T: u8> services::ConnectorRedirectResponse for connector::DummyConnector<T> {
+    fn get_flow_type(
+        &self,
+        _query_params: &str,
+        _json_payload: Option<serde_json::Value>,
+        _action: services::PaymentAction,
+    ) -> CustomResult<payments::CallConnectorAction, ConnectorError> {
+        Ok(payments::CallConnectorAction::Trigger)
+    }
+}
 
 default_imp_for_connector_redirect_response!(
     connector::Aci,
@@ -237,7 +264,7 @@ macro_rules! default_imp_for_connector_request_id{
 }
 
 #[cfg(feature = "dummy_connector")]
-default_imp_for_connector_request_id!(connector::DummyConnector);
+impl<const T: u8> api::ConnectorTransactionId for connector::DummyConnector<T> {}
 
 default_imp_for_connector_request_id!(
     connector::Aci,
@@ -290,7 +317,18 @@ macro_rules! default_imp_for_accept_dispute{
 }
 
 #[cfg(feature = "dummy_connector")]
-default_imp_for_accept_dispute!(connector::DummyConnector);
+impl<const T: u8> api::Dispute for connector::DummyConnector<T> {}
+#[cfg(feature = "dummy_connector")]
+impl<const T: u8> api::AcceptDispute for connector::DummyConnector<T> {}
+#[cfg(feature = "dummy_connector")]
+impl<const T: u8>
+    services::ConnectorIntegration<
+        api::Accept,
+        types::AcceptDisputeRequestData,
+        types::AcceptDisputeResponse,
+    > for connector::DummyConnector<T>
+{
+}
 
 default_imp_for_accept_dispute!(
     connector::Aci,
@@ -352,7 +390,29 @@ macro_rules! default_imp_for_file_upload{
 }
 
 #[cfg(feature = "dummy_connector")]
-default_imp_for_file_upload!(connector::DummyConnector);
+impl<const T: u8> api::FileUpload for connector::DummyConnector<T> {}
+#[cfg(feature = "dummy_connector")]
+impl<const T: u8> api::UploadFile for connector::DummyConnector<T> {}
+#[cfg(feature = "dummy_connector")]
+impl<const T: u8>
+    services::ConnectorIntegration<
+        api::Upload,
+        types::UploadFileRequestData,
+        types::UploadFileResponse,
+    > for connector::DummyConnector<T>
+{
+}
+#[cfg(feature = "dummy_connector")]
+impl<const T: u8> api::RetrieveFile for connector::DummyConnector<T> {}
+#[cfg(feature = "dummy_connector")]
+impl<const T: u8>
+    services::ConnectorIntegration<
+        api::Retrieve,
+        types::RetrieveFileRequestData,
+        types::RetrieveFileResponse,
+    > for connector::DummyConnector<T>
+{
+}
 
 default_imp_for_file_upload!(
     connector::Aci,
@@ -404,7 +464,16 @@ macro_rules! default_imp_for_submit_evidence{
 }
 
 #[cfg(feature = "dummy_connector")]
-default_imp_for_submit_evidence!(connector::DummyConnector);
+impl<const T: u8> api::SubmitEvidence for connector::DummyConnector<T> {}
+#[cfg(feature = "dummy_connector")]
+impl<const T: u8>
+    services::ConnectorIntegration<
+        api::Evidence,
+        types::SubmitEvidenceRequestData,
+        types::SubmitEvidenceResponse,
+    > for connector::DummyConnector<T>
+{
+}
 
 default_imp_for_submit_evidence!(
     connector::Aci,
@@ -456,7 +525,16 @@ macro_rules! default_imp_for_defend_dispute{
 }
 
 #[cfg(feature = "dummy_connector")]
-default_imp_for_defend_dispute!(connector::DummyConnector);
+impl<const T: u8> api::DefendDispute for connector::DummyConnector<T> {}
+#[cfg(feature = "dummy_connector")]
+impl<const T: u8>
+    services::ConnectorIntegration<
+        api::Defend,
+        types::DefendDisputeRequestData,
+        types::DefendDisputeResponse,
+    > for connector::DummyConnector<T>
+{
+}
 
 default_imp_for_defend_dispute!(
     connector::Aci,
diff --git a/crates/router/src/types/api.rs b/crates/router/src/types/api.rs
index 8bcd3a056f3..48f7eec8eb7 100644
--- a/crates/router/src/types/api.rs
+++ b/crates/router/src/types/api.rs
@@ -212,7 +212,11 @@ impl ConnectorData {
             "cybersource" => Ok(Box::new(&connector::Cybersource)),
             "dlocal" => Ok(Box::new(&connector::Dlocal)),
             #[cfg(feature = "dummy_connector")]
-            "dummyconnector" => Ok(Box::new(&connector::DummyConnector)),
+            "dummyconnector1" => Ok(Box::new(&connector::DummyConnector::<1>)),
+            #[cfg(feature = "dummy_connector")]
+            "dummyconnector2" => Ok(Box::new(&connector::DummyConnector::<2>)),
+            #[cfg(feature = "dummy_connector")]
+            "dummyconnector3" => Ok(Box::new(&connector::DummyConnector::<3>)),
             "fiserv" => Ok(Box::new(&connector::Fiserv)),
             "forte" => Ok(Box::new(&connector::Forte)),
             "globalpay" => Ok(Box::new(&connector::Globalpay)),
diff --git a/crates/router/tests/connectors/dummyconnector.rs b/crates/router/tests/connectors/dummyconnector.rs
index 0449647c3c2..c8a9d1acb89 100644
--- a/crates/router/tests/connectors/dummyconnector.rs
+++ b/crates/router/tests/connectors/dummyconnector.rs
@@ -16,8 +16,8 @@ impl utils::Connector for DummyConnectorTest {
     fn get_data(&self) -> types::api::ConnectorData {
         use router::connector::DummyConnector;
         types::api::ConnectorData {
-            connector: Box::new(&DummyConnector),
-            connector_name: types::Connector::DummyConnector,
+            connector: Box::new(&DummyConnector::<1>),
+            connector_name: types::Connector::DummyConnector1,
             get_token: types::api::GetToken::Connector,
         }
     }

## 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 -->
Add multiple dummy connectors and enable dummy connector by default

### 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).
-->
Closes #726.


## 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)?
-->


## 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
- [ ] I added unit tests for my changes where possible
- [ ] I added a [CHANGELOG](/CHANGELOG.md) entry if applicable
