PAYATHON 2026

如何正确掩码 SEPA 的 IBAN 和 BIC 信息?

支付阿杰

结论

在支付方式选择页面中,建议对 IBAN 进行掩码,只保留足以区分账户的少量字符,比如国家代码和最后 4 位:

DE•• •••• •••• •••• ••30 00

也可以使用更简洁的形式:

IBAN 尾号 3000

BIC 标识的是银行或分支机构,不是用户的账户凭据,通常可以完整显示。不过,如果界面上用不到 BIC,就不必展示。多数情况下,银行名称加 IBAN 尾号会更直观。

IBAN 和 BIC 都不能单独用于授权扣款,因此掩码并不是防止交易盗用的主要安全措施。但 IBAN 仍属于个人支付数据,不应在页面、日志、通知或分析系统中无必要地完整暴露。

为什么不能完全照搬信用卡规则

IBAN 和信用卡号的用途不同,风险也不同:

  • IBAN 用于识别银行账户,长度因国家而异,最长可达 34 个字符。
  • BIC 用于识别银行或银行分支机构,通常为 8 位或 11 位。
  • 信用卡号通常参与支付授权。SEPA Direct Debit 则还需要授权委托(mandate)、收款方标识以及交易流程中的其他信息。
  • 完整 IBAN 虽然不是密码,但能关联到具体的个人或企业账户,可能带来隐私泄露、钓鱼和社会工程风险。

因此,不必机械地要求“IBAN 只能显示最后 4 位”。更合适的做法是遵循数据最小化原则,只展示用户识别账户所需的信息。

推荐的展示方式

大多数支付系统可以采用以下组合:

张三
Example Bank
IBAN 尾号 3000

如果用户可能保存多个尾号相同的账户,可以补充少量识别信息:

Example Bank · DE••••3000

不要把最后 4 位当作账户的内部唯一标识,因为不同 IBAN 完全可能拥有相同尾号。提交页面时,应传递支付方式的内部 ID,而不是尾号或完整 IBAN:

{
  "paymentMethodId": "pm_sepa_7f3c2a91"
}

服务端根据该 ID 查找支付方式,并验证它确实属于当前登录用户。

掩码实现示例

下面的 JavaScript 示例先删除空格并转换为大写,再保留国家代码和最后 4 个字符:

function maskIban(iban) {
  const normalized = iban.replace(/\s+/g, "").toUpperCase();

  if (normalized.length < 6) {
    throw new Error("Invalid IBAN");
  }

  const countryCode = normalized.slice(0, 2);
  const lastFour = normalized.slice(-4);
  const maskedLength = normalized.length - 6;

  return `${countryCode}${"•".repeat(maskedLength)}${lastFour}`;
}

console.log(maskIban("DE89 3704 0044 0532 0130 00"));
// DE••••••••••••••••••3000

如果需要每 4 个字符分为一组,可以这样处理:

function formatInGroups(value, groupSize = 4) {
  return value.match(new RegExp(`.{1,${groupSize}}`, "g"))?.join(" ") ?? "";
}

function maskAndFormatIban(iban) {
  const normalized = iban.replace(/\s+/g, "").toUpperCase();

  if (normalized.length < 6) {
    throw new Error("Invalid IBAN");
  }

  const masked =
    normalized.slice(0, 2) +
    "•".repeat(normalized.length - 6) +
    normalized.slice(-4);

  return formatInGroups(masked);
}

console.log(maskAndFormatIban("DE89 3704 0044 0532 0130 00"));
// DE•• •••• •••• •••• ••30 00

如果只需要一个简洁标签,可以直接返回尾号:

function getIbanLabel(iban) {
  const normalized = iban.replace(/\s+/g, "").toUpperCase();

  if (normalized.length < 4) {
    throw new Error("Invalid IBAN");
  }

  return `IBAN 尾号 ${normalized.slice(-4)}`;
}

实际系统最好由服务端生成脱敏后的展示值,避免前端为了执行掩码而接收到完整 IBAN。

BIC 应该如何处理

BIC 通常可以完整显示,例如:

COBADEFFXXX

它表示金融机构,并不像 IBAN 那样直接标识用户账户。许多银行的 BIC 本身也是公开信息,因此一般不需要将它处理成:

XXXXXXXFXXX

不过,可以完整显示并不意味着必须显示。在支付方式选择页面中,展示银行名称通常更合适:

Example Bank · IBAN 尾号 3000

只有业务流程、客服排查或用户确认确实需要时,才显示完整 BIC。

安全与隐私注意事项

掩码解决的是界面展示问题,不能代替其他安全控制:

  • 数据库中应加密保存 IBAN,或者优先保存支付服务商返回的 token、mandate ID、payment method ID。
  • API 默认只返回脱敏值,不要把完整 IBAN 发送给不需要它的客户端。
  • 日志、错误追踪、监控事件和分析埋点中的 IBAN 都应脱敏。
  • 不要把完整 IBAN 写入 URL、查询参数、页面源码或浏览器本地存储。
  • 读取、更新和删除支付方式时,都必须校验其用户归属。
  • 掩码前应先规范化并验证 IBAN,但通过格式校验不代表账户真实存在。
  • 如果需要遵守 GDPR 或其他隐私法规,应根据实际司法辖区、数据处理目的和保存期限进行评估。

稳妥的默认方案是:界面显示银行名称、国家代码和 IBAN 最后 4 位;BIC 默认不显示,确有需要时可以完整展示;所有操作都通过不可推测的内部支付方式 ID 完成。

备注:内容仅供参考。