Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(router): add support for relay refund incoming webhooks #6974

Merged
merged 16 commits into from
Jan 10, 2025

Conversation

ShankarSinghC
Copy link
Contributor

@ShankarSinghC ShankarSinghC commented Jan 2, 2025

Type of Change

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

Description

Some connectors, like Adyen, do not support a refund sync API, so we need to rely on refund webhooks for the status. To address this, support for relay refund webhooks is being added.

To support this use case, a new webhook endpoint needs to be introduced for relay webhooks:
/webhooks/relay/{merchant_id}/{connector_id_or_name}

Once the webhook is identified as a relay webhook, it should be handled based on the flow type, such as refunds, payments, etc. For now, only support for relay refund webhooks has been added.

Additional Changes

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

Motivation and Context

This change is to update the relay status when we have to rely on the connector webhooks for the refund status.

How did you test it?

-> Create a merchant connector account for stripe
-> Setup the webhook url in the stripe dashboard
-> Relay webhook testing
-> Make payment through stripe connector. As this relay webhooks can only handle relay refunds webhooks, we need to return 200 OK for the payments webhooks that we received.

curl --location 'http://localhost:8080/payments' \
--header 'Content-Type: application/json' \
--header 'Accept: application/json' \
--header 'x-tenant-id: hyperswitch' \
--header 'api-key:' \
--data-raw '{
    "amount": 100,
    "amount_to_capture": 100,
    "currency": "USD",
    "confirm": true,
    "capture_method": "automatic",
    "capture_on": "2022-09-10T10:11:12Z",
    "email": "[email protected]",
    "name": "John Doe",
    "phone": "999999999",
    "phone_country_code": "+1",
    "description": "Its my first payment request",
    "authentication_type": "no_three_ds",
    "customer_id": "cu_1736430184",
    "return_url": "http://127.0.0.1:4040",
    "customer_acceptance": {
        "acceptance_type": "offline",
        "accepted_at": "1963-05-03T04:07:52.723Z",
        "online": {
            "ip_address": "in sit",
            "user_agent": "amet irure esse"
        }
    },
    "payment_method": "card",
    "payment_method_data": {
        "card": {
            "card_number": "4111111111111111",
            "card_exp_month": "03",
            "card_exp_year": "2030",
            "card_holder_name": "joseph Doe",
            "card_cvc": "737"
        }
    },
    "billing": {
        "address": {
            "line1": "1467",
            "line2": "Harrison Street",
            "line3": "Harrison Street",
            "city": "San",
            "state": "California",
            "zip": "94122",
            "country": "US",
            "first_name": "PiX",
            "last_name": "ss"
        },
        "email": "[email protected]"
    },
    "shipping": {
        "address": {
            "line1": "1467",
            "line2": "Harrison Street",
            "line3": "Harrison Street",
            "city": "San Fransico",
            "state": "California",
            "zip": "94122",
            "country": "US",
            "first_name": "PiX"
        }
    },
    "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"
    },
    "routing": {
        "type": "single",
        "data": {
            "connector": "cybersource",
            "merchant_connector_id": "mca_8W0CQfwE89J1BJBbpcnt"
        }
    },
    "statement_descriptor_name": "joseph",
    "statement_descriptor_suffix": "JS",
    "metadata": {
        "udf1": "value1",
        "new_customer": "true",
        "login_date": "2019-09-10T10:11:12Z"
    }
}'
{
    "payment_id": "pay_9IYMeErPOtFrHTxEundR",
    "merchant_id": "merchant_1736429319",
    "status": "succeeded",
    "amount": 100,
    "net_amount": 100,
    "shipping_cost": null,
    "amount_capturable": 0,
    "amount_received": 100,
    "connector": "stripe",
    "client_secret": "pay_9IYMeErPOtFrHTxEundR_secret_A9BwRKPAld2g2fPwpN0Z",
    "created": "2025-01-09T13:42:58.438Z",
    "currency": "USD",
    "customer_id": "cu_1736430178",
    "customer": {
        "id": "cu_1736430178",
        "name": "John Doe",
        "email": "[email protected]",
        "phone": "999999999",
        "phone_country_code": "+1"
    },
    "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": "automatic",
    "payment_method": "card",
    "payment_method_data": {
        "card": {
            "last4": "1111",
            "card_type": null,
            "card_network": null,
            "card_issuer": null,
            "card_issuing_country": null,
            "card_isin": "411111",
            "card_extended_bin": null,
            "card_exp_month": "03",
            "card_exp_year": "2030",
            "card_holder_name": "joseph Doe",
            "payment_checks": {
                "cvc_check": "pass",
                "address_line1_check": "pass",
                "address_postal_code_check": "pass"
            },
            "authentication_data": null
        },
        "billing": null
    },
    "payment_token": null,
    "shipping": {
        "address": {
            "city": "San Fransico",
            "country": "US",
            "line1": "1467",
            "line2": "Harrison Street",
            "line3": "Harrison Street",
            "zip": "94122",
            "state": "California",
            "first_name": "PiX",
            "last_name": null
        },
        "phone": null,
        "email": null
    },
    "billing": {
        "address": {
            "city": "San",
            "country": "US",
            "line1": "1467",
            "line2": "Harrison Street",
            "line3": "Harrison Street",
            "zip": "94122",
            "state": "California",
            "first_name": "PiX",
            "last_name": "ss"
        },
        "phone": null,
        "email": "[email protected]"
    },
    "order_details": null,
    "email": "[email protected]",
    "name": "John Doe",
    "phone": "999999999",
    "return_url": "http://127.0.0.1:4040/",
    "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": null,
    "connector_label": null,
    "business_country": null,
    "business_label": "default",
    "business_sub_label": null,
    "allowed_payment_method_types": null,
    "ephemeral_key": {
        "customer_id": "cu_1736430178",
        "created_at": 1736430178,
        "expires": 1736433778,
        "secret": "epk_54d28c2dcea8416fa84ce3ec9f960102"
    },
    "manual_retry_allowed": false,
    "connector_transaction_id": "pi_3QfM0lD5R7gDAGff1L1eaicn",
    "frm_message": null,
    "metadata": {
        "udf1": "value1",
        "login_date": "2019-09-10T10:11:12Z",
        "new_customer": "true"
    },
    "connector_metadata": null,
    "feature_metadata": null,
    "reference_id": "pi_3QfM0lD5R7gDAGff1L1eaicn",
    "payment_link": null,
    "profile_id": "pro_GhoiAnNpnyEAqAAbwULW",
    "surcharge_details": null,
    "attempt_count": 1,
    "merchant_decision": null,
    "merchant_connector_id": "mca_YhBV1Nr6PXdkkG7md9ro",
    "incremental_authorization_allowed": null,
    "authorization_count": null,
    "incremental_authorizations": null,
    "external_authentication_details": null,
    "external_3ds_authentication_attempted": false,
    "expires_on": "2025-01-09T13:57:58.438Z",
    "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-01-09T13:43:00.565Z",
    "split_payments": null,
    "frm_metadata": null,
    "merchant_order_reference_id": null,
    "order_tax_amount": null,
    "connector_mandate_id": null
}

