Suốt loạt bài, ta viết code bên trong Odoo. Nhưng rất nhiều tình huống cần bên ngoài gọi vào: một script đồng bộ đơn hàng từ sàn TMĐT, một app di động đọc điểm thành viên, một hệ thống kế toán khác ghi hoá đơn vào Odoo. Cách chuẩn, cũ mà bền, chạy được từ mọi ngôn ngữ, là XML-RPC. Không cần cài gì trong Odoo — nó có sẵn hai endpoint, bạn chỉ việc gọi. Bài này chỉ luồng đầy đủ (đăng nhập → đọc/ghi) và chạy thật một vòng CRUD từ một script Python ngoài Odoo 19.

Hai endpoint: common và object

Odoo phơi ra hai địa chỉ XML-RPC. /xmlrpc/2/common để đăng nhập (và hỏi phiên bản); /xmlrpc/2/object để gọi mọi model qua một hàm duy nhất execute_kw.

Ảnh chụp mã Python nền tối gọi Odoo từ một script ngoài qua hai endpoint. Import xmlrpc client, URL DB USER PW. Bước 1 endpoint common đăng nhập trả uid: common bằng xmlrpc client ServerProxy URL cộng xmlrpc 2 common, common version trả server_version 19.0, uid bằng common authenticate DB USER PW rỗng trả về 2. Bước 2 endpoint object gọi model qua execute_kw: models bằng ServerProxy URL cộng xmlrpc 2 object, execute_kw nhận db uid pass model method args kwargs, the bằng models execute_kw DB uid PW quan the thanh vien search_read với fields name diem order diem desc. Phần CRUD đầy đủ qua execute_kw: i bằng execute_kw create với dict name TEST diem 50 trả id, execute_kw write đổi diem 99, execute_kw unlink xoá, cũng có search_count fields_get read và mọi method public. Ghi chú XML-RPC là chuẩn gọi từ Python PHP Java bất kỳ, cần login password hoặc API key thay password Odoo 14 cộng, luôn qua HTTPS

Hình 1: Luồng chuẩn. common.authenticate(db, user, password, {}) trả về uid (số). Sau đó mọi thao tác đi qua object.execute_kw(db, uid, password, model, method, args, kwargs) — search_read, create, write, unlink, search_count, fields_get... bất kỳ method public nào của model.

Chạy thật một vòng CRUD

Đây là kết quả thật khi chạy script Python ngoài gọi vào Odoo 19:

Ảnh chụp terminal nền tối chạy script Python ngoài gọi Odoo 19 qua XML-RPC kết quả thật. Lệnh python3 goi_odoo py. version 19.0-20260908. uid 2 authenticate thành công. search_read trả về bốn thẻ: VIP-0001 hang_the bac diem 150, VIP-0003 vang 150, VIP-0002 bac 85, VIP-0004 bac 0. count 4. Phần create write unlink từ xa: create trả id 56, after write diem 99, after unlink count 0. total the now 4 đã dọn về nguyên trạng

Hình 2: Thật, không bịa. version báo 19.0-20260908; authenticate trả uid=2; search_read đọc đúng 4 thẻ; rồi create (id 56) → write (điểm 99) → unlink — một vòng CRUD hoàn chỉnh từ bên ngoài, và dọn sạch để về nguyên trạng (total vẫn 4).

execute_kw: một hàm gọi mọi thứ

Điểm mạnh của XML-RPC Odoo là một hàm execute_kw gọi được mọi method của mọi model — không cần endpoint riêng cho từng thứ:

# search_read: lọc + chọn cột trong một lần
models.execute_kw(DB, uid, PW, 'res.partner', 'search_read',
    [[['is_company', '=', True]]],           # args: domain
    {'fields': ['name', 'email'], 'limit': 10})  # kwargs

# create nhiều bản ghi, write, unlink
ids = models.execute_kw(DB, uid, PW, 'product.product', 'create',
    [[{'name': 'Cà phê A'}, {'name': 'Cà phê B'}]])

# gọi cả method nghiệp vụ tuỳ ý (miễn là public)
models.execute_kw(DB, uid, PW, 'sale.order', 'action_confirm', [[order_id]])

args là danh sách tham số vị trí (domain, dict giá trị...), kwargs là tham số theo tên (fields, limit, order, context). Cùng đúng API ORM bạn dùng trong code server.

Bảo mật: đừng để hớ

XML-RPC mạnh nghĩa là nguy hiểm nếu để hở — nó cho phép đọc/ghi/xoá dữ liệu từ xa:

  • Xác thực bắt buộc. Cần login + password (hoặc uid + password) cho mọi lời gọi execute_kw. Từ Odoo 14+, nên dùng API key thay cho password thật: vào Preferences → Account Security → New API Key, rồi dùng key đó ở chỗ password. Rò rỉ API key thì thu hồi được, không phải đổi mật khẩu.
  • Luôn HTTPS. XML-RPC gửi credential trong payload; qua HTTP thường là lộ. Đặt sau nginx TLS.
  • Quyền của uid vẫn áp dụng. Lời gọi chạy dưới quyền user đăng nhập — Access Rights và Record Rules vẫn chặn. Dùng một user tài-khoản-dịch-vụ với đúng quyền cần, đừng dùng admin cho mọi tích hợp.
  • Giới hạn IP/tần suất ở tầng proxy nếu endpoint mở ra Internet.

XML-RPC hay JSON-RPC?

Odoo phơi ra cả hai giao thức cho cùng chức năng:

  • XML-RPC (bài này): chuẩn lâu đời, thư viện có sẵn ở mọi ngôn ngữ (Python xmlrpc.client, PHP, Java, Ruby...). Payload XML hơi nặng, nhưng ổn định, tài liệu nhiều.
  • JSON-RPC: nhẹ hơn, hợp khi gọi từ JavaScript/HTTP hiện đại — phần sau nói riêng.

Cùng model, cùng execute_kw, chỉ khác định dạng gói tin. Chọn XML-RPC khi cần tương thích rộng, JSON-RPC khi làm web/JS.

Ba ý mang về

  1. XML-RPC cho chương trình ngoài gọi Odoo không cần cài gì thêm: common.authenticate(db, user, pass, {}) lấy uid, rồi object.execute_kw(db, uid, pass, model, method, args, kwargs) gọi mọi method (search_read, create, write, unlink...).
  2. Một hàm execute_kw gọi mọi model/method — args (vị trí: domain, dict), kwargs (theo tên: fields, limit, order, context); đúng API ORM như trong code server, chạy được từ Python/PHP/Java/bất kỳ.
  3. Bảo mật là bắt buộc: xác thực mọi lời gọi (ưu tiên API key thay password, Odoo 14+), luôn HTTPS, dùng user dịch vụ đúng quyền (Record Rules vẫn áp) — đừng phơi admin ra Internet.

XML-RPC hợp cho backend đa ngôn ngữ; nhưng khi gọi từ web/JavaScript, JSON-RPC gọn hơn. Phần sau mổ xẻ gọi Odoo bằng JSON-RPC — cùng khả năng, định dạng nhẹ, và cách gọi từ fetch/JavaScript hay bất kỳ client HTTP nào.