Thanh toán AI agent: Idempotency, Webhook & Đối soát tự động

2026-07-22 · AgentPay VN

aipythonvietqrwebhookmcp

Bài Toán Thực Tế: Khi AI Agent Phải Xử Lý Thanh Toán

Hãy tưởng tượng bạn có một chatbot bán khoá học trực tuyến. Khách hàng nhắn: "Mình muốn mua khoá Python nâng cao." Bot của bạn tạo link thanh toán VietQR và gửi cho khách. Nhưng rồi điều tồi tệ xảy ra:

Đây chính là lý do AgentPay VN ra đời — một SDK Python mã mở (MIT License) giúp AI agent xử lý thanh toán an toàn, tự động, không bao giờ giữ tiền (toàn bộ chuyển thẳng vào tài khoản ngân hàng của bạn). Bài viết này sẽ hướng dẫn bạn tránh những tình huống trên.

Tại Sao Idempotency Quan Trọng Với AI Agent?

Khi một AI agent thực hiện hành động (tạo yêu cầu thanh toán), nó có thể bị gọi lại nhiều lần do: - Timeout hoặc kết nối mạng không ổn định. - Retry logic trong framework AI (Claude, GPT, Agent framework). - Người dùng bấm nút "Thanh toán" lại do chưa thấy kết quả.

Idempotency (tính đơn điệu) đảm bảo rằng dù gọi API 10 lần với cùng dữ liệu, bạn cũng chỉ nhận được 1 yêu cầu thanh toán duy nhất. AgentPay VN xử lý điều này qua idempotency_key — một ID độc nhất do bạn cung cấp:

from agentpay_vn import AgentPayClient

# Khởi tạo client
client = AgentPayClient(api_key="your_api_key_here")

# Tạo yêu cầu thanh toán với idempotency_key
# Nếu gọi lại với cùng key, sẽ nhận lại cùng kết quả thay vì tạo mới
payment_request = client.create_payment_request(
    amount=299000,  # 299k VND cho khoá học
    description="Khoá học Python Nâng Cao",
    merchant_id="shop_python_vn",
    idempotency_key="order_user123_20250116"  # Duy nhất per user/order
)

print(f"Payment ID: {payment_request.payment_id}")
print(f"Checkout URL: {payment_request.checkout_url}")
print(f"QR mã VietQR: {payment_request.vietqr_string}")

Giải thích từng dòng: - idempotency_key: Xây dựng từ user ID + timestamp/order ID đảm bảo tính duy nhất. - amount: Tiền tính bằng VND; không có phí ẩn. - checkout_url: Link mà bạn gửi cho khách hàng (hoặc hiển thị QR đã mã hóa).

Lợi ích: Nếu agent retry 5 lần vì timeout, chỉ 1 thanh toán được tạo. Bạn không sợ khách bị "double charge".

Webhook: Vòng Lặp Xác Nhận Thanh Toán

Không chỉ chờ trong vòng lặp (polling) là không hiệu quả. AgentPay VN gửi webhook tới server của bạn ngay khi thanh toán được xác nhận từ ngân hàng:

from flask import Flask, request, jsonify
import hmac
import hashlib
import json

app = Flask(__name__)
WEBHOOK_SECRET = "your_webhook_secret_key"

@app.route("/webhook/agentpay", methods=["POST"])
def handle_webhook():
    # 1. Xác thực chữ ký webhook để tránh fake request
    signature = request.headers.get("X-Signature")
    body = request.get_data(as_text=True)

    expected_sig = hmac.new(
        WEBHOOK_SECRET.encode(),
        body.encode(),
        hashlib.sha256
    ).hexdigest()

    if not hmac.compare_digest(signature, expected_sig):
        return jsonify({"error": "Invalid signature"}), 401

    # 2. Parse payload từ webhook
    payload = request.json
    payment_id = payload["payment_id"]
    status = payload["status"]  # "settled", "pending", "failed"
    amount = payload["amount"]
    merchant_account = payload["merchant_account"]  # Tài khoản ngân hàng nhận tiền

    # 3. Cập nhật database của bạn
    if status == "settled":
        # Thanh toán thành công → cấp quyền truy cập khoá học
        user_id = payload["metadata"].get("user_id")
        course_id = payload["metadata"].get("course_id")

        grant_course_access(user_id, course_id)
        send_confirmation_email(user_id, course_id, amount)

        print(f"✓ Thanh toán {payment_id} thành công. Tiền vào: {merchant_account}")

    elif status == "failed":
        # Xử lý thanh toán thất bại
        refund_or_notify_user(payment_id)

    # 4. Trả về 200 OK để AgentPay biết bạn đã nhận webhook
    return jsonify({"status": "received"}), 200

