Skip to content

API tra cứu mã số thuế

Tra cứu tên người nộp thuế, địa chỉ và trạng thái để hỗ trợ điền thông tin người mua hóa đơn. API không tạo hoặc phát hành hóa đơn.

Request

http
GET https://api.pay2s.vn/userapi/tax-lookup?mst=0317646674
pay2s-token: BASE64_SECRET_KEY
Accept: application/json
Thành phầnBắt buộcÝ nghĩa
Query mstChuỗi mã số thuế; giữ số 0 đầu, không chuyển thành số
Header pay2s-tokenBase64 chuẩn của chuỗi Secret Key UTF-8, mã hóa đúng một lần

API tra cứu dùng GET, không gửi JSON body. POST tới đường dẫn này không dùng để tra cứu.

Mã doanh nghiệp được hỗ trợ: 10 hoặc 13 chữ số, hoặc mã đơn vị phụ thuộc dạng 0123456789-001. Tra cứu mã định danh cá nhân 12 số chỉ dành cho tài khoản được Pay2S phê duyệt riêng; tài khoản chưa được cấp quyền nhận HTTP 403.

Tài khoản cần gói đang hoạt động, hỗ trợ từ Basic trở lên; gói Free35 không được dùng. Secret Key cửa hàng cũng được hỗ trợ khi khóa và cửa hàng đang hoạt động, kiểm tra gói của tài khoản chủ.

pay2s-token là gì?

text
pay2s-token = Base64(UTF8(Secret Key))

Đây không phải JWT, không phải Access Key, không phải token đăng nhập Dashboard và không phải Base64(accessKey:secretKey). Không thêm tiền tố Bearer hoặc Basic. Không dùng HMAC hay bộ header X-Signature của API tạo hóa đơn điện tử.

Ví dụ minh họa, không phải khóa dùng thật:

text
Secret Key:  example-secret
pay2s-token: ZXhhbXBsZS1zZWNyZXQ=

Nếu đã có token Base64 đúng định dạng thì dùng trực tiếp, không mã hóa lần hai. Base64 có thể giải mã ngược nên token phải được bảo vệ như Secret Key: chỉ dùng trên backend, không đặt trong URL, frontend hoặc log.

Postman

Đặt pay2sSecretKey vào biến bí mật của môi trường Postman. Thêm Pre-request Script:

js
const secret = pm.environment.get('pay2sSecretKey');
if (!secret) throw new Error('Thiếu pay2sSecretKey');
pm.variables.set('pay2sToken', CryptoJS.enc.Base64.stringify(CryptoJS.enc.Utf8.parse(secret)));

Trong Headers, đặt pay2s-token bằng . Phần Authorization chọn No Auth; không dùng đồng thời token đăng nhập hay Bearer tự sinh.

Ví dụ gọi API

cURL

PAY2S_TOKEN là token đã tạo từ Secret Key, lưu trong môi trường server:

bash
curl --get 'https://api.pay2s.vn/userapi/tax-lookup' \
  --data-urlencode 'mst=0317646674' \
  --header "pay2s-token: $PAY2S_TOKEN" \
  --header 'Accept: application/json'

Node.js (backend)

js
async function lookupTaxCode(mst) {
  const secret = process.env.PAY2S_SECRET_KEY;
  if (!secret) throw new Error('Thiếu PAY2S_SECRET_KEY');
  const url = new URL('https://api.pay2s.vn/userapi/tax-lookup');
  url.searchParams.set('mst', mst); // mst là chuỗi, giữ số 0 đầu
  const response = await fetch(url, {
    headers: {
      'pay2s-token': Buffer.from(secret, 'utf8').toString('base64'),
      Accept: 'application/json'
    },
    signal: AbortSignal.timeout(30000)
  });
  const result = await response.json();
  if (!response.ok || result.status !== true) {
    throw new Error(`${response.status}: ${result.message || 'Tra cứu thất bại'}`);
  }
  return result.data;
}

const taxpayer = await lookupTaxCode('0317646674');
// Hiển thị thông tin để người dùng kiểm tra; không tự phát hành hóa đơn ở đây.

PHP

