Bug: update last used when the customer acceptance is passed in the recurring payment



We need to update the last used for a payment method as whenever a payment is done with that particular saved payment method. Currently we if a customer is making a payment (CIT) with the payment data that is same as the one that is already saved we are not updating the last used a for the payment method in the db.

In this case the new CIT with the payment_data that is same as the one saved also needs to be tied to the saved pm and the last used for it needs to be updated.
diff --git a/crates/diesel_models/src/payment_method.rs b/crates/diesel_models/src/payment_method.rs
index d9c7a66a6b2..16e8ddeb7d5 100644
--- a/crates/diesel_models/src/payment_method.rs
+++ b/crates/diesel_models/src/payment_method.rs
@@ -96,8 +96,13 @@ pub struct TokenizeCoreWorkflow {
 
 #[derive(Debug, Serialize, Deserialize)]
 pub enum PaymentMethodUpdate {
-    MetadataUpdate {
+    MetadataUpdateAndLastUsed {
         metadata: Option<serde_json::Value>,
+        last_used_at: PrimitiveDateTime,
+    },
+    UpdatePaymentMethodDataAndLastUsed {
+        payment_method_data: Option<Encryption>,
+        last_used_at: PrimitiveDateTime,
     },
     PaymentMethodDataUpdate {
         payment_method_data: Option<Encryption>,
@@ -191,10 +196,13 @@ impl PaymentMethodUpdateInternal {
 impl From<PaymentMethodUpdate> for PaymentMethodUpdateInternal {
     fn from(payment_method_update: PaymentMethodUpdate) -> Self {
         match payment_method_update {
-            PaymentMethodUpdate::MetadataUpdate { metadata } => Self {
+            PaymentMethodUpdate::MetadataUpdateAndLastUsed {
+                metadata,
+                last_used_at,
+            } => Self {
                 metadata,
                 payment_method_data: None,
-                last_used_at: None,
+                last_used_at: Some(last_used_at),
                 network_transaction_id: None,
                 status: None,
                 locker_id: None,
@@ -232,6 +240,22 @@ impl From<PaymentMethodUpdate> for PaymentMethodUpdateInternal {
                 payment_method_issuer: None,
                 payment_method_type: None,
             },
+            PaymentMethodUpdate::UpdatePaymentMethodDataAndLastUsed {
+                payment_method_data,
+                last_used_at,
+            } => Self {
+                metadata: None,
+                payment_method_data,
+                last_used_at: Some(last_used_at),
+                network_transaction_id: None,
+                status: None,
+                locker_id: None,
+                payment_method: None,
+                connector_mandate_details: None,
+                updated_by: None,
+                payment_method_issuer: None,
+                payment_method_type: None,
+            },
             PaymentMethodUpdate::NetworkTransactionIdAndStatusUpdate {
                 network_transaction_id,
                 status,
diff --git a/crates/router/src/core/payment_methods/cards.rs b/crates/router/src/core/payment_methods/cards.rs
index 53b0063c6ef..04137b53c87 100644
--- a/crates/router/src/core/payment_methods/cards.rs
+++ b/crates/router/src/core/payment_methods/cards.rs
@@ -1389,14 +1389,31 @@ pub async fn call_to_locker_hs<'a>(
     Ok(stored_card)
 }
 
-pub async fn update_payment_method(
+pub async fn update_payment_method_metadata_and_last_used(
     db: &dyn db::StorageInterface,
     pm: payment_method::PaymentMethod,
-    pm_metadata: serde_json::Value,
+    pm_metadata: Option<serde_json::Value>,
+    storage_scheme: MerchantStorageScheme,
+) -> errors::CustomResult<(), errors::VaultError> {
+    let pm_update = payment_method::PaymentMethodUpdate::MetadataUpdateAndLastUsed {
+        metadata: pm_metadata,
+        last_used_at: common_utils::date_time::now(),
+    };
+    db.update_payment_method(pm, pm_update, storage_scheme)
+        .await
+        .change_context(errors::VaultError::UpdateInPaymentMethodDataTableFailed)?;
+    Ok(())
+}
+
+pub async fn update_payment_method_and_last_used(
+    db: &dyn db::StorageInterface,
+    pm: payment_method::PaymentMethod,
+    payment_method_update: Option<Encryption>,
     storage_scheme: MerchantStorageScheme,
 ) -> errors::CustomResult<(), errors::VaultError> {
-    let pm_update = payment_method::PaymentMethodUpdate::MetadataUpdate {
-        metadata: Some(pm_metadata),
+    let pm_update = payment_method::PaymentMethodUpdate::UpdatePaymentMethodDataAndLastUsed {
+        payment_method_data: payment_method_update,
+        last_used_at: common_utils::date_time::now(),
     };
     db.update_payment_method(pm, pm_update, storage_scheme)
         .await
diff --git a/crates/router/src/core/payments/operations/payment_response.rs b/crates/router/src/core/payments/operations/payment_response.rs
index c4e4cb694e6..8fb0964da6e 100644
--- a/crates/router/src/core/payments/operations/payment_response.rs
+++ b/crates/router/src/core/payments/operations/payment_response.rs
@@ -114,9 +114,14 @@ impl<F: Send + Clone> PostUpdateTracker<F, PaymentData<F>, types::PaymentsAuthor
             .get_payment_method_billing()
             .and_then(|billing_details| billing_details.address.as_ref())
             .and_then(|address| address.get_optional_full_name());
+        let mut should_avoid_saving = false;
 
         if let Some(payment_method_info) = &payment_data.payment_method_info {
             if payment_data.payment_intent.off_session.is_none() && resp.response.is_ok() {
+                should_avoid_saving = resp.request.payment_method_type
+                    == Some(enums::PaymentMethodType::ApplePay)
+                    || resp.request.payment_method_type
+                        == Some(enums::PaymentMethodType::GooglePay);
                 payment_methods::cards::update_last_used_at(
                     payment_method_info,
                     state,
@@ -179,6 +184,12 @@ impl<F: Send + Clone> PostUpdateTracker<F, PaymentData<F>, types::PaymentsAuthor
             let (payment_method_id, _payment_method_status) = save_payment_call_future.await?;
             payment_data.payment_attempt.payment_method_id = payment_method_id;
             Ok(())
+        } else if should_avoid_saving {
+            if let Some(pm_info) = &payment_data.payment_method_info {
+                payment_data.payment_attempt.payment_method_id =
+                    Some(pm_info.payment_method_id.clone());
+            };
+            Ok(())
         } else {
             // Save card flow
             let save_payment_data = tokenization::SavePaymentMethodData::from(resp);
diff --git a/crates/router/src/core/payments/tokenization.rs b/crates/router/src/core/payments/tokenization.rs
index 161a9a43532..619d74549e7 100644
--- a/crates/router/src/core/payments/tokenization.rs
+++ b/crates/router/src/core/payments/tokenization.rs
@@ -269,20 +269,15 @@ where
                                         pm.metadata.as_ref(),
                                         connector_token,
                                     )?;
-                                    if let Some(metadata) = pm_metadata {
-                                        payment_methods::cards::update_payment_method(
-                                            db,
-                                            pm.clone(),
-                                            metadata,
-                                            merchant_account.storage_scheme,
-                                        )
-                                        .await
-                                        .change_context(
-                                            errors::ApiErrorResponse::InternalServerError,
-                                        )
-                                        .attach_printable("Failed to add payment method in db")?;
-                                    };
-                                    // update if its a off-session mit payment
+                                    payment_methods::cards::update_payment_method_metadata_and_last_used(
+                                        db,
+                                        pm.clone(),
+                                        pm_metadata,
+                                        merchant_account.storage_scheme,
+                                    )
+                                    .await
+                                    .change_context(errors::ApiErrorResponse::InternalServerError)
+                                    .attach_printable("Failed to add payment method in db")?;
                                     if check_for_mit_mandates {
                                         let connector_mandate_details =
                                             update_connector_mandate_details_in_payment_method(
@@ -511,14 +506,10 @@ where
                                     )
                                     .await;
 
-                                let pm_update =
-                                    storage::PaymentMethodUpdate::PaymentMethodDataUpdate {
-                                        payment_method_data: pm_data_encrypted,
-                                    };
-
-                                db.update_payment_method(
+                                payment_methods::cards::update_payment_method_and_last_used(
+                                    db,
                                     existing_pm,
-                                    pm_update,
+                                    pm_data_encrypted,
                                     merchant_account.storage_scheme,
                                 )
                                 .await
@@ -528,7 +519,7 @@ where
                         }
                     },
                     None => {
-                        let customer_saved_pm_id_option = if payment_method_type
+                        let customer_saved_pm_option = if payment_method_type
                             == Some(api_models::enums::PaymentMethodType::ApplePay)
                             || payment_method_type
                                 == Some(api_models::enums::PaymentMethodType::GooglePay)
@@ -547,7 +538,7 @@ where
                                     .find(|payment_method| {
                                         payment_method.payment_method_type == payment_method_type
                                     })
-                                    .map(|pm| pm.payment_method_id.clone())),
+                                    .cloned()),
                                 Err(error) => {
                                     if error.current_context().is_db_not_found() {
                                         Ok(None)
@@ -566,8 +557,18 @@ where
                             Ok(None)
                         }?;
 
-                        if let Some(customer_saved_pm_id) = customer_saved_pm_id_option {
-                            resp.payment_method_id = customer_saved_pm_id;
+                        if let Some(customer_saved_pm) = customer_saved_pm_option {
+                            payment_methods::cards::update_last_used_at(
+                                &customer_saved_pm,
+                                state,
+                                merchant_account.storage_scheme,
+                            )
+                            .await
+                            .map_err(|e| {
+                                logger::error!("Failed to update last used at: {:?}", e);
+                            })
+                            .ok();
+                            resp.payment_method_id = customer_saved_pm.payment_method_id;
                         } else {
                             let pm_metadata =
                                 create_payment_method_metadata(None, connector_token)?;

## 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 -->
We need to update the last used for a payment method as whenever a payment is done with that particular saved payment method. Currently we if a customer is making a payment (CIT) with the payment data that is same as the one that is already saved we are not updating the last used a for the payment method in the db.

In this case the new CIT with the payment_data that is same as the one saved also needs to be tied to the saved pm and the last used for it needs to be updated.

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

-> Create mca
-> Save card for customer with setup_future_usage offsession
```
{
    "amount": 1000,
    "currency": "USD",
    "confirm": true,
    "capture_method": "automatic",
    "capture_on": "2022-09-10T10:11:12Z",
    "customer_id": "{{$timestamp}}",
    "email": "guest@example.com",
    "name": "John Doe",
    "phone": "999999999",
    "phone_country_code": "+65",
    "description": "Its my first payment request",
    "authentication_type": "no_three_ds",
    "return_url": "https://google.com",
    "payment_method": "card",
    "payment_method_type": "credit",
    "payment_method_data": {
        "card": {
            "card_number": "4111111111111111",
            "card_exp_month": "03",
            "card_exp_year": "2030",
            "card_holder_name": "sai harsha",
            "card_cvc": "737"
        }
    },
    "setup_future_usage": "off_session",
    "customer_acceptance": {
        "acceptance_type": "offline",
        "accepted_at": "1963-05-03T04:07:52.723Z",
        "online": {
            "ip_address": "in sit",
            "user_agent": "amet irure esse"
        }
    },
    "billing": {
        "address": {
            "line1": "1467",
            "line2": "Harrison Street",
            "line3": "Harrison Street",
            "city": "San Fransico",
            "state": "California",
            "zip": "94122",
            "country": "US",
            "first_name": "John",
            "last_name": "Doe"
        },
        "phone": {
            "number": "8056594427",
            "country_code": "+91"
        }
    },
    "shipping": {
        "address": {
            "line1": "1467",
            "line2": "Harrison Street",
            "line3": "Harrison Street",
            "city": "San Fransico",
            "state": "California",
            "zip": "94122",
            "country": "US",
            "first_name": "John",
            "last_name": "Doe"
        },
        "phone": {
            "number": "8056594427",
            "country_code": "+91"
        }
    },
    "browser_info": {
        "user_agent": "Mozilla\/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit\/537.36 (KHTML, like Gecko) Chrome\/70.0.3538.110 Safari\/537.36",
        "accept_header": "text\/html,application\/xhtml+xml,application\/xml;q=0.9,image\/webp,image\/apng,*\/*;q=0.8",
        "language": "nl-NL",
        "color_depth": 24,
        "screen_height": 723,
        "screen_width": 1536,
        "time_zone": 0,
        "java_enabled": true,
        "java_script_enabled": true,
        "ip_address": "125.0.0.1"
    },
    "statement_descriptor_name": "joseph",
    "statement_descriptor_suffix": "JS",
    "metadata": {},
    "order_details": [
        {
            "product_name": "Apple iphone 15",
            "quantity": 1,
            "amount": 0,
            "account_name": "transaction_processing"
        }
    ]
}
```
<img width="1083" alt="image" src="https://github.com/juspay/hyperswitch/assets/83439957/f4d7a58a-5c2d-4686-a669-22dc813fb546">


-> Add a one more payment method for the same customer
```
{
    "amount": 800,
    "currency": "USD",
    "confirm": true,
    "amount_to_capture": 800,
    "customer_id": "1719920836",
    "payment_type": "new_mandate",
    "capture_method": "automatic",
    "capture_on": "2022-09-10T10:11:12Z",
    "authentication_type": "three_ds",
    "return_url": "https://google.com",
    "email": "something@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": "apple_pay",
    "payment_method_data": {
        "wallet": {
            "apple_pay": {
                "payment_data":"eyJkYXRhIjoiSWJKaWp1TTRXT0lpM1BZcTRWVlpIL2wwUld1Qm5JRk5vMHBsWGp1L1E2bW9uQ0JVOE9rVHFDbnkwWDlZVVBZYzVBMXRIckE1eTV0NlpsSFVkZFJyYlY3QXIzMVVEc0NSbVlDVDRweFdEQ0oxTnF5WWYrK3NPQThZRkh5di83aUJiTnJ6K1g0Q0dwelNtelRNL2V6TUxzY2VCdHM4dkozQk05VnRGdVY2bXJsN2lPcGNHUGlNam5wK2ZkaG1OYlNHcGt0Qmt4QVRmaHlpM3VjbWNBejNjYWlMV3RSN2Yrc2owUmlzL0pBcmhuVzVZdmNodE53K2prSFBXZW9HeG1KTEFFUW1HRnZ3dGJCaWFKVFEvVnpmdEJtK3RGYkliWTBYeFdrRXdSQllIajlCVnVmbEVDaVlKK2NYLytBdVhlS2ZHZHZMQWZrNjNSYmZJQm5hTVR6dWlXZ2tEM1N5T3hJbE82MGxveHFPSmkxbkgvQXZSdFlMOUt4NWM0dzEwYnZVcENZZys4aytpdmg0aEdIdTF3PT0iLCJzaWduYXR1cmUiOiJNSUFHQ1NxR1NJYjNEUUVIQXFDQU1JQUNBUUV4RFRBTEJnbGdoa2dCWlFNRUFnRXdnQVlKS29aSWh2Y05BUWNCQUFDZ2dEQ0NBK013Z2dPSW9BTUNBUUlDQ0JaalRJc09NRmNYTUFvR0NDcUdTTTQ5QkFNQ01Ib3hMakFzQmdOVkJBTU1KVUZ3Y0d4bElFRndjR3hwWTJGMGFXOXVJRWx1ZEdWbmNtRjBhVzl1SUVOQklDMGdSek14SmpBa0JnTlZCQXNNSFVGd2NHeGxJRU5sY25ScFptbGpZWFJwYjI0Z1FYVjBhRzl5YVhSNU1STXdFUVlEVlFRS0RBcEJjSEJzWlNCSmJtTXVNUXN3Q1FZRFZRUUdFd0pWVXpBZUZ3MHlOREEwTWpreE56UTNNamRhRncweU9UQTBNamd4TnpRM01qWmFNRjh4SlRBakJnTlZCQU1NSEdWall5MXpiWEF0WW5KdmEyVnlMWE5wWjI1ZlZVTTBMVkJTVDBReEZEQVNCZ05WQkFzTUMybFBVeUJUZVhOMFpXMXpNUk13RVFZRFZRUUtEQXBCY0hCc1pTQkpibU11TVFzd0NRWURWUVFHRXdKVlV6QlpNQk1HQnlxR1NNNDlBZ0VHQ0NxR1NNNDlBd0VIQTBJQUJNSVZkKzNyMXNleUlZOW8zWENRb1NHTng3QzlieXdvUFlSZ2xkbEs5S1ZCRzROQ0R0Z1I4MEIrZ3pNZkhGVEQ5K3N5SU5hNjFkVHY5SktKaVQ1OER4T2pnZ0lSTUlJQ0RUQU1CZ05WSFJNQkFmOEVBakFBTUI4R0ExVWRJd1FZTUJhQUZDUHlTY1JQaytUdkorYkU5aWhzUDZLNy9TNUxNRVVHQ0NzR0FRVUZCd0VCQkRrd056QTFCZ2dyQmdFRkJRY3dBWVlwYUhSMGNEb3ZMMjlqYzNBdVlYQndiR1V1WTI5dEwyOWpjM0F3TkMxaGNIQnNaV0ZwWTJFek1ESXdnZ0VkQmdOVkhTQUVnZ0VVTUlJQkVEQ0NBUXdHQ1NxR1NJYjNZMlFGQVRDQi9qQ0J3d1lJS3dZQkJRVUhBZ0l3Z2JZTWdiTlNaV3hwWVc1alpTQnZiaUIwYUdseklHTmxjblJwWm1sallYUmxJR0o1SUdGdWVTQndZWEowZVNCaGMzTjFiV1Z6SUdGalkyVndkR0Z1WTJVZ2IyWWdkR2hsSUhSb1pXNGdZWEJ3YkdsallXSnNaU0J6ZEdGdVpHRnlaQ0IwWlhKdGN5QmhibVFnWTI5dVpHbDBhVzl1Y3lCdlppQjFjMlVzSUdObGNuUnBabWxqWVhSbElIQnZiR2xqZVNCaGJtUWdZMlZ5ZEdsbWFXTmhkR2x2YmlCd2NtRmpkR2xqWlNCemRHRjBaVzFsYm5SekxqQTJCZ2dyQmdFRkJRY0NBUllxYUhSMGNEb3ZMM2QzZHk1aGNIQnNaUzVqYjIwdlkyVnlkR2xtYVdOaGRHVmhkWFJvYjNKcGRIa3ZNRFFHQTFVZEh3UXRNQ3N3S2FBbm9DV0dJMmgwZEhBNkx5OWpjbXd1WVhCd2JHVXVZMjl0TDJGd2NHeGxZV2xqWVRNdVkzSnNNQjBHQTFVZERnUVdCQlNVVjl0djFYU0Job21KZGk5K1Y0VUg1NXRZSkRBT0JnTlZIUThCQWY4RUJBTUNCNEF3RHdZSktvWklodmRqWkFZZEJBSUZBREFLQmdncWhrak9QUVFEQWdOSkFEQkdBaUVBeHZBanl5WVV1ekE0aUtGaW1ENGFrL0VGYjFENmVNMjV1a3lpUWN3VTRsNENJUUMrUE5EZjBXSkg5a2xFZFRnT25VVENLS0VJa0tPaDNISkxpMHk0aUpnWXZEQ0NBdTR3Z2dKMW9BTUNBUUlDQ0VsdEw3ODZtTnFYTUFvR0NDcUdTTTQ5QkFNQ01HY3hHekFaQmdOVkJBTU1Fa0Z3Y0d4bElGSnZiM1FnUTBFZ0xTQkhNekVtTUNRR0ExVUVDd3dkUVhCd2JHVWdRMlZ5ZEdsbWFXTmhkR2x2YmlCQmRYUm9iM0pwZEhreEV6QVJCZ05WQkFvTUNrRndjR3hsSUVsdVl5NHhDekFKQmdOVkJBWVRBbFZUTUI0WERURTBNRFV3TmpJek5EWXpNRm9YRFRJNU1EVXdOakl6TkRZek1Gb3dlakV1TUN3R0ExVUVBd3dsUVhCd2JHVWdRWEJ3YkdsallYUnBiMjRnU1c1MFpXZHlZWFJwYjI0Z1EwRWdMU0JITXpFbU1DUUdBMVVFQ3d3ZFFYQndiR1VnUTJWeWRHbG1hV05oZEdsdmJpQkJkWFJvYjNKcGRIa3hFekFSQmdOVkJBb01Da0Z3Y0d4bElFbHVZeTR4Q3pBSkJnTlZCQVlUQWxWVE1Ga3dFd1lIS29aSXpqMENBUVlJS29aSXpqMERBUWNEUWdBRThCY1JoQm5YWklYVkdsNGxnUWQyNklDaTc5NTdyazNnamZ4TGsrRXpWdFZtV3pXdUl0Q1hkZzBpVG51NkNQMTJGODZJeTNhN1puQyt5T2dwaFA5VVJhT0I5ekNCOURCR0JnZ3JCZ0VGQlFjQkFRUTZNRGd3TmdZSUt3WUJCUVVITUFHR0ttaDBkSEE2THk5dlkzTndMbUZ3Y0d4bExtTnZiUzl2WTNOd01EUXRZWEJ3YkdWeWIyOTBZMkZuTXpBZEJnTlZIUTRFRmdRVUkvSkp4RStUNU84bjVzVDJLR3cvb3J2OUxrc3dEd1lEVlIwVEFRSC9CQVV3QXdFQi96QWZCZ05WSFNNRUdEQVdnQlM3c042aFdET0ltcVNLbWQ2K3ZldXYyc3NrcXpBM0JnTlZIUjhFTURBdU1DeWdLcUFvaGlab2RIUndPaTh2WTNKc0xtRndjR3hsTG1OdmJTOWhjSEJzWlhKdmIzUmpZV2N6TG1OeWJEQU9CZ05WSFE4QkFmOEVCQU1DQVFZd0VBWUtLb1pJaHZkalpBWUNEZ1FDQlFBd0NnWUlLb1pJemowRUF3SURad0F3WkFJd09zOXlnMUVXbWJHRyt6WERWc3Bpdi9RWDdka1BkVTJpanI3eG5JRmVRcmVKK0pqM20xbWZtTlZCRFkrZDZjTCtBakF5TGRWRUliQ2pCWGRzWGZNNE81Qm4vUmQ4TENGdGxrL0djbW1DRW05VStIcDlHNW5MbXdtSklXRUdtUThKa2gwQUFER0NBWWN3Z2dHREFnRUJNSUdHTUhveExqQXNCZ05WQkFNTUpVRndjR3hsSUVGd2NHeHBZMkYwYVc5dUlFbHVkR1ZuY21GMGFXOXVJRU5CSUMwZ1J6TXhKakFrQmdOVkJBc01IVUZ3Y0d4bElFTmxjblJwWm1sallYUnBiMjRnUVhWMGFHOXlhWFI1TVJNd0VRWURWUVFLREFwQmNIQnNaU0JKYm1NdU1Rc3dDUVlEVlFRR0V3SlZVd0lJRm1OTWl3NHdWeGN3Q3dZSllJWklBV1VEQkFJQm9JR1RNQmdHQ1NxR1NJYjNEUUVKQXpFTEJna3Foa2lHOXcwQkJ3RXdIQVlKS29aSWh2Y05BUWtGTVE4WERUSTBNRFV5TVRBM016TXlORm93S0FZSktvWklodmNOQVFrME1Sc3dHVEFMQmdsZ2hrZ0JaUU1FQWdHaENnWUlLb1pJemowRUF3SXdMd1lKS29aSWh2Y05BUWtFTVNJRUlEa29VdTlwZ01JUHR2R0VEZi9tSXk3LzNjSTg2b3U5eTJaZkV6RkhuRFN0TUFvR0NDcUdTTTQ5QkFNQ0JFWXdSQUlnTWdkSG9rZHNWQndya3RYRzd1VmowMm9QVVNsQllaWGVPeXJyd3RsQk5MUUNJRDdzZnZPaThZcjVWNkVyNjFqU05sKzR3ZDhpR050YUxEdFRMZjNBQ0VhNkFBQUFBQUFBIiwiaGVhZGVyIjp7InB1YmxpY0tleUhhc2giOiJ4MnFmMTFaemRXbnFCZnc0U0NyOWxIYzZRc1JQOEp6Z2xrZnU5RTVkWUpnPSIsImVwaGVtZXJhbFB1YmxpY0tleSI6Ik1Ga3dFd1lIS29aSXpqMENBUVlJS29aSXpqMERBUWNEUWdBRTR0bHR1ODRmdzNldG5zeWR0ZXh5RnJVeVRhN3pqbXlYcjZ3OFIraU9TUm1qUDV5ZWlWUEs4OWFoZDJYM1JtaUZtUjQxdHN4S1AwOEpBZVYrSXpvUXBnPT0iLCJ0cmFuc2FjdGlvbklkIjoiMmEzZDYyYTUzZDBmMzg1NGUwNTA0Y2RhZDU2MzlmYjA2MjJiZTI0YzY0ZDg2ZGYxMDlkMTNjZjdkNTAxNjA1MSJ9LCJ2ZXJzaW9uIjoiRUNfdjEifQ==",
                "payment_method": {
                    "display_name": "Visa 0326",
                    "network": "Mastercard",
                    "type": "debit"
                },
                "transaction_identifier": "55CC32D7BF7890B9064433F15B9F23F849CF84AFD01E4E65DD8ADE306300E9D8"
            }
        }
    },
    "setup_future_usage": "off_session",
    "customer_acceptance": {
        "acceptance_type": "offline",
        "accepted_at": "1963-05-03T04:07:52.723Z",
        "online": {
            "ip_address": "in sit",
            "user_agent": "amet irure esse"
        }
    },
    "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"
        }
    },
    "connector_metadata": {
        "noon": {
            "order_category": "pay"
        }
    }
}
```
<img width="1021" alt="image" src="https://github.com/juspay/hyperswitch/assets/83439957/f808e595-4827-425f-9aa1-701b0d6b2b28">


-> Do payment method list for the customer
```
curl --location 'http://localhost:8080/customers/1719920836/payment_methods' \
--header 'Accept: application/json' \
--header 'api-key:'
```
<img width="1028" alt="image" src="https://github.com/juspay/hyperswitch/assets/83439957/cf96e878-b109-4313-ab7f-b15ab72da3d9">

-> The above result will display the apple pay on the top as it is recently added
-> Now make a payment with the saved card
```
curl --location 'http://localhost:8080/payments' \
--header 'Accept: application/json' \
--header 'api-key: dev_2k0GtUf0vXE48EFiTyUt9BBpuVp3Ir4BllhjCYff5hEkBMoEtpLxhmOekQabpit5' \
--header 'Content-Type: application/json' \
--data-raw '{
    "amount": 800,
    "currency": "USD",
    "confirm": false,
    "amount_to_capture": 800,
    "customer_id": "1719920836",
    "capture_method": "automatic",
    "capture_on": "2022-09-10T10:11:12Z",
    "authentication_type": "three_ds",
    "return_url": "https://google.com",
    "email": "something@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",
    "setup_future_usage": "off_session"
}'
```
<img width="1115" alt="image" src="https://github.com/juspay/hyperswitch/assets/83439957/05abf536-d99f-40d4-a63f-214f40448983">

```
curl --location 'http://localhost:8080/payments/pay_rD3KvlEfGmMOWfdm6GF7/confirm' \
--header 'api-key: pk_dev_a2a54e7ab646435f8ab94e791a8d273e' \
--header 'Content-Type: application/json' \
--data '{
    "payment_token": "token_VV4tgEfPHNvgSkuEZWlN",
    "payment_method": "card",
    "client_secret": "pay_rD3KvlEfGmMOWfdm6GF7_secret_5fe0LNQ4eHIFbd8wz8CH"
}'
```
<img width="1097" alt="image" src="https://github.com/juspay/hyperswitch/assets/83439957/c12f8199-fc0b-4cfd-8c90-5d9bcf205c25">

-> Do payment method list for the customer and the card should appear at the top
```
curl --location 'http://localhost:8080/customers/1719920836/payment_methods' \
--header 'Accept: application/json' \
--header 'api-key: dev_2k0GtUf0vXE48EFiTyUt9BBpuVp3Ir4BllhjCYff5hEkBMoEtpLxhmOekQabpit5'
```
<img width="1138" alt="image" src="https://github.com/juspay/hyperswitch/assets/83439957/a09e4ddf-35fc-4e24-93e8-a9c421347d56">



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