API v4.4 Bảng điều khiển PublisherBảng điều khiển
📡 Hướng dẫn tích hợp cho nhà xuất bản

FastCoins Publisher API
Tài liệu

Mọi thứ bạn cần để tích hợp quảng cáo PTC trên trang của mình — thông báo Postback S2S và tài liệu tham chiếu API đầy đủ.

Postback S2S PTC API Xác thực Bearer Token Ví dụ PHP Miễn phí & Công khai
Tổng quan

FastCoins là mạng nhà xuất bản PTC (Paid-To-Click). Nhúng quảng cáo của chúng tôi vào trang của bạn, người dùng của bạn nhận thưởng bằng token khi xem chúng, và bạn tự động nhận một phần doanh thu.

📡
Postback (S2S)
Máy chủ của bạn được thông báo qua HTTP GET khi người dùng hoàn thành một quảng cáo. Lý tưởng để cộng thưởng tự động mà không cần mã phía client.
🔌
PTC API
Lấy các quảng cáo khả dụng theo cách lập trình và hiển thị bằng giao diện riêng của bạn. Không cần nhúng widget nào.
🪙
Token tùy chỉnh
Cấu hình tên token và tỷ lệ quy đổi của riêng bạn. Phần thưởng được quy đổi và gửi tự động qua postback.
💰
Chia sẻ doanh thu
Bạn kiểm soát tỷ lệ chi trả cho người dùng. Phần còn lại là doanh thu nhà xuất bản của bạn — rút hàng tháng (ngày 1–3).
🚀
Bắt đầu

Tạo tài khoản nhà xuất bản, xác minh bạn sở hữu tên miền và nhận thông tin xác thực API sau khi được xem xét.

  • 1
    Tạo tài khoản nhà xuất bản tại FastCoins.com/publisher_dashboard. Bạn cần tên trang và URL.
  • 2
    Thêm một tên miền trong tab Domains. Mỗi tên miền có API Key, Secret Key, Bearer Token, cấu hình token và URL postback riêng.
  • 3
    Đặt URL postback của bạn — endpoint trên máy chủ của bạn nhận thông báo phần thưởng (xem mục Postback bên dưới).
  • 4
    Tạo Bearer Token từ tab Domains. Cần thiết để xác thực các lệnh gọi API PTC.
  • 5
    Gửi postback thử nghiệm từ tab Domains để kiểm tra endpoint của bạn phản hồi đúng trước khi chạy thật.
ℹ️
Rút tiền: số dư nhà xuất bản chỉ có thể rút từ ngày 1 đến ngày 3 hàng tháng. Hãy hoạch định dòng tiền của bạn tương ứng.
📬
Tích hợp Postback (S2S)

Thông báo máy chủ sang máy chủ gửi đến trang web của bạn khi người dùng xem xong một quảng cáo, để bạn có thể tự động cộng thưởng mà không cần mã phía client.

🔐 Yêu cầu bảo mật

⚠️
Luôn xác thực IP nguồn và chữ ký trước khi cộng bất kỳ phần thưởng nào. Không bao giờ cộng thưởng chỉ dựa trên tham số.
  • IP máy chủ được phép: 62.171.140.250, 2a02:c207:2329:8601::1 — chỉ kiểm tra điều này đối với $_SERVER['REMOTE_ADDR']. Đây là lệnh gọi trực tiếp máy chủ sang máy chủ, không phải yêu cầu trình duyệt, nên không có proxy/CDN nào của chúng ta ở giữa; một header như X-Forwarded-For do client cung cấp và có thể giả mạo dễ dàng, vì vậy đừng tin nó cho việc kiểm tra này.
  • userIp là bắt buộc, không chỉ mang tính thông tin — từ chối callback nếu thiếu hoặc không phải IP hợp lệ. Chúng tôi luôn phân giải và gửi IP thật của người xem đã hoàn thành quảng cáo (qua Cloudflare ở phía chúng tôi) chính xác để bạn có thể dựa vào nó cho việc phát hiện gian lận, giới hạn theo IP và kiểm tra người dùng trùng lặp — một endpoint bỏ qua nó sẽ mất hoàn toàn tín hiệu này.
  • Phản hồi HTTP bắt buộc: chính xác là ok — chữ thường, không có khoảng trắng, không có HTML, HTTP 200
  • Thuật toán chữ ký (khuyến nghị): signature_sha256 = HMAC-SHA256(subId + transId + reward, secret_key)secret_key là khóa HMAC, không được nối vào thông điệp. userIp không nằm trong đó.
  • Thuật toán chữ ký (cũ, vẫn gửi trong mọi callback): signature = MD5(subId + transId + reward + secret_key) — các giá trị nối liền không có dấu phân cách. Vẫn hoạt động vô thời hạn cho các tích hợp được xây trước khi signature_sha256 ra đời; không cần thay đổi gì nếu bạn đã xác thực cách này.
  • Cần nhiều hơn 8 chữ số thập phân? Mọi callback còn mang reward_precise (10 chữ số) với signature_sha256_precise riêng = HMAC-SHA256(subId + transId + reward_precise, secret_key) — hoàn toàn tùy chọn và bổ sung, tính theo cùng cách, chỉ là trên chuỗi có độ chính xác cao hơn. reward/signature_sha256/signature vẫn được gửi y như trước bất kể bạn có dùng nó hay không.
  • Chống trùng lặp: luôn kiểm tra transId trong CSDL của bạn trước khi cộng thưởng

