fix(core): fixed type metadata to accept other udf fields as well (#321)

This commit is contained in:
Abhishek
2023-01-09 16:10:10 +05:30
committed by GitHub
parent 3fe60b5a48
commit 8cffdc96ca
8 changed files with 48 additions and 29 deletions

1
Cargo.lock generated
View File

@ -321,6 +321,7 @@ name = "api_models"
version = "0.1.0" version = "0.1.0"
dependencies = [ dependencies = [
"common_utils", "common_utils",
"error-stack",
"frunk", "frunk",
"frunk_core", "frunk_core",
"masking", "masking",

View File

@ -6,6 +6,7 @@ edition = "2021"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies] [dependencies]
error-stack = "0.2.4"
frunk = "0.4.1" frunk = "0.4.1"
frunk_core = "0.4.1" frunk_core = "0.4.1"
serde = { version = "1.0.145", features = ["derive"] } serde = { version = "1.0.145", features = ["derive"] }

View File

@ -1,6 +1,6 @@
use std::num::NonZeroI64; use std::num::NonZeroI64;
use common_utils::pii; use common_utils::{errors, ext_traits::Encode, pii};
use masking::{PeekInterface, Secret}; use masking::{PeekInterface, Secret};
use router_derive::Setter; use router_derive::Setter;
use time::PrimitiveDateTime; use time::PrimitiveDateTime;
@ -15,11 +15,6 @@ pub enum PaymentOp {
Confirm, Confirm,
} }
#[derive(Default, Debug, serde::Deserialize, serde::Serialize, Clone)]
pub struct Metadata {
pub order_details: OrderDetails,
}
#[derive(Default, Debug, serde::Deserialize, serde::Serialize, Clone)] #[derive(Default, Debug, serde::Deserialize, serde::Serialize, Clone)]
#[serde(deny_unknown_fields)] #[serde(deny_unknown_fields)]
pub struct PaymentsRequest { pub struct PaymentsRequest {
@ -53,7 +48,7 @@ pub struct PaymentsRequest {
pub billing: Option<Address>, pub billing: Option<Address>,
pub statement_descriptor_name: Option<String>, pub statement_descriptor_name: Option<String>,
pub statement_descriptor_suffix: Option<String>, pub statement_descriptor_suffix: Option<String>,
pub metadata: Option<serde_json::Value>, pub metadata: Option<Metadata>,
pub client_secret: Option<String>, pub client_secret: Option<String>,
pub mandate_data: Option<MandateData>, pub mandate_data: Option<MandateData>,
pub mandate_id: Option<String>, pub mandate_id: Option<String>,
@ -561,21 +556,25 @@ impl From<&VerifyRequest> for MandateValidationFields {
} }
} }
impl From<PaymentsRequest> for PaymentsResponse { impl TryFrom<PaymentsRequest> for PaymentsResponse {
fn from(item: PaymentsRequest) -> Self { type Error = error_stack::Report<errors::ParsingError>;
fn try_from(item: PaymentsRequest) -> Result<Self, Self::Error> {
let payment_id = match item.payment_id { let payment_id = match item.payment_id {
Some(PaymentIdType::PaymentIntentId(id)) => Some(id), Some(PaymentIdType::PaymentIntentId(id)) => Some(id),
_ => None, _ => None,
}; };
let metadata = item
Self { .metadata
.map(|a| Encode::<Metadata>::encode_to_value(&a))
.transpose()?;
Ok(Self {
payment_id, payment_id,
merchant_id: item.merchant_id, merchant_id: item.merchant_id,
setup_future_usage: item.setup_future_usage, setup_future_usage: item.setup_future_usage,
off_session: item.off_session, off_session: item.off_session,
shipping: item.shipping, shipping: item.shipping,
billing: item.billing, billing: item.billing,
metadata: item.metadata, metadata,
capture_method: item.capture_method, capture_method: item.capture_method,
payment_method: item.payment_method, payment_method: item.payment_method,
capture_on: item.capture_on, capture_on: item.capture_on,
@ -592,7 +591,7 @@ impl From<PaymentsRequest> for PaymentsResponse {
statement_descriptor_suffix: item.statement_descriptor_suffix, statement_descriptor_suffix: item.statement_descriptor_suffix,
mandate_data: item.mandate_data, mandate_data: item.mandate_data,
..Default::default() ..Default::default()
} })
} }
} }
@ -759,12 +758,19 @@ pub enum SupportedWallets {
Gpay, Gpay,
} }
#[derive(Debug, Default, serde::Deserialize, serde::Serialize, Clone)] #[derive(Debug, Default, Eq, PartialEq, serde::Deserialize, serde::Serialize, Clone)]
pub struct OrderDetails { pub struct OrderDetails {
pub product_name: String, pub product_name: String,
pub quantity: u16, pub quantity: u16,
} }
#[derive(Default, Debug, Eq, PartialEq, serde::Deserialize, serde::Serialize, Clone)]
pub struct Metadata {
pub order_details: Option<OrderDetails>,
#[serde(flatten)]
pub data: serde_json::Value,
}
#[derive(Debug, serde::Deserialize, serde::Serialize, Clone)] #[derive(Debug, serde::Deserialize, serde::Serialize, Clone)]
pub struct PaymentsSessionRequest { pub struct PaymentsSessionRequest {
pub payment_id: String, pub payment_id: String,

View File

@ -132,7 +132,7 @@ pub struct StripePaymentIntentRequest {
pub billing_details: Option<StripeBillingDetails>, pub billing_details: Option<StripeBillingDetails>,
pub statement_descriptor: Option<String>, pub statement_descriptor: Option<String>,
pub statement_descriptor_suffix: Option<String>, pub statement_descriptor_suffix: Option<String>,
pub metadata: Option<Value>, pub metadata: Option<api_models::payments::Metadata>,
pub client_secret: Option<pii::Secret<String>>, pub client_secret: Option<pii::Secret<String>>,
pub payment_method_options: Option<StripePaymentMethodOptions>, pub payment_method_options: Option<StripePaymentMethodOptions>,
} }
@ -277,6 +277,7 @@ pub struct StripePaymentIntentResponse {
pub customer: Option<String>, pub customer: Option<String>,
pub refunds: Option<Vec<refunds::RefundResponse>>, pub refunds: Option<Vec<refunds::RefundResponse>>,
pub mandate_id: Option<String>, pub mandate_id: Option<String>,
pub metadata: Option<Value>,
} }
impl From<payments::PaymentsResponse> for StripePaymentIntentResponse { impl From<payments::PaymentsResponse> for StripePaymentIntentResponse {
@ -294,6 +295,7 @@ impl From<payments::PaymentsResponse> for StripePaymentIntentResponse {
id: resp.payment_id, id: resp.payment_id,
refunds: resp.refunds, refunds: resp.refunds,
mandate_id: resp.mandate_id, mandate_id: resp.mandate_id,
metadata: resp.metadata,
} }
} }
} }

