Bug: [REFACTOR] add support for passing ttl to locker entries



Add config support for passing ttl to locker entries. By default keep the ttl to 7 years
diff --git a/config/config.example.toml b/config/config.example.toml
index d5bdfb5a6a7..d10e8216e9f 100644
--- a/config/config.example.toml
+++ b/config/config.example.toml
@@ -124,11 +124,12 @@ recon_admin_api_key = "recon_test_admin" # recon_admin API key for recon authent
 # PCI Compliant storage entity which stores payment method information
 # like card details
 [locker]
-host = ""                   # Locker host
-host_rs = ""                # Rust Locker host
-mock_locker = true          # Emulate a locker locally using Postgres
-locker_signing_key_id = "1" # Key_id to sign basilisk hs locker
-locker_enabled = true       # Boolean to enable or disable saving cards in locker
+host = ""                                # Locker host
+host_rs = ""                             # Rust Locker host
+mock_locker = true                       # Emulate a locker locally using Postgres
+locker_signing_key_id = "1"              # Key_id to sign basilisk hs locker
+locker_enabled = true                    # Boolean to enable or disable saving cards in locker
+ttl_for_storage_in_secs = 220752000      # Time to live for storage entries in locker
 
 [delayed_session_response]
 connectors_with_delayed_session_response = "trustpay,payme" # List of connectors which has delayed session response
diff --git a/config/deployments/env_specific.toml b/config/deployments/env_specific.toml
index c725a8bd69d..fc02335dcf5 100644
--- a/config/deployments/env_specific.toml
+++ b/config/deployments/env_specific.toml
@@ -115,6 +115,8 @@ mock_locker = true                                                    # Emulate
 locker_signing_key_id = "1"                                           # Key_id to sign basilisk hs locker
 locker_enabled = true                                                 # Boolean to enable or disable saving cards in locker
 redis_temp_locker_encryption_key = "redis_temp_locker_encryption_key" # Encryption key for redis temp locker
+ttl_for_storage_in_secs = 220752000                                   # Time to live for storage entries in locker
+
 
 [log.console]
 enabled = true
diff --git a/config/development.toml b/config/development.toml
index a9f7f4d7b4d..dfba91b514d 100644
--- a/config/development.toml
+++ b/config/development.toml
@@ -71,6 +71,7 @@ host_rs = ""
 mock_locker = true
 basilisk_host = ""
 locker_enabled = true
+ttl_for_storage_in_secs = 220752000
 
 [forex_api]
 call_delay = 21600
diff --git a/config/docker_compose.toml b/config/docker_compose.toml
index 6661d164032..d371d08148a 100644
--- a/config/docker_compose.toml
+++ b/config/docker_compose.toml
@@ -61,6 +61,7 @@ host_rs = ""
 mock_locker = true
 basilisk_host = ""
 locker_enabled = true
+ttl_for_storage_in_secs = 220752000
 
 [jwekey]
 vault_encryption_key = ""
diff --git a/crates/router/src/configs/defaults.rs b/crates/router/src/configs/defaults.rs
index 1fe86a209e3..d3be5cd5248 100644
--- a/crates/router/src/configs/defaults.rs
+++ b/crates/router/src/configs/defaults.rs
@@ -68,6 +68,8 @@ impl Default for super::settings::Locker {
             locker_signing_key_id: "1".into(),
             //true or false
             locker_enabled: true,
+            //Time to live for storage entries in locker
+            ttl_for_storage_in_secs: 60 * 60 * 24 * 365 * 7,
         }
     }
 }
diff --git a/crates/router/src/configs/settings.rs b/crates/router/src/configs/settings.rs
index b8a315f944b..8ac27cce318 100644
--- a/crates/router/src/configs/settings.rs
+++ b/crates/router/src/configs/settings.rs
@@ -407,6 +407,7 @@ pub struct Locker {
     pub basilisk_host: String,
     pub locker_signing_key_id: String,
     pub locker_enabled: bool,
+    pub ttl_for_storage_in_secs: i64,
 }
 
 #[derive(Debug, Deserialize, Clone)]
diff --git a/crates/router/src/core/payment_methods/cards.rs b/crates/router/src/core/payment_methods/cards.rs
index 379050ba73e..cd51face62d 100644
--- a/crates/router/src/core/payment_methods/cards.rs
+++ b/crates/router/src/core/payment_methods/cards.rs
@@ -1070,6 +1070,7 @@ pub async fn add_bank_to_locker(
             merchant_id: &merchant_account.merchant_id,
             merchant_customer_id: customer_id.to_owned(),
             enc_data,
+            ttl: state.conf.locker.ttl_for_storage_in_secs,
         });
     let store_resp = call_to_locker_hs(
         state,
@@ -1229,6 +1230,7 @@ pub async fn add_card_hs(
             card_isin: None,
             nick_name: card.nick_name.as_ref().map(Secret::peek).cloned(),
         },
+        ttl: state.conf.locker.ttl_for_storage_in_secs,
     });
 
     let store_card_payload =
