Files
jtlsrv/test-client.js
2026-06-21 09:09:06 +02:00

203 lines
5.8 KiB
JavaScript

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 <authCode> [name] # 6-digit: step1+2, 4-digit: step1 only');
console.error(' node test-client.js init <authToken>');
console.error(' node test-client.js customergroup <authToken> [lastChangedCustomerGroup]');
console.error(' node test-client.js deletedentity <authToken> [lastChangedDeletedEntity]');
console.error(' node test-client.js category <authToken> [lastChangedCategory]');
console.error(' node test-client.js customer <authToken> [lastChangedCustomer]');
console.error(' node test-client.js product <authToken> [lastChangedProduct]');
console.error(' node test-client.js productcomposite <authToken> [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);
});