AI Chatbot Payment Collection Without Holding Funds

2026-09-14 · AgentPay VN

ai agentspayment integrationvietqrpython sdkchatbot

The Problem: Why Most AI Payment Systems Fail

Imagine you've built an AI chatbot that sells online courses. A customer asks to buy your $50 Python masterclass. Your chatbot generates a checkout link, the customer pays—and now you're stuck.

Your payment processor holds the funds for 3–5 days. Your customer support inbox floods with "Where's my access?" messages. You're manually transferring money between accounts. And if the payment processor's API goes down, your entire sales funnel stops.

Worse: you're now a money handler. That means compliance headaches, PCI audits, and the liability that comes with holding customer funds.

This is the reality for thousands of developers building AI-powered sales bots, course platforms, and subscription services. Traditional payment integrations were never designed for the speed and autonomy of AI agents.

There's a better way.

Introducing AgentPay VN: Payments Without the Risk

AgentPay VN is an open-source Python SDK (MIT license) + MCP server that lets your AI agents accept Vietnamese VietQR payments—without ever touching the money.

Here's the fundamental difference:

The magic: AgentPay VN generates a VietQR code that routes straight to your bank account. No middleman. No holding period. When the bank confirms settlement, your agent gets an instant webhook notification.

It's three lines of logic:

  1. Create a payment request
  2. Send the customer a checkout URL
  3. Await settlement confirmation

That's it. Now let's build it.

Setting Up AgentPay VN in 5 Minutes

Installation

Start with pip:

pip install agentpay-vn

For AI agent integration (Claude, etc.), also install the MCP server:

pip install agentpay-vn[mcp]

Verify the installation:

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

You're ready. No API keys. No merchant onboarding. Just your bank account details.

Your First Payment Flow: Code Walkthrough

Step 1: Create a Payment Request

from agentpay_vn import AgentPayClient

# Initialize the client with your merchant details
client = AgentPayClient(
    merchant_id="MERCHANT_12345",
    merchant_name="My AI Course Store",
    bank_account="0123456789",
    bank_code="970407"  # Vietcombank code
)

# Create a payment request for a $50 course purchase
payment = client.create_payment_request(
    amount=50.00,  # USD equivalent; AgentPay auto-converts to VND
    currency="USD",
    description="Python Masterclass - Full Access",
    customer_id="user_42",
    metadata={
        "product_id": "course_python_101",
        "course_name": "Python Masterclass",
        "access_hours": 72  # Grant access for 72 hours after payment
    }
)

print(f"Payment ID: {payment.id}")
print(f"Checkout URL: {payment.checkout_url}")
print(f"VietQR Code: {payment.qr_code}")

Line-by-line breakdown:

Step 2: Send the Checkout URL to Your Customer

Now your chatbot sends the link:

# In your chatbot message handler
customer_message = "I want to buy the Python Masterclass."

# Agent processes the request
payment = client.create_payment_request(
    amount=50.00,
    currency="USD",
    description="Python Masterclass - Full Access",
    customer_id=user.id,
    metadata={"product_id": "course_python_101"}
)

# Send response to user
bot_response = f"""
Great choice! 🎓

Your checkout link: {payment.checkout_url}

Or scan this QR code:
{payment.qr_code}

I'll grant access as soon as your bank confirms payment (usually 10–30 seconds).
"""

send_to_user(bot_response)

The customer clicks the link or scans the QR. Their banking app opens. They confirm the payment to your bank account. The transaction is complete.

Step 3: Await Settlement & Grant Access

import asyncio
from agentpay_vn import settle_wait

async def handle_payment_settlement(payment_id: str, user_id: str):
    """
    Wait for bank settlement confirmation.
    Once confirmed, grant course access.
    """

    # Poll for settlement (or use webhooks—see below)
    settlement = await settle_wait(
        payment_id=payment_id,
        timeout_seconds=300  # Wait up to 5 minutes
    )

    if settlement.status == "confirmed":
        # Payment confirmed by bank
        print(f"✓ Payment confirmed: {settlement.amount} VND")

        # Grant course access
        grant_course_access(
            user_id=user_id,
            product_id="course_python_101",
            duration_hours=72
        )

        # Notify agent/user
        send_to_user(f"""
        Payment confirmed! 🎉

        Your course access is active for 72 hours.
        Dashboard: https://my-course-app.com/dashboard
        """)
    else:
        print(f"Payment failed: {settlement.error}")

# In your chatbot, trigger this after sending checkout URL
asyncio.create_task(
    handle_payment_settlement(payment.id, user.id)
)

What's happening:

Integrating AgentPay with AI Agents: The MCP Approach

For Claude, ChatGPT, or other AI agents, AgentPay provides an MCP (Model Context Protocol) server. This lets your AI autonomously handle payments.

MCP Server Configuration

Create a mcp_config.json in your agent's config directory:

{
  "mcpServers": {
    "agentpay": {
      "command": "agentpay-mcp",
      "env": {
        "MERCHANT_ID": "MERCHANT_12345",
        "MERCHANT_NAME": "My AI Course Store",
        "BANK_ACCOUNT": "0123456789",
        "BANK_CODE": "970407",
        "WEBHOOK_SECRET": "your_webhook_secret_here"
      }
    }
  }
}

Now your Claude instance can call AgentPay tools directly:

# Claude's available tools (auto-generated from MCP)
# - create_payment_request(amount, currency, description, customer_id, metadata)
# - check_settlement_status(payment_id)
# - list_payments(limit, offset)
# - refund_payment(payment_id, reason)

Your Claude agent can now think: "User wants a course. I'll create a payment request, send the link, and follow up when it's settled." Fully autonomous.

Real-World Example: An AI Course-Selling Bot

