Skip to content

Conversation

@prasunna09
Copy link
Contributor

@prasunna09 prasunna09 commented Sep 4, 2025

Type of Change

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

Description

Add external vault support in v1 payments flow.
Currently we only save card in hs-card-vault
Added new support to save card in external vault based merchant-profile configuration.

Changes in code -
During First CIT (fresh card for a customer c1 - setup future usage - on_session with customer acceptance)

  • based on profile level config, vault is decided, vault creds are fetched from MCA. payment method data is stored in respective vault.
    During Repeat CIT (Saved card for a customer c1 - payment token for c1)
  • based on pm entry - vault type, and vault mca id, if external, mca creds are fetched, if internal, default flow.

DB changes -
In business profile in api level & db level-

is_external_vault_enabled: Option<bool>, //Indicates if external vault is enabled or not.
external_vault_connector_details: Option<ExternalVaultConnectorDetails>,// holds the active External Vault Connector Details

In Payment method table in db level (diesel model) -

pub external_vault_source: Option<common_utils::id_type::MerchantConnectorAccountId>, //holds the mca of external vault with which payment method data has been stored
pub vault_type: Option<storage_enums::VaultType>, //enum variant whether it is ext vault or internal vault

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?

  • Create Vault Connector MCA (Eg - VGS)
curl --location 'http://localhost:8080/account/merchant_1758632854/connectors' \
--header 'Content-Type: application/json' \
--header 'Accept: application/json' \
--header 'api-key: dev_jN7RVfxJgyz3GB7OASKFved09yY2lA17xEJSBbj47tBN03inP9rCADUooCF5Ozz6' \
--data '{
    "connector_type": "vault_processor",
    "connector_name": "vgs",
    "connector_account_details": {
        "auth_type": "SignatureKey",
        "api_key": "api key",
        "key1": "key 1",
        "api_secret": "api_secret"
    },
    "test_mode": true,
    "disabled": false,
    "business_country": "US",
    "business_label": "default",
    "payment_methods_enabled": [
    ],
    "metadata": {
        "endpoint_prefix": "ghjg",
        "google_pay": {
            "allowed_payment_methods": [
                {
                    "type": "CARD",
                    "parameters": {
                        "allowed_auth_methods": [
                            "PAN_ONLY",
                            "CRYPTOGRAM_3DS"
                        ],
                        "allowed_card_networks": [
                            "AMEX",
                            "DISCOVER",
                            "INTERAC",
                            "JCB",
                            "MASTERCARD",
                            "VISA"
                        ]
                    },
                    "tokenization_specification": {
                        "type": "PAYMENT_GATEWAY"
                    }
                }
            ],
            "merchant_info": {
                "merchant_name": "Narayan Bhat"
            }
        }
    },
     "connector_webhook_details": {
        "merchant_secret": "7091687210DF6DCA38B2E670B3D68EB53516A26CA85590E29024FFBD7CD23980"
    },
    "profile_id":"pro_KH7MujUjH2miLhfzGlAB"
}'
  • Update Profile with below config to enable external vault
"is_external_vault_enabled": "enable",
    "external_vault_connector_details": {
        "vault_connector_id": "mca_lRJXlrSQ557zrIJUalxK"
    }
  • Create payment with customer acceptance, and setup_future_usage - on_session/off_session
curl --location 'http://localhost:8080/payments' \
--header 'Content-Type: application/json' \
--header 'Accept: application/json' \
--header 'api-key:api key' \
--data-raw '
{
    "amount": 1000,
    "currency": "USD",
    "confirm": true,
    "capture_method": "automatic",
    "capture_on": "2022-09-10T10:11:12Z",
    
    "customer_id": "cu_1758488194",
    "email": "[email protected]",
    "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": "card_number",
            "card_exp_month": "03",
            "card_exp_year": "2030",
            "card_holder_name": "joseph Doe",
            "card_cvc": "737"
        }
    },

    "billing": {
        "address": {
            "line1": "1467",
            "line2": "Harrison Street",
            "line3": "Harrison Street",
            "city": "San Fransico",
            "state": "California",
            "zip": "94122",
            "country": "US",
            "first_name": "PiX",
            "last_name": "ss"
        }
    },
    "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"
        }
    ],
    "profile_id": "pro_KH7MujUjH2miLhfzGlAB"
}'
  • Payment method should be saved with
    external_vault_source - mca_lRJXlrSQ557zrIJUalxK (VGS mca id)
    vault_type - external
Screenshot 2025-09-22 at 2 35 04 AM
  • If VGS is not enabled, then
    external_vault_source -
    vault_type - internal
Screenshot 2025-09-22 at 2 36 08 AM
  • make repeat CIT

Please note, test backward compatibility
how to -make a payment with existing customer's saved payment method

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

@prasunna09 prasunna09 self-assigned this Sep 4, 2025
@prasunna09 prasunna09 requested review from a team as code owners September 4, 2025 07:51
@semanticdiff-com
Copy link

semanticdiff-com bot commented Sep 4, 2025

Review changes with  SemanticDiff

