Skip to content

Conversation

su-shivanshmathur
Copy link
Contributor

@su-shivanshmathur su-shivanshmathur commented Sep 8, 2025

Type of Change

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

Description

Request creation changes for injector to be used InjectorRequest struct creation.

impl InjectorRequest {
        pub fn new()
}

Also change the response type

pub struct InjectorResponse {
        /// HTTP status code from the connector response
        pub status_code: u16,
        /// Response headers from the connector (optional)
        pub headers: Option<HashMap<String, String>>,
        /// Response body from the connector
        pub response: serde_json::Value,
    }

Additional Changes

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

Motivation and Context

Making injector request and response more responsive and detailed from HTTP request

How did you test it?

Test cases which are present in the crate

  1. Create a profile
curl --location 'http://localhost:8080/v2/profiles' \
--header 'x-merchant-id: MERCHANT_ID' \
--header 'Authorization: admin-api-key=ADMIN_API_KEY' \

--header 'Content-Type: application/json' \
--header 'api-key: ADMIN_API_KEY' \
--data-raw '{
    "profile_name": "business_test_5",
    "return_url": "https://google.com/success",
    "enable_payment_response_hash": true,
    "redirect_to_merchant_with_http_post": false,
    "webhook_details": {
        "webhook_version": "1.0.1",
        "webhook_username": "ekart_retail",
        "webhook_password": "password_ekart@123",
        "webhook_url": "https://webhook.site",
        "payment_created_enabled": true,
        "payment_succeeded_enabled": true,
        "payment_failed_enabled": true
    },
    "metadata": null,
    "order_fulfillment_time": 900,
    "order_fulfillment_time_origin": "create",
    "applepay_verified_domains": null,
    "session_expiry": 900,
    "payment_link_config": null,
    "authentication_connector_details": null,
    "use_billing_as_payment_method_billing": true,
    "collect_shipping_details_from_wallet_connector_if_required": false,
    "collect_billing_details_from_wallet_connector_if_required": false,
    "always_collect_shipping_details_from_wallet_connector": false,
    "always_collect_billing_details_from_wallet_connector": false,
    "is_connector_agnostic_mit_enabled": false,
    "payout_link_config": null,
    "outgoing_webhook_custom_http_headers": null
}'

Response

{
    "merchant_id": "cloth_seller_TEP9F7yYvhHwegRK39Nf",
    "id": "PROFILE_ID",
    "profile_name": "business_test_7",
    "return_url": "https://google.com/success",
    "enable_payment_response_hash": true,
    "payment_response_hash_key": "NFgBM5rvXEI0wLgqQvT3oEgFPqj5w3Ncupj3bEA5MYanoJwq1oIycDh0jWEHGuUx",
    "redirect_to_merchant_with_http_post": false,
    "webhook_details": {
        "webhook_version": "1.0.1",
        "webhook_username": "ekart_retail",
        "webhook_password": "password_ekart@123",
        "webhook_url": "https://webhook.site",
        "payment_created_enabled": true,
        "payment_succeeded_enabled": true,
        "payment_failed_enabled": true,
        "payment_statuses_enabled": null,
        "refund_statuses_enabled": null,
        "payout_statuses_enabled": null
    },
    "metadata": null,
    "applepay_verified_domains": null,
    "session_expiry": 900,
    "payment_link_config": null,
    "authentication_connector_details": null,
    "use_billing_as_payment_method_billing": true,
    "extended_card_info_config": null,
    "collect_shipping_details_from_wallet_connector_if_required": false,
    "collect_billing_details_from_wallet_connector_if_required": false,
    "always_collect_shipping_details_from_wallet_connector": false,
    "always_collect_billing_details_from_wallet_connector": false,
    "is_connector_agnostic_mit_enabled": false,
    "payout_link_config": null,
    "outgoing_webhook_custom_http_headers": null,
    "order_fulfillment_time": 900,
    "order_fulfillment_time_origin": "create",
    "tax_connector_id": null,
    "is_tax_connector_enabled": false,
    "is_network_tokenization_enabled": false,
    "should_collect_cvv_during_payment": null,
    "is_click_to_pay_enabled": false,
    "authentication_product_ids": null,
    "card_testing_guard_config": {
        "card_ip_blocking_status": "disabled",
        "card_ip_blocking_threshold": 3,
        "guest_user_card_blocking_status": "disabled",
        "guest_user_card_blocking_threshold": 10,
        "customer_id_blocking_status": "disabled",
        "customer_id_blocking_threshold": 5,
        "card_testing_guard_expiry": 3600
    },
    "is_clear_pan_retries_enabled": false,
    "is_debit_routing_enabled": false,
    "merchant_business_country": null,
    "is_iframe_redirection_enabled": null,
    "is_external_vault_enabled": null,
    "external_vault_connector_details": null,
    "merchant_category_code": null,
    "merchant_country_code": null,
    "split_txns_enabled": "skip"
}
  1. Create a connector account for vault processor (VGS)
