AI Agents & VietQR Payments: Python SDK Guide

2026-06-18 · AgentPay VN

pythonai-agentsvietqrpaymentsopen-source

The Problem: AI Agents That Can't Actually Get Paid

Imagine you've built an AI assistant that helps small Vietnamese businesses manage inventory, schedules, or customer support. It's brilliant—users love it. But when they ask, "How do I pay you?" you're stuck explaining bank transfers, Momo links, or worse, setting up a clunky payment gateway that takes 3% fees and complicates your architecture.

Or consider this: you're running a Claude-powered tutoring bot that sells access to specialized courses. Right now, payment happens outside the agent conversation—students submit payment separately, you manually verify, then grant access. Friction. Delays. Lost conversions.

The real issue? Most payment solutions weren't built for AI agents. They assume a web form, a user clicking a button, a redirect. They hold your money. They're complicated.

VietQR changes this. Combined with AgentPay VN—an open-source Python SDK and MCP server—your AI agent can now request payments, receive confirmation, and act on settlement within the same conversation. No money ever touches your account. The QR points straight at the merchant's bank, and a bank feed confirms when funds arrive.

This tutorial walks you through everything.

What Is AgentPay VN?

AgentPay VN is a lightweight, MIT-licensed Python SDK + MCP server that bridges AI agents and VietQR payments. Think of it as the nervous system connecting your agent to Vietnam's instant payment infrastructure.

Key facts: - Open-source (MIT): Full control, no vendor lock-in. - Zero holding of funds: QR codes point directly to your merchant bank account. AgentPay VN never touches money—it's purely orchestration. - Bank settlement confirmation: Built-in webhook/feed integration so your agent knows when payment actually arrived. - Three-line flow: create_payment_request()send checkout_url()await_settlement(). - Python-first: Integrates seamlessly with Claude (via MCP), LangChain agents, or any agentic framework.

Installation is one line:

pip install agentpay-vn

For Claude integration via MCP:

agentpay-mcp

The Three-Line Payment Flow

Before diving into code, let's visualize the flow:

  1. Create Payment Request: Your agent generates a payment request with amount, description, and a unique reference.
  2. Send Checkout URL: The agent presents a VietQR checkout link (as text, QR image, or embedded URL) to the user.
  3. Await Settlement: Your agent waits for bank confirmation that funds arrived. Once confirmed, it can proceed (grant access, unlock features, etc.).

No redirects. No intermediaries. The user scans once, pays their bank directly, and your agent immediately knows.

Getting Started: Installation & Configuration

Step 1: Install the SDK

pip install agentpay-vn

Verify installation:

python -c "import agentpay_vn; print(agentpay_vn.__version__)"

Step 2: Set Up Your Merchant Account

You'll need: - Merchant VietQR code (your business bank account QR for receiving payments). - Bank account details (to link settlement notifications). - API credentials (if using webhooks for settlement confirmation).

See AgentPay VN docs for merchant onboarding.

Step 3: Configure Your Agent

If using Claude via MCP, add this to your Claude configuration (e.g., claude_desktop_config.json):

{
  "mcpServers": {
    "agentpay": {
      "command": "agentpay-mcp",
      "env": {
        "MERCHANT_ID": "your_merchant_id",
        "VIETQR_ACCOUNT": "your_bank_account_or_qr_id"
      }
    }
  }
}

Claude can now call AgentPay VN functions natively within conversations.

Real-World Example: An AI Course-Selling Bot

Let's build a practical scenario: CourseBot, an AI assistant that sells access to a Python masterclass.

The Scenario

A student asks CourseBot, "I want to enroll in the advanced async patterns course. How much?"

CourseBot responds: 1. Quotes the price (499,000 VND). 2. Calls create_payment_request() to generate a payment. 3. Sends a VietQR checkout link. 4. Student scans, pays instantly from their bank app. 5. await_settlement() confirms funds arrived within seconds. 6. CourseBot immediately grants access, sends login credentials, and continues the conversation.

Code Implementation

from agentpay_vn import AgentPayClient, PaymentRequest
import json
import time

# Initialize the client with your merchant details
client = AgentPayClient(
    merchant_id="DEMO_MERCHANT",
    vietqr_account="0123456789@vietqr"  # Your bank QR identifier
)