Changed Files
File Status
  crates/router/src/types/api/connector_mapping.rs  88% smaller
  crates/router/src/core/utils.rs  49% smaller
  crates/hyperswitch_domain_models/src/business_profile.rs  45% smaller
  crates/hyperswitch_domain_models/src/payment_methods.rs  34% smaller
  crates/router/src/core/payment_methods.rs  30% smaller
  crates/diesel_models/src/schema_v2.rs  22% smaller
  crates/router/src/core/payment_methods/vault.rs  14% smaller
  crates/diesel_models/src/business_profile.rs  13% smaller
  crates/openapi/src/openapi.rs  7% smaller
  crates/router/src/core/payments/tokenization.rs  1% smaller
  crates/router/src/core/admin.rs  1% smaller
  api-reference/v1/openapi_spec_v1.json  0% smaller
  crates/api_models/src/admin.rs  0% smaller
  crates/api_models/src/payment_methods.rs  0% smaller
  crates/common_enums/src/enums.rs  0% smaller
  crates/diesel_models/src/payment_method.rs  0% smaller
  crates/diesel_models/src/schema.rs  0% smaller
  crates/hyperswitch_domain_models/src/merchant_connector_account.rs  0% smaller
  crates/hyperswitch_domain_models/src/payment_method_data.rs  0% smaller
  crates/payment_methods/src/controller.rs  0% smaller
  crates/payment_methods/src/core/migration/payment_methods.rs  0% smaller
  crates/router/src/core/errors/utils.rs  0% smaller
  crates/router/src/core/payment_methods/cards.rs  0% smaller
  crates/router/src/core/payment_methods/tokenize/card_executor.rs  0% smaller
  crates/router/src/core/payments/helpers.rs  0% smaller
  crates/router/src/core/payments/vault_session.rs Unsupported file format
  crates/router/src/core/payouts/helpers.rs  0% smaller
  crates/router/src/core/pm_auth.rs  0% smaller
  crates/router/src/db/events.rs  0% smaller
  crates/router/src/types/api/admin.rs  0% smaller
  crates/router/src/types/domain.rs  0% smaller
  crates/router/src/types/payment_methods.rs  0% smaller
  migrations/2025-09-20-190742_add_external_vault_source_in_payment_method_and_is_external_vault_enabled_in_profile/down.sql Unsupported file format
  migrations/2025-09-20-190742_add_external_vault_source_in_payment_method_and_is_external_vault_enabled_in_profile/up.sql Unsupported file format

@hyperswitch-bot hyperswitch-bot bot added the M-database-changes Metadata: This PR involves database schema changes label Sep 4, 2025
Comment on lines 1 to 6
-- Your SQL goes here
ALTER TABLE business_profile
ADD COLUMN IF NOT EXISTS is_external_vault_enabled BOOLEAN;

ALTER TABLE business_profile
ADD COLUMN IF NOT EXISTS external_vault_connector_details JSONB;
Copy link
Contributor

Choose a reason for hiding this comment

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

we already have same migrations present in v2_compatible_migrations, instead of multiple instances is it possible to have a common migration between both @hrithikesh026

Copy link
Contributor Author

Choose a reason for hiding this comment

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

yes, we already have v2.
but for v1 schema, v2_compatible_migrations wont be running. so its required to write under v1 migrations.
@sai-harsha-vardhan could you please help here

AkshayaFoiger
AkshayaFoiger previously approved these changes Sep 15, 2025
Copy link
Contributor

@Sakilmostak Sakilmostak left a comment

Choose a reason for hiding this comment

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

LGTM!

Sakilmostak
Sakilmostak previously approved these changes Sep 16, 2025
AkshayaFoiger
AkshayaFoiger previously approved these changes Sep 16, 2025

let key_manager_state = &state.into();

let merchant_connector_account_details = state
Copy link
Member

Choose a reason for hiding this comment

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

We need to abstract these out, we can do this later, normally itself bad to read these static data deeper in the floe

@@ -0,0 +1,2 @@
-- This file should undo anything in `up.sql`
ALTER TABLE payment_methods ADD COLUMN IF NOT EXISTS vault_type VARCHAR(16); No newline at end of file
Copy link
Member

Choose a reason for hiding this comment

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

this can be more like 64, can you merge query to single up and down sql files

jarnura
jarnura previously approved these changes Sep 22, 2025
@prasunna09 prasunna09 linked an issue Sep 22, 2025 that may be closed by this pull request
@hyperswitch-bot hyperswitch-bot bot added the M-api-contract-changes Metadata: This PR involves API contract changes label Sep 23, 2025
@bernard-eugine bernard-eugine added this pull request to the merge queue Sep 23, 2025
Merged via the queue into main with commit e410af2 Sep 23, 2025
21 of 25 checks passed
@bernard-eugine bernard-eugine deleted the add-external-vault-in-v1 branch September 23, 2025 07:20
srujanchikke pushed a commit that referenced this pull request Sep 29, 2025
Co-authored-by: hyperswitch-bot[bot] <148525504+hyperswitch-bot[bot]@users.noreply.github.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

M-api-contract-changes Metadata: This PR involves API contract changes M-database-changes Metadata: This PR involves database schema changes

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[FEATURE] Add external vault support in v1

6 participants