Luhn algoritmi: Uzcard, Humo va Visa kartalarini kodda tekshirish
Amaliyot4 daqInnovialabs tahririyati
Qisqacha
Luhn algoritmi — karta raqamidagi ko‘pchilik xatolarni forma yuborilishidan oldin ushlaydigan oddiy nazorat yig‘indisi; u karta mavjudligini aytmaydi — buni faqat to‘lov provayderi tekshiradi.
Luhn algoritmi nimani tekshiradi
Luhn algoritmi (mod 10) — nazorat yig‘indisi formulasi. Karta raqamining oxirgi raqami shunday tanlanganki, maxsus qoida bo‘yicha hisoblangan yig‘indi 10 ga bo‘linadi. Foydalanuvchi bitta raqamni xato yozsa yoki ikkita qo‘shni raqamning o‘rnini almashtirsa, yig‘indi deyarli har doim to‘g‘ri chiqmay qoladi.
Luhn nimani qilmaydi:
- karta mavjud va faol ekanini tekshirmaydi;
- balans, amal qilish muddati va egasini tekshirmaydi;
- firibgarlikdan himoya qilmaydi.
Bu — foydalanuvchi qulayligi uchun tekshiruv: xatoni provayderga so‘rov yuborilgandan keyin emas, darhol ko‘rsatish.
Yig‘indi qanday hisoblanadi
- Raqamlar bo‘ylab o‘ngdan chapga yuramiz. Oxirgi raqam — nazorat raqami, unga tegmaymiz.
- Har ikkinchi raqamni (o‘ngdan ikkinchi, to‘rtinchi va hokazo) 2 ga ko‘paytiramiz.
- Natija 9 dan katta bo‘lsa, undan 9 ni ayiramiz (raqamlarini qo‘shish bilan bir xil: 16 → 1 + 6 = 7).
- Barcha raqamlarni qo‘shamiz.
- Yig‘indi 10 ga qoldiqsiz bo‘linsa, raqam to‘g‘ri.
79927398713 raqami misolida: o‘ngdan chapga 3, 2, 7, 7, 9, 6, 7, 4, 9, 9, 7 hosil bo‘ladi. Yig‘indi — 70, 10 ga bo‘linadi, raqam tekshiruvdan o‘tadi.
Ma’lum cheklov: qo‘shni 09 ↔ 90 almashinuvini algoritm sezmaydi.
JavaScript da amalga oshirish
function luhnValid(input) {
const digits = String(input).replace(/[\s-]/g, "");
if (!/^[0-9]{12,19}$/.test(digits)) return false;
let sum = 0;
let double = false;
for (let i = digits.length - 1; i >= 0; i--) {
let d = digits.charCodeAt(i) - 48;
if (double) {
d *= 2;
if (d > 9) d -= 9;
}
sum += d;
double = !double;
}
return sum % 10 === 0;
}
luhnValid("4111 1111 1111 1111"); // true
luhnValid("4111 1111 1111 1112"); // false
Python da amalga oshirish
import re
def luhn_valid(number: str) -> bool:
digits = re.sub(r"[\s-]", "", number)
if not re.fullmatch(r"[0-9]{12,19}", digits):
return False
total = 0
for i, ch in enumerate(reversed(digits)):
d = int(ch)
if i % 2 == 1:
d *= 2
if d > 9:
d -= 9
total += d
return total % 10 == 0
assert luhn_valid("4111 1111 1111 1111")
assert not luhn_valid("4111-1111-1111-1112")
E’tibor bering: raqamlar \d bilan emas, [0-9] bilan tekshiriladi. Python da \d standart holatda boshqa yozuvlarning raqamlariga ham mos keladi.
BIN bo‘yicha karta turi
Raqamning birinchi raqamlari — BIN (IIN) — to‘lov tizimi va bankni bildiradi. Interfeysdagi ishora uchun (logotip, niqob uzunligi) odatda prefiks yetarli:
| Tizim | Odatiy prefiks |
|---|---|
| Humo | 9860 |
| Uzcard | 8600 |
| Visa | 4 |
| Mastercard | 51–55, 2221–2720 |
function detectBrand(digits) {
if (digits.startsWith("9860")) return "humo";
if (digits.startsWith("8600")) return "uzcard";
if (digits.startsWith("4")) return "visa";
const p2 = Number(digits.slice(0, 2));
const p4 = Number(digits.slice(0, 4));
if ((p2 >= 51 && p2 <= 55) || (p4 >= 2221 && p4 <= 2720)) return "mastercard";
return "unknown";
}
Muhim:
- BIN diapazonlari o‘zgaradi, yangi diapazonlar va kobeyj kartalar paydo bo‘ladi. Prefikslar jadvalini kod bo‘ylab tarqatmasdan, konfigda saqlang.
- Uzunroq prefikslarni qisqalaridan oldin tekshiring.
- Mahalliy tizimlar uchun ularning raqamlariga Luhn tekshiruvi qo‘llanishini provayder hujjatlaridan aniqlang. Ishonchingiz komil bo‘lmasa, yuborishni bloklamasdan, ogohlantirish ko‘rsating.
unknown— xato emas. Kodingiz tanimagan karta bilan to‘lashga foydalanuvchiga to‘sqinlik qilmang.
Kiritish niqobi
4 tadan guruhlash raqamni ko‘z bilan tekshirishni ancha osonlashtiradi:
const format = (v) =>
v.replace(/[^0-9]/g, "").slice(0, 19).replace(/(\d{4})(?=\d)/g, "$1 ");
Amaliy maslahatlar:
type="number"emas,<input inputmode="numeric" autocomplete="cc-number">dan foydalaning: birinchisi boshidagi nollarni buzadi va strelkalarni ko‘rsatadi.- Probel va tire bilan qo‘yilgan qiymatlarni qabul qiling — rad etmasdan, tozalang.
- Formatlashda kursor o‘rnini saqlang, aks holda o‘rtada tahrirlaganda u oxiriga sakraydi.
- Luhn tekshiruvini har bir belgida emas, to‘liq uzunlik kiritilganda ishga tushiring.
Asl tekshiruv — provayderda
Mijoz tomonidagi tekshiruv faqat xatolarni filtrlaydi. Karta mavjudligi, balans, 3-D Secure yoki SMS tasdiqlash va limitlarni to‘lov provayderi tekshiradi.
- Imkon qadar provayderning to‘lov sahifasi yoki maydonlari va tokenizatsiyadan foydalaning: shunda karta raqami serveringizdan o‘tmaydi.
- To‘liq karta raqamini bazangiz va loglaringizda saqlamang. Karta ma’lumotlari bilan ishlash PCI DSS standarti bilan tartibga solinadi.
- Raqam baribir sizga kelsa, tekshiruvni serverda takrorlang: mijoz kodini aylanib o‘tish oson.