PAYATHON 2026

如何创建支持支付信息 autofill 的 HTML form?

支付阿杰

结论

支付信息自动填充主要依赖标准的 autocomplete token,同时也会受到浏览器字段识别规则的影响。要让银行卡号、持卡人姓名和有效期得到正确识别,需要为每个 <input> 设置准确的 autocomplete、name 和 type 等属性,并采用语义清楚的表单结构。

cc-name 表示银行卡上显示的完整持卡人姓名。如果页面将姓和名拆成两个输入框,应分别使用:

  • cc-given-name:名
  • cc-family-name:姓

不要再调用 form.requestAutocomplete()。这个实验性 API 已被废弃,现代浏览器通常不再提供。支付信息下拉菜单是否出现,取决于用户保存的银行卡、页面安全性、用户操作以及浏览器内部策略,JavaScript 无法强制打开。

推荐写法

如果页面只需要一个“持卡人姓名”输入框,可以采用以下结构:

<form action="/payment" method="post" autocomplete="on">
  <div>
    <label for="card-number">银行卡号</label>
    <input
      id="card-number"
      name="card-number"
      type="text"
      inputmode="numeric"
      autocomplete="cc-number"
      required
    >
  </div>

  <div>
    <label for="cardholder-name">持卡人姓名</label>
    <input
      id="cardholder-name"
      name="cardholder-name"
      type="text"
      autocomplete="cc-name"
      required
    >
  </div>

  <div>
    <label for="expiry-month">有效期月份</label>
    <input
      id="expiry-month"
      name="expiry-month"
      type="text"
      inputmode="numeric"
      autocomplete="cc-exp-month"
      placeholder="MM"
      required
    >
  </div>

  <div>
    <label for="expiry-year">有效期年份</label>
    <input
      id="expiry-year"
      name="expiry-year"
      type="text"
      inputmode="numeric"
      autocomplete="cc-exp-year"
      placeholder="YYYY"
      required
    >
  </div>

  <div>
    <label for="security-code">安全码</label>
    <input
      id="security-code"
      name="security-code"
      type="text"
      inputmode="numeric"
      autocomplete="cc-csc"
      required
    >
  </div>

  <button type="submit">支付</button>
</form>

如果业务要求将姓名拆开,则应使用更具体的 token:

<div>
  <label for="given-name">名</label>
  <input
    id="given-name"
    name="given-name"
    type="text"
    autocomplete="cc-given-name"
    required
  >
</div>

<div>
  <label for="family-name">姓</label>
  <input
    id="family-name"
    name="family-name"
    type="text"
    autocomplete="cc-family-name"
    required
  >
</div>

不过在实际使用中,单个 cc-name 字段通常兼容性更好。许多浏览器保存的是完整的持卡人姓名,而不是分开的姓和名。如果支付接口允许,建议优先使用单字段设计。

有效期也可以使用单字段

银行卡有效期既可以拆分为月份和年份,也可以放在一个字段中:

<label for="card-expiry">有效期</label>
<input
  id="card-expiry"
  name="card-expiry"
  type="text"
  inputmode="numeric"
  autocomplete="cc-exp"
  placeholder="MM/YY"
  required
>

cc-exp 表示完整有效期,cc-exp-month 和 cc-exp-year 分别表示月份和年份。具体采用哪种形式,需要与支付服务商要求的数据格式一致。

浏览器填充的年份可能是两位或四位,例如 28 或 2028。提交前需要解析并验证,不能只依赖 maxlength 或占位文本。

为什么只写 cc-name 仍可能无效

autocomplete 只是提供给浏览器的语义提示,并非强制命令。浏览器还会判断:

  • 页面是否通过 HTTPS 加载;
  • 用户是否在浏览器中保存了银行卡;
  • 用户是否启用了付款方式自动填充;
  • 字段是否可见、可编辑;
  • <label>、name、id 和附近文本是否符合支付场景;
  • 字段是否位于跨域 <iframe> 中;
  • 页面是否存在可疑行为或处于不安全的上下文;
  • 浏览器、操作系统、地区和企业策略是否允许填充支付信息。

因此,有些网站即使没有完整设置 autocomplete 属性,仍能触发自动填充。浏览器也会根据字段名称、标签、布局和历史数据进行启发式识别。不过,这类识别并不是稳定的接口,不能作为实现依据。

表单实现时的注意事项

不要为银行卡字段设置 autocomplete="off"。部分浏览器可能会忽略该值,但它仍会让字段的语义变得不够明确。

也不要省略 name 属性。标准 token 主要写在 autocomplete 中,但清楚的 name 也有助于浏览器识别字段,例如:

name="cardholder-name"
name="card-number"
name="expiry-month"

不要用普通 <div> 模拟输入框,也不要隐藏真正的 <input>,再自行同步其中的内容。浏览器通常需要直接识别并填写可见的原生表单控件,才能完成支付信息自动填充。

银行卡号不适合使用 type="number",因为它可能引入数字步进、格式限制和前导零处理等问题。更合适的写法是:

type="text" inputmode="numeric" autocomplete="cc-number"

自动填充也不能代替表单验证。即使字段由浏览器填写,服务端仍须验证卡号、有效期和其他支付参数。银行卡数据还应交给合规的支付服务商处理,避免自己的服务器直接接触原始卡号和安全码。

JavaScript 不负责触发自动填充

不要继续使用以下代码:

form.requestAutocomplete();
event.preventDefault();

requestAutocomplete() 已经不是可靠的 Web API。正常情况下,只需处理表单提交:

form.addEventListener("submit", (event) => {
  event.preventDefault();

  // 验证数据,并交给支付服务商的 SDK 或支付接口处理。
});

event.preventDefault() 只能阻止表单的默认提交行为,无法让浏览器显示银行卡选择菜单。自动填充菜单通常会在用户聚焦或点击银行卡字段时,由浏览器自行显示。

比较稳妥的做法是使用 HTTPS、原生 <form> 和 <input>,为每个字段配置准确的 autocomplete token,并优先用单个 cc-name 字段保存完整的持卡人姓名。支付信息下拉菜单最终是否出现,仍由浏览器和用户设置决定,页面无法强制触发。

备注:内容仅供参考。