if __name__ == "__main__":
    app.run(port=5000)

Điểm quan trọng: - Xác thực chữ ký (X-Signature): Đảm bảo webhook thực sự từ AgentPay, không phải hacker. - Idempotent processing: Lưu payment_id vào DB; nếu webhook đến 2 lần (hiếm nhưng có thể), bạn chỉ cấp quyền 1 lần. - Status = "settled": Tiền đã tới tài khoản ngân hàng của bạn an toàn. - Metadata: Gắn user_id, order_id hay thông tin custom để xử lý sau.

Đối Soát Tự Động: So Khớp Bank Feed Với Thanh Toán

AgentPay VN cung cấp API để lấy bank feed — danh sách các giao dịch thực tế từ ngân hàng — giúp bạn tự động so khớp với thanh toán đã tạo:

from agentpay_vn import AgentPayClient
from datetime import datetime, timedelta

client = AgentPayClient(api_key="your_api_key_here")

# Lấy danh sách thanh toán từ 7 ngày trước đến hôm nay
start_date = (datetime.now() - timedelta(days=7)).isoformat()
end_date = datetime.now().isoformat()

payments = client.get_payments(
    start_date=start_date,
    end_date=end_date,
    status="settled"  # Chỉ lấy những cái đã xác nhận
)

bank_feed = client.get_bank_feed(
    start_date=start_date,
    end_date=end_date
)

# So khớp: Mỗi payment phải có tương ứng trong bank_feed
matched = 0
unmatched = []

for payment in payments:
    found = False
    for transaction in bank_feed:
        if (
            payment.amount == transaction.amount and
            payment.settlement_date.date() == transaction.date
        ):
            found = True
            matched += 1
            break

    if not found:
        unmatched.append({
            "payment_id": payment.payment_id,
            "amount": payment.amount,
            "reason": "Không tìm thấy trong bank feed"
        })

print(f"Đối soát thành công: {matched}/{len(payments)}")
if unmatched:
    print(f"Cần kiểm tra: {unmatched}")
    # Gửi alert tới team kế toán
    alert_accounting_team(unmatched)

Lợi ích: - Tự động phát hiện lỗi: Nếu thanh toán được tạo nhưng tiền không tới, bạn sẽ biết ngay. - Tuân thủ kiểm toán: Tất cả giao dịch được ghi chép đầy đủ. - Giảm công thủ công: Không cần nhân viên kế toán phải so sánh bằng tay.

Cấu Hình MCP Server Cho Claude & AI Agent

Nếu bạn dùng Claude hoặc các agent framework khác, bạn có thể cấu hình AgentPay VN như một MCP (Model Context Protocol) server để agent gọi trực tiếp:

{
  "mcpServers": {
    "agentpay": {
      "command": "agentpay-mcp",
      "args": [],
      "env": {
        "AGENTPAY_API_KEY": "your_api_key_here",
        "AGENTPAY_WEBHOOK_SECRET": "your_webhook_secret",
        "AGENTPAY_MERCHANT_ID": "your_merchant_id"
      }
    }
  }
}

Trong Claude (hoặc Agent): Bạn không cần viết code gọi API. Claude sẽ tự gọi hàm qua MCP:

User: "Tôi muốn mua khoá học giá 599k"

Claude: "Tôi sẽ tạo yêu cầu thanh toán cho bạn."
[Gọi MCP: agentpay.create_payment_request(amount=599000, ...)]

Claude: "Vui lòng quét mã QR này: [QR]. Thanh toán sẽ được xác nhận trong vòng 30 giây."

Kịch Bản Thực Tế: Bot Bán Khóa Học Online

Hãy tưởng tượng một chatbot Telegram bán khoá học Python:

Luồng xử lý:

  1. User gõ: "Mua khoá Python Nâng Cao"
  2. Bot tạo payment request với idempotency_key = f"user_{user_id}_course_python_nang_cao"
  3. Bot gửi QR + checkout link cho user
  4. User quét, chuyển tiền (hoặc bấm link thanh toán online)
  5. Webhook từ AgentPay tới server → status = settled
  6. Bot tự động: - Cấp quyền truy cập khoá học (lưu vào DB) - Gửi email xác nhận + link học tập - Gửi tin nhắn Telegram: "✓ Thanh toán thành công! Bạn có thể bắt đầu học ngay."
  7. Hàng ngày, script đối soát so khớp các payment với bank feed