image

-> Create a relay refund

curl --location 'http://localhost:8080/relay' \
--header 'Content-Type: application/json' \
--header 'x-profile-id: pro_GhoiAnNpnyEAqAAbwULW' \
--header 'api-key:' \
--data '{
    "connector_id": "mca_YhBV1Nr6PXdkkG7md9ro",
    "connector_resource_id": "pi_3QfM0lD5R7gDAGff1L1eaicn",
    "data": {
        "refund": {
            "amount": 1,
            "currency": "USD"
        }
    },
    "type": "refund"
}'
{
    "id": "relay_WhRindDie9fcGbLRvE3G",
    "status": "success",
    "connector_resource_id": "pi_3QfM0lD5R7gDAGff1L1eaicn",
    "error": null,
    "connector_reference_id": "re_3QfM0lD5R7gDAGff1533tuY2",
    "connector_id": "mca_YhBV1Nr6PXdkkG7md9ro",
    "profile_id": "pro_GhoiAnNpnyEAqAAbwULW",
    "type": "refund",
    "data": {
        "refund": {
            "amount": 1,
            "currency": "USD",
            "reason": null
        }
    }
}

image
-> Manually setting the db recording the pending to test relay status update by webhook

curl --location 'http://localhost:8080/relay/relay_WhRindDie9fcGbLRvE3G' \
--header 'Content-Type: application/json' \
--header 'X-Idempotency-Key: <x-idempotency-key>' \
--header 'X-Profile-Id: pro_GhoiAnNpnyEAqAAbwULW' \
--header 'api-key:' \
--data ''
{
    "id": "relay_WhRindDie9fcGbLRvE3G",
    "status": "pending",
    "connector_resource_id": "pi_3QfM0lD5R7gDAGff1L1eaicn",
    "error": null,
    "connector_reference_id": "re_3QfM0lD5R7gDAGff1533tuY2",
    "connector_id": "mca_YhBV1Nr6PXdkkG7md9ro",
    "profile_id": "pro_GhoiAnNpnyEAqAAbwULW",
    "type": "refund",
    "data": {
        "refund": {
            "amount": 1,
            "currency": "USD",
            "reason": null
        }
    }
}