📋 Tham số Postback (GET)

URL postback của bạn nhận các tham số này qua HTTP GET.

Tham số Kiểu Bắt buộc Mô tả
subIdstringBẮT BUỘCID người dùng duy nhất trong hệ thống của bạn — giá trị bạn đã truyền trong lệnh gọi widget/API
transIdstringBẮT BUỘCID giao dịch duy nhất — luôn kiểm tra để tránh cộng thưởng trùng lặp
rewardfloatBẮT BUỘCPhần thưởng theo đơn vị token của bạn (đã quy đổi theo token_rate đã cấu hình), định dạng 8 chữ số thập phân
reward_precisefloatTùy chọnPhần thưởng giống reward, định dạng 10 chữ số thay vì 8 — dùng khi 8 chữ số chưa đủ chính xác với bạn
reward_namestringBẮT BUỘCTên token như đã cấu hình cho tên miền của bạn (ví dụ POINTS, COINS)
reward_valuefloatBẮT BUỘCGiống reward — có thêm để tương thích với bitcotasks
offer_namestringTùy chọnTiêu đề quảng cáo đã hoàn thành — hữu ích cho việc ghi log
offer_typestringTùy chọnLuôn là ptc với lượt xem quảng cáo FastCoins
payoutfloatTùy chọnGiống reward — có thêm để tương thích với bên thứ ba
userIpstringBẮT BUỘCĐịa chỉ IP thật của người dùng đã hoàn thành offer, được phân giải qua Cloudflare ở phía chúng tôi trước khi gửi callback này — từ chối callback nếu thiếu hoặc không qua được FILTER_VALIDATE_IP. Dùng cho phát hiện gian lận, giới hạn theo IP, phát hiện người dùng trùng, kiểm toán chuyển đổi và phân tích.
statusintegerBẮT BUỘC1 = Cộng thưởng  |  2 = Hoàn tiền (trừ thưởng)
signature_sha256stringBẮT BUỘCHMAC-SHA256 của subId + transId + reward, dùng secret_key làm khóa — khuyến nghị cho tích hợp mới
signature_sha256_precisestringTùy chọnHMAC-SHA256 của subId + transId + reward_precise, dùng secret_key làm khóa — xác thực cái này thay cho signature_sha256 chỉ khi bạn cũng đọc reward_precise
signaturestringBẮT BUỘCCũ: MD5 của subId + transId + reward + secret_key nối liền (không phân cách). Vẫn được gửi trong mọi callback, không đổi — giữ lại cho các tích hợp xây trước khi signature_sha256 ra đời.
testintegerTùy chọn1 = postback thử nghiệm từ bảng điều khiển — đừng cộng thưởng thật

🧮 Ví dụ: Xây dựng & xác minh URL có chữ ký

Một ví dụ đầy đủ đã tính sẵn để bạn có thể đối chiếu cách tính chữ ký của mình với của chúng tôi trước khi chạy thật. Secret key dùng ở đây là bịa ra, chỉ để minh họa.

example
Secret Key (example only, never a real one): demo_secret_do_not_use_9f8e7d6c

Parameters for this conversion:
  subId   = user_12345
  transId = txn_987654321
  reward  = 0.50
  status  = 1
  userIp  = 127.0.0.1