View File

@ -122,7 +122,7 @@ pub struct StripeSetupIntentRequest {
pub billing_details: Option<StripeBillingDetails>, pub billing_details: Option<StripeBillingDetails>,
pub statement_descriptor: Option<String>, pub statement_descriptor: Option<String>,
pub statement_descriptor_suffix: Option<String>, pub statement_descriptor_suffix: Option<String>,
pub metadata: Option<Value>, pub metadata: Option<api_models::payments::Metadata>,
pub client_secret: Option<pii::Secret<String>>, pub client_secret: Option<pii::Secret<String>>,
} }

View File

@ -171,7 +171,7 @@ where
FData: Send, FData: Send,
Op: Operation<F, Req> + Send + Sync + Clone, Op: Operation<F, Req> + Send + Sync + Clone,
Req: Debug, Req: Debug,
Res: transformers::ToResponse<Req, PaymentData<F>, Op> + From<Req>, Res: transformers::ToResponse<Req, PaymentData<F>, Op> + TryFrom<Req>,
// To create connector flow specific interface data // To create connector flow specific interface data
PaymentData<F>: ConstructFlowSpecificData<F, FData, types::PaymentsResponseData>, PaymentData<F>: ConstructFlowSpecificData<F, FData, types::PaymentsResponseData>,
types::RouterData<F, FData, types::PaymentsResponseData>: Feature<F, FData>, types::RouterData<F, FData, types::PaymentsResponseData>: Feature<F, FData>,

View File

