Tất cả bài viết
Các sự kiện nhắn tin di động đi qua bước xác minh webhook kiểu Meta và đường hầm bảo mật tới ứng dụng localhost.
WhatsApp Cloud APIMeta webhookslocalhostwebhook security

Kiểm thử webhook WhatsApp Cloud API trên localhost

Để kiểm tra webhook API WhatsApp Cloud trên máy chủ cục bộ, hãy hiển thị điểm cuối cục bộ của bạn thông qua HTTPS, triển khai thử thách xác minh GET của Meta, sau đó xác minh từng yêu cầu POST X-Hub-Signature-256 đối với nội dung thô. Đăng ký URL đường hầm trong ứng dụng Meta của bạn, đăng ký WhatsApp Tài khoản doanh nghiệp tới messages và gửi tin nhắn thử nghiệm để nhận trọng tải thực mà không cần triển khai.

Các webhook của WhatsApp sử dụng hai luồng xác minh khác nhau

Điểm khác biệt quan trọng nhất là việc thiết lập webhook và phân phối webhook được xác thực khác nhau. Trong quá trình thiết lập, Meta gửi yêu cầu GET chứa hub.mode, hub.verify_tokenhub.challenge. Điểm cuối của bạn so sánh mã thông báo xác minh và trả về thử thách dưới dạng văn bản thuần túy. Sau đó, việc phân phối sự kiện là các yêu cầu POST; những thông tin đó phải được xác thực bằng cách xác thực chữ ký HMAC được tạo bằng Meta App Secret của bạn.

Mã thông báo xác minh là một chuỗi ngẫu nhiên bạn chọn; nó không phải là mã thông báo truy cập WhatsApp và không phải Bí mật ứng dụng. Việc trả lại thử thách chứng tỏ quyền kiểm soát điểm cuối gọi lại. Nó không xác thực các yêu cầu POST trong tương lai. Hướng dẫn webhook WhatsApp chính thức của Meta bao gồm cấu hình gọi lại, đăng ký và trường webhook.

Tạo điểm cuối Bộ định tuyến ứng dụng Next.js

Tuyến đường bên dưới xử lý cả hai giai đoạn. Đọc dữ liệu POST bằng request.text() sẽ giữ lại số byte chính xác cần thiết để xác minh chữ ký.

// app/api/webhooks/whatsapp/route.ts
import crypto from 'node:crypto';
import { NextRequest } from 'next/server';

export const runtime = 'nodejs';

export async function GET(request: NextRequest) {
  const mode = request.nextUrl.searchParams.get('hub.mode');
  const token = request.nextUrl.searchParams.get('hub.verify_token');
  const challenge = request.nextUrl.searchParams.get('hub.challenge');

  if (mode === 'subscribe' && token === process.env.META_VERIFY_TOKEN) {
    return new Response(challenge ?? '', { status: 200 });
  }
  return new Response('Forbidden', { status: 403 });
}

export async function POST(request: Request) {
  const rawBody = await request.text();
  const supplied = request.headers.get('x-hub-signature-256') ?? '';
  const expected = 'sha256=' + crypto
    .createHmac('sha256', process.env.META_APP_SECRET!)
    .update(rawBody)
    .digest('hex');

  const a = Buffer.from(supplied);
  const b = Buffer.from(expected);
  if (a.length !== b.length || !crypto.timingSafeEqual(a, b)) {
    return new Response('Invalid signature', { status: 401 });
  }

  const payload = JSON.parse(rawBody);
  await enqueueWhatsAppPayload(payload);
  return new Response('EVENT_RECEIVED', { status: 200 });
}

Không gọi request.json() rồi tạo lại JSON cho HMAC. Khoảng trắng, lối thoát hoặc thứ tự khóa có thể thay đổi, tạo ra một bản tóm tắt khác. Nếu bạn sử dụng Express, hãy ghi lại Buffer trước trình phân tích cú pháp JSON chung. Hướng dẫn chung về chữ ký webhook giải thích cách xử lý phần thô trên các khung.

Bắt đầu một đường hầm và định cấu hình lệnh gọi lại

  1. Chạy ứng dụng Next.js cục bộ, thông thường với npm run dev trên cổng 3000.
  2. Chạy npx portpreview 3000 trong một thiết bị đầu cuối riêng biệt.
  3. Đặt META_VERIFY_TOKEN thành một giá trị ngẫu nhiên và META_APP_SECRET cho Bí mật ứng dụng từ cài đặt ứng dụng của Meta.
  4. Trong bảng điều khiển dành cho nhà phát triển Meta, hãy mở trang Cấu hình của sản phẩm WhatsApp.
  5. Đặt URL gọi lại thành https://YOUR-TUNNEL.portpreview.dev/api/webhooks/whatsapp và nhập cùng một xác minh mã thông báo.
  6. Sau khi xác minh thành công, hãy đăng ký trường messages cho Tài khoản WhatsApp Business.

