Skip to content

Conversation

NISHANTH1221
Copy link
Contributor

@NISHANTH1221 NISHANTH1221 commented Mar 7, 2025

Type of Change

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

Description

Context: In case of some billing connectors we dont get the enough data in the webhook itself to support creation of payment intent and payment attempt in our system. So previously we derived a flow named "AdditionalRevenuerecoveryDetails" in this PR:#7402 which name is now changed to "BillingConnectorPaymentSync". This flow is used to fetch payment details of the invoices from the billing connectors using an API call to that billing connector. In this pr we are calling the flow and getting the details which are needed to create payment intent and attempt in our system.

  1. Creates a connector integration in stripe billing that supports the API call.
  2. Call the flow in recovery_incoming.rs file and using that details further we are creating the payment intent and attempt and verifying them.

Additional Changes

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

Motivation and Context

Testing

  1. Go to stripe create a new webhook endpoint with a dummy url to get webhook secret key.
  2. create a payment processor stripe

curl --location 'http://localhost:8080/v2/connector-accounts' \
--header 'Content-Type: application/json' \
--header 'Accept: application/json' \
--header 'x-merchant-id: cloth_seller_mQRYaJduFokPeZ54W6bN' \
--header 'x-profile-id: pro_me6dnNKlhwuq32xhfjCA' \
--header 'Authorization: admin-api-key=test_admin' \
--header 'api-key: test_admin' \
--data '{
    "connector_type": "payment_processor",
    "connector_name": "stripe",
    "connector_account_details": {
        "auth_type": "HeaderKey",
        "api_key": "api-key 
},
    "payment_methods_enabled": [
        {
            "payment_method_type": "card_redirect",
            "payment_method_subtypes": [
                {
                    "payment_method_subtype": "card_redirect",
                    "payment_experience": "redirect_to_url",
                    "card_networks": null,
                    "accepted_currencies": null,
                    "accepted_countries": null,
                    "minimum_amount": 1,
                    "maximum_amount": 68607706,
                    "recurring_enabled": true,
                    "installment_payment_enabled": true
                }
            ]
        },
        {
            "payment_method_type": "card",
            "payment_method_subtypes": [
                {
                    "payment_method_subtype": "credit",
                    "payment_experience": null,
                    "card_networks": [
                        "Visa",
                        "Mastercard"
                    ],
                    "accepted_currencies": null,
                    "accepted_countries": null,
                    "minimum_amount": -1,
                    "maximum_amount": 68607706,
                    "recurring_enabled": true,
                    "installment_payment_enabled": true
                },
                {
                    "payment_method_subtype": "debit",
                    "payment_experience": null,
                    "card_networks": [
                        "Visa",
                        "Mastercard"
                    ],
                    "accepted_currencies": null,
                    "accepted_countries": null,
                    "minimum_amount": -1,
                    "maximum_amount": 68607706,
                    "recurring_enabled": true,
                    "installment_payment_enabled": true
                }
            ]
        },
        {
            "payment_method_type": "wallet",
            "payment_method_subtypes": [
                {
                    "payment_method_subtype": "google_pay",
                    "payment_experience": null,
                    "card_networks": null,
                    "accepted_currencies": null,
                    "accepted_countries": null,
                    "minimum_amount": -1,
                    "maximum_amount": 68607706,
                    "recurring_enabled": true,
                    "installment_payment_enabled": true
                },
                {
                    "payment_method_subtype": "apple_pay",
                    "payment_experience": null,
                    "card_networks": null,
                    "accepted_currencies": null,
                    "accepted_countries": null,
                    "minimum_amount": -1,
                    "maximum_amount": 68607706,
                    "recurring_enabled": true,
                    "installment_payment_enabled": true
                },
                {
                    "payment_method_subtype": "we_chat_pay",
                    "payment_experience": null,
                    "card_networks": null,
                    "accepted_currencies": null,
                    "accepted_countries": null,
                    "minimum_amount": -1,
                    "maximum_amount": 68607706,
                    "recurring_enabled": true,
                    "installment_payment_enabled": true
                },
                {
                    "payment_method_subtype": "ali_pay",
                    "payment_experience": null,
                    "card_networks": null,
                    "accepted_currencies": null,
                    "accepted_countries": null,
                    "minimum_amount": -1,
                    "maximum_amount": 68607706,
                    "recurring_enabled": true,
                    "installment_payment_enabled": true
                },
                {
                    "payment_method_subtype": "paypal",
                    "payment_experience": null,
                    "card_networks": null,
                    "accepted_currencies": null,
                    "accepted_countries": null,
                    "minimum_amount": -1,
                    "maximum_amount": 68607706,
                    "recurring_enabled": true,
                    "installment_payment_enabled": true
                },
                {
                    "payment_method_subtype": "mb_way",
                    "payment_experience": null,
                    "card_networks": null,
                    "accepted_currencies": null,
                    "accepted_countries": null,
                    "minimum_amount": -1,
                    "maximum_amount": 68607706,
                    "recurring_enabled": true,
                    "installment_payment_enabled": true
                }
            ]
        },
        {
            "payment_method_type": "pay_later",
            "payment_method_subtypes": [
                {
                    "payment_method_subtype": "klarna",
                    "payment_experience": "redirect_to_url",
                    "card_networks": null,
                    "accepted_currencies": null,
                    "accepted_countries": null,
                    "minimum_amount": -1,
                    "maximum_amount": 68607706,
                    "recurring_enabled": true,
                    "installment_payment_enabled": true
                },
                {
                    "payment_method_subtype": "affirm",
                    "payment_experience": "redirect_to_url",
                    "card_networks": null,
                    "accepted_currencies": null,
                    "accepted_countries": null,
                    "minimum_amount": -1,
                    "maximum_amount": 68607706,
                    "recurring_enabled": true,
                    "installment_payment_enabled": true
                },
                {
                    "payment_method_subtype": "afterpay_clearpay",
                    "payment_experience": "redirect_to_url",
                    "card_networks": null,
                    "accepted_currencies": null,
                    "accepted_countries": null,
                    "minimum_amount": -1,
                    "maximum_amount": 68607706,
                    "recurring_enabled": true,
                    "installment_payment_enabled": true
                },
                {
                    "payment_method_subtype": "walley",
                    "payment_experience": "redirect_to_url",
                    "card_networks": null,
                    "accepted_currencies": null,
                    "accepted_countries": null,
                    "minimum_amount": -1,
                    "maximum_amount": 68607706,
                    "recurring_enabled": true,
                    "installment_payment_enabled": true
                }
            ]
        },
        {
            "payment_method_type": "bank_redirect",
            "payment_method_subtypes": [
                {
                    "payment_method_subtype": "giropay",
                    "payment_experience": "redirect_to_url",
                    "card_networks": null,
                    "accepted_currencies": null,
                    "accepted_countries": null,
                    "minimum_amount": -1,
                    "maximum_amount": 68607706,
                    "recurring_enabled": true,
                    "installment_payment_enabled": true
                },
                {
                    "payment_method_subtype": "ideal",
                    "payment_experience": "redirect_to_url",
                    "card_networks": null,
                    "accepted_currencies": null,
                    "accepted_countries": null,
                    "minimum_amount": -1,
                    "maximum_amount": 68607706,
                    "recurring_enabled": true,
                    "installment_payment_enabled": true
                },
                {
                    "payment_method_subtype": "eps",
                    "payment_experience": "redirect_to_url",
                    "card_networks": null,
                    "accepted_currencies": null,
                    "accepted_countries": null,
                    "minimum_amount": -1,
                    "maximum_amount": 68607706,
                    "recurring_enabled": true,
                    "installment_payment_enabled": true
                },
                {
                    "payment_method_subtype": "bancontact_card",
                    "payment_experience": "redirect_to_url",
                    "card_networks": null,
                    "accepted_currencies": null,
                    "accepted_countries": null,
                    "minimum_amount": -1,
                    "maximum_amount": 68607706,
                    "recurring_enabled": true,
                    "installment_payment_enabled": true
                },
                {
                    "payment_method_subtype": "przelewy24",
                    "payment_experience": "redirect_to_url",
                    "card_networks": null,
                    "accepted_currencies": null,
                    "accepted_countries": null,
                    "minimum_amount": -1,
                    "maximum_amount": 68607706,
                    "recurring_enabled": true,
                    "installment_payment_enabled": true
                },
                {
                    "payment_method_subtype": "sofort",
                    "payment_experience": "redirect_to_url",
                    "card_networks": null,
                    "accepted_currencies": null,
                    "accepted_countries": null,
                    "minimum_amount": -1,
                    "maximum_amount": 68607706,
                    "recurring_enabled": true,
                    "installment_payment_enabled": true
                },
                {
                    "payment_method_subtype": "blik",
                    "payment_experience": "redirect_to_url",
                    "card_networks": null,
                    "accepted_currencies": null,
                    "accepted_countries": null,
                    "minimum_amount": -1,
                    "maximum_amount": 68607706,
                    "recurring_enabled": true,
                    "installment_payment_enabled": true
                },
                {
                    "payment_method_subtype": "trustly",
                    "payment_experience": "redirect_to_url",
                    "card_networks": null,
                    "accepted_currencies": null,
                    "accepted_countries": null,
                    "minimum_amount": -1,
                    "maximum_amount": 68607706,
                    "recurring_enabled": true,
                    "installment_payment_enabled": true
                },
                {
                    "payment_method_subtype": "online_banking_finland",
                    "payment_experience": "redirect_to_url",
                    "card_networks": null,
                    "accepted_currencies": null,
                    "accepted_countries": null,
                    "minimum_amount": -1,
                    "maximum_amount": 68607706,
                    "recurring_enabled": true,
                    "installment_payment_enabled": true
                },
                {
                    "payment_method_subtype": "online_banking_poland",
                    "payment_experience": "redirect_to_url",
                    "card_networks": null,
                    "accepted_currencies": null,
                    "accepted_countries": null,
                    "minimum_amount": -1,
                    "maximum_amount": 68607706,
                    "recurring_enabled": true,
                    "installment_payment_enabled": true
                }
            ]
        },
        {
            "payment_method_type": "bank_transfer",
            "payment_method_subtypes": [
                {
                    "payment_method_subtype": "ach",
                    "payment_experience": "redirect_to_url",
                    "card_networks": null,
                    "accepted_currencies": null,
                    "accepted_countries": null,
                    "minimum_amount": -1,
                    "maximum_amount": 68607706,
                    "recurring_enabled": true,
                    "installment_payment_enabled": true
                },
                {
                    "payment_method_subtype": "sepa",
                    "payment_experience": "redirect_to_url",
                    "card_networks": null,
                    "accepted_currencies": null,
                    "accepted_countries": null,
                    "minimum_amount": -1,
                    "maximum_amount": 68607706,
                    "recurring_enabled": true,
                    "installment_payment_enabled": true
                },
                {
                    "payment_method_subtype": "bacs",
                    "payment_experience": "redirect_to_url",
                    "card_networks": null,
                    "accepted_currencies": null,
                    "accepted_countries": null,
                    "minimum_amount": -1,
                    "maximum_amount": 68607706,
                    "recurring_enabled": true,
                    "installment_payment_enabled": true
                }
            ]
        },
        {
            "payment_method_type": "bank_debit",
            "payment_method_subtypes": [
                {
                    "payment_method_subtype": "ach",
                    "payment_experience": null,
                    "card_networks": null,
                    "accepted_currencies": null,
                    "accepted_countries": null,
                    "minimum_amount": -1,
                    "maximum_amount": 68607706,
                    "recurring_enabled": true,
                    "installment_payment_enabled": true
                },
                {
                    "payment_method_subtype": "sepa",
                    "payment_experience": null,
                    "card_networks": null,
                    "accepted_currencies": null,
                    "accepted_countries": null,
                    "minimum_amount": -1,
                    "maximum_amount": 68607706,
                    "recurring_enabled": true,
                    "installment_payment_enabled": true
                },
                {
                    "payment_method_subtype": "bacs",
                    "payment_experience": null,
                    "card_networks": null,
                    "accepted_currencies": null,
                    "accepted_countries": null,
                    "minimum_amount": -1,
                    "maximum_amount": 68607706,
                    "recurring_enabled": true,
                    "installment_payment_enabled": true
                },
                {
                    "payment_method_subtype": "becs",
                    "payment_experience": null,
                    "card_networks": null,
                    "accepted_currencies": null,
                    "accepted_countries": null,
                    "minimum_amount": -1,
                    "maximum_amount": 68607706,
                    "recurring_enabled": true,
                    "installment_payment_enabled": true
                }
            ]
        }
    ],
    "metadata": {
        "status_url": "https://2753-2401-4900-1cb8-2ff9-24dd-1ccf-ed12-b464.in.ngrok.io/webhooks/merchant_1678699058/globalpay",
        "account_name": "transaction_processing",
        "pricing_type": "fixed_price",
        "acquirer_bin": "438309",
        "acquirer_merchant_id": "00002000000"
    },
    "frm_configs": null,
    "connector_webhook_details": {
        "merchant_secret": ""
    },
    "profile_id": "pro_me6dnNKlhwuq32xhfjCA"
}'