signature_sha256 = HMAC-SHA256(subId + transId + reward, secret_key)
                  = HMAC-SHA256("user_12345" . "txn_987654321" . "0.50", demo_secret_do_not_use_9f8e7d6c)
                  = HMAC-SHA256("user_12345txn_9876543210.50", demo_secret_do_not_use_9f8e7d6c)
                  = df3eafaa3e8cf4fe8fb40c7bed633f34bc7b964bca58d2d691314771a042d59c

signature (legacy) = MD5(subId + transId + reward + secret_key)
                    = MD5("user_12345" . "txn_987654321" . "0.50" . "demo_secret_do_not_use_9f8e7d6c")
                    = MD5("user_12345txn_9876543210.50demo_secret_do_not_use_9f8e7d6c")
                    = d1eb68e41cbd5770de9384c5be8ebb39

Resulting callback URL:
https://yoursite.com/postback.php?subId=user_12345&transId=txn_987654321&reward=0.50&status=1&userIp=127.0.0.1&signature=d1eb68e41cbd5770de9384c5be8ebb39&signature_sha256=df3eafaa3e8cf4fe8fb40c7bed633f34bc7b964bca58d2d691314771a042d59c
⚠️
Đừng bao giờ dùng secret ví dụ này cho việc thật — nó công khai, được in trong tài liệu này. Hãy tính chữ ký bằng Secret Key thật từ tab Domains của bạn, và không bao giờ dán key thật đó ở nơi công khai nào (công cụ chat, tài liệu, repo công khai) — hãy coi nó như mật khẩu. Ví dụ này cũng bỏ qua reward_name, reward_value, offer_name, offer_type, payouttest cho gọn — callback thật của bạn có đủ tất cả, theo bảng ở trên.

📐 Tùy chọn: độ chính xác 10 chữ số (reward_precise)

Cùng secret, cùng callback — chỉ là phần thưởng có nhiều chữ số thập phân hơn 8 chữ số của reward. Hoàn toàn bổ sung: bỏ qua nếu 8 chữ số đã đủ với trường hợp của bạn.

example-precise
Same secret key and subId/transId as above, but the underlying reward this
time carries more precision:

  reward          = 0.12345679   (8 decimals, rounded)
  reward_precise  = 0.1234567890 (10 decimals)

signature_sha256_precise = HMAC-SHA256(subId + transId + reward_precise, secret_key)
                          = HMAC-SHA256("user_12345" . "txn_987654321" . "0.1234567890", demo_secret_do_not_use_9f8e7d6c)
                          = 219d2101a528b8585161bd26c3bb80c5de8a6741d60d2f1778eb805a05f7a707

💻 Triển khai PHP — postback.php

Lưu mã này trên máy chủ của bạn, đặt Secret Key từ tab Domains, rồi dán URL đầy đủ vào trường Postback URL của tên miền.

postback.php
// ── 1. YOUR SECRET KEY (from Domains tab → Secret Key) ─────
$secret = "";  // ← paste your secret key here

// ── 2. IP VALIDATION (callback source) ──────────────────────
// REMOTE_ADDR only — this call comes straight from our server to
// yours, no browser and no proxy of ours in between, so it's the
// one value here that can't be spoofed by whoever is calling you.
// X-Forwarded-For (or any other header) is attacker-controlled and
// must never be trusted for this check.
$allowed_ips = ['62.171.140.250', '2a02:c207:2329:8601::1'];
$ip = $_SERVER['REMOTE_ADDR'] ?? '';
if (!in_array($ip, $allowed_ips, true)) {
    echo "ERROR: Invalid source IP";
    exit;
}

// ── 3. COLLECT PARAMETERS ───────────────────────────────────
$userId    = $_GET['subId']     ?? null;
$transId   = $_GET['transId']   ?? null;
$status    = $_GET['status']    ?? null;
$isTest    = isset($_GET['test']) && $_GET['test'] == 1;
$userIp    = $_GET['userIp']   ?? null;  // real IP of the ad viewer — required, see step 4

// ── 3b. DYNAMIC PRECISION ────────────────────────────────────
// Prefer reward_precise (10 decimals) when the callback carries it;
// fall back to the standard reward (8 decimals) otherwise. Whichever
// pair is picked, it's verified against its own matching signature in
// step 6 — if that signature is valid, the postback is accepted.
$hasPrecise = isset($_GET['reward_precise'], $_GET['signature_sha256_precise']);
$reward    = $hasPrecise ? $_GET['reward_precise']           : ($_GET['reward'] ?? null);
$signature = $hasPrecise ? $_GET['signature_sha256_precise'] : ($_GET['signature_sha256'] ?? null);

