feat(payments_v2): add finish redirection endpoint (#6549)

Co-authored-by: hyperswitch-bot[bot] <148525504+hyperswitch-bot[bot]@users.noreply.github.com>
Co-authored-by: hrithikesh026 <hrithikesh.vm@juspay.in>
This commit is contained in:
Narayan Bhat
2024-11-15 14:06:48 +05:30
committed by GitHub
parent 0b63efbd42
commit 0805a937b1
29 changed files with 534 additions and 136 deletions

View File

@ -159,6 +159,9 @@ pub const MAX_STATEMENT_DESCRIPTOR_LENGTH: u16 = 22;
/// Payout flow identifier used for performing GSM operations
pub const PAYOUT_FLOW_STR: &str = "payout_flow";
/// length of the publishable key
pub const PUBLISHABLE_KEY_LENGTH: u16 = 39;
/// The number of bytes allocated for the hashed connector transaction ID.
/// Total number of characters equals CONNECTOR_TRANSACTION_ID_HASH_BYTES times 2.
pub const CONNECTOR_TRANSACTION_ID_HASH_BYTES: usize = 25;

View File

@ -66,10 +66,15 @@ pub enum ApiEventsType {
},
Routing,
ResourceListAPI,
#[cfg(feature = "v1")]
PaymentRedirectionResponse {
connector: Option<String>,
payment_id: Option<id_type::PaymentId>,
},
#[cfg(feature = "v2")]
PaymentRedirectionResponse {
payment_id: id_type::GlobalPaymentId,
},
Gsm,
// TODO: This has to be removed once the corresponding apiEventTypes are created
Miscellaneous,

View File

@ -37,7 +37,9 @@ use time::PrimitiveDateTime;
use utoipa::ToSchema;
use crate::{
consts::{self, MAX_DESCRIPTION_LENGTH, MAX_STATEMENT_DESCRIPTOR_LENGTH},
consts::{
self, MAX_DESCRIPTION_LENGTH, MAX_STATEMENT_DESCRIPTOR_LENGTH, PUBLISHABLE_KEY_LENGTH,
},
errors::{CustomResult, ParsingError, PercentageError, ValidationError},
fp_utils::when,
};
@ -639,6 +641,17 @@ impl Url {
pub fn into_inner(self) -> url::Url {
self.0
}
/// Add query params to the url
pub fn add_query_params(mut self, (key, value): (&str, &str)) -> Self {
let url = self
.0
.query_pairs_mut()
.append_pair(key, value)
.finish()
.clone();
Self(url)
}
}
impl<DB> ToSql<sql_types::Text, DB> for Url
@ -1064,7 +1077,7 @@ crate::impl_to_sql_from_sql_json!(ChargeRefunds);
/// A common type of domain type that can be used for fields that contain a string with restriction of length
#[derive(Debug, Clone, Serialize, Hash, PartialEq, Eq, AsExpression)]
#[diesel(sql_type = sql_types::Text)]
pub(crate) struct LengthString<const MAX_LENGTH: u16, const MIN_LENGTH: u8>(String);
pub(crate) struct LengthString<const MAX_LENGTH: u16, const MIN_LENGTH: u16>(String);
/// Error generated from violation of constraints for MerchantReferenceId
#[derive(Debug, Error, PartialEq, Eq)]
@ -1075,10 +1088,10 @@ pub(crate) enum LengthStringError {
#[error("the minimum required length for this field is {0}")]
/// Minimum length of string violated
MinLengthViolated(u8),
MinLengthViolated(u16),
}
impl<const MAX_LENGTH: u16, const MIN_LENGTH: u8> LengthString<MAX_LENGTH, MIN_LENGTH> {
impl<const MAX_LENGTH: u16, const MIN_LENGTH: u16> LengthString<MAX_LENGTH, MIN_LENGTH> {
/// Generates new [MerchantReferenceId] from the given input string
pub fn from(input_string: Cow<'static, str>) -> Result<Self, LengthStringError> {
let trimmed_input_string = input_string.trim().to_string();
@ -1089,7 +1102,7 @@ impl<const MAX_LENGTH: u16, const MIN_LENGTH: u8> LengthString<MAX_LENGTH, MIN_L
Err(LengthStringError::MaxLengthViolated(MAX_LENGTH))
})?;
when(length_of_input_string < u16::from(MIN_LENGTH), || {
when(length_of_input_string < MIN_LENGTH, || {
Err(LengthStringError::MinLengthViolated(MIN_LENGTH))
})?;
@ -1101,7 +1114,7 @@ impl<const MAX_LENGTH: u16, const MIN_LENGTH: u8> LengthString<MAX_LENGTH, MIN_L
}
}
impl<'de, const MAX_LENGTH: u16, const MIN_LENGTH: u8> Deserialize<'de>
impl<'de, const MAX_LENGTH: u16, const MIN_LENGTH: u16> Deserialize<'de>
for LengthString<MAX_LENGTH, MIN_LENGTH>
{
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
@ -1113,7 +1126,7 @@ impl<'de, const MAX_LENGTH: u16, const MIN_LENGTH: u8> Deserialize<'de>
}
}
impl<DB, const MAX_LENGTH: u16, const MIN_LENGTH: u8> FromSql<sql_types::Text, DB>
impl<DB, const MAX_LENGTH: u16, const MIN_LENGTH: u16> FromSql<sql_types::Text, DB>
for LengthString<MAX_LENGTH, MIN_LENGTH>
where
DB: Backend,
@ -1125,7 +1138,7 @@ where
}
}
impl<DB, const MAX_LENGTH: u16, const MIN_LENGTH: u8> ToSql<sql_types::Text, DB>
impl<DB, const MAX_LENGTH: u16, const MIN_LENGTH: u16> ToSql<sql_types::Text, DB>
for LengthString<MAX_LENGTH, MIN_LENGTH>
where
DB: Backend,
@ -1136,7 +1149,7 @@ where
}
}
impl<DB, const MAX_LENGTH: u16, const MIN_LENGTH: u8> Queryable<sql_types::Text, DB>
impl<DB, const MAX_LENGTH: u16, const MIN_LENGTH: u16> Queryable<sql_types::Text, DB>
for LengthString<MAX_LENGTH, MIN_LENGTH>
where
DB: Backend,
@ -1518,3 +1531,54 @@ pub trait ConnectorTransactionIdTrait {
self.get_optional_connector_transaction_id()
}
}
/// Domain type for PublishableKey
#[derive(Debug, Clone, PartialEq, Eq, serde::Deserialize, serde::Serialize, AsExpression)]
#[diesel(sql_type = sql_types::Text)]
pub struct PublishableKey(LengthString<PUBLISHABLE_KEY_LENGTH, PUBLISHABLE_KEY_LENGTH>);
impl PublishableKey {
/// Create a new PublishableKey Domain type without any length check from a static str
pub fn generate(env_prefix: &'static str) -> Self {
let publishable_key_string = format!("pk_{env_prefix}_{}", uuid::Uuid::now_v7().simple());
Self(LengthString::new_unchecked(publishable_key_string))
}
/// Get the string representation of the PublishableKey
pub fn get_string_repr(&self) -> &str {
&self.0 .0
}
}
impl<DB> Queryable<sql_types::Text, DB> for PublishableKey
where
DB: Backend,
Self: FromSql<sql_types::Text, DB>,
{
type Row = Self;
fn build(row: Self::Row) -> deserialize::Result<Self> {
Ok(row)
}
}
impl<DB> FromSql<sql_types::Text, DB> for PublishableKey
where
DB: Backend,
LengthString<PUBLISHABLE_KEY_LENGTH, PUBLISHABLE_KEY_LENGTH>: FromSql<sql_types::Text, DB>,
{
fn from_sql(bytes: DB::RawValue<'_>) -> deserialize::Result<Self> {
let val = LengthString::<PUBLISHABLE_KEY_LENGTH, PUBLISHABLE_KEY_LENGTH>::from_sql(bytes)?;
Ok(Self(val))
}
}
impl<DB> ToSql<sql_types::Text, DB> for PublishableKey
where
DB: Backend,
LengthString<PUBLISHABLE_KEY_LENGTH, PUBLISHABLE_KEY_LENGTH>: ToSql<sql_types::Text, DB>,
{
fn to_sql<'b>(&'b self, out: &mut Output<'b, '_, DB>) -> diesel::serialize::Result {
self.0.to_sql(out)
}
}