feat(injector): injector request formation changes#9306
Merged
likhinbopanna merged 20 commits intomainfrom Sep 11, 2025
Merged
Conversation
Changed Files
|
2 tasks
crates/injector/src/injector.rs
Outdated
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) | ||
| })?; |
Contributor
There was a problem hiding this comment.
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);)?; |
crates/injector/src/injector.rs
Outdated
| .build() | ||
| .change_context(HttpClientError::ClientConstructionFailed) | ||
| .attach_printable("Failed to construct client with CA certificate"); | ||
| return client_builder.use_rustls_tls().build().map_err(|e| { |
crates/injector/src/injector.rs
Outdated
| .attach_printable( | ||
| "Failed to construct client with certificate and certificate key", | ||
| ); | ||
| .map_err(|e| { |
crates/injector/src/injector.rs
Outdated
| proxy_config: &Proxy, | ||
| ) -> error_stack::Result<reqwest::Client, InjectorError> { | ||
| let client_builder = get_client_builder(proxy_config)?; | ||
| client_builder.build().map_err(|e| { |
crates/injector/src/injector.rs
Outdated
| ); | ||
|
|
||
| let request = request_builder.build(); | ||
| let mut request = request_builder.build(); |
Contributor
There was a problem hiding this comment.
instead of building a mutable request, populate all required fields in builder itself and call .build() at the end
crates/injector/src/types.rs
Outdated
| None | ||
| } else { | ||
| let mut headers_map = HashMap::new(); | ||
| for (name, value) in header_map.iter() { |
crates/injector/src/types.rs
Outdated
| pub max_response_size: Option<usize>, | ||
| } | ||
| /// External vault metadata processing module | ||
| pub mod vault_metadata { |
Contributor
There was a problem hiding this comment.
modules can be a separate files
hrithikesh026
previously approved these changes
Sep 9, 2025
hrithikesh026
previously approved these changes
Sep 9, 2025
Sakilmostak
reviewed
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"; |
Contributor
There was a problem hiding this comment.
nit: move them to a common consts file
| .attach_printable( | ||
| "Failed to construct client with certificate and certificate key", | ||
| ); | ||
| .change_context(InjectorError::HttpRequestFailed) |
Contributor
There was a problem hiding this comment.
can we unify the client builder to remove early returns?
Contributor
Author
There was a problem hiding this comment.
based on the condition only building the builder, otherwise need to create a mutable reference to the builder
hrithikesh026
previously approved these changes
Sep 10, 2025
Sakilmostak
previously approved these changes
Sep 10, 2025
73b0e20
Sakilmostak
approved these changes
Sep 10, 2025
hrithikesh026
approved these changes
Sep 11, 2025
pixincreate
added a commit
that referenced
this pull request
Sep 11, 2025
…ee-ds * 'main' of github.com:juspay/hyperswitch: feat(webhooks): Provide outgoing webhook support for revenue recovery (#9294) feat(connector): Add Peachpayments Template Code (#9363) feat(connector): [Paysafe] Implement card 3ds flow (#9305) feat(router): Add Connector changes for 3ds (v2) (#9117) feat(connector): [ADYEN] Add support to ideal Mandate Webhook (#9347) refactor(core): accept manual retry from profile (#9302) fix(nuvei): nuvei 3ds fix + psync fix (#9279) fix(connector): [checkout] Add US Support for Apple Pay and Google Pay + Enhanced Checkout Response Data (#9356) fix(router): adding connector_customer_id for external vault proxy (#9263) feat(core): Add first_name and last_name as Secret<String> Types. (#9326) feat(injector): injector request formation changes (#9306) fix(revenue-recovery): Update Redis TTL for customer locks after token selection (#9282) chore(version): 2025.09.11.0 refactor(connector): [Paysafe] fix wasm (#9349) refactor(connector): rename RevenueRecoveryRecordBack as InvoiceRecordBack (#9321) feat(connector): [checkout] add support for MOTO payments (#9327) feat(connector): enhance ACI connector with comprehensive 3DS support - DRAFT (#8986) feat(core): [Retry] MIT Retries (#8628)
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Type of Change
Description
Request creation changes for injector to be used
InjectorRequeststruct creation.Also change the response type
Additional Changes
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
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" }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 }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 }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" }Response
{ "id": "12345_cus_01993844c6c47dc39f528073a92ad278", "merchant_reference_id": "customer_1757585655", "connector_customer_ids": null, "name": "John Doe", "email": "guest@example.com", "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 }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" }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": "guest@example.com" }, "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": "example@example.com" }, "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" }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
cargo +nightly fmt --allcargo clippy