Skip to content

Conversation

@Saptak88
Copy link
Contributor

@Saptak88 Saptak88 commented Oct 5, 2025

Type of Change

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

Description

  • Modified response handling logic to only populate amount_captured in router_data when payment status is Charged.
  • Removed the integrity check error that was preventing overpaid payments from being processed correctly.
  • The PaymentsSyncData::get_captured_amount method was ignoring the amount_captured parameter and only consulting stored payment data and getting total_amount. To fix this added .or(amount_captured.map(MinorUnit::new)) to the chain in PaymentsSyncData::get_captured_amount, ensuring the method prioritizes amount_captured from router_data similar to PaymentsAuthorizeData before consulting payment_data for total_amount.

Additional Changes

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

Motivation and Context

  • Previously, amount_captured was being set from the price_amount field for all payment statuses, including incomplete payments like requires_customer_action
  • Cryptopay allows customers to overpay, but the integrity check was throwing errors when captured_amount > total_capturable_amount and is_overcapture_enabled was false

How did you test it?

Create Payment
{
    "amount": 15,
    "currency": "USD",
    "confirm": true,
    "email": "[email protected]",
    "return_url": "https://google.com",
    "payment_method": "crypto",
    "payment_method_type": "crypto_currency",
    "payment_experience": "redirect_to_url",
    "capture_method": "automatic",
    "payment_method_data": {
        "crypto": {
            "pay_currency": "LTC"
        }
    }
}

Response

{
    "payment_id": "pay_nmtnfFNgKIwgtmwwwfeZ",
    "merchant_id": "merchant_1759732916",
    "status": "requires_customer_action",
    "amount": 15,
    "net_amount": 15,
    "shipping_cost": null,
    "amount_capturable": 15,
    "amount_received": null,
    "connector": "cryptopay",
    "client_secret": "pay_nmtnfFNgKIwgtmwwwfeZ_secret_6Ga6ekLlDTUcJVKLE9xd",
    "created": "2025-10-06T06:46:16.209Z",
    "currency": "USD",
    "customer_id": null,
    "customer": {
        "id": null,
        "name": null,
        "email": "[email protected]",
        "phone": null,
        "phone_country_code": null
    },
    "description": null,
    "refunds": null,
    "disputes": null,
    "mandate_id": null,
    "mandate_data": null,
    "setup_future_usage": null,
    "off_session": null,
    "capture_on": null,
    "capture_method": "automatic",
    "payment_method": "crypto",
    "payment_method_data": {
        "crypto": {
            "pay_currency": "LTC",
            "network": null
        },
        "billing": null
    },
    "payment_token": null,
    "shipping": null,
    "billing": null,
    "order_details": null,
    "email": null,
    "name": null,
    "phone": null,
    "return_url": "https://google.com/",
    "authentication_type": "no_three_ds",
    "statement_descriptor_name": null,
    "statement_descriptor_suffix": null,
    "next_action": {
        "type": "redirect_to_url",
        "redirect_to_url": "http://localhost:8080/payments/redirect/pay_nmtnfFNgKIwgtmwwwfeZ/merchant_1759732916/pay_nmtnfFNgKIwgtmwwwfeZ_1"
    },
    "cancellation_reason": null,
    "error_code": null,
    "error_message": null,
    "unified_code": null,
    "unified_message": null,
    "payment_experience": "redirect_to_url",
    "payment_method_type": "crypto_currency",
    "connector_label": null,
    "business_country": null,
    "business_label": "default",
    "business_sub_label": null,
    "allowed_payment_method_types": null,
    "ephemeral_key": null,
    "manual_retry_allowed": null,
    "connector_transaction_id": "782f2938-c41d-4be2-b93e-c22709654054",
    "frm_message": null,
    "metadata": null,
    "connector_metadata": null,
    "feature_metadata": {
        "redirect_response": null,
        "search_tags": null,
        "apple_pay_recurring_details": null,
        "gateway_system": "direct"
    },
    "reference_id": "pay_nmtnfFNgKIwgtmwwwfeZ_1",
    "payment_link": null,
    "profile_id": "pro_idiFBCtfW7ACI2qZSLdk",
    "surcharge_details": null,
    "attempt_count": 1,
    "merchant_decision": null,
    "merchant_connector_id": "mca_LB9MXkHZW8HRFzhiyJvY",
    "incremental_authorization_allowed": false,
    "authorization_count": null,
    "incremental_authorizations": null,
    "external_authentication_details": null,
    "external_3ds_authentication_attempted": false,
    "expires_on": "2025-10-06T07:01:16.209Z",
    "fingerprint": null,
    "browser_info": null,
    "payment_channel": null,
    "payment_method_id": null,
    "network_transaction_id": null,
    "payment_method_status": null,
    "updated": "2025-10-06T06:46:16.598Z",
    "split_payments": null,
    "frm_metadata": null,
    "extended_authorization_applied": null,
    "request_extended_authorization": null,
    "capture_before": null,
    "merchant_order_reference_id": null,
    "order_tax_amount": null,
    "connector_mandate_id": null,
    "card_discovery": null,
    "force_3ds_challenge": false,
    "force_3ds_challenge_trigger": false,
    "issuer_error_code": null,
    "issuer_error_message": null,
    "is_iframe_redirection_enabled": null,
    "whole_connector_response": null,
    "enable_partial_authorization": null,
    "enable_overcapture": null,
    "is_overcapture_enabled": null,
    "network_details": null,
    "is_stored_credential": null,
    "mit_category": null
}
Underpaid Payment Sync

