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 proxy-confirm-intent api for payments in v2 flow #7215

Open
wants to merge 35 commits into
base: main
Choose a base branch
from

Conversation

AdityaKumaar21
Copy link

@AdityaKumaar21 AdityaKumaar21 commented Feb 7, 2025

Type of Change

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

Description

Developed the proxy-confirm-intent API, specifically designed for Merchant-Initiated Transactions (MIT) payments. This is a generic and reusable API that facilitates MIT payment confirmations.
Its working is similar to confirm-intent api but in proxy flow we will be not having customer's details, rather we need mca_id and psp_token in order to confirm intent.
This API will help in PCR as it totally depends on recurring payments(MIT transaction) so, it needs proxy-confirm-intent.

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?

cURL:-

curl --location 'http://localhost:8080/v2/payments/12345_pay_01953c48fdf57f5394faf843bf06187e/proxy-confirm-intent' \
--header 'x-profile-id: pro_73hfy7wgWWd7ujLBjvrJ' \
--header 'x-client-secret: 12345_pay_01953c48fdf57f5394faf843bf06187e_secret_01953c48fdff7da3983c22d6b08c811d' \
--header 'Content-Type: application/json' \
--header 'api-key: dev_bPve88AB4DOwPb7YWfDFFqsddBaC*************************************' \
--data '{
    "amount":{
        "order_amount":100,
        "currency":"USD"
    },
    "recurring_details":{
        "processor_payment_token":"card_1QqvxW06IkU6uKNZuPtSKnJ5"
    },
    "connector":"stripe",
    "merchant_connector_id":"mca_lXRIeVR2IPZXA2hpSSpO"
}'

edited create_intent cURL(added feature_metadata field):-

{
    "amount_details": {
        "order_amount": 100,
        "currency": "USD"
    },
    "capture_method":"automatic",
    "authentication_type": "no_three_ds",
    "billing": {
        "address": {
            "first_name": "John",
            "last_name": "Dough"
        },
        "email": "[email protected]"
    },
    "shipping": {
        "address": {
            "first_name": "John",
            "last_name": "Dough",
            "city": "Karwar",
            "zip": "581301",
            "state": "Karnataka"
        },
        "email": "[email protected]"
    },
    "feature_metadata":{
        "payment_revenue_recovery_metadata":{
            "total_retry_count":3,
            "payment_connector_transmission":"ConnectorCallSucceeded",
            "billing_connector_id":"{{mca_id}}",
            "active_attempt_payment_connector_id":"{{mca_id}}",
            "billing_connector_payment_details":{
                "payment_processor_token":"card_1QqvxW06IkU6uKNZuPtSKnJ5",
                "connector_customer_id":"cus_RkQYGuTepCnglS"
            },
            "payment_method_type": "card",
            "payment_method_subtype": "credit"
        }
    }
}

Response:-

{
    "id": "12345_pay_01953c48fdf57f5394faf843bf06187e",
    "status": "succeeded",
    "amount": {
        "order_amount": 1000,
        "currency": "USD",
        "shipping_cost": null,
        "order_tax_amount": null,
        "external_tax_calculation": "skip",
        "surcharge_calculation": "skip",
        "surcharge_amount": null,
        "tax_on_surcharge": null,
        "net_amount": 1000,
        "amount_to_capture": null,
        "amount_capturable": 0,
        "amount_captured": 1000
    },
    "customer_id": null,
    "connector": "stripe",
    "client_secret": "12345_pay_01953c48fdf57f5394faf843bf06187e_secret_01953c48fdff7da3983c22d6b08c811d",
    "created": "2025-02-25T08:46:11.456Z",
    "payment_method_data": {
        "billing": null
    },
    "payment_method_type": "card",
    "payment_method_subtype": "debit",
    "next_action": null,
    "connector_transaction_id": "pi_3QwJmO06IkU6uKNZ0QVgMCLQ",
    "connector_reference_id": null,
    "connector_token_details": {
        "token": "card_1QqvxW06IkU6uKNZuPtSKnJ5"
    },
    "merchant_connector_id": "mca_lXRIeVR2IPZXA2hpSSpO",
    "browser_info": null,
    "error": null,
    "authentication_type": "no_three_ds",
    "applied_authentication_type": "no_three_ds"
}

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