change the profile id and other feilds while creating you own one
3. copy the mca id of stripe and paste it in the billing mca curl in feature metadata


curl --location 'http://localhost:8080/v2/connector-accounts' \
--header 'Content-Type: application/json' \
--header 'Accept: application/json' \
--header 'x-merchant-id: cloth_seller_mQRYaJduFokPeZ54W6bN' \
--header 'x-profile-id: pro_me6dnNKlhwuq32xhfjCA' \
--header 'Authorization: admin-api-key=test_admin' \
--header 'api-key: test_admin' \
--data '{
    "connector_type": "billing_processor",
    "connector_name": "stripebilling",
    "connector_account_details": {
        "auth_type": "HeaderKey",
        "api_key": "{your api key}"
    },
    "payment_methods_enabled": [
        {
            "payment_method_type": "card",
            "payment_method_subtypes": [
                {
                    "payment_method_subtype": "credit",
                    "payment_experience": null,
                    "card_networks": [
                        "Visa",
                        "Mastercard"
                    ],
                    "accepted_currencies": null,
                    "accepted_countries": null,
                    "minimum_amount": -1,
                    "maximum_amount": 68607706,
                    "recurring_enabled": true,
                    "installment_payment_enabled": true
                },
                {
                    "payment_method_subtype": "debit",
                    "payment_experience": null,
                    "card_networks": [
                        "Visa",
                        "Mastercard"
                    ],
                    "accepted_currencies": null,
                    "accepted_countries": null,
                    "minimum_amount": -1,
                    "maximum_amount": 68607706,
                    "recurring_enabled": true,
                    "installment_payment_enabled": true
                }
            ]
        }
    ],
    "metadata": {
        "status_url": "https://2753-2401-4900-1cb8-2ff9-24dd-1ccf-ed12-b464.in.ngrok.io/webhooks/merchant_1678699058/globalpay",
        "account_name": "transaction_processing",
        "pricing_type": "fixed_price",
        "acquirer_bin": "438309",
        "acquirer_merchant_id": "00002000000"
    },
    "frm_configs": null,
    "feature_metadata" : {
        "revenue_recovery":{
            "max_retry_count" : 16,
            "billing_connector_retry_threshold": 2,
            "billing_account_reference": {
                "{your stripe mca id here}": "stripebilling"
            }
        }
    },
    "connector_webhook_details": {
        "merchant_secret": "{webhook secret you have copied here}"
    },
    "profile_id": "pro_me6dnNKlhwuq32xhfjCA"
}'

  1. copy the mca id, profile id and merchant id to construct the endpoint of the webhook.
  2. install ngrok and run the service it will give you a https url for your local host port.
  3. copy the https url of ngrok
  4. construct the webhook endpoint : url/v2/webhooks/merchant_id/profile_id/billing_mca_id
  5. paste this endpoint in the place of dummy url you have used to create endpoint in stripe dashboard
  6. now create a test subscription use this card "4000 0000 0000 0341" while creating a test subscription and the billing day should start from the next day. If you are creating a test subscription today billing date should start from tommorow.
  7. now move the clock past one month.
  8. no observe the payment intent table and payment attempt table in db and verify those details with ones we are getting.
    Images of the logs:
