feat(router): add poll ability in external 3ds authorization flow (#4393)

Co-authored-by: hyperswitch-bot[bot] <148525504+hyperswitch-bot[bot]@users.noreply.github.com>
This commit is contained in:
Sai Harsha Vardhan
2024-04-22 21:06:47 +05:30
committed by GitHub
parent 4851da1595
commit 447655382b
11 changed files with 358 additions and 88 deletions

View File

@ -1,11 +1,12 @@
use std::{marker::PhantomData, str::FromStr};
use api_models::enums::{DisputeStage, DisputeStatus};
use common_enums::RequestIncrementalAuthorization;
use common_enums::{IntentStatus, RequestIncrementalAuthorization};
#[cfg(feature = "payouts")]
use common_utils::{crypto::Encryptable, pii::Email};
use common_utils::{errors::CustomResult, ext_traits::AsyncExt};
use error_stack::{report, ResultExt};
use maud::{html, PreEscaped};
use router_env::{instrument, tracing};
use uuid::Uuid;
@ -23,7 +24,7 @@ use crate::{
types::{
self, domain,
storage::{self, enums},
ErrorResponse,
ErrorResponse, PollConfig,
},
utils::{generate_id, generate_uuid, OptionExt, ValueExt},
};
@ -1090,6 +1091,96 @@ pub async fn get_profile_id_from_business_details(
}
}
pub fn get_poll_id(merchant_id: String, unique_id: String) -> String {
format!("poll_{}_{}", merchant_id, unique_id)
}
pub fn get_external_authentication_request_poll_id(payment_id: &String) -> String {
format!("external_authentication_{}", payment_id)
}
pub fn get_html_redirect_response_for_external_authentication(
return_url_with_query_params: String,
payment_response: &api_models::payments::PaymentsResponse,
payment_id: String,
poll_config: &PollConfig,
) -> RouterResult<String> {
// if intent_status is requires_customer_action then set poll_id, fetch poll config and do a poll_status post message, else do open_url post message to redirect to return_url
let html = match payment_response.status {
IntentStatus::RequiresCustomerAction => {
// Request poll id sent to client for retrieve_poll_status api
let req_poll_id = get_external_authentication_request_poll_id(&payment_id);
let poll_frequency = poll_config.frequency;
let poll_delay_in_secs = poll_config.delay_in_secs;
html! {
head {
title { "Redirect Form" }
(PreEscaped(format!(r#"
<script>
let return_url = "{return_url_with_query_params}";
let poll_status_data = {{
'poll_id': '{req_poll_id}',
'frequency': '{poll_frequency}',
'delay_in_secs': '{poll_delay_in_secs}',
'return_url_with_query_params': return_url
}};
try {{
// if inside iframe, send post message to parent for redirection
if (window.self !== window.parent) {{
window.top.postMessage({{poll_status: poll_status_data}}, '*')
// if parent, redirect self to return_url
}} else {{
window.location.href = return_url
}}
}}
catch(err) {{
// if error occurs, send post message to parent and wait for 10 secs to redirect. if doesn't redirect, redirect self to return_url
window.top.postMessage({{poll_status: poll_status_data}}, '*')
setTimeout(function() {{
window.location.href = return_url
}}, 10000);
console.log(err.message)
}}
</script>
"#)))
}
}
.into_string()
},
_ => {
html! {
head {
title { "Redirect Form" }
(PreEscaped(format!(r#"
<script>
let return_url = "{return_url_with_query_params}";
try {{
// if inside iframe, send post message to parent for redirection
if (window.self !== window.parent) {{
window.top.postMessage({{openurl: return_url}}, '*')
// if parent, redirect self to return_url
}} else {{
window.location.href = return_url
}}
}}
catch(err) {{
// if error occurs, send post message to parent and wait for 10 secs to redirect. if doesn't redirect, redirect self to return_url
window.top.postMessage({{openurl: return_url}}, '*')
setTimeout(function() {{
window.location.href = return_url
}}, 10000);
console.log(err.message)
}}
</script>
"#)))
}
}
.into_string()
},
};
Ok(html)
}
#[inline]
pub fn get_flow_name<F>() -> RouterResult<String> {
Ok(std::any::type_name::<F>()