PAYATHON 2026

如何阻止 Chrome 和 Edge 显示已保存的付款方式

支付老李

结论

这通常不是普通的历史输入自动补全,而是 Chromium 的支付信息自动填充。Chrome 和 Edge 会根据字段的 name、id、关联的 <label>、占位文字、输入类型、长度限制及周边字段的语义,判断它是否可能是银行卡号、有效期等付款字段。无论是 autocomplete="off",还是非标准值 autocomplete="nope",都无法可靠关闭这类建议。

处理时,先准确声明字段的用途,并删除容易触发信用卡识别的命名。如果没有适用的标准 autocomplete token,可以尝试 autocomplete="one-time-code"。它在不少 Chromium 环境中可以避开支付信息填充,但并不是规范定义的“禁用付款建议”开关。如果仍然无效,再考虑修改字段名,或让字段在获得焦点后才解除只读状态。

为什么会被识别为付款字段

Chromium 判断字段用途时,不只读取 autocomplete,还可能参考以下特征:

  • name、id 或标签中含有 card、credit、cc、number、account、exp、expiry、month、year 等词。
  • 字段使用数字输入或数字键盘,并设置了接近银行卡号、有效期的长度。
  • 附近还有被识别为持卡人姓名、月份、年份或安全码的输入框。
  • Razor 生成的完整字段名包含容易误判的模型属性名,例如 PaymentDate.Number。
  • 页面结构与常见的结账表单相似。
  • Chromium 曾保存过该页面或类似字段的自动填充分类。

所以,即使单个字段设置了 autocomplete="off",浏览器仍可能根据启发式分类显示付款方式。

首选方案:声明正确的字段语义

如果字段属于生日,可以使用标准的生日自动填充 token:

<input
    type="text"
    name="birthDay"
    id="birthDay"
    inputmode="numeric"
    autocomplete="bday-day"
    maxlength="2">

<input
    type="text"
    name="birthMonth"
    id="birthMonth"
    inputmode="numeric"
    autocomplete="bday-month"
    maxlength="2">

<input
    type="text"
    name="birthYear"
    id="birthYear"
    inputmode="numeric"
    autocomplete="bday-year"
    maxlength="4">

如果业务允许使用完整的日期字段,它通常比拆分后的数字字段更不容易被误判:

<label for="eventDate">日期</label>
<input
    type="date"
    id="eventDate"
    name="eventDate"
    autocomplete="off">

bday-* 仅适用于生日,不能为了隐藏下拉框而将它用于普通业务日期。

普通日期组成部分的处理方式

HTML 没有适用于所有普通日期中日、月、年组成部分的通用自动填充 token。这种情况下可以尝试:

<label for="scheduleDay">日期中的日</label>
<input
    type="text"
    id="scheduleDay"
    name="scheduleDay"
    inputmode="numeric"
    pattern="[0-9]*"
    maxlength="2"
    autocomplete="one-time-code">

使用 type="text" 配合 inputmode="numeric",既能保留移动设备的数字键盘,也能避开 type="number" 的部分行为。服务端仍需验证输入是否为合法数字,以及它是否处于有效的日期范围内。

one-time-code 的标准含义是一次性验证码,并非专门用于关闭信用卡自动填充。它可能改变浏览器对字段的分类,但具体效果会因 Chromium 版本、操作系统和密码管理扩展而异,需要在目标环境中测试。

检查并修改字段名称

字段名应准确表达用途,避免使用含义模糊或接近支付字段的名称:

<!-- 容易引起误判 -->
<input name="cardDateNumber" id="cardDateNumber">

<!-- 更明确 -->
<input name="serviceDateDay" id="serviceDateDay">

标签和占位文字也要说明字段的真实用途:

<label for="serviceDateDay">服务日期(日)</label>
<input
    id="serviceDateDay"
    name="serviceDateDay"
    type="text"
    inputmode="numeric"
    maxlength="2"
    autocomplete="one-time-code"
    aria-describedby="serviceDateDayHint">

<span id="serviceDateDayHint">请输入 1 到 31</span>

不要使用 cc-number、cc-exp、cc-exp-month、cc-exp-year 等 token。这些值会明确告诉浏览器,该字段属于付款信息。

Razor Pages 示例

使用 asp-for 时,最终生成的 name 和 id 可能影响 Chromium 的判断。排查时应检查浏览器实际渲染的 HTML,不能只看 .cshtml 源码。

<label asp-for="ServiceDateDay">服务日期(日)</label>
<input asp-for="ServiceDateDay"
       type="text"
       inputmode="numeric"
       pattern="[0-9]*"
       maxlength="2"
       autocomplete="one-time-code" />
<span asp-validation-for="ServiceDateDay"></span>

模型属性也应采用语义清楚的名称:

[BindProperty]
public int? ServiceDateDay { get; set; }

直接修改 name 会影响 Razor Pages 的模型绑定。如果必须更改提交名称,需要同时调整绑定模型或手动读取请求值。不建议只用 jQuery 临时改名。

最后的兼容性方案

如果修改名称和语义标记后仍然无效,可以让字段初始处于只读状态,等用户主动聚焦时再解除。某些版本的自动填充扫描不会将初始只读字段视为候选:

<input
    id="serviceDateDay"
    name="serviceDateDay"
    type="text"
    inputmode="numeric"
    maxlength="2"
    autocomplete="off"
    readonly>
document.querySelector('#serviceDateDay')
    ?.addEventListener('focus', function () {
        this.removeAttribute('readonly');
    }, { once: true });

这只是兼容性绕行方案,其行为没有 HTML 标准保证。使用前要测试键盘导航、屏幕阅读器、移动端输入和表单校验,确认不会影响可访问性。

注意事项

  • autocomplete="nope" 不是标准 token。浏览器通常会将未知值视为无效值,因此不能依赖它。
  • 没有任何一个属性能够保证在所有 Chrome、Edge、密码管理器和浏览器版本中禁止付款方式建议。
  • 不建议添加隐藏的伪信用卡字段来吸引自动填充。这种做法不稳定,还可能引起可访问性和数据提交问题。
  • 浏览器扩展也可能生成类似的下拉框。可以使用无扩展的浏览器配置或隐私窗口进行对比测试,确认建议是否来自 Chromium 自带的支付自动填充。
  • 通常较稳妥的做法是使用含义明确的 label、id 和 name,选择合适的标准 autocomplete token,并避开与银行卡字段相似的命名和布局。

备注:内容仅供参考。