Bug: [FEATURE]: [GlobalPayments] Use `connector_response_reference_id` as reference to merchant



### :memo: Feature Description

- Reference id are used to map transactions in the connector’s dashboard.
- Hyperswitch manages several reference ids, such as `payment_id`, `attempt_id`, and `connector_transaction_id` for a single transaction. 
- However, merchants may encounter uncertainty when determining which ID to utilize in the connector dashboard to identify the payment.

### :hammer: Possible Implementation

- When we receive a response from the connector for the payment, we deserialize it and populate the `response` field in RouterData. 
- For the `TransactionResponse` type, we must fill the `connector_response_reference_id` with a corresponding reference id for the merchant to identify the transaction. 
- One might need to have exposure to api docs of the connector for which it is being implemented to decide what to fill in connector_response_reference_id.
- You can check this PR for further reference https://github.com/juspay/hyperswitch/pull/1735

🔖 Note: All the changes needed should be contained within `hyperswitch/crates/router/src/connector/`


### :package: Have you spent some time checking if this feature request has been raised before?

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

### :package: Have you read the Contributing Guidelines?

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

###  :sparkles: Are you willing to submit a PR?

diff --git a/Cargo.lock b/Cargo.lock
index 082bb476dec..fff48158ded 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -422,45 +422,6 @@ version = "0.7.3"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "8868f09ff8cea88b079da74ae569d9b8c62a23c68c746240b704ee6f7525c89c"
 
-[[package]]
-name = "asn1-rs"
-version = "0.5.2"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "7f6fd5ddaf0351dff5b8da21b2fb4ff8e08ddd02857f0bf69c47639106c0fff0"
-dependencies = [
- "asn1-rs-derive",
- "asn1-rs-impl",
- "displaydoc",
- "nom",
- "num-traits",
- "rusticata-macros",
- "thiserror",
- "time 0.3.22",
-]
-
-[[package]]
-name = "asn1-rs-derive"
-version = "0.4.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "726535892e8eae7e70657b4c8ea93d26b8553afb1ce617caee529ef96d7dee6c"
-dependencies = [
- "proc-macro2",
- "quote",
- "syn 1.0.109",
- "synstructure",
-]
-
-[[package]]
-name = "asn1-rs-impl"
-version = "0.1.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "2777730b2039ac0f95f093556e61b6d26cebed5393ca6f152717777cec3a42ed"
-dependencies = [
- "proc-macro2",
- "quote",
- "syn 1.0.109",
-]
-
 [[package]]
 name = "assert-json-diff"
 version = "2.0.2"
