Add VietQR Checkout to Your LLM Agent in 10 Minutes

2026-07-27 · AgentPay VN

agentpayvietqrpythonllm-agentspayments

The Problem: Your AI Agent Can't Actually Close a Sale

You've built an impressive LLM agent. It answers questions, recommends products, even negotiates terms. But the moment a customer says "I want to buy," your agent hits a wall. It can't process payments. It can't confirm the transaction. It hands off to a clunky payment modal, losing the conversational flow—and worse, losing trust.

Imagine a course-selling chatbot: a student chats with your Claude-powered agent, decides to enroll, and then... the agent says "please go to this link." The magic evaporates. Or a coffee shop's Telegram bot that recommends a specialty blend but can't let you pay right there in the chat.

This friction costs sales. And it shouldn't exist.

That's where AgentPay VN steps in. It's a Python SDK + MCP server that lets your AI agent generate a VietQR payment link, send it to the customer, and confirm settlement—all in 10 minutes of setup. No money passes through your servers. The QR code points straight at the merchant's bank account. A bank feed confirms when the customer paid. You're just the middleman orchestrating the flow.

How AgentPay VN Works (The 60-Second Version)

AgentPay VN is built on three core ideas:

  1. No money touching your servers. VietQR is a national QR standard in Vietnam that routes payments directly to the merchant's bank account. AgentPay just creates the link.
  2. Agents as payment orchestrators. Your LLM agent decides when and why to collect payment, then calls AgentPay's tools. The settlement happens asynchronously—your agent doesn't wait for the bank.
  3. Bank feeds close the loop. Once the customer pays, the bank notifies AgentPay (via a feed integration). Your agent or backend can then trigger fulfillment: send the course link, unlock the product, etc.

The flow in pseudocode:

Agent receives "I want to buy"
  → calls create_payment_request(amount, description)
  → gets back a checkout_url (VietQR)
  → sends URL to customer
  → calls await_settlement(request_id) [async]
  → bank feed confirms payment
  → Agent sends product/course link

No webhooks to manage. No PCI compliance headaches. No holding customer funds.

Step 1: Install & Set Up AgentPay VN

This takes 90 seconds.

pip install agentpay-vn

That's it. The SDK is MIT-licensed and open-source on GitHub: https://github.com/phuocdu/agentpay-vn

Next, grab your merchant credentials. Head to https://agentpay.servicesai.vn/v1/docs and register your merchant account. You'll receive:

Store these as environment variables:

export AGENTPAY_MERCHANT_ID="your_merchant_id"
export AGENTPAY_API_KEY="your_api_key"
export AGENTPAY_ACCOUNT_NUMBER="your_account_number"
export AGENTPAY_BANK_CODE="your_bank_code"

Step 2: Create Your First Payment Request

Here's the core pattern. Let's say your agent is selling a digital course:

from agentpay_vn import AgentPayClient
import os
import asyncio

# Initialize the client (reads env vars automatically)
client = AgentPayClient(
    merchant_id=os.getenv("AGENTPAY_MERCHANT_ID"),
    api_key=os.getenv("AGENTPAY_API_KEY"),
    account_number=os.getenv("AGENTPAY_ACCOUNT_NUMBER"),
    bank_code=os.getenv("AGENTPAY_BANK_CODE")
)

# Agent decides to collect payment
async def agent_collect_payment(customer_name: str, amount_vnd: int, description: str):
    """
    Called by the LLM agent when a customer wants to buy.
    Returns a VietQR checkout URL to send to the customer.
    """
    # Step 1: Create a payment request
    payment_request = await client.create_payment_request(
        amount=amount_vnd,              # e.g., 199000 (199k VND)
        description=description,        # e.g., "Python Advanced Course"
        customer_identifier=customer_name,  # used for tracking
        metadata={"course_id": "PY_ADV_001"}
    )

    # Step 2: Extract the checkout URL
    checkout_url = payment_request["checkout_url"]
    request_id = payment_request["request_id"]

    # Step 3: Send to customer (agent does this via chat/SMS/email)
    message = f"Click here to pay: {checkout_url}"
    print(f"[Agent] Sent to {customer_name}: {message}")

    # Step 4: Start waiting for settlement (non-blocking)
    asyncio.create_task(wait_and_fulfill(request_id, customer_name))

    return {
        "status": "payment_sent",
        "request_id": request_id,
        "checkout_url": checkout_url
    }

