0

0

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

心靈之曲

心靈之曲

发布时间:2025-08-30 15:00:14

|

448人浏览过

|

来源于php中文网

原创

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

本文旨在指导开发者如何在基于HTML5和JavaScript的表单验证系统中,集成Luhn算法对信用卡号进行实时验证。文章将详细阐述如何正确获取输入字段、应用Luhn算法逻辑,并通过setCustomValidity API管理自定义验证状态及错误提示,确保表单提交前所有字段的有效性,提升用户体验。

1. 理解表单验证与Luhn算法集成挑战

现代web表单通常利用html5内置的验证机制(如required、type="email"等)来提供基础的用户输入校验。然而,对于某些特定业务逻辑的验证,例如信用卡号的luhn算法校验,需要通过javascript进行自定义实现。核心挑战在于如何将这种自定义验证逻辑无缝地融入到现有的html5验证流程中,并确保当信用卡号不符合luhn算法时,能够像其他无效字段一样,正确地显示错误提示并阻止表单提交。

Luhn算法(也称为模10算法)是一种简单的校验和算法,常用于验证各种识别号码,如信用卡号、IMEI号等。它通过特定的计算规则,判断一串数字是否可能是有效号码,但它并不能验证号码的真实性或是否存在。

2. Luhn算法的JavaScript实现

首先,我们需要一个独立的JavaScript函数来实现Luhn算法。这个函数接收一个字符串作为输入(通常是信用卡号),并返回一个布尔值,表示该号码是否通过Luhn校验。

/**
 * 校验给定的字符串是否符合Luhn算法规则
 * @param {string} value - 待校验的字符串(通常为信用卡号)
 * @returns {boolean} - 如果符合Luhn算法返回true,否则返回false
 */
function checkLuhn(value) {
  // 1. 移除所有非数字、非破折号、非空格字符。如果存在其他非数字字符,则直接视为无效。
  if (/[^0-9-\s]+/.test(value)) return false;

  // 2. 移除所有非数字字符,只保留数字进行Luhn算法计算
  value = value.replace(/\D/g, "");

  let nCheck = 0; // 校验和
  let bEven = false; // 标记是否为偶数位(从右往左数,第一位为奇数位)

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

    // 4. 偶数位数字翻倍,如果大于9则减去9
    if (bEven) {
      if ((nDigit *= 2) > 9) {
        nDigit -= 9;
      }
    }

    // 5. 累加到校验和
    nCheck += nDigit;
    bEven = !bEven; // 切换奇偶位标记
  }

  // 6. 如果校验和能被10整除,则通过Luhn算法
  return (nCheck % 10) === 0;
}

Luhn算法原理简述:

  1. 从号码最右边一位开始,将其视为第一位(奇数位)。
  2. 从右向左,每隔一位的数字乘以2(即所有偶数位的数字)。
  3. 如果乘以2的结果是两位数(即大于9),则将这个两位数的两个数字相加(例如,12变成1+2=3)。
  4. 将所有(未翻倍的奇数位和经过处理的偶数位)数字相加,得到一个总和。
  5. 如果这个总和能被10整除,则该号码通过Luhn校验。

3. 集成Luhn算法到表单验证流程

为了将Luhn算法集成到现有表单的HTML5验证流程中,我们需要监听信用卡输入字段的input事件,并在每次输入时执行Luhn校验。关键在于使用HTMLElement.setCustomValidity()方法来控制字段的验证状态和自定义错误消息。

3.1 JavaScript核心集成逻辑

在表单初始化脚本中,添加对信用卡输入字段的事件监听:

