Skip to content

Conversation

Debarshi-Gupta
Copy link
Contributor

@Debarshi-Gupta Debarshi-Gupta commented Feb 7, 2025

Type of Change

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

Description

Previously, we were accepting void_reason as string, but since Nmi accepts specific values for void_reason, those values have been added to an enum.

Additional Changes

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

Motivation and Context

Issue Link: #7222

How did you test it?

Postman Tests

1. Create Payment

-Request

curl --location 'localhost:8080/payments' \
--header 'Content-Type: application/json' \
--header 'Accept: application/json' \
--header 'api-key: dev_XtFublrRhWIHc7iuKjgQtABwUOjTGaEujjdXNQLUs8cI4xaPZiS4YOAO6gMjQ8fK' \
--data-raw '{
    "amount": 3000,
    "currency": "USD",
    "confirm": true,
    "capture_method": "manual",
    "capture_on": "2022-09-10T10:11:12Z",
    "amount_to_capture": 3000,
    "customer_id": "StripeCustomer",
    "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://duck.com",
    "payment_method": "card",
    "payment_method_type": "credit",
    "payment_method_data": {
        "card": {
            "card_number": "4100000000000100",
            "card_exp_month": "10",
            "card_exp_year": "25",
            "card_holder_name": "joseph Doe",
            "card_cvc": "410"
        }
    },
    "billing": {
        "address": {
            "line1": "1467",
            "line2": "Harrison Street",
            "line3": "Harrison Street",
            "city": "San Fransico",
            "state": "California",
            "zip": "94122",
            "country": "US",
            "first_name": "someone",
            "last_name": "happy"
        }
    },
    "shipping": {
        "address": {
            "line1": "1467",
            "line2": "Harrison Street",
            "line3": "Harrison Street",
            "city": "San Fransico",
            "state": "California",
            "zip": "94122",
            "country": "US",
            "first_name": "someone",
            "last_name": "happy"
        }
    },
    "statement_descriptor_name": "joseph",
    "statement_descriptor_suffix": "JS",
    "metadata": {
        "udf1": "value1",
        "new_customer": "true",
        "login_date": "2019-09-10T10:11:12Z"
    }
}'

-Response

