Bug: pass Samsung Pay `public_key_hash` in the confirm call



The token received form Samsung Pay will be int the JWT format. The header of that will contain the `kid` which is the `public_key_hash`. This is needs to be passed to Cybersource in the confirm call.
diff --git a/crates/router/src/connector/adyen.rs b/crates/router/src/connector/adyen.rs
index f0b84fc93c1..810551e0cb7 100644
--- a/crates/router/src/connector/adyen.rs
+++ b/crates/router/src/connector/adyen.rs
@@ -130,6 +130,7 @@ impl ConnectorValidation for Adyen {
                     }
                 },
                 PaymentMethodType::Ach
+                | PaymentMethodType::SamsungPay
                 | PaymentMethodType::Alma
                 | PaymentMethodType::Bacs
                 | PaymentMethodType::Givex
@@ -222,7 +223,6 @@ impl ConnectorValidation for Adyen {
                 | PaymentMethodType::RedCompra
                 | PaymentMethodType::RedPagos
                 | PaymentMethodType::CryptoCurrency
-                | PaymentMethodType::SamsungPay
                 | PaymentMethodType::Evoucher
                 | PaymentMethodType::Cashapp
                 | PaymentMethodType::UpiCollect
diff --git a/crates/router/src/connector/cybersource/transformers.rs b/crates/router/src/connector/cybersource/transformers.rs
index 9c596f5575c..864f77b55dd 100644
--- a/crates/router/src/connector/cybersource/transformers.rs
+++ b/crates/router/src/connector/cybersource/transformers.rs
@@ -6,8 +6,13 @@ use api_models::{
 };
 use base64::Engine;
 use common_enums::FutureUsage;
-use common_utils::{ext_traits::ValueExt, pii, types::SemanticVersion};
+use common_utils::{
+    ext_traits::{OptionExt, ValueExt},
+    pii,
+    types::SemanticVersion,
+};
 use error_stack::ResultExt;
+use josekit::jwt::decode_header;
 use masking::{ExposeInterface, PeekInterface, Secret};
 use serde::{Deserialize, Serialize};
 use serde_json::Value;
@@ -457,6 +462,14 @@ pub struct SamsungPayPaymentInformation {
     tokenized_card: SamsungPayTokenizedCard,
 }
 
+#[derive(Debug, Serialize)]
+#[serde(rename_all = "camelCase")]
+pub struct SamsungPayFluidDataValue {
+    public_key_hash: Secret<String>,
+    version: String,
+    data: Secret<String>,
+}
+
 #[derive(Debug, Serialize)]
 #[serde(untagged)]
 pub enum PaymentInformation {
@@ -1531,13 +1544,17 @@ impl
         let bill_to = build_bill_to(item.router_data.get_optional_billing(), email)?;
         let order_information = OrderInformationWithBill::from((item, Some(bill_to)));
 
+        let samsung_pay_fluid_data_value =
+            get_samsung_pay_fluid_data_value(&samsung_pay_data.payment_credential.token_data)?;
+
+        let samsung_pay_fluid_data_str = serde_json::to_string(&samsung_pay_fluid_data_value)
+            .change_context(errors::ConnectorError::RequestEncodingFailed)
+            .attach_printable("Failed to serialize samsung pay fluid data")?;
+
         let payment_information =
             PaymentInformation::SamsungPay(Box::new(SamsungPayPaymentInformation {
                 fluid_data: FluidData {
-                    value: Secret::from(
-                        consts::BASE64_ENGINE
-                            .encode(samsung_pay_data.payment_credential.token_data.data.peek()),
-                    ),
+                    value: Secret::new(consts::BASE64_ENGINE.encode(samsung_pay_fluid_data_str)),
                     descriptor: Some(
                         consts::BASE64_ENGINE.encode(FLUID_DATA_DESCRIPTOR_FOR_SAMSUNG_PAY),
                     ),
@@ -1571,6 +1588,28 @@ impl
     }
 }
 
+fn get_samsung_pay_fluid_data_value(
+    samsung_pay_token_data: &hyperswitch_domain_models::payment_method_data::SamsungPayTokenData,
+) -> Result<SamsungPayFluidDataValue, error_stack::Report<errors::ConnectorError>> {
+    let samsung_pay_header = decode_header(samsung_pay_token_data.data.clone().peek())
+        .change_context(errors::ConnectorError::RequestEncodingFailed)
+        .attach_printable("Failed to decode samsung pay header")?;
+
+    let samsung_pay_kid_optional = samsung_pay_header.claim("kid").and_then(|kid| kid.as_str());
+
+    let samsung_pay_fluid_data_value = SamsungPayFluidDataValue {
+        public_key_hash: Secret::new(
+            samsung_pay_kid_optional
+                .get_required_value("samsung pay public_key_hash")
+                .change_context(errors::ConnectorError::RequestEncodingFailed)?
+                .to_string(),
+        ),
+        version: samsung_pay_token_data.version.clone(),
+        data: Secret::new(consts::BASE64_ENGINE.encode(samsung_pay_token_data.data.peek())),
+    };
+    Ok(samsung_pay_fluid_data_value)
+}
+
 impl TryFrom<&CybersourceRouterData<&types::PaymentsAuthorizeRouterData>>
     for CybersourcePaymentsRequest
 {

## Type of Change
<!-- Put an `x` in the boxes that apply -->

- [x] Bugfix
- [ ] New feature
- [ ] Enhancement
- [ ] Refactoring
- [ ] Dependency updates
- [ ] Documentation
- [ ] CI/CD

## Description
<!-- Describe your changes in detail -->
The token received form Samsung Pay will be int the JWT format. The header of that will contain the `kid` which is the `public_key_hash`. This is needs to be passed to Cybersource in the confirm call.

### 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)?
-->
Test Samsung Pay flow
-> Enable Samsung Pay payment method for the connector (Cybersource)
```
{
    "connector_type": "payment_processor",
    "connector_name": "cybersource",
    "connector_account_details": {
        "auth_type": "SignatureKey",
        "api_secret": "api_secret",
        "key1": "key1",
        "api_key": "api_key"
    },
    "test_mode": true,
    "disabled": false,
    "payment_methods_enabled": [
        {
            "payment_method": "pay_later",
            "payment_method_types": [
                {
                    "minimum_amount": 1,
                    "maximum_amount": 68607706,
                    "recurring_enabled": true,
                    "installment_payment_enabled": true,
                    "payment_experience": "invoke_sdk_client",
                    "payment_method_type": "klarna"
                }
            ]
        },
        {
            "payment_method": "pay_later",
            "payment_method_types": [
                {
                    "minimum_amount": 1,
                    "maximum_amount": 68607706,
                    "recurring_enabled": true,
                    "installment_payment_enabled": true,
                    "payment_experience": "redirect_to_url",
                    "payment_method_type": "klarna"
                }
            ]
        },
        {
            "payment_method": "card",
            "payment_method_types": [
                {
                    "payment_method_type": "credit",
                    "payment_experience": null,
                    "card_networks": [
                        "Visa",
                        "Mastercard",
                        "Discover",
                        "DinersClub"
                    ],
                    "accepted_currencies": null,
                    "accepted_countries": null,
                    "minimum_amount": 1,
                    "maximum_amount": 68607706,
                    "recurring_enabled": true,
                    "installment_payment_enabled": true
                },
                {
                    "payment_method_type": "debit",
                    "payment_experience": null,
                    "card_networks": [
                        "Visa",
                        "Mastercard"
                    ],
                    "accepted_currencies": null,
                    "accepted_countries": null,
                    "minimum_amount": 1,
                    "maximum_amount": 68607706,
                    "recurring_enabled": true,
                    "installment_payment_enabled": true
                }
            ]
        },
        {
            "payment_method": "bank_debit",
            "payment_method_types": [
                {
                    "payment_method_type": "ach",
                    "recurring_enabled": true,
                    "installment_payment_enabled": true,
                    "minimum_amount": 0,
                    "maximum_amount": 10000
                }
            ]
        },
        {
            "payment_method": "wallet",
            "payment_method_types": [
                {
                    "payment_method_type": "google_pay",
                    "payment_experience": "invoke_sdk_client",
                    "card_networks": null,
                    "accepted_currencies": null,
                    "accepted_countries": null,
                    "minimum_amount": 1,
                    "maximum_amount": 68607706,
                    "recurring_enabled": true,
                    "installment_payment_enabled": true
                },
                {
                    "payment_method_type": "samsung_pay",
                    "payment_experience": "invoke_sdk_client",
                    "card_networks": null,
                    "accepted_currencies": null,
                    "accepted_countries": null,
                    "minimum_amount": 1,
                    "maximum_amount": 68607706,
                    "recurring_enabled": true,
                    "installment_payment_enabled": true
                },
                {
                    "payment_method_type": "apple_pay",
                    "payment_experience": "invoke_sdk_client",
                    "card_networks": null,
                    "accepted_currencies": null,
                    "accepted_countries": null,
                    "minimum_amount": 1,
                    "maximum_amount": 68607706,
                    "recurring_enabled": true,
                    "installment_payment_enabled": true
                },
                {
                    "payment_method_type": "paypal",
                    "payment_experience": "redirect_to_url",
                    "card_networks": null,
                    "accepted_currencies": null,
                    "accepted_countries": null,
                    "minimum_amount": 1,
                    "maximum_amount": 68607706,
                    "recurring_enabled": true,
                    "installment_payment_enabled": true
                }
            ]
        }
    ],
    "connector_wallets_details": {
        "samsung_pay": {
            "service_id": "49400558c67f4a97b3925f",
            "merchant_display_name": "Hyperswitch",
            "merchant_business_country": "IN",
            "allowed_brands": [
                "visa",
                "masterCard",
                "amex",
                "discover"
            ]
        }
    },
    "connector_webhook_details": {
        "merchant_secret": "merchant_secret"
    }
}
```
-> Create a payment
```
curl --location 'http://localhost:8080/payments' \
--header 'Content-Type: application/json' \
--header 'Accept: application/json' \
--header 'api-key: dev_cjSDZPveYx7AbdI5cMRMuPKVdteJ7aIi3ULRasYhU89JtFRZWp9BeNn7PQDLQv8W' \
--data '{
  "amount": 100000,
  "currency": "INR",
  "capture_method": "automatic",
  "authentication_type": "no_three_ds",
  "confirm": false,
  "customer_id": "cu_1726743607"
}'
```
```
{
    "payment_id": "pay_9oXGqEDD6bQTYhbLvC40",
    "merchant_id": "merchant_1727087901",
    "status": "requires_payment_method",
    "amount": 100000,
    "net_amount": 100000,
    "amount_capturable": 0,
    "amount_received": null,
    "connector": null,
    "client_secret": "pay_9oXGqEDD6bQTYhbLvC40_secret_oftRxCm8PcntUjgd7z4P",
    "created": "2024-09-25T05:46:55.720Z",
    "currency": "USD",
    "customer_id": "cu_1727243216",
    "customer": {
        "id": "cu_1727243216",
        "name": null,
        "email": null,
        "phone": null,
        "phone_country_code": null
    },
    "description": null,
    "refunds": null,
    "disputes": null,
    "mandate_id": null,
    "mandate_data": null,
    "setup_future_usage": null,
    "off_session": null,
    "capture_on": null,
    "capture_method": "automatic",
    "payment_method": null,
    "payment_method_data": null,
    "payment_token": null,
    "shipping": null,
    "billing": null,
    "order_details": null,
    "email": null,
    "name": null,
    "phone": null,
    "return_url": null,
    "authentication_type": "no_three_ds",
    "statement_descriptor_name": null,
    "statement_descriptor_suffix": null,
    "next_action": null,
    "cancellation_reason": null,
    "error_code": null,
    "error_message": null,
    "unified_code": null,
    "unified_message": null,
    "payment_experience": null,
    "payment_method_type": null,
    "connector_label": null,
    "business_country": null,
    "business_label": "default",
    "business_sub_label": null,
    "allowed_payment_method_types": null,
    "ephemeral_key": {
        "customer_id": "cu_1727243216",
        "created_at": 1727243215,
        "expires": 1727246815,
        "secret": "epk_af7b8c52b45e490bac3a87ec19188c46"
    },
    "manual_retry_allowed": null,
    "connector_transaction_id": null,
    "frm_message": null,
    "metadata": null,
    "connector_metadata": null,
    "feature_metadata": null,
    "reference_id": null,
    "payment_link": null,
    "profile_id": "pro_avq4S1jpyTn6UkRb4hZc",
    "surcharge_details": null,
    "attempt_count": 1,
    "merchant_decision": null,
    "merchant_connector_id": null,
    "incremental_authorization_allowed": null,
    "authorization_count": null,
    "incremental_authorizations": null,
    "external_authentication_details": null,
    "external_3ds_authentication_attempted": false,
    "expires_on": "2024-09-25T06:01:55.720Z",
    "fingerprint": null,
    "browser_info": null,
    "payment_method_id": null,
    "payment_method_status": null,
    "updated": "2024-09-25T05:46:55.804Z",
    "charges": null,
    "frm_metadata": null,
    "merchant_order_reference_id": null,
    "order_tax_amount": null,
    "connector_mandate_id": null
}
```
-> Session call
```
curl --location 'http://localhost:8080/payments/session_tokens' \
--header 'Content-Type: application/json' \
--header 'x-browser-name: Chrome' \
--header 'x-client-platform: web' \
--header 'x-merchant-domain: sdk-test-app.netlify.app' \
--header 'api-key: pk_dev_3ccbd5ee07844da0a0f7f7b746c3465c' \
--data '{
    "payment_id": "pay_9oXGqEDD6bQTYhbLvC40",
    "wallets": [],
    "client_secret": "pay_9oXGqEDD6bQTYhbLvC40_secret_oftRxCm8PcntUjgd7z4P"
}'
```
```
{
    "payment_id": "pay_9oXGqEDD6bQTYhbLvC40",
    "client_secret": "pay_9oXGqEDD6bQTYhbLvC40_secret_oftRxCm8PcntUjgd7z4P",
    "session_token": [
        {
            "wallet_name": "google_pay",
            "merchant_info": {
                "merchant_name": "Stripe"
            },
            "shipping_address_required": false,
            "email_required": false,
            "shipping_address_parameters": {
                "phone_number_required": false
            },
            "allowed_payment_methods": [
                {
                    "type": "CARD",
                    "parameters": {
                        "allowed_auth_methods": [
                            "PAN_ONLY",
                            "CRYPTOGRAM_3DS"
                        ],
                        "allowed_card_networks": [
                            "AMEX",
                            "DISCOVER",
                            "INTERAC",
                            "JCB",
                            "MASTERCARD",
                            "VISA"
                        ],
                        "billing_address_required": false
                    },
                    "tokenization_specification": {
                        "type": "PAYMENT_GATEWAY",
                        "parameters": {
                            "gateway": "stripe",
                            "stripe:version": "2018-10-31",
                            "stripe:publishableKey": "pk_test_51Msk2GAGHc77EJXX78h549SX2uaOnEkUYqBfjcoD05PIpAnDkYxMn8nQ4d19im85NQuX4Z6WDyHaUw2fFTPBWsIY00Wa7oNerO"
                        }
                    }
                }
            ],
            "transaction_info": {
                "country_code": "US",
                "currency_code": "USD",
                "total_price_status": "Final",
                "total_price": "1000.00"
            },
            "delayed_session_token": false,
            "connector": "cybersource",
            "sdk_next_action": {
                "next_action": "confirm"
            },
            "secrets": null
        },
        {
            "wallet_name": "samsung_pay",
            "version": "2",
            "service_id": "49400558c67f4a97b3925f",
            "order_number": "pay_9oXGqEDD6bQTYhbLvC40",
            "merchant": {
                "name": "Hyperswitch",
                "url": "sdk-test-app.netlify.app",
                "country_code": "IN"
            },
            "amount": {
                "option": "FORMAT_TOTAL_PRICE_ONLY",
                "currency_code": "USD",
                "total": "1000.00"
            },
            "protocol": "PROTOCOL3DS",
            "allowed_brands": [
                "visa",
                "masterCard",
                "amex",
                "discover"
            ]
        },
        {
            "wallet_name": "apple_pay",
            "payment_request_data": {
                "country_code": "US",
                "currency_code": "USD",
                "total": {
                    "label": "applepay",
                    "type": "final",
                    "amount": "1000.00"
                },
                "merchant_capabilities": [
                    "supports3DS"
                ],
                "supported_networks": [
                    "visa",
                    "masterCard",
                    "amex",
                    "discover"
                ],
                "merchant_identifier": "merchant.com.hyperswitch.checkout"
            },
            "connector": "cybersource",
            "delayed_session_token": false,
            "sdk_next_action": {
                "next_action": "confirm"
            },
            "connector_reference_id": null,
            "connector_sdk_public_key": null,
            "connector_merchant_id": null
        }
    ]
}
```
-> Confirm call
```
curl --location 'http://localhost:8080/payments' \
--header 'Content-Type: application/json' \
--header 'Accept: application/json' \
--header 'api-key: dev_i7CIay3cWADIXr8SlfpZUYnlSri7K5xgVeUsaE31Lvms3KstLwTHVoOby02qzez9' \
--data-raw '{
    "amount": 1,
    "currency": "USD",
    "confirm": true,
    "business_country": "US",
    "business_label": "default",
    "amount_to_capture": 1,
    "customer_id": "custhype123",
    "capture_method": "automatic",
    "capture_on": "2022-09-10T10:11:12Z",
    "return_url": "https://google.com",
    "email": "samsungpay@gmail.com",
    "name": "Joseph Doe",
    "phone": "999999999",
    "phone_country_code": "+65",
    "description": "Its my first payment request",
    "statement_descriptor_name": "Juspay",
    "statement_descriptor_suffix": "Router",
    "payment_method": "wallet",
    "payment_method_type": "samsung_pay",
    "billing": {
        "address": {
            "line1": "1467",
            "line2": "Harrison Street",
            "line3": "Harrison Street",
            "city": "San Fransico",
            "state": "California",
            "zip": "94122",
            "country": "US",
            "first_name": "joseph",
            "last_name": "Doe"
        },
        "phone": {
            "number": "8056594427",
            "country_code": "+91"
        }
    },
    "payment_method_data": {
        "wallet": {
            "samsung_pay": {
                "payment_credential": {
                    "card_brand": "visa",
                    "recurring_payment": false,
                    "card_last4digits": "1661",
                    "method": "3DS",
                    "3_d_s": {
                        "type": "S",
                        "version": "100",
                        "data": "eyJhbGciOiJSU0ExXzUiLCJraWQiOiJKdnI0ZlM1L0N0dmx6Ly95cGZYK2xkQ1p4dFBIUVBNUHg4SzI5Ty9lZm1JPSIsInR5cCI6IkpPU0UiLCJjaGFubmVsU2VjdXJpdHlDb250ZXh0IjoiUlNBX1BLSSIsImVuYyI6IkExMjhHQ00ifQ.PC27m6Zz5arTvQuQAVgUDl4fczWtG8lAQwybchbD6v7UYalTz0fIo45ZFHHmlol7Q087pbH_2KPfGAi2dc3i-Akao1I-e7sL5VO4W19MWtnfN1cF2RpMmHIlLuOrqNUcqJQ2WFqhXFpzr1C9hL47nWYc4tTScI2V4kdbERFxMIKpDIHH0SL1xGHl1v5l3oXeehY-sfMFEKpKqINHQs7mxZB0Cw9HLw6WvyJ2IBh-pgzEAvMSFrHpYI2TedKbVSafSDgmHfc6vLcfiHxNXenCiHYYRHEVqqu-MAJ1svfS31fZUCAv3NRLo4G886auZvc-XWaLrwTT-5EoaUsOo8BH6w.yQY3X4j_pVJ6o7Bu.ocIct0IUNZLaHhdbi3LVjWZ3bcy22_2vV-vD7JfwyPPIACGzrZmtdKSB6eEPdo7RGtWJQ2prmDYQsL3VUP9dKRnVGbpnGJsL5Cv5D4p9JX4iPrlgL5GeFNmhHsIFDNmVnepZ-swXhI1p4SzmTpwd16X8Hupt9lQXiTRPkerJHExCpqw3ZZCcTiV2sSm53wfeYOpXYZJ2DvIB51Hpsi1eHyI8F6dDqJ0h6XUBTZzy_5iLWVvuppS2.3RlqL07i3F_Zh_xzjTt_rA"
                    }
                }
            }
        }
    }
}'
```
```
{
    "payment_id": "pay_R5DGXtaNE918aMsxrmmY",
    "merchant_id": "merchant_1727087901",
    "status": "succeeded",
    "amount": 1,
    "net_amount": 1,
    "amount_capturable": 0,
    "amount_received": 1,
    "connector": "cybersource",
    "client_secret": "pay_R5DGXtaNE918aMsxrmmY_secret_uYxRmMDDtbMNF0oJpFp5",
    "created": "2024-09-25T05:48:27.368Z",
    "currency": "USD",
    "customer_id": "custhype123",
    "customer": {
        "id": "custhype123",
        "name": "Joseph Doe",
        "email": "samsungpay@gmail.com",
        "phone": "999999999",
        "phone_country_code": "+65"
    },
    "description": "Its my first payment request",
    "refunds": null,
    "disputes": null,
    "mandate_id": null,
    "mandate_data": null,
    "setup_future_usage": null,
    "off_session": null,
    "capture_on": null,
    "capture_method": "automatic",
    "payment_method": "wallet",
    "payment_method_data": {
        "wallet": {},
        "billing": null
    },
    "payment_token": null,
    "shipping": null,
    "billing": {
        "address": {
            "city": "San Fransico",
            "country": "US",
            "line1": "1467",
            "line2": "Harrison Street",
            "line3": "Harrison Street",
            "zip": "94122",
            "state": "California",
            "first_name": "joseph",
            "last_name": "Doe"
        },
        "phone": {
            "number": "8056594427",
            "country_code": "+91"
        },
        "email": null
    },
    "order_details": null,
    "email": "samsungpay@gmail.com",
    "name": "Joseph Doe",
    "phone": "999999999",
    "return_url": "https://google.com/",
    "authentication_type": "no_three_ds",
    "statement_descriptor_name": "Juspay",
    "statement_descriptor_suffix": "Router",
    "next_action": null,
    "cancellation_reason": null,
    "error_code": null,
    "error_message": null,
    "unified_code": null,
    "unified_message": null,
    "payment_experience": null,
    "payment_method_type": "samsung_pay",
    "connector_label": "cybersource_US_default_default",
    "business_country": "US",
    "business_label": "default",
    "business_sub_label": null,
    "allowed_payment_method_types": null,
    "ephemeral_key": {
        "customer_id": "custhype123",
        "created_at": 1727243307,
        "expires": 1727246907,
        "secret": "epk_26d63c60253046abb4e95d28c66addb5"
    },
    "manual_retry_allowed": false,
    "connector_transaction_id": "7272433088196497503955",
    "frm_message": null,
    "metadata": null,
    "connector_metadata": null,
    "feature_metadata": null,
    "reference_id": "pay_R5DGXtaNE918aMsxrmmY_1",
    "payment_link": null,
    "profile_id": "pro_avq4S1jpyTn6UkRb4hZc",
    "surcharge_details": null,
    "attempt_count": 1,
    "merchant_decision": null,
    "merchant_connector_id": "mca_NMxxPseaV1nTfu7vHpR5",
    "incremental_authorization_allowed": false,
    "authorization_count": null,
    "incremental_authorizations": null,
    "external_authentication_details": null,
    "external_3ds_authentication_attempted": false,
    "expires_on": "2024-09-25T06:03:27.368Z",
    "fingerprint": null,
    "browser_info": null,
    "payment_method_id": null,
    "payment_method_status": null,
    "updated": "2024-09-25T05:48:30.388Z",
    "charges": null,
    "frm_metadata": null,
    "merchant_order_reference_id": null,
    "order_tax_amount": null,
    "connector_mandate_id": null
}
```


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