-> Re trigger the relay webhook and when retrieved the status is expected to be succeeded
image

curl --location 'http://localhost:8080/relay/relay_WhRindDie9fcGbLRvE3G' \
--header 'Content-Type: application/json' \
--header 'X-Idempotency-Key: <x-idempotency-key>' \
--header 'X-Profile-Id: pro_GhoiAnNpnyEAqAAbwULW' \
--header 'api-key:' \
--data ''
{
    "id": "relay_WhRindDie9fcGbLRvE3G",
    "status": "success",
    "connector_resource_id": "pi_3QfM0lD5R7gDAGff1L1eaicn",
    "error": null,
    "connector_reference_id": "re_3QfM0lD5R7gDAGff1533tuY2",
    "connector_id": "mca_YhBV1Nr6PXdkkG7md9ro",
    "profile_id": "pro_GhoiAnNpnyEAqAAbwULW",
    "type": "refund",
    "data": {
        "refund": {
            "amount": 1,
            "currency": "USD",
            "reason": null
        }
    }
}

-> Test stripe normal payments webhooks to ensure that the webhook behaviour is not affected for all other events
-> Create a payment

curl --location 'http://localhost:8080/payments' \
--header 'Content-Type: application/json' \
--header 'Accept: application/json' \
--header 'x-tenant-id: hyperswitch' \
--header 'api-key:' \
--data-raw '{
    "amount": 100,
    "amount_to_capture": 100,
    "currency": "USD",
    "confirm": true,
    "capture_method": "automatic",
    "capture_on": "2022-09-10T10:11:12Z",
    "email": "[email protected]",
    "name": "John Doe",
    "phone": "999999999",
    "phone_country_code": "+1",
    "description": "Its my first payment request",
    "authentication_type": "no_three_ds",
    "customer_id": "cu_1736432186",
    "return_url": "http://127.0.0.1:4040",
    "customer_acceptance": {
        "acceptance_type": "offline",
        "accepted_at": "1963-05-03T04:07:52.723Z",
        "online": {
            "ip_address": "in sit",
            "user_agent": "amet irure esse"
        }
    },
    "payment_method": "card",
    "payment_method_data": {
        "card": {
            "card_number": "4111111111111111",
            "card_exp_month": "03",
            "card_exp_year": "2030",
            "card_holder_name": "joseph Doe",
            "card_cvc": "737"
        }
    },
    "billing": {
        "address": {
            "line1": "1467",
            "line2": "Harrison Street",
            "line3": "Harrison Street",
            "city": "San",
            "state": "California",
            "zip": "94122",
            "country": "US",
            "first_name": "PiX",
            "last_name": "ss"
        },
        "email": "[email protected]"
    },
    "shipping": {
        "address": {
            "line1": "1467",
            "line2": "Harrison Street",
            "line3": "Harrison Street",
            "city": "San Fransico",
            "state": "California",
            "zip": "94122",
            "country": "US",
            "first_name": "PiX"
        }
    },
    "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"
    },
    "routing": {
        "type": "single",
        "data": {
            "connector": "cybersource",
            "merchant_connector_id": "mca_8W0CQfwE89J1BJBbpcnt"
        }
    },
    "statement_descriptor_name": "joseph",
    "statement_descriptor_suffix": "JS",
    "metadata": {
        "udf1": "value1",
        "new_customer": "true",
        "login_date": "2019-09-10T10:11:12Z"
    }
}'
{
    "payment_id": "pay_bnl7rTJB6WUbfsQRTRU3",
    "merchant_id": "merchant_1736429319",
    "status": "succeeded",
    "amount": 100,
    "net_amount": 100,
    "shipping_cost": null,
    "amount_capturable": 0,
    "amount_received": 100,
    "connector": "stripe",
    "client_secret": "pay_bnl7rTJB6WUbfsQRTRU3_secret_YRCZCEKKcDxD6VnbtBGl",
    "created": "2025-01-09T14:07:10.134Z",
    "currency": "USD",
    "customer_id": "cu_1736431630",
    "customer": {
        "id": "cu_1736431630",
        "name": "John Doe",
        "email": "[email protected]",
        "phone": "999999999",
        "phone_country_code": "+1"
    },
    "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": "automatic",
    "payment_method": "card",
    "payment_method_data": {
        "card": {
            "last4": "1111",
            "card_type": null,
            "card_network": null,
            "card_issuer": null,
            "card_issuing_country": null,
            "card_isin": "411111",
            "card_extended_bin": null,
            "card_exp_month": "03",
            "card_exp_year": "2030",
            "card_holder_name": "joseph Doe",
            "payment_checks": {
                "cvc_check": "pass",
                "address_line1_check": "pass",
                "address_postal_code_check": "pass"
            },
            "authentication_data": null
        },
        "billing": null
    },
    "payment_token": null,
    "shipping": {
        "address": {
            "city": "San Fransico",
            "country": "US",
            "line1": "1467",
            "line2": "Harrison Street",
            "line3": "Harrison Street",
            "zip": "94122",
            "state": "California",
            "first_name": "PiX",
            "last_name": null
        },
        "phone": null,
        "email": null
    },
    "billing": {
        "address": {
            "city": "San",
            "country": "US",
            "line1": "1467",
            "line2": "Harrison Street",
            "line3": "Harrison Street",
            "zip": "94122",
            "state": "California",
            "first_name": "PiX",
            "last_name": "ss"
        },
        "phone": null,
        "email": "[email protected]"
    },
    "order_details": null,
    "email": "[email protected]",
    "name": "John Doe",
    "phone": "999999999",
    "return_url": "http://127.0.0.1:4040/",
    "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": null,
    "connector_label": null,
    "business_country": null,
    "business_label": "default",
    "business_sub_label": null,
    "allowed_payment_method_types": null,
    "ephemeral_key": {
        "customer_id": "cu_1736431630",
        "created_at": 1736431630,
        "expires": 1736435230,
        "secret": "epk_bf70a02d2bb64f5c81712679dedac0aa"
    },
    "manual_retry_allowed": false,
    "connector_transaction_id": "pi_3QfMOBD5R7gDAGff0l6jmTHK",
    "frm_message": null,
    "metadata": {
        "udf1": "value1",
        "login_date": "2019-09-10T10:11:12Z",
        "new_customer": "true"
    },
    "connector_metadata": null,
    "feature_metadata": null,
    "reference_id": "pi_3QfMOBD5R7gDAGff0l6jmTHK",
    "payment_link": null,
    "profile_id": "pro_GhoiAnNpnyEAqAAbwULW",
    "surcharge_details": null,
    "attempt_count": 1,
    "merchant_decision": null,
    "merchant_connector_id": "mca_YhBV1Nr6PXdkkG7md9ro",
    "incremental_authorization_allowed": null,
    "authorization_count": null,
    "incremental_authorizations": null,
    "external_authentication_details": null,
    "external_3ds_authentication_attempted": false,
    "expires_on": "2025-01-09T14:22:10.134Z",
    "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-01-09T14:07:12.259Z",
    "split_payments": null,
    "frm_metadata": null,
    "merchant_order_reference_id": null,
    "order_tax_amount": null,
    "connector_mandate_id": null
}

