Tích hợp Webhook Tracking API vận chuyển realtime dễ dàng
Mở đầu: Từ Polling rời rạc đến Webhook thống nhất
Nếu bạn từng viết code tích hợp tracking vận đơn, hẳn bạn không lạ gì cảnh định kỳ gọi REST API của từng hãng vận chuyển để kiểm tra trạng thái – cứ 5, 10 hay 15 phút một lần. Phương thức này, gọi là polling (API pull), ngốn tài nguyên máy chủ, tăng độ trễ phản hồi cho người dùng cuối, và dễ bỏ lỡ các thay đổi trạng thái quan trọng giữa các lần gọi. Webhook tracking API vận chuyển ra đời để giải bài toán đó: thay vì bạn phải liên tục hỏi “đơn hàng thế nào rồi”, hãng vận chuyển sẽ chủ động gửi dữ liệu đến endpoint của bạn ngay khi có cập nhật – đẩy thông tin theo thời gian thực.
Tuy nhiên, thị trường Việt Nam có đến hàng chục đơn vị vận chuyển lớn nhỏ, mỗi hãng lại thiết kế webhook theo chuẩn riêng: payload khác nhau, cách đặt tên trạng thái khác nhau, cơ chế xác thực khác nhau. Việc tích hợp từng hãng một không chỉ tốn thời gian phát triển ban đầu mà còn trở thành cơn ác mộng bảo trì mỗi khi hãng thay đổi schema. Đây chính là lúc một nền tảng trung gian như Goship phát huy giá trị: thay vì N endpoint, bạn chỉ cần đăng ký một endpoint duy nhất trên Goship – mọi webhook từ GHN, GHTK, Viettel Post, J&T Express, Ninja Van, Shopee Express và hơn thế nữa đều được chuẩn hóa và đẩy về cùng một nơi, sẵn sàng cho bạn tiêu thụ.
Trong bài viết kỹ thuật này, Goship sẽ hướng dẫn bạn từng bước từ cấu hình, xử lý payload, xác thực chữ ký HMAC-SHA256, cho đến triển khai retry policy và pattern production-grade như Queue + Worker. Mục tiêu là giúp đội ngũ kỹ thuật của bạn tích hợp tracking realtime một cách nhanh chóng và sẵn sàng cho môi trường thực tế, bất kể bạn đang xây dựng hệ thống cho shop online, sàn TMĐT hay nền tảng logistics.
Tóm tắt giải pháp (answer summary): Webhook tracking API vận chuyển là cơ chế push notification cho phép nhận trạng thái vận đơn theo thời gian thực từ các đơn vị vận chuyển, thay vì phải gửi request liên tục (polling). Goship tập hợp webhook từ nhiều hãng về một endpoint duy nhất, tự động chuẩn hóa payload, tích hợp bảo mật HMAC-SHA256, retry với exponential backoff và idempotency key để đảm bảo độ tin cậy. Bài viết này sẽ đi sâu vào cách triển khai từng thành phần một cách an toàn và hiệu quả.
Tại sao Webhook tốt hơn Polling cho Tracking vận đơn?
Một bức ảnh đáng giá ngàn lời giải thích: sự khác biệt giữa polling (gọi API định kỳ) và webhook (push realtime) được trực quan hóa trong vài giây — giúp developer thấy ngay lý do nên chuyển từ polling sang webhook.
Để thấy rõ sự khác biệt, hãy hình dung hai mô hình sau. Với polling, ứng dụng của bạn định kỳ gửi HTTP request đến API của hãng vận chuyển – ví dụ mỗi 10 phút một lần cho hàng nghìn đơn hàng. Mỗi lần gọi, bạn phải xử lý response, so sánh với trạng thái cũ trong database để phát hiện thay đổi. Cách làm này không chỉ tiêu tốn băng thông và CPU mà còn khiến thông tin bị trễ: nếu đơn hàng chuyển trạng thái “giao thành công” ngay sau lần poll gần nhất, khách hàng của bạn phải đợi thêm gần 10 phút mới thấy cập nhật.
Webhook, ngược lại, hoạt động theo cơ chế push notification: ngay khi trạng thái đơn hàng thay đổi, hãng vận chuyển (hoặc nền tảng trung gian như Goship) sẽ gửi một HTTP POST đến URL mà bạn đã đăng ký. Độ trễ thường dưới 3 giây, giúp bạn cập nhật giao diện người dùng gần như realtime. Bạn không cần duy trì cron job, không lo bỏ lỡ sự kiện giữa các chu kỳ, và tài nguyên server được giải phóng đáng kể.
Tất nhiên, webhook cũng đặt ra những yêu cầu mới: bạn cần một public HTTPS endpoint để nhận dữ liệu, cần cơ chế xác thực để đảm bảo request đến từ nguồn tin cậy (signature verification), và phải xử lý được tình huống webhook bị gửi trùng lặp hoặc đến không đúng thứ tự. Đây chính là những vấn đề mà các phần sau của bài viết sẽ giải quyết một cách hệ thống.
Thách thức khi tích hợp Webhook từ nhiều hãng vận chuyển
Nếu bạn chỉ làm việc với một hãng duy nhất, việc tích hợp webhook không quá phức tạp. Nhưng thực tế, các shop online hay sàn TMĐT thường phối hợp nhiều đơn vị vận chuyển để tối ưu chi phí và thời gian giao. Mỗi hãng lại có một “tiếng nói” riêng, tạo ra hàng loạt thách thức cho developer.
- Schema payload không đồng nhất: GHTK sử dụng trường
label_id, GHN dùngorder_code, Viettel Post cótracking_code, J&T Express lại dùngmailno. Dù cùng là mã vận đơn, bạn phải viết parser riêng cho từng hãng. - Mã trạng thái khác biệt: Trạng thái “giao thành công” có thể là
delivered,completed,Picked,Successtùy hãng. Việc mapping thủ công dễ gây sai lệch logic nghiệp vụ, đặc biệt khi xử lý hoàn hàng hay đối soát COD. - Cơ chế xác thực riêng rẽ: Hãng dùng API key gắn trên header, hãng dùng HMAC-SHA1, hãng dùng bearer token, có nơi lại ký bằng SHA256 với secret riêng. Mỗi phương thức đòi hỏi code xử lý bảo mật khác nhau.
- Độ tin cậy không đồng đều: Không phải hãng nào cũng đảm bảo gửi webhook thành công 100%. Sự cố mạng, timeout, hay lỗi nội bộ của hãng có thể khiến bạn mất cập nhật, mà không có cơ chế retry rõ ràng.
- Chi phí bảo trì cao: Khi hãng vận chuyển nâng cấp API (thay đổi schema, thêm trường mới, đổi endpoint), bạn buộc phải cập nhật parser cho từng hãng. Với hơn 5 hãng, đây là gánh nặng thường trực cho đội kỹ thuật.
Giải pháp cho bài toán này là sử dụng một logistics API aggregator – một cổng trung gian kết nối với nhiều hãng vận chuyển, nhận toàn bộ webhook từ họ, chuẩn hóa payload về một schema duy nhất và phân phối đến endpoint của bạn. Đây chính xác là cách Goship vận hành.
Giải pháp: Webhook Tracking qua Goship – Một endpoint cho 10+ hãng
Trực quan hóa "cơn ác mộng schema": 5 hãng vận chuyển, 5 định dạng payload khác nhau — và giải pháp là một schema duy nhất sau khi qua Goship. Hình ảnh này giúp đội ngũ kỹ thuật thấy ngay giá trị của tầng normalization.
Goship hoạt động như một hub trung tâm, đã tích hợp sẵn với hơn 10 đơn vị vận chuyển hàng đầu tại Việt Nam: GHN, GHTK, Viettel Post, J&T Express, Ninja Van, Shopee Express (SPX), và nhiều hãng khác. Thay vì phải đăng ký webhook riêng lẻ trên từng nền tảng, bạn chỉ cần cấu hình một URL duy nhất trong dashboard Goship. Từ đó, mọi cập nhật trạng thái vận đơn từ tất cả các hãng đều được đẩy về endpoint của bạn.
Điều khiến giải pháp này thực sự khác biệt nằm ở ba lớp giá trị mà Goship thêm vào:
Payload được chuẩn hóa hoàn toàn: Mỗi sự kiện webhook gửi đến bạn đều có cấu trúc thống nhất, bao gồm các trường:
tracking_number,status,timestamp,location,carrier,event_id. Việc mapping từ hàng chục schema riêng lẻ được Goship xử lý ở tầng backend. Bạn chỉ cần viết một parser duy nhất.Bảo mật và độ tin cậy cấp production: Goship trang bị đầy đủ các cơ chế enterprise-ready: xác thực chữ ký HMAC-SHA256 cho mọi webhook, retry policy với exponential backoff và jitter, idempotency key chống trùng lặp, cùng fallback polling tự động khi webhook của hãng gặp sự cố.
Sandbox và tài liệu rõ ràng: Goship cung cấp môi trường sandbox để bạn kiểm thử toàn bộ flow webhook trước khi go-live. Tài liệu API chi tiết cùng code mẫu bằng Node.js và Python giúp rút ngắn thời gian tích hợp.
Với cách tiếp cận này, việc tích hợp tracking realtime cho 10 hãng vận chuyển giờ đây chỉ phức tạp ngang với việc tích hợp một hãng – nhưng bạn nhận được sức mạnh của toàn bộ hệ thống.
Hướng dẫn cấu hình Webhook trên Goship
Quy trình cấu hình webhook trên Goship được thiết kế để bạn có thể hoàn tất trong vài phút. Dưới đây là các bước cụ thể.
Bước 1: Chuẩn bị endpoint nhận webhook Trước tiên, bạn cần một public HTTPS endpoint có khả năng nhận HTTP POST. Có thể là một route trên server hiện tại, hoặc một function serverless (AWS Lambda, Cloudflare Worker, Vercel Function). Lưu ý endpoint phải hỗ trợ TLS (HTTPS) vì Goship chỉ gửi webhook qua kênh bảo mật.
Bước 2: Đăng nhập và vào mục quản lý Webhook Sau khi đăng nhập tài khoản Goship (hoặc đăng ký dùng thử miễn phí), bạn truy cập phần Cài đặt API / Quản lý Webhook trong dashboard. Tại đây, bạn có thể thêm mới một webhook subscription.
Bước 3: Đăng ký URL và chọn sự kiện
Nhập URL endpoint của bạn và chọn các loại sự kiện muốn nhận. Goship hỗ trợ các sự kiện tracking chính như: order_created (đơn hàng đã tạo), in_transit (đang vận chuyển), delivered (giao thành công), returned (trả hàng), cancelled (hủy). Bạn có thể chọn tất cả hoặc chỉ những trạng thái cần thiết.
Bước 4: Nhận và lưu trữ Shared Secret
Sau khi đăng ký, Goship sẽ sinh cho bạn một shared secret – một chuỗi ngẫu nhiên dùng để ký HMAC. Hãy lưu secret này vào biến môi trường (environment variable) hoặc secret manager, tuyệt đối không hardcode hay commit lên repository.
Bước 5: Kiểm tra kết nối với Test Webhook
Goship cung cấp chức năng gửi webhook test đến endpoint của bạn. Hệ thống sẽ gửi một payload mẫu, kèm chữ ký HMAC trong header X-Goship-Signature. Nhiệm vụ của bạn là xác minh chữ ký và trả về HTTP 200 OK. Nếu endpoint phản hồi đúng, bạn có thể kích hoạt webhook chính thức.
Bước 6: Kích hoạt và giám sát Sau khi kích hoạt, mọi cập nhật tracking sẽ bắt đầu được đẩy về endpoint của bạn. Trong dashboard Goship, bạn có thể xem nhật ký gửi webhook (delivery log), trạng thái từng lần gửi (thành công, thất bại, đang retry) để giám sát và xử lý kịp thời.
Mẹo thực tế: Thiết lập timeout cho endpoint của bạn dưới 30 giây. Nếu logic xử lý mất nhiều thời gian (ví dụ cập nhật database, gọi API thứ ba), hãy phản hồi ngay 202 Accepted sau khi xác thực chữ ký, rồi xử lý payload một cách bất đồng bộ (async). Phần sau về Queue + Worker sẽ mô tả chi tiết pattern này.
Xử lý Webhook Payload (Code mẫu)
Khi nhận được webhook từ Goship, request sẽ có dạng HTTP POST với Content-Type: application/json. Body là một JSON object đã được chuẩn hóa, ví dụ:
{
"event_id": "uuid-xxxx-xxxx",
"tracking_number": "GHTK123456789",
"carrier": "ghtk",
"status": "delivered",
"timestamp": "2025-03-30T14:30:00+07:00",
"location": "Kho Hà Nội",
"notes": "Hàng đã giao cho người nhận"
}
Quy trình xử lý chuẩn trong handler của bạn nên tuân theo các bước sau:
- Đọc raw request body (dạng buffer/string, không parse JSON ngay).
- Trích xuất chữ ký từ header
X-Goship-Signature. - Tính HMAC-SHA256 của raw body với shared secret, so sánh với chữ ký nhận được bằng constant-time comparison.
- Nếu không khớp → trả 401 Unauthorized, dừng xử lý.
- Nếu khớp → parse JSON, trích xuất
event_idvà các trường tracking. - Lưu vào database với UPSERT logic (sử dụng
event_idlàm khóa duy nhất để chống trùng lặp). - Trả về HTTP 200 OK.
Dưới đây là code mẫu minh họa bằng Node.js (Express) và Python (Flask).
Node.js (Express)
const express = require('express');
const crypto = require('crypto');
const app = express();
app.post('/webhook/goship', express.raw({type: 'application/json'}), (req, res) => {
const signature = req.headers['x-goship-signature'];
const secret = process.env.GOSHIP_WEBHOOK_SECRET;
// Bước 1: Tính HMAC-SHA256 trên raw body
const hmac = crypto.createHmac('sha256', secret);
hmac.update(req.body);
const computedSignature = hmac.digest('hex');
// Bước 2: Constant-time compare
if (!crypto.timingSafeEqual(Buffer.from(signature), Buffer.from(computedSignature))) {
return res.status(401).send('Invalid signature');
}
// Bước 3: Parse JSON và xử lý
const payload = JSON.parse(req.body.toString());
const { event_id, tracking_number, carrier, status, timestamp } = payload;
// Bước 4: Insert vào database (pseudo-code, dùng UPSERT với event_id unique)
// await db.upsertTrackingEvent(event_id, tracking_number, carrier, status, timestamp);
// Bước 5: Phản hồi thành công
res.status(200).send('OK');
});
app.listen(3000);
Python (Flask)
import hmac
import hashlib
import os
from flask import Flask, request, jsonify
app = Flask(__name__)
@app.route('/webhook/goship', methods=['POST'])
def goship_webhook():
signature = request.headers.get('X-Goship-Signature')
secret = os.environ.get('GOSHIP_WEBHOOK_SECRET').encode()
## Bước 1: Tính HMAC-SHA256 trên raw body
raw_body = request.get_data()
computed_signature = hmac.new(secret, raw_body, hashlib.sha256).hexdigest()
## Bước 2: Constant-time compare
if not hmac.compare_digest(signature, computed_signature):
return 'Invalid signature', 401
## Bước 3: Parse JSON và xử lý
payload = request.get_json()
event_id = payload.get('event_id')
tracking_number = payload.get('tracking_number')
carrier = payload.get('carrier')
status = payload.get('status')
## Bước 4: Insert vào database với UPSERT logic
## db.upsert_tracking_event(event_id, tracking_number, carrier, status)
## Bước 5: Phản hồi thành công
return 'OK', 200
Lưu ý: Vì Goship đã trả về payload đã được chuẩn hóa, bạn không cần viết thêm parser nào cho từng hãng – trường carrier cho biết hãng vận chuyển, còn status và các trường khác luôn tuân theo cùng một danh sách giá trị do Goship định nghĩa.
Bảo mật Webhook: Xác thực chữ ký HMAC-SHA256
Trong môi trường production, việc đảm bảo webhook thực sự đến từ Goship – chứ không phải từ một bên thứ ba giả mạo – là yêu cầu bắt buộc. Goship sử dụng cơ chế HMAC-SHA256, một chuẩn xác thực phổ biến được áp dụng bởi GitHub, Stripe và nhiều nền tảng lớn khác.
Cơ chế hoạt động như sau:
- Khi bạn đăng ký webhook, Goship sinh một chuỗi bí mật (shared secret). Chỉ có Goship và hệ thống của bạn biết secret này.
- Mỗi lần gửi webhook, Goship tính toán
signature = HMAC-SHA256(secret, raw_request_body). Kết quả được gửi trong HTTP headerX-Goship-Signature. - Phía bạn, khi nhận request, cũng tính HMAC-SHA256 trên raw body với secret đã lưu, rồi so sánh bằng constant-time comparison (ví dụ
crypto.timingSafeEqualtrong Node.js hoặchmac.compare_digesttrong Python). Tuyệt đối không dùng toán tử==thông thường vì dễ bị timing attack. - Nếu chữ ký khớp, bạn có thể tin tưởng payload là nguyên vẹn và đến từ Goship. Nếu không, trả 401 và từ chối xử lý.
Để tăng cường bảo mật chống replay attack (kẻ tấn công chặn request hợp lệ và gửi lại nhiều lần), bạn có thể kiểm tra thêm trường timestamp trong payload. Nếu thời gian trong payload lệch quá xa so với thời gian hiện tại của server (ví dụ quá 5 phút), hãy từ chối xử lý. Bước này ngăn chặn request cũ bị phát lại sau khi secret đã được xoay vòng.
Retry Policy & Idempotent Processing
Goship cam kết mô hình gửi webhook at-least-once: mỗi sự kiện sẽ được gửi ít nhất một lần, và có thể gửi lại nếu endpoint của bạn không phản hồi thành công. Để đảm bảo dữ liệu không bị thất lạc ngay cả khi hệ thống của bạn gặp sự cố tạm thời, Goship áp dụng retry policy với các tham số rõ ràng.
Retry policy chi tiết:
- Khi webhook đầu tiên không nhận được HTTP 2xx từ endpoint của bạn, Goship sẽ tự động retry.
- Khoảng cách giữa các lần retry tuân theo exponential backoff: 1 giây, 2 giây, 4 giây, 8 giây, 16 giây… có thể kéo dài đến vài phút.
- Jitter (độ nhiễu ngẫu nhiên) được thêm vào để tránh hiện tượng “thundering herd” – nhiều retry dồn về cùng một thời điểm gây quá tải.
- Tổng số lần retry tối đa khoảng 25 lần, trong cửa sổ 48 giờ. Sau khi hết số lần retry mà vẫn thất bại, sự kiện được chuyển vào Dead Letter Queue (DLQ). DLQ là hàng đợi chứa các sự kiện không gửi được, cho phép bạn kiểm tra và xử lý thủ công sau mà không lo mất dữ liệu.
Idempotent Processing – chống xử lý trùng lặp: Do cơ chế at-least-once, cùng một sự kiện có thể được gửi đến endpoint của bạn nhiều lần (ví dụ: lần đầu bạn xử lý thành công nhưng phản hồi 200 bị chậm hoặc mất gói, Goship coi là thất bại và retry). Để tránh xử lý trùng lặp gây sai lệch dữ liệu (ví dụ gửi email thông báo hai lần, cập nhật trạng thái sai), bạn cần triển khai idempotency.
Mỗi sự kiện webhook của Goship đều chứa trường event_id – một UUID duy nhất đại diện cho sự kiện đó. Khi nhận webhook, bạn thực hiện INSERT event_id vào bảng webhook_events với UNIQUE constraint:
- Nếu INSERT thành công: đây là lần đầu sự kiện được xử lý → thực thi business logic.
- Nếu INSERT thất bại do duplicate key: sự kiện đã được xử lý trước đó → bỏ qua, nhưng vẫn trả 200 OK để Goship biết đã nhận thành công.
Để an toàn, bạn nên lưu event_id với TTL (time-to-live) ít nhất 72 giờ, lâu hơn cửa sổ retry tối đa 48 giờ, nhằm đảm bảo kể cả retry muộn nhất cũng được nhận diện là trùng lặp.
Pattern Production-Grade: Queue + Worker
Kiến trúc Queue + Worker giúp webhook handler phản hồi ngay 200 OK trong mili-giây, trong khi worker xử lý business logic bất đồng bộ — pattern này là "tấm vé thông hành" để hệ thống tracking của bạn sẵn sàng cho production với hàng nghìn sự kiện mỗi ngày.
Trong môi trường thực tế, webhook handler cần phản hồi HTTP 200 càng nhanh càng tốt – lý tưởng dưới 1-2 giây. Nếu bạn thực hiện các tác vụ nặng ngay trong handler (cập nhật nhiều bảng database, gọi API bên thứ ba, gửi email), thời gian phản hồi có thể vượt quá timeout của Goship (30 giây) và gây ra retry không cần thiết. Pattern Queue + Worker ra đời để giải quyết vấn đề này.
Mô hình hoạt động như sau:
- HTTP Handler nhận webhook từ Goship, xác thực chữ ký HMAC-SHA256.
- Sau khi xác thực thành công, handler không xử lý business logic ngay, mà đưa toàn bộ payload (đã parse) vào một message queue – có thể là Redis (với Bull hoặc RSMQ), RabbitMQ, hoặc AWS SQS.
- Ngay sau khi đẩy vào queue thành công, handler trả về HTTP
200 OK(hoặc202 Accepted). - Worker (một process hoặc service riêng) lắng nghe queue, lấy từng job ra và thực hiện các tác vụ như cập nhật database, gọi API, gửi thông báo…
- Nếu worker thất bại (ví dụ database timeout), queue sẽ tự động retry job theo cấu hình (số lần retry, backoff) hoặc chuyển vào DLQ nội bộ của bạn.
Lợi ích của pattern này:
- Phản hồi nhanh: Handler chỉ mất vài millisecond để đẩy vào queue, đảm bảo luôn phản hồi kịp thời cho Goship.
- Xử lý bất đồng bộ: Worker có thể xử lý hàng trăm sự kiện mỗi giây mà không làm chậm webhook response.
- Cô lập lỗi: Nếu worker gặp lỗi, nó không ảnh hưởng đến việc nhận các webhook tiếp theo. Lỗi được giới hạn trong từng job, dễ dàng retry hoặc điều tra.
- Dễ dàng scale: Bạn có thể tăng số lượng worker để đáp ứng lưu lượng cao mà không cần thay đổi code handler.
Ví dụ triển khai nhanh với Node.js và Bull (dựa trên Redis):
// Handler (Express route)
app.post('/webhook/goship', async (req, res) => {
// verify signature (giống ví dụ trước)
// ...
const payload = JSON.parse(req.body);
await trackingQueue.add('process-tracking', payload); // đẩy vào queue
res.status(200).send('OK');
});
// Worker (file riêng)
const Queue = require('bull');
const trackingQueue = new Queue('tracking', 'redis://127.0.0.1:6379');
trackingQueue.process('process-tracking', async (job) => {
const { event_id, tracking_number, carrier, status, timestamp } = job.data;
// Thực hiện UPSERT database, gọi API ngoài...
// Nếu có lỗi, Bull sẽ tự retry theo cấu hình
});
Queue + Worker là pattern đã được kiểm chứng trong hàng loạt hệ thống lớn, và Goship khuyến nghị bạn áp dụng ngay từ đầu để đảm bảo hệ thống tracking hoạt động ổn định, sẵn sàng mở rộng.
Câu hỏi thường gặp (FAQ)
Webhook tracking API khác gì với việc gọi REST API tracking thông thường?
REST API tracking là phương thức pull – bạn phải định kỳ gửi yêu cầu kiểm tra trạng thái (polling). Webhook là push – hãng vận chuyển chủ động gửi dữ liệu đến endpoint của bạn khi có thay đổi. Webhook có độ trễ thấp (realtime dưới 3 giây so với 5-15 phút của polling), tiết kiệm tài nguyên server và giảm rủi ro bỏ lỡ sự kiện giữa các lần poll. Đổi lại, webhook yêu cầu bạn phải có public endpoint HTTPS và xử lý các vấn đề như duplicate delivery hay signature verification.
Tại sao tôi cần normalize payload khi tích hợp nhiều hãng vận chuyển?
Mỗi hãng vận chuyển ở Việt Nam dùng định dạng payload khác nhau: GHTK dùng label_id, GHN dùng order_code, trạng thái cũng có mã khác biệt. Nếu không normalize, bạn phải viết riêng parser cho mỗi hãng, khó bảo trì và dễ lỗi khi schema thay đổi. Goship tự động normalize toàn bộ payload về một cấu trúc thống nhất (tracking_number, status, timestamp, location, carrier), giúp bạn chỉ cần xử lý một định dạng duy nhất.
HMAC-SHA256 signature verification hoạt động như thế nào?
Khi đăng ký webhook, bạn nhận một shared secret. Mỗi lần gửi webhook, Goship tính HMAC-SHA256(secret, raw_body) và gửi kết quả trong header X-Goship-Signature. Phía bạn nhận request, cũng tính HMAC tương tự trên raw body và so sánh bằng constant-time comparison. Nếu khớp thì xử lý; nếu không khớp, trả 401. Phương pháp này ngăn chặn giả mạo và đảm bảo toàn vẹn dữ liệu.
Điều gì xảy ra khi endpoint của tôi bị sập?
Goship áp dụng retry policy với exponential backoff + jitter: nếu endpoint không trả 200 sau lần gửi đầu, sẽ thử lại với khoảng cách tăng dần (vài giây đến vài phút) trong vòng tối đa 48 giờ và 25 lần. Khi tất cả retry đều thất bại, sự kiện được đưa vào Dead Letter Queue để bạn có thể kiểm tra và xử lý thủ công sau mà không mất dữ liệu.
Làm thế nào để tránh xử lý trùng lặp?
Webhook được gửi ít nhất một lần (at-least-once), do đó có thể đến nhiều lần. Sử dụng idempotency key: mỗi sự kiện chứa một event_id duy nhất. Khi nhận, thực hiện INSERT event_id vào database với unique constraint. Nếu INSERT thành công, xử lý bình thường; nếu trùng, bỏ qua. Nên lưu event_id với TTL ít nhất 72 giờ để chống duplicate hiệu quả.
Goship webhook với webhook trực tiếp từ GHN/GHTK khác nhau thế nào?
Khác biệt chính: (1) Bạn chỉ cần 1 endpoint duy nhất của Goship thay vì N endpoint riêng cho từng hãng. (2) Payload được chuẩn hóa, không cần viết parser phức tạp. (3) Cơ chế bảo mật HMAC-SHA256 thống nhất, khác với token riêng từng hãng. (4) Retry policy nhất quán với exponential backoff, đảm bảo tin cậy. (5) Goship cung cấp event_id duy nhất cho idempotency, một số hãng không có. (6) Goship có fallback polling để đối phó khi webhook hãng không ổn định.
Có nên dùng song song cả webhook và polling không?
Đây là best practice trong production. Webhook làm nguồn chính (realtime, ít tốn tài nguyên). Polling định kỳ (5-15 phút) đóng vai trò đối chiếu, truy vấn trạng thái tất cả đơn hàng đang hoạt động và cập nhật nếu có sai lệch. Cách này đảm bảo eventual consistency và bù đắp khi webhook bỏ lỡ sự kiện do sự cố mạng hay lỗi consumer.
Tôi có cần public HTTPS endpoint không? Goship có hỗ trợ gửi webhook đến internal network không?
Có, bạn bắt buộc cần một public HTTPS endpoint. Goship gửi webhook từ hệ thống của mình đến URL bạn cung cấp, do đó endpoint phải có khả năng truy cập từ Internet. Nếu hệ thống của bạn nằm trong mạng nội bộ, hãy sử dụng một reverse proxy (như Nginx, Cloudflare Tunnel, ngrok trong môi trường dev) để public endpoint đó một cách an toàn.
Goship hỗ trợ những sự kiện tracking nào?
Hiện tại, Goship hỗ trợ các sự kiện tracking chính: order_created (đơn hàng đã được tạo trên hệ thống hãng), picked_up (hãng đã lấy hàng), in_transit (đang trên đường giao), delivery_attempt (đang thử giao), delivered (giao thành công), returned (hoàn trả), cancelled (hủy đơn). Bạn có thể đăng ký tất cả hoặc chọn lọc trong dashboard.
Kết luận và bước tiếp theo
Tích hợp tracking vận đơn realtime qua webhook không còn là bài toán đau đầu khi bạn có một nền tảng trung gian mạnh mẽ như Goship. Thay vì phải viết và bảo trì hàng loạt parser cho từng hãng, thay vì loay hoay với retry logic và bảo mật không đồng nhất, giờ đây bạn chỉ cần một endpoint duy nhất – và Goship lo phần còn lại.
Với payload đã được chuẩn hóa, xác thực HMAC-SHA256 đạt chuẩn industry, retry policy rõ ràng cùng idempotency key, giải pháp webhook của Goship sẵn sàng cho môi trường production ngay cả với những hệ thống đòi hỏi độ tin cậy cao. Pattern Queue + Worker được khuyến nghị sẽ giúp bạn xử lý hàng nghìn webhook mỗi ngày một cách mượt mà, không lo nghẽn cổ chai hay mất dữ liệu.
Nếu bạn đang vận hành một sàn TMĐT, một hệ thống quản lý đơn hàng (OMS), hay đơn giản là muốn nâng cấp trải nghiệm theo dõi đơn hàng cho khách hàng của mình, đây là thời điểm để bắt đầu. Đăng ký tài khoản Goship, truy cập Sandbox và thử cấu hình webhook ngay hôm nay. Đội ngũ kỹ thuật của Goship luôn sẵn sàng hỗ trợ bạn trong quá trình tích hợp. Dùng thử miễn phí, không cam kết – và bạn sẽ thấy sự khác biệt ngay từ lần gửi webhook đầu tiên.