Tài liệu API

API Charging v2

Hướng dẫn kết nối gửi thẻ cào

Tài liệu này dùng cho Merchant cần gửi thẻ, kiểm tra trạng thái giao dịch và lấy biểu phí theo tài khoản.

Endpoint chính
https://hoangvistore.com/chargingws/v2

1. Tổng quan tích hợp

Endpoint chính https://hoangvistore.com/chargingws/v2
API biểu phí https://hoangvistore.com/chargingws/v2/getfee?partner_id=YOUR_PARTNER_ID
Method khuyến nghị POST
Kiểu dữ liệu khuyến nghị application/x-www-form-urlencoded hoặc JSON
Lệnh hỗ trợ charging, check

2. Điều kiện trước khi gọi API

  • Bạn cần có partner_id và partner_key từ khu vực Merchant trước khi gọi API.
  • Nếu Merchant bật IP whitelist thì request phải gửi từ đúng IP đã cấu hình.
  • Với command charging, request_id phải là duy nhất theo từng partner_id.
  • Với command check, hãy dùng lại đúng request_id của giao dịch đã gửi trước đó.
  • Nên gửi telco, serial, code ở dạng sạch, đúng chuẩn để hệ thống xử lý nhanh và dễ đối soát.

3. Công thức tạo sign

Công thức khuyến nghị cho charging
md5(partner_key . code . command . partner_id . request_id . serial . telco)

Đây là công thức nên ưu tiên dùng khi gửi thẻ.

Công thức khuyến nghị cho check
md5(partner_key . command . partner_id . request_id)

Phù hợp cho lệnh kiểm tra trạng thái giao dịch.

Công thức tương thích cũ
md5(partner_key . code . serial)

API vẫn hỗ trợ để tương thích ngược với client legacy.

4. Tham số cho lệnh charging

Trường Bắt buộc Ví dụ Mô tả
command Bắt buộc charging Lệnh gửi thẻ lên hệ thống.
partner_id Bắt buộc YOUR_PARTNER_ID Mã Merchant của bạn.
request_id Bắt buộc NAPTHE_20260403_001 Mã giao dịch phía bạn tự sinh và không được trùng.
telco Bắt buộc VIETTEL Mã nhà mạng.
amount Bắt buộc 100000 Mệnh giá bạn khai báo.
serial Bắt buộc 10006139342354 Serial của thẻ.
code Bắt buộc 114384960423544 Mã nạp hoặc PIN của thẻ.
sign Bắt buộc md5(...) Chữ ký xác thực request.

5. Tham số cho lệnh check

Trường Bắt buộc Ví dụ Mô tả
command Bắt buộc check Lệnh kiểm tra trạng thái giao dịch.
partner_id Bắt buộc YOUR_PARTNER_ID Mã Merchant của bạn.
request_id Bắt buộc NAPTHE_20260403_001 request_id đã dùng ở lệnh charging.
sign Bắt buộc md5(...) Khuyến nghị dùng md5(partner_key . command . partner_id . request_id).
telco / serial / code Không bắt buộc VIETTEL / 10006139342354 / 114384960423544 Có thể truyền thêm để tương thích ngược.

6. Ví dụ payload

command=charging
{
    "command": "charging",
    "partner_id": "YOUR_PARTNER_ID",
    "request_id": "NAPTHE_20260403_001",
    "telco": "VIETTEL",
    "amount": "100000",
    "serial": "10006139342354",
    "code": "114384960423544",
    "sign": "md5(partner_key . code . command . partner_id . request_id . serial . telco)"
}
command=check
{
    "command": "check",
    "partner_id": "YOUR_PARTNER_ID",
    "request_id": "NAPTHE_20260403_001",
    "sign": "md5(partner_key . command . partner_id . request_id)"
}

7. Cấu trúc phản hồi

trans_id ID giao dịch trong hệ thống.
request_id Mã giao dịch phía Merchant gửi sang.
amount Số tiền thực nhận về ví sau khi xử lý.
value Mệnh giá thật được xác nhận.
declared_value Mệnh giá Merchant khai báo lúc gửi thẻ.
telco Nhà mạng của thẻ.
serial Serial thẻ đã gửi.
code Mã thẻ đã gửi.
status Trạng thái thẻ hoặc mã lỗi API.
callback_sign Chữ ký phản hồi: md5(partner_key . code . serial).
message Mô tả trạng thái hoặc lỗi.

