Hế lô anh em ✌️✌️✌️
Ngày nay mã QR code chắc đã không còn xa lạ gì với chúng ta nữa. Có hàng trăm trường hợp chúng ta có thể sử dụng loại mã tiện ích này. Từ việc thanh toán trong các ứng dụng ngân hàng cho đến việc trao đổi thông tin hàng ngày...
Có rất nhiều cách để sinh ra mã QR code và trong bài viết này mình sẽ cùng anh em tìm hiểu làm sao trong ứng dụng Spring Boot chúng ta có thể sinh ra loại mã này.
Okay, let's go!!!!!
1/ Mã QR là gì?
Mặc dù bài viết này tập trung vào việc làm sao để chúng ta sinh ra được mã QR trong ứng dụng Spring Boot nhưng mình vẫn muốn giải thích với các bạn bản chất mã QR là gì.
Vì chỉ khi chúng ta hiểu được bản chất của loại mã này thì chúng ta mới hiểu được nó được tạo ra như thế nào. Nếu bạn nào không quan tâm thì có thể nhảy luôn sang phần 2 nhé!
- QR là viết tắt của Quick Response - Phản hồi nhanh. Tức là tốc độ các thiết bị đọc và giải mã loại mã này là rất nhanh.
- Mã QR có thể chứa số, chữ, ký tự (bao gồm cả các ký tự tiếng Nhật vì nguồn gốc loại mã này do người Nhật phát minh ra)
- Một mã QR sẽ gồm có 4 phần:
+ Các ô vuông định hướng: Là 3 ô vuông to ở ba góc giúp các máy quét mã định hướng được hình ảnh
+ Các ô vuông đánh dấu phiên bản: Giúp máy quét mã xác định được phiên bản của mã QR đó để đọc đúng nội dung
+ Các ô vuông đánh dấu khác: Ví dụ như đánh dấu việc sửa lỗi (phần này các bạn cũng không cần hiểu sâu quá vì nó liên quan đến việc sửa lỗi trong mã hóa)
+ Các ô vuông để thể hiện 0 và 1 trong mã nhị phân: Bản chất mã QR sẽ lưu thông tin dưới dạng các bit nhị phân 0 và 1. Các ô đen sẽ có giá trị là 1, các ô trắng sẽ có giá trị là 0.
Khi chúng ta có một chuỗi dữ liệu nếu mã hóa sang dạng mã QR chúng ta sẽ phải chuyển chuỗi đó sang dạng nhị phân 0 và 1 rồi ghi theo thứ tự từ dưới lên trên, từ phải qua trái vào ảnh với các giá trị 0 là ô trắng, 1 là ô đen.
👉Tóm lại thì các bạn chỉ cần hiểu bản chất việc sinh ra mã QR chính là việc mã hóa thông tin sang chuỗi các bit nhị phân và thể hiện chuỗi đó lên ảnh với các ô vuông trắng tương ứng với giá trị 0 và ô vuông đen với giá trị 1.
2/ Tạo ứng dụng và thêm thư viện.
Về cách tạo ứng dụng Spring Boot thì mình đã đề cập trong các bài viết trước rồi. Đơn giản nhất các bạn có thể truy cập vào trang https://start.spring.io/ và tạo một ứng dụng như hình bên dưới.
Đây chính là cấu trúc project sau khi các bạn tải về:
Bây giờ để sinh mã QR thì mình sẽ sử dụng một thư viện có tên là ZXing. Đây là một thư viện của Google và để sử dụng được thư viện này các bạn sẽ phải thêm 2 thư viện (dependency) như bên dưới vào file pom.xml
<!-- https://mvnrepository.com/artifact/com.google.zxing/core -->
<dependency>
<groupId>com.google.zxing</groupId>
<artifactId>core</artifactId>
<version>3.4.1</version>
</dependency>
<!-- https://mvnrepository.com/artifact/com.google.zxing/javase -->
<dependency>
<groupId>com.google.zxing</groupId>
<artifactId>javase</artifactId>
<version>3.4.1</version>
</dependency>
Cụ thể các bạn có thể xem ảnh bên dưới.
3/ Coding
3.1 - Đặt vấn đề
Trong bài viết này mình sẽ tạo một API và giả sử ứng dụng (mobile app hoặc web app) sau khi gọi API này, truyền các thông tin cần mã hóa lên và mình sẽ trả ra một chuỗi base64.
Chuỗi base64 này chính là ảnh QR code sau khi được mã hóa. Ứng dụng (mobile app hoặc web app) sau khi nhận được chuỗi base64 này từ server sẽ giải mã ngược lại ra ảnh ban đầu và hiển thị cho người dùng.
3.2 - Code
Để sinh ra một mã QR thường cần có 3 tham số:
+ Nội dung chúng ta muốn mã hóa: thường sẽ là một chuỗi, trong bài viết này mình sẽ mã hóa một chuỗi JSON chứa thông tin đăng nhập của người dùng.
+ Chiều rộng của ảnh chứa mã QR sau khi mã hóa.
+ Chiều dài của ảnh chứa mã QR sau khi mã hóa.
Lưu ý: chúng ta thường thấy mã QR có dạng hình vuông nên chiều dài và chiều rộng sẽ bằng nhau (trong bài viết này mình sẽ để là 300pxl)
Bây giờ mình sẽ code hàm quan trọng nhất đó chính là hàm dùng để sinh ra mã QR như sau:
public static String generateQrCode(String data, int width, int height) {
StringBuilder resultImage = new StringBuilder();
if (!data.isEmpty()) {
ByteArrayOutputStream os = new ByteArrayOutputStream();
try {
QRCodeWriter writer = new QRCodeWriter();
BitMatrix bitMatrix = writer.encode(data, BarcodeFormat.QR_CODE, width, height);
BufferedImage bufferedImage = MatrixToImageWriter.toBufferedImage(bitMatrix);
ImageIO.write(bufferedImage, "png", os);
resultImage.append("data:image/png;base64,");
resultImage.append(new String(Base64.getEncoder().encode(os.toByteArray())));
} catch (Exception e) {
e.printStackTrace();
}
}
return resultImage.toString();
}
Mình sẽ giải thích một chút.
Đầu tiên là hàm encode()
của lớp QRCodeWriter
sẽ nhận vào 4 tham số:
QRCodeWriter writer = new QRCodeWriter();
BitMatrix bitMatrix = writer.encode(data, BarcodeFormat.QR_CODE, width, height);
data
: Dữ liệu đầu vào cần mã hóa (thường là một chuỗi)
BarcodeFormat.QR_CODE
: Hàm encode()
hỗ trợ mã hóa theo nhiều kiểu mã hóa khác nhau. Với BarcodeFormat.QR_CODE có nghĩa là chúng ta đang mã hóa thành mã QR.
width
và height
là hai tham số về kích thước của ma trận ảnh sau khi sinh ra.
Hàm wirte()
nhận vào 3 tham số:
BufferedImage bufferedImage = MatrixToImageWriter.toBufferedImage(bitMatrix);
ImageIO.write(bufferedImage, "png", os);
bufferedImage
: Đây chính kết quả sau khi chúng ta thực hiện "ghi" ma trận các bit vào ảnh
png
: Là định dạng file chúng ta muốn ghi ra
os
: Là kiểu dữ liệu chúng ta sẽ ghi ra, trong trường hợp này là một luồng các mảng byte thông qua lớp ByteArrayOutputStream
.
Cuối cùng mình sử dụng mã hóa Base64 để mã hóa ảnh đầu vào. Ở đây mình thêm một phần là "data:image/png;base64,"
. Phần này dùng để định nghĩa ảnh được mã hóa base64 khi mà chúng ta thêm vào thẻ src trong file .html
resultImage.append("data:image/png;base64,");
resultImage.append(new String(Base64.getEncoder().encode(os.toByteArray())));
Trên đây là toàn bộ nội dung hàm quan trọng nhất của bài viết. Bây giờ mình sẽ tạo một API để chúng ta có thể mô phỏng cách thức sinh mã QR này như thế nào nhé.
Đầu tiên mình sẽ tạo lớp controller với API /generateQRCode
sử dụng phương thức POST
để truyền thông tin lên server như sau:
@RestController
public class GenerateQrController {
@Autowired
QrCodeService qrCodeService;
@PostMapping(value = "generateQRCode")
public String generateQRCode(
@RequestBody UserLoginSdi sdi
) {
return qrCodeService.generateQrCode(sdi);
}
}
Data truyền lên:
@Data
public class UserLoginSdi {
private String name;
private String email;
private String phone;
}
Sau đó là các lớp service để thực hiện các logic nghiệp vụ (trong bài viết này chỉ đơn giản là sinh mã QR và trả về cho client)
@Service
public class QrCodeServiceImpl implements QrCodeService{
private static final int ORDER_QR_CODE_SIZE_WIDTH = 300;
private static final int ORDER_QR_CODE_SIZE_HEIGHT = 300;
@Override
public String generateQrCode(UserLoginSdi sdi) {
String prettyData = AppUtils.prettyObject(sdi);
String qrCode = AppUtils.generateQrCode(prettyData, ORDER_QR_CODE_SIZE_WIDTH, ORDER_QR_CODE_SIZE_HEIGHT);
return qrCode;
}
}
Ở đây có một hàm là prettyObject()
. Mình sử dụng để chuyển đổi đối tượng trong Java sang dạng JSON. Các bạn có thể tham khảo nội dung hàm này trong phần mã nguồn mình đính kèm cuối bài viết.
Okay, vậy là code xong rồi đó, cũng không phức tạp lắm! Cơ bản đã có thư viện lo hết rồi, việc của chúng ta chỉ là sử dụng thôi.
4/ Testing
Bây giờ mình sẽ chạy ứng dụng lên và sử dụng Postman để test. Các bạn có thể xem ảnh bên dưới để dễ hình dung hơn.
Sau khi có được chuỗi mã hóa dạng Base64 mình sẽ gửi lại thông tin này cho các ứng dụng app hoặc web. Các ứng dụng này sẽ giải mã và hiển thị cho người dùng.
Trong ví dụ này để đơn giản thì mình sẽ sử dụng một trình giải mã Base64 online để giải mã thay cho ứng dụng app hoặc web app.
Đây là đại chỉ trang web mình sử dụng: https://codebeautify.org/base64-to-image-converter
Và kết quả sẽ như sau:
Các bạn có thể sử dụng điện thoại hoặc bất cứ thiết bị nào hỗ trợ quét mã QR để quét mã trên. Và đây là kết quả khi mình sử dụng điện thoại để quét.
Tất nhiên trong thực tế các ứng dụng mobile hoặc ứng dụng web sẽ sử dụng thông tin này để chuyển hướng đến một trang nào đó hoặc thậm chí họ cũng có thể tự sinh ra mã QR mà không cần phía server phải sinh ra như thế này.
5/ Lời kết
Vậy là trong bài viết này mình đã cùng các bạn tìm hiểu cách mà chúng ta sinh ra mã QR trong ứng dụng Spring Boot.
Tất nhiên thư viện đã hỗ trợ chúng ta rất nhiều nhưng trên thực tế việc sinh mã QR không đơn giản như vậy. Bài viết này với mục đích giới thiệu và hướng dẫn cơ bản nên hi vọng sẽ giúp ích được các bạn.
Nếu còn thiết sót gì các bạn có thể bình luận để mình bổ sung nhé.
Cuối cùng là mã nguồn nếu bạn nào muốn tham khảo thì có thể tìm thấy tại đây
Thanks all ❤️❤️❤️ Hẹn gặp lại các bạn trong các bài viết tiếp theo.!
Không có nhận xét nào: