API mua thẻ

SandboxĐang bật: chỉ mô phỏng trong trình duyệt, không gửi yêu cầu nào lên máy chủ, không trừ hay cộng tiền.

cardws

Mua mã thẻ#

Mua mã thẻ điện tử, tải lại đơn đã mua, kiểm tra tồn kho, lấy số dư và danh sách sản phẩm.

Tổng quan#

Mọi lệnh gửi tới một endpoint, phân biệt bằng tham số command. Gửi POST với thân JSON (form urlencoded cũng được nhận). Danh sách sản phẩm lấy qua một endpoint GET riêng.

Endpoint
https://thepay1s.com/api/cardws
Danh sách sản phẩm
https://thepay1s.com/api/cardws/products?partner_id=YOUR_PARTNER_ID
Phương thức
POST (lệnh), GET (danh sách sản phẩm)
Kiểu dữ liệu
application/json
Lệnh
buycard, redownload, checkavailable, getbalance

Điều kiện

  • Kết nối API có loại Mua mã thẻ và đang hoạt động; tài khoản sở hữu và ví không bị khoá.
  • Kết nối Mua mã thẻ bắt buộc khai báo Địa chỉ IP. Yêu cầu từ IP khác, hoặc khi danh sách trống, bị từ chối với status=114.
  • wallet_number là số ví của tài khoản sở hữu kết nối, xem ở trang Kết nối API.
  • request_id của buycard là duy nhất trong tài khoản; trùng trả status=109. Dùng lại request_id đó cho redownload.
  • API không gọi callback. Đơn trả status=2 thì gọi redownload sau ít phút để nhận mã thẻ.

Ghi chú tương thích

  • status trả về là chuỗi số (1, 2, 116…); nên ép sang số trước khi so sánh.
  • Số dư không đủ trả 121, không tìm thấy đơn trả 103, hết hàng hoặc bảo trì trả 118.
  • Hạn dùng của thẻ nằm ở trường expire.
  • API sản phẩm trả thêm discount theo từng mệnh giá, imgurl đầy đủ và mô tả sản phẩm.

Chữ ký#

sign là MD5 của Partner Key ghép với Partner ID, tên lệnh và (với buycard, redownload) request_id. API danh sách sản phẩm không cần chữ ký.

Công thứcLệnh
md5(partner_key + partner_id + command + request_id)buycard, redownload
md5(partner_key + partner_id + command)checkavailable, getbalance
Ghép liền theo đúng thứ tự, không dấu phân cách; dấu + chỉ minh hoạ phép nối chuỗi. Kết quả là chuỗi hex 32 ký tự, không phân biệt hoa thường. Chữ ký luôn được kiểm, trừ khi quản trị viên tắt kiểm tra chữ ký cho kết nối của bạn.

Ví dụ tính chữ ký

Với Partner Key giả định YOUR_PARTNER_KEY và Partner ID ở các ví dụ:

md5(partner_key + partner_id + command + request_id)Chuỗi trước khi bămYOUR_PARTNER_KEYYOUR_PARTNER_IDbuycardCARD20261024001Kết quả32c58a3753c5d13822ee35ead1c9dfc4
md5(partner_key + partner_id + command)Chuỗi trước khi bămYOUR_PARTNER_KEYYOUR_PARTNER_IDgetbalanceKết quả1a4651ad1fc33b21b9a5dabf410c7f79

buycard#

Mua mã thẻ điện tử. Tiền được trừ khỏi ví khi tạo đơn; thẻ có sẵn được trả ngay trong phản hồi.

POSThttps://thepay1s.com/api/cardws
  • commandchuỗiBắt buộcTên lệnh, đúng như tên mục.
  • partner_idchuỗiBắt buộcPartner ID của kết nối.
  • request_idchuỗiBắt buộcMã đơn phía bạn. Lệnh buycard: mã mới, duy nhất trong tài khoản. Lệnh redownload: request_id đã dùng khi mua.
  • service_codechuỗiBắt buộcMã sản phẩm, lấy từ API danh sách sản phẩm.
  • valuesố nguyênBắt buộcMệnh giá thẻ (VND), là một value trong cardvalue của sản phẩm.
  • qtysố nguyênBắt buộcSố lượng thẻ, số nguyên dương.
  • wallet_numberchuỗiBắt buộcSố ví thanh toán của tài khoản sở hữu kết nối.
  • signchuỗiBắt buộcChữ ký md5(partner_key + partner_id + command + request_id), xem mục Chữ ký.
{
    "command": "buycard",
    "partner_id": "YOUR_PARTNER_ID",
    "request_id": "CARD20261024001",
    "service_code": "VIETTEL",
    "value": 100000,
    "qty": 2,
    "wallet_number": "4821061234",
    "sign": "32c58a3753c5d13822ee35ead1c9dfc4"
}
  • Số tiền trừ ví: total_price = value × (100 − discount) / 100 × qty, với discount theo nhóm của tài khoản (xem API danh sách sản phẩm).
  • Thẻ trong kho được trả ngay với status=1. Nếu phải lấy từ nhà cung cấp mà chưa có thẻ, đơn trả status=2: tiền đã trừ, gọi redownload sau để nhận thẻ.
  • qty tối đa theo cấu hình của hệ thống (mặc định 10 thẻ mỗi đơn); vượt mức trả status=125.
  • Gửi lại cùng request_id trả status=109 và không trừ tiền lần hai; dùng redownload để lấy đơn đã mua.

redownload#

Lấy lại mã thẻ của một đơn đã mua, hoặc nhận thẻ của đơn đang chờ.

POSThttps://thepay1s.com/api/cardws
  • commandchuỗiBắt buộcTên lệnh, đúng như tên mục.
  • partner_idchuỗiBắt buộcPartner ID của kết nối.
  • request_idchuỗiBắt buộcMã đơn phía bạn. Lệnh buycard: mã mới, duy nhất trong tài khoản. Lệnh redownload: request_id đã dùng khi mua.
  • signchuỗiBắt buộcChữ ký md5(partner_key + partner_id + command + request_id), xem mục Chữ ký.
{
    "command": "redownload",
    "partner_id": "YOUR_PARTNER_ID",
    "request_id": "CARD20261024001",
    "sign": "068d7702f03666aae248ca16b0b072a7"
}
  • Dùng khi mất kết nối lúc mua, khi đơn trả status=2, hoặc khi cần xem lại mã thẻ.
  • Đơn đã có thẻ trả status=1; đang chờ trả status=2; đã huỷ và hoàn tiền trả status=3; thất bại chưa hoàn tiền trả status=102.

checkavailable#

Kiểm tra tồn kho của một mệnh giá trước khi mua.

POSThttps://thepay1s.com/api/cardws
  • commandchuỗiBắt buộcTên lệnh, đúng như tên mục.
  • partner_idchuỗiBắt buộcPartner ID của kết nối.
  • service_codechuỗiBắt buộcMã sản phẩm, lấy từ API danh sách sản phẩm.
  • valuesố nguyênBắt buộcMệnh giá thẻ (VND), là một value trong cardvalue của sản phẩm.
  • qtysố nguyênBắt buộcSố lượng thẻ, số nguyên dương.
  • signchuỗiBắt buộcChữ ký md5(partner_key + partner_id + command), xem mục Chữ ký.
{
    "command": "checkavailable",
    "partner_id": "YOUR_PARTNER_ID",
    "service_code": "VIETTEL",
    "value": 100000,
    "qty": 2,
    "sign": "5cdd77a9a2175621c73c6c0cf25e21ab"
}
  • Không giữ hàng: tồn kho có thể thay đổi trước khi bạn gọi buycard. Phản hồi là JSON trực tiếp, không có khung status.

getbalance#

Lấy số dư ví dùng để mua thẻ.

POSThttps://thepay1s.com/api/cardws
  • commandchuỗiBắt buộcTên lệnh, đúng như tên mục.
  • partner_idchuỗiBắt buộcPartner ID của kết nối.
  • wallet_numberchuỗiBắt buộcSố ví thanh toán của tài khoản sở hữu kết nối.
  • signchuỗiBắt buộcChữ ký md5(partner_key + partner_id + command), xem mục Chữ ký.
{
    "command": "getbalance",
    "partner_id": "YOUR_PARTNER_ID",
    "wallet_number": "4821061234",
    "sign": "1a4651ad1fc33b21b9a5dabf410c7f79"
}
  • wallet_number phải là số ví của tài khoản sở hữu kết nối. Phản hồi là JSON trực tiếp, không có khung status.

