使用 Luhn 算法实现表单信用卡号验证

花韻仙語
发布: 2025-08-30 15:19:00
原创
826人浏览过

使用 luhn 算法实现表单信用卡号验证

本文详细介绍了如何在前端表单中集成自定义验证逻辑,特别是使用 Luhn 算法验证信用卡号。通过利用 HTML5 的原生表单验证 API 和 setCustomValidity 方法,您可以无缝地将复杂的验证规则(如 Luhn 算法)与浏览器内置的验证机制结合,为用户提供即时、友好的错误反馈,从而提升表单的健壮性和用户体验。

1. 前端表单验证的重要性与挑战

在现代 Web 应用中,表单验证是不可或缺的一环。良好的客户端验证不仅能提升用户体验,减少无效提交,还能减轻服务器端压力。HTML5 引入了原生的表单验证机制,如 required、type="email" 等属性,极大地简化了常见验证任务。然而,对于某些复杂的业务规则,例如信用卡号的 Luhn 算法验证,原生 HTML5 验证能力有限,需要结合 JavaScript 进行自定义扩展。

2. Luhn 算法原理与实现

Luhn 算法(也称为模 10 算法)是一种简单的校验和算法,常用于验证各种识别号码,包括信用卡号。其核心思想是通过对数字序列进行特定计算,判断其是否符合规则。

以下是 Luhn 算法的 JavaScript 实现:

/**
 * 校验给定的字符串是否符合 Luhn 算法规则
 * @param {string} value 待校验的数字字符串
 * @returns {boolean} 如果符合 Luhn 算法则返回 true,否则返回 false
 */
function checkLuhn(value) {
  // 接受只包含数字、破折号或空格的字符串
  if (/[^0-9-\s]+/.test(value)) return false;

  let nCheck = 0,
    nDigit = 0,
    bEven = false;
  // 移除所有非数字字符
  value = value.replace(/\D/g, "");

  // 从右向左遍历数字
  for (let n = value.length - 1; n >= 0; n--) {
    const cDigit = value.charAt(n);
    nDigit = parseInt(cDigit, 10);

    if (bEven) {
      // 偶数位(从右边开始数的第二位、第四位...)数字乘以2
      if ((nDigit *= 2) > 9) nDigit -= 9; // 如果结果大于9,则减去9
    }

    nCheck += nDigit; // 累加所有数字
    bEven = !bEven; // 切换奇偶标志
  }

  // 如果总和能被10整除,则校验通过
  return (nCheck % 10) === 0;
}
登录后复制

Luhn 算法步骤解析:

  1. 从右向左处理数字: 从信用卡号的最右边数字开始,向左依次处理。
  2. 隔位加倍: 从右边开始的第一个数字(校验位)不加倍,第二个数字加倍,第三个不加倍,第四个加倍,以此类推。
  3. 处理加倍结果: 如果加倍后的数字大于 9(例如 7 * 2 = 14),则将其各位数字相加(1 + 4 = 5),或者直接减去 9(14 - 9 = 5)。
  4. 求和: 将所有处理后的数字(未加倍的数字和加倍后处理的数字)相加。
  5. 模 10 校验: 如果最终的总和能被 10 整除,则该信用卡号是有效的。

3. 集成自定义验证与 setCustomValidity

HTML5 表单元素提供了一个 setCustomValidity() 方法,允许开发者设置自定义验证消息。当传入一个非空字符串时,该字段将被标记为无效,并显示该字符串作为验证消息;传入空字符串则表示字段有效。这是将自定义验证逻辑与浏览器原生验证机制无缝结合的关键。

以下是将 Luhn 算法集成到信用卡号输入字段的示例:

// 当信用卡号输入框内容变化时触发验证
$('#cc').on('input', function(){
  // 获取信用卡号输入框的 DOM 元素
  // 注意:这里需要确保 field 变量正确引用到输入框,
  // 否则 setCustomValidity 将无法调用
  const field = document.querySelector('#cardContainer input'); // 假设输入框在一个 id 为 'cardContainer' 的父元素内

  if (checkLuhn($('#cc').val())) {
    field.setCustomValidity(""); // 验证通过,清除自定义错误消息
  } else {
    field.setCustomValidity("Invalid field."); // 验证失败,设置自定义错误消息
  }
});
登录后复制

关键点说明:

  • 事件监听: 使用 input 事件监听器,可以在用户输入时实时进行验证,提供即时反馈。
  • 获取 DOM 元素: field 变量必须指向实际的 <input> DOM 元素。在本例中,我们通过 document.querySelector('#cardContainer input') 获取,这要求 HTML 中信用卡输入框的父元素具有 id="cardContainer"。如果 id="cc" 在整个文档中是唯一的,也可以直接使用 document.getElementById('cc')。
  • setCustomValidity(""): 当 checkLuhn 返回 true 时,调用此方法清除任何自定义验证消息,使字段被浏览器视为有效。
  • setCustomValidity("Invalid field."): 当 checkLuhn 返回 false 时,调用此方法设置一个自定义错误消息,使字段被浏览器标记为无效,并在提交时阻止表单提交。

4. 整体表单验证流程

除了自定义 Luhn 算法验证,一个完整的表单通常还包含其他字段(如姓名、邮箱)的原生 HTML5 验证。以下是结合所有验证逻辑的表单提交处理流程:

表单大师AI
表单大师AI

一款基于自然语言处理技术的智能在线表单创建工具,可以帮助用户快速、高效地生成各类专业表单。

表单大师AI 74
查看详情 表单大师AI
(function () {
  "use strict";

  const forms = document.querySelectorAll(".needs-validation");
  const result = document.getElementById("result");

  Array.prototype.slice.call(forms).forEach(function (form) {
    form.addEventListener(
      "submit",
      function (event) {
        // 在提交前,先执行所有验证(包括原生HTML5验证和通过setCustomValidity设置的自定义验证)
        if (!form.checkValidity()) {
          event.preventDefault(); // 阻止默认提交行为
          event.stopPropagation(); // 阻止事件冒泡

          // 聚焦到第一个无效字段
          form.querySelectorAll(":invalid")[0].focus();
        } else {
          // 如果所有字段都有效,则处理表单提交(例如通过 Fetch API 发送到后端)
          const formData = new FormData(form);
          event.preventDefault();
          event.stopPropagation();

          const object = {};
          formData.forEach((value, key) => {
            object[key] = value;
          });
          const json = JSON.stringify(object);
          result.innerHTML = "Please wait...";

          fetch("https://api.web3forms.com/submit", {
            method: "POST",
            headers: {
              "Content-Type": "application/json",
              Accept: "application/json"
            },
            body: json
          })
            .then(async (response) => {
              let json = await response.json();
              if (response.status === 200) {
                result.innerHTML = json.message;
                result.classList.remove("text-gray-500");
                result.classList.add("text-green-500");
              } else {
                console.log(response);
                result.innerHTML = json.message;
                result.classList.remove("text-gray-500");
                result.classList.add("text-red-500");
              }
            })
            .catch((error) => {
              console.log(error);
              result.innerHTML = "Something went wrong!";
            })
            .then(function () {
              form.reset(); // 重置表单
              form.classList.remove("was-validated"); // 移除验证样式
              setTimeout(() => {
                result.style.display = "none";
              }, 5000);
            });
        }
        form.classList.add("was-validated"); // 添加验证样式,触发CSS显示错误信息
      },
      false
    );
  });
})();
登录后复制

此流程的关键点:

  • form.checkValidity(): 这是 HTML5 表单验证 API 的核心。它会检查表单中所有带有验证规则(如 required、type="email"、pattern)的字段,以及通过 setCustomValidity() 设置了错误消息的字段。如果任何字段无效,它将返回 false。
  • 阻止默认行为: 当 form.checkValidity() 返回 false 时,调用 event.preventDefault() 和 event.stopPropagation() 来阻止表单的默认提交行为,并防止事件进一步传播。
  • was-validated 类: 在表单提交尝试后,通过添加 was-validated 类,可以触发 CSS 规则来显示验证反馈消息。

5. HTML 结构与样式

