Skip to content

feat(core): add manual retry cutoff duration#9330

Merged
Gnanasundari24 merged 14 commits intomainfrom
manual_retry_cutoff
Sep 18, 2025
Merged

feat(core): add manual retry cutoff duration#9330
Gnanasundari24 merged 14 commits intomainfrom
manual_retry_cutoff

Conversation

@Sakilmostak
Copy link
Contributor

@Sakilmostak Sakilmostak commented Sep 9, 2025

Type of Change

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

Description

introduces cutoff limit for manual retry

  • after the creation of intent, if the cutoff duration is expired, don't allow any payment through manual retry
  • cutoff duration is 50% of session expiry set in profile or default (50% of 15 minutes)
  • this only happens in case of manual retry i.e doesn't affect the first confirm

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?

Tested through Postman:

  • Create a MCA
  • Update business profile with manual retry enabled and session expiry duration
curl --location '{{baseUrl}}/account/{{merchant_id}}/business_profile/{{profile_id}}' \
--header 'Content-Type: application/json' \
--header 'Accept: application/json' \
--header 'api-key:{{api_key}}' \
--data '{
    "is_manual_retry_enabled": true,
    "session_expiry": 120
}'
  • Create an intent
curl --location '{{baseUrl}}/payments' \
--header 'Content-Type: application/json' \
--header 'Accept: application/json' \
--header 'api-key:{{api_key}}' \
--data-raw '{
    "amount": 10,
    "currency": "EUR",
    "confirm": false,
    "capture_method": "automatic",
    "capture_on": "2022-09-10T10:11:12Z",
    "customer_id": "cus_r4hlpxACcjdVr64ypkwQ",
    "email": "guest@example.com",
    "name": "John Doe",
    "phone": "999999999",
    "phone_country_code": "+65",
    "description": "Its my first payment request",
    "authentication_type": "no_three_ds",
    "return_url": "https://hyperswitch.io",
    "billing": {
        "address": {
            "city": "test",
            "country": "AT",
            "line1": "here is some \n there is some \n none is some? \n ",
            "line2": "there",
            "line3": "anywhere",
            "zip": "560095",
            "state": "Varaždin County",
            "first_name": "S@k!l",
            "last_name": "M*st@k"
        }
    },
    "shipping": {
        "address": {
            "line1": "1467",
            "line2": "Harrison Street",
            "line3": "Harrison Street",
            "city": "San Fransico",
            "state": "California",
            "zip": "94122",
            "country": "AT",
            "first_name": "PiX"
        }
    },
    "statement_descriptor_name": "joseph",
    "statement_descriptor_suffix": "JS",
    "metadata": {
        "udf1": "value1",
        "new_customer": "true",
        "login_date": "2019-09-10T10:11:12Z"
    }
    ,
    "setup_future_usage": "on_session"
}'
  • Instantly do a confirm after the intent creation (failed case)
curl --location '{{baseUrl}}/payments/{{payment_Id}}/confirm' \
--header 'Content-Type: application/json' \
--header 'Accept: application/json' \
--header 'api-key:{{publishable_key}}' \
--data-raw '{
    "payment_method": "card",
    "payment_method_data": {
        "billing": {
            "address": {
                "city": "sakilmostak",
                "country": "US",
                "line1": "here",
                "line2": "there",
                "line3": "anywhere",
                "zip": "560090",
                "state": "Washingtonr",
                "first_name": "One",
                "last_name": "Two"
            },
            "phone": {
                "number": "1234567890",
                "country_code": "+1"
            },
            "email": "guest@example.com"
        },
        "card": {
            "card_number": "4242424242424242",
            "card_exp_month": "02",
            "card_exp_year": "2026",
            "card_holder_name": "Sakil Mostak",
            "card_cvc": "999"
            
        }
    },
    "connector": [
        "cybersource"
    ],
    "billing": {
        "address": {
            "city": "Mostak",
            "country": "GB",
            "line1": "here is some \n there is some \n none is some? \n ",
            "line2": "there",
            "line3": "anywhere",
            "zip": "560095",
            "state": "Varaždin County",
            "first_name": "Sakil",
            "last_name": "Mostak"
        }
    },
    "client_secret": "pay_HBMbPEDLk4eAPKViLjdo_secret_jCFGoQ3wCB2D529cvMfj",
    "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"
    }
}'
  • wait for the cutoff duration to be over (1 minute in this case)
  • try to confirm the intent again, it should throw the following error
{
    "error": {
        "type": "invalid_request",
        "message": "You cannot confirm this payment using `manual_retry` because the allowed duration has expired",
        "code": "IR_16"
    }
}

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

@Sakilmostak Sakilmostak self-assigned this Sep 9, 2025
@Sakilmostak Sakilmostak requested a review from a team as a code owner September 9, 2025 18:04
@Sakilmostak Sakilmostak added A-core Area: Core flows C-feature Category: Feature request or enhancement labels Sep 9, 2025
@semanticdiff-com
Copy link

semanticdiff-com bot commented Sep 9, 2025

Review changes with  SemanticDiff

Changed Files
File Status
  crates/router/src/core/payments/helpers.rs  0% smaller

Base automatically changed from change_manual_retry_behaviour to main September 11, 2025 14:32
@Sakilmostak Sakilmostak requested a review from a team as a code owner September 11, 2025 14:32
@Gnanasundari24 Gnanasundari24 added this pull request to the merge queue Sep 18, 2025
Merged via the queue into main with commit bc549d3 Sep 18, 2025
21 of 25 checks passed
@Gnanasundari24 Gnanasundari24 deleted the manual_retry_cutoff branch September 18, 2025 08:40
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

A-core Area: Core flows C-feature Category: Feature request or enhancement

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants