From 0840163dcb1738b199724d129544423de8c3289c Mon Sep 17 00:00:00 2001 From: Mateusz Walesiak Date: Mon, 2 Jun 2025 09:14:45 +0200 Subject: [PATCH] feat(POS-1338): Implement ActionHandler instance binding (remedy cross-contamination) --- src/processout/actionhandler.ts | 40 ++++++++++++++++++++++++++++++--- 1 file changed, 37 insertions(+), 3 deletions(-) diff --git a/src/processout/actionhandler.ts b/src/processout/actionhandler.ts index 62ac9eeb..cd63a79a 100644 --- a/src/processout/actionhandler.ts +++ b/src/processout/actionhandler.ts @@ -194,10 +194,16 @@ module ProcessOut { protected options: ActionHandlerOptions; /** - * listenerCount is the number of listener that were set - * @type {number} + * Action handler static counter to track events + * @var {number} */ - protected static listenerCount = 0; + protected static listenerCount: number = 0; + + /** + * Unique identifier for this ActionHandler instance + * @var {string} + */ + protected instanceUID: string; /** * newWindowName is the name of the new windows created by the @@ -217,6 +223,11 @@ module ProcessOut { if (!this.options) this.options = new ActionHandlerOptions(); + // Generate unique identifier for this instance to prevent cross-contamination + this.instanceUID = `action_${Math.random().toString(36).substring(7)}`; + + // Note: setResourceID() should be invoked when calling specific action methods + // We need to create the wrapper beforehand if (this.options.flow == ActionFlow.IFrame) { var iframeWrapper = document.createElement("div"); @@ -466,6 +477,11 @@ module ProcessOut { if (data.namespace != Message.checkoutNamespace) return; + // Validate the message is intended for this specific ActionHandler instance to prevent cross-contamination + if (data.frameID && data.frameID !== this.instanceUID) { + return; // Message is for a different ActionHandler instance + } + // Not the latest listener anymore if (ActionHandler.listenerCount != cur) { // Reset the timer if it hasn't been done already @@ -551,6 +567,24 @@ module ProcessOut { return this.canceled; } + /** + * Set the resource ID for this ActionHandler instance + * @param {string} resourceID + * @return {void} + */ + public setResourceID(resourceID: string): void { + this.resourceID = resourceID; + } + + /** + * Get the unique instance ID for this ActionHandler + * This can be used by checkout pages to include in postMessage responses + * @return {string} + */ + public getInstanceUID(): string { + return this.instanceUID; + } + } }