Response

{
    "payment_id": "pay_AQ3kBO4NEV65g4nzsI5H",
    "merchant_id": "merchant_1759732916",
    "status": "partially_captured",
    "amount": 15,
    "net_amount": 15,
    "shipping_cost": null,
    "amount_capturable": 0,
    "amount_received": 12,
    "connector": "cryptopay",
    "client_secret": "pay_AQ3kBO4NEV65g4nzsI5H_secret_ogakUxfaNRXMgwTm2Cx2",
    "created": "2025-10-06T10:31:46.564Z",
    "currency": "USD",
    "customer_id": null,
    "customer": {
        "id": null,
        "name": null,
        "email": "[email protected]",
        "phone": null,
        "phone_country_code": null
    },
    "description": null,
    "refunds": null,
    "disputes": null,
    "attempts": [
        {
            "attempt_id": "pay_AQ3kBO4NEV65g4nzsI5H_1",
            "status": "partial_charged",
            "amount": 15,
            "order_tax_amount": null,
            "currency": "USD",
            "connector": "cryptopay",
            "error_message": null,
            "payment_method": "crypto",
            "connector_transaction_id": "8157c59c-7ef1-4520-adc0-ff505d67c4c2",
            "capture_method": "automatic",
            "authentication_type": "no_three_ds",
            "created_at": "2025-10-06T10:31:46.567Z",
            "modified_at": "2025-10-06T10:41:51.594Z",
            "cancellation_reason": null,
            "mandate_id": null,
            "error_code": null,
            "payment_token": null,
            "connector_metadata": null,
            "payment_experience": "redirect_to_url",
            "payment_method_type": "crypto_currency",
            "reference_id": "pay_AQ3kBO4NEV65g4nzsI5H_1",
            "unified_code": null,
            "unified_message": null,
            "client_source": null,
            "client_version": null
        }
    ],
    "mandate_id": null,
    "mandate_data": null,
    "setup_future_usage": null,
    "off_session": null,
    "capture_on": null,
    "capture_method": "automatic",
    "payment_method": "crypto",
    "payment_method_data": {
        "crypto": {
            "pay_currency": "LTC",
            "network": null
        },
        "billing": null
    },
    "payment_token": null,
    "shipping": null,
    "billing": null,
    "order_details": null,
    "email": null,
    "name": null,
    "phone": null,
    "return_url": "https://google.com/",
    "authentication_type": "no_three_ds",
    "statement_descriptor_name": null,
    "statement_descriptor_suffix": null,
    "next_action": null,
    "cancellation_reason": null,
    "error_code": null,
    "error_message": null,
    "unified_code": null,
    "unified_message": null,
    "payment_experience": "redirect_to_url",
    "payment_method_type": "crypto_currency",
    "connector_label": null,
    "business_country": null,
    "business_label": "default",
    "business_sub_label": null,
    "allowed_payment_method_types": null,
    "ephemeral_key": null,
    "manual_retry_allowed": null,
    "connector_transaction_id": "8157c59c-7ef1-4520-adc0-ff505d67c4c2",
    "frm_message": null,
    "metadata": null,
    "connector_metadata": null,
    "feature_metadata": {
        "redirect_response": null,
        "search_tags": null,
        "apple_pay_recurring_details": null,
        "gateway_system": "direct"
    },
    "reference_id": "pay_AQ3kBO4NEV65g4nzsI5H_1",
    "payment_link": null,
    "profile_id": "pro_idiFBCtfW7ACI2qZSLdk",
    "surcharge_details": null,
    "attempt_count": 1,
    "merchant_decision": null,
    "merchant_connector_id": "mca_LB9MXkHZW8HRFzhiyJvY",
    "incremental_authorization_allowed": false,
    "authorization_count": null,
    "incremental_authorizations": null,
    "external_authentication_details": null,
    "external_3ds_authentication_attempted": false,
    "expires_on": "2025-10-06T10:46:46.564Z",
    "fingerprint": null,
    "browser_info": null,
    "payment_channel": null,
    "payment_method_id": null,
    "network_transaction_id": null,
    "payment_method_status": null,
    "updated": "2025-10-06T10:41:51.594Z",
    "split_payments": null,
    "frm_metadata": null,
    "extended_authorization_applied": null,
    "request_extended_authorization": null,
    "capture_before": null,
    "merchant_order_reference_id": null,
    "order_tax_amount": null,
    "connector_mandate_id": null,
    "card_discovery": null,
    "force_3ds_challenge": false,
    "force_3ds_challenge_trigger": false,
    "issuer_error_code": null,
    "issuer_error_message": null,
    "is_iframe_redirection_enabled": null,
    "whole_connector_response": null,
    "enable_partial_authorization": null,
    "enable_overcapture": null,
    "is_overcapture_enabled": null,
    "network_details": null,
    "is_stored_credential": null,
    "mit_category": null
}
Overpaid Payment sync

