Skip to Content
OneRoster 1.2

Ví dụ đồng bộ

Mã mẫu lấy mã truy cập, đọc hết danh sách sinh viên và kết quả thực tập, bằng Python và JavaScript.

Ví dụ dưới đây làm đủ một vòng đồng bộ: lấy mã truy cập, đọc từng trang danh sách sinh viên, rồi đọc kết quả thực tập. Thay BASE bằng địa chỉ cổng của trường, đặt mã ứng dụng và khoá bí mật vào biến môi trường TTDN_CLIENT_ID, TTDN_CLIENT_SECRET. Không ghi khoá bí mật thẳng vào mã.

import os
import requests

BASE = "https://truong.example.edu.vn"   # địa chỉ cổng của trường
CLIENT_ID = os.environ["TTDN_CLIENT_ID"]
CLIENT_SECRET = os.environ["TTDN_CLIENT_SECRET"]

def get_token():
    r = requests.post(
        f"{BASE}/oauth/token",
        auth=(CLIENT_ID, CLIENT_SECRET),
        data={"grant_type": "client_credentials"},
        timeout=30,
    )
    r.raise_for_status()
    return r.json()["access_token"]   # hết hạn sau 1 giờ

def read_all(token, path, key, params=None):
    """Đọc hết mọi trang của một danh sách, 1000 bản ghi mỗi lần."""
    rows, offset = [], 0
    while True:
        r = requests.get(
            f"{BASE}/ims/oneroster/{path}",
            headers={"Authorization": f"Bearer {token}"},
            params={**(params or {}), "limit": 1000, "offset": offset},
            timeout=30,
        )
        r.raise_for_status()
        page = r.json()[key]
        rows += page
        total = int(r.headers.get("X-Total-Count", len(rows)))
        offset += len(page)
        if not page or offset >= total:
            return rows

token = get_token()
students = read_all(token, "rostering/v1p2/students", "users")
results = read_all(token, "gradebook/v1p2/results", "results")

placed = {r["student"]["sourcedId"]: r["comment"] for r in results if r["scoreStatus"] == "fully graded"}
for s in students:
    print(s["identifier"], s["familyName"], s["givenName"], "→", placed.get(s["sourcedId"], "chưa có nơi thực tập"))

Đồng bộ định kỳ

Sau lần đầu, chỉ cần lấy phần thay đổi. Lưu lại thời điểm bắt đầu mỗi lần chạy và truyền vào bộ lọc ở lần sau:

since = "2026-11-10T00:00:00.000Z"   # thời điểm bắt đầu lần chạy trước
changed = read_all(token, "rostering/v1p2/users", "users", {"filter": f"dateLastModified>'{since}'"})

Bản ghi có status = "tobedeleted" là bản ghi đã gỡ ở cổng thực tập: cập nhật hoặc ẩn ở hệ thống của trường.

Xử lý lỗi

  • 401: mã hết hạn hoặc kết nối đã bị thu hồi. Xin mã mới; vẫn lỗi thì liên hệ nhà trường.
  • 429: gọi quá 600 lần trong một phút. Đợi khoảng một phút rồi thử lại.
  • Các lỗi khác: xem Lỗi và giới hạn.

On this page