-> Manually set the status to pending in the db to test webhooks flow

curl --location 'http://localhost:8080/payments/pay_bnl7rTJB6WUbfsQRTRU3' \
--header 'Accept: application/json' \
--header 'api-key:'
{
    "payment_id": "pay_bnl7rTJB6WUbfsQRTRU3",
    "merchant_id": "merchant_1736429319",
    "status": "processing",
    "amount": 100,
    "net_amount": 100,
    "shipping_cost": null,
    "amount_capturable": 0,
    "amount_received": 100,
    "connector": "stripe",
    "client_secret": "pay_bnl7rTJB6WUbfsQRTRU3_secret_YRCZCEKKcDxD6VnbtBGl",
    "created": "2025-01-09T14:07:10.134Z",
    "currency": "USD",
    "customer_id": "cu_1736431630",
    "customer": {
        "id": "cu_1736431630",
        "name": "John Doe",
        "email": "[email protected]",
        "phone": "999999999",
        "phone_country_code": "+1"
    },
    "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": "automatic",
    "payment_method": "card",
    "payment_method_data": {
        "card": {
            "last4": "1111",
            "card_type": null,
            "card_network": null,
            "card_issuer": null,
            "card_issuing_country": null,
            "card_isin": "411111",
            "card_extended_bin": null,
            "card_exp_month": "03",
            "card_exp_year": "2030",
            "card_holder_name": "joseph Doe",
            "payment_checks": {
                "cvc_check": "pass",
                "address_line1_check": "pass",
                "address_postal_code_check": "pass"
            },
            "authentication_data": null
        },
        "billing": null
    },
    "payment_token": null,
    "shipping": {
        "address": {
            "city": "San Fransico",
            "country": "US",
            "line1": "1467",
            "line2": "Harrison Street",
            "line3": "Harrison Street",
            "zip": "94122",
            "state": "California",
            "first_name": "PiX",
            "last_name": null
        },
        "phone": null,
        "email": null
    },
    "billing": {
        "address": {
            "city": "San",
            "country": "US",
            "line1": "1467",
            "line2": "Harrison Street",
            "line3": "Harrison Street",
            "zip": "94122",
            "state": "California",
            "first_name": "PiX",
            "last_name": "ss"
        },
        "phone": null,
        "email": "[email protected]"
    },
    "order_details": null,
    "email": "[email protected]",
    "name": "John Doe",
    "phone": "999999999",
    "return_url": "http://127.0.0.1:4040/",
    "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": null,
    "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": "pi_3QfMOBD5R7gDAGff0l6jmTHK",
    "frm_message": null,
    "metadata": {
        "udf1": "value1",
        "login_date": "2019-09-10T10:11:12Z",
        "new_customer": "true"
    },
    "connector_metadata": null,
    "feature_metadata": null,
    "reference_id": "pi_3QfMOBD5R7gDAGff0l6jmTHK",
    "payment_link": null,
    "profile_id": "pro_GhoiAnNpnyEAqAAbwULW",
    "surcharge_details": null,
    "attempt_count": 1,
    "merchant_decision": null,
    "merchant_connector_id": "mca_YhBV1Nr6PXdkkG7md9ro",
    "incremental_authorization_allowed": null,
    "authorization_count": null,
    "incremental_authorizations": null,
    "external_authentication_details": null,
    "external_3ds_authentication_attempted": false,
    "expires_on": "2025-01-09T14:22:10.134Z",
    "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": "pm_2aJAicSBjlanyP8w6jYQ",
    "payment_method_status": "active",
    "updated": "2025-01-09T14:15:56.696Z",
    "split_payments": null,
    "frm_metadata": null,
    "merchant_order_reference_id": null,
    "order_tax_amount": null,
    "connector_mandate_id": null
}

