Khung thời gian Cấp quyền
Access Time Windows cho phép một Partner Member mang theo quyền ra vào tạm thời hoặc định kỳ do một hệ thống bên ngoài cung cấp. Trang này là hướng dẫn chính thức dành cho bên tạo dữ liệu access_time_windows và access_time_windows_revision.
Access Time Windows là các quyền bổ sung chỉ có tác dụng cho phép. Một khung thời gian đang hiệu lực có thể cho phép ra vào, nhưng một khung thời gian không hiệu lực, đã hết hạn, đã cũ hoặc chưa được ánh xạ sẽ không từ chối quyền ra vào mà một quy tắc thông thường hoặc quyền cấp vĩnh viễn đã cho phép. Việc vô hiệu hóa người dùng, chặn cửa rõ ràng, chế độ bảo trì, geofencing, giới hạn tốc độ và tình trạng khả dụng của bộ điều khiển vẫn được áp dụng.
Phần triển khai cho từng hệ thống upstream cụ thể là các bộ điều hợp (adapter) riêng biệt. Chúng phải chuyển đổi dữ liệu nguồn sang hợp đồng không phụ thuộc nhà cung cấp này mà không thay đổi ý nghĩa của các trường.
Các trường ảnh chụp nhanh của hội viên
-
access_time_windows
arraytùy chọnẢnh chụp nhanh Access Time Window đầy đủ cho hội viên này và nguồn đối tác này. Một ảnh chụp nhanh có thể kết hợp các khung thời gian
absolutevàweekly. Bỏ qua trường này để giữ nguyên ảnh chụp nhanh đã lưu; gửi[]để thu hồi mọi khung thời gian thuộc nguồn này. -
access_time_windows_revision
integerbắt buộc khi có access_time_windowsMột số nguyên không âm, tăng đơn điệu, an toàn với JSON cho chuỗi phiên bản của hội viên/nguồn này. Trường này bắt buộc bất cứ khi nào có
access_time_windowsvà không được vượt quá9007199254740991.
Mỗi ảnh chụp nhanh chấp nhận tối đa 50 khung thời gian. external_id, scope_key và label chấp nhận tối đa 120 ký tự. Khung thời gian tuyệt đối có thể kéo dài tối đa 90 ngày. Mỗi ngày trong tuần chấp nhận tối đa tám khối không chồng lấn. Dữ liệu không hợp lệ sẽ bị từ chối thay vì bị cắt bớt hoặc suy đoán.
Cấu trúc khung thời gian
Một khung thời gian tuyệt đối xác định một khoảng thời gian chính xác:
{
"external_id": "access-4b1782",
"kind": "absolute",
"from": 1792053000,
"to": 1792058400,
"timezone": "Australia/Perth",
"scope_key": "after_hours_entry",
"label": "Temporary site access"
}
Các trường bắt buộc là external_id, kind, from và to. timezone, scope_key và label là không bắt buộc.
Một khung thời gian hằng tuần xác định các khoảng thời gian định kỳ theo giờ địa phương, có thể được giới hạn bởi các thời điểm UTC:
{
"external_id": "weekly-early-access",
"kind": "weekly",
"timezone": "America/New_York",
"access_hours": {
"sun": [],
"mon": [["06:00", "08:30"]],
"tue": [["06:00", "08:30"]],
"wed": [["06:00", "08:30"]],
"thu": [["06:00", "08:30"]],
"fri": [["06:00", "08:30"]],
"sat": []
},
"active_from": 1790812800,
"active_until": 1796083200,
"scope_key": "main_entry",
"label": "Weekday early access"
}
Các trường bắt buộc là external_id, kind và access_hours. timezone, active_from, active_until, scope_key và label là không bắt buộc.
Yêu cầu kết hợp đầy đủ
Yêu cầu này thay thế ảnh chụp nhanh trước đó thuộc nguồn của hội viên bằng một khung thời gian tuyệt đối và một khung thời gian hằng tuần:
curl -X POST https://partner-api.performancehub.co/partner/v1/members \
-u sk_live_YOUR_PARTNER_SECRET_KEY: \
-H "Content-Type: application/json" \
-d '{
"members": [
{
"member_id": "member_11111",
"facility_id": "550e8400-e29b-41d4-a716-446655440000",
"first_name": "John",
"last_name": "Smith",
"access_time_windows_revision": 1842,
"access_time_windows": [
{
"external_id": "access-4b1782",
"kind": "absolute",
"from": 1792053000,
"to": 1792058400,
"timezone": "Australia/Perth",
"scope_key": "after_hours_entry",
"label": "Temporary site access"
},
{
"external_id": "weekly-early-access",
"kind": "weekly",
"timezone": "America/New_York",
"access_hours": {
"sun": [],
"mon": [["06:00", "08:30"]],
"tue": [["06:00", "08:30"]],
"wed": [["06:00", "08:30"]],
"thu": [["06:00", "08:30"]],
"fri": [["06:00", "08:30"]],
"sat": []
},
"active_from": 1790812800,
"active_until": 1796083200,
"scope_key": "main_entry",
"label": "Weekday early access"
}
]
}
]
}'
Sử dụng facility_id hoặc linking_identifier theo phương thức liên kết đã cấu hình. Không gửi cả hai.
Quy tắc về thời gian và ranh giới
from, to, active_from và active_until là số nguyên JSON tính bằng giây Unix, xác định các thời điểm UTC:
- Gửi số nguyên JSON không đặt trong dấu ngoặc kép. Chuỗi số, số thực, chuỗi RFC 3339 và mili giây Unix sẽ bị từ chối.
- Mọi khoảng thời gian đều là nửa mở:
[from, to). Quyền ra vào có thể bắt đầu đúng tạifrom; quyền không còn hiệu lực đúng tạito. fromphải nhỏ hơnto. Khi có cả hai giới hạn hằng tuần,active_fromphải nhỏ hơnactive_until.- Không suy ra epoch từ ngày/giờ địa phương không có múi giờ. Trước tiên hãy quy đổi thời gian nguồn thành một thời điểm UTC, sau đó chia số mili giây Unix cho 1000 và xác minh kết quả là số nguyên.
Chuyển đổi epoch
2026-10-15T08:30:00Z được chuyển đổi thành 1792053000:
UTC instant Unix milliseconds Unix seconds sent
2026-10-15T08:30:00Z 1792053000000 1792053000
Cách chuyển đổi không phụ thuộc ngôn ngữ lập trình:
instant = parse_source_timestamp_with_explicit_zone(source_timestamp)
milliseconds = instant.to_unix_milliseconds()
assert milliseconds modulo 1000 equals 0
seconds = milliseconds / 1000
assert seconds is a JSON-safe nonnegative integer
Nếu nguồn có độ chính xác dưới một giây, hãy xác định chính sách làm tròn thời điểm bắt đầu/kết thúc một cách có chủ đích trước khi kiểm thử tích hợp. Không bao giờ truyền mili giây và trông chờ API tự suy ra đơn vị.
Múi giờ và giờ mùa hè
timezone phải là một múi giờ IANA hợp lệ, chẳng hạn UTC, Australia/Perth hoặc America/New_York. Mặc định là UTC khi bị bỏ qua.
- Khung thời gian tuyệt đối:
fromvàtođã xác định chính xác các thời điểm UTC.timezonechỉ là siêu dữ liệu để hiển thị và kiểm toán; việc thay đổi trường này không bao giờ làm dịch chuyển hai thời điểm đó. - Khung thời gian hằng tuần:
timezonexác định giờ địa phương và quy tắc giờ mùa hè dùng để đánh giáaccess_hours. Không chuyển đổi trước các khối hằng tuần sang UTC. - Khi chuyển sang giờ mùa hè (đồng hồ tiến lên), một giờ địa phương bị múi giờ bỏ qua sẽ không bao giờ xảy ra.
- Khi kết thúc giờ mùa hè (đồng hồ lùi lại), cả hai thời điểm thực mang cùng giờ địa phương lặp lại đều khớp với khối hằng tuần.
active_fromvàactive_untilvẫn là thời điểm UTC ngay cả khi khung thời gian hằng tuần sử dụng múi giờ khác UTC.
access_hours sử dụng chữ thường từ sun đến sat. Mỗi giá trị là một mảng các cặp [start, end] theo định dạng HH:mm 24 giờ có số 0 đứng đầu. Các khối phải không rỗng, được sắp xếp theo thứ tự và không chồng lấn. end không bao gồm thời điểm kết thúc. Một khối không được vượt qua nửa đêm; hãy tách một khoảng thời gian qua đêm từ nguồn thành một khối muộn vào ngày đầu tiên và một khối sớm vào ngày hôm sau.
ID ổn định và ánh xạ phạm vi
external_id phải ổn định trong suốt vòng đời của một khung thời gian logic và là duy nhất trong ảnh chụp nhanh của hội viên. Giữ nguyên giá trị này khi thời gian hoặc nhãn thay đổi để người vận hành và bản ghi kiểm toán có thể đối chiếu các phiên bản. Không dùng lại giá trị này cho một khung thời gian không liên quan.
scope_key là mục tiêu ra vào logic ổn định của bạn. Mặc định là default. Quản trị viên cơ sở ánh xạ từng khóa được phép tới các mục tiêu trong Performance Hub: toàn bộ cơ sở, cửa hoặc Phạm vi truy cập:
Partner scope_key Performance Hub mapping
default Facility's configured default target
main_entry Access Scope "Main entrances"
after_hours_entry Doors approved for after-hours entry
Đối tác không gửi ID cơ sở, ID cửa hoặc ID Phạm vi truy cập của Performance Hub bên trong một khung thời gian. Một scope_key không xác định, bị vô hiệu hóa hoặc chưa được ánh xạ sẽ khiến khung thời gian đó không cấp quyền truy cập nào; nó không mở rộng quyền ra vào. Hãy thống nhất và kiểm thử các ánh xạ trước khi ra mắt.
Ảnh chụp nhanh đầy đủ và phiên bản
Hãy coi hai trường này là một phân vùng có phiên bản riêng trong thao tác upsert Member:
| Đầu vào | Kết quả |
|---|---|
Bỏ qua access_time_windows | Ảnh chụp nhanh hiện có được giữ nguyên; không cần phiên bản |
| Có mặt với phiên bản mới hơn | Toàn bộ ảnh chụp nhanh đã lưu của hội viên/nguồn này được thay thế |
| Cùng phiên bản và cùng payload đã chuẩn hóa | Phát lại idempotent; ảnh chụp nhanh không thay đổi |
| Cùng phiên bản nhưng payload đã chuẩn hóa khác | Xung đột; cấp phiên bản mới sau khi đối soát |
| Phiên bản cũ hơn | Ảnh chụp nhanh cũ bị bỏ qua; không thể ghi đè trạng thái mới hơn |
access_time_windows: [] với phiên bản mới hơn | Thu hồi rõ ràng mọi khung thời gian thuộc nguồn |
Ảnh chụp nhanh là bản đầy đủ, không phải bản vá. Nếu phiên bản 1842 có khung thời gian A và B, thì phiên bản 1843 chỉ chứa B sẽ xóa A.
Duy trì một chuỗi phiên bản được điều phối thống nhất cho mỗi đối tác/hội viên giữa các worker webhook, thăm dò định kỳ, phát lại và đối soát toàn bộ. Nên dùng một sequence bền vững trong cơ sở dữ liệu. Chỉ có thể dùng giá trị mili giây Unix làm phiên bản khi mọi bên ghi đều được điều phối và đảm bảo thứ tự nghiêm ngặt cũng như tính duy nhất; đó là giá trị phiên bản, không phải trường epoch.
Lưu lại chính xác yêu cầu và phiên bản cho đến khi biết phản hồi của API. Thử lại cùng ảnh chụp nhanh đã chuẩn hóa với cùng phiên bản sau khi hết thời gian chờ hoặc gặp lỗi tạm thời. Không cấp phiên bản mới chỉ vì việc truyền tải không chắc chắn.
Hủy bỏ, hết hạn và lỗi upstream
- Hủy một khung thời gian: truy xuất thành công trạng thái nguồn có thẩm quyền, xóa khung thời gian đó và gửi ảnh chụp nhanh đầy đủ còn lại với phiên bản mới hơn.
- Hủy tất cả khung thời gian: gửi
access_time_windows: []với phiên bản mới hơn. - Để khung thời gian tuyệt đối hết hạn: khung thời gian ngừng cho phép tại
to; hãy gửi một lần đối soát sau đó không có mục đã hết hạn để giữ ảnh chụp nhanh gọn gàng. - Kết thúc khung thời gian hằng tuần: xóa khung thời gian đó trong một ảnh chụp nhanh mới hơn, hoặc dùng
active_untilkhi nguồn có thời điểm kết thúc đã biết. - Truy xuất nguồn thất bại hoặc không đầy đủ: không gửi
[]và không phát hành ảnh chụp nhanh không đầy đủ. Hãy cảnh báo và thử truy xuất lại. Biến lỗi upstream thành ảnh chụp nhanh rỗng là một lần thu hồi quyền ra vào ngoài ý muốn. - Yêu cầu Partner API không vượt qua kiểm tra dữ liệu: sửa dữ liệu và chỉ gửi phiên bản mới hơn nếu ảnh chụp nhanh đã chuẩn hóa thay đổi. Thử lại các lỗi tạm thời với phiên bản ban đầu.
Độ mới của nguồn được cấu hình theo từng tích hợp dựa trên tần suất gửi và đối soát đã cam kết. Trước khi kích hoạt, hãy thống nhất độ cũ tối đa của nguồn, điều gì xảy ra khi vượt quá, các ngưỡng cảnh báo và liệu người vận hành có thể xác nhận việc chỉ dựa vào giới hạn riêng của từng khung thời gian hay không. Một khung thời gian từ nguồn đã cũ không bao giờ trở thành quy tắc từ chối; các quy tắc thông thường và quyền cấp vĩnh viễn vẫn là đường dự phòng.
Thuật toán dành cho bên tạo dữ liệu
Áp dụng quy trình không phụ thuộc ngôn ngữ lập trình này cho mọi lần cập nhật hội viên:
function publish_member(member_key):
source_result = fetch_authoritative_access_state(member_key)
if source_result.failed or source_result.incomplete:
record_failure(member_key)
schedule_retry(member_key)
return without sending access_time_windows
windows = []
for source_window in source_result.current_windows:
if source_window.is_absolute:
windows.append({
external_id: stable_window_id(source_window),
kind: "absolute",
from: to_integer_unix_seconds(source_window.start_instant),
to: to_integer_unix_seconds(source_window.end_instant),
timezone: source_window.display_timezone or "UTC",
scope_key: stable_scope_key(source_window) or "default",
label: safe_label(source_window)
})
else:
windows.append({
external_id: stable_window_id(source_window),
kind: "weekly",
timezone: valid_iana_zone(source_window.timezone) or "UTC",
access_hours: split_validate_and_sort_weekly_blocks(source_window),
active_from: optional_integer_unix_seconds(source_window.active_start),
active_until: optional_integer_unix_seconds(source_window.active_end),
scope_key: stable_scope_key(source_window) or "default",
label: safe_label(source_window)
})
normalized_snapshot = validate_sort_and_deduplicate(windows)
revision = next_durable_member_revision(member_key)
request = member_upsert_with(normalized_snapshot, revision)
persist_for_retry(member_key, request)
response = post_request(request)
if response.is_transient_or_unknown:
retry_exact_request_with_same_revision(request)
else if response.is_revision_conflict:
reconcile_with_latest_committed_source_state(member_key)
else if response.is_stale_skip:
stop_replaying_this_revision_and_reconcile(member_key)
Danh sách kiểm tra chứng nhận
Hoàn tất các bước kiểm tra sau tại một cơ sở staging bằng ánh xạ scope_key cuối cùng:
- Khung thời gian tuyệt đối được chấp nhận khi bỏ qua múi giờ và được đánh giá theo UTC.
- Khung thời gian tuyệt đối với múi giờ IANA tùy chỉnh giữ nguyên các thời điểm
from/to. - Khung thời gian hằng tuần với múi giờ IANA tùy chỉnh tuân theo giờ địa phương qua các lần chuyển sang và kết thúc giờ mùa hè.
- Ảnh chụp nhanh kết hợp tuyệt đối/hằng tuần thay thế hoàn toàn ảnh chụp nhanh trước đó.
- Quyền ra vào bắt đầu đúng tại
fromvà dừng đúng tạito; thời điểm kết thúc của khối hằng tuần cũng không được bao gồm. - Cập nhật thời gian dưới cùng
external_idvới phiên bản mới hơn sẽ có hiệu lực. - Bỏ qua
access_time_windowssẽ thay đổi các trường Member khác mà không thay đổi khung thời gian. - Phát lại cùng phiên bản/payload là idempotent.
- Cùng phiên bản/payload khác trả về xung đột và không thay đổi ảnh chụp nhanh.
- Phiên bản cũ hơn đến không theo thứ tự được báo cáo là cũ và không thể đưa trạng thái quay lại.
- Một
[]mới hơn thu hồi các khung thời gian thuộc nguồn; lỗi truy xuất từ upstream không gửi gì cả. - Một
scope_keykhông xác định hoặc chưa được ánh xạ không cấp quyền truy cập và tạo cảnh báo mà người vận hành có thể thấy. - Cảnh báo về độ cũ của nguồn và chính sách nguồn đã cũ được cấu hình hoạt động đúng tại ngưỡng đã thống nhất.
- Đường webhook và đường đối soát toàn bộ hội tụ về cùng ảnh chụp nhanh và thứ tự phiên bản.
- Dữ liệu từ chuỗi đến được Door & Gate Access trong thời gian mục tiêu đã thống nhất.
- Khung thời gian đang hiệu lực có thể cho phép ra vào cửa thực tế đã được ánh xạ, nhưng không thể vượt qua việc vô hiệu hóa người dùng,
blockAllAccess, chế độ bảo trì hoặc geofencing. - Trước, ngoài và sau một khung thời gian, các quy tắc thông thường và quyền cấp vĩnh viễn vẫn cho phép những người dùng đủ điều kiện theo cách khác.
Bộ dữ liệu kiểm thử tối thiểu
[
{
"name": "absolute-half-open",
"window": {
"external_id": "tv-absolute",
"kind": "absolute",
"from": 1792053000,
"to": 1792058400
},
"expect": {
"1792052999": "inactive",
"1792053000": "active",
"1792058399": "active",
"1792058400": "inactive"
}
},
{
"name": "weekly-dst",
"window": {
"external_id": "tv-weekly-dst",
"kind": "weekly",
"timezone": "America/New_York",
"access_hours": {
"sun": [["01:00", "03:30"]],
"mon": [],
"tue": [],
"wed": [],
"thu": [],
"fri": [],
"sat": []
}
},
"expect": "Evaluate local wall time: skipped times do not occur; both repeated 01:30 instants qualify."
}
]
Đồng thời gửi các bộ dữ liệu kiểm thử phủ định cho mili giây Unix, chuỗi số, số thực, múi giờ IANA không hợp lệ, from >= to, external_id trùng lặp, các khối chồng lấn, khối qua đêm, hơn tám khối trong một ngày, hơn 50 khung thời gian và các khóa phạm vi chưa được ánh xạ.