@@ -533,7 +494,7 @@ dependencies = [
  "log",
  "parking",
  "polling",
- "rustix 0.37.20",
+ "rustix",
  "slab",
  "socket2",
  "waker-fn",
@@ -567,7 +528,7 @@ checksum = "16e62a023e7c117e27523144c5d2459f4397fcc3cab0085af8e2224f643a0193"
 dependencies = [
  "proc-macro2",
  "quote",
- "syn 2.0.32",
+ "syn 2.0.29",
 ]
 
 [[package]]
@@ -578,7 +539,7 @@ checksum = "bc00ceb34980c03614e35a3a4e218276a0a824e911d07651cd0d858a51e8c0f0"
 dependencies = [
  "proc-macro2",
  "quote",
- "syn 2.0.32",
+ "syn 2.0.29",
 ]
 
 [[package]]
@@ -1189,9 +1150,9 @@ checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a"
 
 [[package]]
 name = "bitflags"
-version = "2.4.0"
+version = "2.3.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "b4682ae6287fcf752ecaabbfcc7b6f9b72aa33933dc23a554d853aea8eea8635"
+checksum = "6dbe3c979c178231552ecba20214a8272df4e09f232a87aef4320cf06539aded"
 
 [[package]]
 name = "blake3"
@@ -1251,9 +1212,9 @@ checksum = "2c676a478f63e9fa2dd5368a42f28bba0d6c560b775f38583c8bbaa7fcd67c9c"
 
 [[package]]
 name = "bytemuck"
-version = "1.14.0"
+version = "1.13.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "374d28ec25809ee0e23827c2ab573d729e293f281dfe393500e7ad618baa61c6"
+checksum = "17febce684fd15d89027105661fec94afb475cb995fbc59d2865198446ba2eea"
 
 [[package]]
 name = "byteorder"
@@ -1424,7 +1385,7 @@ dependencies = [
  "heck",
  "proc-macro2",
  "quote",
- "syn 2.0.32",
+ "syn 2.0.29",
 ]
 
 [[package]]
@@ -1464,7 +1425,6 @@ dependencies = [
  "fake",
  "futures",
  "hex",
- "http",
  "masking",
  "md5",
  "nanoid",
@@ -1474,7 +1434,6 @@ dependencies = [
  "quick-xml",
  "rand 0.8.5",
  "regex",
- "reqwest",
  "ring",
  "router_env",
  "serde",
@@ -1482,7 +1441,6 @@ dependencies = [
  "serde_urlencoded",
  "signal-hook",
  "signal-hook-tokio",
- "strum 0.24.1",
  "test-case",
  "thiserror",
  "time 0.3.22",
@@ -1693,7 +1651,7 @@ dependencies = [
  "proc-macro2",
  "quote",
  "strsim",
- "syn 2.0.32",
+ "syn 2.0.29",
 ]
 
 [[package]]
@@ -1715,7 +1673,7 @@ checksum = "29a358ff9f12ec09c3e61fef9b5a9902623a695a46a917b07f269bff1445611a"
 dependencies = [
  "darling_core 0.20.1",
  "quote",
- "syn 2.0.32",
+ "syn 2.0.29",
 ]
 
 [[package]]
@@ -1731,12 +1689,6 @@ dependencies = [
  "parking_lot_core",
 ]
 
-[[package]]
-name = "data-encoding"
-version = "2.4.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "c2e66c9d817f1720209181c316d28635c050fa304f9c79e47a520882661b7308"
-
 [[package]]
 name = "data_models"
 version = "0.1.0"
@@ -1746,7 +1698,6 @@ dependencies = [
  "common_enums",
  "common_utils",
  "error-stack",
- "masking",
  "serde",
  "serde_json",
  "strum 0.25.0",
@@ -1783,20 +1734,6 @@ dependencies = [
  "byteorder",
 ]
 
-[[package]]
-name = "der-parser"
-version = "8.2.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "dbd676fbbab537128ef0278adb5576cf363cff6aa22a7b24effe97347cfab61e"
-dependencies = [
- "asn1-rs",
- "displaydoc",
- "nom",
- "num-bigint",
- "num-traits",
- "rusticata-macros",
-]
-
 [[package]]
 name = "derive_deref"
 version = "1.1.1"
@@ -1827,7 +1764,7 @@ version = "2.1.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "f7a532c1f99a0f596f6960a60d1e119e91582b24b39e2d83a190e61262c3ef0c"
 dependencies = [
- "bitflags 2.4.0",
+ "bitflags 2.3.2",
  "byteorder",
  "diesel_derives",
  "itoa",
@@ -1846,7 +1783,7 @@ dependencies = [
  "diesel_table_macro_syntax",
  "proc-macro2",
  "quote",
- "syn 2.0.32",
+ "syn 2.0.29",
 ]
 
 [[package]]
@@ -1879,7 +1816,7 @@ version = "0.1.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "fc5557efc453706fed5e4fa85006fe9817c224c3f480a34c7e5959fd700921c5"
 dependencies = [
- "syn 2.0.32",
+ "syn 2.0.29",
 ]
 
 [[package]]
@@ -1919,17 +1856,6 @@ dependencies = [
  "winapi",
 ]
 
-[[package]]
-name = "displaydoc"
-version = "0.2.4"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "487585f4d0c6655fe74905e2504d8ad6908e4db67f744eb140876906c2f3175d"
-dependencies = [
- "proc-macro2",
- "quote",
- "syn 2.0.32",
-]
-
 [[package]]
 name = "dlv-list"
 version = "0.3.0"
@@ -2336,7 +2262,7 @@ checksum = "89ca545a94061b6365f2c7355b4b32bd20df3ff95f02da9329b34ccc3bd6ee72"
 dependencies = [
  "proc-macro2",
  "quote",
- "syn 2.0.32",
+ "syn 2.0.29",
 ]
 
 [[package]]
@@ -2781,12 +2707,13 @@ checksum = "12b6ee2129af8d4fb011108c73d99a1b83a85977f23b82460c0ae2e25bb4b57f"
 
 [[package]]
 name = "is-terminal"
-version = "0.4.9"
+version = "0.4.7"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "cb0889898416213fab133e1d33a0e5858a48177452750691bde3666d0fdbaf8b"
+checksum = "adcf93614601c8129ddf72e2d5633df827ba6551541c6d8c59520a371475be1f"
 dependencies = [
  "hermit-abi 0.3.1",
- "rustix 0.38.3",
+ "io-lifetimes",
+ "rustix",
  "windows-sys 0.48.0",
 ]
 
@@ -2945,12 +2872,6 @@ version = "0.3.8"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "ef53942eb7bf7ff43a617b3e2c1c4a5ecf5944a7c1bc12d7ee39bbb15e5c1519"
 
-[[package]]
-name = "linux-raw-sys"
-version = "0.4.7"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "1a9bad9f94746442c783ca431b22403b519cd7fbeed0533fdd6328b2f2212128"
-
 [[package]]
 name = "literally"
 version = "0.1.3"
@@ -3305,15 +3226,6 @@ dependencies = [
  "libc",
 ]
 
-[[package]]
-name = "oid-registry"
-version = "0.6.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "9bedf36ffb6ba96c2eb7144ef6270557b52e54b20c0a8e1eb2ff99a6c6959bff"
-dependencies = [
- "asn1-rs",
-]
-
 [[package]]
 name = "once_cell"
 version = "1.18.0"
@@ -3349,7 +3261,7 @@ checksum = "a948666b637a0f465e8564c73e89d4dde00d72d4d473cc972f390fc3dcee7d9c"
 dependencies = [
  "proc-macro2",
  "quote",
- "syn 2.0.32",
+ "syn 2.0.29",
 ]
 
 [[package]]
@@ -3563,7 +3475,7 @@ dependencies = [
  "pest_meta",
  "proc-macro2",
  "quote",
- "syn 2.0.32",
+ "syn 2.0.29",
 ]
 
 [[package]]
@@ -3614,7 +3526,7 @@ checksum = "39407670928234ebc5e6e580247dd567ad73a3578460c5990f9503df207e8f07"
 dependencies = [
  "proc-macro2",
  "quote",
- "syn 2.0.32",
+ "syn 2.0.29",
 ]
 
 [[package]]
@@ -4175,7 +4087,6 @@ dependencies = [
  "nanoid",
  "num_cpus",
  "once_cell",
- "openssl",
  "qrcode",
  "rand 0.8.5",
  "redis_interface",
@@ -4208,7 +4119,6 @@ dependencies = [
  "utoipa-swagger-ui",
  "uuid",
  "wiremock",
- "x509-parser",
 ]
 
 [[package]]
@@ -4282,7 +4192,7 @@ dependencies = [
  "quote",
  "rust-embed-utils",
  "shellexpand",
- "syn 2.0.32",
+ "syn 2.0.29",
  "walkdir",
 ]
 
@@ -4321,15 +4231,6 @@ dependencies = [
  "semver",
 ]
 
-[[package]]
-name = "rusticata-macros"
-version = "4.1.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "faf0c4a6ece9950b9abdb62b1cfcf2a68b3b67a10ba445b3bb85be2a293d0632"
-dependencies = [
- "nom",
-]
-
 [[package]]
 name = "rustix"
 version = "0.37.20"
@@ -4340,20 +4241,7 @@ dependencies = [
  "errno",
  "io-lifetimes",
  "libc",
- "linux-raw-sys 0.3.8",
- "windows-sys 0.48.0",
-]
-
-[[package]]
-name = "rustix"
-version = "0.38.3"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "ac5ffa1efe7548069688cd7028f32591853cd7b5b756d41bcffd2353e4fc75b4"
-dependencies = [
- "bitflags 2.4.0",
- "errno",
- "libc",
- "linux-raw-sys 0.4.7",
+ "linux-raw-sys",
  "windows-sys 0.48.0",
 ]
 
@@ -4540,31 +4428,31 @@ dependencies = [
 
 [[package]]
 name = "serde"
-version = "1.0.188"
+version = "1.0.164"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "cf9e0fcba69a370eed61bcf2b728575f726b50b55cba78064753d708ddc7549e"
+checksum = "9e8c8cf938e98f769bc164923b06dce91cea1751522f46f8466461af04c9027d"
 dependencies = [
  "serde_derive",
 ]
 
 [[package]]
 name = "serde_derive"
-version = "1.0.188"
+version = "1.0.164"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "4eca7ac642d82aa35b60049a6eccb4be6be75e599bd2e9adb5f875a737654af2"
+checksum = "d9735b638ccc51c28bf6914d90a2e9725b377144fc612c49a611fddd1b631d68"
 dependencies = [
  "proc-macro2",
  "quote",
- "syn 2.0.32",
+ "syn 2.0.29",
 ]
 
 [[package]]
 name = "serde_json"
-version = "1.0.106"
+version = "1.0.96"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "2cc66a619ed80bf7a0f6b17dd063a84b88f6dea1813737cf469aef1d081142c2"
+checksum = "057d394a50403bcac12672b2b18fb387ab6d289d957dab67dd201875391e52f1"
 dependencies = [
- "indexmap 2.0.0",
+ "indexmap 1.9.3",
  "itoa",
  "ryu",
  "serde",
@@ -4618,7 +4506,7 @@ checksum = "bcec881020c684085e55a25f7fd888954d56609ef363479dc5a1305eb0d40cab"
 dependencies = [
  "proc-macro2",
  "quote",
- "syn 2.0.32",
+ "syn 2.0.29",
 ]
 
 [[package]]
@@ -4667,7 +4555,7 @@ dependencies = [
  "darling 0.20.1",
  "proc-macro2",
  "quote",
- "syn 2.0.32",
+ "syn 2.0.29",
 ]
 
 [[package]]
@@ -4692,7 +4580,7 @@ checksum = "91d129178576168c589c9ec973feedf7d3126c01ac2bf08795109aa35b69fb8f"
 dependencies = [
  "proc-macro2",
  "quote",
- "syn 2.0.32",
+ "syn 2.0.29",
 ]
 
 [[package]]
@@ -4864,7 +4752,6 @@ dependencies = [
  "ring",
  "router_env",
  "serde",
- "serde_json",
  "thiserror",
  "tokio",
 ]
@@ -4925,7 +4812,7 @@ dependencies = [
  "proc-macro2",
  "quote",
  "rustversion",
- "syn 2.0.32",
+ "syn 2.0.29",
 ]
 
 [[package]]
@@ -4947,9 +4834,9 @@ dependencies = [
 
 [[package]]
 name = "syn"
-version = "2.0.32"
+version = "2.0.29"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "239814284fd6f1a4ffe4ca893952cdd93c224b6a1571c9a9eadd670295c0c9e2"
+checksum = "c324c494eba9d92503e6f1ef2e6df781e78f6a7705a0202d9801b198807d518a"
 dependencies = [
  "proc-macro2",
  "quote",
@@ -4962,18 +4849,6 @@ version = "0.1.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "2047c6ded9c721764247e62cd3b03c09ffc529b2ba5b10ec482ae507a4a70160"
 
-[[package]]
-name = "synstructure"
-version = "0.12.6"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "f36bdaa60a83aca3921b5259d5400cbf5e90fc51931376a9bd4a0eb79aa7210f"
-dependencies = [
- "proc-macro2",
- "quote",
- "syn 1.0.109",
- "unicode-xid",
-]
-
 [[package]]
 name = "tagptr"
 version = "0.2.0"
@@ -4990,7 +4865,7 @@ dependencies = [
  "cfg-if",
  "fastrand",
  "redox_syscall 0.3.5",
- "rustix 0.37.20",
+ "rustix",
  "windows-sys 0.48.0",
 ]
 
@@ -5120,7 +4995,7 @@ checksum = "f9456a42c5b0d803c8cd86e73dd7cc9edd429499f37a3550d286d5e86720569f"
 dependencies = [
  "proc-macro2",
  "quote",
- "syn 2.0.32",
+ "syn 2.0.29",
 ]
 
 [[package]]
@@ -5234,7 +5109,7 @@ checksum = "630bdcf245f78637c13ec01ffae6187cca34625e8c63150d424b59e55af2675e"
 dependencies = [
  "proc-macro2",
  "quote",
- "syn 2.0.32",
+ "syn 2.0.29",
 ]
 
 [[package]]
@@ -5581,12 +5456,6 @@ version = "1.10.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "1dd624098567895118886609431a7c3b8f516e41d30e0643f03d94592a147e36"
 
-[[package]]
-name = "unicode-xid"
-version = "0.2.4"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "f962df74c8c05a667b5ee8bcf162993134c104e96440b663c8daa176dc772d8c"
-
 [[package]]
 name = "unidecode"
 version = "0.3.0"
@@ -5644,7 +5513,7 @@ dependencies = [
  "proc-macro-error",
  "proc-macro2",
  "quote",
- "syn 2.0.32",
+ "syn 2.0.29",
 ]
 
 [[package]]
@@ -5783,7 +5652,7 @@ dependencies = [
  "once_cell",
  "proc-macro2",
  "quote",
- "syn 2.0.32",
+ "syn 2.0.29",
  "wasm-bindgen-shared",
 ]
 
@@ -5817,7 +5686,7 @@ checksum = "54681b18a46765f095758388f2d0cf16eb8d4169b639ab575a8f5693af210c7b"
 dependencies = [
  "proc-macro2",
  "quote",
- "syn 2.0.32",
+ "syn 2.0.29",
  "wasm-bindgen-backend",
  "wasm-bindgen-shared",
 ]
@@ -6085,23 +5954,6 @@ dependencies = [
  "tokio",
 ]
 
-[[package]]
-name = "x509-parser"
-version = "0.15.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "7069fba5b66b9193bd2c5d3d4ff12b839118f6bcbef5328efafafb5395cf63da"
-dependencies = [
- "asn1-rs",
- "data-encoding",
- "der-parser",
- "lazy_static",
- "nom",
- "oid-registry",
- "rusticata-macros",
- "thiserror",
- "time 0.3.22",
-]
-
 [[package]]
 name = "xmlparser"
 version = "0.13.5"
diff --git a/crates/router/src/connector/adyen.rs b/crates/router/src/connector/adyen.rs
index 1801f108f2e..9da548baf24 100644
--- a/crates/router/src/connector/adyen.rs
+++ b/crates/router/src/connector/adyen.rs
@@ -80,8 +80,10 @@ impl ConnectorValidation for Adyen {
     ) -> CustomResult<(), errors::ConnectorError> {
         let capture_method = capture_method.unwrap_or_default();
         match capture_method {
-            enums::CaptureMethod::Automatic | enums::CaptureMethod::Manual => Ok(()),
-            enums::CaptureMethod::ManualMultiple | enums::CaptureMethod::Scheduled => Err(
+            enums::CaptureMethod::Automatic
+            | enums::CaptureMethod::Manual
+            | enums::CaptureMethod::ManualMultiple => Ok(()),
+            enums::CaptureMethod::Scheduled => Err(
                 connector_utils::construct_not_implemented_error_report(capture_method, self.id()),
             ),
         }
@@ -204,6 +206,7 @@ impl
                 data: data.clone(),
                 http_code: res.status_code,
             },
+            None,
             false,
         ))
         .change_context(errors::ConnectorError::ResponseHandlingFailed)
@@ -468,15 +471,18 @@ impl
             .response
             .parse_struct("AdyenPaymentResponse")
             .change_context(errors::ConnectorError::ResponseDeserializationFailed)?;
-        let is_manual_capture =
-            data.request.capture_method == Some(storage_enums::CaptureMethod::Manual);
+        let is_multiple_capture_sync = match data.request.sync_type {
+            types::SyncRequestType::MultipleCaptureSync(_) => true,
+            types::SyncRequestType::SinglePaymentSync => false,
+        };
         types::RouterData::try_from((
             types::ResponseRouterData {
                 response,
                 data: data.clone(),
                 http_code: res.status_code,
             },
-            is_manual_capture,
+            data.request.capture_method,
+            is_multiple_capture_sync,
         ))
         .change_context(errors::ConnectorError::ResponseHandlingFailed)
     }
@@ -496,6 +502,12 @@ impl
             reason: None,
         })
     }
+
+    fn get_multiple_capture_sync_method(
+        &self,
+    ) -> CustomResult<services::CaptureSyncMethod, errors::ConnectorError> {
+        Ok(services::CaptureSyncMethod::Individual)
+    }
 }
 
 #[async_trait::async_trait]
@@ -624,15 +636,14 @@ impl
             .response
             .parse_struct("AdyenPaymentResponse")
             .change_context(errors::ConnectorError::ResponseDeserializationFailed)?;
-        let is_manual_capture =
-            data.request.capture_method == Some(diesel_models::enums::CaptureMethod::Manual);
         types::RouterData::try_from((
             types::ResponseRouterData {
                 response,
                 data: data.clone(),
                 http_code: res.status_code,
             },
-            is_manual_capture,
+            data.request.capture_method,
+            false,
         ))
         .change_context(errors::ConnectorError::ResponseHandlingFailed)
     }
@@ -1437,6 +1448,16 @@ impl api::IncomingWebhook for Adyen {
     ) -> CustomResult<api_models::webhooks::ObjectReferenceId, errors::ConnectorError> {
         let notif = get_webhook_object_from_body(request.body)
             .change_context(errors::ConnectorError::WebhookReferenceIdNotFound)?;
+        // for capture_event, original_reference field will have the authorized payment's PSP reference
+        if adyen::is_capture_event(&notif.event_code) {
+            return Ok(api_models::webhooks::ObjectReferenceId::PaymentId(
+                api_models::payments::PaymentIdType::ConnectorTransactionId(
+                    notif
+                        .original_reference
+                        .ok_or(errors::ConnectorError::WebhookReferenceIdNotFound)?,
+                ),
+            ));
+        }
         if adyen::is_transaction_event(&notif.event_code) {
             return Ok(api_models::webhooks::ObjectReferenceId::PaymentId(
                 api_models::payments::PaymentIdType::PaymentAttemptId(notif.merchant_reference),
diff --git a/crates/router/src/connector/adyen/transformers.rs b/crates/router/src/connector/adyen/transformers.rs
index c4d0c4f2c50..7e85d8d42da 100644
--- a/crates/router/src/connector/adyen/transformers.rs
+++ b/crates/router/src/connector/adyen/transformers.rs
@@ -278,6 +278,7 @@ pub struct Response {
     refusal_reason: Option<String>,
     refusal_reason_code: Option<String>,
     additional_data: Option<AdditionalData>,
+    event_code: Option<WebhookEventCode>,
 }
 
 #[derive(Debug, Clone, Serialize, Deserialize)]
@@ -1449,7 +1450,8 @@ fn get_browser_info(
 
 fn get_additional_data(item: &types::PaymentsAuthorizeRouterData) -> Option<AdditionalData> {
     match item.request.capture_method {
-        Some(diesel_models::enums::CaptureMethod::Manual) => Some(AdditionalData {
+        Some(diesel_models::enums::CaptureMethod::Manual)
+        | Some(diesel_models::enums::CaptureMethod::ManualMultiple) => Some(AdditionalData {
             authorisation_type: Some(AuthType::PreAuth),
             manual_capture: Some(true),
             network_tx_reference: None,
@@ -2822,6 +2824,7 @@ pub fn get_adyen_response(
 > {
     let status =
         storage_enums::AttemptStatus::foreign_from((is_capture_manual, response.result_code));
+    let status = update_attempt_status_based_on_event_type_if_needed(status, &response.event_code);
     let error = if response.refusal_reason.is_some() || response.refusal_reason_code.is_some() {
         Some(types::ErrorResponse {
             code: response
@@ -2860,6 +2863,42 @@ pub fn get_adyen_response(
     Ok((status, error, payments_response_data))
 }
 
+pub fn get_adyen_response_for_multiple_partial_capture(
+    response: Response,
+    status_code: u16,
+) -> errors::CustomResult<
+    (
+        storage_enums::AttemptStatus,
+        Option<types::ErrorResponse>,
+        types::PaymentsResponseData,
+    ),
+    errors::ConnectorError,
+> {
+    let (status, error, _) = get_adyen_response(response.clone(), true, status_code)?;
+    let status = update_attempt_status_based_on_event_type_if_needed(status, &response.event_code);
+    let capture_sync_response_list = utils::construct_captures_response_hashmap(vec![response]);
+    Ok((
+        status,
+        error,
+        types::PaymentsResponseData::MultipleCaptureResponse {
+            capture_sync_response_list,
+        },
+    ))
+}
+
+fn update_attempt_status_based_on_event_type_if_needed(
+    status: storage_enums::AttemptStatus,
+    event: &Option<WebhookEventCode>,
+) -> storage_enums::AttemptStatus {
+    if status == storage_enums::AttemptStatus::Authorized
+        && event == &Some(WebhookEventCode::Capture)
+    {
+        storage_enums::AttemptStatus::Charged
+    } else {
+        status
+    }
+}
+
 pub fn get_redirection_response(
     response: RedirectionResponse,
     is_manual_capture: bool,
@@ -3269,21 +3308,26 @@ pub fn get_present_to_shopper_metadata(
 impl<F, Req>
     TryFrom<(
         types::ResponseRouterData<F, AdyenPaymentResponse, Req, types::PaymentsResponseData>,
+        Option<storage_enums::CaptureMethod>,
         bool,
     )> for types::RouterData<F, Req, types::PaymentsResponseData>
 {
     type Error = Error;
     fn try_from(
-        items: (
+        (item, capture_method, is_multiple_capture_psync_flow): (
             types::ResponseRouterData<F, AdyenPaymentResponse, Req, types::PaymentsResponseData>,
+            Option<storage_enums::CaptureMethod>,
             bool,
         ),
     ) -> Result<Self, Self::Error> {
-        let item = items.0;
-        let is_manual_capture = items.1;
+        let is_manual_capture = utils::is_manual_capture(capture_method);
         let (status, error, payment_response_data) = match item.response {
             AdyenPaymentResponse::Response(response) => {
-                get_adyen_response(*response, is_manual_capture, item.http_code)?
+                if is_multiple_capture_psync_flow {
+                    get_adyen_response_for_multiple_partial_capture(*response, item.http_code)?
+                } else {
+                    get_adyen_response(*response, is_manual_capture, item.http_code)?
+                }
             }
             AdyenPaymentResponse::PresentToShopper(response) => {
                 get_present_to_shopper_response(*response, is_manual_capture, item.http_code)?
@@ -3319,9 +3363,15 @@ impl TryFrom<&types::PaymentsCaptureRouterData> for AdyenCaptureRequest {
     type Error = Error;
     fn try_from(item: &types::PaymentsCaptureRouterData) -> Result<Self, Self::Error> {
         let auth_type = AdyenAuthType::try_from(&item.connector_auth_type)?;
+        let reference = match item.request.multiple_capture_data.clone() {
+            // if multiple capture request, send capture_id as our reference for the capture
+            Some(multiple_capture_request_data) => multiple_capture_request_data.capture_reference,
+            // if single capture request, send connector_request_reference_id(attempt_id)
+            None => item.connector_request_reference_id.clone(),
+        };
         Ok(Self {
             merchant_account: auth_type.merchant_account,
-            reference: item.connector_request_reference_id.clone(),
+            reference,
             amount: Amount {
                 currency: item.request.currency.to_string(),
                 value: item.request.amount_to_capture,
@@ -3348,13 +3398,18 @@ impl TryFrom<types::PaymentsCaptureResponseRouterData<AdyenCaptureResponse>>
     fn try_from(
         item: types::PaymentsCaptureResponseRouterData<AdyenCaptureResponse>,
     ) -> Result<Self, Self::Error> {
+        let connector_transaction_id = if item.data.request.multiple_capture_data.is_some() {
+            item.response.psp_reference
+        } else {
+            item.response.payment_psp_reference
+        };
         Ok(Self {
             // From the docs, the only value returned is "received", outcome of refund is available
             // through refund notification webhook
             // For more info: https://docs.adyen.com/online-payments/capture
             status: storage_enums::AttemptStatus::Pending,
             response: Ok(types::PaymentsResponseData::TransactionResponse {
-                resource_id: types::ResponseId::ConnectorTransactionId(item.response.psp_reference),
+                resource_id: types::ResponseId::ConnectorTransactionId(connector_transaction_id),
                 redirection_data: None,
                 mandate_reference: None,
                 connector_metadata: None,
@@ -3493,7 +3548,7 @@ pub struct AdyenAmountWH {
     pub currency: String,
 }
 
-#[derive(Clone, Debug, Deserialize, strum::Display)]
+#[derive(Clone, Debug, Deserialize, Serialize, strum::Display, PartialEq)]
 #[serde(rename_all = "SCREAMING_SNAKE_CASE")]
 #[strum(serialize_all = "SCREAMING_SNAKE_CASE")]
 pub enum WebhookEventCode {
@@ -3507,6 +3562,8 @@ pub enum WebhookEventCode {
     SecondChargeback,
     PrearbitrationWon,
     PrearbitrationLost,
+    Capture,
+    CaptureFailed,
     #[serde(other)]
     Unknown,
 }
@@ -3515,6 +3572,13 @@ pub fn is_transaction_event(event_code: &WebhookEventCode) -> bool {
     matches!(event_code, WebhookEventCode::Authorisation)
 }
 
+pub fn is_capture_event(event_code: &WebhookEventCode) -> bool {
+    matches!(
+        event_code,
+        WebhookEventCode::Capture | WebhookEventCode::CaptureFailed
+    )
+}
+
 pub fn is_refund_event(event_code: &WebhookEventCode) -> bool {
     matches!(
         event_code,
@@ -3559,6 +3623,8 @@ impl ForeignFrom<(WebhookEventCode, Option<DisputeStatus>)> for webhooks::Incomi
             (WebhookEventCode::PrearbitrationWon, _) => Self::DisputeWon,
             (WebhookEventCode::PrearbitrationLost, _) => Self::DisputeLost,
             (WebhookEventCode::Unknown, _) => Self::EventNotSupported,
+            (WebhookEventCode::Capture, _) => Self::PaymentIntentSuccess,
+            (WebhookEventCode::CaptureFailed, _) => Self::PaymentIntentFailure,
         }
     }
 }
@@ -3619,10 +3685,33 @@ impl From<AdyenNotificationRequestItemWH> for Response {
             refusal_reason: None,
             refusal_reason_code: None,
             additional_data: None,
+            event_code: Some(notif.event_code),
         }
     }
 }
 
+impl utils::MultipleCaptureSyncResponse for Response {
+    fn get_connector_capture_id(&self) -> String {
+        self.psp_reference.clone()
+    }
+
+    fn get_capture_attempt_status(&self) -> enums::AttemptStatus {
+        match self.result_code {
+            AdyenStatus::Authorised => enums::AttemptStatus::Charged,
+            _ => enums::AttemptStatus::CaptureFailed,
+        }
+    }
+
+    fn is_capture_response(&self) -> bool {
+        self.event_code == Some(WebhookEventCode::Capture)
+            || self.event_code == Some(WebhookEventCode::CaptureFailed)
+    }
+
+    fn get_connector_reference_id(&self) -> Option<String> {
+        Some(self.merchant_reference.clone())
+    }
+}
+
 // Payouts
 #[cfg(feature = "payouts")]
 #[derive(Debug, Serialize, Deserialize)]
diff --git a/crates/router/src/connector/globalpay.rs b/crates/router/src/connector/globalpay.rs
index 31696ee3868..de0470be2e4 100644
--- a/crates/router/src/connector/globalpay.rs
+++ b/crates/router/src/connector/globalpay.rs
@@ -483,11 +483,18 @@ impl ConnectorIntegration<api::PSync, types::PaymentsSyncData, types::PaymentsRe
             .response
             .parse_struct("globalpay PaymentsResponse")
             .change_context(errors::ConnectorError::ResponseDeserializationFailed)?;
-        types::RouterData::try_from(types::ResponseRouterData {
-            response,
-            data: data.clone(),
-            http_code: res.status_code,
-        })
+        let is_multiple_capture_sync = match data.request.sync_type {
+            types::SyncRequestType::MultipleCaptureSync(_) => true,
+            types::SyncRequestType::SinglePaymentSync => false,
+        };
+        types::RouterData::try_from((
+            types::ResponseRouterData {
+                response,
+                data: data.clone(),
+                http_code: res.status_code,
+            },
+            is_multiple_capture_sync,
+        ))
         .change_context(errors::ConnectorError::ResponseHandlingFailed)
     }
     fn get_multiple_capture_sync_method(
diff --git a/crates/router/src/connector/globalpay/requests.rs b/crates/router/src/connector/globalpay/requests.rs
index 4e3efcd12f2..ee62e8c2c2c 100644
--- a/crates/router/src/connector/globalpay/requests.rs
+++ b/crates/router/src/connector/globalpay/requests.rs
@@ -806,6 +806,7 @@ pub struct GlobalpayRefundRequest {
 pub struct GlobalpayCaptureRequest {
     pub amount: Option<String>,
     pub capture_sequence: Option<Sequence>,
+    pub reference: Option<String>,
 }
 
 #[derive(Default, Debug, Serialize)]
diff --git a/crates/router/src/connector/globalpay/transformers.rs b/crates/router/src/connector/globalpay/transformers.rs
index 6ef80213209..2100aa34f66 100644
--- a/crates/router/src/connector/globalpay/transformers.rs
+++ b/crates/router/src/connector/globalpay/transformers.rs
@@ -98,6 +98,11 @@ impl TryFrom<&types::PaymentsCaptureRouterData> for requests::GlobalpayCaptureRe
                     Sequence::Subsequent
                 }
             }),
+            reference: value
+                .request
+                .multiple_capture_data
+                .as_ref()
+                .map(|mcd| mcd.capture_reference.clone()),
         })
     }
 }
@@ -228,7 +233,7 @@ fn get_payment_response(
             mandate_reference,
             connector_metadata: None,
             network_txn_id: None,
-            connector_response_reference_id: None,
+            connector_response_reference_id: response.reference,
         }),
     }
 }
@@ -274,6 +279,35 @@ impl<F, T>
     }
 }
 
+impl
+    TryFrom<(
+        types::PaymentsSyncResponseRouterData<GlobalpayPaymentsResponse>,
+        bool,
+    )> for types::PaymentsSyncRouterData
+{
+    type Error = Error;
+
+    fn try_from(
+        (value, is_multiple_capture_sync): (
+            types::PaymentsSyncResponseRouterData<GlobalpayPaymentsResponse>,
+            bool,
+        ),
+    ) -> Result<Self, Self::Error> {
+        if is_multiple_capture_sync {
+            let capture_sync_response_list =
+                utils::construct_captures_response_hashmap(vec![value.response]);
+            Ok(Self {
+                response: Ok(types::PaymentsResponseData::MultipleCaptureResponse {
+                    capture_sync_response_list,
+                }),
+                ..value.data
+            })
+        } else {
+            Self::try_from(value)
+        }
+    }
+}
+
 impl<F, T>
     TryFrom<types::ResponseRouterData<F, GlobalpayRefreshTokenResponse, T, types::AccessToken>>
     for types::RouterData<F, T, types::AccessToken>
@@ -458,3 +492,21 @@ impl TryFrom<&api_models::payments::BankRedirectData> for PaymentMethodData {
         }
     }
 }
+
+impl utils::MultipleCaptureSyncResponse for GlobalpayPaymentsResponse {
+    fn get_connector_capture_id(&self) -> String {
+        self.id.clone()
+    }
+
+    fn get_capture_attempt_status(&self) -> diesel_models::enums::AttemptStatus {
+        enums::AttemptStatus::from(self.status)
+    }
+
+    fn is_capture_response(&self) -> bool {
+        true
+    }
+
+    fn get_connector_reference_id(&self) -> Option<String> {
+        self.reference.clone()
+    }
+}
diff --git a/crates/router/src/connector/utils.rs b/crates/router/src/connector/utils.rs
index d7f0cf6d404..04c9af069c7 100644
--- a/crates/router/src/connector/utils.rs
+++ b/crates/router/src/connector/utils.rs
@@ -21,10 +21,7 @@ use crate::{
     consts,
     core::errors::{self, CustomResult},
     pii::PeekInterface,
-    types::{
-        self, api, storage::enums as storage_enums, transformers::ForeignTryFrom,
-        PaymentsCancelData, ResponseId,
-    },
+    types::{self, api, transformers::ForeignTryFrom, PaymentsCancelData, ResponseId},
     utils::{OptionExt, ValueExt},
 };
 
@@ -1364,7 +1361,7 @@ mod error_code_error_message_tests {
 
 pub trait MultipleCaptureSyncResponse {
     fn get_connector_capture_id(&self) -> String;
-    fn get_capture_attempt_status(&self) -> storage_enums::AttemptStatus;
+    fn get_capture_attempt_status(&self) -> enums::AttemptStatus;
     fn is_capture_response(&self) -> bool;
     fn get_connector_reference_id(&self) -> Option<String> {
         None
@@ -1397,6 +1394,11 @@ where
     hashmap
 }
 
+pub fn is_manual_capture(capture_method: Option<enums::CaptureMethod>) -> bool {
+    capture_method == Some(enums::CaptureMethod::Manual)
+        || capture_method == Some(enums::CaptureMethod::ManualMultiple)
+}
+
 pub fn validate_currency(
     request_currency: types::storage::enums::Currency,
     merchant_config_currency: Option<types::storage::enums::Currency>,
diff --git a/crates/router/src/core/payments.rs b/crates/router/src/core/payments.rs
index 8e976740e6a..76d4198c88b 100644
--- a/crates/router/src/core/payments.rs
+++ b/crates/router/src/core/payments.rs
@@ -1344,7 +1344,7 @@ where
     Ok(payment_data.to_owned())
 }
 
-#[derive(Clone)]
+#[derive(Clone, PartialEq)]
 pub enum CallConnectorAction {
     Trigger,
     Avoid,
@@ -1485,7 +1485,13 @@ pub fn should_call_connector<Op: Debug, F: Clone>(
                 payment_data.payment_intent.status,
                 storage_enums::IntentStatus::RequiresCapture
                     | storage_enums::IntentStatus::PartiallyCaptured
-            )
+            ) || (matches!(
+                payment_data.payment_intent.status,
+                storage_enums::IntentStatus::Processing
+            ) && matches!(
+                payment_data.payment_attempt.capture_method,
+                Some(storage_enums::CaptureMethod::ManualMultiple)
+            ))
         }
         "CompleteAuthorize" => true,
         "PaymentApprove" => true,
diff --git a/crates/router/src/core/payments/flows/psync_flow.rs b/crates/router/src/core/payments/flows/psync_flow.rs
index b6920387b13..1c01af79f56 100644
--- a/crates/router/src/core/payments/flows/psync_flow.rs
+++ b/crates/router/src/core/payments/flows/psync_flow.rs
@@ -157,10 +157,9 @@ impl types::RouterData<api::PSync, types::PaymentsSyncData, types::PaymentsRespo
             types::PaymentsResponseData,
         >,
     ) -> RouterResult<Self> {
-        let mut capture_sync_response_list = HashMap::new();
-        for connector_capture_id in pending_connector_capture_id_list {
-            self.request.connector_transaction_id =
-                types::ResponseId::ConnectorTransactionId(connector_capture_id.clone());
+        let mut capture_sync_response_map = HashMap::new();
+        if let payments::CallConnectorAction::HandleResponse(_) = call_connector_action {
+            // webhook consume flow, only call connector once. Since there will only be a single event in every webhook
             let resp = services::execute_connector_processing_step(
                 state,
                 connector_integration.clone(),
@@ -170,30 +169,40 @@ impl types::RouterData<api::PSync, types::PaymentsSyncData, types::PaymentsRespo
             )
             .await
             .to_payment_failed_response()?;
-            let capture_sync_response = match resp.response {
-                Err(err) => types::CaptureSyncResponse::Error {
-                    code: err.code,
-                    message: err.message,
-                    reason: err.reason,
-                    status_code: err.status_code,
-                },
-                Ok(types::PaymentsResponseData::TransactionResponse {
-                    resource_id,
-                    connector_response_reference_id,
-                    ..
-                }) => types::CaptureSyncResponse::Success {
-                    resource_id,
-                    status: resp.status,
-                    connector_response_reference_id,
-                },
-                // this error is never meant to occur. response type will always be PaymentsResponseData::TransactionResponse
-                _ => Err(ApiErrorResponse::PreconditionFailed { message: "Response type must be PaymentsResponseData::TransactionResponse for payment sync".into() })?,
-            };
-            capture_sync_response_list.insert(connector_capture_id.clone(), capture_sync_response);
+            Ok(resp)
+        } else {
+            // in trigger, call connector for every capture_id
+            for connector_capture_id in pending_connector_capture_id_list {
+                self.request.connector_transaction_id =
+                    types::ResponseId::ConnectorTransactionId(connector_capture_id.clone());
+                let resp = services::execute_connector_processing_step(
+                    state,
+                    connector_integration.clone(),
+                    &self,
+                    call_connector_action.clone(),
+                    None,
+                )
+                .await
+                .to_payment_failed_response()?;
+                match resp.response {
+                    Err(err) => {
+                        capture_sync_response_map.insert(connector_capture_id, types::CaptureSyncResponse::Error {
+                            code: err.code,
+                            message: err.message,
+                            reason: err.reason,
+                            status_code: err.status_code,
+                        });
+                    },
+                    Ok(types::PaymentsResponseData::MultipleCaptureResponse { capture_sync_response_list })=> {
+                        capture_sync_response_map.extend(capture_sync_response_list.into_iter());
+                    }
+                    _ => Err(ApiErrorResponse::PreconditionFailed { message: "Response type must be PaymentsResponseData::MultipleCaptureResponse for payment sync".into() })?,
+                };
+            }
+            self.response = Ok(types::PaymentsResponseData::MultipleCaptureResponse {
+                capture_sync_response_list: capture_sync_response_map,
+            });
+            Ok(self)
         }
-        self.response = Ok(types::PaymentsResponseData::MultipleCaptureResponse {
-            capture_sync_response_list,
-        });
-        Ok(self)
     }
 }
diff --git a/crates/router/src/core/payments/helpers.rs b/crates/router/src/core/payments/helpers.rs
index d29cfbf100c..7ae71ec2a6b 100644
--- a/crates/router/src/core/payments/helpers.rs
+++ b/crates/router/src/core/payments/helpers.rs
@@ -1448,16 +1448,30 @@ pub(crate) fn validate_capture_method(
 }
 
 #[instrument(skip_all)]
-pub(crate) fn validate_status(status: storage_enums::IntentStatus) -> RouterResult<()> {
+pub(crate) fn validate_status_with_capture_method(
+    status: storage_enums::IntentStatus,
+    capture_method: storage_enums::CaptureMethod,
+) -> RouterResult<()> {
+    if status == storage_enums::IntentStatus::Processing
+        && !(capture_method == storage_enums::CaptureMethod::ManualMultiple)
+    {
+        return Err(report!(errors::ApiErrorResponse::PaymentUnexpectedState {
+            field_name: "capture_method".to_string(),
+            current_flow: "captured".to_string(),
+            current_value: capture_method.to_string(),
+            states: "manual_multiple".to_string()
+        }));
+    }
     utils::when(
         status != storage_enums::IntentStatus::RequiresCapture
-            && status != storage_enums::IntentStatus::PartiallyCaptured,
+            && status != storage_enums::IntentStatus::PartiallyCaptured
+            && status != storage_enums::IntentStatus::Processing,
         || {
             Err(report!(errors::ApiErrorResponse::PaymentUnexpectedState {
                 field_name: "payment.status".to_string(),
                 current_flow: "captured".to_string(),
                 current_value: status.to_string(),
-                states: "requires_capture, partially captured".to_string()
+                states: "requires_capture, partially_captured, processing".to_string()
             }))
         },
     )
diff --git a/crates/router/src/core/payments/operations/payment_capture.rs b/crates/router/src/core/payments/operations/payment_capture.rs
index 596e25f0528..054f9a31b90 100644
--- a/crates/router/src/core/payments/operations/payment_capture.rs
+++ b/crates/router/src/core/payments/operations/payment_capture.rs
@@ -61,10 +61,6 @@ impl<F: Send + Clone> GetTracker<F, payments::PaymentData<F>, api::PaymentsCaptu
             .await
             .to_not_found_response(errors::ApiErrorResponse::PaymentNotFound)?;
 
-        helpers::validate_status(payment_intent.status)?;
-
-        helpers::validate_amount_to_capture(payment_intent.amount, request.amount_to_capture)?;
-
         payment_attempt = db
             .find_payment_attempt_by_payment_id_merchant_id_attempt_id(
                 payment_intent.payment_id.as_str(),
@@ -83,6 +79,10 @@ impl<F: Send + Clone> GetTracker<F, payments::PaymentData<F>, api::PaymentsCaptu
             .capture_method
             .get_required_value("capture_method")?;
 
+        helpers::validate_status_with_capture_method(payment_intent.status, capture_method)?;
+
+        helpers::validate_amount_to_capture(payment_intent.amount, request.amount_to_capture)?;
+
         helpers::validate_capture_method(capture_method)?;
 
         let (multiple_capture_data, connector_response) = if capture_method

## 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 enables multiple partial capture for Adyen.


### 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 it is 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)?
-->
Manual


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