-> resend the webhook and when retrieved the payment status is expected to be succeeded

curl --location 'http://localhost:8080/payments/pay_bnl7rTJB6WUbfsQRTRU3' \
--header 'Accept: application/json' \
--header 'api-key:'
{
    "payment_id": "pay_bnl7rTJB6WUbfsQRTRU3",
    "merchant_id": "merchant_1736429319",
    "status": "succeeded",
    "amount": 100,
    "net_amount": 100,
    "shipping_cost": null,
    "amount_capturable": 0,
    "amount_received": 100,
    "connector": "stripe",
    "client_secret": "pay_bnl7rTJB6WUbfsQRTRU3_secret_YRCZCEKKcDxD6VnbtBGl",
    "created": "2025-01-09T14:07:10.134Z",
    "currency": "USD",
    "customer_id": "cu_1736431630",
    "customer": {
        "id": "cu_1736431630",
        "name": "John Doe",
        "email": "[email protected]",
        "phone": "999999999",
        "phone_country_code": "+1"
    },
    "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": "automatic",
    "payment_method": "card",
    "payment_method_data": {
        "card": {
            "last4": "1111",
            "card_type": null,
            "card_network": null,
            "card_issuer": null,
            "card_issuing_country": null,
            "card_isin": "411111",
            "card_extended_bin": null,
            "card_exp_month": "03",
            "card_exp_year": "2030",
            "card_holder_name": "joseph Doe",
            "payment_checks": {
                "cvc_check": "pass",
                "address_line1_check": "pass",
                "address_postal_code_check": "pass"
            },
            "authentication_data": null
        },
        "billing": null
    },
    "payment_token": null,
    "shipping": {
        "address": {
            "city": "San Fransico",
            "country": "US",
            "line1": "1467",
            "line2": "Harrison Street",
            "line3": "Harrison Street",
            "zip": "94122",
            "state": "California",
            "first_name": "PiX",
            "last_name": null
        },
        "phone": null,
        "email": null
    },
    "billing": {
        "address": {
            "city": "San",
            "country": "US",
            "line1": "1467",
            "line2": "Harrison Street",
            "line3": "Harrison Street",
            "zip": "94122",
            "state": "California",
            "first_name": "PiX",
            "last_name": "ss"
        },
        "phone": null,
        "email": "[email protected]"
    },
    "order_details": null,
    "email": "[email protected]",
    "name": "John Doe",
    "phone": "999999999",
    "return_url": "http://127.0.0.1:4040/",
    "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": null,
    "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": "pi_3QfMOBD5R7gDAGff0l6jmTHK",
    "frm_message": null,
    "metadata": {
        "udf1": "value1",
        "login_date": "2019-09-10T10:11:12Z",
        "new_customer": "true"
    },
    "connector_metadata": null,
    "feature_metadata": null,
    "reference_id": "pi_3QfMOBD5R7gDAGff0l6jmTHK",
    "payment_link": null,
    "profile_id": "pro_GhoiAnNpnyEAqAAbwULW",
    "surcharge_details": null,
    "attempt_count": 1,
    "merchant_decision": null,
    "merchant_connector_id": "mca_YhBV1Nr6PXdkkG7md9ro",
    "incremental_authorization_allowed": null,
    "authorization_count": null,
    "incremental_authorizations": null,
    "external_authentication_details": null,
    "external_3ds_authentication_attempted": false,
    "expires_on": "2025-01-09T14:22:10.134Z",
    "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": "pm_2aJAicSBjlanyP8w6jYQ",
    "payment_method_status": "active",
    "updated": "2025-01-09T14:21:04.293Z",
    "split_payments": null,
    "frm_metadata": null,
    "merchant_order_reference_id": null,
    "order_tax_amount": null,
    "connector_mandate_id": 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

@ShankarSinghC ShankarSinghC added A-core Area: Core flows C-refactor Category: Refactor A-refunds Area: Refund flows labels Jan 2, 2025
@ShankarSinghC ShankarSinghC self-assigned this Jan 2, 2025
@ShankarSinghC ShankarSinghC requested review from a team as code owners January 2, 2025 13:49
Copy link

semanticdiff-com bot commented Jan 2, 2025

@ShankarSinghC ShankarSinghC changed the title add support for relay refund incoming webhooks feat(router): add support for relay refund incoming webhooks Jan 2, 2025
@ShankarSinghC ShankarSinghC linked an issue Jan 2, 2025 that may be closed by this pull request
crates/router/src/core/webhooks/incoming.rs Outdated Show resolved Hide resolved
crates/router/src/core/webhooks/incoming.rs Outdated Show resolved Hide resolved
) -> impl Responder {
let flow = Flow::IncomingWebhookReceive;
let (merchant_id, connector_id_or_name) = path.into_inner();
let is_relay_webhook = true;
Copy link
Contributor

Choose a reason for hiding this comment

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

Move this to a const

Copy link
Member

Choose a reason for hiding this comment

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

Can we consider using an enum instead of a bool maybe?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Can I take this up in my next pr ?
I have a relay refactor pr, will address this in the same pr.
#6954

crates/router/src/routes/app.rs Show resolved Hide resolved
crates/router/src/routes/app.rs Outdated Show resolved Hide resolved
crates/router/src/core/webhooks/incoming.rs Outdated Show resolved Hide resolved
crates/router/src/core/webhooks/incoming.rs Outdated Show resolved Hide resolved
crates/router/src/core/webhooks/incoming.rs Outdated Show resolved Hide resolved
crates/diesel_models/src/query/relay.rs Outdated Show resolved Hide resolved
crates/diesel_models/src/query/relay.rs Show resolved Hide resolved
crates/router/src/core/webhooks/incoming.rs Outdated Show resolved Hide resolved
crates/router/src/core/webhooks/incoming.rs Outdated Show resolved Hide resolved
crates/router/src/core/webhooks/incoming.rs Outdated Show resolved Hide resolved
crates/router/src/core/webhooks/incoming.rs Outdated Show resolved Hide resolved
crates/router/src/core/webhooks/incoming.rs Outdated Show resolved Hide resolved
crates/router/src/routes/app.rs Outdated Show resolved Hide resolved
@hyperswitch-bot hyperswitch-bot bot added the M-database-changes Metadata: This PR involves database schema changes label Jan 7, 2025
crates/diesel_models/src/query/relay.rs Outdated Show resolved Hide resolved
crates/router/src/db/relay.rs Outdated Show resolved Hide resolved
impl RelayWebhooks {
pub fn server(state: AppState) -> Scope {
use api_models::webhooks as webhook_type;
web::scope("/webhooks/relay")
Copy link
Member

Choose a reason for hiding this comment

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

Have we confirmed that this doesn't affect the existing incoming webhooks flows, due to the possibly conflicting routes?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Yes, I have added the test cases for it

) -> impl Responder {
let flow = Flow::IncomingWebhookReceive;
let (merchant_id, connector_id_or_name) = path.into_inner();
let is_relay_webhook = true;
Copy link
Member

Choose a reason for hiding this comment

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

Can we consider using an enum instead of a bool maybe?

crates/router/src/routes/webhooks.rs Outdated Show resolved Hide resolved
crates/router/src/routes/webhooks.rs Outdated Show resolved Hide resolved
migrations/2025-01-07-105739_create_index_for_relay/up.sql Outdated Show resolved Hide resolved
@Gnanasundari24 Gnanasundari24 added this pull request to the merge queue Jan 10, 2025
Merged via the queue into main with commit d850f17 Jan 10, 2025
17 of 19 checks passed
@Gnanasundari24 Gnanasundari24 deleted the relay/incoming-webhook branch January 10, 2025 08:07
pixincreate added a commit that referenced this pull request Jan 10, 2025
…d-memory-cache

* 'main' of github.com:juspay/hyperswitch:
  feat(connector): [Novalnet] Add zero auth mandate (#6631)
  feat(router): add support for relay refund incoming webhooks (#6974)
  chore(version): 2025.01.10.0
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
A-core Area: Core flows A-refunds Area: Refund flows C-refactor Category: Refactor M-database-changes Metadata: This PR involves database schema changes
Projects
None yet
Development

Successfully merging this pull request may close these issues.

add support for relay refund incoming webhooks
4 participants