diff --git a/crates/router/src/core/payment_methods/transformers.rs b/crates/router/src/core/payment_methods/transformers.rs
index 08e87b47f91..86b41d1d0fe 100644
--- a/crates/router/src/core/payment_methods/transformers.rs
+++ b/crates/router/src/core/payment_methods/transformers.rs
@@ -43,6 +43,7 @@ pub struct StoreCardReq<'a> {
     #[serde(skip_serializing_if = "Option::is_none")]
     pub requestor_card_reference: Option<String>,
     pub card: Card,
+    pub ttl: i64,
 }
 
 #[derive(Debug, Deserialize, Serialize)]
@@ -51,6 +52,7 @@ pub struct StoreGenericReq<'a> {
     pub merchant_customer_id: String,
     #[serde(rename = "enc_card_data")]
     pub enc_data: String,
+    pub ttl: i64,
 }
 
 #[derive(Debug, Deserialize, Serialize)]
diff --git a/crates/router/src/core/payouts/helpers.rs b/crates/router/src/core/payouts/helpers.rs
index dad0739879f..9c6cdbd8881 100644
--- a/crates/router/src/core/payouts/helpers.rs
+++ b/crates/router/src/core/payouts/helpers.rs
@@ -220,6 +220,7 @@ pub async fn save_payout_data_to_locker(
                         nick_name: None,
                     },
                     requestor_card_reference: None,
+                    ttl: state.conf.locker.ttl_for_storage_in_secs,
                 });
                 (
                     payload,
@@ -255,6 +256,7 @@ pub async fn save_payout_data_to_locker(
                     merchant_id: merchant_account.merchant_id.as_ref(),
                     merchant_customer_id: payout_attempt.customer_id.to_owned(),
                     enc_data,
+                    ttl: state.conf.locker.ttl_for_storage_in_secs,
                 });
                 match payout_method_data {
                     payouts::PayoutMethodData::Bank(bank) => (
diff --git a/loadtest/config/development.toml b/loadtest/config/development.toml
index 2c3e83ad2ba..878451080e3 100644
--- a/loadtest/config/development.toml
+++ b/loadtest/config/development.toml
@@ -38,6 +38,7 @@ host_rs = ""
 mock_locker = true
 basilisk_host = ""
 locker_enabled = true
+ttl_for_storage_in_secs = 220752000
 
 [forex_api]
 call_delay = 21600
@@ -320,4 +321,4 @@ client_secret = ""
 partner_id = ""
 
 [unmasked_headers]
-keys = "user-agent"
\ No newline at end of file
+keys = "user-agent"

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

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

## Description
<!-- Describe your changes in detail -->
This PR adds config support for passing ttl to locker entries as application config. By default ttl is kept to 7 years.

### Additional Changes

- [ ] This PR modifies the API contract
- [ ] This PR modifies the database schema
- [x] 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)?
-->
TTL assignment in locker cannot be known (unless we access the locker db). Hyperswitch just sends the TTL as 7 years to locker. Hyperswitch doesn't store the TTL. Even during payment methods retrieve in Hyperswitch, the TTL is not fetched from locker. 
So basic card saving flow has to be tested

Local testing - 

1. Save card in locker 

```
curl --location 'http://localhost:8080/payment_methods' \
--header 'Content-Type: application/json' \
--header 'Accept: application/json' \
--header 'api-key: dev_sQtjddP5dtSitN2ZB01xgmzYnQboxyx4u3m9nWjMSRCZlApGGjqAnXyVGAPl8OlI' \
--data '{
    "payment_method": "card",
    "payment_method_type": "credit",
    "payment_method_issuer": "Visa",
    "card": {
        "card_number": "4111111111111111",
        "card_exp_month": "04",
        "card_exp_year": "25",
        "card_holder_name": "John",
        "card_network": "Visa"
    },
    "customer_id": "cus_kr9m9hY3ZpS7oJLtJ4mo",
    "metadata": {
        "city": "NY",
        "unit": "245"
    }
}'
```

![image](https://github.com/juspay/hyperswitch/assets/70657455/15d7a9d1-508f-49d9-b6e7-dd42d21a1f70)

2. Locker DB (ttl is 7 years from created time) 

![image](https://github.com/juspay/hyperswitch/assets/70657455/4ee33346-b047-49fb-8028-25eb608abec8)

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