@AdityaKumaar21 AdityaKumaar21 requested review from a team as code owners February 7, 2025 11:10
@AdityaKumaar21 AdityaKumaar21 self-assigned this Feb 12, 2025
@hyperswitch-bot hyperswitch-bot bot added the M-api-contract-changes Metadata: This PR involves API contract changes label Feb 13, 2025
@hyperswitch-bot hyperswitch-bot bot removed the M-api-contract-changes Metadata: This PR involves API contract changes label Feb 16, 2025
@@ -5272,6 +5299,73 @@ pub struct PaymentsConfirmIntentResponse {
pub error: Option<ErrorDetails>,
}

#[cfg(feature = "v2")]
#[derive(Debug, serde::Serialize, ToSchema)]
pub struct ProxyPaymentsIntentResponse {
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 use payments response here instead of creating a new response?

Copy link
Author

Choose a reason for hiding this comment

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

applied_authentication_type this is a required field in confirmIntentResponse and is not relevant to proxyResponse

Copy link
Member

Choose a reason for hiding this comment

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

Yes still, let's use the same response, if there are any changes make those fields optional

@@ -591,6 +627,7 @@ where
pub payment_attempt: PaymentAttempt,
pub payment_method_data: Option<payment_method_data::PaymentMethodData>,
pub payment_address: payment_address::PaymentAddress,
pub mandate_data: Option<api_models::payments::MandateIds>,
Copy link
Member

Choose a reason for hiding this comment

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

we should not be using types from the api models here
cc: @Aprabhat19

Copy link
Author

Choose a reason for hiding this comment

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

should i create this MandateIDs in hyperswitch_domain_model because it is not present there

Copy link
Member

Choose a reason for hiding this comment

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

Yes please, create a struct in domain models for this.

@@ -215,11 +215,14 @@ impl TaxDetails {
/// Get the tax amount
/// If default tax is present, return the default tax amount
/// If default tax is not present, return the tax amount based on the payment method if it matches the provided payment method type
pub fn get_tax_amount(&self, payment_method: PaymentMethodType) -> Option<MinorUnit> {
pub fn get_tax_amount(&self, payment_method: Option<PaymentMethodType>) -> Option<MinorUnit> {
Copy link
Member

Choose a reason for hiding this comment

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

change the field name to payment_method_type

Copy link
Author

Choose a reason for hiding this comment

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

there is a subfield in PaymentMethodType with same name of payment_method_type and this subfield is also being used in this function

customer_acceptance: None,
profile_id: payment_intent.profile_id.clone(),
organization_id: payment_intent.organization_id.clone(),
payment_method_type: storage_enums::PaymentMethod::Card,
Copy link
Member

Choose a reason for hiding this comment

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

we cannot set this value as card, set this to Mandate
cc: @Aprabhat19

Copy link
Author

@AdityaKumaar21 AdityaKumaar21 Feb 24, 2025

Choose a reason for hiding this comment

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

bro for our use case we are not dealing anything other than cards for so, i will create another pr for generic use case because it requires a lot of changes in the codebase

payment_method_type: storage_enums::PaymentMethod::Card,
payment_method_id: None,
connector_payment_id: None,
payment_method_subtype: storage_enums::PaymentMethodType::Credit,
Copy link
Member

Choose a reason for hiding this comment

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

same here, use mandate / connector_token variant
cc: @Aprabhat19

@AdityaKumaar21 AdityaKumaar21 requested review from a team as code owners February 24, 2025 17:47
@Narayanbhat166 Narayanbhat166 removed request for a team February 25, 2025 06:42
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.

2 participants