Let's build a complete scenario. You're running an online course platform with an AI chatbot front-end.

The User Journey

  1. User: "I want to buy your JavaScript course."
  2. Bot: "Sure! That's $79. Here's your payment link: [URL]. I'll wait for confirmation."
  3. User: Clicks link, scans QR with banking app, pays.
  4. Bot (within 30 seconds): "Confirmed! Your course is unlocked. Start lesson 1: [Link]"

Implementation

from agentpay_vn import AgentPayClient
import asyncio

class AICourseBot:
    def __init__(self):
        self.client = AgentPayClient(
            merchant_id="COURSE_BOT_001",
            merchant_name="AI Academy",
            bank_account="0123456789",
            bank_code="970407"
        )
        self.courses = {
            "javascript_101": {"name": "JavaScript 101", "price": 79.00},
            "python_ml": {"name": "Python for ML", "price": 99.00},
        }

    async def sell_course(self, user_id: str, course_key: str):
        course = self.courses[course_key]

        # Step 1: Create payment
        payment = self.client.create_payment_request(
            amount=course["price"],
            currency="USD",
            description=f"Course: {course['name']}",
            customer_id=user_id,
            metadata={"course_key": course_key, "course_name": course["name"]}
        )

        # Step 2: Send to user
        self.send_message(user_id, f"""
        Great! {course['name']} costs ${course['price']}.

        Pay here: {payment.checkout_url}

        I'm waiting for confirmation...
        """)

        # Step 3: Wait for settlement
        settlement = await self.client.await_settlement(payment.id, timeout=300)

        if settlement.status == "confirmed":
            # Grant access
            self.grant_course_access(user_id, course_key)
            self.send_message(user_id, f"""
            ✓ Payment received!

            Your {course['name']} course is now active.
            Start here: https://academy.ai/courses/{course_key}
            """)
        else:
            self.send_message(user_id, "Payment failed. Try again?")

    def send_message(self, user_id: str, text: str):
        # Your messaging backend (Slack, Telegram, etc.)
        print(f"[To {user_id}] {text}")

    def grant_course_access(self, user_id: str, course_key: str):
        # Your database logic
        print(f"Granted {course_key} to {user_id}")

# Usage
bot = AICourseBot()
asyncio.run(bot.sell_course("user_42", "python_ml"))

This bot: - Never holds customer money - Grants access within 30 seconds of payment - Scales to thousands of concurrent transactions - Requires zero compliance overhead

Do's and Don'ts: AgentPay Best Practices

✅ Do ❌ Don't
Store payment_id for each transaction Assume settlement is instant; use await_settlement()
Include descriptive metadata for auditing Collect payment details yourself
Use webhooks for production (faster than polling) Hardcode merchant credentials in code; use env vars
Test with small amounts first ($1–$5) Create multiple payment requests for the same customer without clearing old ones
Handle failed settlements gracefully Forget to validate the settlement.amount matches your request
Use different customer_id per unique user Process refunds without checking refund_status

Advanced Tips

Webhooks for Real-Time Notifications

Instead of polling with await_settlement(), set up a webhook:

# Your webhook endpoint
@app.post("/webhooks/agentpay")
async def agentpay_webhook(request: Request):
    data = await request.json()
    payment_id = data["payment_id"]
    status = data["status"]  # "confirmed" or "failed"

    if status == "confirmed":
        # Grant access immediately
        grant_course_access(data["customer_id"], data["metadata"]["course_key"])

    return {"ok": True}

# Register webhook with AgentPay
client.register_webhook(
    url="https://myapp.com/webhooks/agentpay",
    secret="your_webhook_secret"
)

Webhooks are fired instantly (no polling delay). Ideal for high-volume sales.

Refunds and Reversals

# Initiate a refund
refund = client.refund_payment(
    payment_id="pay_abc123",
    reason="Customer requested cancellation"
)

print(f"Refund status: {refund.status}")  # "pending" → "completed"

Refunds are processed to the customer's bank within 1–2 business days.

Currency Support

AgentPay auto-converts USD, EUR, GBP to VND using live rates:

# These all work:
client.create_payment_request(amount=50.00, currency="USD")   # ~1,250,000 VND
client.create_payment_request(amount=50.00, currency="EUR")   # ~1,450,000 VND
client.create_payment_request(amount=50.00, currency="GBP")   # ~1,550,000 VND

Frequently Asked Questions

Q: Does AgentPay hold my money? No. The QR code routes directly to your bank account. Settlement is confirmed by your bank, not AgentPay.

Q: What's the settlement time? Typically 10–30 seconds after the customer completes the bank transfer. AgentPay receives the bank's confirmation via feed integration.

Q: Can I use AgentPay with non-Vietnamese banks? Currently, AgentPay supports Vietnamese banks (Vietcombank, Techcombank, etc.). International bank accounts are on the roadmap.

Q: What happens if a payment fails? The customer's bank will decline the transaction. settle_wait() returns with status="failed" and an error code. You can retry or offer support.

Q: Do I need to do anything for PCI compliance? No. You never see or store credit card numbers. All transactions are routed through bank transfers (VietQR). You're not a payment processor in the regulatory sense.

Key Takeaways

Next Steps

Ready to build? Start here:

  1. Install AgentPay VN: bash pip install agentpay-vn

  2. Explore the full docs: https://agentpay.servicesai.vn/v1/docs

  3. See the source code: https://github.com/phuocdu/agentpay-vn

  4. Try a demo: Clone the repo and run examples/course_bot.py to see it in action.

Your AI chatbot can now sell courses, ebooks, software licenses, and digital services—without ever touching customer funds. Build faster. Ship safer. Scale confidently.

Happy selling! 🚀

Get started →

← All posts