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(payments_v2): implement create and confirm intent flow #7106

Merged
merged 22 commits into from
Feb 5, 2025
Merged
Show file tree
Hide file tree
Changes from 3 commits
Commits
Show all changes
22 commits
Select commit Hold shift + click to select a range
727253a
feat(payments_v2): implement create and confirm setup intent flow
SanchithHegde Jan 24, 2025
4ce2685
chore: remove redundant log line in `handle_response()`
SanchithHegde Jan 24, 2025
67fa8f7
refactor(hyperswitch_domain_models): address `clippy::large_enum_vari…
SanchithHegde Jan 24, 2025
ecc7bdf
Merge branch 'main' into setup-intent-v2
SanchithHegde Jan 27, 2025
8942c15
refactor(api_models): rename `PaymentsSetupIntentRequest` to `Payment…
SanchithHegde Jan 27, 2025
dcf5948
feat(api_models): copy over doc comments for `PaymentsRequest` v2 stuct
SanchithHegde Jan 27, 2025
a7469d8
refactor(payments_v2): rename `payments_create_and_confirm_setup_inte…
SanchithHegde Jan 27, 2025
c49e4f5
refactor(payments_v2): remove `GenerateResponse<PaymentsResponse>` im…
SanchithHegde Jan 28, 2025
1e40714
refactor(payments_v2): extract JSON response handling to a separate f…
SanchithHegde Jan 28, 2025
7e70079
refactor(payments_v2): add `connector_token_details` field to `Paymen…
SanchithHegde Jan 28, 2025
01d3c80
refactor(payments_v2): return `PaymentsResponse` from `payments_creat…
SanchithHegde Jan 28, 2025
ae04358
refactor(payments_v2): call authorize or setup intent flow based on o…
SanchithHegde Jan 28, 2025
267b0a5
docs(openapi): include `payments_create_and_confirm_intent()` route i…
SanchithHegde Jan 28, 2025
7c88e0f
docs(mintlify): include `payments_create_and_confirm_intent()` route …
SanchithHegde Jan 28, 2025
a5dce07
Merge branch 'main' into setup-intent-v2
SanchithHegde Jan 28, 2025
2b8ca14
refactor(payments_v2): remove unnecessary mutable binding of variable
SanchithHegde Jan 28, 2025
a6496a2
refactor(api_models): update doc comments of `ConnectorTokenDetails`
SanchithHegde Jan 30, 2025
025454c
refactor(payments_v2): rename `connector_mandate_detail` to `connecto…
SanchithHegde Jan 30, 2025
25ec17c
refactor(v2_migrations): rename `2024-10-08-081847_drop_v1_columns` d…
SanchithHegde Jan 30, 2025
2e6478b
Merge branch 'main' into setup-intent-v2
SanchithHegde Jan 30, 2025
b34b6a5
Merge branch 'main' into setup-intent-v2
SanchithHegde Feb 4, 2025
86b0ab9
refactor(hyperswitch_domain_models): avoid absolute import for constants
SanchithHegde Feb 5, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
19 changes: 18 additions & 1 deletion crates/api_models/src/events/payment.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,8 @@ use common_utils::events::{ApiEventMetric, ApiEventsType};
#[cfg(feature = "v2")]
use super::{
PaymentStartRedirectionRequest, PaymentsConfirmIntentResponse, PaymentsCreateIntentRequest,
PaymentsGetIntentRequest, PaymentsIntentResponse,
PaymentsGetIntentRequest, PaymentsIntentResponse, PaymentsSetupIntentRequest,
SetupIntentWrapperResponse,
};
#[cfg(all(
any(feature = "v2", feature = "v1"),
Expand Down Expand Up @@ -150,6 +151,22 @@ impl ApiEventMetric for PaymentsCreateIntentRequest {
}
}

#[cfg(feature = "v2")]
impl ApiEventMetric for PaymentsSetupIntentRequest {
fn get_api_event_type(&self) -> Option<ApiEventsType> {
None
}
}

#[cfg(feature = "v2")]
impl ApiEventMetric for SetupIntentWrapperResponse {
fn get_api_event_type(&self) -> Option<ApiEventsType> {
Some(ApiEventsType::Payment {
payment_id: self.confirm_intent_response.id.clone(),
})
}
}

