Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

refactor(core): Refactor Payment method vaulting APIs for v2 #5041

Open
wants to merge 82 commits into
base: main
Choose a base branch
from

Conversation

Sarthak1799
Copy link
Contributor

@Sarthak1799 Sarthak1799 commented Jun 19, 2024

Type of Change

  • Bugfix
  • New feature
  • Enhancement
  • Refactoring
  • Dependency updates
  • Documentation
  • CI/CD

Description

This PR does -

  • Refactored the api model types for payment method create
  • Added new implementations for vaulting APIs for v2

Additional Changes

  • This PR modifies the API contract
  • This PR modifies the database schema
  • This PR modifies application configuration/environment variables

Motivation and Context

How did you test it?

  • Vault payment method directly using S2S call
curl --location --request POST 'http://localhost:8080/v2/payment_methods' \
--header 'Content-Type: application/json' \
--header 'Accept: application/json' \
--header 'api-key: dev_cHN6hMdCFUUrNWjYSxnwhiuMsg83rXTX9jBmtHmCL6sq9a43PswY304MSt3a9blR' \
--data-raw '{
    "customer_id": "cus_douWhgGzf3QzCpnN09Sl",
    "payment_method": "card",
    "payment_method_type": "credit",
    "payment_method_issuer": "visa",
     "payment_method_data": {
        "card": {
            "card_number": "4242424242424242",
            "card_exp_month": "08",
            "card_exp_year": "2028",
            "card_holder_name": "joseph"
        }
    }
}'

Response

{
    "merchant_id": "sarthak1",
    "customer_id": "cus_douWhgGzf3QzCpnN09Sl",
    "payment_method_id": "pm_4mziQ0WdlJ9DmgEAkZKB",
    "payment_method": "card",
    "payment_method_type": "credit",
    "recurring_enabled": false,
    "installment_payment_enabled": false,
    "payment_experience": [
        "redirect_to_url"
    ],
    "metadata": null,
    "created": "2024-07-02T13:35:57.283Z",
    "last_used_at": "2024-07-02T13:35:57.283Z",
    "client_secret": "pm_4mziQ0WdlJ9DmgEAkZKB_secret_ywxq9ociaeoJ5L5KqtDT",
    "payment_method_data": {
        "card": {
            "scheme": null,
            "issuer_country": null,
            "last4_digits": "4242",
            "expiry_month": "08",
            "expiry_year": "2028",
            "card_token": null,
            "card_holder_name": "joseph",
            "card_fingerprint": null,
            "nick_name": null,
            "card_network": null,
            "card_isin": "424242",
            "card_issuer": null,
            "card_type": null,
            "saved_to_locker": true
        }
    }
}
  • Vault using SDK, hit /payment_methods to get client_secret
curl --location --request POST 'http://localhost:8080/v2/payment_methods' \
--header 'Content-Type: application/json' \
--header 'Accept: application/json' \
--header 'api-key: dev_cHN6hMdCFUUrNWjYSxnwhiuMsg83rXTX9jBmtHmCL6sq9a43PswY304MSt3a9blR' \
--data-raw '{
    "customer_id": "cus_douWhgGzf3QzCpnN09Sl"
}'

Response -

{
    "merchant_id": "sarthak1",
    "customer_id": "cus_douWhgGzf3QzCpnN09Sl",
    "payment_method_id": "pm_DSj3Cxa5hdvuGn4vBEm9",
    "payment_method": null,
    "payment_method_type": null,
    "recurring_enabled": false,
    "installment_payment_enabled": false,
    "payment_experience": null,
    "metadata": null,
    "created": "2024-07-02T13:36:59.676Z",
    "last_used_at": null,
    "client_secret": "pm_DSj3Cxa5hdvuGn4vBEm9_secret_My7N4P2w3eAL7sKW1c8G",
    "payment_method_data": null
}
  • Vault using /save