8. Ví dụ response

Pending
{
    "trans_id": 123456,
    "request_id": "NAPTHE_20260403_001",
    "amount": 0,
    "value": 0,
    "declared_value": "100000",
    "telco": "VIETTEL",
    "serial": "10006139342354",
    "code": "114384960423544",
    "status": 99,
    "callback_sign": "md5(partner_key . code . serial)",
    "message": "PENDING"
}
Success
{
    "trans_id": 123456,
    "request_id": "NAPTHE_20260403_001",
    "amount": 81000,
    "value": 100000,
    "declared_value": 100000,
    "telco": "VIETTEL",
    "serial": "10006139342354",
    "code": "114384960423544",
    "status": 1,
    "callback_sign": "1d55e0d5f8b4e8f815a3efbb9f5c7b21",
    "message": "VALID_CARD"
}
Error
{
    "status": 102,
    "message": "Dữ liệu xác thực không hợp lệ hoặc chữ ký sign sai."
}

9. Trạng thái thẻ

Status Tên Mô tả
99 PENDING Thẻ đang chờ xử lý hoặc chờ nhà cung cấp trả kết quả.
1 VALID_CARD Thẻ đúng, giao dịch thành công.
2 CARD_WRONG_VALUE Thẻ đúng nhưng sai mệnh giá khai báo.
3 INVALID_CARD Thẻ không hợp lệ hoặc dữ liệu thẻ sai.
4 MAINTENANCE Nhà mạng hoặc cổng xử lý đang bảo trì.

10. Mã lỗi ở mức request

100 Lỗi xử lý chung hoặc không thể tạo giao dịch.
101 Không tìm thấy giao dịch khi gọi command check.
102 Sai xác thực request, sai IP, sai sign hoặc dữ liệu đầu vào không hợp lệ.
103 Có ngoại lệ trong quá trình xử lý request.
104 Command không hợp lệ. Chỉ hỗ trợ charging và check.

11. API biểu phí và mệnh giá hỗ trợ

Dùng endpoint sau để lấy biểu phí theo Merchant:

https://hoangvistore.com/chargingws/v2/getfee?partner_id=YOUR_PARTNER_ID

Không cần sign. Response là biểu phí theo nhóm giá của tài khoản (thành viên / đại lý / đối tác), nhóm theo nhà mạng: {"VIETTEL":[{"telco":"VIETTEL","value":10000,"fees":17,"penalty":50}]}. fees: % phí trừ trên mệnh giá thật; penalty: % phạt khi sai mệnh giá (tính trên mệnh giá nhỏ hơn).

Callback kết quả thẻ

Khi thẻ có kết quả cuối (status 1, 2, 3, 4), hệ thống gửi về Đường dẫn nhận dữ liệu khai ở trang Kết nối API, đúng kiểu GET (tham số trên URL) hoặc POST (JSON) đã chọn. Nội dung giống response của command check, kèm callback_sign = md5(partner_key . code . serial). Hãy kiểm tra chữ ký này và chống xử lý trùng theo request_id trước khi cộng tiền.

Trả về HTTP 200 để xác nhận đã nhận. Lỗi hoặc quá 10 giây thì hệ thống gửi lại sau 1, 2, 5, 15, 30, 60 phút rồi dừng; khi đó dùng command check để đối soát.

Lưu ý tích hợp

  • status trong response có thể là trạng thái thẻ hoặc mã lỗi ở mức request, nên cần đọc kèm message.
  • sign luôn bắt buộc; sai sign, sai IP whitelist hoặc kết nối đang bị khoá đều trả status 102.
  • request_id không được dùng lại; gửi trùng trả status 100.
  • Nên gọi API getfee trước khi dựng form nạp thẻ phía frontend để lấy đúng biểu phí và mệnh giá hỗ trợ.

Nhà mạng đang hỗ trợ

