chữ ký số và hóa đơn điện tử
Để tích hợp chữ ký số (Digital Signature) và hóa đơn điện tử (E-invoice) vào hệ thống bán vé hiện tại của anh (Flask + PostgreSQL), quy trình thực tế sẽ không chạy trực tiếp bằng code thuần tự viết từ đầu. Lý do là hóa đơn điện tử bắt buộc phải được cấp mã hoặc truyền dữ liệu đến Cục Thuế thông qua một nhà cung cấp giải pháp được Tổng cục Thuế cấp phép (gọi là bên T-VAN như Viettel Sinvoice, VNPT Invoice, BKAV eHoadon, MISA MeInvoice,...).
Dưới đây là kiến trúc luồng đi và các bước để anh triển khai tích hợp:
1. Kiến trúc luồng hoạt động (Workflow)
Khi khách hàng thanh toán vé thành công, hệ thống sẽ tự động chạy luồng sau:
SePay bắn Webhook báo
paid(Thành công) vềapp.pycủa anh.Code Python sau khi chuyển trạng thái vé thành
paidtrong DB, sẽ lập tức gọi một hàm kết nối sang API của nhà cung cấp Hóa đơn điện tử (ví dụ: VNPT, Viettel, MISA).Nhà cung cấp hóa đơn nhận dữ liệu đơn hàng $\rightarrow$ Sử dụng Chữ ký số (thường là HSM - chữ ký số server để ký tự động tốc độ cao) để ký số lên file hóa đơn.
Hệ thống hóa đơn điện tử gửi dữ liệu lên Cục Thuế để lấy mã (nếu là hóa đơn có mã).
Trả về file
PDF(để xem) vàXML(dữ liệu gốc) $\rightarrow$ Hệ thống của anh lưu lại link hoặc gửi email tự động cho khách hàng.
2. Các bước triển khai thực tế
Bước 1: Chuẩn bị hạ tầng pháp lý & Tài khoản API
Anh không thể tự sinh ra file hóa đơn rồi bảo đó là hóa đơn điện tử hợp pháp được. Anh cần liên hệ một bên cung cấp (MISA, Viettel, VNPT...) để:
Ký hợp đồng mua gói hóa đơn điện tử (ví dụ: gói 1.000 hóa đơn).
Đăng ký mẫu hóa đơn với Cục Thuế (bên cung cấp sẽ hỗ trợ từ A-Z).
Mua Chữ ký số HSM (Hardware Security Module): Đây là loại chữ ký số đặt trên server của nhà cung cấp hóa đơn, giúp hệ thống Python của anh gọi API là tự động ký được ngay (không thể dùng USB Token cắm vào máy tính vì USB Token cần người bấm mật khẩu tay từng tờ, không tự động hóa hoàn toàn được).
Yêu cầu họ cấp: Tài liệu API tích hợp, Đường dẫn Environment (Test/Live), API Key / Secret / Token.
Bước 2: Viết Module gọi API xuất hóa đơn trong app.py
Khi đã có thông tin API từ nhà cung cấp (ví dụ dưới đây mô phỏng theo cấu trúc chuẩn RESTful API của các bên như MISA/Viettel), anh bổ sung một hàm create_invoice vào file Python.
Anh cần cài thêm thư viện gọi API: pip install requests
import requests
def create_invoice_auto(ticket_id, customer_name, ticket_count, total_amount):
"""
Hàm tự động gọi sang nhà cung cấp Hóa đơn để lập và ký số hóa đơn
"""
# URL API do bên phát hành hóa đơn cung cấp
API_URL = "https://api.nhacunghocaphoadon.vn/v1/invoice/create-and-sign"
headers = {
"Authorization": "Bearer YOUR_API_ACCESS_TOKEN",
"Content-Type": "application/json"
}
# Dữ liệu hóa đơn chuẩn bị gửi đi
invoice_data = {
"invoice_type": "HOA_DON_BAN_HANG", # Hoặc hóa đơn GTGT
"buyer_name": customer_name,
"buyer_legal_name": customer_name,
"payment_method": "CK", # Chuyển khoản
"items": [
{
"item_name": "Vé tham quan",
"quantity": ticket_count,
"price": 20000,
"amount": total_amount,
"tax_rate": 0 # Hoặc 8%, 10% tùy loại dịch vụ của anh
}
],
"total_amount": total_amount,
"reference_id": ticket_id # Gắn mã vé của anh để đối chiếu
}
try:
response = requests.post(API_URL, json=invoice_data, headers=headers, timeout=10)
if response.status_code == 200:
result = response.json()
# Trả về link PDF hóa đơn hoặc mã số hóa đơn để lưu trữ
print(f"--> [HÓA ĐƠN OK] Đã xuất HDĐT cho vé {ticket_id}. Số HD: {result.get('invoice_number')}")
return result.get("invoice_pdf_url")
else:
print(f"--> [LỖI HÓA ĐƠN] Bên hóa đơn trả về lỗi: {response.text}")
return None
except Exception as e:
print(f"--> [LỖI KẾT NỐI API HOA ĐƠN]: {str(e)}")
return None
Bước 3: Gắn hàm xuất hóa đơn vào luồng Webhook thành công
Tại hàm @app.route('/webhook/agribank-notify', methods=['POST']) anh đang chạy, ngay dưới dòng cập nhật database sang paid, anh gọi hàm này để hệ thống tự động xuất hóa đơn khi nhận được tiền:
# ... Đoạn code xử lý trong vòng lặp Webhook của anh ...
if transfer_amount >= int(ticket['total_amount']):
# 1. Cập nhật trạng thái vé thành đã thanh toán
cur.execute("UPDATE tickets SET status = 'paid' WHERE id = %s;", (ticket['id'],))
conn.commit()
print(f"--> [OK AUTOMATIC] Vé #{ticket['id']} đã được tự động duyệt!")
# 2. GỌI TỰ ĐỘNG XUẤT HÓA ĐƠN ĐIỆN TỬ TẠI ĐÂY
pdf_invoice_url = create_invoice_auto(
ticket_id=ticket['id'],
customer_name=ticket['customer_name'], # Tên khách hàng lấy từ DB
ticket_count=ticket['ticket_count'],
total_amount=ticket['total_amount']
)
# 3. (Tùy chọn) Lưu link hóa đơn vào DB hoặc gửi email cho khách kèm link này
if pdf_invoice_url:
# Cập nhật trường invoice_url trong bảng tickets nếu anh có cấu hình cột này
pass
is_matched = True
# ...
3. Lời khuyên cho anh khi chọn giải pháp
Về Chữ ký số: Tuyệt đối chọn Chữ ký số HSM / Chữ ký số từ xa (Remote Signing) tích hợp thẳng vào server hóa đơn. Đừng chọn loại USB Token vì anh không thể cắm USB vào máy chủ rồi bắt nó tự động ký mà không có người can thiệp trực tiếp được.
Về nhà cung cấp hóa đơn: Anh nên ưu tiên chọn MISA (MeInvoice) hoặc Viettel (SInvoice). Đây là hai bên có tài liệu API bằng Python/JSON rất rõ ràng, tường minh và đội ngũ kỹ thuật hỗ trợ cổng kết nối (Webhook/API) cho lập trình viên rất nhanh.
Anh định chọn nhà cung cấp hóa đơn điện tử nào để em có thể hướng dẫn cấu hình chi tiết theo đúng form dữ liệu của bên đó?

