Tài liệu API: chuyển tiền và Lì xì
Các phương thức chi trả. Một lệnh chuyển đưa tiền từ số dư ứng dụng của bạn
vào ví của một người dùng Telegram hoặc tạm giữ tiền cho đến khi người nhận mới
mở bot. Một Lì xì là liên kết nhận tiền, với số tiền được tạm giữ trước
trên số dư ứng dụng. Các quy ước chung (xác thực, cấu trúc phản hồi, số tiền, spend_id)
nằm ở trang tài liệu Merchant API.
Cả ba phương thức đưa tiền ra đều tuân theo
chế độ chi trả của ứng dụng: một ứng
dụng mới chi trả được cho bất kỳ ai ngay từ đầu; nếu chủ sở hữu đã siết lại,
chỉ những người nhận trong danh sách mới được chi trả
(403 recipient_not_allowed), hoặc không ai cả (403 payouts_disabled). Chủ
sở hữu đặt chế độ này trong Mini App; API không đổi được. Còn các khoản chi trả
được phép dùng vào việc gì thì do điều khoản Merchant API
quy định.
transfer
POST /pay/api/transfer — scope payouts, giới hạn 30 mỗi phút. Người nhận
đã có trong ứng dụng sẽ nhận tiền ngay. Nếu username chưa có trong ứng dụng,
lệnh chuyển có trạng thái pending: tiền được tạm giữ cho đến khi người nhận
mở bot lần đầu bằng đúng username đó. Tiền chưa được nhận sẽ trả về số dư ứng dụng sau hạn 30 ngày (expires_at). Xác nhận trạng thái status: "returned" trước khi ghi nhận khoản hoàn vào sổ sách. Bạn cần tự gửi invite_url cho người nhận vì bot không
thể nhắn cho người chưa từng mở bot. Trạng thái cuối cùng là completed hoặc
returned; hãy bật webhook transfer_completed và
transfer_returned, hoặc gọi getTransfers để theo dõi.
Chỉ truyền một trong hai tham số user_id hoặc username. Nếu bỏ cả hai hoặc
truyền đồng thời cả hai, yêu cầu sẽ bị từ chối do tham số không hợp lệ.
| Tham số | Kiểu | Bắt buộc | Ý nghĩa |
|---|---|---|---|
user_id | integer | một trong user_id / username | ID Telegram của người nhận; người nhận phải đã có trong ứng dụng |
username | string | một trong user_id / username | tên người dùng của người nhận, có hoặc không có @; tên chưa có trong ứng dụng sẽ tạo khoản chi trả đang chờ |
asset | string | có | mã tài sản |
amount | string | có | chuỗi thập phân dương; ngoài ra còn phải nằm trong mức tối thiểu và tối đa cho mỗi lệnh của nền tảng (ước lượng theo giá trị quy đổi ra USD tại tỷ giá hiện hành) |
spend_id | string | có | khóa idempotency, 1–64 ký tự, không trùng giữa các khoản chi |
comment | string | không | tối đa 1024 ký tự, hiện cho người nhận |
disable_send_notification | boolean | không | true tắt thông báo cho người nhận khi chi trả ngay; khi nhận một khoản chuyển đang chờ, người nhận vẫn được thông báo |
Kết quả là đối tượng transfer: transfer_id, hash, user_id,
recipient_username, asset, amount, amount_minor, spend_id, comment,
status (pending / completed / returned), created_at, completed_at,
expires_at, invite_url. user_id có thể là null khi đang chờ người nhận
mới; completed_at là null cho đến khi lệnh chuyển hoàn tất.
Lỗi: 403 payouts_disabled / 403 recipient_not_allowed (do
chế độ chi trả), 404 user_not_found
(ID chưa có trong ứng dụng hoặc người nhận không khả dụng), 400 invalid_recipient
(tên người dùng của người nhận sai định dạng),
400 amount_too_small / 400 amount_too_big
(nằm ngoài khoảng cho phép của mỗi lệnh), 409 insufficient_funds,
400 unknown_asset, 400 invalid_amount, và cặp lỗi của spend_id:
409 idempotency_conflict / 409 idempotency_in_progress.
transferBatch
POST /pay/api/transferBatch — scope payouts, giới hạn 10 mỗi phút.
Một phần mở rộng dành cho chi trả hàng loạt: tối đa 100 lệnh chuyển trong một
lần gọi.
Một tham số: items — một mảng mà mỗi phần tử là trọn bộ tham số của transfer
(user_id hoặc username, asset, amount, spend_id, kèm comment và
disable_send_notification tùy chọn). Các spend_id phải khác nhau trong cùng
một lô, nếu không cả lần gọi thất bại với 400 duplicate_spend_id trước khi bất
cứ gì được thực thi. Cấu trúc phần tử không hợp lệ, chế độ chi trả hoặc hạn mức hằng ngày của ứng dụng cũng có thể khiến cả yêu cầu bị từ chối trước khi chi trả. Khi yêu cầu được chấp nhận, kết quả nằm trong result.items.
Các phần tử được xử lý độc lập, theo thứ tự — một phần tử thất bại không bao
giờ làm hoàn tác các phần tử khác. Lần gọi vẫn trả về HTTP 200 với ok: true
ngay cả khi có phần tử thất bại, nên hãy luôn kiểm tra từng phần tử:
- thành công:
{"ok": true, "spend_id": "…", "result": <transfer object>} - thất bại:
{"ok": false, "spend_id": "…", "error": {"code": …, "name": "…"}}với đúng bộ tên lỗi của mộttransferđơn lẻ.
Các phần tử trong lô dùng chung không gian idempotency với lệnh chuyển đơn lẻ:
thử lại cả lô — hoặc gửi lại một phần tử dưới dạng một transfer đơn lẻ với cùng
spend_id — sẽ trả lại kết quả đã lưu thay vì chi trả hai lần.
getTransfers
GET /pay/api/getTransfers — scope read. Bộ lọc: asset,
transfer_ids (phân tách bằng dấu phẩy), spend_id (khớp chính xác — tra một
khoản chi theo khóa của riêng bạn), status (pending / completed / returned),
cùng offset / count. Trả về
{"items": [transfer, …]}, mới nhất trước.
createCheck
POST /pay/api/createCheck — scope checks, giới hạn 60 mỗi phút.
Mặc định, tạo Lì xì dùng một lần từ số dư ứng dụng. Ai có liên kết hoặc chỉ người được gán sẵn có thể nhận. Phần mở rộng recipients tạo danh sách người nhận cụ thể với số tiền riêng cho từng người. Tổng tiền được tạm giữ ngay khi tạo (available chuyển sang onhold trong getBalance). Tạo Lì xì chịu cùng giới hạn số tiền và hạn mức chi trả hằng ngày như lệnh chuyển.
| Tham số | Kiểu | Bắt buộc | Ý nghĩa |
|---|---|---|---|
asset | string | có | mã tài sản |
amount | string | trừ khi đặt recipients | chuỗi thập phân dương; nếu có recipients, tổng tiền được tính từ danh sách |
pin_to_user_id | integer | không | chỉ Telegram user id này được nhận |
pin_to_username | string | không | chỉ @username này được nhận (dấu @ là tùy chọn; bị bỏ qua khi đã đặt cả pin_to_user_id). Username phải thuộc về người dùng đã có trong ứng dụng |
spend_id | string | không | khóa idempotency (phần mở rộng) — hãy dùng nó |
recipients | array | không | phần mở rộng: 1–100 phần tử, mỗi phần tử có user_id hoặc username và amount là chuỗi thập phân dương. Không dùng cùng người nhận được gán sẵn |
password | string | không | phần mở rộng: mật khẩu bắt buộc khi nhận, tối đa 64 ký tự |
expires_in | integer | không | phần mở rộng: thời hạn tính bằng giây; bỏ trống hoặc 0 = không hết hạn |
Kết quả là đối tượng check: check_id, hash, asset,
amount, amount_minor, bot_check_url (liên kết t.me để nhận),
status (active / activated), pin_to_user_id, created_at,
activated_at, expires_at và recipients (null với Lì xì thông thường; nếu có danh sách, mỗi phần tử gồm user_id, username, amount, amount_minor, claimed_at). Mỗi lượt nhận gửi webhook check_activated nếu đã bật; lượt nhận theo danh sách còn có activated_slot. Hết hạn sẽ trả lại phần chưa nhận; Lì xì theo danh sách có thể gửi check_expired.
Phản hồi hiện tại trả status: "active" cho mọi Lì xì chưa được nhận hết, kể cả đã hết hạn. Hãy kiểm tra cả expires_at; riêng active không chứng minh liên kết vẫn nhận được tiền.
Lỗi: 403 payouts_disabled / 403 recipient_not_allowed (do
chế độ chi trả — ở chế độ allowlist,
mọi người được gán sẵn hoặc nêu trong danh sách nhận đều phải được phép nhận), 400 unknown_asset,
400 invalid_amount, 404 user_not_found (username được gán không khớp với
ai), 409 insufficient_funds, và cặp lỗi của spend_id.
deleteCheck
POST /pay/api/deleteCheck — scope checks. Một tham số: check_id.
Hủy Lì xì đang hoạt động và trả phần chưa nhận về số dư ứng dụng của bạn;
trả về true. Lỗi: 404 check_not_found,
409 check_not_active (đã nhận hết, hết hạn hoặc bị xóa).
getChecks
GET /pay/api/getChecks — scope read. Bộ lọc: asset, check_ids
(phân tách bằng dấu phẩy), status (active / activated), cùng offset /
count. Trả về {"items": [check, …]}, mới nhất trước; các Lì xì đã xóa không
bao giờ được trả về.
Bài viết này có giúp được bạn không?
Cảm ơn phản hồi của bạn.