Skip to content

Conversation

bsayak03
Copy link
Contributor

@bsayak03 bsayak03 commented May 20, 2025

Type of Change

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

Description

Populated network_advice_code, network_decline_code and network_error_response in ErrorResponse. Also added integrity check support for Authorize, Capture, Refund, PSync and RSync flows.

What is an integrity check?
A scenario where there is a discrepancy between the amount sent in the request and the amount received from the connector, which is checked during response handling.
https://developer.fiserv.com/product/CommerceHub/api/?type=post&path=/payments/v1/charges&branch=main&version=1.25.0400

Additional Changes

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

Motivation and Context

How did you test it?

For Integrity Checks

Case 1: Automatic Capture

cURL:

curl --location 'http://localhost:8080/payments' \
--header 'Content-Type: application/json' \
--header 'Accept: application/json' \
--header 'api-key: dev_8BoyoSPgaCnEZ7hPrLeVLSyEpsxM1d95WnoRRlgyLJfhUD3Rt9vaYiErFlhICRJy' \
--header 'Cookie: PHPSESSID=0b47db9d7de94c37b6b272087a9f2fa7' \
--data-raw '{
    "amount": 651200,
    "currency": "USD",
    "confirm": true,
    "capture_method": "automatic",
    "capture_on": "2022-09-10T10:11:12Z",
    "customer_id": "First_Customer",
    "name": "John Doe",
    "authentication_type": "three_ds",
    "return_url": "https://google.com",
    "payment_method": "card",
    "payment_method_type": "credit",
    "payment_method_data": {
        "card": {
            
            "card_number": "4147463011110083",
            "card_exp_month": "12",
            "card_exp_year": "27",
            "card_holder_name": "joseph Doe",
            "card_cvc": "123"
        }
    },
    "billing": {
        "phone": {
            "number": "8056594427",
            "country_code": "+91"
        },
        "email": "[email protected]"
    }
}'

Response:

{
    "error": {
        "type": "api",
        "message": "Integrity Check Failed! as data mismatched for amount expected 651200 but found 651300",
        "code": "IE_00",
        "connector_transaction_id": "CHG0165dcaf19383fef3b997c70f17e33f882"
    }
}

We hardcoded the amount at the connector level to a value greater than the one sent in the request. This is verified at response time, causing a discrepancy between the amount passed in the request and the amount passed to the connector, which triggers the integrity check.

  1. Manual Capture:

cURL :

curl --location 'http://localhost:8080/payments' \
--header 'Content-Type: application/json' \
--header 'Accept: application/json' \
--header 'api-key: dev_8BoyoSPgaCnEZ7hPrLeVLSyEpsxM1d95WnoRRlgyLJfhUD3Rt9vaYiErFlhICRJy' \
--header 'Cookie: PHPSESSID=0b47db9d7de94c37b6b272087a9f2fa7' \
--data-raw '{
    "amount": 651200,
    "currency": "USD",
    "confirm": true,
    "capture_method": "manual",
    "capture_on": "2022-09-10T10:11:12Z",
    "customer_id": "First_Customer",
    "name": "John Doe",
    "authentication_type": "three_ds",
    "return_url": "https://google.com",
    "payment_method": "card",
    "payment_method_type": "credit",
    "payment_method_data": {
        "card": {
            
            "card_number": "4147463011110083",
            "card_exp_month": "12",
            "card_exp_year": "27",
            "card_holder_name": "joseph Doe",
            "card_cvc": "123"
        }
    },
    "billing": {
        "phone": {
            "number": "8056594427",
            "country_code": "+91"
        },
        "email": "[email protected]"
    }
}'


Response:

{
    "error": {
        "type": "api",
        "message": "Integrity Check Failed! as data mismatched for amount expected 651200 but found 651300",
        "code": "IE_00",
        "connector_transaction_id": "CHG01e6b342a643cf24269162a523ae884b49"
    }
}

Reason: We hardcoded the amount in the code to an amount which is more than the one being sent in the connector request.

  1. Refund

First, do a payments create( a successful one) and donot hardcode anything.

cURL :