Screenshot 2025-03-11 at 5 52 53 PM Screenshot 2025-03-11 at 5 53 10 PM Screenshot 2025-03-11 at 5 53 21 PM Screenshot 2025-03-11 at 5 54 32 PM Screenshot 2025-03-10 at 4 52 08 PM Screenshot 2025-03-10 at 4 52 20 PM

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

Nishanth Challa and others added 30 commits February 9, 2025 12:36
router_request_types::revenue_recovery::RevenueRecoveryRecordBackRequest,
router_response_types::revenue_recovery::RevenueRecoveryRecordBackResponse,
types::RevenueRecoveryRecordBackRouterData,
router_flow_types::revenue_recovery::{
Copy link
Member

Choose a reason for hiding this comment

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

Suggested change
router_flow_types::revenue_recovery::{
router_flow_types::revenue_recovery

@NISHANTH1221 NISHANTH1221 requested a review from jarnura March 26, 2025 16:23
@@ -71,10 +71,10 @@ pub use self::fraud_check_v2::*;
pub use self::payouts::*;
#[cfg(feature = "payouts")]
pub use self::payouts_v2::*;
pub use self::{payments::*, refunds::*};
pub use self::{payments::*, refunds::*, revenue_recovery::*};
Copy link
Member

Choose a reason for hiding this comment

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

Suggested change
pub use self::{payments::*, refunds::*, revenue_recovery::*};
pub use self::{payments::*, refunds::*, revenue_recovery};

errors::api_error_response, revenue_recovery, router_data_v2::flow_common_types,
router_flow_types, router_request_types::revenue_recovery as revenue_recovery_request,
router_response_types::revenue_recovery as revenue_recovery_response,
types::AdditionalRevenueRecoveryDetailsRouterData,
Copy link
Member

Choose a reason for hiding this comment

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

Suggested change
types::AdditionalRevenueRecoveryDetailsRouterData,
types,

router_response_types::revenue_recovery as revenue_recovery_response,
types::AdditionalRevenueRecoveryDetailsRouterData,
};
use hyperswitch_interfaces::{api::RevenueRecovery, webhooks as interface_webhooks};
Copy link
Member

Choose a reason for hiding this comment

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

Suggested change
use hyperswitch_interfaces::{api::RevenueRecovery, webhooks as interface_webhooks};
use hyperswitch_interfaces::{api, webhooks as interface_webhooks};

jarnura
jarnura previously approved these changes Mar 27, 2025
router_flow_types::revenue_recovery::{
GetAdditionalRevenueRecoveryDetails, RecoveryRecordBack,
},
router_flow_types::revenue_recovery::{BillingConnectorPaymentsSync, RecoveryRecordBack},
Copy link
Member

Choose a reason for hiding this comment

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

Suggested change
router_flow_types::revenue_recovery::{BillingConnectorPaymentsSync, RecoveryRecordBack},
router_flow_types::revenue_recovery,

Copy link
Member

Choose a reason for hiding this comment

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

change for other imports too

srujanchikke
srujanchikke previously approved these changes Mar 27, 2025
@NISHANTH1221 NISHANTH1221 dismissed stale reviews from srujanchikke and jarnura via dfe7a20 March 27, 2025 16:55
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
A-connector-compatibility Area: Connector compatibility A-connector-integration Area: Connector integration api-v2 M-api-contract-changes Metadata: This PR involves API contract changes
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants