IlmHamroh
JavaScript Full-stack/29-qism. Backend integratsiyalar: fayl, to'lov, bot, realtime12/69-dars14 daqiqa
Mundarija (23)

QR kod va shtrix-kod generatsiyasi: chipta, havola va imzolangan payload

Qisqacha: QR kod — matnni (ko'pincha havolani) kvadrat rasmga aylantirish; shtrix-kod — raqam yoki qisqa matnni chiziqlarga. Serverda qrcode paketi PNG va SVG yasaydi, bwip-js esa Code 128, EAN-13 va boshqa shtrix-kodlarni. Asosiy qoida: QR ichidagi ma'lumot shifrlanmagan — istalgan telefon uni o'qiydi. Chipta yoki kirish QR'i ichiga maxfiy ma'lumot emas, server imzolagan qisqa token qo'yiladi: o'zgartirilsa — "imzo noto'g'ri", muddati o'tsa — rad, bir marta ishlatilgach — qayta kirib bo'lmaydi.

Bu darsda

  • QR kodning versiyasi, xato tuzatish darajasi va sig'imini kanon o'lchovi bilan tushunasiz.
  • qrcode bilan PNG va SVG yasaysiz, qaysi birini qachon ishlatishni bilasiz.
  • bwip-js bilan shtrix-kod yasaysiz va EAN-13 nazorat raqamini hisoblaysiz.
  • QR ichiga HMAC bilan imzolangan, muddatli token joylaysiz va uni tekshirasiz.
  • Bir martalik chipta uchun qayta ishlatishdan himoya qilasiz.

Oldin bilishingiz kerak: crypto 1: tasodif, hash va HMAC, PDF generatsiya, Fayl yuklab berish va arxivlash, Buffer va binar ma'lumot.

Oldingi darslarda PDF va fayllarni yasadik va berdik. QR — ularning tez-tez uchraydigan bo'lagi: chek, chipta, sertifikatdagi "haqiqiyligini tekshirish" kodi.

1. Nega bu kerak?

Uch holat:

  1. Ulashish. Malika vazifasini hamkasbiga ko'rsatmoqchi — ekranda QR, telefon bilan skanerlanadi, havola ochiladi.
  2. Chipta. Tadbirga kirish: QR skanerlanadi, server "haqiqiy, hali ishlatilmagan" deydi.
  3. Mahsulot. Do'kon tovarlari uchun shtrix-kod (EAN-13), ombor yorliqlari (Code 128).

O'zbekistonda QR kundalik hayotda keng: to'lov ilovalaridagi QR orqali to'lov, cheklardagi soliq QR'i, davlat hujjatlaridagi tekshiruv QR'i. Hammasining asosi bir xil: rasm ichida matn. Qanday matn qo'yishingiz — xavfsizlik masalasi.

2. QR kod tuzilishi

2.1 Modul, versiya, daraja

QR — kvadrat modullar (qora-oq kataklar) to'ri. Versiya 1 dan 40 gacha: versiya 1 — 21×21 modul, har keyingisi +4 (versiya 40 — 177×177). Ma'lumot ko'p bo'lsa — versiya kattaroq, kod zichroq.

Xato tuzatish darajasi — kodning bir qismi shikastlansa (dog', yirtiq, logotip) ham o'qiladi:

Daraja Tiklash ulushi (standart) Qachon
L ~7 % ekrandagi toza kod, ko'p ma'lumot
M ~15 % oddiy tanlov (sukut)
Q ~25 % bosma, yorliq
H ~30 % o'rtaga logotip qo'yilsa

Kanon 36 belgili havolani (https://vazifalar.example.uz/v/12345) to'rt darajada yasadi. Har qatorda versiya va modul soniga qarang:

text
L: versiya 3, 29×29 modul, PNG 1289 bayt (scale 4)
M: versiya 3, 29×29 modul, PNG 1270 bayt (scale 4)
Q: versiya 4, 33×33 modul, PNG 1626 bayt (scale 4)
H: versiya 5, 37×37 modul, PNG 1983 bayt (scale 4)
Tiklash ulushi (standart): L ~7 %, M ~15 %, Q ~25 %, H ~30 % — logotip qo'yilsa H.

Nima bo'ldi? Bir xil havola, lekin H darajada kod 29 dan 37 modulga kattalashdi. Daraja oshgan sari tiklash ma'lumoti ko'payadi — kod kattalashadi (versiya 3 → 5). Formulani tekshiring: versiya 3 → 21 + 2 × 4 = 29, versiya 5 → 21 + 4 × 4 = 37.

2.2 Sig'im

text
100 bayt: versiya 5
1000 bayt: versiya 22
2953 bayt: versiya 40
2954 bayt: Error: The amount of data is too big to be stored in a QR Code
kirill 'Ўқиш': segmentlar Byte:8 (UTF-8 bayt rejimi)
  • Bayt rejimida L darajada eng ko'pi 2 953 bayt — bitta ortiqcha bayt — xato ("ma'lumot QR kodga sig'maydi").
  • 1 000 bayt — versiya 22: 105×105 modul, telefon kamerasi uchun juda zich.
  • Kirill Ўқиш — 4 belgi, lekin UTF-8 da 8 bayt: QR kirill harfni 2 bayt sifatida saqlaydi.

Amaliy xulosa: QR'ga butun ma'lumotni emas, qisqa havola yoki ID qo'ying. Qisqa QR — kichik versiya — yomon kamera va xira bosmada ham o'qiladi.

Tekshirib ko'ring: Chipta QR'iga ism, familiya, pasport raqami, o'rindiq, tadbir nomi va sanani JSON qilib qo'ymoqchisiz. Bu qanday ikki sababga ko'ra yomon g'oya?

Javob
  1. Maxfiylik: QR shifrlanmagan — chipta rasmi ijtimoiy tarmoqqa tushsa, pasport raqami ham. 2. Sig'im va o'qilish: JSON yuzlab bayt — kod zich, yomon sharoitda o'qilmaydi. To'g'ri yo'l — qisqa imzolangan token; ma'lumot serverda, token bo'yicha olinadi.

3. qrcode paketi: PNG va SVG

bash
npm i qrcode@1.5.4
js
import QRCode from "qrcode";

const URL_ = "https://vazifalar.example.uz/v/12345";
const png = await QRCode.toBuffer(URL_, {
  errorCorrectionLevel: "M", margin: 4, scale: 4,
});
const svg = await QRCode.toString(URL_, {
  type: "svg", errorCorrectionLevel: "M", margin: 2,
});
const q = QRCode.create(URL_, { errorCorrectionLevel: "M" });
console.log(q.version, q.modules.size);

Kanon natijasi:

text
SVG 1512 belgi, boshi: <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 33 33" shape-rendering="crispEdges"><…
PNG yasash: mediana 4.77 ms
SVG yasash: mediana 0.77 ms
PNG SVG
Yasash (kanon, mediana) 4.77 ms 0.77 ms
Kattalashtirish xiralashadi (o'lcham scale bilan oldindan) istalgancha, aniq
Qayerda email (ko'p pochta dasturi SVG ko'rsatmaydi), Telegram veb-sahifa, PDF
  • margin — atrofdagi oq hoshiya (modullarda). Skanerlar uchun kerak; standart tavsiyasi — 4. Kanon SVG'da 2 ishlatdi: viewBox="0 0 33 33" = 29 + 2 × 2.
  • shape-rendering="crispEdges" — brauzer kvadrat chetlarini xiralashtirmasin.
  • SVG — oddiy matn: uni sahifaga to'g'ridan qo'yish mumkin. Lekin bu SVG sizning serveringiz yasagan — foydalanuvchi yuklagan SVG emas (Fayl yuklash xavfsizligi).

QR'ni PDF'ga qo'yish: PDFKit'da doc.image(pngBuferi, x, y, { width: 100 }) (PDF generatsiya).

4. Shtrix-kod: bwip-js

4.1 Turlari

bash
npm i bwip-js@4.11.4

bwip-js — 100 dan ortiq shtrix-kod turini yasaydi (u BWIPP PostScript kutubxonasining JS porti). Eng ko'p uchraydiganlari:

Tur (bcid) Nima uchun Ma'lumot
code128 ombor, yetkazib berish yorliqlari harf, raqam, belgilar
ean13 chakana savdo mahsuloti 12 raqam + nazorat raqami
qrcode, datamatrix 2D kodlar matn

Kanon natijasi:

text
code128 VZF-000123: PNG 3406 bayt
ean13 478000000001: PNG 1670 bayt
ean13 4780000000019: Error: bwipp.ean13badCheckDigit#6915: Incorrect EAN-13 check digit provided
ean13 4780000000010: Error: bwipp.ean13badCheckDigit#6915: Incorrect EAN-13 check digit provided
EAN-13 nazorat raqami '478000000001' → 4

12 raqam berilsa — bwip-js nazorat raqamini o'zi qo'shadi. 13 raqam noto'g'ri nazorat bilan — xato ("noto'g'ri EAN-13 nazorat raqami").

4.2 Nazorat raqami

EAN-13 nazorat raqami — skaner xatosini ushlash uchun. Qoida: 12 raqam, toq o'rindagilar ×1, juft o'rindagilar ×3, yig'indini 10 ga to'ldiruvchi raqam:

js
function nazorat(s12) {
  const y = [...s12].reduce(
    (a, d, i) => a + Number(d) * (i % 2 ? 3 : 1), 0);
  return (10 - (y % 10)) % 10;
}
console.log(nazorat("478000000001"));
console.log("478000000001" + nazorat("478000000001"));

Konsolda:

text
4
4780000000014

478000000001: 4 + 7×3 + 8 + 0… + 1×3 = 36, 40 gacha — 4. Kanon bilan bir xil. Oxirgi % 10 — yig'indi 10 ga karrali bo'lsa, nazorat 0 (10 emas).

478 — GS1 O'zbekiston prefiksi (GS1 prefikslar ro'yxati, 2026-10 holati). Prefiks mahsulot qayerda ishlab chiqarilganini bildirmaydi — faqat kodni qaysi milliy GS1 tashkiloti berganini. Haqiqiy mahsulot kodi faqat GS1 a'zoligi bilan beriladi — o'zingiz "478…" kod o'ylab topib, savdoga chiqara olmaysiz. Ichki ombor yorlig'i uchun Code 128 yetarli.

5. Imzolangan payload

5.1 Muammo

Tadbir chiptasi QR'ida https://tadbir.example.uz/chipta/12345. Hujumchi 12346 deb o'zgartirib, yangi QR yasaydi — boshqa odamning chiptasi. Yoki chiptani bir necha do'stiga yuboradi.

Yechim — QR ichiga imzolangan token: payload.imzo, bu yerda payload — base64url JSON ({ v, k, exp }), imzo — server siri bilan HMAC-SHA256 (crypto 1: tasodif, hash va HMAC). Bu JWT g'oyasining soddalashtirilgan ko'rinishi — JWT'ni 28-qismda chuqur o'rganasiz.

5.2 Web Crypto bilan

Kanon node:crypto (createHmac, timingSafeEqual) ishlatdi. Biz xuddi shu mantiqni brauzerda ham ishlaydigan Web Crypto bilan yozamiz. Sir — namuna (haqiqiy ilovada .env dan, kamida 32 tasodifiy bayt):

js
const enc = new TextEncoder();
const b64u = (bayt) => btoa(String.fromCharCode(...bayt))
  .replaceAll("+", "-").replaceAll("/", "_").replace(/=+$/, "");
const b64uOch = (s) => Uint8Array.from(
  atob(s.replaceAll("-", "+").replaceAll("_", "/")),
  (c) => c.charCodeAt(0));

// namuna sir — haqiqiy ilovada .env dan
const kalit = await crypto.subtle.importKey("raw",
  enc.encode("namuna-sir-faqat-dars-uchun-32-bayt!"),
  { name: "HMAC", hash: "SHA-256" }, false, ["sign", "verify"]);

async function imzola(obj) {
  const p = b64u(enc.encode(JSON.stringify(obj)));
  const s = await crypto.subtle.sign("HMAC", kalit, enc.encode(p));
  return `${p}.${b64u(new Uint8Array(s))}`;
}
async function tekshir(token, hozir) {
  const [p, s] = token.split(".");
  if (!p || !s) return "format";
  const ok = await crypto.subtle.verify("HMAC", kalit,
    b64uOch(s), enc.encode(p));
  if (!ok) return "imzo noto'g'ri";
  const o = JSON.parse(new TextDecoder().decode(b64uOch(p)));
  if (o.exp < hozir / 1000) return "muddati o'tgan";
  return o;
}

const hozir = Date.parse("2026-10-28T10:00:00Z");
const token = await imzola({ v: 12345, k: "ulashish",
  exp: hozir / 1000 + 600 });
console.log(token);
console.log(`https://vazifalar.example.uz/q/${token}`.length);
console.log(await tekshir(token, hozir));

const [p, s] = token.split(".");
const soxta = b64u(enc.encode(JSON.stringify(
  { v: 99999, k: "ulashish", exp: hozir / 1000 + 600 })));
console.log(await tekshir(`${soxta}.${s}`, hozir));
console.log(await tekshir(token, hozir + 3600_000));
console.log(new TextDecoder().decode(b64uOch(p)));

Konsolda:

text
eyJ2IjoxMjM0NSwiayI6InVsYXNoaXNoIiwiZXhwIjoxNzkzMTgyMjAwfQ.Wo0t5YnOqdeI2YRQ7n5dvf3n4jazMREuGFmuT73wZ5A
133
{ v: 12345, k: 'ulashish', exp: 1793182200 }
imzo noto'g'ri
muddati o'tgan
{"v":12345,"k":"ulashish","exp":1793182200}

Kanon natijasi (o'z sirida, tasodifiy — shuning uchun token va exp boshqa):

text
havola: 133 belgi; QR versiya (M): 8
tekshiruv: {"v":12345,"k":"ulashish","exp":1793110748}
payload o'zgartirildi (v 99999): imzo noto'g'ri
1 soatdan keyin: muddati o'tgan
Eslatma: payload base64url — SHIFRLANMAGAN, istalgan kishi o'qiydi: {"v":12345,"k":"ulashish","exp":1793110748}

Bir xil manzara:

  • Havola 133 belgi — QR versiya 8 (49×49), skanerlash uchun hali qulay.
  • v ni 99999 ga o'zgartirish — "imzo noto'g'ri": sirsiz yangi imzo yasab bo'lmaydi.
  • 1 soatdan keyin — "muddati o'tgan".
  • Oxirgi qator: payload'ni istalgan kishi o'qiydi. Imzo o'zgartirishdan himoya qiladi, o'qishdan emas. Maxfiy narsa qo'ymang.

crypto.subtle.verify imzoni doimiy vaqtda solishtiradi; kanon node:crypto da buning uchun timingSafeEqual ishlatdi. Oddiy === bilan solishtirish vaqt bo'yicha ma'lumot sizdirishi mumkin. Bu timing attack (vaqt hujumi): === birinchi farq qilgan belgida to'xtaydi, hujumchi javob vaqtini o'lchab imzoni belgima-belgi taxmin qiladi.

sequenceDiagram
  participant S as Server
  participant T as Telefon (skaner)
  participant K as Kirish nazorati
  S->>S: payload + HMAC(sir) = token
  S-->>T: QR: https://…/q/token
  T->>K: token
  K->>K: imzo, muddat, ishlatilganmi
  K-->>T: kirish yoki rad

6. Bir martalik chipta

Imzo va muddat chiptaning soxta emasligini isbotlaydi, lekin uni nusxalashdan himoya qilmaydi: bir xil QR'ni 5 kishi skanerlasa, beshalasi uchun ham imzo to'g'ri. Yechim — server holati: ishlatilgan chipta ID'lari. 3-mashqda buni Set bilan qilasiz; real ilovada — baza:

sql
UPDATE chiptalar SET ishlatilgan_vaqt = now()
 WHERE id = $1 AND ishlatilgan_vaqt IS NULL
RETURNING id;

Bitta atomik UPDATE: ikki kirish nazoratchisi bir vaqtda skanerlasa ham, faqat biri qator oladi, ikkinchisi 0 rows — "allaqachon ishlatilgan" (UPDATE va DELETE xavfsiz). Bu SQL — naqsh; chiptalar jadvali kanonda yo'q.

7. Hujumchi nigohi

  1. ID'ni o'zgartirish. Imzosiz QR'dagi ID almashtiriladi. Himoya: HMAC imzo.
  2. Nusxalash. Bitta QR — ko'p kirish. Himoya: bir martalik holat, atomik UPDATE.
  3. Maxfiy ma'lumot QR'da. Payload shifrlanmagan. Himoya: faqat ID va muddat.
  4. QR orqali fishing (quishing). Afishadagi QR ustiga boshqa QR yopishtiriladi — foydalanuvchi soxta saytga. Himoya: QR havolasi faqat o'z domeningizga; ilovada QR skanerlaganda domenni ko'rsating.
  5. Sir sizishi. HMAC siri kodda yoki GitHub'da — hamma chipta yasaydi. Himoya: .env, sirlar menejeri, sirni almashtirish rejasi (Sirlarni boshqarish).

8. Ko'p uchraydigan xatolar

Xato Sabab Davosi
The amount of data is too big 2 953 baytdan ko'p (L) qisqa havola yoki ID
QR yomon o'qiladi versiya katta, hoshiya yo'q qisqa ma'lumot, margin ≥ 4
Logotip qo'yilgach o'qilmaydi daraja L/M H daraja
Emailda QR ko'rinmaydi SVG PNG (yoki CID ilova)
ean13badCheckDigit nazorat raqami noto'g'ri 12 raqam bering yoki hisoblang
Bitta chipta bilan ko'p kirish holat yo'q bir martalik UPDATE
Imzo === bilan solishtirildi timing attack verify / timingSafeEqual

9. Mashqlar

Mashqlar kurs/mashqlar/29/12-qr/ da.

1-mashq (oson): bo'shliqlarni to'ldiring

  • Logotipli QR uchun xato tuzatish darajasi —
  • Versiya 1 QR — ×21 modul
  • Bayt rejimida L darajada eng ko'p — bayt
  • QR payload base64url'da — u
  • EAN-13 da raqamlar soni —
Yechim
  • H — ~30 % tiklash.
  • 21 — har versiya +4.
  • 2953 — 2 954 da xato.
  • shifrlanmagan — imzo faqat o'zgartirishdan himoya qiladi.
  • 13 — 12 + nazorat raqami.

2-mashq (o'rta): EAN-13 tekshiruvchi

ean13Togrimi(kod) funksiyasini yozing: 13 ta raqam bo'lmasa "format", nazorat raqami to'g'ri bo'lsa "to'g'ri", aks holda "xato" qaytarsin. Kanondagi uchta kod, 12 raqamli kod va mashhur namuna 4006381333931 bilan sinang.

Yechim
js
function ean13Togrimi(kod) {
  if (!/^\d{13}$/.test(kod)) return "format";
  const y = [...kod.slice(0, 12)].reduce(
    (a, d, i) => a + Number(d) * (i % 2 ? 3 : 1), 0);
  const togri = (10 - (y % 10)) % 10 === Number(kod[12]);
  return togri ? "to'g'ri" : "xato";
}
for (const k of ["4780000000014", "4780000000019", "4780000000010",
  "478000000001", "4006381333931"]) {
  console.log(k.padEnd(14), ean13Togrimi(k));
}

Konsolda:

text
4780000000014  to'g'ri
4780000000019  xato
4780000000010  xato
478000000001   format
4006381333931  to'g'ri

Ikki "xato" — kanonda bwip-js ean13badCheckDigit bergan kodlar. Bu tekshiruvni importda (mahsulotlar CSV'si — Excel va CSV) ishlatsangiz, skaner yoki qo'lda kiritish xatosini darhol ushlaysiz.

3-mashq (qiyin): bir martalik chipta

Darsdagi imzola va tekshiruv mantiqi asosida kirit(token, hozir) funksiyasini yozing: imzo, muddat va ishlatilgan (Set) ni tekshirsin. Birinchi to'g'ri skanerda "kirish: chipta <id>" qaytarib, ID'ni belgilasin; takrorda — "allaqachon ishlatilgan". Payload — { id, exp }. Besh holatni sinang: birinchi kirish, takror, muddati o'tgan, buzilgan imzo va ikkinchi chiptaning vaqtida kirishi.

Yechim
js
const enc = new TextEncoder();
const b64u = (bayt) => btoa(String.fromCharCode(...bayt))
  .replaceAll("+", "-").replaceAll("/", "_").replace(/=+$/, "");
const b64uOch = (s) => Uint8Array.from(
  atob(s.replaceAll("-", "+").replaceAll("_", "/")),
  (c) => c.charCodeAt(0));
const kalit = await crypto.subtle.importKey("raw",
  enc.encode("namuna-sir-faqat-dars-uchun-32-bayt!"),
  { name: "HMAC", hash: "SHA-256" }, false, ["sign", "verify"]);

async function imzola(obj) {
  const p = b64u(enc.encode(JSON.stringify(obj)));
  const s = await crypto.subtle.sign("HMAC", kalit, enc.encode(p));
  return `${p}.${b64u(new Uint8Array(s))}`;
}

const ishlatilgan = new Set();
async function kirit(token, hozir) {
  const [p, s] = token.split(".");
  if (!p || !s) return "format";
  const ok = await crypto.subtle.verify("HMAC", kalit,
    b64uOch(s), enc.encode(p));
  if (!ok) return "imzo noto'g'ri";
  const o = JSON.parse(new TextDecoder().decode(b64uOch(p)));
  if (o.exp < hozir / 1000) return "muddati o'tgan";
  if (ishlatilgan.has(o.id)) return "allaqachon ishlatilgan";
  ishlatilgan.add(o.id);
  return `kirish: chipta ${o.id}`;
}

const hozir = Date.parse("2026-10-28T10:00:00Z");
const exp = hozir / 1000 + 3600;
const a = await imzola({ id: "CH-001", exp });
const b = await imzola({ id: "CH-002", exp });
console.log(await kirit(a, hozir));
console.log(await kirit(a, hozir + 60_000));
console.log(await kirit(b, hozir + 2 * 3600_000));
console.log(await kirit(b.slice(0, -2) + "xx", hozir));
console.log(await kirit(b, hozir));

Konsolda:

text
kirish: chipta CH-001
allaqachon ishlatilgan
muddati o'tgan
imzo noto'g'ri
kirish: chipta CH-002

Tartib muhim: avval imzo, keyin muddat, oxirida holat. Imzosiz tokenni Set ga qo'shsangiz, hujumchi soxta ID'lar bilan haqiqiy chiptalarni "ishlatilgan" qilib qo'yadi. Set — jarayon xotirasida: server qayta yonsa yoki ikki nusxa bo'lsa, holat yo'qoladi. Shuning uchun real tizimda — bazadagi atomik UPDATE («Bir martalik chipta» bo'limi).

10. Loyiha qadami: kanon tajribasi, loyihaga hali kirmaydi

Bu darsda vazifalar-api ga kod qo'shilmaydi. Kanon qrcode va bwip-js ni faqat tajribada sinadi: darajalar, sig'im, PNG/SVG vaqti, imzolangan payload va shtrix-kodlar. Sabab: vazifalar ilovasida "QR bilan ulashish" — imzolangan token va ulashish huquqi kerak, bu esa auth (28-qism) va ulashish modeliga bog'liq. Chiptalar va mahsulot shtrix-kodlari — 38-qism bozor loyihasida tabiiy joy topadi.

O'zingiz sinab ko'ring: alohida papkada npm i qrcode@1.5.4, «Web Crypto bilan» bo'limidagi tokenni QRCode.toString(havola, { type: "svg" }) bilan SVG qiling, HTML faylga qo'yib, telefon kamerasi bilan skanerlang.

11. Real ishda

  • To'lov QR'lari — to'lov ilovalari QR ichiga savdogar va summa ma'lumotini qo'yadi; ular ham imzolangan yoki server tomonida tekshiriladi (to'lovlar — shu qismning keyingi darslari).
  • Cheklar — soliq tizimi QR'i chekning haqiqiyligini tekshirish sahifasiga olib boradi.
  • Tadbir va transport chiptalari — imzolangan, muddatli, bir martalik token; ba'zan oflayn tekshiruv uchun ochiq kalitli imzo (Ed25519).
  • Intervyuda: "QR ichiga nima qo'yasiz?", "Chiptani nusxalashdan qanday himoya qilasiz?", "HMAC va shifrlash farqi?"

Xulosa

  • QR: versiya 1–40 (21 + 4 × (v − 1) modul), daraja L/M/Q/H (~7–30 % tiklash); bayt rejimida L — 2 953 bayt.
  • qrcode: PNG 4.77 ms (email), SVG 0.77 ms (veb, PDF); qisqa ma'lumot — kichik versiya — yaxshi o'qilish.
  • bwip-js: Code 128, EAN-13; nazorat raqami 1/3 og'irlik bilan, noto'g'risi — ean13badCheckDigit.
  • QR payload shifrlanmagan: maxfiy narsa emas, imzolangan qisqa token (HMAC-SHA256, muddat).
  • Imzo soxtalikdan, bazadagi atomik holat — nusxalashdan himoya qiladi.

Keyingi dars: Email yuborish: SMTP va Nodemailer — fayl mavzusi tugadi; endi foydalanuvchiga xat yuboramiz.

Manbalar

Ulashish:Telegram'da

Izohlar (0)

Izoh yozish uchun kiring.

  • Hozircha izoh yo'q. Birinchi bo'ling!