{
    "payment_id": "pay_uPyEZvr3oVAvYsVvZ0jN",
    "merchant_id": "postman_merchant_GHAction_dd590ad1-bf12-47a6-bde5-586f878b3ba1",
    "status": "processing",
    "amount": 3000,
    "net_amount": 3000,
    "shipping_cost": null,
    "amount_capturable": 3000,
    "amount_received": null,
    "connector": "nmi",
    "client_secret": "pay_uPyEZvr3oVAvYsVvZ0jN_secret_9j87TpZlvvlMpSC5eFDq",
    "created": "2025-02-10T04:51:56.569Z",
    "currency": "USD",
    "customer_id": "StripeCustomer",
    "customer": {
        "id": "StripeCustomer",
        "name": "John Doe",
        "email": "[email protected]",
        "phone": "999999999",
        "phone_country_code": "+65"
    },
    "description": "Its my first payment request",
    "refunds": null,
    "disputes": null,
    "mandate_id": null,
    "mandate_data": null,
    "setup_future_usage": null,
    "off_session": null,
    "capture_on": null,
    "capture_method": "manual",
    "payment_method": "card",
    "payment_method_data": {
        "card": {
            "last4": "0100",
            "card_type": null,
            "card_network": null,
            "card_issuer": null,
            "card_issuing_country": null,
            "card_isin": "410000",
            "card_extended_bin": null,
            "card_exp_month": "10",
            "card_exp_year": "25",
            "card_holder_name": "joseph Doe",
            "payment_checks": null,
            "authentication_data": null
        },
        "billing": null
    },
    "payment_token": "token_hdl9v3A1JuIvmH2tO02R",
    "shipping": {
        "address": {
            "city": "San Fransico",
            "country": "US",
            "line1": "1467",
            "line2": "Harrison Street",
            "line3": "Harrison Street",
            "zip": "94122",
            "state": "California",
            "first_name": "someone",
            "last_name": "happy"
        },
        "phone": null,
        "email": null
    },
    "billing": {
        "address": {
            "city": "San Fransico",
            "country": "US",
            "line1": "1467",
            "line2": "Harrison Street",
            "line3": "Harrison Street",
            "zip": "94122",
            "state": "California",
            "first_name": "someone",
            "last_name": "happy"
        },
        "phone": null,
        "email": null
    },
    "order_details": null,
    "email": "[email protected]",
    "name": "John Doe",
    "phone": "999999999",
    "return_url": "https://duck.com/",
    "authentication_type": "no_three_ds",
    "statement_descriptor_name": "joseph",
    "statement_descriptor_suffix": "JS",
    "next_action": null,
    "cancellation_reason": null,
    "error_code": null,
    "error_message": null,
    "unified_code": null,
    "unified_message": null,
    "payment_experience": null,
    "payment_method_type": "credit",
    "connector_label": null,
    "business_country": null,
    "business_label": "default",
    "business_sub_label": null,
    "allowed_payment_method_types": null,
    "ephemeral_key": {
        "customer_id": "StripeCustomer",
        "created_at": 1739163116,
        "expires": 1739166716,
        "secret": "epk_515db508176144d8a80582b802c6da31"
    },
    "manual_retry_allowed": false,
    "connector_transaction_id": "10396960775",
    "frm_message": null,
    "metadata": {
        "udf1": "value1",
        "login_date": "2019-09-10T10:11:12Z",
        "new_customer": "true"
    },
    "connector_metadata": null,
    "feature_metadata": null,
    "reference_id": "pay_uPyEZvr3oVAvYsVvZ0jN_1",
    "payment_link": null,
    "profile_id": "pro_qonNkZSegDkXycMtUZsb",
    "surcharge_details": null,
    "attempt_count": 1,
    "merchant_decision": null,
    "merchant_connector_id": "mca_EtKPhtxukFIa5pSEBtsO",
    "incremental_authorization_allowed": null,
    "authorization_count": null,
    "incremental_authorizations": null,
    "external_authentication_details": null,
    "external_3ds_authentication_attempted": false,
    "expires_on": "2025-02-10T05:06:56.569Z",
    "fingerprint": null,
    "browser_info": null,
    "payment_method_id": null,
    "payment_method_status": null,
    "updated": "2025-02-10T04:51:59.965Z",
    "split_payments": null,
    "frm_metadata": null,
    "merchant_order_reference_id": null,
    "order_tax_amount": null,
    "connector_mandate_id": null
}

2. Psync

-Request

curl --location 'localhost:8080/payments/pay_uPyEZvr3oVAvYsVvZ0jN?force_sync=true' \
--header 'Accept: application/json' \
--header 'api-key: dev_XtFublrRhWIHc7iuKjgQtABwUOjTGaEujjdXNQLUs8cI4xaPZiS4YOAO6gMjQ8fK'

-Response