Danh sách sản phẩm#

Lấy danh sách sản phẩm đang bán và mệnh giá. Gọi GET, không cần chữ ký, chỉ cần partner_id trên query string. IP gọi phải nằm trong danh sách IP của kết nối.

GEThttps://thepay1s.com/api/cardws/products?partner_id=YOUR_PARTNER_ID
  • partner_idchuỗiBắt buộcPartner ID của kết nối có loại Mua mã thẻ.Ví dụ: YOUR_PARTNER_ID
curl 'https://thepay1s.com/api/cardws/products?partner_id=YOUR_PARTNER_ID'
[
    {
        "name": "Viettel",
        "slug": "viettel",
        "service_code": "VIETTEL",
        "image": "/uploads/softcard/viettel.png",
        "short_description": null,
        "description": null,
        "imgurl": "https://thepay1s.com/uploads/softcard/viettel.png",
        "cardvalue": [
            {
                "service_code": "VIETTEL",
                "value": 50000,
                "id": 10,
                "discount": "2.5"
            },
            {
                "service_code": "VIETTEL",
                "value": 100000,
                "id": 11,
                "discount": "2.5"
            }
        ]
    }
]

Các trường

  • name
    Kiểu
    chuỗi
    Mô tả
    Tên sản phẩm.
  • slug
    Kiểu
    chuỗi
    Mô tả
    Đường dẫn rút gọn của sản phẩm.
  • service_code
    Kiểu
    chuỗi
    Mô tả
    Mã sản phẩm, gửi trong service_code của buycard và checkavailable.
  • image
    Kiểu
    chuỗi
    Mô tả
    Đường dẫn ảnh tương đối.
  • imgurl
    Kiểu
    chuỗi
    Mô tả
    Đường dẫn ảnh đầy đủ.
  • short_description, description
    Kiểu
    chuỗi
    Mô tả
    Mô tả ngắn và mô tả chi tiết, có thể là null.
  • cardvalue
    Kiểu
    mảng
    Mô tả
    Mệnh giá đang bán: service_code, value, id và discount (phần trăm, dạng chuỗi).

Phản hồi lỗi

  • 104
    message
    Du lieu gui len khong dung
    Nguyên nhân và cách xử lý
    Thiếu partner_id.
  • 108
    message
    Khong ton tai tai khoan merchant
    Nguyên nhân và cách xử lý
    Không có kết nối loại Mua mã thẻ với partner_id này, kết nối chưa khai IP hoặc IP gọi không nằm trong danh sách IP của kết nối.
  • 115
    message
    API KEY CHƯA ĐƯỢC BẬT
    Nguyên nhân và cách xử lý
    Kết nối đang tắt.
  • 429
    message
    Gui qua nhieu yeu cau, vui long thu lai sau
    Nguyên nhân và cách xử lý
    Một IP gọi quá nhiều lần trong một phút, chờ rồi gọi lại.
  • Thành công trả mảng JSON; lỗi trả object có status là số, message và data bằng false.
  • Danh sách thay đổi khi quản trị viên bật, tắt sản phẩm; nên lấy lại định kỳ.

Phản hồi và trạng thái đơn#

buycard và redownload trả khung status, message, data. checkavailable và getbalance trả JSON trực tiếp. Lỗi của mọi lệnh chỉ gồm status và message. Luôn trả HTTP 200.

