mirror of
https://github.com/juspay/hyperswitch.git
synced 2025-11-02 04:04:43 +08:00
feat(order_details): Adding order_details both inside and outside of metadata, in payments request, for backward compatibility (#1344)
Co-authored-by: Narayan Bhat <48803246+Narayanbhat166@users.noreply.github.com>
This commit is contained in:
@ -2,7 +2,7 @@ use std::borrow::Cow;
|
||||
|
||||
use base64::Engine;
|
||||
use common_utils::{
|
||||
ext_traits::{AsyncExt, ByteSliceExt, ValueExt},
|
||||
ext_traits::{AsyncExt, ByteSliceExt, Encode, ValueExt},
|
||||
fp_utils, generate_id, pii,
|
||||
};
|
||||
// TODO : Evaluate all the helper functions ()
|
||||
@ -1686,6 +1686,7 @@ mod tests {
|
||||
active_attempt_id: "nopes".to_string(),
|
||||
business_country: storage_enums::CountryAlpha2::AG,
|
||||
business_label: "no".to_string(),
|
||||
order_details: None,
|
||||
};
|
||||
let req_cs = Some("1".to_string());
|
||||
let merchant_fulfillment_time = Some(900);
|
||||
@ -1725,6 +1726,7 @@ mod tests {
|
||||
active_attempt_id: "nopes".to_string(),
|
||||
business_country: storage_enums::CountryAlpha2::AG,
|
||||
business_label: "no".to_string(),
|
||||
order_details: None,
|
||||
};
|
||||
let req_cs = Some("1".to_string());
|
||||
let merchant_fulfillment_time = Some(10);
|
||||
@ -1764,6 +1766,7 @@ mod tests {
|
||||
active_attempt_id: "nopes".to_string(),
|
||||
business_country: storage_enums::CountryAlpha2::AG,
|
||||
business_label: "no".to_string(),
|
||||
order_details: None,
|
||||
};
|
||||
let req_cs = Some("1".to_string());
|
||||
let merchant_fulfillment_time = Some(10);
|
||||
@ -2144,3 +2147,105 @@ impl AttemptType {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn validate_and_add_order_details_to_payment_intent(
|
||||
payment_intent: &mut storage::payment_intent::PaymentIntent,
|
||||
request: &api::PaymentsRequest,
|
||||
) -> RouterResult<()> {
|
||||
let parsed_metadata_db: Option<api_models::payments::Metadata> = payment_intent
|
||||
.metadata
|
||||
.as_ref()
|
||||
.map(|metadata_value| {
|
||||
metadata_value
|
||||
.peek()
|
||||
.clone()
|
||||
.parse_value("metadata")
|
||||
.change_context(errors::ApiErrorResponse::InvalidDataValue {
|
||||
field_name: "metadata",
|
||||
})
|
||||
.attach_printable("unable to parse metadata")
|
||||
})
|
||||
.transpose()?;
|
||||
let order_details_metadata_db = parsed_metadata_db
|
||||
.as_ref()
|
||||
.and_then(|meta| meta.order_details.to_owned());
|
||||
let order_details_outside_metadata_db = payment_intent.order_details.as_ref();
|
||||
let order_details_outside_metadata_req = request.order_details.as_ref();
|
||||
let order_details_metadata_req = request
|
||||
.metadata
|
||||
.as_ref()
|
||||
.and_then(|meta| meta.order_details.to_owned());
|
||||
|
||||
if order_details_metadata_db
|
||||
.as_ref()
|
||||
.zip(order_details_outside_metadata_db.as_ref())
|
||||
.is_some()
|
||||
{
|
||||
Err(errors::ApiErrorResponse::NotSupported { message: "order_details cannot be present both inside and outside metadata in payment intent in db".to_string() })?
|
||||
}
|
||||
let order_details_outside = match order_details_outside_metadata_req {
|
||||
Some(order) => match order_details_metadata_db {
|
||||
Some(_) => Err(errors::ApiErrorResponse::NotSupported {
|
||||
message: "order_details previously present inside of metadata".to_string(),
|
||||
})?,
|
||||
None => Some(order),
|
||||
},
|
||||
None => match order_details_metadata_req {
|
||||
Some(_order) => match order_details_outside_metadata_db {
|
||||
Some(_) => Err(errors::ApiErrorResponse::NotSupported {
|
||||
message: "order_details previously present outside of metadata".to_string(),
|
||||
})?,
|
||||
None => None,
|
||||
},
|
||||
None => None,
|
||||
},
|
||||
};
|
||||
add_order_details_and_metadata_to_payment_intent(
|
||||
payment_intent,
|
||||
request,
|
||||
parsed_metadata_db,
|
||||
&order_details_outside.map(|data| data.to_owned()),
|
||||
)
|
||||
}
|
||||
|
||||
pub fn add_order_details_and_metadata_to_payment_intent(
|
||||
mut payment_intent: &mut storage::payment_intent::PaymentIntent,
|
||||
request: &api::PaymentsRequest,
|
||||
parsed_metadata_db: Option<api_models::payments::Metadata>,
|
||||
order_details_outside: &Option<Vec<api_models::payments::OrderDetailsWithAmount>>,
|
||||
) -> RouterResult<()> {
|
||||
let metadata_with_order_details = match request.metadata.as_ref() {
|
||||
Some(meta) => {
|
||||
let transformed_metadata = match parsed_metadata_db {
|
||||
Some(meta_db) => api_models::payments::Metadata {
|
||||
order_details: meta.order_details.to_owned(),
|
||||
..meta_db
|
||||
},
|
||||
None => meta.to_owned(),
|
||||
};
|
||||
let transformed_metadata_value =
|
||||
Encode::<api_models::payments::Metadata>::encode_to_value(&transformed_metadata)
|
||||
.change_context(errors::ApiErrorResponse::InternalServerError)
|
||||
.attach_printable("Encoding Metadata to value failed")?;
|
||||
Some(masking::Secret::new(transformed_metadata_value))
|
||||
}
|
||||
None => None,
|
||||
};
|
||||
if let Some(order_details_outside_struct) = order_details_outside {
|
||||
let order_details_outside_value = order_details_outside_struct
|
||||
.iter()
|
||||
.map(|order| {
|
||||
Encode::<api_models::payments::OrderDetailsWithAmount>::encode_to_value(order)
|
||||
.change_context(errors::ApiErrorResponse::InternalServerError)
|
||||
.map(masking::Secret::new)
|
||||
})
|
||||
.collect::<Result<Vec<_>, _>>()?;
|
||||
payment_intent.order_details = Some(order_details_outside_value);
|
||||
};
|
||||
|
||||
if metadata_with_order_details.is_some() {
|
||||
payment_intent.metadata = metadata_with_order_details;
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user