Workfino Task Lease - Tích hợp App miễn phí

Workfino cấp license gốc vĩnh viễn. Server 2 chỉ quản lý thời hạn sử dụng và nhiệm vụ gia hạn. App không dùng ngày của Windows; mỗi lần mở app đều hỏi Server 2.

1. Luồng tổng thể

Bước 1App đọc license key + Product UUID + Device UUID.
Bước 2App gọi POST /v1/license/check.
Bước 3Server 2 xác thực license với Workfino.
Bước 4Server 2 dùng giờ server/DB để kiểm tra expires_at.
Bước 5Nếu hết hạn, app gọi POST /v1/tasks/create.
Bước 6Người dùng tìm Google, vào trang đích, nhập mã 6 số.
Bước 7Browser heartbeat đủ thời gian → Server 2 cộng ngày.
Bước 8App poll task rồi gọi lại /v1/license/check.

2. Thông tin app cần lưu cục bộ

BiếnÝ nghĩa
license_keyKey license vĩnh viễn do Workfino cấp.
product_public_idUUID sản phẩm/app trên Workfino.
device_public_idUUID tạo 1 lần khi cài app, giữ ổn định.
device_fingerprintDấu vân tay thiết bị nếu policy Workfino yêu cầu.

Không tự tính hạn bằng time.Now() của máy người dùng. Chỉ tin server_time, expires_atactive do Server 2 trả về.

3. Kiểm tra license khi mở app

POST https://tasks.workfino.com/v1/license/check

{
  "license_key": "WF-...",
  "product_public_id": "PRODUCT-UUID",
  "device_public_id": "DEVICE-UUID",
  "device_fingerprint": "sha256-or-stable-device-fingerprint",
  "platform": "windows"
}

Phản hồi khi còn hạn:

{
  "valid": true,
  "active": true,
  "server_time": "2026-08-31T03:40:00Z",
  "expires_at": "2026-09-30T03:40:00Z",
  "remaining_seconds": 2592000,
  "task_available": false,
  "license_public_id": "...",
  "product_public_id": "..."
}

Logic app:

if valid == false:
    khóa app và báo license Workfino không hợp lệ
else if active == true:
    mở app bình thường
else:
    hiện nút "Gia hạn miễn phí"

4. Tạo nhiệm vụ gia hạn

POST /v1/tasks/create với cùng dữ liệu license/device.

Server 2 trả:

{
  "task_id": "TASK-UUID",
  "status_token": "SECRET_STATUS_TOKEN",
  "verification_code": "628194",
  "keyword": "mẫu nhà phố 3 tầng 4x18m",
  "target_host": "workfino.com",
  "required_seconds": 60,
  "reward_days": 30,
  "task_expires_at": "..."
}

App hiển thị:

NHIỆM VỤ GIA HẠN MIỄN PHÍ

1. Mở Google.
2. Tìm: "mẫu nhà phố 3 tầng 4x18m"
3. Mở kết quả trên workfino.com
4. Nhập mã: 628194
5. Giữ trang đang hiển thị đến khi hoàn thành.

[ MỞ GOOGLE ]

Nút “Mở Google” nên mở https://www.google.com/. Không cần truyền license key hoặc task token vào URL.

5. App theo dõi nhiệm vụ

GET /v1/tasks/{task_id}/status

Authorization: Bearer SECRET_STATUS_TOKEN

Poll khoảng 3–5 giây/lần khi màn hình nhiệm vụ đang mở.

{
  "task_id": "...",
  "status": "completed",
  "elapsed_seconds": 60,
  "required_seconds": 60,
  "lease_expires_at": "2026-10-30T03:40:00Z",
  "server_time": "...",
  "completed": true
}

Khi completed=true, app gọi lại POST /v1/license/check. Nếu active=true thì mở khóa ngay.

6. Ví dụ Go tối giản trong app

type CheckResponse struct {
    Valid            bool      `json:"valid"`
    Active           bool      `json:"active"`
    ServerTime       time.Time `json:"server_time"`
    ExpiresAt        time.Time `json:"expires_at"`
    RemainingSeconds int64     `json:"remaining_seconds"`
    TaskAvailable    bool      `json:"task_available"`
}

func CheckLicense(ctx context.Context, baseURL string, payload any) (CheckResponse, error) {
    body, _ := json.Marshal(payload)
    req, _ := http.NewRequestWithContext(ctx, http.MethodPost,
        strings.TrimRight(baseURL, "/")+"/v1/license/check", bytes.NewReader(body))
    req.Header.Set("Content-Type", "application/json")

    resp, err := http.DefaultClient.Do(req)
    if err != nil { return CheckResponse{}, err }
    defer resp.Body.Close()

    var out CheckResponse
    if err := json.NewDecoder(resp.Body).Decode(&out); err != nil { return out, err }
    if resp.StatusCode != http.StatusOK { return out, fmt.Errorf("license check HTTP %d", resp.StatusCode) }
    return out, nil
}

7. Đánh dấu trang Workfino làm trang nhiệm vụ

Trong HTML content của Gig hoặc Product, thêm marker sau:

<div data-wf-task></div>

Marker này đã được cấu hình để TinyMCE giữ nguyên khi lưu nội dung.

Workfino vẫn xóa mọi <script> do seller nhập. Marker được sanitizer đổi thành phần tử inert, sau đó bridge JS do Workfino tự quản lý sẽ hiện ô nhập mã khi người dùng đi từ Google.

Trên VPS Workfino phải có:

WORKFINO_TASK_SERVER_URL=https://tasks.workfino.com

8. Website ngoài Workfino

Nếu website cho phép JavaScript trong content, chỉ cần chèn:

<script defer src="https://tasks.workfino.com/task-widget.js"></script>

Không cần hard-code task ID. Server 2 xác định task bằng mã 6 số mà người dùng nhập và kiểm tra URL hiện tại với campaign.

9. Quy tắc bảo mật đang áp dụng