Response

{
    "payment_id": "pay_GDtiguqwSEiybP9S2Pgc",
    "merchant_id": "merchant_1759732916",
    "status": "succeeded",
    "amount": 15,
    "net_amount": 15,
    "shipping_cost": null,
    "amount_capturable": 0,
    "amount_received": 17,
    "connector": "cryptopay",
    "client_secret": "pay_GDtiguqwSEiybP9S2Pgc_secret_yVeHrITuZPa434ZYDMN4",
    "created": "2025-10-06T06:42:08.937Z",
    "currency": "USD",
    "customer_id": null,
    "customer": {
        "id": null,
        "name": null,
        "email": "[email protected]",
        "phone": null,
        "phone_country_code": null
    },
    "description": null,
    "refunds": null,
    "disputes": null,
    "attempts": [
        {
            "attempt_id": "pay_GDtiguqwSEiybP9S2Pgc_1",
            "status": "charged",
            "amount": 15,
            "order_tax_amount": null,
            "currency": "USD",
            "connector": "cryptopay",
            "error_message": null,
            "payment_method": "crypto",
            "connector_transaction_id": "98c30587-0544-4c2f-949e-923965773a87",
            "capture_method": "automatic",
            "authentication_type": "no_three_ds",
            "created_at": "2025-10-06T06:42:08.940Z",
            "modified_at": "2025-10-06T06:45:42.581Z",
            "cancellation_reason": null,
            "mandate_id": null,
            "error_code": null,
            "payment_token": null,
            "connector_metadata": null,
            "payment_experience": "redirect_to_url",
            "payment_method_type": "crypto_currency",
            "reference_id": "pay_GDtiguqwSEiybP9S2Pgc_1",
            "unified_code": null,
            "unified_message": null,
            "client_source": null,
            "client_version": null
        }
    ],
    "mandate_id": null,
    "mandate_data": null,
    "setup_future_usage": null,
    "off_session": null,
    "capture_on": null,
    "capture_method": "automatic",
    "payment_method": "crypto",
    "payment_method_data": {
        "crypto": {
            "pay_currency": "LTC",
            "network": null
        },
        "billing": null
    },
    "payment_token": null,
    "shipping": null,
    "billing": null,
    "order_details": null,
    "email": null,
    "name": null,
    "phone": null,
    "return_url": "https://google.com/",
    "authentication_type": "no_three_ds",
    "statement_descriptor_name": null,
    "statement_descriptor_suffix": null,
    "next_action": null,
    "cancellation_reason": null,
    "error_code": null,
    "error_message": null,
    "unified_code": null,
    "unified_message": null,
    "payment_experience": "redirect_to_url",
    "payment_method_type": "crypto_currency",
    "connector_label": null,
    "business_country": null,
    "business_label": "default",
    "business_sub_label": null,
    "allowed_payment_method_types": null,
    "ephemeral_key": null,
    "manual_retry_allowed": null,
    "connector_transaction_id": "98c30587-0544-4c2f-949e-923965773a87",
    "frm_message": null,
    "metadata": null,
    "connector_metadata": null,
    "feature_metadata": {
        "redirect_response": null,
        "search_tags": null,
        "apple_pay_recurring_details": null,
        "gateway_system": "direct"
    },
    "reference_id": "pay_GDtiguqwSEiybP9S2Pgc_1",
    "payment_link": null,
    "profile_id": "pro_idiFBCtfW7ACI2qZSLdk",
    "surcharge_details": null,
    "attempt_count": 1,
    "merchant_decision": null,
    "merchant_connector_id": "mca_LB9MXkHZW8HRFzhiyJvY",
    "incremental_authorization_allowed": false,
    "authorization_count": null,
    "incremental_authorizations": null,
    "external_authentication_details": null,
    "external_3ds_authentication_attempted": false,
    "expires_on": "2025-10-06T06:57:08.936Z",
    "fingerprint": null,
    "browser_info": null,
    "payment_channel": null,
    "payment_method_id": null,
    "network_transaction_id": null,
    "payment_method_status": null,
    "updated": "2025-10-06T06:45:42.581Z",
    "split_payments": null,
    "frm_metadata": null,
    "extended_authorization_applied": null,
    "request_extended_authorization": null,
    "capture_before": null,
    "merchant_order_reference_id": null,
    "order_tax_amount": null,
    "connector_mandate_id": null,
    "card_discovery": null,
    "force_3ds_challenge": false,
    "force_3ds_challenge_trigger": false,
    "issuer_error_code": null,
    "issuer_error_message": null,
    "is_iframe_redirection_enabled": null,
    "whole_connector_response": null,
    "enable_partial_authorization": null,
    "enable_overcapture": null,
    "is_overcapture_enabled": null,
    "network_details": null,
    "is_stored_credential": null,
    "mit_category": null
}
Exact amount paid Payment Sync

Response

{
    "payment_id": "pay_0yVxECTGSurN7u9hMe1j",
    "merchant_id": "merchant_1759732916",
    "status": "succeeded",
    "amount": 15,
    "net_amount": 15,
    "shipping_cost": null,
    "amount_capturable": 0,
    "amount_received": 15,
    "connector": "cryptopay",
    "client_secret": "pay_0yVxECTGSurN7u9hMe1j_secret_i3GfK1Km0iitrQx66IgF",
    "created": "2025-10-10T07:49:43.268Z",
    "currency": "USD",
    "customer_id": null,
    "customer": {
        "id": null,
        "name": null,
        "email": "[email protected]",
        "phone": null,
        "phone_country_code": null
    },
    "description": null,
    "refunds": null,
    "disputes": null,
    "attempts": [
        {
            "attempt_id": "pay_0yVxECTGSurN7u9hMe1j_1",
            "status": "charged",
            "amount": 15,
            "order_tax_amount": null,
            "currency": "USD",
            "connector": "cryptopay",
            "error_message": null,
            "payment_method": "crypto",
            "connector_transaction_id": "af24ef5c-f51c-43de-9c73-732ac3c4857d",
            "capture_method": "automatic",
            "authentication_type": "no_three_ds",
            "created_at": "2025-10-10T07:49:43.275Z",
            "modified_at": "2025-10-10T07:55:00.411Z",
            "cancellation_reason": null,
            "mandate_id": null,
            "error_code": null,
            "payment_token": null,
            "connector_metadata": null,
            "payment_experience": "redirect_to_url",
            "payment_method_type": "crypto_currency",
            "reference_id": "pay_0yVxECTGSurN7u9hMe1j_1",
            "unified_code": null,
            "unified_message": null,
            "client_source": null,
            "client_version": null
        }
    ],
    "mandate_id": null,
    "mandate_data": null,
    "setup_future_usage": null,
    "off_session": null,
    "capture_on": null,
    "capture_method": "automatic",
    "payment_method": "crypto",
    "payment_method_data": {
        "crypto": {
            "pay_currency": "LTC",
            "network": null
        },
        "billing": null
    },
    "payment_token": null,
    "shipping": null,
    "billing": null,
    "order_details": null,
    "email": null,
    "name": null,
    "phone": null,
    "return_url": "https://google.com/",
    "authentication_type": "no_three_ds",
    "statement_descriptor_name": null,
    "statement_descriptor_suffix": null,
    "next_action": null,
    "cancellation_reason": null,
    "error_code": null,
    "error_message": null,
    "unified_code": null,
    "unified_message": null,
    "payment_experience": "redirect_to_url",
    "payment_method_type": "crypto_currency",
    "connector_label": null,
    "business_country": null,
    "business_label": "default",
    "business_sub_label": null,
    "allowed_payment_method_types": null,
    "ephemeral_key": null,
    "manual_retry_allowed": null,
    "connector_transaction_id": "af24ef5c-f51c-43de-9c73-732ac3c4857d",
    "frm_message": null,
    "metadata": null,
    "connector_metadata": null,
    "feature_metadata": {
        "redirect_response": null,
        "search_tags": null,
        "apple_pay_recurring_details": null,
        "gateway_system": "direct"
    },
    "reference_id": "pay_0yVxECTGSurN7u9hMe1j_1",
    "payment_link": null,
    "profile_id": "pro_idiFBCtfW7ACI2qZSLdk",
    "surcharge_details": null,
    "attempt_count": 1,
    "merchant_decision": null,
    "merchant_connector_id": "mca_LB9MXkHZW8HRFzhiyJvY",
    "incremental_authorization_allowed": false,
    "authorization_count": null,
    "incremental_authorizations": null,
    "external_authentication_details": null,
    "external_3ds_authentication_attempted": false,
    "expires_on": "2025-10-10T08:04:43.267Z",
    "fingerprint": null,
    "browser_info": null,
    "payment_channel": null,
    "payment_method_id": null,
    "network_transaction_id": null,
    "payment_method_status": null,
    "updated": "2025-10-10T07:55:00.412Z",
    "split_payments": null,
    "frm_metadata": null,
    "extended_authorization_applied": null,
    "request_extended_authorization": null,
    "capture_before": null,
    "merchant_order_reference_id": null,
    "order_tax_amount": null,
    "connector_mandate_id": null,
    "card_discovery": null,
    "force_3ds_challenge": false,
    "force_3ds_challenge_trigger": false,
    "issuer_error_code": null,
    "issuer_error_message": null,
    "is_iframe_redirection_enabled": null,
    "whole_connector_response": null,
    "enable_partial_authorization": null,
    "enable_overcapture": null,
    "is_overcapture_enabled": null,
    "network_details": null,
    "is_stored_credential": null,
    "mit_category": 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

@Saptak88 Saptak88 requested a review from a team as a code owner October 5, 2025 17:48
@semanticdiff-com
Copy link

semanticdiff-com bot commented Oct 5, 2025

Review changes with  SemanticDiff

Changed Files
File Status
  crates/router/src/connector/utils.rs  29% smaller
  crates/hyperswitch_connectors/src/connectors/cryptopay/transformers.rs  1% smaller
  crates/router/src/types.rs  0% smaller

@Saptak88 Saptak88 self-assigned this Oct 6, 2025
@Saptak88 Saptak88 linked an issue Oct 6, 2025 that may be closed by this pull request
2 tasks
@Saptak88 Saptak88 requested a review from a team as a code owner October 6, 2025 10:46
@likhinbopanna likhinbopanna added this pull request to the merge queue Oct 10, 2025
Merged via the queue into main with commit a4bf608 Oct 10, 2025
36 of 40 checks passed
@likhinbopanna likhinbopanna deleted the cryptopay-response-amount branch October 10, 2025 08:50
chaitak-gorai pushed a commit that referenced this pull request Oct 16, 2025
drdholu pushed a commit to drdholu/hyperswitch that referenced this pull request Oct 30, 2025
aadityaguptaa pushed a commit that referenced this pull request Nov 10, 2025
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.

[BUG] amount_captured population logic in Cryptopay connector

6 participants