refactor(core): add support for expand attempt list in psync v2 (#7209)

Co-authored-by: Chikke Srujan <chikke.srujan@Chikke-Srujan-N7WRTY72X7.local>
Co-authored-by: hyperswitch-bot[bot] <148525504+hyperswitch-bot[bot]@users.noreply.github.com>
This commit is contained in:
chikke srujan
2025-02-11 16:13:51 +05:30
committed by GitHub
parent 1d607d7970
commit d093317019
15 changed files with 415 additions and 73 deletions

View File

@ -2327,6 +2327,7 @@ impl PaymentRedirectFlow for PaymentRedirectSync {
let payment_sync_request = api::PaymentsRetrieveRequest {
param: Some(req.query_params.clone()),
force_sync: true,
expand_attempts: false,
};
let operation = operations::PaymentGet;

View File

@ -169,11 +169,32 @@ impl<F: Send + Clone + Sync> GetTracker<F, PaymentStatusData<F>, PaymentsRetriev
Some(true),
);
let attempts = match request.expand_attempts {
true => payment_intent
.active_attempt_id
.as_ref()
.async_map(|active_attempt| async {
db.find_payment_attempts_by_payment_intent_id(
key_manager_state,
payment_id,
key_store,
storage_scheme,
)
.await
.change_context(errors::ApiErrorResponse::InternalServerError)
.attach_printable("Could not find payment attempts for the given the intent id")
})
.await
.transpose()?,
false => None,
};
let payment_data = PaymentStatusData {
flow: std::marker::PhantomData,
payment_intent,
payment_attempt,
payment_address,
attempts,
should_sync_with_connector,
};

View File

@ -1687,6 +1687,12 @@ where
let error = optional_payment_attempt
.and_then(|payment_attempt| payment_attempt.error.clone())
.map(api_models::payments::ErrorDetails::foreign_from);
let attempts = self.attempts.as_ref().map(|attempts| {
attempts
.iter()
.map(api_models::payments::PaymentAttemptResponse::foreign_from)
.collect()
});
let payment_method_data =
Some(api_models::payments::PaymentMethodDataResponseWithBilling {
@ -1729,6 +1735,7 @@ where
merchant_connector_id,
browser_info: None,
error,
attempts,
};
Ok(services::ApplicationResponse::JsonWithHeaders((
@ -4146,6 +4153,61 @@ impl
}
}
#[cfg(feature = "v2")]
impl ForeignFrom<&hyperswitch_domain_models::payments::payment_attempt::PaymentAttempt>
for api_models::payments::PaymentAttemptResponse
{
fn foreign_from(
attempt: &hyperswitch_domain_models::payments::payment_attempt::PaymentAttempt,
) -> Self {
Self {
id: attempt.get_id().to_owned(),
status: attempt.status,
amount: api_models::payments::PaymentAttemptAmountDetails::foreign_from(
&attempt.amount_details,
),
connector: attempt.connector.clone(),
error: attempt
.error
.clone()
.map(api_models::payments::ErrorDetails::foreign_from),
authentication_type: attempt.authentication_type,
created_at: attempt.created_at,
modified_at: attempt.modified_at,
cancellation_reason: attempt.cancellation_reason.clone(),
payment_token: attempt.payment_token.clone(),
connector_metadata: attempt.connector_metadata.clone(),
payment_experience: attempt.payment_experience,
payment_method_type: attempt.payment_method_type,
connector_reference_id: attempt.connector_response_reference_id.clone(),
payment_method_subtype: attempt.get_payment_method_type(),
connector_payment_id: attempt.get_connector_payment_id().map(ToString::to_string),
payment_method_id: attempt.payment_method_id.clone(),
client_source: attempt.client_source.clone(),
client_version: attempt.client_version.clone(),
}
}
}
#[cfg(feature = "v2")]
impl ForeignFrom<&hyperswitch_domain_models::payments::payment_attempt::AttemptAmountDetails>
for api_models::payments::PaymentAttemptAmountDetails
{
fn foreign_from(
amount: &hyperswitch_domain_models::payments::payment_attempt::AttemptAmountDetails,
) -> Self {
Self {
net_amount: amount.get_net_amount(),
amount_to_capture: amount.get_amount_to_capture(),
surcharge_amount: amount.get_surcharge_amount(),
tax_on_surcharge: amount.get_tax_on_surcharge(),
amount_capturable: amount.get_amount_capturable(),
shipping_cost: amount.get_shipping_cost(),
order_tax_amount: amount.get_order_tax_amount(),
}
}
}
#[cfg(feature = "v2")]
impl ForeignFrom<hyperswitch_domain_models::payments::payment_attempt::ErrorDetails>
for api_models::payments::ErrorDetails

View File

@ -431,6 +431,7 @@ async fn payments_incoming_webhook_flow(
payments::operations::PaymentGet,
api::PaymentsRetrieveRequest {
force_sync: true,
expand_attempts: false,
param: None,
},
get_trackers_response,
@ -630,6 +631,7 @@ where
flow: PhantomData,
payment_intent,
payment_attempt: Some(payment_attempt),
attempts: None,
should_sync_with_connector: true,
payment_address,
},

View File

@ -1618,6 +1618,24 @@ impl PaymentAttemptInterface for KafkaStore {
.await
}
#[cfg(feature = "v2")]
async fn find_payment_attempts_by_payment_intent_id(
&self,
key_manager_state: &KeyManagerState,
payment_id: &id_type::GlobalPaymentId,
merchant_key_store: &domain::MerchantKeyStore,
storage_scheme: MerchantStorageScheme,
) -> error_stack::Result<Vec<storage::PaymentAttempt>, errors::DataStorageError> {
self.diesel_store
.find_payment_attempts_by_payment_intent_id(
key_manager_state,
payment_id,
merchant_key_store,
storage_scheme,
)
.await
}
#[cfg(feature = "v1")]
async fn find_payment_attempt_last_successful_attempt_by_payment_id_merchant_id(
&self,