Thanh toán AI Agent với Idempotency & Webhook: Hướng dẫn AgentPay VN
Nỗi Đau Thực Tế: Khi AI Agent Không Biết "Tiền Đã Về Hay Chưa"
Bạn vừa xây dựng một bot bán khoá học trực tuyến chạy 24/7. Khách hàng thanh toán qua bot, bot gửi tài liệu PDF... nhưng đột nhiên mạng bị gián đoạn. Bot không biết tiền đã chuyển vào tài khoản ngân hàng hay chưa, nên nó gửi khoá học 2 lần. Hoặc tệ hơn: bot không nhận được xác nhận settlement từ đâu, khách kêu "tôi đã chuyển rồi mà sao chưa nhận?"
Đây là cuộc chiến thường ngày của những developer xây dựng hệ thống AI agent thanh toán tự động. May mắn là AgentPay VN đã giải quyết vấn đề này một cách sạch sẽ.
Vì Sao Idempotency Là Anh Hùng Thầm Lặng
Idempotency có nghĩa là: "Dù gọi API bao nhiêu lần, kết quả cũng giống nhau." Tưởng tượng bạn gọi hàm create_payment_request() ba lần do timeout — nếu không có idempotency, bạn sẽ có ba yêu cầu thanh toán khác nhau, khách hàng sẽ confused ("Sao có 3 QR code?").
AgentPay VN xử lý điều này tự động:
from agentpay_vn import AgentPayClient
client = AgentPayClient(api_key="your_api_key_here")
# Tạo yêu cầu thanh toán với idempotency key
# Dù gọi 10 lần, vẫn chỉ tạo 1 request
payment_req = client.create_payment_request(
amount=299_000, # VNĐ
description="Khoá học Python Pro",
merchant_id="shop_123",
idempotency_key="order_khoa_hoc_2024_001" # Chìa khoá bí mật!
)
print(f"QR Code URL: {payment_req['checkout_url']}")
print(f"Payment ID: {payment_req['payment_id']}")
Giải thích từng dòng:
- amount=299_000: Giá bán (đơn vị đồng)
- description: Mô tả sản phẩm, khách sẽ thấy trên app ngân hàng
- idempotency_key: Mã duy nhất (thường dùng order_id hoặc email+timestamp). Nếu gọi lại với key này, hệ thống trả về request cũ, không tạo request mới
Đây là lý do tại sao bot của bạn sẽ không bao giờ gửi khoá học 2 lần — vì payment request đã tồn tại rồi.
Webhook: Bot Biết Tiền Về Khi Nào, Từ Đâu
Webhook là cách AgentPay gọi ngược lại bot của bạn để báo tin tốt: "Tiền đã vào!" Thay vì bot phải hỏi "Tiền về chưa? Tiền về chưa?" cứ mỗi 5 giây (gọi là polling, rất lãng phí), webhook chủ động push sự kiện tới bot.
Cấu hình webhook cho AgentPay MCP server (cho Claude hoặc agent khác):
{
"tools": [
{
"name": "agentpay-mcp",
"config": {
"webhook_url": "https://your-bot-domain.com/webhooks/agentpay",
"webhook_secret": "your_webhook_secret_key_12345",
"events": ["payment.settled", "payment.failed", "payment.expired"]
}
}
]
}
Lưu ý quan trọng: AgentPay KHÔNG BAO GIỜ giữ tiền. QR code trỏ thẳng vào tài khoản ngân hàng thương nhân của bạn. Khi khách quét QR và chuyển khoản, tiền tức thì về bank account bạn. AgentPay chỉ theo dõi, xác nhận qua bank feed (OTP hoặc API ngân hàng), rồi gửi webhook tới bot.
Kịch Bản Đời Thực: Bot Bán Khóa Học Online
Phạm Minh Anh (30 tuổi) mở cửa hàng khóa học trực tuyến trên Telegram. Hàng ngày cô nhận 5-10 đơn hàng. Trước đây cô phải check bank app thủ công, sau đó copy-paste link Drive vào tin nhắn khách (rất kém efficiency).
Sau khi dùng AgentPay VN, quy trình tự động hoàn toàn:
- Khách gõ:
/mua khoa_python_pro - Bot tạo payment request (với idempotency_key = telegram_user_id + timestamp)
- Bot gửi QR code cho khách (QR này trỏ thẳng vào tài khoản bank của cô)
- Khách quét & chuyển khoản qua app ngân hàng (Vietcombank, Techcombank, ...)
- Tiền vào account cô ngay lập tức
- AgentPay webhook báo "payment.settled" tới Telegram bot
- Bot tự động gửi link Drive cho khách (không cần cô can thiệp)
Công việc thủ công cô từ 2 giờ/ngày còn 5 phút/ngày.
Hướng Dẫn Từng Bước: Từ Cài Đặt Đến Đối Soát Tự Động
1. Cài đặt AgentPay SDK
pip install agentpay-vn
2. Code Workflow 3 Bước
import asyncio
from agentpay_vn import AgentPayClient
from datetime import datetime
client = AgentPayClient(
api_key="sk_live_your_key_here",
merchant_id="merchant_abc123"
)
async def payment_flow(customer_email: str, product_name: str, amount: int):
"""
Quy trình thanh toán 3 bước: request → checkout → await
"""
# Bước 1: Tạo yêu cầu thanh toán
idempotency_key = f"{customer_email}_{product_name}_{int(datetime.now().timestamp())}"
payment_req = client.create_payment_request(
amount=amount,
description=f"Purchase: {product_name}",
idempotency_key=idempotency_key,
metadata={"customer_email": customer_email}
)
checkout_url = payment_req['checkout_url']
payment_id = payment_req['payment_id']
print(f"✓ Tạo yêu cầu thành công!")
print(f" Mã thanh toán: {payment_id}")
print(f" Link QR: {checkout_url}")
# Bước 2: Gửi QR cho khách (thực hiện bên ngoài, ví dụ gửi SMS/email)
# send_qr_to_customer(checkout_url, customer_email)
# Bước 3: Chờ xác nhận settlement từ bank feed
# timeout=300 (5 phút), check mỗi 3 giây
settlement = await client.await_settlement(
payment_id=payment_id,
timeout=300,
check_interval=3
)
if settlement['status'] == 'settled':
print(f"✓ THANH TOÁN THÀNH CÔNG!")
print(f" Số tiền: {settlement['amount']:,} VNĐ")
print(f" Thời gian: {settlement['settled_at']}")
return True
else:
print(f"✗ Thanh toán thất bại: {settlement['reason']}")
return False
# Chạy
async def main():
success = await payment_flow(
customer_email="customer@example.com",
product_name="khoa_python_pro",
amount=499_000
)
if __name__ == "__main__":
asyncio.run(main())
Chi tiết code:
- idempotency_key: Tạo mã unique từ email + tên sản phẩm + timestamp
- create_payment_request(): Trả về dict với checkout_url (QR) và payment_id
- await_settlement(): Chờ xác nhận từ bank feed (async, không chặn thread)
- metadata: Dữ liệu thêm để theo dõi (customer_email, order_id, ...)
3. Setup MCP Server Cho Claude
Nếu bạn dùng Claude hoặc agent khác, chạy MCP server:
agentpay-mcp --api-key sk_live_your_key --port 3000
Rồi config trong Claude:
{
"mcpServers": {
"agentpay": {
"command": "agentpay-mcp",
"args": ["--api-key", "sk_live_your_key", "--port", "3000"],
"env": {
"WEBHOOK_URL": "https://your-bot.com/webhooks/agentpay"
}
}
}
}
Bây giờ Claude có thể gọi create_payment_request và await_settlement như một tool thông thường.
Nên Làm & Không Nên Làm
| Nên Làm ✓ | Không Nên Làm ✗ |
|---|---|
| Dùng idempotency_key duy nhất per order | Gọi create_payment_request mà không idempotency_key |
| Lưu payment_id để sau có thể query lại | Tin tưởng ngay mà không chờ webhook/settlement |
| Dùng webhook để nhận sự kiện real-time | Polling API mỗi 2 giây (tốn tài nguyên) |
| Kiểm tra webhook_secret trước xử lý | Bỏ qua secret, dễ bị giả mạo |
| Set timeout hợp lý (300-600s) cho await_settlement | Timeout quá ngắn (< 10s) khiến false negative |
| Log payment_id & idempotency_key vào database | Mất vết thanh toán, khó debug sau |
| Test với sandbox trước production | Deploy thẳng vào production |
Nâng Cao: Xử Lý Lỗi & Retry
Thực tế, mạng không bao giờ hoàn hảo. Webhook có thể tới muộn, network timeout, server down tạm thời. Code production cần handle những trường hợp này:
import asyncio
from agentpay_vn.exceptions import AgentPayError
async def robust_payment_flow(payment_id: str, max_retries: int = 3):
"""
Chờ settlement với retry logic
"""
for attempt in range(max_retries):
try:
settlement = await client.await_settlement(
payment_id=payment_id,
timeout=120,
check_interval=5
)
if settlement['status'] == 'settled':
return settlement
elif settlement['status'] == 'failed':
raise Exception("Khách hàng hủy thanh toán")
except asyncio.TimeoutError:
print(f"Lần {attempt+1}: Timeout. Thử lại trong 10s...")
await asyncio.sleep(10)
except AgentPayError as e:
if "rate_limit" in str(e) and attempt < max_retries - 1:
print(f"Rate limit. Chờ 30s...")
await asyncio.sleep(30)
else:
raise
# Nếu vẫn chưa xong, lưu vào queue để check sau
print(f"Không xác nhận được {payment_id}. Sẽ check lại sau 1 giờ.")
schedule_retry(payment_id, delay=3600)
FAQ: Những Câu Hỏi Hay Gặp
Q1: Tiền thanh toán qua QR có đi vào tài khoản AgentPay không? Không! Tiền trực tiếp vào tài khoản ngân hàng của bạn. AgentPay chỉ track transaction qua bank feed API. Bạn luôn là chủ nhân tiền.
Q2: Webhook có độ trễ không? Nếu webhook mất (down server), thanh toán có bị mất không?
Webhook có thể trễ 5-30s (phụ thuộc mạng), nhưng nó sẽ tới cuối cùng. Nếu bot của bạn down, AgentPay sẽ retry webhook 3 lần trong 1 giờ. Và dù webhook mất, bạn vẫn có thể query payment status sau này bằng client.get_payment(payment_id). Tiền không bao giờ bị mất.
Q3: Có phí gì không? AgentPay VN là open-source MIT, miễn phí. Nhưng ngân hàng có thể tính phí API/bank feed (thường 0-2%). Bạn nên hỏi ngân hàng của mình.
Q4: Dùng idempotency_key dài bao nhiêu là đủ?
Nên dùng ≥ 32 ký tự (ví dụ UUID hoặc hash). AgentPay chấp nhận max 255 ký tự. Ví dụ: order_20240115_john_doe_8ba31562.
Tóm Tắt Nhanh
- Idempotency key = chìa khoá tránh trùng lặp payment request, dù gọi API bao nhiêu lần
- Webhook = cách AgentPay báo tin tốt (tiền về) tới bot bạn ngay lập tức
- Quy trình 3 bước:
create_payment_request()→ gửi QR →await_settlement() - Tiền an toàn: Trực tiếp vào bank account bạn, không qua AgentPay
- MCP server: Cho phép Claude/agent gọi AgentPay như một tool
- Code đơn giản: 10 dòng là đủ để tạo payment & chờ xác nhận
- Production-ready: Kèm retry logic, timeout, error handling
Kết & Hành Động Tiếp Theo
Nếu bạn đang chạy bot AI (Telegram, Discord, web app) cần nhận tiền từ người dùng, AgentPay VN sẽ giảm 90% pain point của bạn: không cần tích hợp API ngân hàng phức tạp, không cần xử lý idempotency thủ công, không cần poll API hàng giây.
Hành động ngay hôm nay:
- Cài đặt:
pip install agentpay-vn - Đọc docs: https://agentpay.servicesai.vn/v1/docs
- Sao chép code ví dụ trên, test ở sandbox
- Deploy lên production (nếu bạn không có sandbox, hãy contact team qua GitHub)
- Theo dõi webhook để xác nhận settlement
Repo GitHub (star ⭐ nếu thích): https://github.com/phuocdu/agentpay-vn
Chúc bạn xây dựng bot thanh toán tuyệt vời! 🎉