Viettel
VIETTEL
10.000 20.000 30.000 50.000 100.000 200.000 300.000 500.000 1.000.000
Vinaphone
VINAPHONE
10.000 20.000 30.000 50.000 100.000 200.000 300.000 500.000
Mobifone
MOBIFONE
10.000 20.000 30.000 50.000 100.000 200.000 300.000 500.000
Vietnamobile
VNMOBI
10.000 20.000 30.000 50.000 100.000 200.000 300.000 500.000
Zing
ZING
10.000 20.000 50.000 100.000 200.000 500.000 1.000.000
Garena
GARENA
5.000 10.000 20.000 50.000 100.000 200.000 500.000
Vcoin
VCOIN
10.000 20.000 50.000 100.000 200.000 300.000 500.000 1.000.000 2.000.000 5.000.000 10.000.000
Scoin
SCOIN
10.000 20.000 50.000 100.000 200.000 500.000 1.000.000 2.000.000 5.000.000

12. Code mẫu theo ngôn ngữ

PHP
<?php
$endpoint = 'https://hoangvistore.com/chargingws/v2';
$partnerId = 'YOUR_PARTNER_ID';
$partnerKey = 'YOUR_PARTNER_KEY';
$requestId = 'NAPTHE_20260403_001';

$payload = [
    'command' => 'charging',
    'partner_id' => $partnerId,
    'request_id' => $requestId,
    'telco' => 'VIETTEL',
    'amount' => '100000',
    'serial' => '10006139342354',
    'code' => '114384960423544',
];

$payload['sign'] = md5(
    $partnerKey .
    $payload['code'] .
    $payload['command'] .
    $payload['partner_id'] .
    $payload['request_id'] .
    $payload['serial'] .
    $payload['telco']
);
C#
var sign = Md5(
    partnerKey +
    code +
    "charging" +
    partnerId +
    requestId +
    serial +
    telco
);

var payload = new Dictionary<string, string>
{
    ["command"] = "charging",
    ["partner_id"] = partnerId,
    ["request_id"] = requestId,
    ["telco"] = telco,
    ["amount"] = "100000",
    ["serial"] = serial,
    ["code"] = code,
    ["sign"] = sign,
};
Java
String sign = md5(
    partnerKey + code + "charging" + partnerId + requestId + serial + telco
);

Map<String, String> payload = new LinkedHashMap<>();
payload.put("command", "charging");
payload.put("partner_id", partnerId);
payload.put("request_id", requestId);
payload.put("telco", telco);
payload.put("amount", "100000");
payload.put("serial", serial);
payload.put("code", code);
payload.put("sign", sign);
Node.js
const sign = md5(
  partnerKey + code + 'charging' + partnerId + requestId + serial + telco
);

const payload = {
  command: 'charging',
  partner_id: partnerId,
  request_id: requestId,
  telco,
  amount: '100000',
  serial,
  code,
  sign,
};
Python
payload = {
    "command": "charging",
    "partner_id": partner_id,
    "request_id": request_id,
    "telco": telco,
    "amount": "100000",
    "serial": serial,
    "code": code,
}

payload["sign"] = md5(
    partner_key + code + "charging" + partner_id + request_id + serial + telco
)
API Recharge

Hướng dẫn nạp tiền dịch vụ

Tài liệu này dành cho Merchant cần topup dịch vụ, kiểm tra trạng thái, lấy số dư, danh sách sản phẩm và bảng phí.

Endpoint chính
https://hoangvistore.com/api/rechargews

1. Tổng quan tích hợp

Endpoint chính https://hoangvistore.com/api/rechargews
Method khuyến nghị POST
Kiểu dữ liệu khuyến nghị application/json
Lệnh hỗ trợ topup, getstatus, getbalance, productlist, canceltopup, feetopup

2. Điều kiện trước khi gọi API

  • Bạn cần có partner_id và partner_key từ Merchant trước khi gọi API.
  • Kết nối phải đang hoạt động (không bị quản trị viên khoá) và ví đủ số dư cho đơn topup.
  • IP gửi request phải nằm trong whitelist được phép.
  • Với lệnh topup, request_id phải là duy nhất để tránh tạo trùng giao dịch.
  • Nên gọi productlist trước để biết đúng service_code và cấu trúc account_info cần truyền.

3. Công thức tạo sign

topup và getstatus
md5(partner_key . partner_id . command . request_id)

Dùng cho các lệnh có request_id bắt buộc.

getbalance, productlist, feetopup
md5(partner_key . partner_id . command)

Các lệnh này không dùng request_id trong bước xác thực sign.

canceltopup
md5(partner_key . partner_id . command)

Lệnh huỷ nhận cả md5(partner_key . partner_id . command . request_id).

4. Chi tiết từng lệnh