async def wait_and_fulfill(request_id: str, customer_name: str):
    """
    Waits for the bank to confirm payment, then triggers fulfillment.
    """
    # Step 1: Block until settlement confirmed
    settlement = await client.await_settlement(
        request_id=request_id,
        timeout_seconds=3600  # wait up to 1 hour
    )

    # Step 2: Settlement confirmed by bank feed
    if settlement["status"] == "completed":
        print(f"[Agent] {customer_name} paid {settlement['amount']} VND")
        # Step 3: Agent can now fulfill (send course link, unlock product, etc.)
        print(f"[Agent] Sending course link to {customer_name}...")
        # In real code: send email, update database, etc.
    else:
        print(f"[Agent] Payment failed or expired: {settlement['status']}")

# Simulate: customer buys a course
async def main():
    result = await agent_collect_payment(
        customer_name="Nguyen Van A",
        amount_vnd=199000,
        description="Python Advanced Course"
    )
    print(result)

    # Keep the script running so async tasks complete
    await asyncio.sleep(5)

if __name__ == "__main__":
    asyncio.run(main())

What each line does:

Step 3: Integrate with Your LLM Agent (Claude via MCP)

If you're using Claude as your agent backbone, use the AgentPay MCP server. This exposes payment functions as tools Claude can call directly.

Install the MCP server:

pip install agentpay-mcp

Configure Claude to use it. In your claude_config.json (or equivalent):

{
  "mcpServers": {
    "agentpay": {
      "command": "agentpay-mcp",
      "env": {
        "AGENTPAY_MERCHANT_ID": "${AGENTPAY_MERCHANT_ID}",
        "AGENTPAY_API_KEY": "${AGENTPAY_API_KEY}",
        "AGENTPAY_ACCOUNT_NUMBER": "${AGENTPAY_ACCOUNT_NUMBER}",
        "AGENTPAY_BANK_CODE": "${AGENTPAY_BANK_CODE}"
      }
    }
  }
}

Now Claude can call these tools in conversation:

Example Claude prompt:

You are an AI course advisor. When a student decides to enroll,
call the agentpay:create_payment_request tool to generate a
payment link. Send it in your message. Then use
agentpay:check_settlement to confirm payment before sending
the course access link.

Claude will now autonomously handle the entire payment flow in one conversation—no handoff, no friction.

Real-World Walkthrough: An Online Coffee Shop Bot

Let's say you run a specialty coffee roastery and want a Telegram bot that recommends blends and sells them.

The conversation:

Customer: What coffee would you recommend for a dark roast lover?
Bot (Claude Agent): I'd suggest our Dak Lak Dark Blend—rich, earthy,
  with hints of chocolate. It's 250g for 189,000 VND.

Customer: That sounds perfect. Can I buy it?
Bot: Absolutely! Here's your checkout link: [VietQR QR code]
  Just scan with your banking app and pay 189,000 VND.

[Customer scans, pays via their bank app]

