Files
hcapEnv/src/generator/payload.js
2026-02-21 18:27:49 +08:00

85 lines
2.9 KiB
JavaScript

/**
* Payload Builder - Assembling the Final Form
*
* Takes all our crafted components and stitches them into
* the exact structure hCaptcha expects.
*
* From h.html source, the payload object (s) contains:
* {v, sitekey, host, hl, motionData, n, c, rqdata, pst, pd, pdc, pem...}
*
* IMPORTANT: The 'c' field is included in the payload object but gets
* REMOVED before encryption. The encrypted body is then packed as:
* msgpack.encode([JSON.stringify(c), encrypted_payload_without_c])
*/
export class PayloadBuilder {
/**
* Build the getcaptcha request payload
*
* The returned object includes 'c' - the caller is responsible for
* cloning and deleting 'c' before encryption (matching h.html behavior).
*/
static build({ siteKey, host, n, c, motionData, rqdata = '' }) {
const now = Date.now();
return {
v: '1', // Protocol version
sitekey: siteKey,
host,
hl: 'en', // Language
// Challenge response
n, // Proof of work from hsw.js
// c field — will be stripped before encryption,
// then used separately in body packing as msgpack([c_string, encrypted])
c: typeof c === 'string' ? c : JSON.stringify(c),
// Motion telemetry
motionData: typeof motionData === 'string'
? motionData
: JSON.stringify(motionData),
// Additional fields from h.html source
rqdata, // Request data from checksiteconfig
pst: false, // Previous success token
// Performance / detection data
pd: JSON.stringify({
si: now - 5000, // Script init
ce: now - 4500, // Challenge end
cs: now - 4000, // Challenge start
re: now - 500, // Response end
rs: now - 1000, // Response start
}),
pdc: JSON.stringify({}), // Performance data cached
pem: JSON.stringify({}), // Performance event map
// Previous state
prev: JSON.stringify({
escaped: false,
passed: false,
expiredChallenge: false,
expiredResponse: false,
}),
};
}
/**
* Build form-encoded payload (alternative format for non-encrypted requests)
*/
static buildFormData(data) {
const params = new URLSearchParams();
for (const [key, value] of Object.entries(data)) {
if (typeof value === 'object') {
params.append(key, JSON.stringify(value));
} else {
params.append(key, String(value));
}
}
return params.toString();
}
}