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.
POST /v1/license/check.expires_at.POST /v1/tasks/create./v1/license/check.| Biến | Ý nghĩa |
|---|---|
license_key | Key license vĩnh viễn do Workfino cấp. |
product_public_id | UUID sản phẩm/app trên Workfino. |
device_public_id | UUID tạo 1 lần khi cài app, giữ ổn định. |
device_fingerprint | Dấ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_at và active do Server 2 trả về.
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í"
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.
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.
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
}
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
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.
license_model=perpetual.visible và khoảng heartbeat không vượt giới hạn.