curl --location 'http://localhost:8080/payments' \
--header 'Content-Type: application/json' \
--header 'Accept: application/json' \
--header 'api-key: dev_8BoyoSPgaCnEZ7hPrLeVLSyEpsxM1d95WnoRRlgyLJfhUD3Rt9vaYiErFlhICRJy' \
--header 'Cookie: PHPSESSID=0b47db9d7de94c37b6b272087a9f2fa7' \
--data-raw '{
    "amount": 651200,
    "currency": "USD",
    "confirm": true,
    "capture_method": "automatic",
    "capture_on": "2022-09-10T10:11:12Z",
    "customer_id": "First_Customer",
    "name": "John Doe",
    "authentication_type": "three_ds",
    "return_url": "https://google.com",
    "payment_method": "card",
    "payment_method_type": "credit",
    "payment_method_data": {
        "card": {
            
            "card_number": "4147463011110083",
            "card_exp_month": "12",
            "card_exp_year": "27",
            "card_holder_name": "joseph Doe",
            "card_cvc": "123"
        }
    },
    "billing": {
        "phone": {
            "number": "8056594427",
            "country_code": "+91"
        },
        "email": "[email protected]"
    }
}'


Response of Payments - Create :

{
    "payment_id": "pay_9YN7bLpjbmbFkA1laXqC",
    "merchant_id": "merchant_1747656283",
    "status": "succeeded",
    "amount": 651200,
    "net_amount": 651200,
    "shipping_cost": null,
    "amount_capturable": 0,
    "amount_received": 651200,
    "connector": "fiserv",
    "client_secret": "pay_9YN7bLpjbmbFkA1laXqC_secret_onbFfEy4CWh2pd3jAdTt",
    "created": "2025-05-19T20:59:12.836Z",
    "currency": "USD",
    "customer_id": "First_Customer",
    "customer": {
        "id": "First_Customer",
        "name": "John Doe",
        "email": null,
        "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": "card",
    "payment_method_data": {
        "card": {
            "last4": "0083",
            "card_type": null,
            "card_network": null,
            "card_issuer": null,
            "card_issuing_country": null,
            "card_isin": "414746",
            "card_extended_bin": null,
            "card_exp_month": "12",
            "card_exp_year": "27",
            "card_holder_name": "joseph Doe",
            "payment_checks": null,
            "authentication_data": null
        },
        "billing": null
    },
    "payment_token": null,
    "shipping": null,
    "billing": {
        "address": null,
        "phone": {
            "number": "8056594427",
            "country_code": "+91"
        },
        "email": "[email protected]"
    },
    "order_details": null,
    "email": null,
    "name": "John Doe",
    "phone": null,
    "return_url": "https://google.com/",
    "authentication_type": "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": 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": "First_Customer",
        "created_at": 1747688352,
        "expires": 1747691952,
        "secret": "epk_f6e6cc342a9147eb91b4d8144bc28958"
    },
    "manual_retry_allowed": false,
    "connector_transaction_id": "964bbc9b9e494be8bf575977cf2582b5",
    "frm_message": null,
    "metadata": null,
    "connector_metadata": null,
    "feature_metadata": null,
    "reference_id": "CHG01012441523bde085d4ec1a37b6c72c768",
    "payment_link": null,
    "profile_id": "pro_kg6n3seduV6leLIAxPwL",
    "surcharge_details": null,
    "attempt_count": 1,
    "merchant_decision": null,
    "merchant_connector_id": "mca_EZ1kF48ElbkcXo52Eu0z",
    "incremental_authorization_allowed": null,
    "authorization_count": null,
    "incremental_authorizations": null,
    "external_authentication_details": null,
    "external_3ds_authentication_attempted": false,
    "expires_on": "2025-05-19T21:14:12.836Z",
    "fingerprint": null,
    "browser_info": null,
    "payment_method_id": null,
    "payment_method_status": null,
    "updated": "2025-05-19T20:59:14.534Z",
    "split_payments": null,
    "frm_metadata": null,
    "extended_authorization_applied": null,
    "capture_before": null,
    "merchant_order_reference_id": null,
    "order_tax_amount": null,
    "connector_mandate_id": null,
    "card_discovery": "manual",
    "force_3ds_challenge": false,
    "force_3ds_challenge_trigger": false,
    "issuer_error_code": null,
    "issuer_error_message": null,
    "is_iframe_redirection_enabled": null
}

