Xác thực
- OAuth 2.1 client credentials
- Định danh client gắn với mTLS
- Phạm vi quyền theo nguyên tắc tối thiểu
- Xoay vòng bí mật và kiểm toán
Mô hình tài nguyên, xác thực, idempotency, webhook có chữ ký, giới hạn tốc độ, cơ chế thử lại và danh mục lỗi.
Mô hình tài nguyên, xác thực, idempotency, webhook có chữ ký, giới hạn tốc độ, cơ chế thử lại và danh mục lỗi.
| Tài nguyên | Mục đích | Kiểm soát chính |
|---|---|---|
| /consignments | Tạo và truy vấn giao dịch giao nhận | Idempotency, chính sách định danh |
| /events | Đọc sự kiện vòng đời | Phân trang, thứ tự bất biến |
| /evidence | Lấy gói bằng chứng | Ủy quyền, toàn vẹn |
| /verification | Xác minh một gói | Mã băm, con dấu, dấu thời gian, trạng thái |
curl --request POST https://sandbox.example/v1/consignments \
--cert client.crt --key client.key \
--header "Authorization: Bearer ${TOKEN}" \
--header "Idempotency-Key: 04df..." \
--header "Content-Type: application/json" \
--data '{"recipient":{"type":"legal_entity","id":"DEMO-001"},"contentHash":"sha256:...","callbackUrl":"https://client.example/webhooks/delivery"}'
// Java 21 example: validate input, use idempotency and handle retryable failures.
HttpRequest request = HttpRequest.newBuilder(endpoint)
.header("Authorization", "Bearer " + token)
.header("Idempotency-Key", idempotencyKey)
.header("Content-Type", "application/json")
.POST(HttpRequest.BodyPublishers.ofString(payload))
.build();
HttpResponse<String> response = client.send(request, BodyHandlers.ofString());
if (response.statusCode() == 429 || response.statusCode() >= 500) {
retryWithExponentialBackoff(request); // bounded, jittered retry
}
if (response.statusCode() / 100 != 2) throw new DeliveryApiException(response.body());
// Node.js: validate, send idempotently, verify the signed webhook separately.
const response = await fetch(endpoint, {
method: 'POST',
headers: { authorization: `Bearer ${token}`, 'idempotency-key': key,
'content-type': 'application/json' },
body: JSON.stringify(payload),
signal: AbortSignal.timeout(10_000)
});
if ([429, 500, 502, 503, 504].includes(response.status)) await boundedRetry();
if (!response.ok) throw new Error(`Delivery API ${response.status}`);
# Python: typed validation, timeout and bounded retry.
with httpx.Client(cert=("client.crt", "client.key"), timeout=10.0) as client:
response = client.post(endpoint, json=payload, headers={
"Authorization": f"Bearer {token}",
"Idempotency-Key": idempotency_key,
})
if response.status_code in {429, 500, 502, 503, 504}:
raise RetryableDeliveryError(response.text)
response.raise_for_status()
result = response.json()
// .NET: use HttpClientFactory, mTLS handler, timeout and idempotency.
using var request = new HttpRequestMessage(HttpMethod.Post, endpoint);
request.Headers.Authorization = new("Bearer", token);
request.Headers.Add("Idempotency-Key", idempotencyKey);
request.Content = JsonContent.Create(payload);
using var response = await client.SendAsync(request, cancellationToken);
if ((int)response.StatusCode == 429 || (int)response.StatusCode >= 500)
throw new RetryableDeliveryException(await response.Content.ReadAsStringAsync());
response.EnsureSuccessStatusCode();