mirror of
https://github.com/juspay/hyperswitch.git
synced 2025-10-28 04:04:55 +08:00
fix(router): store connector_mandate_id in complete auth (#3576)
Co-authored-by: Narayan Bhat <48803246+Narayanbhat166@users.noreply.github.com> Co-authored-by: hyperswitch-bot[bot] <148525504+hyperswitch-bot[bot]@users.noreply.github.com>
This commit is contained in:
@ -1,7 +1,7 @@
|
|||||||
pub mod helpers;
|
pub mod helpers;
|
||||||
pub mod utils;
|
pub mod utils;
|
||||||
use api_models::payments;
|
use api_models::payments;
|
||||||
use common_utils::{ext_traits::Encode, pii};
|
use common_utils::ext_traits::Encode;
|
||||||
use diesel_models::{enums as storage_enums, Mandate};
|
use diesel_models::{enums as storage_enums, Mandate};
|
||||||
use error_stack::{report, IntoReport, ResultExt};
|
use error_stack::{report, IntoReport, ResultExt};
|
||||||
use futures::future;
|
use futures::future;
|
||||||
@ -24,7 +24,7 @@ use crate::{
|
|||||||
ConnectorData, GetToken,
|
ConnectorData, GetToken,
|
||||||
},
|
},
|
||||||
domain, storage,
|
domain, storage,
|
||||||
transformers::ForeignTryFrom,
|
transformers::ForeignFrom,
|
||||||
},
|
},
|
||||||
utils::OptionExt,
|
utils::OptionExt,
|
||||||
};
|
};
|
||||||
@ -154,25 +154,46 @@ pub async fn revoke_mandate(
|
|||||||
pub async fn update_connector_mandate_id(
|
pub async fn update_connector_mandate_id(
|
||||||
db: &dyn StorageInterface,
|
db: &dyn StorageInterface,
|
||||||
merchant_account: String,
|
merchant_account: String,
|
||||||
mandate_ids_opt: Option<api_models::payments::MandateIds>,
|
mandate_ids_opt: Option<String>,
|
||||||
|
payment_method_id: Option<String>,
|
||||||
resp: Result<types::PaymentsResponseData, types::ErrorResponse>,
|
resp: Result<types::PaymentsResponseData, types::ErrorResponse>,
|
||||||
) -> RouterResponse<mandates::MandateResponse> {
|
) -> RouterResponse<mandates::MandateResponse> {
|
||||||
let connector_mandate_id = Option::foreign_try_from(resp)?;
|
let mandate_details = Option::foreign_from(resp);
|
||||||
|
let connector_mandate_id = mandate_details
|
||||||
|
.clone()
|
||||||
|
.map(|md| {
|
||||||
|
Encode::<types::MandateReference>::encode_to_value(&md)
|
||||||
|
.change_context(errors::ApiErrorResponse::InternalServerError)
|
||||||
|
.map(masking::Secret::new)
|
||||||
|
})
|
||||||
|
.transpose()?;
|
||||||
|
|
||||||
//Ignore updation if the payment_attempt mandate_id or connector_mandate_id is not present
|
//Ignore updation if the payment_attempt mandate_id or connector_mandate_id is not present
|
||||||
if let Some((mandate_ids, connector_id)) = mandate_ids_opt.zip(connector_mandate_id) {
|
if let Some((mandate_id, connector_id)) = mandate_ids_opt.zip(connector_mandate_id) {
|
||||||
let mandate_id = &mandate_ids.mandate_id;
|
|
||||||
let mandate = db
|
let mandate = db
|
||||||
.find_mandate_by_merchant_id_mandate_id(&merchant_account, mandate_id)
|
.find_mandate_by_merchant_id_mandate_id(&merchant_account, &mandate_id)
|
||||||
.await
|
.await
|
||||||
.change_context(errors::ApiErrorResponse::MandateNotFound)?;
|
.change_context(errors::ApiErrorResponse::MandateNotFound)?;
|
||||||
|
|
||||||
|
let update_mandate_details = match payment_method_id {
|
||||||
|
Some(pmd_id) => storage::MandateUpdate::ConnectorMandateIdUpdate {
|
||||||
|
connector_mandate_id: mandate_details
|
||||||
|
.and_then(|mandate_reference| mandate_reference.connector_mandate_id),
|
||||||
|
connector_mandate_ids: Some(connector_id),
|
||||||
|
payment_method_id: pmd_id,
|
||||||
|
original_payment_id: None,
|
||||||
|
},
|
||||||
|
None => storage::MandateUpdate::ConnectorReferenceUpdate {
|
||||||
|
connector_mandate_ids: Some(connector_id),
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
// only update the connector_mandate_id if existing is none
|
// only update the connector_mandate_id if existing is none
|
||||||
if mandate.connector_mandate_id.is_none() {
|
if mandate.connector_mandate_id.is_none() {
|
||||||
db.update_mandate_by_merchant_id_mandate_id(
|
db.update_mandate_by_merchant_id_mandate_id(
|
||||||
&merchant_account,
|
&merchant_account,
|
||||||
mandate_id,
|
&mandate_id,
|
||||||
storage::MandateUpdate::ConnectorReferenceUpdate {
|
update_mandate_details,
|
||||||
connector_mandate_ids: Some(connector_id),
|
|
||||||
},
|
|
||||||
)
|
)
|
||||||
.await
|
.await
|
||||||
.change_context(errors::ApiErrorResponse::MandateUpdateFailed)?;
|
.change_context(errors::ApiErrorResponse::MandateUpdateFailed)?;
|
||||||
@ -454,27 +475,16 @@ pub async fn retrieve_mandates_list(
|
|||||||
Ok(services::ApplicationResponse::Json(mandates_list))
|
Ok(services::ApplicationResponse::Json(mandates_list))
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ForeignTryFrom<Result<types::PaymentsResponseData, types::ErrorResponse>>
|
impl ForeignFrom<Result<types::PaymentsResponseData, types::ErrorResponse>>
|
||||||
for Option<pii::SecretSerdeValue>
|
for Option<types::MandateReference>
|
||||||
{
|
{
|
||||||
type Error = error_stack::Report<errors::ApiErrorResponse>;
|
fn foreign_from(resp: Result<types::PaymentsResponseData, types::ErrorResponse>) -> Self {
|
||||||
fn foreign_try_from(
|
match resp {
|
||||||
resp: Result<types::PaymentsResponseData, types::ErrorResponse>,
|
|
||||||
) -> errors::RouterResult<Self> {
|
|
||||||
let mandate_details = match resp {
|
|
||||||
Ok(types::PaymentsResponseData::TransactionResponse {
|
Ok(types::PaymentsResponseData::TransactionResponse {
|
||||||
mandate_reference, ..
|
mandate_reference, ..
|
||||||
}) => mandate_reference,
|
}) => mandate_reference,
|
||||||
_ => None,
|
_ => None,
|
||||||
};
|
}
|
||||||
|
|
||||||
mandate_details
|
|
||||||
.map(|md| {
|
|
||||||
Encode::<types::MandateReference>::encode_to_value(&md)
|
|
||||||
.change_context(errors::ApiErrorResponse::MandateNotFound)
|
|
||||||
.map(masking::Secret::new)
|
|
||||||
})
|
|
||||||
.transpose()
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -819,17 +819,27 @@ async fn payment_response_update_tracker<F: Clone, T: types::Capturable>(
|
|||||||
.in_current_span(),
|
.in_current_span(),
|
||||||
);
|
);
|
||||||
|
|
||||||
// When connector requires redirection for mandate creation it can update the connector mandate_id during Psync
|
// When connector requires redirection for mandate creation it can update the connector mandate_id during Psync and CompleteAuthorize
|
||||||
let m_db = state.clone().store;
|
let m_db = state.clone().store;
|
||||||
|
let m_payment_method_id = payment_data.payment_attempt.payment_method_id.clone();
|
||||||
let m_router_data_merchant_id = router_data.merchant_id.clone();
|
let m_router_data_merchant_id = router_data.merchant_id.clone();
|
||||||
let m_payment_data_mandate_id = payment_data.mandate_id.clone();
|
let m_payment_data_mandate_id =
|
||||||
|
payment_data
|
||||||
|
.payment_attempt
|
||||||
|
.mandate_id
|
||||||
|
.clone()
|
||||||
|
.or(payment_data
|
||||||
|
.mandate_id
|
||||||
|
.clone()
|
||||||
|
.map(|mandate_ids| mandate_ids.mandate_id));
|
||||||
let m_router_data_response = router_data.response.clone();
|
let m_router_data_response = router_data.response.clone();
|
||||||
let mandate_update_fut = tokio::spawn(
|
let mandate_update_fut = tokio::spawn(
|
||||||
async move {
|
async move {
|
||||||
mandate::update_connector_mandate_id(
|
mandate::update_connector_mandate_id(
|
||||||
m_db.as_ref(),
|
m_db.as_ref(),
|
||||||
m_router_data_merchant_id,
|
m_router_data_merchant_id.clone(),
|
||||||
m_payment_data_mandate_id,
|
m_payment_data_mandate_id,
|
||||||
|
m_payment_method_id,
|
||||||
m_router_data_response,
|
m_router_data_response,
|
||||||
)
|
)
|
||||||
.await
|
.await
|
||||||
|
|||||||
Reference in New Issue
Block a user