Skip to content

Conversation

bsayak03
Copy link
Contributor

@bsayak03 bsayak03 commented May 21, 2025

Type of Change

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

Description

Added Integrity Checks for PSync and RSync flows in Trustpay.
Why not for other flows as well?
The reason being, Trustpay doesnt send amount field in their response. Without getting to know the amount, we cannot perform integrity check. But they do send an amount field in Webhooks, so it will be checked upon receiving the webhooks payload.

Also added a function which converts f64 to StringMajorUnit directly because there wasn't any function already which does it. We needed this function to convert the amount being received in f64 from Webhooks into StringMajorUnit which is required for the integrity check function.

Also added new enum variants in AttemptStatus and IntentStatus. In AttemptStatus added an enum variant "IntegrityFailure" and in IntentStatus added an enum variant "Conflicted".

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?

Note: Since we donot have the Trustpay Dashboard access for SEPA Bank Transfer payment method hence we are sending the webhook payload by ourselves and thereby adding a function inside impl IncomingWebhooks so that the source verification becomes true.

async fn verify_webhook_source(
        &self,
        _request: &webhooks::IncomingWebhookRequestDetails<'_>,
        _merchant_id: &common_utils::id_type::MerchantId,
        _connector_webhook_details: Option<common_utils::pii::SecretSerdeValue>,
        _connector_account_details: crypto::Encryptable<masking::Secret<serde_json::Value>>,
        _connector_name: &str,
    ) -> CustomResult<bool, errors::ConnectorError> {
        Ok(true)
    }

Step 1: Do a Payments - Create (3DS)

cURL :

curl --location 'http://localhost:8080/payments' \
--header 'Content-Type: application/json' \
--header 'Accept: application/json' \
--header 'api-key: dev_SHOvApfNQsc4Jinsu2maY97fKEA8fmphKoXvhPRM5io9C6KhCVdfNQbLJhm3pkx2' \
--header 'Cookie: PHPSESSID=0b47db9d7de94c37b6b272087a9f2fa7' \
--data-raw '{
  "amount": 6540,
  "currency": "EUR",
  "confirm": true,
  "capture_method": "automatic",
  "capture_on": "2022-09-10T10:11:12Z",
  "amount_to_capture": 6540,
  "customer_id": "StripeCustomer",
  "email": "[email protected]",
  "name": "John Doe", 
  "phone": "999999999",
  "phone_country_code": "+1",
  "description": "Its my first payment request",
  "authentication_type": "three_ds",
  "return_url": "https://google.com",
    "payment_method": "bank_transfer",
  "payment_method_type" :"sepa_bank_transfer",
  "payment_method_data": {
    "bank_transfer": {
      "sepa_bank_transfer": {  }
    }
  },
  "statement_descriptor_name": "joseph",
  "statement_descriptor_suffix": "JS",
  "metadata": {
    "udf1": "value1",
    "new_customer": "true",
    "login_date": "2019-09-10T10:11:12Z"
  },
  "billing": {
    "address": {
      "line1": "1467",
      "line2": "Harrison Street",
      "line3": "Harrison Street",
      "city": "San Fransico",
      "state": "California",
      "zip": "94122",
      "country": "ES",
      "first_name": "joseph",
      "last_name": "Doe"
    },
    "phone": {
      "number": "8056594427",
      "country_code": "+91"
    }
  },
  "shipping": {
    "address": {
      "line1": "1467",
      "line2": "Harrison Street",
      "line3": "Harrison Street",
      "city": "San Fransico",
      "state": "California",
      "zip": "94122",
      "country": "ES",
      "first_name": "joseph",
      "last_name": "Doe"
    },
    "phone": {
      "number": "8056594427",
      "country_code": "+91"
    }
  },
  "browser_info": {
        "user_agent": "Mozilla\/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit\/537.36 (KHTML, like Gecko) Chrome\/70.0.3538.110 Safari\/537.36",
        "accept_header": "text\/html,application\/xhtml+xml,application\/xml;q=0.9,image\/webp,image\/apng,*\/*;q=0.8",
        "language": "nl-NL",
        "color_depth": 24,
        "screen_height": 723,
        "screen_width": 1536,
        "time_zone": 0,
        "java_enabled": true,
        "java_script_enabled": true,
        "ip_address": "125.0.0.1"
    }
}'