curl --location 'http://localhost:8080/v2/connector-accounts' \
--header 'Content-Type: application/json' \
--header 'Accept: application/json' \
--header 'x-merchant-id: MERCHANT_ID' \
--header 'x-profile-id: PROFILE_ID' \
--header 'x-feature: hyperswitch-custom-v2' \
--header 'Authorization: admin-api-key=ADMIN_API_KEY' \
--header 'api-key: ADMIN_API_KEY' \
--data-raw '{
"connector_type": "vault_processor",
    "connector_name": "vgs",
    "connector_account_details": {
        "auth_type": "SignatureKey",
        "api_key": "{CONNECTOR_API_KEY}",
        "key1": "{CONNECTOR_KEY1}",
        "api_secret": "{CONNECTOR_API_SECRET}"
    },
    "frm_configs": null,
    "connector_webhook_details": {
        "merchant_secret": ""
    },
    "profile_id": "PROFILE_ID",
    "metadata": {
        "proxy_url": "{VAULT_URL}",
        "certificate": "{BASE64_ENCODED_CERTIFICATE}"
    }
}'

Response

{
    "connector_type": "vault_processor",
    "connector_name": "vgs",
    "connector_label": "vgs_business_test_7",
    "id": "MERCHANT_CONNECTOR_ACCOUNT_ID",
    "profile_id": "PROFILE_ID",
    "connector_account_details": {
        "auth_type": "SignatureKey",
        "api_key": "US********************mi",
        "key1": "86********************************26",
        "api_secret": "tn*******lr"
    },
    "payment_methods_enabled": null,
    "connector_webhook_details": {
        "merchant_secret": "",
        "additional_secret": null
    },
    "metadata": {
        "proxy_url": "https://vault.verygoodproxy.com",
        "certificate": "CERTIFICATE_BASE64_ENCODED"
    },
    "disabled": false,
    "frm_configs": null,
    "applepay_verified_domains": null,
    "pm_auth_config": null,
    "status": "active",
    "additional_merchant_data": null,
    "connector_wallets_details": null,
    "feature_metadata": null
}
  1. Create a connector account for payment processor (Adyen)