// ── 4. VALIDATE USER IP (required) ──────────────────────────
// userIp is mandatory — this is the real IP of the person who
// completed the offer, already resolved through Cloudflare on our
// end. Reject the callback outright rather than silently accepting
// one without it, since your fraud detection / IP-limit / duplicate-
// user checks depend on this value actually being present and valid.
if (!$userIp || !filter_var($userIp, FILTER_VALIDATE_IP)) {
    echo "ERROR: Invalid user IP";
    exit;
}

// ── 5. VALIDATE REQUIRED PARAMS ─────────────────────────────
if (!$userId || !$transId || $reward === null || !$signature) {
    echo "ERROR: Missing parameters";
    exit;
}

// ── 6. VERIFY SIGNATURE ─────────────────────────────────────
// Only subId + transId + reward go into this hash — userIp is NOT
// part of it. $secret is the HMAC key, not concatenated into the
// message. Don't add userIp here unless a different provider's docs
// explicitly say their signature scheme includes it.
$expected = hash_hmac('sha256', $userId . $transId . $reward, $secret);
if (!hash_equals($expected, $signature)) {
    echo "ERROR: Signature mismatch";
    exit;
}

// ── 7. HANDLE CHARGEBACK (status = 2) ───────────────────────
if ((int)$status === 2) {
    $reward = -abs((float)$reward);  // negative = deduct
}

// ── 8. TEST CALLBACK ─────────────────────────────────────────
// Authenticated and validated like any other callback, but must not
// touch a real balance.
if ($isTest) {
    echo "ok";
    exit;
}

// ── 9. PREVENT DUPLICATES, CREDIT REWARD & STORE USER IP ──────
// Replace with your actual DB logic.
if (!isTransactionProcessed($transId)) {
    creditUserReward($userId, $reward, $transId);
    // If your credit function only takes these 3 args, store $userIp
    // with the conversion separately, e.g.:
    //   saveConversionIp($transId, $userId, $userIp);
}

// ── 10. REQUIRED RESPONSE ───────────────────────────────────
echo "ok";  // MUST return exactly this, nothing else

🕓 Xác thực kiểu cũ — MD5

💡
Đã xác thực signature bằng MD5? Nó vẫn được gửi trong mọi callback, hoàn toàn không đổi — mục này chỉ để tham khảo. Không cần hành động gì. Tích hợp mới nên dùng signature_sha256 ở trên.
postback-legacy.php
$signature = $_GET['signature'] ?? null;
$expected  = md5($userId . $transId . $reward . $secret);
if (!hash_equals($expected, $signature)) {
    echo "ERROR: Signature mismatch";
    exit;
}
// ...same IP check, userIp check, and crediting logic as the main example above.

🔀 Luồng callback

  • 1
    Callback đã nhận
  • 2
    Đối chiếu REMOTE_ADDR với danh sách IP trắng
  • 3
    Đọc các tham số, bao gồm userIp
  • 4
    Xác thực userIp — từ chối nếu thiếu hoặc không phải IP hợp lệ
  • 5
    Xác thực các tham số bắt buộc khác
  • 6
    Xác minh chữ ký
  • 7
    Kiểm tra status — xử lý như hoàn tiền nếu là 2
  • 8
    Nếu test=1, trả về ok mà không cộng thưởng gì
  • 9
    Đối chiếu transId với CSDL để tránh cộng thưởng trùng
  • 10
    Cộng hoặc hoàn lại phần thưởng, và lưu userIp cùng bản chuyển đổi
  • 11
    Trả về ok

Các phản hồi có thể:

  • ok — callback đã xử lý (hoặc được xác nhận là callback thử nghiệm)
  • ERROR: Invalid source IP
  • ERROR: Invalid user IP
  • ERROR: Missing parameters
  • ERROR: Signature mismatch