Đường hầm phải duy trì hoạt động trong cả thử thách GET và gửi POST tiếp theo. URL được sao chép từ phiên cũ hơn có thể giải quyết nhưng không còn chuyển tiếp tới máy của bạn nữa, vì vậy hãy xác nhận lệnh gọi lại chính xác bất cứ khi nào đường hầm cục bộ thay đổi.

Kiểm tra thử thách GET một cách độc lập

Trước khi sử dụng trang tổng quan, hãy tạo lại yêu cầu cục bộ:

curl -i \
  "http://localhost:3000/api/webhooks/whatsapp?hub.mode=subscribe&hub.verify_token=${META_VERIFY_TOKEN}&hub.challenge=123456"

Phản hồi đúng là trạng thái 200 với nội dung 123456, không phải JSON và không phải "123456" có dấu ngoặc kép. Nếu mã thông báo sai thì 403 là phù hợp. Không ghi nhật ký các tham số truy vấn vì mã thông báo xác minh xuất hiện ở đó.

Hiểu tải trọng của tin nhắn trước khi viết logic nghiệp vụ

WhatsApp bao bọc dữ liệu ở nhiều cấp độ sâu. Một thông báo điển hình có object: "whatsapp_business_account", một mảng entry, một mảng changes và một thay đổi có fieldmessages. Bên trong value, nội dung người dùng đến sẽ xuất hiện trong messages; Các cập nhật về gửi, đọc và lỗi cho tin nhắn bạn đã gửi sẽ xuất hiện trong statuses.

for (const entry of payload.entry ?? []) {
  for (const change of entry.changes ?? []) {
    if (change.field !== 'messages') continue;
    for (const message of change.value.messages ?? []) {
      await handleInboundMessage({
        id: message.id,
        from: message.from,
        type: message.type,
        text: message.text?.body,
      });
    }
    for (const status of change.value.statuses ?? []) {
      await updateDeliveryStatus(status.id, status.status);
    }
  }
}

Đừng cho rằng mọi thông báo đều chứa tin nhắn văn bản. Hình ảnh, âm thanh, tài liệu, vị trí, câu trả lời tương tác, thông báo hệ thống và tải trọng chỉ có trạng thái có các hình dạng khác nhau. Giữ bộ điều phối được khóa bằng message.type, xác thực các trường tùy chọn và giữ lại các loại sự kiện không xác định để xem xét thay vì gặp sự cố.

Xác minh chính xác chữ ký POST

Giá trị X-Hub-Signature-256 sử dụng biểu mẫu sha256=<hex digest>. Tính toán HMAC-SHA256 trên các byte yêu cầu thô bằng cách sử dụng Meta App Secret. Mã thông báo truy cập WhatsApp vĩnh viễn hoặc tạm thời được sử dụng cho lệnh gọi API Đồ thị; nó không phải là khóa HMAC. Sử dụng so sánh theo thời gian liên tục và từ chối chữ ký bị thiếu.

Hãy luôn bật xác minh cục bộ. Bất kỳ ai tìm hiểu URL đường hầm đều có thể POST JSON tùy ý lên đó. Nếu không xác minh, một sự kiện giả mạo có thể kích hoạt phản hồi tự động, thay đổi bản ghi CRM hoặc tiết lộ trạng thái của khách hàng. Xoay Bí mật ứng dụng nếu nó vô tình được cam kết, in hoặc chia sẻ.

Xác nhận nhanh chóng và loại bỏ các tin nhắn trùng lặp

Trả về 200 sau khi xác thực và xếp hàng sự kiện lâu dài. Đừng chờ đợi trong khi tải xuống phương tiện, gọi LLM hoặc cập nhật một số dịch vụ. Nhà cung cấp thử gửi lại khi xác nhận không thành công và mạng không rõ ràng nghĩa là việc trùng lặp là bình thường.

Sử dụng tin nhắn WhatsApp id làm khóa tạm thời cho các tin nhắn gửi đến và đối tượng trạng thái. Đặt một ràng buộc duy nhất xung quanh các ID đã xử lý. Quá trình chuyển đổi trạng thái có thể chuyển tiếp một cách hợp pháp từ trạng thái đã gửi sang đã phân phối để đọc, do đó, hãy loại bỏ trùng lặp từng chuyển đổi có liên quan mà không loại bỏ trạng thái sau này.

Khắc phục sự cố khi thiết lập webhook WhatsApp

Không thể xác thực URL gọi lại