{
    "payment_id": "pay_uPyEZvr3oVAvYsVvZ0jN",
    "merchant_id": "postman_merchant_GHAction_dd590ad1-bf12-47a6-bde5-586f878b3ba1",
    "status": "requires_capture",
    "amount": 3000,
    "net_amount": 3000,
    "shipping_cost": null,
    "amount_capturable": 3000,
    "amount_received": null,
    "connector": "nmi",
    "client_secret": "pay_uPyEZvr3oVAvYsVvZ0jN_secret_9j87TpZlvvlMpSC5eFDq",
    "created": "2025-02-10T04:51:56.569Z",
    "currency": "USD",
    "customer_id": "StripeCustomer",
    "customer": {
        "id": "StripeCustomer",
        "name": "John Doe",
        "email": "[email protected]",
        "phone": "999999999",
        "phone_country_code": "+65"
    },
    "description": "Its my first payment request",
    "refunds": null,
    "disputes": null,
    "mandate_id": null,
    "mandate_data": null,
    "setup_future_usage": null,
    "off_session": null,
    "capture_on": null,
    "capture_method": "manual",
    "payment_method": "card",
    "payment_method_data": {
        "card": {
            "last4": "0100",
            "card_type": null,
            "card_network": null,
            "card_issuer": null,
            "card_issuing_country": null,
            "card_isin": "410000",
            "card_extended_bin": null,
            "card_exp_month": "10",
            "card_exp_year": "25",
            "card_holder_name": "joseph Doe",
            "payment_checks": null,
            "authentication_data": null
        },
        "billing": null
    },
    "payment_token": "token_hdl9v3A1JuIvmH2tO02R",
    "shipping": {
        "address": {
            "city": "San Fransico",
            "country": "US",
            "line1": "1467",
            "line2": "Harrison Street",
            "line3": "Harrison Street",
            "zip": "94122",
            "state": "California",
            "first_name": "someone",
            "last_name": "happy"
        },
        "phone": null,
        "email": null
    },
    "billing": {
        "address": {
            "city": "San Fransico",
            "country": "US",
            "line1": "1467",
            "line2": "Harrison Street",
            "line3": "Harrison Street",
            "zip": "94122",
            "state": "California",
            "first_name": "someone",
            "last_name": "happy"
        },
        "phone": null,
        "email": null
    },
    "order_details": null,
    "email": "[email protected]",
    "name": "John Doe",
    "phone": "999999999",
    "return_url": "https://duck.com/",
    "authentication_type": "no_three_ds",
    "statement_descriptor_name": "joseph",
    "statement_descriptor_suffix": "JS",
    "next_action": null,
    "cancellation_reason": null,
    "error_code": null,
    "error_message": null,
    "unified_code": null,
    "unified_message": null,
    "payment_experience": null,
    "payment_method_type": "credit",
    "connector_label": null,
    "business_country": null,
    "business_label": "default",
    "business_sub_label": null,
    "allowed_payment_method_types": null,
    "ephemeral_key": null,
    "manual_retry_allowed": false,
    "connector_transaction_id": "10396960775",
    "frm_message": null,
    "metadata": {
        "udf1": "value1",
        "login_date": "2019-09-10T10:11:12Z",
        "new_customer": "true"
    },
    "connector_metadata": null,
    "feature_metadata": null,
    "reference_id": "pay_uPyEZvr3oVAvYsVvZ0jN_1",
    "payment_link": null,
    "profile_id": "pro_qonNkZSegDkXycMtUZsb",
    "surcharge_details": null,
    "attempt_count": 1,
    "merchant_decision": null,
    "merchant_connector_id": "mca_EtKPhtxukFIa5pSEBtsO",
    "incremental_authorization_allowed": null,
    "authorization_count": null,
    "incremental_authorizations": null,
    "external_authentication_details": null,
    "external_3ds_authentication_attempted": false,
    "expires_on": "2025-02-10T05:06:56.569Z",
    "fingerprint": null,
    "browser_info": null,
    "payment_method_id": null,
    "payment_method_status": null,
    "updated": "2025-02-10T04:54:48.886Z",
    "split_payments": null,
    "frm_metadata": null,
    "merchant_order_reference_id": null,
    "order_tax_amount": null,
    "connector_mandate_id": null
}

3. Cancel (Invalid Cancellation Reason)

-Request

curl --location 'localhost:8080/payments/pay_uPyEZvr3oVAvYsVvZ0jN/cancel' \
--header 'Content-Type: application/json' \
--header 'Accept: application/json' \
--header 'api-key: dev_XtFublrRhWIHc7iuKjgQtABwUOjTGaEujjdXNQLUs8cI4xaPZiS4YOAO6gMjQ8fK' \
--data '{
    "cancellation_reason": "abcde"
}'

-Response