php
$secret = getenv('PAY2S_SECRET_KEY');
if (!$secret) throw new RuntimeException('Thiếu PAY2S_SECRET_KEY');
$url = 'https://api.pay2s.vn/userapi/tax-lookup?' . http_build_query(['mst' => '0317646674']);
$ch = curl_init($url);
curl_setopt_array($ch, [
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_CONNECTTIMEOUT => 10,
    CURLOPT_TIMEOUT => 30,
    CURLOPT_HTTPHEADER => ['pay2s-token: ' . base64_encode($secret), 'Accept: application/json'],
]);
$body = curl_exec($ch);
$http = curl_getinfo($ch, CURLINFO_HTTP_CODE);
$error = curl_error($ch);
curl_close($ch);
if ($body === false) throw new RuntimeException($error);
$result = json_decode($body, true, 512, JSON_THROW_ON_ERROR);
if ($http !== 200 || ($result['status'] ?? false) !== true) {
    throw new RuntimeException($result['message'] ?? 'Tra cứu thất bại');
}
$taxpayer = $result['data'];

Response thành công

HTTP 200, ví dụ theo cấu trúc hiện tại:

json
{
  "status": true,
  "message": "Tra cứu mã số thuế thành công.",
  "data": {
    "taxCode": "0317646674",
    "companyName": "CÔNG TY TNHH CÔNG NGHỆ EZ",
    "address": "Số 72, Đường số 6, KDC Cityland Park Hills, Phường Gò Vấp, Thành phố Hồ Chí Minh, Việt Nam",
    "status": {"code": "00", "name": "NNT đã được cấp MST"},
    "canIssueInvoice": true
  },
  "meta": {"fresh": true},
  "request_id": "TAX-20260918090000-1234ABCD"
}

Tên/địa chỉ trong ví dụ là dữ liệu minh họa theo ảnh kết quả, không phải kết quả vừa tra cứu trực tiếp.

TrườngÝ nghĩa
status ngoài cùngRequest tra cứu có thành công hay không
data.taxCodeMã số thuế tìm được
data.companyNameTên người nộp thuế/đơn vị
data.addressĐịa chỉ do nguồn tra cứu trả về
data.status.codeMã trạng thái người nộp thuế, chuỗi; giữ nguyên "00"
data.status.nameMô tả trạng thái từ nguồn tra cứu
data.canIssueInvoiceCờ khả năng xuất hóa đơn từ nguồn tra cứu; không có nghĩa đã phát hành hoặc đã được bật quyền Production trên Pay2S
meta.freshBản hiện tại tra cứu mới, không dùng kết quả cache
request_idMã đối soát khi liên hệ hỗ trợ; cũng có ở header X-Request-ID khi vào bước tra cứu

Bản phản hồi cũ có thể dùng meta.cached: false thay meta.fresh: true. Không dùng các trường meta để quyết định thanh toán hoặc phát hành hóa đơn.

Không nhầm status: true ngoài cùng với trạng thái thuế hợp lệ. Luồng tự động HĐĐT trên Pay2S chỉ tiếp tục với mã trạng thái thuế "00"; cần kiểm tra thông tin/mẫu và quyền phát hành như bình thường.

Lỗi và giới hạn

HTTPCách xử lý
401Thiếu/sai pay2s-token; kiểm tra Secret Key, Base64 đúng một lần, không thêm Bearer
403Gói hết hạn/không đủ điều kiện hoặc chưa được cấp quyền tra cứu mã cá nhân
404Không tìm thấy thông tin mã số thuế
422MST sai định dạng
429Vượt giới hạn tốc độ/ngày; đợi theo header Retry-After hoặc retry_after trong JSON
502 / 504Nguồn tra cứu lỗi/timeout; thử lại có giãn cách, không tự kết luận MST sai
503Dịch vụ phụ trợ chưa sẵn sàng; thử lại sau hoặc liên hệ hỗ trợ

Giới hạn tốc độ được trả trong X-RateLimit-Limit, X-RateLimit-Remaining; hạn mức ngày trong X-Daily-RateLimit-Limit, X-Daily-RateLimit-Remaining. Đọc giá trị server trả về, không gọi lặp liên tục khi nhận 429.

Sau khi người dùng kiểm tra kết quả:

Kết quả tra cứuMetadata Collection Link V2API tạo nháp HĐĐT
taxCodecustomerInfo.taxCodebuyer_tax_code
companyName (đơn vị/doanh nghiệp)customerInfo.buyerCompanyNamebuyer_name
addresscustomerInfo.addressbuyer_address

Không tự gán tên doanh nghiệp vào họ tên người liên hệ. Với cá nhân/hộ kinh doanh, kiểm tra đúng loại người mua trước khi ánh xạ.

Xem Collection Link V2, API hóa đơn điện tửquy tắc dữ liệu người mua. Nếu Collection Link đã tự xử lý HĐĐT cho đơn, không đồng thời gọi tạo hóa đơn độc lập cho cùng đơn.