Kiểm tra lộ trình GET thông qua URL công khai. Đảm bảo nó chấp nhận GET, so sánh mã thông báo xác minh chính xác và chỉ phản hồi với thử thách. Chuyển hướng, phần mềm trung gian xác thực, viết lại ngôn ngữ hoặc trình bao bọc JSON có thể phá vỡ quá trình xác minh. Xác nhận biến môi trường được tải bởi quy trình phát triển đang chạy.

Xác minh thành công nhưng không có tin nhắn nào đến

Chỉ riêng xác minh gọi lại sẽ không đăng ký Tài khoản WhatsApp Business vào các trường. Xác nhận đăng ký messages trong trang tổng quan và số điện thoại đó thuộc về ứng dụng và tài khoản dự kiến. Gửi tin nhắn từ người nhận được phép nếu ứng dụng vẫn đang ở chế độ phát triển.

Mỗi POST không xác thực được chữ ký

Các nguyên nhân thông thường là sử dụng mã thông báo truy cập thay vì Bí mật ứng dụng, băm JSON được phân tích cú pháp, bỏ qua tiền tố sha256= hoặc so sánh các cách mã hóa khác nhau. Ghi lại độ dài nội dung và liệu tiêu đề có tồn tại hay không nhưng không bao giờ in trọng tải bí mật hoặc đầy đủ của khách hàng.

Tin nhắn văn bản hoạt động nhưng việc xử lý phương tiện không thành công

Thông báo phương tiện chứa ID, không nhất thiết phải là byte tệp. Tìm nạp phương tiện thông qua API Đồ thị bằng mã thông báo truy cập hợp lệ, sau đó tải xuống. Giữ quy trình làm việc chậm hơn đó bên ngoài đường dẫn xác nhận webhook.

Điểm cuối cục bộ nhìn thấy các sự kiện trùng lặp

Kiểm tra trạng thái phản hồi và độ trễ, thêm tính ổn định lâu bền và phát lại một sự kiện đã ghi lại sau mỗi lần khắc phục. Hướng dẫn sử dụng lại webhook chỉ ra cách tránh gửi tin nhắn thực mới mỗi khi thay đổi mã.

Bảo vệ dữ liệu khách hàng trong quá trình kiểm tra cục bộ

  • Sử dụng số điện thoại thử nghiệm và cuộc trò chuyện tổng hợp nếu có thể.
  • Xóa lại số điện thoại, nội dung tin nhắn, URL phương tiện, danh bạ và tên hồ sơ từ nhật ký.
  • Chỉ lưu trữ Bí mật ứng dụng, mã thông báo truy cập và mã thông báo xác minh trong các tệp môi trường bị bỏ qua hoặc trình quản lý bí mật.
  • Hạn chế người có thể xem các ảnh chụp đường hầm và xóa chúng sau phiên gỡ lỗi.
  • Xác thực số nhận dạng đối tượng, trường và tài khoản trước khi thực hiện hành động kinh doanh.

Đường hầm giúp quá trình lặp lại diễn ra nhanh chóng nhưng cũng mang dữ liệu cá nhân được định hình sản xuất đến máy của nhà phát triển. Áp dụng các biện pháp kiểm soát trong danh sách kiểm tra bảo mật đường hầm trước khi thử nghiệm với người dùng thực.

Câu hỏi thường gặp

Làm cách nào để kiểm tra webhook API WhatsApp Cloud trên localhost?
Chạy cục bộ trình xử lý webhook của bạn, hiển thị nó bằng đường hầm HTTPS, đăng ký URL gọi lại công khai và xác minh mã thông báo trong Meta, đăng ký tin nhắn, sau đó gửi tin nhắn kiểm tra.
Điểm cuối xác minh webhook WhatsApp sẽ trả về điều gì?
Đối với yêu cầu GET hợp lệ trong đó hub.mode đăng ký và hub.verify_token khớp, hãy trả về giá trị hub.challenge dưới dạng văn bản thuần túy với HTTP 200.
Làm cách nào để xác minh các yêu cầu POST webhook WhatsApp?
Tính toán HMAC-SHA256 trên nội dung yêu cầu thô chính xác với Meta App Secret, thêm sha256= vào tiền tố tóm tắt hex và so sánh nó với X-Hub-Signature-256 một cách an toàn về mặt thời gian.
Tại sao webhook WhatsApp đã xác minh của tôi không nhận được sự kiện nào?
Xác minh gọi lại không tự động đăng ký mọi trường. Xác nhận rằng Tài khoản WhatsApp Business đã đăng ký tin nhắn và người gửi thử nghiệm cũng như số điện thoại của bạn có sẵn trong ứng dụng.