Now attempt a Refund with this payment_id. In code I have hardcoded the refund amount same as the captured amount but in the request will be passing an amount which will be less than that.

Refunds - Create cURL:

curl --location 'http://localhost:8080/refunds' \
--header 'Content-Type: application/json' \
--header 'Accept: application/json' \
--header 'api-key: dev_8BoyoSPgaCnEZ7hPrLeVLSyEpsxM1d95WnoRRlgyLJfhUD3Rt9vaYiErFlhICRJy' \
--header 'Cookie: PHPSESSID=0b47db9d7de94c37b6b272087a9f2fa7' \
--data '{
    "payment_id": "pay_kshnzcowY4iP7ZhiBArY",
    "amount": 651100,
    "reason": "Customer returned product",
    "refund_type": "instant",
    "metadata": {
        "udf1": "value1",
        "new_customer": "true",
        "login_date": "2019-09-10T10:11:12Z"
    }
}'

Response :

{
    "refund_id": "ref_qvFT2TJmnx0irSvV5MTX",
    "payment_id": "pay_kshnzcowY4iP7ZhiBArY",
    "amount": 651100,
    "currency": "USD",
    "status": "review",
    "reason": "Customer returned product",
    "metadata": {
        "udf1": "value1",
        "new_customer": "true",
        "login_date": "2019-09-10T10:11:12Z"
    },
    "error_message": "Integrity Check Failed! as data mismatched for fields refund_amount expected 651100 but found 651200",
    "error_code": "IE",
    "unified_code": null,
    "unified_message": null,
    "created_at": "2025-05-19T21:12:21.095Z",
    "updated_at": "2025-05-19T21:12:22.577Z",
    "connector": "fiserv",
    "profile_id": "pro_kg6n3seduV6leLIAxPwL",
    "merchant_connector_id": "mca_EZ1kF48ElbkcXo52Eu0z",
    "split_refunds": null,
    "issuer_error_code": null,
    "issuer_error_message": 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

@bsayak03 bsayak03 requested a review from a team as a code owner May 20, 2025 04:12
Copy link

semanticdiff-com bot commented May 20, 2025

Review changes with  SemanticDiff

Changed Files
File Status
  crates/hyperswitch_connectors/src/connectors/fiserv.rs  21% smaller
  crates/hyperswitch_connectors/src/connectors/fiserv/transformers.rs  8% smaller

@bsayak03 bsayak03 self-assigned this May 20, 2025
sahkal
sahkal previously approved these changes May 20, 2025
Copy link
Contributor

@sahkal sahkal left a comment

Choose a reason for hiding this comment

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

Integrity checks LGTM!

Comment on lines 193 to 198

let network_advice_code = first_error.message.clone();

let network_decline_code = first_error.code.clone();

let network_error_message = first_error.additional_info.clone();
Copy link
Contributor

@srujanchikke srujanchikke May 20, 2025

Choose a reason for hiding this comment

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

These fields are not equivalent to network error codes, If they are not present can you make them None instead of mapping to processor error. And also you can add network error codes in 2xx response.If webhooks are present please add it there as well.

@bsayak03 bsayak03 dismissed stale reviews from deepanshu-iiitu and sahkal via eca6ac4 May 29, 2025 13:50
@bsayak03 bsayak03 force-pushed the fiserv/integ_check/ntw_err branch from 670e277 to eca6ac4 Compare May 29, 2025 13:50
@bsayak03 bsayak03 changed the title feat(connector): [FISERV] Populated Network Advice Fields in ErrorResponse & Added Integrity Check support for Payment & Refund Flows feat(connector): [FISERV] Added Integrity Check support for Payment & Refund Flows May 29, 2025
@bsayak03 bsayak03 changed the title feat(connector): [FISERV] Added Integrity Check support for Payment & Refund Flows feat(connector): [FISERV] Added Integrity Check support for all Payment & Refund Flows May 29, 2025
This was referenced Sep 1, 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.

5 participants