Bot: Payment confirmed! Your Dak Lak Dark Blend is being roasted
  and will ship tomorrow. Tracking: [#TRK123]. Thank you!

Behind the scenes (your code):

  1. Bot receives "Can I buy it?"
  2. Agent calls create_payment_request(amount=189000, description="Dak Lak Dark Blend 250g", customer_identifier=telegram_user_id)
  3. VietQR checkout URL is generated and sent to customer
  4. Agent calls await_settlement(request_id) (non-blocking)
  5. Bank feed notifies AgentPay when money arrives
  6. Agent sends shipping confirmation + tracking link
  7. Your warehouse fulfills the order

No payment gateway integration. No PCI scope. No chargeback headaches. Just a conversational payment flow that feels native.

Do's & Don'ts

Do Don't
Call create_payment_request only after the customer confirms they want to buy Try to process multiple payments for the same order—generate one request per transaction
Use await_settlement in a background task so your agent stays responsive Assume await_settlement returns immediately; it's blocking until confirmed
Store the request_id in your database to link payments to orders Lose track of request IDs—you need them to check settlement status
Test with small amounts (e.g., 10,000 VND) before going live Regenerate a checkout URL for the same request_id; it won't work
Set a reasonable timeout in await_settlement (e.g., 3600 seconds = 1 hour) Wait forever—customers might walk away after paying; set a timeout

Advanced Tips

Metadata & Custom Fields

Store arbitrary data in metadata for tracking:

payment_request = await client.create_payment_request(
    amount=99000,
    description="Ebook: AI for Beginners",
    customer_identifier="user_12345",
    metadata={
        "ebook_id": "AI_101",
        "customer_email": "alice@example.com",
        "promo_code": "LAUNCH20"
    }
)

When settlement arrives, this metadata is returned, so you can instantly send the right product to the right email.

Handling Timeouts

If a customer pays after your await_settlement timeout, use check_settlement to verify:

settlement_status = await client.check_settlement(request_id)
if settlement_status["status"] == "completed":
    # Process the order now
else:
    # Still pending or failed

Multiple Currencies (Future)

AgentPay VN currently handles VND. If you need multi-currency, store the exchange rate in your agent's context and convert accordingly before calling create_payment_request.

Troubleshooting

Q: I created a payment request but the checkout_url is not working. A: Verify your merchant credentials are correct in the env vars. Try a test request with amount=10000 (10k VND) first.

Q: How long does await_settlement take? A: Depends on the customer's bank and how fast the bank feed updates AgentPay. Typically 30 seconds to 5 minutes. For instant confirmation, ask the customer to screenshot their bank confirmation.

Q: What if the customer pays the wrong amount? A: VietQR locks the amount in the QR code. If they pay more, you'll see the overage in the settlement response. You can issue a refund or apply it as credit.

Q: Can I refund a payment? A: Yes, but refunds go through your bank's system (not AgentPay). After settlement confirmation, initiate a bank transfer back to the customer's account.

FAQ

Q: Does AgentPay hold my money? A: No. AgentPay never touches funds. Payments go straight to your merchant bank account via VietQR. AgentPay only orchestrates the request and tracks settlement via the bank feed.

Q: What happens if my agent crashes after sending a payment request? A: The payment request remains valid. When your agent restarts, call check_settlement(request_id) to see if the customer paid. If they did, proceed with fulfillment.

Q: Can I use AgentPay with agents other than Claude? A: Yes. The Python SDK works with any LLM that your code orchestrates (e.g., GPT-4, Llama, etc.). The MCP server is Claude-specific, but the SDK is agent-agnostic.

Q: Is there a fee? A: AgentPay itself is MIT-licensed and free. VietQR payments may incur standard bank transfer fees (typically 0–1% depending on your bank). No AgentPay-specific markup.

Key Takeaways

Get Started Now

Install AgentPay VN:

pip install agentpay-vn

Read the full docs: https://agentpay.servicesai.vn/v1/docs

Explore the open-source code: https://github.com/phuocdu/agentpay-vn

Next step: Register your merchant account at the docs link, grab your credentials, and try the first code example above. Within 10 minutes, you'll have a payment-ready AI agent.

Your customers won't believe they can buy something, pay, and get access—all without leaving the chat. That's the future of conversational commerce. Start building it today.

Get started →

← All posts