(function () {
  "use strict";

  // ... 现有表单验证逻辑 ...

  // 监听信用卡输入字段的输入事件
  // 注意:这里使用了jQuery的on('input')方法
  $('#cc').on('input', function() {
    // 1. 获取信用卡输入字段的DOM元素
    // 确保这里的选择器能够准确地获取到你的input元素。
    // 在本例中,HTML结构是 
// 所以可以使用 document.querySelector('#cardContainer input') 或更直接的 document.getElementById('cc') const field = document.getElementById('cc'); // 或者 document.querySelector('#cardContainer input'); // 2. 执行Luhn算法校验 if (checkLuhn($('#cc').val())) { // 如果校验通过,清除自定义验证消息,使字段变为有效状态 field.setCustomValidity(""); } else { // 如果校验失败,设置自定义验证消息,使字段变为无效状态 field.setCustomValidity("Invalid field."); // 这条消息将显示在浏览器默认的错误提示中 } }); // ... 现有Luhn算法函数 checkLuhn ... })();

关键点解释:

  • field变量的正确获取:原代码中field变量未定义,导致setCustomValidity无法调用。必须先通过document.getElementById('cc')或document.querySelector('#cardContainer input')等方式获取到实际的DOM元素。
  • setCustomValidity(""):当字段通过自定义校验时,必须调用setCustomValidity("")并传入空字符串,以清除任何先前设置的自定义错误,并使该字段被浏览器视为有效。如果传入非空字符串,字段将被视为无效,并显示该字符串作为错误消息。
  • input事件:选择input事件而不是change事件,可以实现实时反馈,提升用户体验。

3.2 HTML结构调整

为了确保setCustomValidity设置的错误消息能够被正确地显示,并且与现有的CSS样式协同工作,我们需要确保HTML结构中包含用于显示错误消息的元素,并且CSS样式能够响应字段的验证状态。

ChatGPT Website Builder
ChatGPT Website Builder

ChatGPT网站生成器,AI对话快速生成网站

下载

在信用卡输入字段的HTML部分,确保包含id属性,并且有empty-feedback和invalid-feedback的div:

Please provide your credit card number.
Please provide a valid credit card number.

这里为信用卡输入字段的父容器添加了id="cardContainer",虽然在document.getElementById('cc')的情况下不是必需的,但如果你的选择器是document.querySelector('#cardContainer input'),则该ID是必要的。

3.3 CSS样式

确保以下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伪类和通用兄弟选择器(~)来根据字段的验证状态和是否为空来显示不同的错误提示。当setCustomValidity设置了错误消息时,浏览器会将该字段标记为:invalid。

4. 完整代码示例

以下是整合了Luhn算法验证的完整HTML、CSS和JavaScript代码:

HTML (index.html)




  
  
  信用卡号Luhn算法表单验证
  
  


  

联系我们

填写以下表格发送消息。

Please provide your first name.
Please provide your email address.
Please provide a valid email address.
Please provide your credit card number.
Please provide a valid credit card number.

JavaScript (main.js)

(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) {
        // 在提交前再次检查所有字段的有效性
        if (!form.checkValidity()) {
          event.preventDefault();
          event.stopPropagation();
          // 将焦点设置到第一个无效字段
          form.querySelectorAll(":invalid")[0].focus();
        } else {
          /*
           * 使用fetch()进行表单提交
           */
          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 = "请稍候...";

          fetch("https://api.web3forms.com/submit", {
            method: "POST",
            headers: {
              "Content-Type": "application/json",
              Accept: "application/json"
            },
            body: json
          })
            .then(async (response) => {
              let jsonResponse = await response.json();
              if (response.status === 200) {
                result.innerHTML = jsonResponse.message;
                result.classList.remove("text-gray-500");
                result.classList.add("text-green-500");
              } else {
                console.error(response);
                result.innerHTML = jsonResponse.message;
                result.classList.remove("text-gray-500");
                result.classList.add("text-red-500");
              }
            })
            .catch((error) => {
              console.error(error);
              result.innerHTML = "发生了一些错误!";
            })
            .then(function () {
              form.reset();
              form.classList.remove("was-validated");
              setTimeout(() => {
                result.style.display = "none";
              }, 5000);
            });
        }
        form.classList.add("was-validated"); // 标记表单为已验证,触发CSS显示错误
      },
      false
    );
  });

  // 信用卡输入字段的Luhn算法验证
  $('#cc').on('input', function(){
    // 获取信用卡输入字段的DOM元素
    const field = document.getElementById('cc'); // 或者 document.querySelector('#cardContainer input');
    const inputValue = $(this).val(); // 获取当前输入值

    if (checkLuhn(inputValue)) {
      field.setCustomValidity(""); // 校验通过,清除自定义错误
    } else {
      field.setCustomValidity("Invalid field."); // 校验失败,设置自定义错误
    }
  });

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

    // 移除所有非数字字符
    value = value.replace(/\D/g, "");

    let nCheck = 0, bEven = false;
    for (let n = value.length - 1; n >= 0; n--) {
      let cDigit = value.charAt(n);
      let nDigit = parseInt(cDigit, 10);

      if (bEven) {
        if ((nDigit *= 2) > 9) nDigit -= 9;
      }
      nCheck += nDigit;
      bEven = !bEven;
    }
    return (nCheck % 10) === 0;
  }
})();

5. 注意事项与最佳实践

  • 客户端验证与服务器端验证:Luhn算法在客户端的实现主要是为了提供即时用户反馈和提升用户体验。安全性要求高的场景下,服务器端必须对所有提交的数据进行再次验证,因为客户端验证可以被绕过。
  • 错误消息的清晰性与多语言支持:setCustomValidity()中的错误消息应该清晰明了,指导用户如何修正。对于国际化应用,这些消息应支持多语言。
  • 用户体验:实时验证(oninput事件)可以显著改善用户体验,让用户在输入过程中就能得到反馈,而不是等到提交时才发现错误。
  • 与其他验证的协同:当一个字段有多个验证规则时(例如,既required又需要Luhn校验),setCustomValidity会覆盖或与浏览器默认的错误消息协同。如果setCustomValidity设置了非空字符串,它将优先显示。
  • CSS样式匹配:确保你的自定义错误消息样式(如.invalid-feedback)能够正确响应setCustomValidity触发的:invalid状态。

总结

通过将Luhn算法封装为独立的JavaScript函数,并结合HTMLElement.setCustomValidity() API,我们可以有效地将自定义验证逻辑

热门AI工具