1. Lệnh topup

Tạo giao dịch nạp tiền dịch vụ cho tài khoản đích.

Trường Bắt buộc Ví dụ Mô tả
command Bắt buộc topup Tên lệnh gọi API.
partner_id Bắt buộc YOUR_PARTNER_ID Mã Merchant của bạn.
request_id Bắt buộc TOPUP_20260403_001 Mã giao dịch do phía bạn tự sinh.
service_code Bắt buộc VINA-DATA Mã dịch vụ lấy từ productlist.
amount Bắt buộc 100000 Giá trị cần nạp.
account_info Bắt buộc {"phone":"0987654321"} Thông tin tài khoản nhận nạp, tùy theo sản phẩm.
sign Bắt buộc md5(...) Chữ ký xác thực request.
Ví dụ request
{
    "command": "topup",
    "partner_id": "YOUR_PARTNER_ID",
    "request_id": "TOPUP_20260403_001",
    "service_code": "VINA-DATA",
    "amount": 100000,
    "account_info": {
        "phone": "0987654321"
    },
    "sign": "md5(partner_key . partner_id . command . request_id)"
}
Ví dụ response
{
    "status": "success",
    "message": "Thành công",
    "data": {
        "time": "2026-04-03 14:30:00",
        "request_id": "TOPUP_20260403_001",
        "account": {
            "phone": "0987654321"
        },
        "order_code": "RE240403001",
        "pay_amount": 95000,
        "discount": 5,
        "service_code": "VINA-DATA",
        "amount": 100000,
        "status": "pending"
    }
}
2. Lệnh getstatus

Tra cứu trạng thái giao dịch recharge đã tạo trước đó.

Trường Bắt buộc Ví dụ Mô tả
command Bắt buộc getstatus Tên lệnh gọi API.
partner_id Bắt buộc YOUR_PARTNER_ID Mã Merchant của bạn.
request_id Bắt buộc TOPUP_20260403_001 request_id của giao dịch đã gửi.
order_code Bắt buộc RE240403001 Mã đơn hàng hệ thống trả về sau khi tạo giao dịch.
sign Bắt buộc md5(...) Chữ ký xác thực request.
Ví dụ request
{
    "command": "getstatus",
    "partner_id": "YOUR_PARTNER_ID",
    "request_id": "TOPUP_20260403_001",
    "order_code": "RE240403001",
    "sign": "md5(partner_key . partner_id . command . request_id)"
}
Ví dụ response
{
    "status": "success",
    "message": "Thành công",
    "data": {
        "account": {
            "phone": "0987654321"
        },
        "request_value": 100000,
        "amount": 100000,
        "request_id": "TOPUP_20260403_001",
        "order_code": "RE240403001",
        "status": "completed"
    }
}
3. Lệnh getbalance

Lấy số dư ví Merchant đang dùng để thanh toán recharge.

Trường Bắt buộc Ví dụ Mô tả
command Bắt buộc getbalance Tên lệnh gọi API.
partner_id Bắt buộc YOUR_PARTNER_ID Mã Merchant của bạn.
sign Bắt buộc md5(...) Chữ ký không dùng request_id.
Ví dụ request
{
    "command": "getbalance",
    "partner_id": "YOUR_PARTNER_ID",
    "sign": "md5(partner_key . partner_id . command)"
}
Ví dụ response
{
    "status": "success",
    "message": "Thành công",
    "data": {
        "balance": 1200000,
        "currency": "VND"
    }
}
4. Lệnh productlist

Lấy danh sách dịch vụ, mệnh giá, giá bán và các option nhập liệu.

Trường Bắt buộc Ví dụ Mô tả
command Bắt buộc productlist Tên lệnh gọi API.
partner_id Bắt buộc YOUR_PARTNER_ID Mã Merchant của bạn.
sign Bắt buộc md5(...) Chữ ký không dùng request_id.
Ví dụ request
{
    "command": "productlist",
    "partner_id": "YOUR_PARTNER_ID",
    "sign": "md5(partner_key . partner_id . command)"
}
Ví dụ response
{
    "status": "success",
    "message": "Thành công",
    "data": [
        {
            "name": "Nạp data VinaPhone",
            "service_code": "VINA-DATA",
            "items": [
                {
                    "name": "Gói 100.000đ",
                    "value": 100000,
                    "price": 95000,
                    "discount": 5
                }
            ],
            "options": [
                {
                    "key": "phone",
                    "name": "Số điện thoại",
                    "type": "text"
                }
            ]
        }
    ]
}
5. Lệnh canceltopup

