feat(actionhandler): allow actions to opt out of window-closed monitoring - #274
Draft
roshan-gorasia-cko wants to merge 4 commits into
Draft
feat(actionhandler): allow actions to opt out of window-closed monitoring#274roshan-gorasia-cko wants to merge 4 commits into
roshan-gorasia-cko wants to merge 4 commits into
Conversation
…ring
Some gateways (e.g. MercadoPago cash) transiently close and reopen the
redirect payment window/tab. The ActionHandler's 500ms monitor polls
window.closed and treats a closed window as a cancellation, firing a
spurious "customer.canceled" ({ reason: "tab_closed" }) that kills an
otherwise-valid payment.
Add a listenToWindowClosed option (default true) to ActionHandlerOptions.
When false, the monitor skips all window.closed detection and relies on
explicit cancellation / postMessage completion instead. Wire it from the
no_listen_to_window_closed customer_action metadata flag in the url and
redirect flows (same mechanism as the existing no_iframe flag).
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Bumps the version so the active bundle is traceable via the ProcessOut-JS-Version request header during staging testing. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
The vanilla APM redirect opens the hosted checkout page in a new tab; the ActionHandler polling window.closed lives on the *parent* page, while the no_listen_to_window_closed metadata is only seen by the checkout page in the *child* tab. So the previous handleCardActions-only wiring never reached the handler that raises the spurious "customer.canceled". - Child: when handleCardActions sees the flag and a window.opener exists, postMessage the opener with a new "disable-window-close-monitoring" checkout-namespace action. - Parent: listenEvents handles that action by flipping options.listenToWindowClosed to false on the live monitor, without terminating the flow, so it keeps waiting for the real outcome. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Diagnostics and mitigation for the "cancels as soon as the APM page opens" race, where the redirect tab navigates to the gateway login page before the checkout tab's disable-window-close-monitoring message is received. - debugLog helper: mirrors traces to console + telemetry (tagged apm-window-monitoring, carries SCRIPT_VERSION) at every decision point: window opened, popup-blocked, isCanceled cancel, closed-window cancel, every inbound checkout message (with elapsed timings), and the disable-monitoring send/receive. - 2s startup grace window: a window-closed report (or access error) within the first 2s is logged but does not cancel, giving a late disable message time to land. Explicit user cancellation is unaffected. - Bump version to 1.9.11. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What
Stops processout.js from raising a spurious
customer.canceled({ reason: "tab_closed" }) when a gateway (e.g. MercadoPago cash) transiently closes and reopens its redirect window/tab, driven by ano_listen_to_window_closedaction-metadata flag.Why
In the vanilla APM redirect, the hosted checkout page opens in a new tab. The
ActionHandlerthat pollswindow.closedruns on the parent page, but theno_listen_to_window_closedmetadata (from tessel9'sCreatePaymentFieldTV) is only seen by the checkout page in the child tab. So a handler that only reads the metadata locally never reaches the monitor that actually throws the error.How
actionhandler.tslistenToWindowClosedoption (defaulttrue) onActionHandlerOptions. The 500ms monitor skips allwindow.closeddetection when it'sfalse. Explicit cancellation and postMessage-driven completion are unaffected.listenEventshandles a newdisable-window-close-monitoringcheckout-namespace action by flippingoptions.listenToWindowClosedtofalseon the live monitor without terminating the flow (keeps waiting for the real success/cancel/error).processout.ts(handleCardActions)customer_action.metadata.no_listen_to_window_closed === "true"(same mechanism asno_iframe).ActionHandlerOptionsfor theurl/redirectflows.window.openerpresent), postMessages the opener thedisable-window-close-monitoringaction so the parent monitor stops treating the closed tab as a cancel.1.9.9→1.9.10for traceability via theProcessOut-JS-Versionheader.Deployment dependency
Both the merchant page and the hosted checkout page must run this build (≥
1.9.10) — the parent needs the receiver, the child needs the sender. Backend flag comes from tessel9 processout/tessel9#7230 (scoped tomercadopagomxcash).Testing
customer.canceled. VerifyProcessOut-JS-Version: 1.9.10in request headers.🤖 Generated with Claude Code