更多
DeepSeek
DeepSeek

幻方量化公司旗下的开源大模型平台

豆包大模型
豆包大模型

字节跳动自主研发的一系列大型语言模型

通义千问
通义千问

阿里巴巴推出的全能AI助手

腾讯元宝
腾讯元宝

腾讯混元平台推出的AI助手

文心一言
文心一言

文心一言是百度开发的AI聊天机器人,通过对话可以生成各种形式的内容。

讯飞写作
讯飞写作

基于讯飞星火大模型的AI写作工具,可以快速生成新闻稿件、品宣文案、工作总结、心得体会等各种文文稿

即梦AI
即梦AI

一站式AI创作平台,免费AI图片和视频生成。

ChatGPT
ChatGPT

最最强大的AI聊天机器人程序,ChatGPT不单是聊天机器人,还能进行撰写邮件、视频脚本、文案、翻译、代码等任务。

相关专题

更多
html5动画制作有哪些制作方法
html5动画制作有哪些制作方法

html5动画制作方法有使用CSS3动画、使用JavaScript动画库、使用HTML5 Canvas等。想了解更多html5动画制作方法相关内容,可以阅读本专题下面的文章。

514

2023.10.23

HTML与HTML5的区别
HTML与HTML5的区别

HTML与HTML5的区别:1、html5支持矢量图形,html本身不支持;2、html5中可临时存储数据,html不行;3、html5新增了许多控件;4、html本身不支持音频和视频,html5支持;5、html无法处理不准确的语法,html5能够处理等等。想了解更多HTML与HTML5的相关内容,可以阅读本专题下面的文章。

440

2024.03.06

html5从入门到精通汇总
html5从入门到精通汇总

想系统掌握HTML5开发?本合集精选全网优质学习资源,涵盖免费教程、实战项目、视频课程与权威电子书,从基础语法到高级特性(Canvas、本地存储、响应式布局等)一应俱全,适合零基础小白到进阶开发者,助你高效入门并精通HTML5前端开发。

92

2025.12.30

html5新老标签汇总
html5新老标签汇总

HTML5在2026年持续优化网页语义化与交互体验,不仅引入了如<header>、<nav>、<article>、<section>、<aside>、<footer>等结构化标签,还新增了<video>、<audio>、<canvas>、<figure>、<time>、<mark>等增强多媒体与

125

2025.12.30

html5空格代码怎么写
html5空格代码怎么写

在HTML5中,空格不能直接通过键盘空格键实现,需使用特定代码。本合集详解常用空格写法:&nbsp;(不间断空格)、&ensp;(半个中文空格)、&emsp;(一个中文空格)及CSS的white-space属性等方法,帮助开发者精准控制页面排版,避免因空格失效导致布局错乱,适用于新手入门与实战参考。

79

2025.12.30

html5怎么做网站教程
html5怎么做网站教程

想从零开始学做网站?这份《HTML5怎么做网站教程》合集专为新手打造!涵盖HTML5基础语法、页面结构搭建、表单与多媒体嵌入、响应式布局及与CSS3/JavaScript协同开发等核心内容。无需编程基础,手把手教你用纯HTML5创建美观、兼容、移动端友好的现代网页。附实战案例+代码模板,快速上手,轻松迈出Web开发第一步!

159

2025.12.31

HTML5建模教程
HTML5建模教程

想快速掌握HTML5模板搭建?本合集汇集实用HTML5建模教程,从零基础入门到实战开发全覆盖!内容涵盖响应式布局、语义化标签、Canvas绘图、表单验证及移动端适配等核心技能,提供可直接复用的模板结构与代码示例。无需复杂配置,助你高效构建现代网页,轻松上手前端开发!

31

2025.12.31

html5怎么使用
html5怎么使用

想快速上手HTML5开发?本合集为你整理最实用的HTML5使用指南!涵盖HTML5基础语法、主流框架(如Bootstrap、Vue、React)集成方法,以及无需安装、直接在线编辑运行的平台推荐(如CodePen、JSFiddle)。无论你是新手还是进阶开发者,都能轻松掌握HTML5网页制作、响应式布局与交互功能开发,零配置开启高效前端编程之旅!

46

2025.12.31

C++ 设计模式与软件架构
C++ 设计模式与软件架构

本专题深入讲解 C++ 中的常见设计模式与架构优化,包括单例模式、工厂模式、观察者模式、策略模式、命令模式等,结合实际案例展示如何在 C++ 项目中应用这些模式提升代码可维护性与扩展性。通过案例分析,帮助开发者掌握 如何运用设计模式构建高质量的软件架构,提升系统的灵活性与可扩展性。

14

2026.01.30

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
Sass 教程
Sass 教程

共14课时 | 0.8万人学习

Bootstrap 5教程
Bootstrap 5教程

共46课时 | 3.1万人学习

CSS教程
CSS教程

共754课时 | 25.5万人学习

关于我们 免责申明 举报中心 意见反馈 讲师合作 广告合作 最新更新
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号 技术交流群
PHP中文网订阅号
每天精选资源文章推送

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