WebGL PayStation CLOSE event never triggers cancel (wrong undefined check)
Summary
In the WebGL PayStation widget integration, when a player closes the PayStation window manually, the Unity-side “payment canceled” callback is not triggered. This prevents the client from detecting cancellation in real time and can leave purchases in a “pending” state unless the game implements polling (inventory/order status) as a workaround.
Environment
- Unity WebGL build
- Xsolla Unity SDK (PayStation widget / embed flow)
- File:
Assets/Xsolla/Core/Plugins/paystation.jslib
Observed behavior
When the user closes PayStation manually:
Module.SendMessage('XsollaWebCallbacks', 'PublishPaymentCancel') is not sent
- Unity-side
XsollaWebCallbacks.PublishPaymentCancel() is not called
OrderTrackerByPaystationCallbacks.HandlePaymentCancel() is not executed
- tracking may continue and the order may stay in
new
- client code does not receive a “canceled by user” signal (often
onBrowseClosed is never invoked as a result)
Expected behavior
When the user closes PayStation manually:
- WebGL plugin should send
PublishPaymentCancel to Unity
- Unity-side order tracker should stop promptly and the game should be notified immediately (no polling needed for cancel)
Root cause analysis
The current WebGL plugin code treats “cancel” as:
if (data === 'undefined') {
Module.SendMessage('XsollaWebCallbacks', 'PublishPaymentCancel');
}
But in JavaScript, if data is missing it is the primitive undefined (or sometimes null), not the string 'undefined'.
Therefore the condition is always false and the cancel path never runs.
Reproduction (minimal)
- Start a WebGL build with Xsolla PayStation widget enabled.
- Initiate a purchase so the PayStation widget opens.
- Close the widget manually using the close button / overlay close / ESC (depending on configuration).
- Observe: Unity does not receive a cancellation callback.
Fix
Replace the string comparison with a proper JS check for undefined / null.
Patch (diff)
diff --git a/Assets/Xsolla/Core/Plugins/paystation.jslib b/Assets/Xsolla/Core/Plugins/paystation.jslib
index 6cece9b2cf..bb18dce06b 100644
--- a/Assets/Xsolla/Core/Plugins/paystation.jslib
+++ b/Assets/Xsolla/Core/Plugins/paystation.jslib
@@ -120,10 +120,11 @@ mergeInto(LibraryManager.library, {
});
XPayStationWidget.on(XPayStationWidget.eventTypes.CLOSE, function (event, data) {
- if (data === 'undefined') {
+ // data is usually undefined/null when user closes PayStation manually.
+ // Treat that case as "cancel" so the Unity side can stop tracking and react immediately.
+ if (typeof data === 'undefined' || data === null) {
Module.SendMessage('XsollaWebCallbacks', 'PublishPaymentCancel');
- }
- else {
+ } else {
Module.SendMessage('XsollaWebCallbacks', 'PublishPaymentStatusUpdate');
}
});
Final code snippet (for reference)
XPayStationWidget.on(XPayStationWidget.eventTypes.CLOSE, function (event, data) {
// data is usually undefined/null when user closes PayStation manually.
// Treat that case as "cancel" so the Unity side can stop tracking and react immediately.
if (typeof data === 'undefined' || data === null) {
Module.SendMessage('XsollaWebCallbacks', 'PublishPaymentCancel');
} else {
Module.SendMessage('XsollaWebCallbacks', 'PublishPaymentStatusUpdate');
}
});
Impact / why it matters
- Without this fix, WebGL clients cannot reliably detect user cancellation via SDK callbacks.
- Games are forced to implement polling (inventory/order status) to “unstick” the UI.
- This causes poor UX (stuck “processing purchase” states) and complicates integration.
Notes
This fix is safe: it only changes how the CLOSE payload is interpreted, aligning it with standard JavaScript behavior (undefined/null).
WebGL PayStation CLOSE event never triggers cancel (wrong
undefinedcheck)Summary
In the WebGL PayStation widget integration, when a player closes the PayStation window manually, the Unity-side “payment canceled” callback is not triggered. This prevents the client from detecting cancellation in real time and can leave purchases in a “pending” state unless the game implements polling (inventory/order status) as a workaround.
Environment
Assets/Xsolla/Core/Plugins/paystation.jslibObserved behavior
When the user closes PayStation manually:
Module.SendMessage('XsollaWebCallbacks', 'PublishPaymentCancel')is not sentXsollaWebCallbacks.PublishPaymentCancel()is not calledOrderTrackerByPaystationCallbacks.HandlePaymentCancel()is not executednewonBrowseClosedis never invoked as a result)Expected behavior
When the user closes PayStation manually:
PublishPaymentCancelto UnityRoot cause analysis
The current WebGL plugin code treats “cancel” as:
But in JavaScript, if
datais missing it is the primitiveundefined(or sometimesnull), not the string'undefined'.Therefore the condition is always false and the cancel path never runs.
Reproduction (minimal)
Fix
Replace the string comparison with a proper JS check for
undefined/null.Patch (diff)
Final code snippet (for reference)
Impact / why it matters
Notes
This fix is safe: it only changes how the CLOSE payload is interpreted, aligning it with standard JavaScript behavior (
undefined/null).