Phản hồi bắt buộc: trả HTTP 200 với nội dung chính xác là ok — không khoảng trắng, không xuống dòng, không HTML.
⚠️
Postback thất bại có thể được gửi lại từ tab Postback Logs trong bảng điều khiển của bạn. Hãy luôn làm endpoint của bạn bất biến (idempotent) — an toàn khi gọi nhiều lần với cùng một transId.
💡
Thử trước: Dùng nút Test Postback trong tab Domains để kiểm tra endpoint của bạn trước khi chạy thật. Postback thử nghiệm có test=1 — bỏ qua cộng thưởng cho chúng.
🔌
API PTC — Lấy quảng cáo theo cách lập trình

Truy vấn các quảng cáo PTC khả dụng qua REST API và hiển thị bằng giao diện riêng của bạn. Không cần nhúng widget nào.

🌐 Endpoint

GET https://FastCoins.com/api/[API_KEY]/[USER_ID]/[USER_IP]/[DEVICE]
ĐoạnMô tả
API_KEYAPI Key của tên miền bạn — nằm trong tab Domains của Bảng điều khiển Publisher
USER_IDĐịnh danh duy nhất của người dùng trong hệ thống của bạn. Được trả về dưới dạng subId trong postback
USER_IPĐịa chỉ IP thật của người dùng — dùng cho nhắm mục tiêu quảng cáo và phòng chống gian lận. Truyền IP thật của client
DEVICEChính xác là desktop hoặc mobile — không có giá trị thứ ba. Máy tính bảng (iPad, tablet Android) tính là mobile. Thiết bị thật của khách truy cập là bắt buộc khi có bất kỳ nhà quảng cáo nào chạy chiến dịch nhắm theo thiết bị: vì bạn gọi API này từ máy chủ của mình, User-Agent của máy chủ không phải của khách truy cập nên chúng tôi không thể phát hiện giúp — bạn phải phát hiện và truyền qua. Gửi bất kỳ giá trị nào khác ngoài desktop/mobile (kể cả chuỗi "tablet") được coi như bỏ qua — hãy tự quy về mobile. Yêu cầu thiếu hoặc sai chính tả giá trị này sẽ nhận HTTP 400 trong trường hợp đó.
⚠️
Thay đổi lớn: nếu tích hợp của bạn chưa gửi [DEVICE] thì hãy thêm ngay. Hiện nó bị bỏ qua âm thầm, nhưng sẽ bắt đầu trả HTTP 400 ngay khi nhắm mục tiêu theo thiết bị kích hoạt — đừng đợi đến lúc nó làm hỏng feed của bạn.

🔑 Xác thực — Bearer Token

⚠️
Mọi yêu cầu API đều cần một Bearer Token trong header Authorization. Tạo một token cho mỗi tên miền từ tab Domains (nút 🔄 cạnh "Bearer Token").
Authorization: Bearer [YOUR_BEARER_TOKEN]
ℹ️
Nếu tên miền chưa cấu hình Bearer Token, việc xác thực bị bỏ qua. Luôn đặt một token cho môi trường sản xuất.

💻 Ví dụ PHP

get-ads.php
// ── YOUR CREDENTIALS (from Domains tab) ─────────────────────
$apiKey      = 'YOUR_API_KEY';
$bearerToken = 'YOUR_BEARER_TOKEN';

// ── USER DATA ────────────────────────────────────────────────
$userId = $_SESSION['user_id'];  // your user's unique ID
// REMOTE_ADDR by default — it's the one value here that can't be
// spoofed by the visitor. Only read a proxy header instead (e.g.
// CF-Connecting-IP) if your own server sits behind a reverse proxy
// you control and trust — never a client-supplied header like
// X-Forwarded-For, which the visitor's own browser can set to
// anything.
$userIp = $_SERVER['REMOTE_ADDR'] ?? '';

// Required once any advertiser runs a device-targeted campaign — this
// script call happens during the visitor's own page load, so THIS
// server's incoming User-Agent is theirs. Don't skip this: a call from a
// background job/cron with no real visitor attached has no correct value
// to send here.
$userAgent = $_SERVER['HTTP_USER_AGENT'] ?? '';
$device    = preg_match('/Mobi|Android|iPhone|iPod|iPad|BlackBerry|IEMobile|Opera Mini/i', $userAgent)
    ? 'mobile' : 'desktop';

// ── BUILD URL ────────────────────────────────────────────────
$url = 'https://FastCoins.com/api/' . $apiKey
     . '/' . urlencode($userId)
     . '/' . urlencode($userIp)
     . '/' . $device;