{
    "error": {
        "type": "invalid_request",
        "message": "Payment method type not supported",
        "code": "IR_19",
        "reason": "Json deserialise error: unknown variant `abcde` expected to be one of `fraud`, `user_cancel`, `icc_rejected`,  `icc_card_removed`, `icc_no_confirmation`, `pos_timeout`. This cancellation_reason is not supported by nmi"
    }
}

4. Cancel (Valid Cancellation Reason)

-Request

curl --location 'localhost:8080/payments/pay_uPyEZvr3oVAvYsVvZ0jN/cancel' \
--header 'Content-Type: application/json' \
--header 'Accept: application/json' \
--header 'api-key: dev_XtFublrRhWIHc7iuKjgQtABwUOjTGaEujjdXNQLUs8cI4xaPZiS4YOAO6gMjQ8fK' \
--data '{
    "cancellation_reason": "fraud"
}'

-Response

{
    "payment_id": "pay_uPyEZvr3oVAvYsVvZ0jN",
    "merchant_id": "postman_merchant_GHAction_dd590ad1-bf12-47a6-bde5-586f878b3ba1",
    "status": "processing",
    "amount": 3000,
    "net_amount": 3000,
    "shipping_cost": null,
    "amount_capturable": 0,
    "amount_received": null,
    "connector": "nmi",
    "client_secret": "pay_uPyEZvr3oVAvYsVvZ0jN_secret_9j87TpZlvvlMpSC5eFDq",
    "created": "2025-02-10T04:51:56.569Z",
    "currency": "USD",
    "customer_id": "StripeCustomer",
    "customer": {
        "id": "StripeCustomer",
        "name": "John Doe",
        "email": "[email protected]",
        "phone": "999999999",
        "phone_country_code": "+65"
    },
    "description": "Its my first payment request",
    "refunds": null,
    "disputes": null,
    "mandate_id": null,
    "mandate_data": null,
    "setup_future_usage": null,
    "off_session": null,
    "capture_on": null,
    "capture_method": "manual",
    "payment_method": "card",
    "payment_method_data": {
        "card": {
            "last4": "0100",
            "card_type": null,
            "card_network": null,
            "card_issuer": null,
            "card_issuing_country": null,
            "card_isin": "410000",
            "card_extended_bin": null,
            "card_exp_month": "10",
            "card_exp_year": "25",
            "card_holder_name": "joseph Doe",
            "payment_checks": null,
            "authentication_data": null
        },
        "billing": null
    },
    "payment_token": "token_hdl9v3A1JuIvmH2tO02R",
    "shipping": {
        "address": {
            "city": "San Fransico",
            "country": "US",
            "line1": "1467",
            "line2": "Harrison Street",
            "line3": "Harrison Street",
            "zip": "94122",
            "state": "California",
            "first_name": "someone",
            "last_name": "happy"
        },
        "phone": null,
        "email": null
    },
    "billing": {
        "address": {
            "city": "San Fransico",
            "country": "US",
            "line1": "1467",
            "line2": "Harrison Street",
            "line3": "Harrison Street",
            "zip": "94122",
            "state": "California",
            "first_name": "someone",
            "last_name": "happy"
        },
        "phone": null,
        "email": null
    },
    "order_details": null,
    "email": "[email protected]",
    "name": "John Doe",
    "phone": "999999999",
    "return_url": "https://duck.com/",
    "authentication_type": "no_three_ds",
    "statement_descriptor_name": "joseph",
    "statement_descriptor_suffix": "JS",
    "next_action": null,
    "cancellation_reason": "fraud",
    "error_code": null,
    "error_message": null,
    "unified_code": null,
    "unified_message": null,
    "payment_experience": null,
    "payment_method_type": "credit",
    "connector_label": null,
    "business_country": null,
    "business_label": "default",
    "business_sub_label": null,
    "allowed_payment_method_types": null,
    "ephemeral_key": null,
    "manual_retry_allowed": false,
    "connector_transaction_id": "10396960775",
    "frm_message": null,
    "metadata": {
        "udf1": "value1",
        "login_date": "2019-09-10T10:11:12Z",
        "new_customer": "true"
    },
    "connector_metadata": null,
    "feature_metadata": null,
    "reference_id": "pay_uPyEZvr3oVAvYsVvZ0jN_1",
    "payment_link": null,
    "profile_id": "pro_qonNkZSegDkXycMtUZsb",
    "surcharge_details": null,
    "attempt_count": 1,
    "merchant_decision": null,
    "merchant_connector_id": "mca_EtKPhtxukFIa5pSEBtsO",
    "incremental_authorization_allowed": null,
    "authorization_count": null,
    "incremental_authorizations": null,
    "external_authentication_details": null,
    "external_3ds_authentication_attempted": false,
    "expires_on": "2025-02-10T05:06:56.569Z",
    "fingerprint": null,
    "browser_info": null,
    "payment_method_id": null,
    "payment_method_status": null,
    "updated": "2025-02-10T04:58:20.070Z",
    "split_payments": null,
    "frm_metadata": null,
    "merchant_order_reference_id": null,
    "order_tax_amount": null,
    "connector_mandate_id": null
}

