项目背景
在现代支付系统中,信用卡(Credit Card)仍然是全球最重要的支付工具之一。无论是电商平台、SaaS 订阅系统、线下 POS 终端,还是移动支付网关,在接收信用卡号时都必须进行基础合法性校验。
如果不进行验证,可能会导致:
- 无效数据进入数据库
- 支付接口频繁失败
- 欺诈风险上升
- 系统性能浪费
- 客户体验下降
信用卡号校验主要分为两类:
- 格式校验(长度、前缀、数字)
- Luhn 算法校验(校验位验证)
其中,Luhn 算法(也称为模 10 算法)是全球通用的银行卡校验标准。
项目需求
基础需求
实现函数:
func IsValidCreditCard(number string) bool
判断字符串是否为合法信用卡号码。
合法信用卡必须满足
- 非空
- 仅包含数字(可自动去除空格)
- 长度在 13–19 位之间
- 通过 Luhn 校验算法
- 可选:支持常见卡类型识别
合法示例(测试号)
4111111111111111 // Visa
5500000000000004 // MasterCard
340000000000009 // American Express
非法示例
1234567890123456
4111111111111112
abcd123456
相关技术
信用卡结构
典型结构:
[发卡机构标识] + [账户号] + [校验位]
长度:
- 13–19 位
- 最后一位是 Luhn 校验位
Luhn 算法原理
步骤:
- 从右向左遍历数字
- 每隔一位乘以 2
- 若乘积大于 9,则减 9
- 所有数字求和
- 总和 % 10 == 0 则合法
示例:
卡号:4111111111111111
计算后总和 % 10 == 0 → 合法
常见卡类型前缀
| 类型 | 前缀 |
|---|---|
| Visa | 4 |
| MasterCard | 51–55 |
| AmEx | 34, 37 |
| Discover | 6011 |
设计原则
- 单一职责
- 可扩展
- 可识别卡类型
- 错误信息清晰
- 支持空格自动处理
实现思路
整体流程:
- 去除空格
- 判空
- 判断是否全为数字
- 判断长度范围
- 执行 Luhn 算法
- 可选:识别卡类型
- 返回结果
设计结构体
type CreditCardValidator struct {
MinLength int
MaxLength int
}
Luhn 算法实现关键点
- 使用字符串转数字
- 从右往左遍历
- 控制倍增标志
可扩展设计
- 支持卡类型识别
- 支持黑名单前缀
- 支持日志记录
完整实现代码
// =============================
// file: validator/creditcard_validator.go
// =============================
package validator
import (
"errors"
"strconv"
"strings"
"unicode"
)
// CreditCardValidator 信用卡校验结构体
type CreditCardValidator struct {
MinLength int
MaxLength int
}
// NewCreditCardValidator 构造函数
func NewCreditCardValidator() *CreditCardValidator {
return &CreditCardValidator{
MinLength: 13,
MaxLength: 19,
}
}
// IsValid 校验信用卡是否合法
func (v *CreditCardValidator) IsValid(number string) (bool, error) {
// 1. 去除空格
number = strings.ReplaceAll(number, " ", "")
// 2. 判空
if number == "" {
return false, errors.New("信用卡号不能为空")
}
// 3. 判断是否全为数字
for _, r := range number {
if !unicode.IsDigit(r) {
return false, errors.New("信用卡号必须为数字")
}
}
// 4. 长度校验
if len(number) < v.MinLength || len(number) > v.MaxLength {
return false, errors.New("信用卡号长度不合法")
}
// 5. Luhn 算法校验
if !luhnCheck(number) {
return false, errors.New("未通过 Luhn 校验")
}
return true, nil
}
// luhnCheck Luhn 算法实现
func luhnCheck(number string) bool {
sum := 0
double := false
// 从右往左遍历
for i := len(number) - 1; i >= 0; i-- {
digit, _ := strconv.Atoi(string(number[i]))
if double {
digit *= 2
if digit > 9 {
digit -= 9
}
}
sum += digit
double = !double
}
return sum%10 == 0
}
// GetCardType 识别卡类型
func GetCardType(number string) string {
number = strings.ReplaceAll(number, " ", "")
if strings.HasPrefix(number, "4") {
return "Visa"
}
if len(number) >= 2 {
prefix2 := number[:2]
if prefix2 == "34" || prefix2 == "37" {
return "American Express"
}
}
if len(number) >= 2 {
prefix2 := number[:2]
if prefix2 >= "51" && prefix2 <= "55" {
return "MasterCard"
}
}
if strings.HasPrefix(number, "6011") {
return "Discover"
}
return "Unknown"
}
// =============================
// file: main.go
// =============================
package main
import (
"fmt"
"creditcard/validator"
)
func main() {
v := validator.NewCreditCardValidator()
testCases := []string{
"4111111111111111",
"5500000000000004",
"340000000000009",
"1234567890123456",
"4111111111111112",
}
for _, t := range testCases {
valid, err := v.IsValid(t)
fmt.Println("卡号:", t)
fmt.Println("是否有效:", valid)
fmt.Println("错误:", err)
fmt.Println("卡类型:", validator.GetCardType(t))
fmt.Println("---------------------")
}
}
代码解读
NewCreditCardValidator
初始化校验器,设置长度范围 13–19。
IsValid
主校验函数:
- 去空格
- 判空
- 判断是否数字
- 长度限制
- Luhn 算法验证
luhnCheck
实现模 10 算法:
- 从右往左
- 每隔一位乘 2
- 超过 9 减 9
- 求和后模 10 判断
GetCardType
根据前缀识别卡类型。
项目总结
本项目实现了:
✔ 严格数字校验 ✔ Luhn 算法实现 ✔ 卡类型识别 ✔ 可扩展设计 ✔ 企业级基础校验逻辑
适用于:
- 支付网关
- 电商平台
- 金融系统
- 表单前端后端双重校验
常见问题
Q1:通过 Luhn 就一定是有效卡吗?
不是,只是格式合法。
Q2:是否可以验证真实卡存在?
需要调用银行 API 或支付网关。
Q3:是否支持借记卡?
支持,只要符合 Luhn。
扩展与优化
1️⃣ 支持更多卡组织
可扩展前缀判断规则,例如:
- Visa
- MasterCard
- American Express
- Discover
2️⃣ 支持 BIN 数据库校验
引入 BIN 数据库做更精确识别。
3️⃣ 并发批量校验优化
当前算法时间复杂度 O(n),非常轻量。
4️⃣ 添加单元测试
使用:
go test
结语
本教程完整实现了 Go 语言验证信用卡号码(Luhn 算法)算法。