Các trường

  • data.cards
    Kiểu
    mảng
    Lệnh
    buycard, redownload
    Mô tả
    Danh sách thẻ của đơn, rỗng khi đơn đang chờ hoặc đã huỷ.
  • data.cards[].name
    Kiểu
    chuỗi
    Lệnh
    buycard, redownload
    Mô tả
    Tên thẻ.
  • data.cards[].serial
    Kiểu
    chuỗi
    Lệnh
    buycard, redownload
    Mô tả
    Serial thẻ.
  • data.cards[].code
    Kiểu
    chuỗi
    Lệnh
    buycard, redownload
    Mô tả
    Mã thẻ.
  • data.cards[].expire
    Kiểu
    chuỗi
    Lệnh
    buycard, redownload
    Mô tả
    Hạn dùng của thẻ, có thể là null.
  • data.time
    Kiểu
    chuỗi
    Lệnh
    buycard, redownload
    Mô tả
    Thời điểm phản hồi, dạng YYYY-MM-DD HH:mm:ss giờ Việt Nam.
  • data.request_id
    Kiểu
    chuỗi
    Lệnh
    buycard, redownload
    Mô tả
    request_id bạn đã gửi.
  • data.order_code
    Kiểu
    chuỗi
    Lệnh
    buycard, redownload
    Mô tả
    Mã đơn của hệ thống.
  • data.total_price
    Kiểu
    số nguyên
    Lệnh
    buycard, redownload
    Mô tả
    Tổng tiền đã trừ ví.
  • stock_available
    Kiểu
    boolean
    Lệnh
    checkavailable
    Mô tả
    true nếu kho đủ qty thẻ.
  • SERVICE-VALUE
    Kiểu
    chuỗi
    Lệnh
    checkavailable
    Mô tả
    Khoá dạng SERVICE_CODE-VALUE, giá trị là Còn hàng, Hết hàng hoặc Sản phẩm không tồn tại.
  • balance
    Kiểu
    số nguyên
    Lệnh
    getbalance
    Mô tả
    Số dư ví (VND).
  • currency_code
    Kiểu
    chuỗi
    Lệnh
    getbalance
    Mô tả
    Luôn là VND.

Trạng thái đơn

  • 1
    message
    Mua thẻ thành công
    Ý nghĩa
    Đơn hoàn tất, data.cards có đủ thẻ.
  • 2
    message
    Đơn hàng đang chờ xử lý
    Ý nghĩa
    Tiền đã trừ, đang chờ nhà cung cấp trả thẻ. Gọi redownload sau ít phút.
  • 2
    message
    Đơn hàng đã hủy và hoàn tiền
    Ý nghĩa
    Đơn bị huỷ, tiền đã hoàn về ví.

Mã lỗi#

Thông báo được giữ nguyên văn để bạn so khớp, nhưng nên xử lý theo status.

  • 100
    message
    Thiếu dữ liệu bắt buộc
    Nguyên nhân và cách xử lý
    Thiếu partner_id, command hoặc sign, hoặc thiếu request_id, wallet_number của lệnh cần chúng.
  • 100
    message
    Tài khoản bị khóa
    Nguyên nhân và cách xử lý
    Tài khoản sở hữu kết nối đang bị khoá.
  • 100
    message
    Địa chỉ ví bị khóa
    Nguyên nhân và cách xử lý
    Ví của tài khoản đang bị khoá.
  • 100
    message
    Dữ liệu mua thẻ không hợp lệ
    Nguyên nhân và cách xử lý
    buycard thiếu service_code, hoặc value, qty không phải số dương.
  • 100
    message
    Dữ liệu kiểm tra tồn kho không hợp lệ
    Nguyên nhân và cách xử lý
    checkavailable thiếu service_code, hoặc value, qty không phải số dương.
  • 100
    message
    Sản phẩm không tồn tại hoặc bị tắt
    Nguyên nhân và cách xử lý
    Không có mệnh giá value đang bán của service_code này.
  • 100
    message
    Lệnh không hợp lệ
    Nguyên nhân và cách xử lý
    command không thuộc danh sách lệnh hỗ trợ.
  • 102
    message
    Đơn chưa có mã thẻ
    Nguyên nhân và cách xử lý
    redownload: đơn thất bại và chưa được hoàn tiền; liên hệ hỗ trợ.
  • 103
    message
    Không tìm thấy giao dịch
    Nguyên nhân và cách xử lý
    redownload: không có đơn nào của tài khoản với request_id này.
  • 107
    message
    Lỗi tạo đơn hàng, vui lòng báo kỹ thuật
    Nguyên nhân và cách xử lý
    Không tạo được đơn; tiền không bị trừ.
  • 108
    message
    Api key không hợp lệ
    Nguyên nhân và cách xử lý
    partner_id không tồn tại hoặc kết nối không có loại Mua mã thẻ.
  • 109
    message
    request_id đã tồn tại
    Nguyên nhân và cách xử lý
    request_id đã được dùng cho một đơn khác trong tài khoản.
  • 114
    message
    Địa chỉ IP không được phép, vui lòng gửi IP này cho admin
    Nguyên nhân và cách xử lý
    IP gọi API không nằm trong danh sách Địa chỉ IP của kết nối, hoặc kết nối chưa khai báo IP.
  • 115
    message
    Api key chưa được bật
    Nguyên nhân và cách xử lý
    Kết nối đang tắt.
  • 116
    message
    Chữ ký không hợp lệ
    Nguyên nhân và cách xử lý
    Chữ ký không khớp. Kiểm tra Partner Key, thứ tự ghép và lệnh có ghép request_id hay không.
  • 118
    message
    Website đang bảo trì
    Nguyên nhân và cách xử lý
    Chức năng mua thẻ đang tạm dừng.
  • 118
    message
    Sản phẩm đã hết
    Nguyên nhân và cách xử lý
    Kho và nhà cung cấp đều không đủ thẻ cho mệnh giá này.
  • 118
    message
    Nhà cung cấp tạm hết số dư
    Nguyên nhân và cách xử lý
    Nhà cung cấp tạm không bán được; thử lại sau.
  • 121
    message
    Số dư không đủ
    Nguyên nhân và cách xử lý
    Số dư ví không đủ cho total_price.
  • 125
    message
    Đơn hàng vượt quá số lượng cho phép
    Nguyên nhân và cách xử lý
    qty vượt số thẻ tối đa mỗi đơn (mặc định 10).

