Accept your first QR payment in 7 lines of code
The TConnect API requires AES-256-CBC encryption on every request and JWT token management. Instead of handling those parts yourself, use the official SDK — a single file that bundles encryption, login, automatic token refresh, and every endpoint. You just call create_qr(...).
Step 1 — Prepare your credentials
TConnect provides you with the following (Staging environment):
| Item | Used for |
|---|---|
partner_code | Merchant identifier |
username / password | JWT login |
client_id / client_secret | JWT login |
secret_key | AES-256 key (hex string) to encrypt requests |
service_code / va / bincode | From Get Services — used when creating a QR |
Step 2 — Download the SDK (1 file, copy into your project)
- Python
- Node.js
- Java
- PHP
📥 Download tconnect.py · Install dependencies: pip install requests cryptography
📥 Download tconnect.js · Requires Node 18+ · no npm package needed
📥 Download TConnect.java · Java 11+ · JDK standard library only
📥 Download tconnect.php · PHP 7.4+ · uses the built-in openssl + curl
Step 3 — Create a QR (7 lines)
- Python
- Node.js
- Java
- PHP
- cURL (raw)
from tconnect import TConnect
client_id="...", client_secret="...", secret_key="<AES_HEX_KEY>",
service_code="vccb-qr", va="VA100023312", bincode="970454")
qr = tc.create_qr(order_id="ORDER123", amount=150000) # auto login + encrypt + call the API
print(qr["image_png_base64"]) # drop into <img src="data:image/png;base64,...">
const { TConnect } = require("./tconnect");
const tc = new TConnect({ partnerCode: "81234567", username: "[email protected]", password: "Password#123",
clientId: "...", clientSecret: "...", secretKey: "<AES_HEX_KEY>",
serviceCode: "vccb-qr", va: "VA100023312", bincode: "970454" });
const qr = await tc.createQr({ orderId: "ORDER123", amount: 150000 });
console.log(qr.image_png_base64);
TConnect tc = TConnect.builder()
.partnerCode("81234567").username("[email protected]").password("Password#123")
.clientId("...").clientSecret("...").secretKey("<AES_HEX_KEY>")
.serviceCode("vccb-qr").va("VA100023312").bincode("970454").build();
String qr = tc.createQr("ORDER123", 150000, null, null, null, null); // returns JSON with image_png_base64 + qr_content
System.out.println(qr);
require "tconnect.php";
$tc = new TConnect(["partnerCode" => "81234567", "username" => "[email protected]", "password" => "Password#123",
"clientId" => "...", "clientSecret" => "...", "secretKey" => "<AES_HEX_KEY>",
"serviceCode" => "vccb-qr", "va" => "VA100023312", "bincode" => "970454"]);
$qr = $tc->createQr("ORDER123", 150000);
echo $qr["image_png_base64"];
# The raw API requires you to encrypt the AES payload before calling — 3 steps:
# 1) Login for an access_token 2) Encrypt the body 3) Call create-qr
curl -X POST https://sme-open-api-sandbox.tconnect.vn/openapi/v1/transaction/qr/generate \
-H "partner-code: 81234567" \
-H "x-service-code: vccb-qr" \
-H "Authorization: Bearer <access_token>" \
-H "Content-Type: application/json" \
-d '{"data":"<AES_ENCRYPTED_PAYLOAD>"}'
With cURL you must encrypt the AES payload and manage the token yourself. See AES Encryption. The SDK in the other tabs does all of this for you.
Step 4 — Receive the payment result (IPN webhook)
When the customer pays, TConnect calls your webhook with an encrypted payload. The SDK decrypts it in one line:
- Python
- Node.js
- Java
- PHP
# Inside your webhook route (Flask/FastAPI/Django...)
event = tc.parse_ipn(request.body) # -> {"order_id": "...", "amount": ..., ...}
# Reconcile event["order_id"] + event["amount"], update the order, return HTTP 200
// Inside your webhook route (Express...)
const event = tc.parseIpn(req.body); // -> { order_id, amount, ... }
// Reconcile order_id + amount, update the order, res.sendStatus(200)
String event = tc.parseIpn(requestBody); // decrypted JSON: {"order_id":...,"amount":...}
// Reconcile order_id + amount, update the order, return HTTP 200
$event = $tc->parseIpn(file_get_contents("php://input")); // -> ["order_id"=>..., "amount"=>...]
// Reconcile order_id + amount, update the order, return HTTP 200
Before marking an order as paid, compare the amount in the IPN with the original order amount. Details: IPN Callback.
What else can the SDK do?
Beyond create_qr and parse_ipn, the SDK wraps every endpoint:
| Task | Python / Node / PHP / Java |
|---|---|
| List services | get_services() / getServices() |
| Create a Virtual Account (VA) | create_va() / createVa() |
| Push payment to a POS (card) / Soundbox | push_to_device() / pushToDevice() |
| Create / cancel an Ecom payment link | create_payment_link() · cancel_payment_link() / createPaymentLink() · cancelPaymentLink() |
| Get QR transactions | get_qr_transactions() / getQrTransactions() |
| Look up by Order ID | check_qr_order() / checkQrOrder() |
| Card / cash transactions | get_card_transactions() · get_cash_transactions() |
Next steps
- 👉 Full API reference — reference for every endpoint
- 👉 AES Encryption — details if you want to implement it yourself
- 👉 IPN Callback — handling the webhook
The SDK here is a single-file reference implementation for fast integration. You can adapt it to your project. Official packages (pip / npm / composer) will be released later.