---
title: "QR Code là gì? Hướng dẫn Tạo và Đọc QR Code với TypeScript"
description: "QR code là mã vạch ma trận hai chiều cho phép lưu trữ nhiều dữ liệu (hàng nghìn ký tự), quét được từ mọi góc độ và có khả năng chống lỗi cao"
canonical: "https://200lab.io/blog/qr-code-la-gi"
published: "2025-03-06T07:48:42Z"
updated: "2026-08-21T07:17:48Z"
authors: ["Hướng nội"]
tags: ["Backend"]
reading_minutes: 7
access: "public"
---

## 1. QR Code là gì?

QR code (Quick Response code) là mã vạch ma trận hai chiều được phát triển bởi Denso Wave năm 1994, cho phép lưu trữ nhiều dữ liệu (hàng nghìn ký tự), quét được từ mọi góc độ và có khả năng chống lỗi cao. Được ứng dụng rộng rãi trong thanh toán, marketing và xác thực.

![](https://assets.200lab.io/images/2025/03/06/qr-code-la-gi-2-f19dfeddc0f4d373ac3f.webp)

Khác với mã vạch truyền thống (1D), QR code sử dụng cấu trúc ma trận điểm (module)** **để lưu trữ dữ liệu, cho phép nó chứa lượng thông tin lớn trong một kích thước nhỏ, đồng thời đảm bảo quét chính xác ngay cả khi bị hư hỏng hoặc đặt trong điều kiện ánh sáng kém.

Một QR code tiêu chuẩn có thể chứa:

- Tối đa 7.089 ký tự số
- 4.296 ký tự chữ và số
- 2.953 byte dữ liệu nhị phân
- 1.817 ký tự Kanji/Kana

## 2. So sánh QR Code với Barcode

Đặc điểm
QR Code
Barcode

Hướng quét
Quét được từ mọi góc độ (360°)
Chỉ quét được theo chiều ngang

Dung lượng dữ liệu
Lớn (hàng nghìn ký tự)
Nhỏ (chỉ 10-20 ký tự)

Kích thước
Nhỏ gọn, chứa được nhiều thông tin
Cần nhiều không gian hơn với cùng lượng thông tin

Khả năng chống lỗi
Có thể đọc được khi 30% mã bị hỏng
Dễ bị lỗi khi mã bị hỏng

Loại dữ liệu
Đa dạng (URL, văn bản, số, email...)
Chủ yếu là số và một số ký tự đặc biệt

Quét bằng
Smartphone, máy quét chuyên dụng
Máy quét chuyên dụng

Ứng dụng
Đa dạng (thanh toán, marketing, truy xuất...)
Chủ yếu dùng trong bán lẻ và kho vận

## 3. Cấu trúc cơ bản của QR Code

QR code bao gồm các thành phần chính sau:

- **Finder Patterns** : Ba hình vuông lớn ở ba góc của QR code. Các hình vuông này giúp máy quét xác định vị trí, kích thước và góc của QR code. Nhờ vậy, QR code có thể được quét từ bất kỳ góc độ nào, không cần phải thẳng hàng như mã vạch truyền thống.
- **Alignment Patterns** : Các hình vuông nhỏ hơn phân bố trong QR code (thường nằm ở góc thứ tư và rải rác trong mã). Chúng giúp hiệu chỉnh độ cong hoặc biến dạng khi QR code được in trên bề mặt không phẳng hoặc khi máy ảnh không quét thẳng góc.
- **Timing Patterns** : Các đường đứt đoạn gồm các module đen-trắng xen kẽ, chạy ngang và dọc giữa các Finder Patterns. Chúng giúp máy quét xác định vị trí chính xác của mỗi module trong QR code, đặc biệt khi mã bị méo hoặc kích thước thay đổi.

![](https://assets.200lab.io/images/2025/03/06/qr-code-la-gi-1-8439641dab210d7a7759.webp)

- **Version Information**: Dành cho QR code từ phiên bản 7 trở lên, chứa thông tin về phiên bản của QR code. Phiên bản càng cao thì QR code càng lớn và chứa nhiều dữ liệu hơn (từ phiên bản 1 với 21x21 module đến phiên bản 40 với 177x177 module).
- **Format Information** (Thông tin định dạng): Vùng chứa thông tin về mức độ sửa lỗi và mask pattern được sử dụng. Nằm gần các Finder Patterns, giúp máy quét điều chỉnh cách đọc dữ liệu.
- **Data Area** : Phần còn lại của QR code, nơi chứa thông tin được mã hóa thực sự. Dữ liệu được mã hóa thành các module đen và trắng theo thuật toán cụ thể.
- **Error Correction Level** : QR code có 4 mức độ sửa lỗi:

- **L (Low)**: Có thể khôi phục 7% dữ liệu bị mất
- **M (Medium)**: Có thể khôi phục 15% dữ liệu bị mất
- **Q (Quartile)**: Có thể khôi phục 25% dữ liệu bị mất
- **H (High)**: Có thể khôi phục 30% dữ liệu bị mất
- **Quiet Zone** : Khoảng trống xung quanh QR code, thường có độ rộng ít nhất bằng 4 module. Vùng trống này giúp máy quét phân biệt QR code với những yếu tố khác xung quanh nó.

Nhờ cấu trúc đặc biệt này, máy quét có thể nhanh chóng nhận diện QR code, xác định hướng và giải mã nội dung, ngay cả khi mã bị hư hỏng một phần hoặc được quét từ nhiều góc độ khác nhau.

## 4. Quá trình máy quét đọc và hiểu QR code

1. **Chụp ảnh QR code**: Máy quét hoặc camera điện thoại chụp ảnh QR code.
2. **Nhận diện vị trí**: Phần mềm xác định ba Finder Patterns (góc) để định hướng và xác định biên của QR code.
3. **Hiệu chỉnh góc nhìn**: Dựa vào Alignment Patterns, phần mềm điều chỉnh hình ảnh để bù đắp cho độ nghiêng hoặc méo.
4. **Đọc các module**: Sau khi đã căn chỉnh, phần mềm đọc giá trị của từng module (đen = 1, trắng = 0) tạo thành chuỗi bit.
5. **Gỡ bỏ mask pattern**: Phần mềm xác định mask pattern đã được áp dụng và gỡ bỏ nó khỏi dữ liệu.
6. **Giải mã và sửa lỗi**: Dữ liệu nhị phân được giải mã và các lỗi được sửa nếu cần thiết.
7. **Chuyển đổi sang dữ liệu gốc**: Cuối cùng, chuỗi bit được chuyển đổi lại thành dạng dữ liệu gốc (URL, văn bản, vCard, v.v.).

Ví dụ đơn giản: Nếu bạn muốn mã hóa từ "Hello" trong QR code:

1. "Hello" được chuyển thành mã ASCII: 72 101 108 108 111
2. Các mã này được chuyển sang nhị phân: 01001000 01100101 01101100 01101100 01101111
3. Thông tin về loại dữ liệu (văn bản) được thêm vào đầu chuỗi
4. Thêm mã sửa lỗi
5. Toàn bộ chuỗi bit được sắp xếp thành các module đen trắng theo thuật toán QR code

Nhờ vậy, khi bạn quét QR code, ứng dụng quét có thể đảo ngược quá trình này để hiển thị lại từ "Hello" cho bạn.

Đây là lý do tại sao QR code có thể chứa lượng thông tin lớn trong không gian nhỏ và vẫn đảm bảo độ chính xác cao khi quét.

## 5. Hướng dẫn tạo và quét QR Code với TypeScript

### 5.1 Tạo QR Code với TypeScript

Trước tiên cài đặt thư viện bằng lệnh `npm install qrcode @types/qrcode`.

```
import QRCode from 'qrcode';

// Tạo QR code dạng URL ảnh
const generateQRAsDataURL = async (data: string): Promise<string> => {
  try {
    const url = await QRCode.toDataURL(data, {
      errorCorrectionLevel: 'M',
      margin: 1,
      width: 300
    });
    return url;
  } catch (error) {
    console.error('Error generating QR code:', error);
    throw error;
  }
};

// Sử dụng
generateQRAsDataURL('https://example.com')
  .then(url => {
    // Hiển thị QR code
    const img = document.createElement('img');
    img.src = url;
    document.body.appendChild(img);
  })
  .catch(err => console.error(err));

```

### 5.2 Quét QR Code với Typescript

```
// Cài đặt: npm install jsqr @types/jsqr
import jsQR from 'jsqr';

// Quét QR code từ webcam
class QRScanner {
  private video: HTMLVideoElement;
  private canvas: HTMLCanvasElement;
  private context: CanvasRenderingContext2D;
  private scanning: boolean = false;

  constructor(videoElementId: string) {
    this.video = document.getElementById(videoElementId) as HTMLVideoElement;
    this.canvas = document.createElement('canvas');
    this.context = this.canvas.getContext('2d') as CanvasRenderingContext2D;
  }

  public async start(callback: (data: string) => void): Promise<void> {
    try {
      const stream = await navigator.mediaDevices.getUserMedia({
        video: { facingMode: "environment" }
      });

      this.video.srcObject = stream;
      this.video.play();
      this.scanning = true;

      const scan = () => {
        if (!this.scanning) return;

        if (this.video.readyState === this.video.HAVE_ENOUGH_DATA) {
          this.canvas.width = this.video.videoWidth;
          this.canvas.height = this.video.videoHeight;
          this.context.drawImage(this.video, 0, 0, this.canvas.width, this.canvas.height);

          const imageData = this.context.getImageData(0, 0, this.canvas.width, this.canvas.height);
          const code = jsQR(imageData.data, imageData.width, imageData.height, {
            inversionAttempts: "dontInvert"
          });

          if (code) {
            callback(code.data);
          }
        }

        requestAnimationFrame(scan);
      };

      scan();

    } catch (error) {
      console.error('Error accessing camera:', error);
      throw error;
    }
  }

  public stop(): void {
    this.scanning = false;
    if (this.video.srcObject) {
      const tracks = (this.video.srcObject as MediaStream).getTracks();
      tracks.forEach(track => track.stop());
      this.video.srcObject = null;
    }
  }
}

// Sử dụng
const scanner = new QRScanner('video-element');
scanner.start((data) => {
  console.log('Scan result:', data);
  document.getElementById('result').textContent = data;
  // Nếu muốn dừng sau khi quét thành công
  // scanner.stop();
});

```

## 6. Kết luận

QR Code là một công nghệ đơn giản, dễ sử dụng nhưng lại cực kỳ hiệu quả. Với khả năng lưu trữ dữ liệu lớn, quét nhanh từ mọi góc độ và khôi phục dữ liệu ngay cả khi bị hư hại, QR Code đã và đang trở thành một phần không thể thiếu trong các giải pháp công nghệ hiện đại.

## Đọc thêm

- [Architecture Pattern - Phần 7: Hexagonal Architecture](https://200lab.io/blog/hexagonal-architecture-la-gi.md): Hexagonal Architecture là pattern kiến trúc mà mọi tương tác từ bên ngoài đều phải đi qua một Adapter để kết nối vào một Port của Application
- [File __init__.py trong Python: Hướng dẫn sử dụng toàn diện](https://200lab.io/blog/huong-dan-su-dung-toan-dien-file-init-trong-python.md): __init__.py không chỉ đơn thuần là một file đánh dấu package, nó quyết định cách package của bạn được cấu trúc, import và tối ưu ra sao
- [Thiết kế Leaderboard hiệu năng cao: Khi nào chọn SQL, Khi nào dùng Redis?](https://200lab.io/blog/thiet-ke-leaderboard-hieu-nang-cao-khi-nao-chon-sql-khi-nao-dung-redis.md): Khám phá cách thiết kế hệ thống Leaderboard tối ưu, linh hoạt, dễ mở rộng, kết hợp giữa tư duy thiết kế hệ thống hiện đại và kinh nghiệm thực tế
- [Hành vi giúp Phân biệt các Senior Engineer với những người còn lại](https://200lab.io/blog/hanh-vi-giup-phan-biet-cac-senior-engineer-voi-nhung-nguoi-con-lai.md): Việc trở thành một senior engineer thực sự không chỉ nằm ở chức danh bạn được giao, mà là kết quả của tư duy, cách tiếp cận công việc mà bạn rèn luyện mỗi ngày
- [Asynchronous Request-Reply Pattern: Giải pháp cho những tác vụ nặng](https://200lab.io/blog/asynchronous-request-reply-pattern-la-gi.md): Pattern giúp tách rời phần xử lý backend, diễn ra bất đồng bộ khỏi frontend nhưng vẫn phải đảm bảo frontend nhận được thông báo kết quả cuối cùng
- [Mọi bài viết chủ đề Backend](https://200lab.io/blog/tags/backend.md)

Toàn bộ nội dung: https://200lab.io/llms.txt
