mirror of
https://github.com/juspay/hyperswitch.git
synced 2025-10-30 01:27:31 +08:00
feat(payment-link): emit intent status to parent before rendering payment link UI (#7531)
Co-authored-by: hyperswitch-bot[bot] <148525504+hyperswitch-bot[bot]@users.noreply.github.com>
This commit is contained in:
@ -7944,6 +7944,7 @@ pub struct PaymentLinkDetails {
|
|||||||
pub background_colour: Option<String>,
|
pub background_colour: Option<String>,
|
||||||
pub sdk_ui_rules: Option<HashMap<String, HashMap<String, String>>>,
|
pub sdk_ui_rules: Option<HashMap<String, HashMap<String, String>>>,
|
||||||
pub payment_link_ui_rules: Option<HashMap<String, HashMap<String, String>>>,
|
pub payment_link_ui_rules: Option<HashMap<String, HashMap<String, String>>>,
|
||||||
|
pub status: api_enums::IntentStatus,
|
||||||
pub enable_button_only_on_form_ready: bool,
|
pub enable_button_only_on_form_ready: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -191,7 +191,7 @@ pub async fn form_payment_link_data(
|
|||||||
let merchant_name = capitalize_first_char(&payment_link_config.seller_name);
|
let merchant_name = capitalize_first_char(&payment_link_config.seller_name);
|
||||||
let payment_link_status = check_payment_link_status(session_expiry);
|
let payment_link_status = check_payment_link_status(session_expiry);
|
||||||
|
|
||||||
let is_terminal_state = check_payment_link_invalid_conditions(
|
let is_payment_link_terminal_state = check_payment_link_invalid_conditions(
|
||||||
payment_intent.status,
|
payment_intent.status,
|
||||||
&[
|
&[
|
||||||
storage_enums::IntentStatus::Cancelled,
|
storage_enums::IntentStatus::Cancelled,
|
||||||
@ -201,9 +201,11 @@ pub async fn form_payment_link_data(
|
|||||||
storage_enums::IntentStatus::RequiresMerchantAction,
|
storage_enums::IntentStatus::RequiresMerchantAction,
|
||||||
storage_enums::IntentStatus::Succeeded,
|
storage_enums::IntentStatus::Succeeded,
|
||||||
storage_enums::IntentStatus::PartiallyCaptured,
|
storage_enums::IntentStatus::PartiallyCaptured,
|
||||||
|
storage_enums::IntentStatus::RequiresCustomerAction,
|
||||||
],
|
],
|
||||||
);
|
);
|
||||||
if is_terminal_state || payment_link_status == api_models::payments::PaymentLinkStatus::Expired
|
if is_payment_link_terminal_state
|
||||||
|
|| payment_link_status == api_models::payments::PaymentLinkStatus::Expired
|
||||||
{
|
{
|
||||||
let status = match payment_link_status {
|
let status = match payment_link_status {
|
||||||
api_models::payments::PaymentLinkStatus::Active => {
|
api_models::payments::PaymentLinkStatus::Active => {
|
||||||
@ -211,7 +213,7 @@ pub async fn form_payment_link_data(
|
|||||||
PaymentLinkStatusWrap::IntentStatus(payment_intent.status)
|
PaymentLinkStatusWrap::IntentStatus(payment_intent.status)
|
||||||
}
|
}
|
||||||
api_models::payments::PaymentLinkStatus::Expired => {
|
api_models::payments::PaymentLinkStatus::Expired => {
|
||||||
if is_terminal_state {
|
if is_payment_link_terminal_state {
|
||||||
logger::info!("displaying status page as the requested payment link has reached terminal state with payment status as {:?}", payment_intent.status);
|
logger::info!("displaying status page as the requested payment link has reached terminal state with payment status as {:?}", payment_intent.status);
|
||||||
PaymentLinkStatusWrap::IntentStatus(payment_intent.status)
|
PaymentLinkStatusWrap::IntentStatus(payment_intent.status)
|
||||||
} else {
|
} else {
|
||||||
@ -292,6 +294,7 @@ pub async fn form_payment_link_data(
|
|||||||
payment_button_text_colour: payment_link_config.payment_button_text_colour.clone(),
|
payment_button_text_colour: payment_link_config.payment_button_text_colour.clone(),
|
||||||
sdk_ui_rules: payment_link_config.sdk_ui_rules.clone(),
|
sdk_ui_rules: payment_link_config.sdk_ui_rules.clone(),
|
||||||
payment_link_ui_rules: payment_link_config.payment_link_ui_rules.clone(),
|
payment_link_ui_rules: payment_link_config.payment_link_ui_rules.clone(),
|
||||||
|
status: payment_intent.status,
|
||||||
enable_button_only_on_form_ready: payment_link_config.enable_button_only_on_form_ready,
|
enable_button_only_on_form_ready: payment_link_config.enable_button_only_on_form_ready,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@ -181,6 +181,30 @@ var hyper = null;
|
|||||||
|
|
||||||
const translations = getTranslations(window.__PAYMENT_DETAILS.locale);
|
const translations = getTranslations(window.__PAYMENT_DETAILS.locale);
|
||||||
|
|
||||||
|
var isFramed = false;
|
||||||
|
try {
|
||||||
|
isFramed = window.parent.location !== window.location;
|
||||||
|
|
||||||
|
// If parent's window object is restricted, DOMException is
|
||||||
|
// thrown which concludes that the webpage is iframed
|
||||||
|
} catch (err) {
|
||||||
|
isFramed = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Trigger - on boot
|
||||||
|
* Use - emit latest payment status to parent window
|
||||||
|
*/
|
||||||
|
function emitPaymentStatus(paymentDetails) {
|
||||||
|
var message = {
|
||||||
|
payment: {
|
||||||
|
status: paymentDetails.status,
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
window.parent.postMessage(message, "*");
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Trigger - init function invoked once the script tag is loaded
|
* Trigger - init function invoked once the script tag is loaded
|
||||||
* Use
|
* Use
|
||||||
@ -190,13 +214,16 @@ const translations = getTranslations(window.__PAYMENT_DETAILS.locale);
|
|||||||
* - Initialize event listeners for updating UI on screen size changes
|
* - Initialize event listeners for updating UI on screen size changes
|
||||||
* - Initialize SDK
|
* - Initialize SDK
|
||||||
**/
|
**/
|
||||||
|
|
||||||
|
|
||||||
function boot() {
|
function boot() {
|
||||||
|
|
||||||
// @ts-ignore
|
// @ts-ignore
|
||||||
var paymentDetails = window.__PAYMENT_DETAILS;
|
var paymentDetails = window.__PAYMENT_DETAILS;
|
||||||
|
|
||||||
|
// Emit latest payment status
|
||||||
|
if (isFramed) {
|
||||||
|
emitPaymentStatus(paymentDetails);
|
||||||
|
}
|
||||||
|
|
||||||
if (paymentDetails.display_sdk_only) {
|
if (paymentDetails.display_sdk_only) {
|
||||||
hide(".checkout-page")
|
hide(".checkout-page")
|
||||||
var sdkDisplayWidth = document.querySelector('.hyper-checkout-sdk');
|
var sdkDisplayWidth = document.querySelector('.hyper-checkout-sdk');
|
||||||
|
|||||||
@ -137,6 +137,10 @@ body > div {
|
|||||||
font-size: 13px;
|
font-size: 13px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.hidden {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
|
||||||
.ellipsis-container-2 {
|
.ellipsis-container-2 {
|
||||||
height: 2.5em;
|
height: 2.5em;
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
|
|||||||
@ -16,7 +16,7 @@
|
|||||||
{{ rendered_js }}
|
{{ rendered_js }}
|
||||||
</script>
|
</script>
|
||||||
</head>
|
</head>
|
||||||
<body onload="boot()">
|
<body onload="boot()" class="hidden">
|
||||||
<div>
|
<div>
|
||||||
<div class="hyper-checkout-status-wrap">
|
<div class="hyper-checkout-status-wrap">
|
||||||
<div id="hyper-checkout-status-header"></div>
|
<div id="hyper-checkout-status-header"></div>
|
||||||
|
|||||||
@ -52,8 +52,8 @@ function invertToBW(color, bw, asArr) {
|
|||||||
? hexToRgbArray(options.black)
|
? hexToRgbArray(options.black)
|
||||||
: options.black
|
: options.black
|
||||||
: asArr
|
: asArr
|
||||||
? hexToRgbArray(options.white)
|
? hexToRgbArray(options.white)
|
||||||
: options.white;
|
: options.white;
|
||||||
}
|
}
|
||||||
function invert(color, bw) {
|
function invert(color, bw) {
|
||||||
if (bw === void 0) {
|
if (bw === void 0) {
|
||||||
@ -87,6 +87,31 @@ window.state = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
const translations = getTranslations(window.__PAYMENT_DETAILS.locale);
|
const translations = getTranslations(window.__PAYMENT_DETAILS.locale);
|
||||||
|
|
||||||
|
var isFramed = false;
|
||||||
|
try {
|
||||||
|
isFramed = window.parent.location !== window.location;
|
||||||
|
|
||||||
|
// If parent's window object is restricted, DOMException is
|
||||||
|
// thrown which concludes that the webpage is iframed
|
||||||
|
} catch (err) {
|
||||||
|
isFramed = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Trigger - on boot
|
||||||
|
* Use - emit latest payment status to parent window
|
||||||
|
*/
|
||||||
|
function emitPaymentStatus(paymentDetails) {
|
||||||
|
var message = {
|
||||||
|
payment: {
|
||||||
|
status: paymentDetails.status,
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
window.parent.postMessage(message, "*");
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Trigger - init function invoked once the script tag is loaded
|
* Trigger - init function invoked once the script tag is loaded
|
||||||
* Use
|
* Use
|
||||||
@ -100,20 +125,43 @@ function boot() {
|
|||||||
// @ts-ignore
|
// @ts-ignore
|
||||||
var paymentDetails = window.__PAYMENT_DETAILS;
|
var paymentDetails = window.__PAYMENT_DETAILS;
|
||||||
|
|
||||||
// Attach document icon
|
// Emit latest payment status
|
||||||
if (paymentDetails.merchant_logo) {
|
if (isFramed) {
|
||||||
var link = document.createElement("link");
|
emitPaymentStatus(paymentDetails);
|
||||||
link.rel = "icon";
|
|
||||||
link.href = paymentDetails.merchant_logo;
|
|
||||||
link.type = "image/x-icon";
|
|
||||||
document.head.appendChild(link);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Render status details
|
if (shouldRenderUI(paymentDetails)) {
|
||||||
renderStatusDetails(paymentDetails);
|
removeClass("body", "hidden");
|
||||||
|
// Attach document icon
|
||||||
|
if (paymentDetails.merchant_logo) {
|
||||||
|
var link = document.createElement("link");
|
||||||
|
link.rel = "icon";
|
||||||
|
link.href = paymentDetails.merchant_logo;
|
||||||
|
link.type = "image/x-icon";
|
||||||
|
document.head.appendChild(link);
|
||||||
|
}
|
||||||
|
|
||||||
// Add event listeners
|
// Render status details
|
||||||
initializeEventListeners(paymentDetails);
|
renderStatusDetails(paymentDetails);
|
||||||
|
|
||||||
|
// Add event listeners
|
||||||
|
initializeEventListeners(paymentDetails);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Trigger - on boot
|
||||||
|
* Use - Check if UI should be rendered based on some conditions
|
||||||
|
* @returns {Boolean}
|
||||||
|
*/
|
||||||
|
function shouldRenderUI(paymentDetails) {
|
||||||
|
var status = paymentDetails.status;
|
||||||
|
if (isFramed) {
|
||||||
|
switch (status) {
|
||||||
|
case "requires_customer_action": return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -158,6 +206,7 @@ function renderStatusDetails(paymentDetails) {
|
|||||||
).toTimeString();
|
).toTimeString();
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case "requires_customer_action":
|
||||||
case "processing":
|
case "processing":
|
||||||
statusDetails.imageSource = "https://live.hyperswitch.io/payment-link-assets/pending.png";
|
statusDetails.imageSource = "https://live.hyperswitch.io/payment-link-assets/pending.png";
|
||||||
statusDetails.message = translations.paymentTakingLonger;
|
statusDetails.message = translations.paymentTakingLonger;
|
||||||
@ -279,7 +328,7 @@ function renderStatusDetails(paymentDetails) {
|
|||||||
var innerText =
|
var innerText =
|
||||||
secondsLeft === 0
|
secondsLeft === 0
|
||||||
? translations.redirecting
|
? translations.redirecting
|
||||||
: translations.redirectingIn + secondsLeft + " "+translations.seconds;
|
: translations.redirectingIn + secondsLeft + " " + translations.seconds;
|
||||||
// @ts-ignore
|
// @ts-ignore
|
||||||
statusRedirectTextNode.innerText = innerText;
|
statusRedirectTextNode.innerText = innerText;
|
||||||
if (secondsLeft === 0) {
|
if (secondsLeft === 0) {
|
||||||
@ -341,5 +390,18 @@ function initializeEventListeners(paymentDetails) {
|
|||||||
if (statusRedirectTextNode instanceof HTMLDivElement) {
|
if (statusRedirectTextNode instanceof HTMLDivElement) {
|
||||||
statusRedirectTextNode.style.color = contrastBWColor;
|
statusRedirectTextNode.style.color = contrastBWColor;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
function addClass(id, className) {
|
||||||
|
var element = document.querySelector(id);
|
||||||
|
if (element instanceof HTMLElement) {
|
||||||
|
element.classList.add(className);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function removeClass(id, className) {
|
||||||
|
var element = document.querySelector(id);
|
||||||
|
if (element instanceof HTMLElement) {
|
||||||
|
element.classList.remove(className);
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user