5. Psync

-Request

curl --location 'localhost:8080/payments/pay_uPyEZvr3oVAvYsVvZ0jN?force_sync=true' \
--header 'Accept: application/json' \
--header 'api-key: dev_XtFublrRhWIHc7iuKjgQtABwUOjTGaEujjdXNQLUs8cI4xaPZiS4YOAO6gMjQ8fK'

-Response

{
    "payment_id": "pay_uPyEZvr3oVAvYsVvZ0jN",
    "merchant_id": "postman_merchant_GHAction_dd590ad1-bf12-47a6-bde5-586f878b3ba1",
    "status": "cancelled",
    "amount": 3000,
    "net_amount": 3000,
    "shipping_cost": null,
    "amount_capturable": 0,
    "amount_received": null,
    "connector": "nmi",
    "client_secret": "pay_uPyEZvr3oVAvYsVvZ0jN_secret_9j87TpZlvvlMpSC5eFDq",
    "created": "2025-02-10T04:51:56.569Z",
    "currency": "USD",
    "customer_id": "StripeCustomer",
    "customer": {
        "id": "StripeCustomer",
        "name": "John Doe",
        "email": "[email protected]",
        "phone": "999999999",
        "phone_country_code": "+65"
    },
    "description": "Its my first payment request",
    "refunds": null,
    "disputes": null,
    "mandate_id": null,
    "mandate_data": null,
    "setup_future_usage": null,
    "off_session": null,
    "capture_on": null,
    "capture_method": "manual",
    "payment_method": "card",
    "payment_method_data": {
        "card": {
            "last4": "0100",
            "card_type": null,
            "card_network": null,
            "card_issuer": null,
            "card_issuing_country": null,
            "card_isin": "410000",
            "card_extended_bin": null,
            "card_exp_month": "10",
            "card_exp_year": "25",
            "card_holder_name": "joseph Doe",
            "payment_checks": null,
            "authentication_data": null
        },
        "billing": null
    },
    "payment_token": "token_hdl9v3A1JuIvmH2tO02R",
    "shipping": {
        "address": {
            "city": "San Fransico",
            "country": "US",
            "line1": "1467",
            "line2": "Harrison Street",
            "line3": "Harrison Street",
            "zip": "94122",
            "state": "California",
            "first_name": "someone",
            "last_name": "happy"
        },
        "phone": null,
        "email": null
    },
    "billing": {
        "address": {
            "city": "San Fransico",
            "country": "US",
            "line1": "1467",
            "line2": "Harrison Street",
            "line3": "Harrison Street",
            "zip": "94122",
            "state": "California",
            "first_name": "someone",
            "last_name": "happy"
        },
        "phone": null,
        "email": null
    },
    "order_details": null,
    "email": "[email protected]",
    "name": "John Doe",
    "phone": "999999999",
    "return_url": "https://duck.com/",
    "authentication_type": "no_three_ds",
    "statement_descriptor_name": "joseph",
    "statement_descriptor_suffix": "JS",
    "next_action": null,
    "cancellation_reason": "fraud",
    "error_code": null,
    "error_message": null,
    "unified_code": null,
    "unified_message": null,
    "payment_experience": null,
    "payment_method_type": "credit",
    "connector_label": null,
    "business_country": null,
    "business_label": "default",
    "business_sub_label": null,
    "allowed_payment_method_types": null,
    "ephemeral_key": null,
    "manual_retry_allowed": false,
    "connector_transaction_id": "10396960775",
    "frm_message": null,
    "metadata": {
        "udf1": "value1",
        "login_date": "2019-09-10T10:11:12Z",
        "new_customer": "true"
    },
    "connector_metadata": null,
    "feature_metadata": null,
    "reference_id": "pay_uPyEZvr3oVAvYsVvZ0jN_1",
    "payment_link": null,
    "profile_id": "pro_qonNkZSegDkXycMtUZsb",
    "surcharge_details": null,
    "attempt_count": 1,
    "merchant_decision": null,
    "merchant_connector_id": "mca_EtKPhtxukFIa5pSEBtsO",
    "incremental_authorization_allowed": null,
    "authorization_count": null,
    "incremental_authorizations": null,
    "external_authentication_details": null,
    "external_3ds_authentication_attempted": false,
    "expires_on": "2025-02-10T05:06:56.569Z",
    "fingerprint": null,
    "browser_info": null,
    "payment_method_id": null,
    "payment_method_status": null,
    "updated": "2025-02-10T04:59:47.927Z",
    "split_payments": null,
    "frm_metadata": null,
    "merchant_order_reference_id": null,
    "order_tax_amount": null,
    "connector_mandate_id": null
}