Tra khả năng huỷ đơn. Đơn đã chuyển sang nhà cung cấp thì không huỷ được (trả cancel_not_supported); đơn đã có kết quả trả order_finished. Đơn thất bại luôn được tự hoàn tiền về ví.

Trường Bắt buộc Ví dụ Mô tả
command Bắt buộc canceltopup Tên lệnh gọi API.
partner_id Bắt buộc YOUR_PARTNER_ID Mã Merchant của bạn.
request_id Bắt buộc TOPUP_20260403_001 request_id của giao dịch cần hủy.
order_code Bắt buộc RE240403001 Mã đơn hàng cần hủy.
sign Bắt buộc md5(...) md5(partner_key . partner_id . command), hoặc ghép thêm request_id.
Ví dụ request
{
    "command": "canceltopup",
    "partner_id": "YOUR_PARTNER_ID",
    "request_id": "TOPUP_20260403_001",
    "order_code": "RE240403001",
    "sign": "md5(partner_key . partner_id . command)"
}
Ví dụ response
{
    "status": "cancel_not_supported",
    "message": "Đơn đã gửi sang nhà cung cấp nên không huỷ được. Đơn thất bại sẽ tự hoàn tiền về ví.",
    "data": {
        "request_id": "TOPUP_20260403_001",
        "order_code": "RE240403001",
        "status": "pending"
    }
}
6. Lệnh feetopup

Lấy bảng giá và chiết khấu theo Merchant.

Trường Bắt buộc Ví dụ Mô tả
command Bắt buộc feetopup Tên lệnh gọi API.
partner_id Bắt buộc YOUR_PARTNER_ID Mã Merchant của bạn.
sign Bắt buộc md5(...) Chữ ký không dùng request_id.
Ví dụ request
{
    "command": "feetopup",
    "partner_id": "YOUR_PARTNER_ID",
    "sign": "md5(partner_key . partner_id . command)"
}
Ví dụ response
{
    "status": "success",
    "message": "Thành công",
    "data": [
        {
            "key": "VINA-DATA",
            "value": 100000,
            "price": 95000,
            "discount": 5
        }
    ]
}

5. Ghi chú về phản hồi

  • Recharge API trả về khung JSON gồm status, message và data.
  • Trường status là chuỗi, riêng lỗi sai IP trả số 114.
  • data.status của đơn: pending đang xử lý, completed thành công, failed thất bại (đã hoàn tiền về ví).
  • Nên xử lý luồng nghiệp vụ theo status, không chỉ dựa vào message.

6. Trạng thái thường gặp

success Request hợp lệ và xử lý thành công.
command_invalid Lệnh command không nằm trong danh sách hỗ trợ.
wrong_post_data Thiếu hoặc sai dữ liệu đầu vào bắt buộc.
product_not_found Không tìm thấy service_code tương ứng.
account_info_not_correct account_info không đúng định dạng mong muốn.
payment_fail Thanh toán ví thất bại.
order_not_found Không tìm thấy đơn hàng cần tra cứu hoặc hủy.
wrong_signature Sai chữ ký sign.
114 IP gọi API không nằm trong whitelist cho phép.
duplicate_request_idrequest_id đã được dùng cho đơn khác. Dùng getstatus để tra cứu.
topup_failNhà cung cấp từ chối hoặc lỗi kết nối. Nếu đơn đã tạo thì tiền đã hoàn về ví, data kèm mã đơn.
cancel_not_supportedĐơn đang xử lý, không huỷ được qua API.
order_finishedĐơn đã có kết quả, không huỷ được.
partner_not_foundpartner_id không tồn tại.
merchant_inactiveKết nối đang bị khoá hoặc không có quyền dùng API topup.
system_errorLỗi hệ thống, thử lại sau.

7. Code mẫu theo ngôn ngữ

PHP
<?php
$payload = [
    'command' => 'topup',
    'partner_id' => 'YOUR_PARTNER_ID',
    'request_id' => 'TOPUP_20260403_001',
    'service_code' => 'VINA-DATA',
    'amount' => 100000,
    'account_info' => ['phone' => '0987654321'],
];

