使用Selenium+C#操作第三方支付页时遇JSON.stringify报错问题
解决方案:Selenium C# 第三方支付页面跳转后JSON.stringify报错问题
错误原因
这个报错是因为第三方支付页面的JS代码可能覆盖了全局的JSON.stringify方法,导致Selenium内部调用该方法时失败;也可能是页面未完全加载就执行操作,或者支付输入区域在iframe中未切换上下文。
具体解决步骤
1. 确保页面完全加载后再操作
跳转后不要立即执行输入,先等待页面加载完成,或者等待目标输入元素可交互:
// 等待页面加载完成(document.readyState为complete) WebDriverManager.CurrentWebDriver.WaitUntil(d => ((IJavaScriptExecutor)d).ExecuteScript("return document.readyState").ToString() == "complete"); // 显式等待银行卡输入框可交互 var wait = new WebDriverWait(WebDriverManager.CurrentWebDriver, TimeSpan.FromSeconds(15)); var cardInput = wait.Until(ExpectedConditions.ElementToBeClickable(By.CssSelector("input[name='cardNumber']")));
2. 重新注入JSON.stringify方法
如果页面确实覆盖了全局JSON对象,在执行操作前重新注入标准的JSON.stringify实现:
// 注入polyfill修复JSON.stringify WebDriverManager.CurrentWebDriver.ExecuteJavaScript(@" if (!window.JSON || typeof JSON.stringify !== 'function') { window.JSON = window.JSON || {}; JSON.stringify = function(value, replacer, space) { var i, len, key, val; var indent = '', gap = ''; if (typeof space === 'number') { for (i = 0; i < space; i++) gap += ' '; } else if (typeof space === 'string') gap = space; function str(key, holder) { var arr = [], partial, value = holder[key]; if (value && typeof value === 'object' && typeof value.toJSON === 'function') { value = value.toJSON(key); } if (typeof replacer === 'function') value = replacer.call(holder, key, value); switch (typeof value) { case 'string': return '"' + value.replace(/[\\"\x00-\x1f\x7f-\x9f]/g, function(c) { var hex = c.charCodeAt(0).toString(16); return '\\' + (hex.length < 2 ? '0' + hex : hex); }) + '"'; case 'number': return isFinite(value) ? String(value) : 'null'; case 'boolean': case 'null': return String(value); case 'object': if (!value) return 'null'; if (value instanceof Array) { for (i = 0, len = value.length; i < len; i++) { arr[i] = str(i, value) || 'null'; } partial = arr.length === 0 ? '[]' : gap ? '[\n' + gap + arr.join(',\n' + gap) + '\n]' : '[' + arr.join(',') + ']'; return partial; } for (key in value) { if (Object.prototype.hasOwnProperty.call(value, key)) { partial = str(key, value); if (partial) arr.push('"' + key + '":' + (gap ? ' ' : '') + partial); } } partial = arr.length === 0 ? '{}' : gap ? '{\n' + gap + arr.join(',\n' + gap) + '\n}' : '{' + arr.join(',') + '}'; return partial; } } return str('', {'': value}); }; } ");
3. 检查并切换iframe上下文
第三方支付页面通常会用iframe承载银行卡输入区域,跳转后需要切换到对应的iframe:
// 等待iframe加载完成并切换 var paymentIframe = wait.Until(ExpectedConditions.ElementExists(By.CssSelector("iframe[src*='payment']"))); WebDriverManager.CurrentWebDriver.SwitchTo().Frame(paymentIframe); // 执行银行卡输入操作 cardInput.SendKeys("1234 5678 9012 3456"); // 操作完成后切回主页面 WebDriverManager.CurrentWebDriver.SwitchTo().DefaultContent();
4. 替换JavaScript点击为原生Selenium点击
如果JavaScript点击可能引发页面状态异常,尝试改用原生Selenium点击方法:
var element = WebDriverManager.CurrentWebDriver.AttemptToFindElement(cssSelector); element.Click(); // 替换ExecuteJavaScript点击
内容的提问来源于stack exchange,提问作者Shivam
相关产品推荐
相关产品推荐