Thử bằng key sandbox

Dùng key sandbox (Partner ID bắt đầu bằng sandbox_) với đúng URL này. Sản phẩm, mệnh giá, tài khoản và giá vẫn kiểm tra trên danh mục thật; kết quả chọn bằng đuôi request_id, đọc từ dấu _ cuối cùng, không phân biệt hoa thường.

  • (không có)
    Kết quả
    status 1 kèm mã thẻ giả có prefix SANDBOX, trừ tiền thử
  • _pending
    Kết quả
    status 2 chưa có thẻ, vài giây sau redownload trả thẻ
  • _canceled
    Kết quả
    status 2 đơn huỷ, trừ rồi hoàn tiền thử
  • _nocards
    Kết quả
    status 2 chờ mãi, redownload trả lỗi 102 chưa có mã thẻ
  • _soldout
    Kết quả
    Trả lỗi 118 hết hàng, không trừ tiền
  • _provider
    Kết quả
    Trả lỗi 118 nhà cung cấp hết số dư, không trừ tiền
  • _maintenance
    Kết quả
    Trả lỗi 118 bảo trì, không trừ tiền
  • _failed
    Kết quả
    Trả lỗi 107 lỗi tạo đơn, không trừ tiền
  • _locked
    Kết quả
    Trả lỗi 100 tài khoản bị khoá, không trừ tiền
  • _walletlocked
    Kết quả
    Trả lỗi 100 ví bị khoá, không trừ tiền

Code mẫu#

Hàm mẫu tự tính chữ ký theo từng lệnh rồi gửi yêu cầu; ví dụ mua thẻ rồi tải lại đơn. Tab cURL gửi lệnh buycard.

PARTNER_ID='YOUR_PARTNER_ID'
PARTNER_KEY='YOUR_PARTNER_KEY'
REQUEST_ID='CARD20261024001'
SIGN=$(printf '%s' "${PARTNER_KEY}${PARTNER_ID}buycard${REQUEST_ID}" | md5sum | cut -d ' ' -f 1)

curl -X POST 'https://thepay1s.com/api/cardws' \
  -H 'Content-Type: application/json' \
  --data-binary @- <<JSON
{
  "command": "buycard",
  "partner_id": "$PARTNER_ID",
  "request_id": "$REQUEST_ID",
  "service_code": "VIETTEL",
  "value": 100000,
  "qty": 2,
  "wallet_number": "4821061234",
  "sign": "$SIGN"
}
JSON