// ── CURL REQUEST ─────────────────────────────────────────────
$ch = curl_init($url);
curl_setopt_array($ch, [
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_TIMEOUT        => 10,
    CURLOPT_HTTPHEADER     => [
        'Authorization: Bearer ' . $bearerToken,
        'Accept: application/json',
    ],
]);
$response = curl_exec($ch);
$httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
curl_close($ch);

$data = json_decode($response, true);

// ── HANDLE RESPONSE ──────────────────────────────────────────
if ($httpCode === 200 && $data['status'] === '200') {
    foreach ($data['data'] as $ad) {
        // $ad['url'] already contains the user subId encoded
        echo '<a href="' . htmlspecialchars($ad['url']) . '" target="_blank">';
        echo htmlspecialchars($ad['title']);
        echo ' — ' . $ad['reward'] . ' ' . $ad['currency_name'];
        echo '</a><br>';
    }
} else {
    echo 'No ads available.';
}

📦 Định dạng phản hồi

Phản hồi thành công trả về HTTP 200 với cấu trúc JSON này:

{ "status": "200", "message": "success", "data": [ { "id": "123", "image": "https://FastCoins.com/banners/ad.png", "title": "Visit Our Site & Earn", "description": "Watch this ad for 30 seconds", "duration": "30", "reward": "100.0000", "currency_name": "Coins", "url": "https://FastCoins.com/view/abc123", "boosted_campaign": false, "ad_type": "Iframe" } ] }
TrườngKiểuMô tả
idstringĐịnh danh duy nhất của quảng cáo
imagestringURL đầy đủ của ảnh banner quảng cáo — có thể trống
titlestringTiêu đề hiển thị — hãy hiện nó cho người dùng của bạn
descriptionstringMô tả ngắn của quảng cáo
durationstringThời gian xem bắt buộc tính bằng giây: 2, 30 hoặc 60
rewardfloatSố tiền thưởng theo đơn vị token của tên miền bạn (đã quy đổi)
currency_namestringTên token như đã cấu hình cho tên miền của bạn (ví dụ COINS, USDT)
urlstringChuyển hướng người dùng đến đây để xem quảng cáo. Postback tự động kích hoạt khi hoàn thành. Đã mã hóa sẵn subId của người dùng.
boosted_campaignbooleanCó phải quảng cáo được đẩy hay không — cân nhắc làm nổi bật các quảng cáo này trong giao diện của bạn
ad_typestringIframe = phát trong một khung  |  Redirect = người dùng chuyển đến trang của nhà quảng cáo

⚠️ Mã lỗi

Các phản hồi lỗi dùng chung cấu trúc JSON với trường trạng thái khác 200.

HTTPstatusNguyên nhân & cách xử lý
401401API key không hợp lệ — kiểm tra đoạn API_KEY trong URL, hoặc thiếu Bearer Token khi tên miền yêu cầu
403403Bearer Token không khớp — tạo lại và cập nhật trong tab Domains
400400Định dạng USER_ID không hợp lệ — phải là chữ-số (a-z, 0-9, _, -, .), tối đa 255 ký tự
400400Đoạn DEVICE thiếu hoặc không hợp lệ — chỉ trả về khi nhắm mục tiêu theo thiết bị đã kích hoạt. Phải chính xác là desktop hoặc mobile
500500Lỗi máy chủ nội bộ — trường message chứa chi tiết gỡ lỗi. Liên hệ hỗ trợ nếu vẫn tiếp diễn.
🔄
Luồng tích hợp

Luồng đầu-cuối từ lệnh gọi API đến việc cộng thưởng trên trang của bạn.

📡 Luồng API + Postback

Trang của bạn gọi
GET /api/…
Người dùng bấm vào url của quảng cáo
Người dùng xem quảng cáo trên FastCoins.com
FastCoins kích hoạt
GET postback.php
Xác thực & cộng thưởng
Trả về ok

🧩 Nhúng widget (lựa chọn khác)

Nếu bạn không muốn dùng API, hãy nhúng widget dạng iframe — nó tự xử lý mọi thứ, style được cô lập khỏi phần còn lại của trang.

widget-embed.php
<iframe src="https://fastcoins.click/widget-embed.php?api_key=YOUR_API_KEY&sub_id={USER_ID}"
    style="width:100%;height:640px;border:none;" loading="lazy"></iframe>