Cypress Test Screenshots

No3DSAutoCapture

image

No3DSManualCapture

image

3DSAutoCapture

image

3DSManualCapture

image

Refund

image

Void

image

Headless Tests

image

Note: Please note that subsequent cypress tests for the same flows might fail because NMI has a validation from their end which prevents duplicate transactions from going through, and throws an error similar to "Duplicate transaction REFID:198369517" for the same.

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

@Debarshi-Gupta Debarshi-Gupta requested a review from a team as a code owner February 7, 2025 13:30
Copy link

semanticdiff-com bot commented Feb 7, 2025

Review changes with  SemanticDiff

Changed Files
File Status
  crates/router/src/connector/nmi/transformers.rs  35% smaller

@Debarshi-Gupta Debarshi-Gupta self-assigned this Feb 7, 2025
@Debarshi-Gupta Debarshi-Gupta linked an issue Feb 7, 2025 that may be closed by this pull request
2 tasks
@Debarshi-Gupta Debarshi-Gupta added A-connector-integration Area: Connector integration C-bug Category: Bug labels Feb 10, 2025
@Gnanasundari24 Gnanasundari24 added this pull request to the merge queue Feb 24, 2025
Merged via the queue into main with commit 9032165 Feb 24, 2025
20 of 24 checks passed
@Gnanasundari24 Gnanasundari24 deleted the nmi-void-reason-fix branch February 24, 2025 20:56
pixincreate added a commit to pixincreate/hyperswitch that referenced this pull request Feb 25, 2025
…tion-fork

* 'main' of github.com:juspay/hyperswitch:
  feat(core): [Card Testing Guard] Implement Card Testing Guard  (juspay#7108)
  chore(version): 2025.02.25.0
  ci: minor refactors and improvements (juspay#7308)
  fix(connector): [NMI] Added enum for Void Reason (juspay#7221)
  ci(CI-pr): disable `cargo-hack` step for hotfix PRs (juspay#7334)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
A-connector-integration Area: Connector integration C-bug Category: Bug
Projects
None yet
Development

Successfully merging this pull request may close these issues.

[BUG] Void Reason accepted as string for Nmi
4 participants