We will get a status of requires_customer_action and upon getting redirected we will complete the payment and get a status of processing upon doing a PSync.

PSync cURL :

curl --location 'http://localhost:8080/payments/pay_hfikYPO1IQG1QNjmTA7f?force_sync=true&expand_captures=true&expand_attempts=true' \
--header 'Accept: application/json' \
--header 'api-key: dev_SHOvApfNQsc4Jinsu2maY97fKEA8fmphKoXvhPRM5io9C6KhCVdfNQbLJhm3pkx2' \
--header 'Cookie: PHPSESSID=0b47db9d7de94c37b6b272087a9f2fa7'

Response:

{
    "payment_id": "pay_hfikYPO1IQG1QNjmTA7f",
    "merchant_id": "merchant_1747840487",
    "status": "processing",
    "amount": 6540,
    "net_amount": 6540,
    "shipping_cost": null,
    "amount_capturable": 6540,
    "amount_received": null,
    "connector": "trustpay",
    "client_secret": "pay_hfikYPO1IQG1QNjmTA7f_secret_fokQJrYy4upXurha5WqK",
    "created": "2025-05-21T15:15:05.524Z",
    "currency": "EUR",
    "customer_id": "StripeCustomer",
    "customer": {
        "id": "StripeCustomer",
        "name": "John Doe",
        "email": "[email protected]",
        "phone": "999999999",
        "phone_country_code": "+1"
    },
    "description": "Its my first payment request",
    "refunds": null,
    "disputes": null,
    "attempts": [
        {
            "attempt_id": "pay_hfikYPO1IQG1QNjmTA7f_1",
            "status": "authorizing",
            "amount": 6540,
            "order_tax_amount": null,
            "currency": "EUR",
            "connector": "trustpay",
            "error_message": null,
            "payment_method": "bank_transfer",
            "connector_transaction_id": "1668403613",
            "capture_method": "automatic",
            "authentication_type": "three_ds",
            "created_at": "2025-05-21T15:15:05.524Z",
            "modified_at": "2025-05-21T15:15:49.679Z",
            "cancellation_reason": null,
            "mandate_id": null,
            "error_code": null,
            "payment_token": null,
            "connector_metadata": null,
            "payment_experience": null,
            "payment_method_type": "sepa_bank_transfer",
            "reference_id": null,
            "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": "bank_transfer",
    "payment_method_data": {
        "bank_transfer": {
            "sepa": {}
        },
        "billing": null
    },
    "payment_token": null,
    "shipping": {
        "address": {
            "city": "San Fransico",
            "country": "ES",
            "line1": "1467",
            "line2": "Harrison Street",
            "line3": "Harrison Street",
            "zip": "94122",
            "state": "California",
            "first_name": "joseph",
            "last_name": "Doe"
        },
        "phone": {
            "number": "8056594427",
            "country_code": "+91"
        },
        "email": null
    },
    "billing": {
        "address": {
            "city": "San Fransico",
            "country": "ES",
            "line1": "1467",
            "line2": "Harrison Street",
            "line3": "Harrison Street",
            "zip": "94122",
            "state": "California",
            "first_name": "joseph",
            "last_name": "Doe"
        },
        "phone": {
            "number": "8056594427",
            "country_code": "+91"
        },
        "email": null
    },
    "order_details": null,
    "email": "[email protected]",
    "name": "John Doe",
    "phone": "999999999",
    "return_url": "https://google.com/",
    "authentication_type": "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": "sepa_bank_transfer",
    "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": "1668403613",
    "frm_message": null,
    "metadata": {
        "udf1": "value1",
        "login_date": "2019-09-10T10:11:12Z",
        "new_customer": "true"
    },
    "connector_metadata": null,
    "feature_metadata": null,
    "reference_id": null,
    "payment_link": null,
    "profile_id": "pro_4l7F4ABCL71EMcjo792M",
    "surcharge_details": null,
    "attempt_count": 1,
    "merchant_decision": null,
    "merchant_connector_id": "mca_iiEi4DvepGnrCFNuMeam",
    "incremental_authorization_allowed": null,
    "authorization_count": null,
    "incremental_authorizations": null,
    "external_authentication_details": null,
    "external_3ds_authentication_attempted": false,
    "expires_on": "2025-05-21T15:30:05.524Z",
    "fingerprint": null,
    "browser_info": {
        "language": "nl-NL",
        "time_zone": 0,
        "ip_address": "125.0.0.1",
        "user_agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/70.0.3538.110 Safari/537.36",
        "color_depth": 24,
        "java_enabled": true,
        "screen_width": 1536,
        "accept_header": "text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8",
        "screen_height": 723,
        "java_script_enabled": true
    },
    "payment_method_id": null,
    "payment_method_status": null,
    "updated": "2025-05-21T15:16:21.400Z",
    "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": 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
}

Once the status gets to 'suceedeed` and we receive webhooks and if there's a discrepency between the amount sent and amount sent to the connector, we receive this

Webhook Payload :

curl --location 'https://af82-110-227-219-118.ngrok-free.app/webhooks/merchant_1747815234/mca_CK494Qer53vC6Qfi0tHI' \
--header 'Content-Type: application/json' \
--data '{
    "PaymentInformation": {
        "CreditDebitIndicator": "CRDT",
    "References": {
        "MerchantReference": "pay_Q5hHIJ1qTvUf9l7gq8Xp_1",        
        "PaymentId": "6964857984"                              
        
    },
    "Status": "Paid",
    "Amount": {
        "Amount": 65.41,
        "Currency": "EUR"
    },
    "StatusReasonInformation": null
    },
    "Signature": "abcd"
}'

Response:

{
    "error": {
        "type": "api",
        "message": "Integrity Check Failed! as data mismatched for amount expected 6540 but found 6541",
        "code": "IE_00",
        "connector_transaction_id": "6964857984"
    }
}
Screenshot 2025-05-22 at 1 26 50 AM Screenshot 2025-05-22 at 1 27 11 AM

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 self-assigned this May 21, 2025
@bsayak03 bsayak03 requested review from a team as code owners May 21, 2025 10:01
Copy link

semanticdiff-com bot commented May 21, 2025

Review changes with  SemanticDiff

Changed Files
File Status
  crates/hyperswitch_connectors/src/connectors/chargebee/transformers.rs  88% smaller
  crates/hyperswitch_connectors/src/connectors/recurly/transformers.rs  88% smaller
  crates/router/src/core/revenue_recovery/transformers.rs  87% smaller
  crates/router/src/compatibility/stripe/payment_intents/types.rs  84% smaller
  crates/router/src/compatibility/stripe/setup_intents/types.rs  84% smaller
  crates/router/src/types.rs  83% smaller
  crates/hyperswitch_connectors/src/utils.rs  81% smaller
  crates/router/src/core/payments/operations/payment_get.rs  79% smaller
  crates/router/src/core/payments/operations/payment_update_intent.rs  79% smaller
  crates/router/src/core/payments/retry.rs  79% smaller
  crates/router/src/core/payments/helpers.rs  78% smaller
  crates/router/src/connector/utils.rs  77% smaller
  crates/hyperswitch_domain_models/src/router_data.rs  74% smaller
  crates/hyperswitch_connectors/src/connectors/paypal/transformers.rs  70% smaller
  crates/router/src/core/payments/operations/payment_response.rs  70% smaller
  crates/router/src/types/transformers.rs  68% smaller
  api-reference-v2/openapi_spec.json  67% smaller
  api-reference/openapi_spec.json  67% smaller
  crates/router/src/core/payments/operations/proxy_payments_intent.rs  67% smaller
  crates/router/src/core/routing/helpers.rs  65% smaller
  crates/common_enums/src/enums.rs  62% smaller
  crates/router/src/core/payments.rs  27% smaller
  crates/router/src/core/payments/operations/payment_attempt_record.rs  27% smaller
  crates/router/src/core/payments/operations/payment_capture_v2.rs  27% smaller
  crates/router/src/core/payments/operations/payment_confirm_intent.rs  27% smaller
  crates/router/src/core/payments/payment_methods.rs  21% smaller
  crates/hyperswitch_connectors/src/connectors/stripe/transformers.rs  7% smaller
  crates/router/src/core/payments/operations/payment_session_intent.rs  3% smaller
  crates/hyperswitch_connectors/src/connectors/trustpay.rs  1% smaller
  crates/common_enums/src/transformers.rs  0% smaller
  migrations/2025-05-21-194538_modify_attemptstatus_and_intentstatus/down.sql Unsupported file format
  migrations/2025-05-21-194538_modify_attemptstatus_and_intentstatus/up.sql Unsupported file format

…Flows & Added new variants in AttemptStatus & IntentStatus
@bsayak03 bsayak03 requested review from a team as code owners May 21, 2025 20:07
@hyperswitch-bot hyperswitch-bot bot added the M-database-changes Metadata: This PR involves database schema changes label May 21, 2025
@bsayak03 bsayak03 changed the title feat(connector): [TRUSTPAY] Added Integrity Checks for PSync & RSync flows feat(connector): [TRUSTPAY] Added Integrity Checks for PSync & RSync flows & Added New Variants in AttemptStatus & IntentStatus May 21, 2025
@bsayak03 bsayak03 requested a review from a team as a code owner May 22, 2025 06:48
@hyperswitch-bot hyperswitch-bot bot added the M-api-contract-changes Metadata: This PR involves API contract changes label May 29, 2025
srujanchikke
srujanchikke previously approved these changes Jun 9, 2025
Comment on lines 11 to 14
AttemptStatus::Authorized
| AttemptStatus::Charged
| AttemptStatus::AutoRefunded
| AttemptStatus::IntegrityFailure => Self::Succeeded,
Copy link
Contributor

@srujanchikke srujanchikke Jun 10, 2025

Choose a reason for hiding this comment

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

This we can change to InvalidStatus, Since merchant intervention is needed anyway, Process tracker also we will be stopped to avoid other recovery retries.
cc : @Aprabhat19

@Gnanasundari24 Gnanasundari24 added this pull request to the merge queue Jun 10, 2025
Merged via the queue into main with commit a76a9c1 Jun 10, 2025
15 of 20 checks passed
@Gnanasundari24 Gnanasundari24 deleted the trustpay/fix branch June 10, 2025 17:03
pixincreate added a commit that referenced this pull request Jun 10, 2025
…ordea-sepa

* 'main' of github.com:juspay/hyperswitch: (63 commits)
  feat(connector): [TRUSTPAY] Added Integrity Checks for PSync & RSync flows & Added New Variants in AttemptStatus & IntentStatus (#8096)
  fix(connector): [STRIPE] Throwing Missing Required Field Error if connector_customer is not present (#8309)
  refactor(connectors): [worldpayvantiv] replace sandbox url with pre-live url and fix typo (#8286)
  fix: payment link styling for dynamic classes (#8273)
  feat(core): Make installment_payment_enabled,recurring_enabled Optional (#8201)
  fix(cypress): fix itaubank, datatrans and facilitapay (#8229)
  fix(connector): [jpmorgan] 5xx during payment authorize and `cancellation_reason` (#8282)
  revert(connector): [Worldpay] add root CA certificate (#8224)
  ci(cypress): fix fiuu, fiservemea , paybox and worldpay connector (#8209)
  fix(connector): removed forked josekit dependency from payout connector Nomupay (#8183)
  chore(version): 2025.06.10.0
  feat(tokenio): Add OpenBanking Redirection Flow (#8152)
  fix: Unified scarf setup (#8238)
  feat(health): Health check for Decision engine (#8243)
  chore: Update apple pay currency filter configs (#8217)
  refactor(customers_v2): Remove merchant reference id from v2 customer update (#7879)
  chore(version): 2025.06.09.0
  chore(postman): update Postman collection files
  ci(postman): add tunnel collection to postman tests (#8269)
  feat(connector): Added recurring payments support for split payments in Stripe (#8271)
  ...
pixincreate added a commit that referenced this pull request Jun 10, 2025
…ordea-sepa

* 'main' of github.com:juspay/hyperswitch: (63 commits)
  feat(connector): [TRUSTPAY] Added Integrity Checks for PSync & RSync flows & Added New Variants in AttemptStatus & IntentStatus (#8096)
  fix(connector): [STRIPE] Throwing Missing Required Field Error if connector_customer is not present (#8309)
  refactor(connectors): [worldpayvantiv] replace sandbox url with pre-live url and fix typo (#8286)
  fix: payment link styling for dynamic classes (#8273)
  feat(core): Make installment_payment_enabled,recurring_enabled Optional (#8201)
  fix(cypress): fix itaubank, datatrans and facilitapay (#8229)
  fix(connector): [jpmorgan] 5xx during payment authorize and `cancellation_reason` (#8282)
  revert(connector): [Worldpay] add root CA certificate (#8224)
  ci(cypress): fix fiuu, fiservemea , paybox and worldpay connector (#8209)
  fix(connector): removed forked josekit dependency from payout connector Nomupay (#8183)
  chore(version): 2025.06.10.0
  feat(tokenio): Add OpenBanking Redirection Flow (#8152)
  fix: Unified scarf setup (#8238)
  feat(health): Health check for Decision engine (#8243)
  chore: Update apple pay currency filter configs (#8217)
  refactor(customers_v2): Remove merchant reference id from v2 customer update (#7879)
  chore(version): 2025.06.09.0
  chore(postman): update Postman collection files
  ci(postman): add tunnel collection to postman tests (#8269)
  feat(connector): Added recurring payments support for split payments in Stripe (#8271)
  ...
pixincreate added a commit that referenced this pull request Jun 10, 2025
… into trustpay-banktransfer

* 'trustpay-banktransfer' of github.com:juspay/hyperswitch:
  feat(connector): [TRUSTPAY] Added Integrity Checks for PSync & RSync flows & Added New Variants in AttemptStatus & IntentStatus (#8096)
  fix(connector): [STRIPE] Throwing Missing Required Field Error if connector_customer is not present (#8309)
  refactor(connectors): [worldpayvantiv] replace sandbox url with pre-live url and fix typo (#8286)
  fix: payment link styling for dynamic classes (#8273)
  feat(core): Make installment_payment_enabled,recurring_enabled Optional (#8201)
  fix(cypress): fix itaubank, datatrans and facilitapay (#8229)
  fix(connector): [jpmorgan] 5xx during payment authorize and `cancellation_reason` (#8282)
  revert(connector): [Worldpay] add root CA certificate (#8224)
  ci(cypress): fix fiuu, fiservemea , paybox and worldpay connector (#8209)
  fix(connector): removed forked josekit dependency from payout connector Nomupay (#8183)
  chore(version): 2025.06.10.0
bsayak03 added a commit that referenced this pull request Jun 11, 2025
…flows & Added New Variants in AttemptStatus & IntentStatus (#8096)

Co-authored-by: Sayak Bhattacharya <[email protected]>
Co-authored-by: hyperswitch-bot[bot] <148525504+hyperswitch-bot[bot]@users.noreply.github.com>
Co-authored-by: Sahkal Poddar <[email protected]>
bsayak03 added a commit that referenced this pull request Jun 11, 2025
…flows & Added New Variants in AttemptStatus & IntentStatus (#8096)

Co-authored-by: Sayak Bhattacharya <[email protected]>
Co-authored-by: hyperswitch-bot[bot] <148525504+hyperswitch-bot[bot]@users.noreply.github.com>
Co-authored-by: Sahkal Poddar <[email protected]>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
M-api-contract-changes Metadata: This PR involves API contract changes M-database-changes Metadata: This PR involves database schema changes
Projects
None yet
Development

Successfully merging this pull request may close these issues.

9 participants