curl --location --request POST 'http://localhost:8080/v2/payment_methods/pm_DSj3Cxa5hdvuGn4vBEm9/save' \
--header 'Content-Type: application/json' \
--header 'Accept: application/json' \
--header 'api-key: pk_dev_16e38a16176e45298a70da6c56c5028d' \
--data-raw '{
    "payment_method": "card",
    "payment_method_type": "credit",
    "payment_method_issuer": "visa",
    "client_secret": "pm_DSj3Cxa5hdvuGn4vBEm9_secret_My7N4P2w3eAL7sKW1c8G",
    "payment_method_data": {
        "card": {
            "card_number": "4242424242424242",
            "card_exp_month": "08",
            "card_exp_year": "2028",
            "card_holder_name": "joseph"
        }
    }
}'

Response -

{
    "merchant_id": "sarthak1",
    "customer_id": null,
    "payment_method_id": "pm_DSj3Cxa5hdvuGn4vBEm9",
    "payment_method": "card",
    "payment_method_type": "credit",
    "recurring_enabled": false,
    "installment_payment_enabled": false,
    "payment_experience": [
        "redirect_to_url"
    ],
    "metadata": null,
    "created": "2024-07-02T13:37:50.553Z",
    "last_used_at": "2024-07-02T13:37:50.554Z",
    "client_secret": "pm_DSj3Cxa5hdvuGn4vBEm9_secret_My7N4P2w3eAL7sKW1c8G",
    "payment_method_data": {
        "card": {
            "scheme": null,
            "issuer_country": null,
            "last4_digits": "4242",
            "expiry_month": "08",
            "expiry_year": "2028",
            "card_token": null,
            "card_holder_name": "joseph",
            "card_fingerprint": null,
            "nick_name": null,
            "card_network": null,
            "card_isin": "424242",
            "card_issuer": null,
            "card_type": null,
            "saved_to_locker": true
        }
    }
}

Checklist

  • I formatted the code cargo +nightly fmt --all
  • I addressed lints thrown by cargo clippy
  • I reviewed the submitted code
  • I added unit tests for my changes where possible

@Sarthak1799 Sarthak1799 added A-core Area: Core flows A-payment-methods Area: Payment Methods C-refactor Category: Refactor labels Jun 19, 2024
@Sarthak1799 Sarthak1799 self-assigned this Jun 19, 2024
@Sarthak1799 Sarthak1799 requested review from a team as code owners June 19, 2024 10:35
@hyperswitch-bot hyperswitch-bot bot added the M-api-contract-changes Metadata: This PR involves API contract changes label Jun 26, 2024
@Sarthak1799 Sarthak1799 requested a review from a team as a code owner July 28, 2024 10:19
#[cfg(all(feature = "v2", feature = "payment_methods_v2"))]
pub struct PaymentMethodVaultingData {
pub pm_id: Option<String>,
pub payment_method: Option<diesel_models::PaymentMethod>,
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We don't have a equivalent domain type for this?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not yet, will implement domain model for Payment Method along with the diesel related changes.

crates/router/src/core/payment_methods.rs Outdated Show resolved Hide resolved
}

#[cfg(all(feature = "v2", feature = "payment_methods_v2"))]
pub async fn perform_surcharge_decision_management_for_saved_cards(
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

what us surcharge_decision_management. write a comment explaining that or change the function name to give more specific meaning

@@ -660,6 +681,89 @@ pub async fn get_client_secret_or_add_payment_method(
}
}

#[cfg(all(feature = "v2", feature = "payment_methods_v2"))]
#[instrument(skip_all)]
pub async fn get_client_secret_or_add_payment_method(
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What is the client_secret part here?, the function implementation says only about adding a payment_method.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In case the payment_method_data is present in body, we take the data and vault directly (S2S call).
In case it is not present, we create a payment_method entry along with a client_secret and send back the response. This client_secret can be used to vault payment_method using SDK (the /save endpoint)

status: Some(enums::PaymentMethodStatus::Inactive),
};

db.update_payment_method(payment_method, pm_update, merchant_account.storage_scheme)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Already we are updating the payment_method then why we do have get_or_insert_payment_method below this?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There are two different payment_methods involved here. For the /save endpoint, i.e. vault a payment_method using SDK, if the data for payment_method is duplicated, we deactivate the current record for the payment_method and fetch the already existing one.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
A-core Area: Core flows A-payment-methods Area: Payment Methods C-refactor Category: Refactor M-api-contract-changes Metadata: This PR involves API contract changes
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants