Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
2 changes: 1 addition & 1 deletion crates/hyperswitch_domain_models/src/payments.rs
Original file line number Diff line number Diff line change
Expand Up @@ -881,7 +881,7 @@ where
{
pub flow: PhantomData<F>,
pub payment_intent: PaymentIntent,
pub payment_attempt: Option<PaymentAttempt>,
pub payment_attempt: PaymentAttempt,
pub payment_address: payment_address::PaymentAddress,
pub attempts: Option<Vec<PaymentAttempt>>,
/// Should the payment status be synced with connector
Expand Down
10 changes: 3 additions & 7 deletions crates/hyperswitch_domain_models/src/router_data.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1129,11 +1129,7 @@ impl
.get_captured_amount(payment_data)
.unwrap_or(MinorUnit::zero());

let total_amount = payment_data
.payment_attempt
.as_ref()
.map(|attempt| attempt.amount_details.get_net_amount())
.unwrap_or(MinorUnit::zero());
let total_amount = payment_data.payment_attempt.amount_details.get_net_amount();

if amount_captured == total_amount {
common_enums::AttemptStatus::Charged
Expand All @@ -1149,7 +1145,7 @@ impl
&self,
payment_data: &payments::PaymentStatusData<router_flow_types::PSync>,
) -> Option<MinorUnit> {
let payment_attempt = payment_data.payment_attempt.as_ref()?;
let payment_attempt = &payment_data.payment_attempt;

// Based on the status of the response, we can determine the amount capturable
let intent_status = common_enums::IntentStatus::from(self.status);
Expand Down Expand Up @@ -1179,7 +1175,7 @@ impl
&self,
payment_data: &payments::PaymentStatusData<router_flow_types::PSync>,
) -> Option<MinorUnit> {
let payment_attempt = payment_data.payment_attempt.as_ref()?;
let payment_attempt = &payment_data.payment_attempt;

// Based on the status of the response, we can determine the amount capturable
let intent_status = common_enums::IntentStatus::from(self.status);
Expand Down
20 changes: 7 additions & 13 deletions crates/router/src/core/payments.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1808,7 +1808,7 @@ pub async fn record_attempt_core(
let default_payment_status_data = PaymentStatusData {
flow: PhantomData,
payment_intent: payment_data.payment_intent.clone(),
payment_attempt: Some(payment_data.payment_attempt.clone()),
payment_attempt: payment_data.payment_attempt.clone(),
attempts: None,
should_sync_with_connector: false,
payment_address: payment_data.payment_address.clone(),
Expand Down Expand Up @@ -1839,7 +1839,7 @@ pub async fn record_attempt_core(
payment_data: PaymentStatusData {
flow: PhantomData,
payment_intent: payment_data.payment_intent.clone(),
payment_attempt: Some(payment_data.payment_attempt.clone()),
payment_attempt: payment_data.payment_attempt.clone(),
attempts: None,
should_sync_with_connector: true,
payment_address: payment_data.payment_address.clone(),
Expand All @@ -1863,9 +1863,7 @@ pub async fn record_attempt_core(
let record_payment_data = domain_payments::PaymentAttemptRecordData {
flow: PhantomData,
payment_intent: payment_status_data.payment_intent,
payment_attempt: payment_status_data
.payment_attempt
.unwrap_or(payment_data.payment_attempt.clone()),
payment_attempt: payment_status_data.payment_attempt,
revenue_recovery_data: payment_data.revenue_recovery_data.clone(),
payment_address: payment_data.payment_address.clone(),
};
Expand Down Expand Up @@ -2730,11 +2728,7 @@ impl PaymentRedirectFlow for PaymentRedirectSync {
let payment_data = &get_tracker_response.payment_data;
self.validate_status_for_operation(payment_data.payment_intent.status)?;

let payment_attempt = payment_data
.payment_attempt
.as_ref()
.ok_or(errors::ApiErrorResponse::InternalServerError)
.attach_printable("payment_attempt not found in get_tracker_response")?;
let payment_attempt = payment_data.payment_attempt.clone();

let connector = payment_attempt
.connector
Expand Down Expand Up @@ -9112,7 +9106,7 @@ impl<F: Clone> OperationSessionSetters<F> for PaymentConfirmData<F> {
impl<F: Clone> OperationSessionGetters<F> for PaymentStatusData<F> {
#[track_caller]
fn get_payment_attempt(&self) -> &storage::PaymentAttempt {
todo!()
&self.payment_attempt
}
fn get_client_secret(&self) -> &Option<Secret<String>> {
todo!()
Expand Down Expand Up @@ -9241,7 +9235,7 @@ impl<F: Clone> OperationSessionGetters<F> for PaymentStatusData<F> {
}

fn get_optional_payment_attempt(&self) -> Option<&storage::PaymentAttempt> {
self.payment_attempt.as_ref()
Some(&self.payment_attempt)
}

fn get_all_keys_required(&self) -> Option<bool> {
Expand All @@ -9262,7 +9256,7 @@ impl<F: Clone> OperationSessionSetters<F> for PaymentStatusData<F> {
todo!()
}
fn set_payment_attempt(&mut self, payment_attempt: storage::PaymentAttempt) {
self.payment_attempt = Some(payment_attempt);
self.payment_attempt = payment_attempt;
}

fn set_payment_method_data(&mut self, _payment_method_data: Option<domain::PaymentMethodData>) {
Expand Down
124 changes: 80 additions & 44 deletions crates/router/src/core/payments/operations/payment_get.rs
Original file line number Diff line number Diff line change
Expand Up @@ -30,9 +30,41 @@ impl ValidateStatusForOperation for PaymentGet {
/// Validate if the current operation can be performed on the current status of the payment intent
fn validate_status_for_operation(
&self,
_intent_status: common_enums::IntentStatus,
intent_status: common_enums::IntentStatus,
) -> Result<(), errors::ApiErrorResponse> {
Ok(())
match intent_status {
common_enums::IntentStatus::RequiresCapture
| common_enums::IntentStatus::RequiresCustomerAction
| common_enums::IntentStatus::RequiresMerchantAction
| common_enums::IntentStatus::Processing
| common_enums::IntentStatus::Succeeded
| common_enums::IntentStatus::Failed
| common_enums::IntentStatus::PartiallyCapturedAndCapturable
| common_enums::IntentStatus::PartiallyCaptured
| common_enums::IntentStatus::Cancelled => Ok(()),
// These statuses are not valid for this operation
common_enums::IntentStatus::RequiresConfirmation
| common_enums::IntentStatus::RequiresPaymentMethod => {
Err(errors::ApiErrorResponse::PaymentUnexpectedState {
current_flow: format!("{self:?}"),
field_name: "status".to_string(),
current_value: intent_status.to_string(),
states: [
common_enums::IntentStatus::RequiresCapture,
common_enums::IntentStatus::RequiresCustomerAction,
common_enums::IntentStatus::RequiresMerchantAction,
common_enums::IntentStatus::Processing,
common_enums::IntentStatus::Succeeded,
common_enums::IntentStatus::Failed,
common_enums::IntentStatus::PartiallyCapturedAndCapturable,
common_enums::IntentStatus::PartiallyCaptured,
common_enums::IntentStatus::Cancelled,
]
.map(|enum_value| enum_value.to_string())
.join(", "),
})
}
}
}
}

Expand Down Expand Up @@ -137,22 +169,24 @@ impl<F: Send + Clone + Sync> GetTracker<F, PaymentStatusData<F>, PaymentsRetriev
.await
.to_not_found_response(errors::ApiErrorResponse::PaymentNotFound)?;

let payment_attempt = payment_intent
.active_attempt_id
.as_ref()
.async_map(|active_attempt| async {
db.find_payment_attempt_by_id(
key_manager_state,
merchant_context.get_merchant_key_store(),
active_attempt,
storage_scheme,
)
.await
.change_context(errors::ApiErrorResponse::InternalServerError)
.attach_printable("Could not find payment attempt given the attempt id")
})
self.validate_status_for_operation(payment_intent.status)?;

let active_attempt_id = payment_intent.active_attempt_id.as_ref().ok_or_else(|| {
errors::ApiErrorResponse::MissingRequiredField {
field_name: ("active_attempt_id"),
}
})?;

let payment_attempt = db
.find_payment_attempt_by_id(
key_manager_state,
merchant_context.get_merchant_key_store(),
active_attempt_id,
storage_scheme,
)
.await
.transpose()?;
.change_context(errors::ApiErrorResponse::InternalServerError)
.attach_printable("Could not find payment attempt given the attempt id")?;

let should_sync_with_connector =
request.force_sync && payment_intent.status.should_force_sync_with_connector();
Expand All @@ -168,9 +202,8 @@ impl<F: Send + Clone + Sync> GetTracker<F, PaymentStatusData<F>, PaymentsRetriev
.clone()
.map(|address| address.into_inner()),
payment_attempt
.as_ref()
.and_then(|payment_attempt| payment_attempt.payment_method_billing_address.as_ref())
.cloned()
.payment_method_billing_address
.clone()
.map(|address| address.into_inner()),
Some(true),
);
Expand Down Expand Up @@ -268,34 +301,37 @@ impl<F: Clone + Send + Sync> Domain<F, PaymentsRetrieveRequest, PaymentStatusDat
// TODO: do not take the whole payment data here
payment_data: &mut PaymentStatusData<F>,
) -> CustomResult<ConnectorCallType, errors::ApiErrorResponse> {
match &payment_data.payment_attempt {
Some(payment_attempt) if payment_data.should_sync_with_connector => {
let connector = payment_attempt
.connector
.as_ref()
.get_required_value("connector")
.change_context(errors::ApiErrorResponse::InternalServerError)
.attach_printable("Connector is none when constructing response")?;
let payment_attempt = &payment_data.payment_attempt;

let merchant_connector_id = payment_attempt
.merchant_connector_id
.as_ref()
.get_required_value("merchant_connector_id")
.change_context(errors::ApiErrorResponse::InternalServerError)
.attach_printable("Merchant connector id is none when constructing response")?;
if payment_data.should_sync_with_connector {
let connector = payment_attempt
.connector
.as_ref()
.get_required_value("connector")
.change_context(errors::ApiErrorResponse::InternalServerError)
.attach_printable("Connector is none when constructing response")?;

let connector_data = api::ConnectorData::get_connector_by_name(
&state.conf.connectors,
connector,
api::GetToken::Connector,
Some(merchant_connector_id.to_owned()),
)
let merchant_connector_id = payment_attempt
.merchant_connector_id
.as_ref()
.get_required_value("merchant_connector_id")
.change_context(errors::ApiErrorResponse::InternalServerError)
.attach_printable("Invalid connector name received")?;
.attach_printable("Merchant connector id is none when constructing response")?;

Ok(ConnectorCallType::PreDetermined(connector_data.into()))
}
None | Some(_) => Ok(ConnectorCallType::Skip),
let connector_data = api::ConnectorData::get_connector_by_name(
&state.conf.connectors,
connector,
api::GetToken::Connector,
Some(merchant_connector_id.to_owned()),
)
.change_context(errors::ApiErrorResponse::InternalServerError)
.attach_printable("Invalid connector name received")?;

Ok(ConnectorCallType::PreDetermined(
api::ConnectorRoutingData::from(connector_data),
))
} else {
Ok(ConnectorCallType::Skip)
}
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2593,12 +2593,7 @@ impl<F: Clone> PostUpdateTracker<F, PaymentStatusData<F>, types::PaymentsSyncDat
let payment_attempt_update =
response_router_data.get_payment_attempt_update(&payment_data, storage_scheme);

let payment_attempt = payment_data
.payment_attempt
.ok_or(errors::ApiErrorResponse::InternalServerError)
.attach_printable(
"Payment attempt not found in payment data in post update trackers",
)?;
let payment_attempt = payment_data.payment_attempt;

let updated_payment_intent = db
.update_payment_intent(
Expand All @@ -2625,7 +2620,7 @@ impl<F: Clone> PostUpdateTracker<F, PaymentStatusData<F>, types::PaymentsSyncDat
.attach_printable("Unable to update payment attempt")?;

payment_data.payment_intent = updated_payment_intent;
payment_data.payment_attempt = Some(updated_payment_attempt);
payment_data.payment_attempt = updated_payment_attempt;

Ok(payment_data)
}
Expand Down
49 changes: 14 additions & 35 deletions crates/router/src/core/payments/transformers.rs
Original file line number Diff line number Diff line change
Expand Up @@ -587,11 +587,7 @@ pub async fn construct_router_data_for_psync<'a>(
.change_context(errors::ApiErrorResponse::InternalServerError)
.attach_printable("Failed while parsing value for ConnectorAuthType")?;

let attempt = &payment_data
.payment_attempt
.get_required_value("attempt")
.change_context(errors::ApiErrorResponse::InternalServerError)
.attach_printable("Payment Attempt is not available in payment data")?;
let attempt = &payment_data.payment_attempt;

let connector_request_reference_id = payment_intent
.merchant_reference_id
Expand Down Expand Up @@ -1913,21 +1909,19 @@ where
profile: &domain::Profile,
) -> RouterResponse<api_models::payments::PaymentsResponse> {
let payment_intent = self.payment_intent;
let optional_payment_attempt = self.payment_attempt.as_ref();
let payment_attempt = &self.payment_attempt;

let amount = api_models::payments::PaymentAmountDetailsResponse::foreign_from((
&payment_intent.amount_details,
optional_payment_attempt.map(|payment_attempt| &payment_attempt.amount_details),
&payment_attempt.amount_details,
));

let connector =
optional_payment_attempt.and_then(|payment_attempt| payment_attempt.connector.clone());
let connector = payment_attempt.connector.clone();

let merchant_connector_id = optional_payment_attempt
.and_then(|payment_attempt| payment_attempt.merchant_connector_id.clone());
let merchant_connector_id = payment_attempt.merchant_connector_id.clone();

let error = optional_payment_attempt
.and_then(|payment_attempt| payment_attempt.error.clone())
let error = payment_attempt
.error
.as_ref()
.map(api_models::payments::ErrorDetails::foreign_from);
let attempts = self.attempts.as_ref().map(|attempts| {
Expand All @@ -1949,8 +1943,8 @@ where

let connector_token_details = self
.payment_attempt
.as_ref()
.and_then(|attempt| attempt.connector_token_details.clone())
.connector_token_details
.clone()
.and_then(Option::<api_models::payments::ConnectorTokenDetails>::foreign_from);

let return_url = payment_intent.return_url.or(profile.return_url.clone());
Expand All @@ -1969,31 +1963,16 @@ where
shipping: self.payment_address.get_shipping().cloned().map(From::from),
created: payment_intent.created_at,
payment_method_data,
payment_method_type: self
.payment_attempt
.as_ref()
.map(|attempt| attempt.payment_method_type),
payment_method_subtype: self
.payment_attempt
.as_ref()
.map(|attempt| attempt.payment_method_subtype),
connector_transaction_id: self
.payment_attempt
.as_ref()
.and_then(|attempt| attempt.connector_payment_id.clone()),
payment_method_type: Some(payment_attempt.payment_method_type),
payment_method_subtype: Some(payment_attempt.payment_method_subtype),
connector_transaction_id: payment_attempt.connector_payment_id.clone(),
connector_reference_id: None,
merchant_connector_id,
browser_info: None,
connector_token_details,
payment_method_id: self
.payment_attempt
.as_ref()
.and_then(|attempt| attempt.payment_method_id.clone()),
payment_method_id: payment_attempt.payment_method_id.clone(),
error,
authentication_type_applied: self
.payment_attempt
.as_ref()
.and_then(|attempt| attempt.authentication_applied),
authentication_type_applied: payment_attempt.authentication_applied,
authentication_type: payment_intent.authentication_type,
next_action: None,
attempts,
Expand Down
6 changes: 2 additions & 4 deletions crates/router/src/core/revenue_recovery.rs
Original file line number Diff line number Diff line change
Expand Up @@ -259,10 +259,8 @@ pub async fn perform_payments_sync(
revenue_recovery_payment_data,
)
.await?;
// If there is an active_attempt id then there will be a payment attempt
let payment_attempt = psync_data
.payment_attempt
.get_required_value("Payment Attempt")?;

let payment_attempt = psync_data.payment_attempt;
let mut revenue_recovery_metadata = payment_intent
.feature_metadata
.as_ref()
Expand Down
Loading
Loading