@ -1,7 +1,7 @@
use std::marker::PhantomData; use std::marker::PhantomData;
use async_trait::async_trait; use async_trait::async_trait;
use common_utils::ext_traits::AsyncExt; use common_utils::ext_traits::{AsyncExt, Encode};
use error_stack::ResultExt; use error_stack::ResultExt;
use router_derive::PaymentOperation; use router_derive::PaymentOperation;
use router_env::{instrument, tracing}; use router_env::{instrument, tracing};
@ -143,7 +143,7 @@ impl<F: Send + Clone> GetTracker<F, PaymentData<F>, api::PaymentsRequest> for Pa
request, request,
shipping_address.clone().map(|x| x.address_id), shipping_address.clone().map(|x| x.address_id),
billing_address.clone().map(|x| x.address_id), billing_address.clone().map(|x| x.address_id),
), )?,
storage_scheme, storage_scheme,
) )
.await .await
@ -481,14 +481,21 @@ impl PaymentCreate {
request: &api::PaymentsRequest, request: &api::PaymentsRequest,
shipping_address_id: Option<String>, shipping_address_id: Option<String>,
billing_address_id: Option<String>, billing_address_id: Option<String>,
) -> storage::PaymentIntentNew { ) -> RouterResult<storage::PaymentIntentNew> {
let created_at @ modified_at @ last_synced = Some(common_utils::date_time::now()); let created_at @ modified_at @ last_synced = Some(common_utils::date_time::now());
let status = let status =
helpers::payment_intent_status_fsm(&request.payment_method_data, request.confirm); helpers::payment_intent_status_fsm(&request.payment_method_data, request.confirm);
let client_secret = let client_secret =
crate::utils::generate_id(consts::ID_LENGTH, format!("{payment_id}_secret").as_str()); crate::utils::generate_id(consts::ID_LENGTH, format!("{payment_id}_secret").as_str());
let (amount, currency) = (money.0, Some(money.1)); let (amount, currency) = (money.0, Some(money.1));
storage::PaymentIntentNew { let metadata = request
.metadata
.as_ref()
.map(|a| Encode::<api_models::payments::Metadata>::encode_to_value(&a))
.transpose()
.change_context(errors::ApiErrorResponse::InternalServerError)
.attach_printable("Encoding Metadata to value failed")?;
Ok(storage::PaymentIntentNew {
payment_id: payment_id.to_string(), payment_id: payment_id.to_string(),
merchant_id: merchant_id.to_string(), merchant_id: merchant_id.to_string(),
status, status,
@ -506,9 +513,9 @@ impl PaymentCreate {
billing_address_id, billing_address_id,
statement_descriptor_name: request.statement_descriptor_name.clone(), statement_descriptor_name: request.statement_descriptor_name.clone(),
statement_descriptor_suffix: request.statement_descriptor_suffix.clone(), statement_descriptor_suffix: request.statement_descriptor_suffix.clone(),
metadata: request.metadata.clone(), metadata,
..storage::PaymentIntentNew::default() ..storage::PaymentIntentNew::default()
} })
} }
#[instrument(skip_all)] #[instrument(skip_all)]

View File

@ -103,7 +103,7 @@ where
pub trait ToResponse<Req, D, Op> pub trait ToResponse<Req, D, Op>
where where
Self: From<Req>, Self: TryFrom<Req>,
Op: Debug, Op: Debug,
{ {
fn generate_response( fn generate_response(
@ -118,7 +118,7 @@ where
impl<F, Req, Op> ToResponse<Req, PaymentData<F>, Op> for api::PaymentsResponse impl<F, Req, Op> ToResponse<Req, PaymentData<F>, Op> for api::PaymentsResponse
where where
Self: From<Req>, Self: TryFrom<Req>,
F: Clone, F: Clone,
Op: Debug, Op: Debug,
{ {
@ -233,7 +233,7 @@ pub fn payments_to_payments_response<R, Op>(
operation: Op, operation: Op,
) -> RouterResponse<api::PaymentsResponse> ) -> RouterResponse<api::PaymentsResponse>
where where
api::PaymentsResponse: From<R>, api::PaymentsResponse: TryFrom<R>,
Op: Debug, Op: Debug,
{ {
let currency = payment_attempt let currency = payment_attempt
@ -256,7 +256,9 @@ where
.map_err(|_| errors::ApiErrorResponse::InternalServerError)?; .map_err(|_| errors::ApiErrorResponse::InternalServerError)?;
services::BachResponse::Form(form) services::BachResponse::Form(form)
} else { } else {
let mut response: api::PaymentsResponse = request.into(); let mut response: api::PaymentsResponse = request
.try_into()
.map_err(|_| errors::ApiErrorResponse::InternalServerError)?;
let mut next_action_response = None; let mut next_action_response = None;
if payment_intent.status == enums::IntentStatus::RequiresCustomerAction { if payment_intent.status == enums::IntentStatus::RequiresCustomerAction {
next_action_response = Some(api::NextAction { next_action_response = Some(api::NextAction {
@ -406,7 +408,7 @@ impl<F: Clone> TryFrom<PaymentData<F>> for types::PaymentsAuthorizeData {
.transpose() .transpose()
.unwrap_or_default(); .unwrap_or_default();
let order_details = parsed_metadata.map(|data| data.order_details); let order_details = parsed_metadata.and_then(|data| data.order_details);
Ok(Self { Ok(Self {
payment_method_data: { payment_method_data: {
@ -504,7 +506,7 @@ impl<F: Clone> TryFrom<PaymentData<F>> for types::PaymentsSessionData {
.transpose() .transpose()
.unwrap_or_default(); .unwrap_or_default();
let order_details = parsed_metadata.map(|data| data.order_details); let order_details = parsed_metadata.and_then(|data| data.order_details);
Ok(Self { Ok(Self {
amount: payment_data.amount.into(), amount: payment_data.amount.into(),