const https = require('node:https'); const { gunzipSync } = require('node:zlib'); const HOST = process.env.JTL_HOST || '192.168.178.81'; const PORT = Number(process.env.JTL_PORT) || 4433; const INIT_QUERY = 'mandantId=1&lastChangedCategory=0&lastChangedCustomer=0&lastChangedCustomerGroup=0&lastChangedProduct=0&lastChangedConfigurationGroup=0&lastChangedConfigurationItem=0&lastChangedCompositeProduct=0&lastChangedDeletedEntity=0'; function usage() { console.error('Usage:'); console.error(' node test-client.js [name] # 6-digit: step1+2, 4-digit: step1 only'); console.error(' node test-client.js init '); console.error(' node test-client.js customergroup [lastChangedCustomerGroup]'); console.error(' node test-client.js deletedentity [lastChangedDeletedEntity]'); console.error(' node test-client.js category [lastChangedCategory]'); console.error(' node test-client.js customer [lastChangedCustomer]'); console.error(' node test-client.js product [lastChangedProduct]'); console.error(' node test-client.js productcomposite [lastChangedCompositeProduct]'); process.exit(1); } function posHeaders(authToken) { const headers = { accept: 'application/json', 'content-type': 'application/json', 'cache-control': 'no-cache', version: '1.0.11.14', system: 'JTL-POS', charset: 'utf-8', connection: 'Keep-Alive', 'user-agent': 'Dalvik/2.1.0 (Linux; U; Android 14; SM-A528B Build/UP1A.231005.007)', 'accept-encoding': 'gzip', }; if (authToken) { headers.authorization = `Bearer ${authToken}`; } return headers; } function decodeBody(buffer, headers) { if (headers['content-encoding'] === 'gzip') { return gunzipSync(buffer); } return buffer; } function request(path, authToken) { return new Promise((resolve, reject) => { const req = https.request( { hostname: HOST, port: PORT, path, method: 'GET', headers: posHeaders(authToken), rejectUnauthorized: false, }, (res) => { const chunks = []; res.on('data', (chunk) => chunks.push(chunk)); res.on('end', () => { const raw = Buffer.concat(chunks); resolve({ statusCode: res.statusCode, headers: res.headers, body: decodeBody(raw, res.headers), }); }); } ); req.on('error', reject); req.end(); }); } function printResponse(res) { console.log(`status: ${res.statusCode}`); console.log('headers:', JSON.stringify(res.headers, null, 2)); console.log('body:'); try { console.log(JSON.stringify(JSON.parse(res.body.toString('utf8')), null, 2)); } catch { console.log(res.body.toString('utf8')); } } async function clientRequest(authCode, name, label) { const path = `/api/v1/client?authCode=${encodeURIComponent(authCode)}&name=${encodeURIComponent(name)}`; console.log(`${label} GET https://${HOST}:${PORT}${path}\n`); const res = await request(path); printResponse(res); console.log(); return res; } async function main() { const mode = process.argv[2]; if (!mode) { usage(); } if (mode === 'init') { const authToken = process.argv[3] || process.env.AUTH_TOKEN; if (!authToken) { usage(); } const path = `/api/v1/init?${INIT_QUERY}`; console.log(`GET https://${HOST}:${PORT}${path}\n`); const res = await request(path, authToken); printResponse(res); return; } if (mode === 'customergroup') { const authToken = process.argv[3] || process.env.AUTH_TOKEN; if (!authToken) { usage(); } const lastChanged = process.argv[4] || '0'; const path = `/api/v1/customergroup?mandantId=1&lastChangedCustomerGroup=${encodeURIComponent(lastChanged)}`; console.log(`GET https://${HOST}:${PORT}${path}\n`); const res = await request(path, authToken); printResponse(res); return; } if (mode === 'deletedentity') { const authToken = process.argv[3] || process.env.AUTH_TOKEN; if (!authToken) { usage(); } const lastChanged = process.argv[4] || '0'; const path = `/api/v1/deletedentity?mandantId=1&limit=200&lastChangedDeletedEntity=${encodeURIComponent(lastChanged)}`; console.log(`GET https://${HOST}:${PORT}${path}\n`); const res = await request(path, authToken); printResponse(res); return; } const entityModes = { category: { param: 'lastChangedCategory', path: '/api/v1/category?mandantId=1&limit=20', }, customer: { param: 'lastChangedCustomer', path: '/api/v1/customer?mandantId=1&limit=20', }, product: { param: 'lastChangedProduct', path: '/api/v1/product?mandantId=1&limit=20', }, productcomposite: { param: 'lastChangedCompositeProduct', path: '/api/v1/productcomposite?mandantId=1&limit=20', }, }; if (entityModes[mode]) { const authToken = process.argv[3] || process.env.AUTH_TOKEN; if (!authToken) { usage(); } const { param, path: basePath } = entityModes[mode]; const lastChanged = process.argv[4] || '0'; const path = `${basePath}&${param}=${encodeURIComponent(lastChanged)}`; console.log(`GET https://${HOST}:${PORT}${path}\n`); const res = await request(path, authToken); printResponse(res); return; } const name = process.argv[3] || process.env.CLIENT_NAME || '001'; const fullCode = mode; if (fullCode.length === 6) { await clientRequest(fullCode.slice(0, 4), name, '=== step 1 (4 digits) ==='); await clientRequest(fullCode, name, '=== step 2 (6 digits) ==='); return; } await clientRequest(fullCode, name, '=== step 1 (4 digits) ==='); } main().catch((err) => { console.error('request failed:', err.message); process.exit(1); });