curl --location 'http://localhost:8080/v2/connector-accounts' \
--header 'Content-Type: application/json' \
--header 'Accept: application/json' \
--header 'x-merchant-id: MERCHANT_ID' \
--header 'x-profile-id: PROFILE_ID' \
--header 'Authorization: admin-api-key=ADMIN_API_KEY' \
--header 'api-key: ADMIN_API_KEY' \
--data '{
    "connector_type": "payment_processor",
    "connector_name": "adyen",
     "connector_account_details": {
        "auth_type": "SignatureKey",
        "api_key": "{CONNECTOR_API_KEY}",
        "key1": "{CONNECTOR_KEY1}",
        "api_secret":"{CONNECTOR_API_SECRET}"
    },
    "payment_methods_enabled": [
        {
            "payment_method_type": "card",
            "payment_method_subtypes": [
                {
                    "payment_method_subtype": "credit",
                    "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_subtype": "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_type": "wallet",
            "payment_method_subtypes": [
                {
                    "payment_method_subtype": "google_pay",
                    "payment_experience": null,
                    "card_networks": null,
                    "accepted_currencies": null,
                    "accepted_countries": null,
                    "minimum_amount": -1,
                    "maximum_amount": 68607706,
                    "recurring_enabled": true,
                    "installment_payment_enabled": true
                },
                {
                    "payment_method_subtype": "apple_pay",
                    "payment_experience": null,
                    "card_networks": null,
                    "accepted_currencies": null,
                    "accepted_countries": null,
                    "minimum_amount": -1,
                    "maximum_amount": 68607706,
                    "recurring_enabled": true,
                    "installment_payment_enabled": true
                },
                {
                    "payment_method_subtype": "we_chat_pay",
                    "payment_experience": null,
                    "card_networks": null,
                    "accepted_currencies": null,
                    "accepted_countries": null,
                    "minimum_amount": -1,
                    "maximum_amount": 68607706,
                    "recurring_enabled": true,
                    "installment_payment_enabled": true
                },
                {
                    "payment_method_subtype": "ali_pay",
                    "payment_experience": null,
                    "card_networks": null,
                    "accepted_currencies": null,
                    "accepted_countries": null,
                    "minimum_amount": -1,
                    "maximum_amount": 68607706,
                    "recurring_enabled": true,
                    "installment_payment_enabled": true
                },
                {
                    "payment_method_subtype": "paypal",
                    "payment_experience": null,
                    "card_networks": null,
                    "accepted_currencies": null,
                    "accepted_countries": null,
                    "minimum_amount": -1,
                    "maximum_amount": 68607706,
                    "recurring_enabled": true,
                    "installment_payment_enabled": true
                },
                {
                    "payment_method_subtype": "mb_way",
                    "payment_experience": null,
                    "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": "pay_later",
            "payment_method_subtypes": [
                {
                    "payment_method_subtype": "klarna",
                    "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
                },
                {
                    "payment_method_subtype": "affirm",
                    "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
                },
                {
                    "payment_method_subtype": "afterpay_clearpay",
                    "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
                },
                {
                    "payment_method_subtype": "walley",
                    "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
                }
            ]
        }
        
        
    ],
    "metadata": {
        "status_url": "https://example.com/status",
        "account_name": "transaction_processing",
        "pricing_type": "fixed_price",
        "acquirer_bin": "438309",
        "acquirer_merchant_id": "00002000000"
    },
    "frm_configs": null,
    "connector_webhook_details": {
        "merchant_secret": ""
    },
    "profile_id": "PROFILE_ID"
}'

Response

{
    "connector_type": "payment_processor",
    "connector_name": "adyen",
    "connector_label": "adyen_business_test_7",
    "id": "MERCHANT_CONNECTOR_ACCOUNT_ID",
    "profile_id": "PROFILE_ID",
    "connector_account_details": {
        "auth_type": "SignatureKey",
        "api_key": "US********************mi",
        "key1": "Ju*******************************OM",
        "api_secret": "tn*******"
    },
    "payment_methods_enabled": [
        {
            "payment_method_type": "card",
            "payment_method_subtypes": [
                {
                    "payment_method_subtype": "credit",
                    "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_subtype": "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_type": "wallet",
            "payment_method_subtypes": [
                {
                    "payment_method_subtype": "google_pay",
                    "payment_experience": null,
                    "card_networks": null,
                    "accepted_currencies": null,
                    "accepted_countries": null,
                    "minimum_amount": -1,
                    "maximum_amount": 68607706,
                    "recurring_enabled": true,
                    "installment_payment_enabled": true
                },
                {
                    "payment_method_subtype": "apple_pay",
                    "payment_experience": null,
                    "card_networks": null,
                    "accepted_currencies": null,
                    "accepted_countries": null,
                    "minimum_amount": -1,
                    "maximum_amount": 68607706,
                    "recurring_enabled": true,
                    "installment_payment_enabled": true
                },
                {
                    "payment_method_subtype": "we_chat_pay",
                    "payment_experience": null,
                    "card_networks": null,
                    "accepted_currencies": null,
                    "accepted_countries": null,
                    "minimum_amount": -1,
                    "maximum_amount": 68607706,
                    "recurring_enabled": true,
                    "installment_payment_enabled": true
                },
                {
                    "payment_method_subtype": "ali_pay",
                    "payment_experience": null,
                    "card_networks": null,
                    "accepted_currencies": null,
                    "accepted_countries": null,
                    "minimum_amount": -1,
                    "maximum_amount": 68607706,
                    "recurring_enabled": true,
                    "installment_payment_enabled": true
                },
                {
                    "payment_method_subtype": "paypal",
                    "payment_experience": null,
                    "card_networks": null,
                    "accepted_currencies": null,
                    "accepted_countries": null,
                    "minimum_amount": -1,
                    "maximum_amount": 68607706,
                    "recurring_enabled": true,
                    "installment_payment_enabled": true
                },
                {
                    "payment_method_subtype": "mb_way",
                    "payment_experience": null,
                    "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": "pay_later",
            "payment_method_subtypes": [
                {
                    "payment_method_subtype": "klarna",
                    "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
                },
                {
                    "payment_method_subtype": "affirm",
                    "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
                },
                {
                    "payment_method_subtype": "afterpay_clearpay",
                    "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
                },
                {
                    "payment_method_subtype": "walley",
                    "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_webhook_details": {
        "merchant_secret": "",
        "additional_secret": null
    },
    "metadata": {
        "status_url": "https://2753-2401-4900-1cb8-2ff9-24dd-1ccf-ed12-b464.in.ngrok.io/webhooks/merchant_1678699058/globalpay",
        "account_name": "transaction_processing",
        "acquirer_bin": "438309",
        "pricing_type": "fixed_price",
        "acquirer_merchant_id": "00002000000"
    },
    "disabled": false,
    "frm_configs": null,
    "applepay_verified_domains": null,
    "pm_auth_config": null,
    "status": "active",
    "additional_merchant_data": null,
    "connector_wallets_details": null,
    "feature_metadata": null
}
  1. Create an API key for the profile
curl --location 'http://localhost:8080/v2/api-keys' \
--header 'x-merchant-id: MERCHANT_ID' \
--header 'Authorization: admin-api-key=ADMIN_API_KEY' \
--header 'Content-Type: application/json' \
--header 'api-key: ADMIN_API_KEY' \
--data '{
    "name": "My Api Key",
    "expiration": "never"
}'

Response

{
    "key_id": "KEY_ID",
    "merchant_id": "MERCHANT_ID",
    "name": "My Api Key",
    "description": null,
    "api_key": "API_KEY",
    "created": "2025-09-11T10:14:53.929Z",
    "expiration": "never"
}
  1. Create a customer
curl --location 'http://localhost:8080/v2/customers' \
--header 'x-profile-id: PROFILE_ID' \
--header 'Authorization: api-key=API_KEY' \
--header 'Content-Type: application/json' \
--header 'api-key: API_KEY' \
--data-raw '{   
    "merchant_reference_id": "customer_1757584966",
    "name": "John Doe",
    "email": "[email protected]",
    "phone": "999999999",
    "phone_country_code": "+65",
    "description": "First customer",
    "default_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"
    },
    "default_shipping_address": {
        "line1": "1467",
        "line2": "Harrison Street",
        "line3": "Harrison Street",
        "city": "San Fransico",
        "state": "California",
        "zip": "94122",
        "country": "US",
        "first_name": "joseph",
        "last_name": "Doe"
    },
    "metadata": {
        "udf1": "value1",
        "new_customer": "true",
        "login_date": "2019-09-10T10:11:12Z"
    }
}'

Response

{
    "id": "12345_cus_01993844c6c47dc39f528073a92ad278",
    "merchant_reference_id": "customer_1757585655",
    "connector_customer_ids": null,
    "name": "John Doe",
    "email": "[email protected]",
    "phone": "999999999",
    "phone_country_code": "+65",
    "description": "First customer",
    "default_billing_address": null,
    "default_shipping_address": null,
    "created_at": "2025-09-11T10:14:15.493Z",
    "metadata": {
        "udf1": "value1",
        "new_customer": "true",
        "login_date": "2019-09-10T10:11:12Z"
    },
    "default_payment_method_id": null,
    "tax_registration_id": null
}
  1. Update the profile to add external vault details
curl -v --location --request PUT 'http://localhost:8080/v2/profiles/PROFILE_ID' \
--header 'Content-Type: application/json' \
--header 'x-profile-id: PROFILE_ID' \
--header 'Authorization: admin-api-key=ADMIN_API_KEY' \
--header 'x-merchant-id: MERCHANT_ID' \
--header 'x-tenant: public' \
--data-raw '{
    "profile_name": "Update",
    "return_url": "https://google.com/success",
    "enable_payment_response_hash": true,
    "redirect_to_merchant_with_http_post": false,
    "webhook_details": {
        "webhook_version": "1.0.1",
        "webhook_username": "ekart_retail",
        "webhook_password": "password_ekart@123",
        "webhook_url": "https://webhook.site",
        "payment_created_enabled": true,
        "payment_succeeded_enabled": true,
        "payment_failed_enabled": true
    },
    "metadata": null,
    "order_fulfillment_time": 900,
    "order_fulfillment_time_origin": "create",
    "applepay_verified_domains": null,
    "session_expiry": 900,
    "payment_link_config": null,
    "authentication_connector_details": null,
    "use_billing_as_payment_method_billing": true,
    "collect_shipping_details_from_wallet_connector_if_required": false,
    "collect_billing_details_from_wallet_connector_if_required": false,
    "always_collect_shipping_details_from_wallet_connector": false,
    "always_collect_billing_details_from_wallet_connector": false,
    "is_connector_agnostic_mit_enabled": false,
    "payout_link_config": null,
    "outgoing_webhook_custom_http_headers": null,
    "is_external_vault_enabled": true,
    "external_vault_connector_details": {
        
        "vault_connector_id": "MERCHANT_CONNECTOR_ACCOUNT",
        "vault_sdk": "vgs_sdk"
    }
}'

Response

{
    "merchant_id": "{MERCHANT_ID}",
    "id": "PROFILE_ID",
    "profile_name": "Update",
    "return_url": "https://google.com/success",
    "enable_payment_response_hash": true,
    "payment_response_hash_key": "doVXhW8TEtgpZNZgrytLAnIuegoyApXlKwnXMM7nIe3tWKbRwlZ14CiNWRaThnQX",
    "redirect_to_merchant_with_http_post": false,
    "webhook_details": {
        "webhook_version": "1.0.1",
        "webhook_username": "ekart_retail",
        "webhook_password": "password_ekart@123",
        "webhook_url": "https://webhook.site",
        "payment_created_enabled": true,
        "payment_succeeded_enabled": true,
        "payment_failed_enabled": true,
        "payment_statuses_enabled": null,
        "refund_statuses_enabled": null,
        "payout_statuses_enabled": null
    },
    "metadata": null,
    "applepay_verified_domains": null,
    "session_expiry": 900,
    "payment_link_config": null,
    "authentication_connector_details": null,
    "use_billing_as_payment_method_billing": true,
    "extended_card_info_config": null,
    "collect_shipping_details_from_wallet_connector_if_required": false,
    "collect_billing_details_from_wallet_connector_if_required": false,
    "always_collect_shipping_details_from_wallet_connector": false,
    "always_collect_billing_details_from_wallet_connector": false,
    "is_connector_agnostic_mit_enabled": false,
    "payout_link_config": null,
    "outgoing_webhook_custom_http_headers": null,
    "order_fulfillment_time": 900,
    "order_fulfillment_time_origin": "create",
    "tax_connector_id": null,
    "is_tax_connector_enabled": false,
    "is_network_tokenization_enabled": false,
    "should_collect_cvv_during_payment": null,
    "is_click_to_pay_enabled": false,
    "authentication_product_ids": null,
    "card_testing_guard_config": {
        "card_ip_blocking_status": "disabled",
        "card_ip_blocking_threshold": 3,
        "guest_user_card_blocking_status": "disabled",
        "guest_user_card_blocking_threshold": 10,
        "customer_id_blocking_status": "disabled",
        "customer_id_blocking_threshold": 5,
        "card_testing_guard_expiry": 3600
    },
    "is_clear_pan_retries_enabled": false,
    "is_debit_routing_enabled": false,
    "merchant_business_country": null,
    "is_iframe_redirection_enabled": null,
    "is_external_vault_enabled": true,
    "external_vault_connector_details": {
        "vault_connector_id": "MERCHANT_CONNECTOR_ACCOUNT",
        "vault_sdk": "vgs_sdk"
    },
    "merchant_category_code": null,
    "merchant_country_code": null,
    "split_txns_enabled": "skip"
}
  1. Create a payment intent with card details using external vault
curl --location 'http://localhost:8080/v2/payments/create-intent' \
--header 'Content-Type: application/json' \
--header 'x-profile-id: PROFILE_ID' \
--header 'Authorization: api-key=API_KEY' \

--header 'x-tenant: public' \
--header 'api-key: API_KEY' \
--data-raw '{
    "amount_details": {
        "order_amount": 100,
        "currency": "USD"
    },
    "customer_id": "CUSTOMER_ID",
    "capture_method":"manual",
    "authentication_type": "no_three_ds",
    "shipping": {
        "address": {
            "first_name": "John",
            "last_name": "Dough",
            "city": "Karwar",
            "zip": "581301",
            "state": "Karnataka",
            "country": "NL"
        },
        "email": "[email protected]"
    },
    "metadata":{
        "udf":"test"
    },
    "merchant_reference_id":"NOPA",
    "billing": {
        "address": {
            "city": "test",
            "country": "NL",
            "line1": "here is some \n there is some \n none is some? \n ",
            "line2": "there",
            "line3": "anywhere",
            "zip": "560095",
            "state": "SE",
            "first_name": "Sakil",
            "last_name": "Mostak"
        },
        "phone": {
            "number": "1234567890",
            "country_code": "+1"
        },
        "email": "[email protected]"
    }
}'

Response

{
    "id": "12345_pay_019914bad4b97b51a5784378d30b65e2",
    "status": "requires_payment_method",
    "amount_details": {
        "order_amount": 100,
        "currency": "USD",
        "shipping_cost": null,
        "order_tax_amount": null,
        "external_tax_calculation": "skip",
        "surcharge_calculation": "skip",
        "surcharge_amount": null,
        "tax_on_surcharge": null
    },
    "client_secret": "cs_019914bad58a7d419202971c85f52e78",
    "profile_id": "pro_zxVxleDz6pBK70pPhvHw",
    "merchant_reference_id": "NOPA",
    "routing_algorithm_id": null,
    "capture_method": "manual",
    "authentication_type": "no_three_ds",
    "billing": {
        "address": {
            "city": "test",
            "country": "NL",
            "line1": "here is some \n there is some \n none is some? \n ",
            "line2": "there",
            "line3": "anywhere",
            "zip": "560095",
            "state": "SE",
            "first_name": "Sakil",
            "last_name": "Mostak",
            "origin_zip": null
        },
        "phone": {
            "number": "1234567890",
            "country_code": "+1"
        },
        "email": "[email protected]"
    },
    "shipping": {
        "address": {
            "city": "Karwar",
            "country": "NL",
            "line1": null,
            "line2": null,
            "line3": null,
            "zip": "581301",
            "state": "Karnataka",
            "first_name": "John",
            "last_name": "Dough",
            "origin_zip": null
        },
        "phone": null,
        "email": "[email protected]"
    },
    "customer_id": "CUSTOMER_ID",
    "customer_present": "present",
    "description": null,
    "return_url": null,
    "setup_future_usage": "on_session",
    "apply_mit_exemption": "Skip",
    "statement_descriptor": null,
    "order_details": null,
    "allowed_payment_method_types": null,
    "metadata": {
        "udf": "test"
    },
    "connector_metadata": null,
    "feature_metadata": null,
    "payment_link_enabled": "Skip",
    "payment_link_config": null,
    "request_incremental_authorization": "false",
    "split_txns_enabled": "skip",
    "expires_on": "2025-09-04T12:51:52.734Z",
    "frm_metadata": null,
    "request_external_three_ds_authentication": "Skip",
    "payment_type": "normal"
}
  1. Confirm the payment intent using card details and vault data
curl --location 'http://localhost:8080/v2/payments/12345_pay_019914bad4b97b51a5784378d30b65e2/confirm-intent/external-vault-proxy' \
--header 'x-client-secret: CLIENT_SECRET' \
--header 'x-profile-id: PROFILE_ID' \
--header 'Authorization: api-key=API_KEY' \
--header 'Content-Type: application/json' \
--header 'api-key: API_KEY' \
--data '{
  "payment_method_type": "card",
  "payment_method_subtype": "debit",
  "payment_method_data": {
    "vault_data_card": {
      "card_number": "4166679492386746",
      "card_exp_month": "03",
      "card_exp_year": "2030",
      "card_cvc": "tok_sandbox_hmUN1L4M6ds1GQG62QmT8T",
      "bin_number": "42424",
      "last_four": "4242"
    }
  }
}'

Response

{
    "id": "12345_pay_019914bad4b97b51a5784378d30b65e2",
    "status": "succeeded",
    "amount": {
        "order_amount": 100,
        "currency": "USD",
        "shipping_cost": null,
        "order_tax_amount": null,
        "external_tax_calculation": "skip",
        "surcharge_calculation": "skip",
        "surcharge_amount": null,
        "tax_on_surcharge": null,
        "net_amount": 100,
        "amount_to_capture": null,
        "amount_capturable": 0,
        "amount_captured": 100
    },
    "customer_id": "CUSTOMER_ID",
    "connector": "adyen",
    "created": "2025-09-04T12:36:52.734Z",
    "payment_method_data": {
        "billing": null
    },
    "payment_method_type": "card",
    "payment_method_subtype": "credit",
    "connector_transaction_id": "Z2FDRSJ53HKV5CV5",
    "connector_reference_id": "NOPA",
    "merchant_connector_id": "mca_DJWBJR6rTI5PdoJBWhov",
    "browser_info": null,
    "error": {
        "code": "CONNECTOR_ERROR",
        "message": "Failed to deserialize connector response",
        "unified_code": null,
        "unified_message": null,
        "network_advice_code": null,
        "network_decline_code": null,
        "network_error_message": null
    },
    "shipping": null,
    "billing": null,
    "attempts": null,
    "connector_token_details": null,
    "payment_method_id": null,
    "next_action": null,
    "return_url": "https://google.com/success",
    "authentication_type": "no_three_ds",
    "authentication_type_applied": "no_three_ds",
    "is_iframe_redirection_enabled": null,
    "merchant_reference_id": "NOPA",
    "raw_connector_response": null,
    "feature_metadata": null
}

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

@su-shivanshmathur su-shivanshmathur requested a review from a team as a code owner September 8, 2025 20:45
Copy link

semanticdiff-com bot commented Sep 8, 2025

Review changes with  SemanticDiff

Changed Files
File Status
  crates/injector/src/types.rs  13% smaller
  crates/injector/src/injector.rs  11% smaller
  crates/injector/src/consts.rs  0% smaller
  crates/injector/src/lib.rs  0% smaller
  crates/injector/src/vault_metadata.rs  0% smaller

@su-shivanshmathur su-shivanshmathur linked an issue Sep 8, 2025 that may be closed by this pull request
2 tasks
Comment on lines 109 to 112
let cert = reqwest::Certificate::from_pem(pem.as_bytes()).map_err(|e| {
logger::error!("Failed to parse CA certificate PEM block: {}", e);
error_stack::Report::new(InjectorError::HttpRequestFailed)
})?;
Copy link
Contributor

Choose a reason for hiding this comment

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

Suggested change
let cert = reqwest::Certificate::from_pem(pem.as_bytes()).map_err(|e| {
logger::error!("Failed to parse CA certificate PEM block: {}", e);
error_stack::Report::new(InjectorError::HttpRequestFailed)
})?;
let cert = reqwest::Certificate::from_pem(pem.as_bytes()).change_context(error_stack::Report::new(InjectorError::HttpRequestFailed))
.inspect(|e| logger::error!("Failed to parse CA certificate PEM block: {}", e);)?;

.build()
.change_context(HttpClientError::ClientConstructionFailed)
.attach_printable("Failed to construct client with CA certificate");
return client_builder.use_rustls_tls().build().map_err(|e| {
Copy link
Contributor

Choose a reason for hiding this comment

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

same here

.attach_printable(
"Failed to construct client with certificate and certificate key",
);
.map_err(|e| {
Copy link
Contributor

Choose a reason for hiding this comment

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

change_context

proxy_config: &Proxy,
) -> error_stack::Result<reqwest::Client, InjectorError> {
let client_builder = get_client_builder(proxy_config)?;
client_builder.build().map_err(|e| {
Copy link
Contributor

Choose a reason for hiding this comment

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

change_context

@@ -561,66 +656,61 @@ pub mod core {
"Certificate configuration applied"
);

let request = request_builder.build();
let mut request = request_builder.build();
Copy link
Contributor

Choose a reason for hiding this comment

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

instead of building a mutable request, populate all required fields in builder itself and call .build() at the end

None
} else {
let mut headers_map = HashMap::new();
for (name, value) in header_map.iter() {
Copy link
Contributor

Choose a reason for hiding this comment

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

use iter().map()

pub max_response_size: Option<usize>,
}
/// External vault metadata processing module
pub mod vault_metadata {
Copy link
Contributor

Choose a reason for hiding this comment

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

modules can be a separate files

hrithikesh026
hrithikesh026 previously approved these changes Sep 9, 2025
hrithikesh026
hrithikesh026 previously approved these changes Sep 9, 2025
Comment on lines 10 to 11
const BASE64_ENGINE: base64::engine::GeneralPurpose = base64::engine::general_purpose::STANDARD;
pub const EXTERNAL_VAULT_METADATA_HEADER: &str = "x-external-vault-metadata";
Copy link
Contributor

Choose a reason for hiding this comment

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

nit: move them to a common consts file

.attach_printable(
"Failed to construct client with certificate and certificate key",
);
.change_context(InjectorError::HttpRequestFailed)
Copy link
Contributor

Choose a reason for hiding this comment

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

can we unify the client builder to remove early returns?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

based on the condition only building the builder, otherwise need to create a mutable reference to the builder

hrithikesh026
hrithikesh026 previously approved these changes Sep 10, 2025
Sakilmostak
Sakilmostak previously approved these changes Sep 10, 2025
@hyperswitch-bot hyperswitch-bot bot dismissed stale reviews from Sakilmostak and hrithikesh026 via 73b0e20 September 10, 2025 12:35
@likhinbopanna likhinbopanna added this pull request to the merge queue Sep 11, 2025
Merged via the queue into main with commit fabe82d Sep 11, 2025
33 of 37 checks passed
@likhinbopanna likhinbopanna deleted the injector_changes branch September 11, 2025 12:12
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

[FEATURE] Payments V2 supporting External vault
4 participants