diff --git a/api-reference-v2/openapi_spec.json b/api-reference-v2/openapi_spec.json index 13014a44e0e..d6ff0619a8c 100644 --- a/api-reference-v2/openapi_spec.json +++ b/api-reference-v2/openapi_spec.json @@ -13076,11 +13076,6 @@ "type": "string", "description": "URL for rendering the open payment link" }, - "secure_link": { - "type": "string", - "description": "URL for rendering the secure payment link", - "nullable": true - }, "payment_link_id": { "type": "string", "description": "Identifier for the payment link" @@ -19297,11 +19292,6 @@ } ], "nullable": true - }, - "secure_link": { - "type": "string", - "description": "Secure payment link (with security checks and listing saved payment methods)", - "nullable": true } } }, diff --git a/api-reference/openapi_spec.json b/api-reference/openapi_spec.json index d218e4d2074..895c7131d39 100644 --- a/api-reference/openapi_spec.json +++ b/api-reference/openapi_spec.json @@ -16192,11 +16192,6 @@ "type": "string", "description": "URL for rendering the open payment link" }, - "secure_link": { - "type": "string", - "description": "URL for rendering the secure payment link", - "nullable": true - }, "payment_link_id": { "type": "string", "description": "Identifier for the payment link" @@ -23847,11 +23842,6 @@ } ], "nullable": true - }, - "secure_link": { - "type": "string", - "description": "Secure payment link (with security checks and listing saved payment methods)", - "nullable": true } } }, diff --git a/crates/api_models/src/payments.rs b/crates/api_models/src/payments.rs index b6152cc9787..02011850ad2 100644 --- a/crates/api_models/src/payments.rs +++ b/crates/api_models/src/payments.rs @@ -6967,8 +6967,6 @@ pub struct RetrievePaymentLinkRequest { pub struct PaymentLinkResponse { /// URL for rendering the open payment link pub link: String, - /// URL for rendering the secure payment link - pub secure_link: Option, /// Identifier for the payment link pub payment_link_id: String, } @@ -6997,8 +6995,6 @@ pub struct RetrievePaymentLinkResponse { pub status: PaymentLinkStatus, #[schema(value_type = Option)] pub currency: Option, - /// Secure payment link (with security checks and listing saved payment methods) - pub secure_link: Option, } #[derive(Clone, Debug, serde::Deserialize, ToSchema, serde::Serialize)] diff --git a/crates/router/src/core/payment_link.rs b/crates/router/src/core/payment_link.rs index 477803c92a2..53acd3f348c 100644 --- a/crates/router/src/core/payment_link.rs +++ b/crates/router/src/core/payment_link.rs @@ -285,98 +285,113 @@ pub async fn form_payment_link_data( )) } -pub async fn initiate_secure_payment_link_flow( - state: SessionState, - merchant_account: domain::MerchantAccount, - key_store: domain::MerchantKeyStore, - merchant_id: common_utils::id_type::MerchantId, - payment_id: common_utils::id_type::PaymentId, +#[derive(Clone, Copy, Debug, Eq, PartialEq)] +pub enum PaymentLinkType { + SecurePaymentLink, + OpenPaymentLink, +} + +impl PaymentLinkType { + fn get_requested_payment_link_type(request_headers: &header::HeaderMap) -> Self { + match request_headers + .get("sec-fetch-dest") + .and_then(|v| v.to_str().ok()) + { + Some("iframe") => Self::SecurePaymentLink, + _ => Self::OpenPaymentLink, + } + } +} + +fn generate_secure_payment_link( + state: &SessionState, request_headers: &header::HeaderMap, + payment_link: &PaymentLink, + payment_link_config: PaymentLinkConfig, + payment_details: api_models::payments::PaymentLinkDetails, + css_script: String, ) -> RouterResponse { - let (payment_link, payment_link_details, payment_link_config) = - form_payment_link_data(&state, merchant_account, key_store, merchant_id, payment_id) - .await?; - validator::validate_secure_payment_link_render_request( request_headers, - &payment_link, + payment_link, &payment_link_config, )?; + let secure_payment_link_details = api_models::payments::SecurePaymentLinkDetails { + enabled_saved_payment_method: payment_link_config.enabled_saved_payment_method, + hide_card_nickname_field: payment_link_config.hide_card_nickname_field, + show_card_form_by_default: payment_link_config.show_card_form_by_default, + payment_link_details: payment_details.to_owned(), + payment_button_text: payment_link_config.payment_button_text.clone(), + }; + let js_script = format!( + "window.__PAYMENT_DETAILS = {}", + serde_json::to_string(&secure_payment_link_details) + .change_context(errors::ApiErrorResponse::InternalServerError) + .attach_printable("Failed to serialize PaymentLinkData")? + ); + let html_meta_tags = get_meta_tags_html(&payment_details); + let payment_link_data = services::PaymentLinkFormData { + js_script, + sdk_url: state.conf.payment_link.sdk_url.clone(), + css_script: css_script.clone(), + html_meta_tags, + }; + let allowed_domains = payment_link_config + .allowed_domains + .clone() + .ok_or(report!(errors::ApiErrorResponse::InternalServerError)) + .attach_printable_lazy(|| { + format!( + "Invalid list of allowed_domains found - {:?}", + payment_link_config.allowed_domains.clone() + ) + })?; - let css_script = get_color_scheme_css(&payment_link_config); - - match payment_link_details { - PaymentLinkData::PaymentLinkStatusDetails(ref status_details) => { - let js_script = get_js_script(&payment_link_details)?; - let payment_link_error_data = services::PaymentLinkStatusData { - js_script, - css_script, - }; - logger::info!( - "payment link data, for building payment link status page {:?}", - status_details - ); - Ok(services::ApplicationResponse::PaymentLinkForm(Box::new( - services::api::PaymentLinkAction::PaymentLinkStatus(payment_link_error_data), - ))) - } - PaymentLinkData::PaymentLinkDetails(link_details) => { - let secure_payment_link_details = api_models::payments::SecurePaymentLinkDetails { - enabled_saved_payment_method: payment_link_config.enabled_saved_payment_method, - hide_card_nickname_field: payment_link_config.hide_card_nickname_field, - show_card_form_by_default: payment_link_config.show_card_form_by_default, - payment_link_details: *link_details.to_owned(), - payment_button_text: payment_link_config.payment_button_text, - }; - let js_script = format!( - "window.__PAYMENT_DETAILS = {}", - serde_json::to_string(&secure_payment_link_details) - .change_context(errors::ApiErrorResponse::InternalServerError) - .attach_printable("Failed to serialize PaymentLinkData")? - ); - let html_meta_tags = get_meta_tags_html(&link_details); - let payment_link_data = services::PaymentLinkFormData { - js_script, - sdk_url: state.conf.payment_link.sdk_url.clone(), - css_script, - html_meta_tags, - }; - let allowed_domains = payment_link_config - .allowed_domains - .clone() - .ok_or(report!(errors::ApiErrorResponse::InternalServerError)) - .attach_printable_lazy(|| { - format!( - "Invalid list of allowed_domains found - {:?}", - payment_link_config.allowed_domains.clone() - ) - })?; - - if allowed_domains.is_empty() { - return Err(report!(errors::ApiErrorResponse::InternalServerError)) - .attach_printable_lazy(|| { - format!( - "Invalid list of allowed_domains found - {:?}", - payment_link_config.allowed_domains.clone() - ) - }); - } + if allowed_domains.is_empty() { + return Err(report!(errors::ApiErrorResponse::InternalServerError)).attach_printable_lazy( + || { + format!( + "Invalid list of allowed_domains found - {:?}", + payment_link_config.allowed_domains.clone() + ) + }, + ); + } + let link_data = GenericLinks { + allowed_domains, + data: GenericLinksData::SecurePaymentLink(payment_link_data), + locale: DEFAULT_LOCALE.to_string(), + }; + logger::info!( + "payment link data, for building secure payment link {:?}", + link_data + ); - let link_data = GenericLinks { - allowed_domains, - data: GenericLinksData::SecurePaymentLink(payment_link_data), - locale: DEFAULT_LOCALE.to_string(), - }; - logger::info!( - "payment link data, for building secure payment link {:?}", - link_data - ); + Ok(services::ApplicationResponse::GenericLinkForm(Box::new( + link_data, + ))) +} - Ok(services::ApplicationResponse::GenericLinkForm(Box::new( - link_data, - ))) - } - } +fn generate_open_payment_link( + state: &SessionState, + payment_details: api_models::payments::PaymentLinkDetails, + js_script: String, + css_script: String, +) -> RouterResponse { + let html_meta_tags = get_meta_tags_html(&payment_details); + let payment_link_data = services::PaymentLinkFormData { + js_script, + sdk_url: state.conf.payment_link.sdk_url.clone(), + css_script, + html_meta_tags, + }; + logger::info!( + "payment link data, for building open payment link {:?}", + payment_link_data + ); + Ok(services::ApplicationResponse::PaymentLinkForm(Box::new( + services::api::PaymentLinkAction::PaymentLinkFormData(payment_link_data), + ))) } pub async fn initiate_payment_link_flow( @@ -385,13 +400,15 @@ pub async fn initiate_payment_link_flow( key_store: domain::MerchantKeyStore, merchant_id: common_utils::id_type::MerchantId, payment_id: common_utils::id_type::PaymentId, + request_headers: &header::HeaderMap, ) -> RouterResponse { - let (_, payment_details, payment_link_config) = + let (payment_link, payment_details, payment_link_config) = form_payment_link_data(&state, merchant_account, key_store, merchant_id, payment_id) .await?; - let css_script = get_color_scheme_css(&payment_link_config); let js_script = get_js_script(&payment_details)?; + let requested_payment_link_type = + PaymentLinkType::get_requested_payment_link_type(request_headers); match payment_details { PaymentLinkData::PaymentLinkStatusDetails(status_details) => { @@ -407,22 +424,19 @@ pub async fn initiate_payment_link_flow( services::api::PaymentLinkAction::PaymentLinkStatus(payment_link_error_data), ))) } - PaymentLinkData::PaymentLinkDetails(payment_details) => { - let html_meta_tags = get_meta_tags_html(&payment_details); - let payment_link_data = services::PaymentLinkFormData { - js_script, - sdk_url: state.conf.payment_link.sdk_url.clone(), + PaymentLinkData::PaymentLinkDetails(payment_details) => match requested_payment_link_type { + PaymentLinkType::SecurePaymentLink => generate_secure_payment_link( + &state, + request_headers, + &payment_link, + payment_link_config, + *payment_details, css_script, - html_meta_tags, - }; - logger::info!( - "payment link data, for building open payment link {:?}", - payment_link_data - ); - Ok(services::ApplicationResponse::PaymentLinkForm(Box::new( - services::api::PaymentLinkAction::PaymentLinkFormData(payment_link_data), - ))) - } + ), + PaymentLinkType::OpenPaymentLink => { + generate_open_payment_link(&state, *payment_details, js_script, css_script) + } + }, } } diff --git a/crates/router/src/core/payment_link/validator.rs b/crates/router/src/core/payment_link/validator.rs index 0968c8301aa..1fffec4cd7c 100644 --- a/crates/router/src/core/payment_link/validator.rs +++ b/crates/router/src/core/payment_link/validator.rs @@ -26,41 +26,6 @@ pub fn validate_secure_payment_link_render_request( ) })?; - // Validate secure_link was generated - if payment_link.secure_link.clone().is_none() { - return Err(report!(errors::ApiErrorResponse::InvalidRequestUrl)).attach_printable_lazy( - || { - format!( - "Secure payment link was not generated for {}\nmissing secure_link", - link_id - ) - }, - ); - } - - // Fetch destination is "iframe" - match request_headers.get("sec-fetch-dest").and_then(|v| v.to_str().ok()) { - Some("iframe") => Ok(()), - Some(requestor) => Err(report!(errors::ApiErrorResponse::AccessForbidden { - resource: "payment_link".to_string(), - })) - .attach_printable_lazy(|| { - format!( - "Access to payment_link [{}] is forbidden when requested through {}", - link_id, requestor - ) - }), - None => Err(report!(errors::ApiErrorResponse::AccessForbidden { - resource: "payment_link".to_string(), - })) - .attach_printable_lazy(|| { - format!( - "Access to payment_link [{}] is forbidden when sec-fetch-dest is not present in request headers", - link_id - ) - }), - }?; - // Validate origin / referer let domain_in_req = { let origin_or_referer = request_headers diff --git a/crates/router/src/core/payments/operations/payment_create.rs b/crates/router/src/core/payments/operations/payment_create.rs index 2bb751d4e14..9cf564c9d62 100644 --- a/crates/router/src/core/payments/operations/payment_create.rs +++ b/crates/router/src/core/payments/operations/payment_create.rs @@ -1571,16 +1571,6 @@ async fn create_payment_link( locale_str.clone(), ); - let secure_link = payment_link_config.allowed_domains.as_ref().map(|_| { - format!( - "{}/payment_link/s/{}/{}?locale={}", - domain_name, - merchant_id.get_string_repr(), - payment_id.get_string_repr(), - locale_str, - ) - }); - let payment_link_config_encoded_value = payment_link_config.encode_to_value().change_context( errors::ApiErrorResponse::InvalidDataValue { field_name: "payment_link_config", @@ -1601,7 +1591,7 @@ async fn create_payment_link( description, payment_link_config: Some(payment_link_config_encoded_value), profile_id: Some(profile_id), - secure_link, + secure_link: None, //It is deprecated now., }; let payment_link_db = db .insert_payment_link(payment_link_req) @@ -1612,7 +1602,6 @@ async fn create_payment_link( Ok(Some(api_models::payments::PaymentLinkResponse { link: payment_link_db.link_to_pay.clone(), - secure_link: payment_link_db.secure_link, payment_link_id: payment_link_db.payment_link_id, })) } diff --git a/crates/router/src/routes/app.rs b/crates/router/src/routes/app.rs index fffb3eab09e..c54f3449ffe 100644 --- a/crates/router/src/routes/app.rs +++ b/crates/router/src/routes/app.rs @@ -1744,10 +1744,6 @@ impl PaymentLink { web::resource("{merchant_id}/{payment_id}") .route(web::get().to(payment_link::initiate_payment_link)), ) - .service( - web::resource("s/{merchant_id}/{payment_id}") - .route(web::get().to(payment_link::initiate_secure_payment_link)), - ) .service( web::resource("status/{merchant_id}/{payment_id}") .route(web::get().to(payment_link::payment_link_status)), diff --git a/crates/router/src/routes/payment_link.rs b/crates/router/src/routes/payment_link.rs index 361367c7d27..f5c05444e0d 100644 --- a/crates/router/src/routes/payment_link.rs +++ b/crates/router/src/routes/payment_link.rs @@ -61,40 +61,6 @@ pub async fn initiate_payment_link( let flow = Flow::PaymentLinkInitiate; let (merchant_id, payment_id) = path.into_inner(); - let payload = api_models::payments::PaymentLinkInitiateRequest { - payment_id, - merchant_id: merchant_id.clone(), - }; - Box::pin(api::server_wrap( - flow, - state, - &req, - payload.clone(), - |state, auth: auth::AuthenticationData, _, _| { - initiate_payment_link_flow( - state, - auth.merchant_account, - auth.key_store, - payload.merchant_id.clone(), - payload.payment_id.clone(), - ) - }, - &crate::services::authentication::MerchantIdAuth(merchant_id), - api_locking::LockAction::NotApplicable, - )) - .await -} - -pub async fn initiate_secure_payment_link( - state: web::Data, - req: actix_web::HttpRequest, - path: web::Path<( - common_utils::id_type::MerchantId, - common_utils::id_type::PaymentId, - )>, -) -> impl Responder { - let flow = Flow::PaymentSecureLinkInitiate; - let (merchant_id, payment_id) = path.into_inner(); let payload = api_models::payments::PaymentLinkInitiateRequest { payment_id, merchant_id: merchant_id.clone(), @@ -106,7 +72,7 @@ pub async fn initiate_secure_payment_link( &req, payload.clone(), |state, auth: auth::AuthenticationData, _, _| { - initiate_secure_payment_link_flow( + initiate_payment_link_flow( state, auth.merchant_account, auth.key_store, diff --git a/crates/router/src/types/api/payment_link.rs b/crates/router/src/types/api/payment_link.rs index 3d50db35fc4..85cb539d411 100644 --- a/crates/router/src/types/api/payment_link.rs +++ b/crates/router/src/types/api/payment_link.rs @@ -30,7 +30,6 @@ impl PaymentLinkResponseExt for RetrievePaymentLinkResponse { expiry: payment_link.fulfilment_time, currency: payment_link.currency, status, - secure_link: payment_link.secure_link, }) } } diff --git a/crates/router/src/types/transformers.rs b/crates/router/src/types/transformers.rs index 2348fae72ab..7ceeb74b584 100644 --- a/crates/router/src/types/transformers.rs +++ b/crates/router/src/types/transformers.rs @@ -1746,7 +1746,6 @@ impl ForeignFrom<(storage::PaymentLink, payments::PaymentLinkStatus)> description: payment_link_config.description, currency: payment_link_config.currency, status, - secure_link: payment_link_config.secure_link, } } }