ℹ️
Thay YOUR_API_KEY bằng API Key của tên miền bạn và {USER_ID} bằng ID người dùng hiện tại (render phía máy chủ). Widget hiển thị các quảng cáo và nhiệm vụ khả dụng ngay tại chỗ và tự kích hoạt postback khi hoàn thành. Điều chỉnh 640px trong style để iframe cao hơn hoặc thấp hơn theo bố cục của bạn.
⚠️
Một sub_id duy nhất (= {USER_ID}) cho mỗi người dùng thật — không tách ID bằng hậu tố. Mỗi người dùng của bạn phải được định danh bằng một id duy nhất, ổn định. Bạn chọn định dạng — một id mơ hồ, tên đăng nhập, email (ví dụ ABD01230A23, [email protected]) — nhưng một người dùng thật chỉ tương ứng đúng một id, mãi mãi.

Không được phép: lấy một id gốc rồi thêm hậu tố số để tạo ra nhiều "người dùng" từ một người thật. Cơ chế phát hiện không phụ thuộc dấu phân cách — nó bỏ một -, _ hoặc . ở cuối theo sau bởi chữ số và coi phần còn lại là định danh người dùng. Bất kỳ cặp nào dưới đây cũng bị từ chối:
  • 123-1 & 123-2
  • ABC_1 & ABC_2
  • A23-23 & A23-24
  • order.1 & order.2
Id liền mạch không có dấu phân cách là một định danh duy nhất và không bao giờ bị tách (ABD01230A23, 1001, [email protected] đều hợp lệ).

Khi phát hiện mẫu này, API vẫn trả về ok nhưng kèm thông báo id không được phép và không cộng thưởng nào; lần thử được ghi nhận là gian lận.
Nhiệm vụ (CPA) — dành cho nhà quảng cáo

Tạo một nhiệm vụ (ví dụ "đăng ký trên trang của tôi"), nạp tiền cho N lượt hoàn thành, và xác nhận từng lượt bằng postback có chữ ký máy chủ sang máy chủ. Người dùng được cộng thưởng tự động ngay khi postback của bạn đến — không duyệt thủ công, không giữ tiền trên nền tảng.

📡 Cách hoạt động

Bạn tạo nhiệm vụ
/create-task
Người dùng mở URL của bạn với cka_cid
Người dùng hoàn thành hành động
Máy chủ của bạn gọi postback của chúng tôi
Người dùng được cộng thưởng ngay lập tức

1) URL postback

GET https://fastcoins.click/webhooks/task-postback.php?cka_cid={CLICK_ID}&sign={SIGN}
  • cka_cid — click id mà chúng tôi đính kèm vào URL đích của bạn khi người dùng bắt đầu (your-url?cka_cid=…). Hãy trả lại nguyên vẹn.
  • signhash_hmac('sha256', $cka_cid, $task_secret) (hex chữ thường). Secret riêng của từng nhiệm vụ hiển thị trong Create Task → My Tasks.

2) Chữ ký

// PHP
$sign = hash_hmac('sha256', $cka_cid, $task_secret);

// Node.js
const sign = crypto.createHmac('sha256', taskSecret).update(ckaCid).digest('hex');

# Python
import hmac, hashlib
sign = hmac.new(task_secret.encode(), cka_cid.encode(), hashlib.sha256).hexdigest()
ℹ️
Chỉ các IP máy chủ trong danh sách trắng của bạn mới được gọi postback (cấu hình theo từng nhiệm vụ). IP khác sẽ nhận 403 ngay cả khi chữ ký hợp lệ. Điều này cộng với HMAC là toàn bộ mô hình xác thực — hãy giữ bí mật của bạn an toàn.
⚠️
Việc cộng thưởng diễn ra ngay lập tức và chốt tại postback của bạn — không có hoàn tiền. Một lượt hoàn thành được cộng ngay khi postback có chữ ký của bạn được xác minh, vì postback của bạn CHÍNH là bằng chứng người dùng đã làm việc đó. Hãy chắc chắn các bước chống gian lận của bạn chạy trước khi gọi postback: đã gửi thì không thể đảo ngược. Chỉ gọi cho những lượt hoàn thành mà bạn chắc chắn là thật.

3) Pixel phân tích tùy chọn

Đặt mã này trên trang chuyển đổi để tự làm phân tích của bạn. Nó không bao giờ cộng thưởng — postback ở trên mới là thứ duy nhất cộng thưởng.