$payload['sign'] = md5(
    $partnerKey . $payload['partner_id'] . $payload['command'] . $payload['request_id']
);
C#
var payload = new Dictionary<string, object>
{
    ["command"] = "topup",
    ["partner_id"] = partnerId,
    ["request_id"] = requestId,
    ["service_code"] = "VINA-DATA",
    ["amount"] = 100000,
    ["account_info"] = new Dictionary<string, object> { ["phone"] = "0987654321" },
};

payload["sign"] = Md5(partnerKey + partnerId + "topup" + requestId);
Java
String sign = md5(partnerKey + partnerId + "topup" + requestId);

String payload = """
{
  "command": "topup",
  "partner_id": "%s",
  "request_id": "%s",
  "service_code": "VINA-DATA",
  "amount": 100000,
  "account_info": {"phone": "0987654321"},
  "sign": "%s"
}
""".formatted(partnerId, requestId, sign);
Node.js
const payload = {
  command: 'topup',
  partner_id: partnerId,
  request_id: requestId,
  service_code: 'VINA-DATA',
  amount: 100000,
  account_info: { phone: '0987654321' },
};

payload.sign = md5(partnerKey + partnerId + payload.command + requestId);
Python
payload = {
    "command": "topup",
    "partner_id": partner_id,
    "request_id": request_id,
    "service_code": "VINA-DATA",
    "amount": 100000,
    "account_info": {"phone": "0987654321"},
}

payload["sign"] = md5(partner_key + partner_id + payload["command"] + request_id)

Lưu ý tích hợp

  • Nên gọi productlist trước khi topup để xác định đúng service_code, mệnh giá và option đầu vào.
  • Sau khi tạo đơn topup, status trong data thường là pending vì hệ thống còn gọi sang nhà cung cấp.
  • Dịch vụ khách tự nhập số tiền có trường amount_rule (min, max, step) trong productlist; amount gửi lên phải nằm trong hạn mức đó.
  • account_info chỉ nhận đúng các key trong options của productlist; thiếu key bắt buộc trả account_info_not_correct.

API liên quan

Callback kết quả đơn topup

Khi đơn có kết quả cuối (completed / failed), hệ thống gửi về Đường dẫn nhận dữ liệu của kết nối (GET hoặc POST JSON) nội dung giống data của getstatus, kèm callback_sign = md5(partner_key . request_id . order_code). Trả HTTP 200 để xác nhận; lỗi thì hệ thống gửi lại sau 1, 2, 5, 15, 30, 60 phút.

API Softcard

Hướng dẫn mua mã thẻ điện tử

Tài liệu này dùng để mua card, tải lại đơn đã mua, kiểm tra tồn kho, lấy số dư ví và danh sách sản phẩm.

Endpoint chính
https://hoangvistore.com/api/cardws

1. Tổng quan tích hợp

Endpoint chính https://hoangvistore.com/api/cardws
API danh sách sản phẩm https://hoangvistore.com/api/cardws/products?partner_id=YOUR_PARTNER_ID
Method POST cho /api/cardws, GET cho /api/cardws/products
Kiểu dữ liệu khuyến nghị application/json
Lệnh hỗ trợ buycard, redownload, checkavailable, getbalance

2. Điều kiện trước khi gọi API

  • Merchant phải được cấp quyền dùng module Softcard và đang hoạt động.
  • sign luôn bắt buộc và phải khớp công thức của từng lệnh.
  • Nếu kết nối có khai IP whitelist thì request phải gửi từ đúng IP đó.
  • Với buycard và redownload, request_id phải là mã riêng để tránh trùng đơn.
  • wallet_number là số ví hiển thị ở trang Kết nối API (dạng VND000000012), phải đúng ví của kết nối.

3. Công thức tạo sign

buycard và redownload
md5(partner_key . partner_id . command . request_id)

Áp dụng cho các lệnh có request_id bắt buộc.

checkavailable và getbalance
md5(partner_key . partner_id . command)

Dùng cho các lệnh không cần request_id.

4. Chi tiết từng lệnh

1. Lệnh buycard

Mua mã thẻ điện tử và nhận card ngay nếu hệ thống xử lý thành công.