def sell_course_to_student(student_name: str, course_id: str, price_vnd: int):
    """
    Main function: Student -> Payment Request -> Checkout -> Settlement -> Access Grant
    """

    # Step 1: Create a payment request
    # This generates a unique request with metadata tied to the student and course
    payment_request = client.create_payment_request(
        amount=price_vnd,
        description=f"Enrollment in {course_id} for {student_name}",
        reference_id=f"course_{course_id}_{student_name}_{int(time.time())}",
        metadata={
            "student_name": student_name,
            "course_id": course_id,
            "product_type": "course"
        }
    )

    print(f"✓ Payment request created")
    print(f"  Reference: {payment_request['reference_id']}")
    print(f"  Amount: {payment_request['amount']:,} VND")

    # Step 2: Send checkout URL to the student
    # In a real agent, you'd present this as a clickable link or QR image
    checkout_url = payment_request['checkout_url']
    qr_image_url = payment_request['qr_image_url']

    agent_response = f"""
    Great! I've set up your enrollment for {course_id}.

    **Payment Details:**
    - Amount: {price_vnd:,} VND
    - Please scan and pay within 5 minutes

    **QR Code:** {qr_image_url}
    **Or use this link:** {checkout_url}

    I'll grant you access as soon as payment confirms.
    """

    print(agent_response)

    # Step 3: Wait for settlement confirmation
    # In production, this would be event-driven via webhooks.
    # For this example, we poll with a timeout.
    reference_id = payment_request['reference_id']
    max_wait_seconds = 300  # 5 minutes
    poll_interval = 2  # Check every 2 seconds

    settled = client.await_settlement(
        reference_id=reference_id,
        timeout_seconds=max_wait_seconds,
        poll_interval_seconds=poll_interval
    )

    if settled:
        settlement_info = client.get_settlement_details(reference_id)
        print(f"\n✓ Payment confirmed!")
        print(f"  Settlement time: {settlement_info['settled_at']}")
        print(f"  Bank reference: {settlement_info['bank_transaction_id']}")

        # Step 4: Grant course access
        grant_course_access(student_name, course_id)

        final_message = f"""
        🎉 Welcome to {course_id}!

        Your enrollment is active. Here are your login credentials:
        - Username: {student_name}
        - Password: [sent to your email]
        - Course portal: https://courses.example.com

        You have 24/7 access. Let's start learning!
        """
        print(final_message)
        return True
    else:
        print(f"\n✗ Payment timeout. Student should retry.")
        return False

def grant_course_access(student_name: str, course_id: str):
    """
    Example: Grant course access in your database
    """
    # This would update your learning platform's database
    print(f"[DB] Granting {student_name} access to {course_id}...")
    # enrollment_db.create(student_name, course_id, active=True)

# Run the scenario
if __name__ == "__main__":
    sell_course_to_student(
        student_name="Nguyen Van A",
        course_id="python-async-mastery",
        price_vnd=499000
    )

Line-by-line explanation:

Advanced: Using MCP with Claude

If you're running Claude through the MCP server, your agent can call AgentPay functions directly in conversation. Here's how a conversation might flow:

User: "I want the Pro plan. What's the cost?"

Claude: [internally calls agentpay:create_payment_request with plan details] "The Pro plan is 999,000 VND/month. Here's your payment link: [QR]. Scan to confirm."

User: [scans, pays]

Claude: [internally polls agentpay:await_settlement] "Confirmed! Your Pro plan is now active. You can now access [features]. Need help?"

The MCP server handles all AgentPay calls transparently—Claude doesn't need explicit SDK imports.

Do's and Don'ts

Do Don't
Create a unique reference ID per transaction (include timestamp, user ID). This prevents duplicates if the agent retries. Don't reuse reference IDs across multiple transactions.
Poll or use webhooks to confirm settlement before granting access. Don't assume payment succeeded without confirmation.
Store the bank transaction ID from settlement details for reconciliation. Don't rely solely on the payment request ID; always verify with settlement data.
Implement timeout logic (e.g., "payment not confirmed in 5 min, please retry"). Don't wait indefinitely for settlement.
Log all payment events (request created, settled, failed) for auditing. Don't log sensitive customer data (full card numbers, etc.).
Use metadata fields to link payments to courses, products, or user accounts. Don't mix payment requests—each transaction should be isolated.

Handling Edge Cases

Scenario 1: Student Scans But Doesn't Pay

Use a timeout:

if not client.await_settlement(reference_id, timeout_seconds=300):
    agent_message = "Payment not received within 5 minutes. Your checkout link is still valid—please try again."

Scenario 2: Student Pays Twice (Accidental)

The unique reference_id ensures each payment is tracked independently. Your database should prevent duplicate course enrollments on the application side:

if already_enrolled(student_name, course_id):
    agent_message = "You're already enrolled. Check your email for login details."
else:
    grant_course_access(student_name, course_id)

Scenario 3: Agent Crashes Mid-Settlement

Store the reference_id immediately after creating the request. On restart, query settlement status:

status = client.get_settlement_status(reference_id)
if status == "settled":
    grant_access(...)
elif status == "pending":
    await_settlement(reference_id, remaining_timeout)

FAQ

Q: Does AgentPay VN hold my money? No. The QR code points directly at your merchant bank account. AgentPay VN only orchestrates the payment request and confirms settlement via bank feeds. You receive funds in your account instantly.

Q: How long does settlement confirmation take? VietQR payments are typically confirmed within 10-30 seconds of transfer. Your agent should see settlement status immediately via await_settlement().

Q: Can I use AgentPay VN outside Vietnam? Currently, AgentPay VN is built for Vietnamese merchants and customers with VietQR-compatible bank accounts. International support is on the roadmap; check GitHub discussions.

Q: What if my agent crashes while awaiting settlement? Store the reference_id in your database. On restart, call client.get_settlement_status(reference_id) to resume. If settled, grant access. If still pending, resume waiting.

Key Takeaways

Getting Started Today

Ready to let your AI agent accept VietQR payments?

  1. Install: pip install agentpay-vn
  2. Read the docs: https://agentpay.servicesai.vn/v1/docs
  3. Explore the source: https://github.com/phuocdu/agentpay-vn
  4. Set up your merchant account and start building.

Your agent won't just talk anymore—it'll close deals, process payments, and grant access all in one conversation. Welcome to agentic commerce. 🚀

Get started →

← All posts