为了支持上述验证逻辑和错误消息显示,HTML 结构需要包含相应的输入字段、标签和反馈消息占位符。同时,CSS 样式用于控制错误消息的显示和输入框的视觉反馈。

HTML 结构示例(信用卡号部分):

<div class="flex mb-6 space-x-4">
  <div id="cardContainer" class="w-full md:w-1/2">
    <label for="cc" class="block mb-2 text-sm text-gray-600 dark:text-gray-400">Credit Card Number</label>
    <input type="text" id="cc" placeholder="XXXX XXXX XXXX XXXX" required
           class="w-full px-3 py-2 placeholder-gray-300 border-2 border-gray-200 rounded-md focus:outline-none focus:ring focus:ring-indigo-100 focus:border-indigo-300" />

    <!-- 提示用户输入为空的反馈信息 -->
    <div class="empty-feedback text-red-400 text-sm mt-1">
      Please provide your credit card number.
    </div>
    <!-- 提示用户输入无效的反馈信息 -->
    <div class="invalid-feedback text-red-400 text-sm mt-1">
      Please provide a valid credit card number.
    </div>
  </div>
</div>
登录后复制

CSS 样式示例:

.invalid-feedback,
.empty-feedback {
  display: none; /* 默认隐藏错误反馈 */
}

/* 当表单被标记为 'was-validated' 且输入框为空且无效时,显示 'empty-feedback' */
.was-validated :placeholder-shown:invalid ~ .empty-feedback {
  display: block;
}

/* 当表单被标记为 'was-validated' 且输入框非空但无效时,显示 'invalid-feedback' */
.was-validated :not(:placeholder-shown):invalid ~ .invalid-feedback {
  display: block;
}

/* 当输入框无效时,设置边框颜色 */
.is-invalid,
.was-validated :invalid {
  border-color: #dc3545; /* 红色边框 */
}
登录后复制

这些 CSS 规则利用了 :invalid、:placeholder-shown 等伪类和 ~ (兄弟选择器),配合 was-validated 类,实现了在不同验证状态下显示不同的错误消息和输入框样式。

6. 注意事项与最佳实践

  • 客户端与服务器端验证: 客户端验证是为了提供即时用户反馈和优化体验,但绝不能替代服务器端验证。所有提交到服务器的数据都必须在服务器端再次进行严格验证,以防止恶意攻击和数据损坏。
  • 用户体验: 确保错误消息清晰、具体且易于理解。实时验证(如 input 事件监听)可以显著提升用户体验,但对于复杂的验证逻辑,可以考虑使用防抖(debounce)或节流(throttle)技术,避免在用户快速输入时频繁触发计算。
  • 可访问性: 确保验证错误对屏幕阅读器等辅助技术是可访问的。使用 ARIA 属性(如 aria-invalid、aria-describedby)可以增强表单的可访问性。
  • 代码组织: 将验证逻辑模块化,例如将 checkLuhn 函数独立出来,有助于代码的复用和维护。

7. 总结

通过本文的教程,您应该已经掌握了如何在前端表单中有效地集成自定义验证逻辑。利用 HTML5 的原生验证能力与 JavaScript 的 setCustomValidity() 方法,我们可以为用户提供一个既强大又用户友好的表单验证体验。无论是简单的必填项检查,还是复杂的 Luhn 算法校验,这种结合方式都能帮助您构建出更加健壮和可靠的 Web 表单。请记住,客户端验证是用户体验的基石,而服务器端验证则是数据安全的最后防线,两者缺一不可。

以上就是使用 Luhn 算法实现表单信用卡号验证的详细内容,更多请关注php中文网其它相关文章!

360借条
360借条

3分钟审核,最快5分钟放款,极速到账,低服务费,年化综合息费率7.2%起。

下载
来源:php中文网
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn
最新问题
开源免费商场系统广告
热门教程
更多>
最新下载
更多>
网站特效
网站源码
网站素材
前端模板
关于我们 免责申明 举报中心 意见反馈 讲师合作 广告合作 最新更新 English
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号 技术交流群
PHP中文网订阅号
每天精选资源文章推送
PHP中文网APP
随时随地碎片化学习

Copyright 2014-2025 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号