Trường Bắt buộc Ví dụ Mô tả
command Bắt buộc buycard Tên lệnh gọi API.
partner_id Bắt buộc YOUR_PARTNER_ID Mã Merchant của bạn.
request_id Bắt buộc CARD_20260403_001 Mã giao dịch do phía bạn tự sinh.
service_code Bắt buộc VIETTEL Mã sản phẩm cần mua.
value Bắt buộc 100000 Mệnh giá thẻ.
qty Bắt buộc 2 Số lượng thẻ cần mua, phải là số nguyên dương.
wallet_number Bắt buộc VND000000012 Số ví của kết nối, xem ở trang Kết nối API.
sign Bắt buộc md5(...) Chữ ký xác thực request.
Ví dụ request
{
    "command": "buycard",
    "partner_id": "YOUR_PARTNER_ID",
    "request_id": "CARD_20260403_001",
    "service_code": "VIETTEL",
    "value": 100000,
    "qty": 2,
    "wallet_number": "VND000000012",
    "sign": "md5(partner_key . partner_id . command . request_id)"
}
Ví dụ response
{
    "status": 1,
    "message": "Mua thẻ thành công",
    "data": {
        "cards": [
            {
                "name": "Thẻ Viettel 100.000",
                "serial": "10006139342354",
                "code": "114384960423544",
                "expired": "2027-12-31"
            }
        ],
        "request_id": "CARD_20260403_001",
        "order_code": "SC240403001"
    }
}
2. Lệnh redownload

Tải lại thông tin card của đơn hàng đã mua trước đó.

Trường Bắt buộc Ví dụ Mô tả
command Bắt buộc redownload Tên lệnh gọi API.
partner_id Bắt buộc YOUR_PARTNER_ID Mã Merchant của bạn.
request_id Bắt buộc CARD_20260403_001 request_id đã dùng khi mua thẻ.
sign Bắt buộc md5(...) Chữ ký xác thực request.
Ví dụ request
{
    "command": "redownload",
    "partner_id": "YOUR_PARTNER_ID",
    "request_id": "CARD_20260403_001",
    "sign": "md5(partner_key . partner_id . command . request_id)"
}
Ví dụ response
{
    "status": 1,
    "message": "Mua thẻ thành công",
    "data": {
        "cards": [
            {
                "name": "Thẻ Viettel 100.000",
                "serial": "10006139342354",
                "code": "114384960423544",
                "expired": "2027-12-31"
            }
        ],
        "request_id": "CARD_20260403_001",
        "order_code": "SC240403001"
    }
}
3. Lệnh checkavailable

Kiểm tra tồn kho sản phẩm trước khi mua.

Trường Bắt buộc Ví dụ Mô tả
command Bắt buộc checkavailable Tên lệnh gọi API.
partner_id Bắt buộc YOUR_PARTNER_ID Mã Merchant của bạn.
service_code Bắt buộc VIETTEL Mã sản phẩm cần kiểm tra.
value Bắt buộc 100000 Mệnh giá thẻ cần kiểm tra.
qty Bắt buộc 5 Số lượng muốn kiểm tra tồn kho.
sign Bắt buộc md5(...) Chữ ký xác thực request.
Ví dụ request
{
    "command": "checkavailable",
    "partner_id": "YOUR_PARTNER_ID",
    "service_code": "VIETTEL",
    "value": 100000,
    "qty": 5,
    "sign": "md5(partner_key . partner_id . command)"
}
Ví dụ response
{
    "stock_available": true,
    "VIETTEL-100000": "Còn hàng"
}
4. Lệnh getbalance

Lấy số dư của ví Merchant đang dùng để mua card.

Trường Bắt buộc Ví dụ Mô tả
command Bắt buộc getbalance Tên lệnh gọi API.
partner_id Bắt buộc YOUR_PARTNER_ID Mã Merchant của bạn.
wallet_number Bắt buộc VND000000012 Số ví của kết nối, xem ở trang Kết nối API.
sign Bắt buộc md5(...) Chữ ký xác thực request.
Ví dụ request
{
    "command": "getbalance",
    "partner_id": "YOUR_PARTNER_ID",
    "wallet_number": "VND000000012",
    "sign": "md5(partner_key . partner_id . command)"
}
Ví dụ response
{
    "balance": 2500000,
    "currency_code": "VND"
}

5. API danh sách sản phẩm

Dùng endpoint sau để lấy danh sách sản phẩm và mệnh giá hỗ trợ:

https://hoangvistore.com/api/cardws/products?partner_id=YOUR_PARTNER_ID
Ví dụ response
[
    {
        "name": "Viettel",
        "slug": "viettel",
        "service_code": "VIETTEL",
        "image": "/uploads/softcard/viettel.png",
        "cardvalue": [
            {
                "service_code": "VIETTEL",
                "value": 100000,
                "price": 97000,
                "id": 10
            }
        ]
    }
]

6. Ghi chú về phản hồi

  • buycard và redownload trả về JSON theo khung status, message, data.
  • checkavailable trả về JSON trực tiếp gồm stock_available và thông tin tồn kho.
  • getbalance trả về JSON trực tiếp gồm balance và currency_code.
  • API /api/cardws/products trả về mảng sản phẩm JSON trực tiếp.

7. Bảng mã trạng thái

1 Mua thẻ thành công hoặc tải lại card thành công.
2 Đơn hàng đang chờ xử lý.
3 Đơn hàng đã hủy và hoàn tiền.
102 Số dư ví không đủ.
109 request_id đã tồn tại.
114 Merchant gọi sai IP đăng ký.
116 Sai chữ ký sign.
118 Sản phẩm đã hết.
129 Đơn hàng không tồn tại.
130 Lỗi lấy thẻ từ nguồn cung cấp. Tiền đã được hoàn về ví.
113partner_id không tồn tại, kết nối đang bị khoá hoặc không có quyền dùng API mua thẻ.
117Sai dữ liệu: thiếu request_id, qty ngoài 1–10, sai wallet_number, sai service_code/value hoặc command.

8. Code mẫu theo ngôn ngữ

PHP
<?php
$payload = [
    'command' => 'buycard',
    'partner_id' => 'YOUR_PARTNER_ID',
    'request_id' => 'CARD_20260403_001',
    'service_code' => 'VIETTEL',
    'value' => 100000,
    'qty' => 2,
    'wallet_number' => 'VND000000012',
];

$payload['sign'] = md5(
    $partnerKey . $payload['partner_id'] . $payload['command'] . $payload['request_id']
);
C#
var payload = new Dictionary<string, object>
{
    ["command"] = "buycard",
    ["partner_id"] = partnerId,
    ["request_id"] = requestId,
    ["service_code"] = "VIETTEL",
    ["value"] = 100000,
    ["qty"] = 2,
    ["wallet_number"] = walletNumber,
};

payload["sign"] = Md5(partnerKey + partnerId + "buycard" + requestId);
Java
String sign = md5(partnerKey + partnerId + "buycard" + requestId);

String payload = """
{
  "command": "buycard",
  "partner_id": "%s",
  "request_id": "%s",
  "service_code": "VIETTEL",
  "value": 100000,
  "qty": 2,
  "wallet_number": "%s",
  "sign": "%s"
}
""".formatted(partnerId, requestId, walletNumber, sign);
Node.js
const payload = {
  command: 'buycard',
  partner_id: partnerId,
  request_id: requestId,
  service_code: 'VIETTEL',
  value: 100000,
  qty: 2,
  wallet_number: walletNumber,
};

payload.sign = md5(partnerKey + partnerId + payload.command + requestId);
Python
payload = {
    "command": "buycard",
    "partner_id": partner_id,
    "request_id": request_id,
    "service_code": "VIETTEL",
    "value": 100000,
    "qty": 2,
    "wallet_number": wallet_number,
}

payload["sign"] = md5(partner_key + partner_id + payload["command"] + request_id)

Lưu ý tích hợp

  • Nên gọi API products trước để lấy đúng service_code và mệnh giá hợp lệ.
  • buycard sẽ trừ tiền ví Merchant rồi cố gắng lấy card ngay từ hệ thống hoặc nhà cung cấp.
  • redownload chỉ nên dùng khi request_id cũ đã mua thành công.
  • checkavailable thường được dùng để kiểm tra tồn kho trước khi cho phép đặt mua số lượng lớn.

API liên quan

API sản phẩm
https://hoangvistore.com/api/cardws/products?partner_id=YOUR_PARTNER_ID

Lấy danh sách sản phẩm Softcard và các mệnh giá theo service_code.

Kết quả mua thẻ

buycard trả thẻ ngay trong response, không có callback. Mất kết nối giữa chừng thì gọi redownload với cùng request_id để lấy lại thẻ (không trừ tiền thêm).