#[cfg(feature = "v2")]
impl ApiEventMetric for PaymentsGetIntentRequest {
fn get_api_event_type(&self) -> Option<ApiEventsType> {
Expand Down
96 changes: 96 additions & 0 deletions crates/api_models/src/payments.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4784,6 +4784,102 @@ pub struct PaymentsConfirmIntentRequest {
pub browser_info: Option<common_utils::types::BrowserInformation>,
}

// This struct contains the union of fields in `PaymentsCreateIntentRequest` and
// `PaymentsConfirmIntentRequest`
#[derive(Debug, serde::Serialize, serde::Deserialize, Clone)]
#[serde(deny_unknown_fields)]
#[cfg(feature = "v2")]
pub struct PaymentsSetupIntentRequest {
pub amount_details: AmountDetails,
pub merchant_reference_id: Option<id_type::PaymentReferenceId>,
pub routing_algorithm_id: Option<id_type::RoutingId>,
pub capture_method: Option<api_enums::CaptureMethod>,
pub authentication_type: Option<api_enums::AuthenticationType>,
pub billing: Option<Address>,
pub shipping: Option<Address>,
pub customer_id: Option<id_type::GlobalCustomerId>,
pub customer_present: Option<common_enums::PresenceOfCustomerDuringPayment>,
pub description: Option<common_utils::types::Description>,
pub return_url: Option<common_utils::types::Url>,
pub setup_future_usage: Option<api_enums::FutureUsage>,
pub apply_mit_exemption: Option<common_enums::MitExemptionRequest>,
pub statement_descriptor: Option<common_utils::types::StatementDescriptor>,
pub order_details: Option<Vec<OrderDetailsWithAmount>>,
pub allowed_payment_method_types: Option<Vec<api_enums::PaymentMethodType>>,
pub metadata: Option<pii::SecretSerdeValue>,
pub connector_metadata: Option<ConnectorMetadata>,
pub feature_metadata: Option<FeatureMetadata>,
pub payment_link_enabled: Option<common_enums::EnablePaymentLinkRequest>,
pub payment_link_config: Option<admin::PaymentLinkConfigRequest>,
pub request_incremental_authorization: Option<common_enums::RequestIncrementalAuthorization>,
pub session_expiry: Option<u32>,
pub frm_metadata: Option<pii::SecretSerdeValue>,
pub request_external_three_ds_authentication:
Option<common_enums::External3dsAuthenticationRequest>,
pub payment_method_data: PaymentMethodDataRequest,
pub payment_method_type: api_enums::PaymentMethod,
pub payment_method_subtype: api_enums::PaymentMethodType,
pub customer_acceptance: Option<CustomerAcceptance>,
pub browser_info: Option<common_utils::types::BrowserInformation>,
}

#[cfg(feature = "v2")]
impl From<&PaymentsSetupIntentRequest> for PaymentsCreateIntentRequest {
fn from(request: &PaymentsSetupIntentRequest) -> Self {
Self {
amount_details: request.amount_details.clone(),
merchant_reference_id: request.merchant_reference_id.clone(),
routing_algorithm_id: request.routing_algorithm_id.clone(),
capture_method: request.capture_method,
authentication_type: request.authentication_type,
billing: request.billing.clone(),
shipping: request.shipping.clone(),
customer_id: request.customer_id.clone(),
customer_present: request.customer_present.clone(),
description: request.description.clone(),
return_url: request.return_url.clone(),
setup_future_usage: request.setup_future_usage,
apply_mit_exemption: request.apply_mit_exemption.clone(),
statement_descriptor: request.statement_descriptor.clone(),
order_details: request.order_details.clone(),
allowed_payment_method_types: request.allowed_payment_method_types.clone(),
metadata: request.metadata.clone(),
connector_metadata: request.connector_metadata.clone(),
feature_metadata: request.feature_metadata.clone(),
payment_link_enabled: request.payment_link_enabled.clone(),
payment_link_config: request.payment_link_config.clone(),
request_incremental_authorization: request.request_incremental_authorization,
session_expiry: request.session_expiry,
frm_metadata: request.frm_metadata.clone(),
request_external_three_ds_authentication: request
.request_external_three_ds_authentication
.clone(),
}
}
}

#[cfg(feature = "v2")]
impl From<&PaymentsSetupIntentRequest> for PaymentsConfirmIntentRequest {
fn from(request: &PaymentsSetupIntentRequest) -> Self {
Self {
return_url: request.return_url.clone(),
payment_method_data: request.payment_method_data.clone(),
payment_method_type: request.payment_method_type,
payment_method_subtype: request.payment_method_subtype,
shipping: request.shipping.clone(),
customer_acceptance: request.customer_acceptance.clone(),
browser_info: request.browser_info.clone(),
}
}
}

#[cfg(feature = "v2")]
#[derive(Debug, serde::Serialize)]
pub struct SetupIntentWrapperResponse {
pub confirm_intent_response: PaymentsConfirmIntentResponse,
pub connector_mandate_reference_id: Option<ConnectorMandateReferenceId>,
}

// Serialize is implemented because, this will be serialized in the api events.
// Usually request types should not have serialize implemented.
//
Expand Down
1 change: 1 addition & 0 deletions crates/diesel_models/src/payment_attempt.rs
Original file line number Diff line number Diff line change
Expand Up @@ -791,6 +791,7 @@ pub struct PaymentAttemptUpdateInternal {
// client_version: Option<String>,
// customer_acceptance: Option<pii::SecretSerdeValue>,
// card_network: Option<String>,
pub connector_mandate_detail: Option<ConnectorMandateReferenceId>,
SanchithHegde marked this conversation as resolved.
Show resolved Hide resolved
}

#[cfg(feature = "v1")]
Expand Down
83 changes: 49 additions & 34 deletions crates/hyperswitch_domain_models/src/payments/payment_attempt.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1405,6 +1405,18 @@ impl PaymentAttemptUpdate {
}
}

#[cfg(feature = "v2")]
#[derive(Debug, Clone, Serialize)]
pub struct ConfirmIntentResponseUpdate {
jarnura marked this conversation as resolved.
Show resolved Hide resolved
pub status: storage_enums::AttemptStatus,
pub connector_payment_id: Option<String>,
pub updated_by: String,
pub redirection_data: Option<router_response_types::RedirectForm>,
pub connector_metadata: Option<pii::SecretSerdeValue>,
pub amount_capturable: Option<MinorUnit>,
pub connector_mandate_detail: Option<ConnectorMandateReferenceId>,
}

#[cfg(feature = "v2")]
#[derive(Debug, Clone, Serialize)]
pub enum PaymentAttemptUpdate {
Expand All @@ -1416,14 +1428,7 @@ pub enum PaymentAttemptUpdate {
merchant_connector_id: id_type::MerchantConnectorAccountId,
},
/// Update the payment attempt on confirming the intent, after calling the connector on success response
ConfirmIntentResponse {
status: storage_enums::AttemptStatus,
connector_payment_id: Option<String>,
updated_by: String,
redirection_data: Option<router_response_types::RedirectForm>,
connector_metadata: Option<pii::SecretSerdeValue>,
amount_capturable: Option<MinorUnit>,
},
ConfirmIntentResponse(Box<ConfirmIntentResponseUpdate>),
/// Update the payment attempt after force syncing with the connector
SyncUpdate {
status: storage_enums::AttemptStatus,
Expand Down Expand Up @@ -2083,6 +2088,7 @@ impl From<PaymentAttemptUpdate> for diesel_models::PaymentAttemptUpdateInternal
connector_metadata: None,
amount_capturable: None,
amount_to_capture: None,
connector_mandate_detail: None,
},
PaymentAttemptUpdate::ErrorUpdate {
status,
Expand All @@ -2107,33 +2113,39 @@ impl From<PaymentAttemptUpdate> for diesel_models::PaymentAttemptUpdateInternal
connector_metadata: None,
amount_capturable,
amount_to_capture: None,
connector_mandate_detail: None,
},
PaymentAttemptUpdate::ConfirmIntentResponse {
status,
connector_payment_id,
updated_by,
redirection_data,
connector_metadata,
amount_capturable,
} => Self {
status: Some(status),
amount_capturable,
error_message: None,
error_code: None,
modified_at: common_utils::date_time::now(),
browser_info: None,
error_reason: None,
updated_by,
merchant_connector_id: None,
unified_code: None,
unified_message: None,
connector_payment_id,
connector: None,
redirection_data: redirection_data
.map(diesel_models::payment_attempt::RedirectForm::from),
connector_metadata,
amount_to_capture: None,
},
PaymentAttemptUpdate::ConfirmIntentResponse(confirm_intent_response_update) => {
let ConfirmIntentResponseUpdate {
status,
connector_payment_id,
updated_by,
redirection_data,
connector_metadata,
amount_capturable,
connector_mandate_detail,
} = *confirm_intent_response_update;
Self {
status: Some(status),
amount_capturable,
error_message: None,
error_code: None,
modified_at: common_utils::date_time::now(),
browser_info: None,
error_reason: None,
updated_by,
merchant_connector_id: None,
unified_code: None,
unified_message: None,
connector_payment_id,
connector: None,
redirection_data: redirection_data
.map(diesel_models::payment_attempt::RedirectForm::from),
connector_metadata,
amount_to_capture: None,
connector_mandate_detail,
}
}
PaymentAttemptUpdate::SyncUpdate {
status,
amount_capturable,
Expand All @@ -2155,6 +2167,7 @@ impl From<PaymentAttemptUpdate> for diesel_models::PaymentAttemptUpdateInternal
redirection_data: None,
connector_metadata: None,
amount_to_capture: None,
connector_mandate_detail: None,
},
PaymentAttemptUpdate::CaptureUpdate {
status,
Expand All @@ -2177,6 +2190,7 @@ impl From<PaymentAttemptUpdate> for diesel_models::PaymentAttemptUpdateInternal
connector: None,
redirection_data: None,
connector_metadata: None,
connector_mandate_detail: None,
},
PaymentAttemptUpdate::PreCaptureUpdate {
amount_to_capture,
Expand All @@ -2198,6 +2212,7 @@ impl From<PaymentAttemptUpdate> for diesel_models::PaymentAttemptUpdateInternal
status: None,
connector_metadata: None,
amount_capturable: None,
connector_mandate_detail: None,
},
}
}
Expand Down
Loading
Loading