<img src="https://fastcoins.click/task-pixel.php?cid={CLICK_ID}" width="1" height="1" alt="">
💡
Thực hành tốt nhất

Các khuyến nghị cho một tích hợp ổn định, an toàn và doanh thu cao.

⚡ Hiệu năng

  • Cache phản hồi API ít nhất 60 giây mỗi người dùng. Đừng gọi API ở mỗi lần tải trang — quảng cáo thay đổi nhiều nhất vài phút một lần.
  • Truyền IP thật của người dùng. Mặc định dùng REMOTE_ADDR — đây là giá trị duy nhất khách truy cập không thể giả mạo. Chỉ đọc header proxy thay thế (ví dụ CF-Connecting-IP) khi máy chủ của bạn đứng sau một reverse proxy bạn kiểm soát và tin tưởng; không bao giờ dùng header do client cung cấp như X-Forwarded-For. IP sai làm giảm chất lượng nhắm mục tiêu quảng cáo.
  • Đặt timeout 10 giây cho các lệnh gọi cURL để tránh tải trang chậm nếu API của chúng tôi tạm thời chậm.

🔒 Bảo mật

  • Không bao giờ để lộ Secret Key trong mã phía client hay kho lưu trữ công khai. Nó chỉ được dùng phía máy chủ để xác thực chữ ký.
  • Luôn kiểm tra transId với cơ sở dữ liệu của bạn trước khi cộng thưởng — điều này tránh thưởng trùng do postback bị gửi lại ngoài ý muốn.
  • Xác thực IP nguồn trước khi xử lý bất kỳ postback nào. Chỉ chấp nhận yêu cầu từ 62.171.140.250 hoặc 2a02:c207:2329:8601::1.
  • Dùng HTTPS cho endpoint postback của bạn. Endpoint HTTP có thể bị chặn.
  • Gửi một sub_id duy nhất cho mỗi người dùng thật. Đừng thêm hậu tố số vào một id gốc (123-1/123-2, ABC_1/ABC_2, order.1/order.2) — bất kỳ dấu phân cách nào (- _ .) đều bị phát hiện là gian lận và bị từ chối mà không cộng thưởng. Xem quy tắc ở trên.

💰 Doanh thu

  • Quảng cáo được đẩy (boosted_campaign: true) trả cao hơn — hãy làm nổi bật chúng trong giao diện để tăng tỷ lệ nhấp.
  • Quảng cáo dài (60 giây) trả cao hơn hẳn quảng cáo ngắn (2 giây). Ưu tiên chúng khi người dùng tương tác cao.
  • Cân bằng phần chia cho người dùng — mức chi trả cao hơn thu hút nhiều người dùng hoạt động hơn; mức chi trả thấp hơn tăng biên lợi nhuận của bạn.
  • Rút tiền mở từ ngày 1 đến ngày 3 hàng tháng — đánh dấu vào lịch của bạn.

🐛 Gỡ lỗi

  • Dùng nút Test Postback trong tab Domains để kiểm tra endpoint của bạn trả về chính xác ok với HTTP 200.
  • Xem tab Postback Logs để có phản hồi HTTP đầy đủ của mọi lần thử postback — nó hiển thị mã trạng thái và phản hồi của máy chủ.
  • Postback thất bại có thể được gửi lại từng cái hoặc hàng loạt từ tab Logs. Không có dữ liệu nào bị mất vĩnh viễn.
  • Nếu chữ ký luôn sai: với signature_sha256, kiểm tra secret_key được truyền làm khóa HMAC (không nối vào thông điệp) và bạn băm subId + transId + reward không có dấu phân cách; với signature kiểu cũ, kiểm tra bạn nối subId + transId + reward + secret không có dấu phân cách. Dù thế nào, hãy đảm bảo reward khớp chính xác chuỗi từ tham số GET (không làm tròn).
  • Nếu bạn xác thực signature_sha256_precise: nó được băm trên reward_precise, không phải reward — việc trộn hai trường với nhầm chữ ký là lỗi phổ biến nhất ở đây.

Sẵn sàng bắt đầu kiếm tiền?

Tạo tài khoản nhà xuất bản trong chưa đầy 2 phút, rồi xác minh tên miền của bạn để bắt đầu.

Mở Bảng điều khiển Publisher →
✓ Đã sao chép vào bộ nhớ tạm