sro-correios
Version:
JavaScript library for tracking orders through Correios (BR)
206 lines (205 loc) • 7.62 kB
JavaScript
"use strict";
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.SroCorreios = void 0;
const node_fetch_1 = __importDefault(require("node-fetch"));
const capitalize_1 = __importDefault(require("capitalize"));
const crypto_1 = __importDefault(require("crypto"));
class SroCorreios {
constructor() {
this.PARALLEL_TRACKS = 10;
}
async track(...codes) {
const flatCodes = codes.flat();
const chunkSize = Math.ceil(flatCodes.length / this.PARALLEL_TRACKS);
const tracks = [];
for (let i = 0; i < chunkSize; i++) {
const results = await Promise.all(flatCodes.slice(this.PARALLEL_TRACKS * i, this.PARALLEL_TRACKS * (i + 1)).map(this.requestObject.bind(this)));
tracks.push(...results);
}
return tracks;
}
async requestObject(code) {
try {
if (!SroCorreios.isValidOrderCode(code)) {
return {
code,
isInvalid: true,
error: 'invalid_code'
};
}
const hashSign = this.generateHashSign();
const loginResponse = await (0, node_fetch_1.default)(this.loginUri(), {
method: 'POST',
headers: {
'User-Agent': this.userAgent,
'Content-Type': 'application/json'
},
body: JSON.stringify({
requestToken: this.loginToken(),
data: hashSign.date,
sign: hashSign.sign
})
});
const { token } = await loginResponse.json();
const response = await (0, node_fetch_1.default)(this.uri(code), {
method: 'GET',
headers: {
'User-Agent': this.userAgent,
'Content-Type': 'application/json',
'app-check-token': token
}
});
const data = await response.json();
return this.parseResponse(data, code);
}
catch (error) {
return {
code,
isInvalid: true,
error: 'service_unavailable'
};
}
}
parseResponse(data, code) {
if (data.objetos[0].mensagem !== undefined || data.objetos[0].eventos === undefined) {
return {
code,
isInvalid: true,
error: 'not_found'
};
}
const events = [];
data.objetos[0].eventos.forEach(event => {
const locality = this.locationRules(event.unidade).locality;
const origin = this.locationRules(event.unidade).origin;
let destination = null;
if (event.unidadeDestino !== undefined) {
destination = this.locationRules(event.unidadeDestino).origin;
}
events.push({
locality,
status: event.descricao,
origin,
destination,
trackedAt: new Date(event.dtHrCriado)
});
});
const [lastEvent, firstEvent] = [events[0], events[events.length - 1]];
const isDelivered = lastEvent.status.includes('Objeto entregue');
const category = this.parseCategory(data.objetos[0].tipoPostal);
return {
code,
category,
isDelivered,
postedAt: firstEvent.trackedAt,
updatedAt: lastEvent.trackedAt,
events
};
}
parseLocation(unit) {
const city = (0, capitalize_1.default)(unit.endereco.cidade);
const locality = `${city} / ${unit.endereco.uf}`;
const origin = `${unit.tipo} - ${locality}`;
return {
locality,
origin
};
}
parseInternationalLocation(unit) {
const origin = capitalize_1.default.words(unit.nome);
return {
locality: null,
origin
};
}
locationRules(unit) {
if (unit.tipo === 'País') {
return this.parseInternationalLocation(unit);
}
else {
return this.parseLocation(unit);
}
}
parseCategory(postalType) {
if (postalType === undefined) {
return {
name: 'Desconhecido',
description: 'Não identificado'
};
}
const name = capitalize_1.default.words(postalType?.categoria ?? 'Desconhecido');
let description = capitalize_1.default.words(postalType?.descricao ?? 'Não identificado');
if (!description.includes('identificado') && !description.includes('Internacional')) {
const postalCode = description.split(' ').filter(word => word.length === 2)[0];
if (postalCode !== undefined) {
description = description.replace(postalCode, postalCode.toUpperCase());
}
}
return {
name,
description
};
}
generateHashSign() {
const hash = crypto_1.default.createHash('md5');
const date = new Date().toLocaleString('pt-BR', { timeZone: 'America/Sao_Paulo' }).replace(',', '');
const hashString = `requestToken${this.loginToken()}data${date}`;
const sign = hash.update(hashString).digest('hex');
return {
sign,
date
};
}
uri(code) {
const baseUrl = this.decoder(`
\x61\x48\x52\x30\x63\x48\x4d\x36\x4c\x79\x39\x77\x63
\x6d\x39\x34\x65\x57\x46\x77\x63\x43\x35\x6a\x62\x33
\x4a\x79\x5a\x57\x6c\x76\x63\x79\x35\x6a\x62\x32\x30
\x75\x59\x6e\x49\x76\x64\x6a\x45\x76\x63\x33\x4a\x76
\x4c\x58\x4a\x68\x63\x33\x52\x79\x62\x79\x38\x3d
`);
return baseUrl + code;
}
loginUri() {
const url = this.decoder(`
\x61\x48\x52\x30\x63\x48\x4d\x36\x4c\x79\x39\x77\x63\x6d
\x39\x34\x65\x57\x46\x77\x63\x43\x35\x6a\x62\x33\x4a\x79
\x5a\x57\x6c\x76\x63\x79\x35\x6a\x62\x32\x30\x75\x59\x6e
\x49\x76\x64\x6a\x45\x76\x59\x58\x42\x77\x4c\x58\x5a\x68
\x62\x47\x6c\x6b\x59\x58\x52\x70\x62\x32\x34\x3d
`).replace('v1', 'v2');
return url;
}
loginToken() {
const token = this.decoder(`
\x57\x56\x63\x31\x61\x32\x4e\x74\x4f\x58\x42\x61\x52\x48
\x52\x70\x59\x32\x6b\x31\x61\x6d\x49\x79\x4d\x48\x56\x5a
\x4d\x6a\x6c\x35\x59\x32\x31\x57\x63\x47\x49\x7a\x54\x58
\x56\x6a\x53\x45\x70\x73\x57\x56\x68\x53\x62\x47\x4a\x74
\x55\x6e\x42\x69\x56\x31\x5a\x31\x5a\x45\x63\x34\x4e\x31
\x4a\x71\x54\x58\x6c\x53\x56\x45\x6b\x31\x54\x31\x52\x6a
\x4d\x6b\x35\x36\x51\x54\x56\x4e\x65\x6c\x55\x31\x54\x30
\x52\x56\x4e\x56\x4a\x55\x51\x6b\x4e\x50\x56\x47\x52\x48
\x54\x6d\x74\x5a\x4e\x46\x46\x55\x55\x54\x52\x4e\x4d\x45
\x6b\x31\x55\x57\x70\x72\x4d\x55\x31\x36\x56\x54\x4e\x50
\x51\x54\x30\x39
`);
return token;
}
get userAgent() {
const UAS = this.decoder(`
\x52\x47\x46\x79\x64\x43\x38\x79\x4c\x6a\x45\x34\x49\x43
\x68\x6b\x59\x58\x4a\x30\x4f\x6d\x6c\x76\x4b\x51\x3d\x3d
`);
return UAS;
}
decoder(value) {
return Buffer.from(value, '\x62\x61\x73\x65\x36\x34').toString('utf-8');
}
;
}
exports.SroCorreios = SroCorreios;
SroCorreios.isValidOrderCode = (code) => /^[A-Z]{2}[0-9]{9}[A-Z]{2}$/.test(code);