Lợi ích: - Toàn bộ tự động, không cần can thiệp. - User nhận quyền truy cập ngay (UX tuyệt vời). - Không bao giờ bị "double charge" nhờ idempotency. - Tài chính rõ ràng, dễ kiểm toán.

Nên & Không Nên Khi Dùng AgentPay VN

Nên Làm Không Nên Làm
✓ Luôn dùng idempotency_key khi tạo payment ✗ Bỏ qua idempotency; tạo payment mà không key
✓ Xác thực webhook bằng signature ✗ Tin tưởng mọi webhook mà không verify
✓ Lưu payment_id vào DB ngay sau khi tạo ✗ Chỉ lưu khi webhook tới (có thể mất dữ liệu)
✓ Xử lý idempotent trong webhook (check DB trước) ✗ Cấp quyền/gửi email ngay mà không check trùng
✓ Đối soát hàng ngày với bank feed ✗ Chỉ tin webhook; không so khớp với thực tế
✓ Gắn metadata (user_id, order_id) vào payment ✗ Tạo payment trống, không thể track sau

Hướng Dẫn Cài Đặt Từng Bước

1. Cài SDK

pip install agentpay-vn

2. Lấy API Key

Truy cập https://agentpay.servicesai.vn/v1/docs → đăng ký tài khoản merchant → copy API key.

3. Khởi Tạo Client

from agentpay_vn import AgentPayClient

client = AgentPayClient(
    api_key="sk_live_xxxxx",  # Hoặc sk_test_ cho sandbox
    base_url="https://agentpay.servicesai.vn/api"  # Tuỳ chọn
)

4. Tạo Payment Request

payment = client.create_payment_request(
    amount=100000,
    description="Sản phẩm test",
    merchant_id="your_merchant_id",
    idempotency_key="test_key_001",
    metadata={"user_id": "123", "order_id": "ord_456"}
)

print(payment.checkout_url)  # Gửi cho khách

5. Setup Webhook

6. Đợi & Xác Nhận

import time

payment_id = payment.payment_id

# Nếu không dùng webhook, có thể polling (không khuyến khích)
for i in range(30):  # Chờ tối đa 30 giây
    status = client.get_payment_status(payment_id)
    if status == "settled":
        print("✓ Thanh toán thành công!")
        break
    time.sleep(1)

Câu Hỏi Thường Gặp (FAQ)

Q1: AgentPay VN có giữ tiền của tôi không?

Không bao giờ. Toàn bộ tiền từ QR code VietQR được chuyển trực tiếp vào tài khoản ngân hàng của bạn. AgentPay chỉ là một cầu nối — xử lý logic, webhook, và đối soát.

Q2: Nếu webhook bị mất/không tới, tôi sẽ biết khi nào?

Bạn có thể (1) polling get_payment_status() sau một khoảng thời gian, hoặc (2) đối soát hàng ngày với bank feed. Nếu payment tồn tại trong payment list nhưng webhook không tới, bạn sẽ phát hiện trong bước đối soát.

Q3: Có phí ẩn nào không?

Không. Giá được hiển thị rõ ràng trên tài liệu. Chỉ có phí service (khoảng 1-2%) được tính khi tạo payment, không có phí webhook hoặc API call thêm.

Q4: Tôi có thể test trước khi production không?

Có. Dùng API key sk_test_ và merchant sandbox. Mọi payment sẽ được giả lập — không tiêu tiền thật.

Mẹo Nâng Cao

Tóm Tắt Nhanh

Bước Tiếp Theo

  1. Cài đặt: pip install agentpay-vn
  2. Đọc docs: https://agentpay.servicesai.vn/v1/docs
  3. Fork repository: https://github.com/phuocdu/agentpay-vn (nếu muốn contribute)
  4. Setup sandbox và thử tạo payment đầu tiên.
  5. Deploy webhook và test xác nhận thanh toán.

Nếu gặp vấn đề, hãy mở issue trên GitHub — team AgentPay VN sẽ hỗ trợ bạn. Chúc bạn triển khai thành công! 🚀

Bắt đầu →

← Tất cả bài