Skip to content

Commit 2a4f5d1

Browse files
sahkalgithub-actions[bot]kashif-mKashif
authored
feat(router): added Payment link new design (#2731)
Co-authored-by: Sahkal Poddar <[email protected]> Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com> Co-authored-by: Kashif <[email protected]> Co-authored-by: Kashif <[email protected]>
1 parent 20c4226 commit 2a4f5d1

File tree

7 files changed

+737
-667
lines changed

7 files changed

+737
-667
lines changed

crates/api_models/src/admin.rs

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -463,9 +463,8 @@ pub struct PaymentLinkConfig {
463463
#[serde(deny_unknown_fields)]
464464

465465
pub struct PaymentLinkColorSchema {
466-
pub primary_color: Option<String>,
467-
pub primary_accent_color: Option<String>,
468-
pub secondary_color: Option<String>,
466+
pub background_primary_color: Option<String>,
467+
pub sdk_theme: Option<String>,
469468
}
470469

471470
#[derive(Clone, Debug, Deserialize, ToSchema, Serialize)]

crates/api_models/src/payments.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3150,6 +3150,7 @@ pub struct PaymentLinkDetails {
31503150
pub merchant_logo: String,
31513151
pub return_url: String,
31523152
pub merchant_name: String,
3153-
pub order_details: Vec<pii::SecretSerdeValue>,
3153+
pub order_details: Option<Vec<OrderDetailsWithAmount>>,
31543154
pub max_items_visible_after_collapse: i8,
3155+
pub sdk_theme: Option<String>,
31553156
}

crates/common_enums/Cargo.toml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,9 +12,9 @@ dummy_connector = []
1212

1313
[dependencies]
1414
diesel = { version = "2.1.0", features = ["postgres"] }
15-
serde = { version = "1.0.160", features = [ "derive" ] }
15+
serde = { version = "1.0.160", features = ["derive"] }
1616
serde_json = "1.0.96"
17-
strum = { version = "0.25", features = [ "derive" ] }
17+
strum = { version = "0.25", features = ["derive"] }
1818
time = { version = "0.3.21", features = ["serde", "serde-well-known", "std"] }
1919
utoipa = { version = "3.3.0", features = ["preserve_order"] }
2020

crates/common_utils/src/consts.rs

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,3 +29,15 @@ pub const SURCHARGE_PERCENTAGE_PRECISION_LENGTH: u8 = 2;
2929

3030
/// Header Key for application overhead of a request
3131
pub const X_HS_LATENCY: &str = "x-hs-latency";
32+
33+
/// SDK Default Theme const
34+
pub const DEFAULT_SDK_THEME: &str = "#7EA8F6";
35+
36+
/// Default Payment Link Background color
37+
pub const DEFAULT_BACKGROUND_COLOR: &str = "#E5E5E5";
38+
39+
/// Default product Img Link
40+
pub const DEFAULT_PRODUCT_IMG: &str = "https://i.imgur.com/On3VtKF.png";
41+
42+
/// Default Merchant Logo Link
43+
pub const DEFAULT_MERCHANT_LOGO: &str = "https://i.imgur.com/RfxPFQo.png";

crates/router/src/core/payment_link.rs

Lines changed: 65 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,12 @@
11
use api_models::admin as admin_types;
2+
use common_utils::{
3+
consts::{
4+
DEFAULT_BACKGROUND_COLOR, DEFAULT_MERCHANT_LOGO, DEFAULT_PRODUCT_IMG, DEFAULT_SDK_THEME,
5+
},
6+
ext_traits::ValueExt,
7+
};
28
use error_stack::{IntoReport, ResultExt};
3-
use masking::PeekInterface;
9+
use masking::{PeekInterface, Secret};
410

511
use super::errors::{self, RouterResult, StorageErrorExt};
612
use crate::{
@@ -76,12 +82,7 @@ pub async fn intiate_payment_link_flow(
7682
})
7783
.transpose()?;
7884

79-
let order_details = payment_intent
80-
.order_details
81-
.get_required_value("order_details")
82-
.change_context(errors::ApiErrorResponse::MissingRequiredField {
83-
field_name: "order_details",
84-
})?;
85+
let order_details = validate_order_details(payment_intent.order_details)?;
8586

8687
let return_url = if let Some(payment_create_return_url) = payment_intent.return_url {
8788
payment_create_return_url
@@ -99,6 +100,9 @@ pub async fn intiate_payment_link_flow(
99100
payment_intent.client_secret,
100101
)?;
101102

103+
let (default_sdk_theme, default_background_color) =
104+
(DEFAULT_SDK_THEME, DEFAULT_BACKGROUND_COLOR);
105+
102106
let payment_details = api_models::payments::PaymentLinkDetails {
103107
amount: payment_intent.amount,
104108
currency,
@@ -116,13 +120,25 @@ pub async fn intiate_payment_link_flow(
116120
client_secret,
117121
merchant_logo: payment_link_config
118122
.clone()
119-
.map(|pl_metadata| pl_metadata.merchant_logo.unwrap_or_default())
123+
.map(|pl_config| {
124+
pl_config
125+
.merchant_logo
126+
.unwrap_or(DEFAULT_MERCHANT_LOGO.to_string())
127+
})
120128
.unwrap_or_default(),
121129
max_items_visible_after_collapse: 3,
130+
sdk_theme: payment_link_config.clone().and_then(|pl_config| {
131+
pl_config
132+
.color_scheme
133+
.map(|color| color.sdk_theme.unwrap_or(default_sdk_theme.to_string()))
134+
}),
122135
};
123136

124137
let js_script = get_js_script(payment_details)?;
125-
let css_script = get_color_scheme_css(payment_link_config.clone());
138+
let css_script = get_color_scheme_css(
139+
payment_link_config.clone(),
140+
default_background_color.to_string(),
141+
);
126142
let payment_link_data = services::PaymentLinkFormData {
127143
js_script,
128144
sdk_url: state.conf.payment_link.sdk_url.clone(),
@@ -149,38 +165,21 @@ fn get_js_script(
149165

150166
fn get_color_scheme_css(
151167
payment_link_config: Option<api_models::admin::PaymentLinkConfig>,
168+
default_primary_color: String,
152169
) -> String {
153-
let (default_primary_color, default_accent_color, default_secondary_color) = (
154-
"#C6C7C8".to_string(),
155-
"#6A8EF5".to_string(),
156-
"#0C48F6".to_string(),
157-
);
158-
159-
let (primary_color, primary_accent_color, secondary_color) = payment_link_config
170+
let background_primary_color = payment_link_config
160171
.and_then(|pl_config| {
161172
pl_config.color_scheme.map(|color| {
162-
(
163-
color.primary_color.unwrap_or(default_primary_color.clone()),
164-
color
165-
.primary_accent_color
166-
.unwrap_or(default_accent_color.clone()),
167-
color
168-
.secondary_color
169-
.unwrap_or(default_secondary_color.clone()),
170-
)
173+
color
174+
.background_primary_color
175+
.unwrap_or(default_primary_color.clone())
171176
})
172177
})
173-
.unwrap_or((
174-
default_primary_color,
175-
default_accent_color,
176-
default_secondary_color,
177-
));
178+
.unwrap_or(default_primary_color);
178179

179180
format!(
180181
":root {{
181-
--primary-color: {primary_color};
182-
--primary-accent-color: {primary_accent_color};
183-
--secondary-color: {secondary_color};
182+
--primary-color: {background_primary_color};
184183
}}"
185184
)
186185
}
@@ -203,3 +202,36 @@ fn validate_sdk_requirements(
203202
})?;
204203
Ok((pub_key, currency, client_secret))
205204
}
205+
206+
fn validate_order_details(
207+
order_details: Option<Vec<Secret<serde_json::Value>>>,
208+
) -> Result<
209+
Option<Vec<api_models::payments::OrderDetailsWithAmount>>,
210+
error_stack::Report<errors::ApiErrorResponse>,
211+
> {
212+
let order_details = order_details
213+
.map(|order_details| {
214+
order_details
215+
.iter()
216+
.map(|data| {
217+
data.to_owned()
218+
.parse_value("OrderDetailsWithAmount")
219+
.change_context(errors::ApiErrorResponse::InvalidDataValue {
220+
field_name: "OrderDetailsWithAmount",
221+
})
222+
.attach_printable("Unable to parse OrderDetailsWithAmount")
223+
})
224+
.collect::<Result<Vec<api_models::payments::OrderDetailsWithAmount>, _>>()
225+
})
226+
.transpose()?;
227+
228+
let updated_order_details = order_details.map(|mut order_details| {
229+
for order in order_details.iter_mut() {
230+
if order.product_img_link.is_none() {
231+
order.product_img_link = Some(DEFAULT_PRODUCT_IMG.to_string());
232+
}
233+
}
234+
order_details
235+
});
236+
Ok(updated_order_details)
237+
}

0 commit comments

Comments
 (0)