fastcheck/server/src/services/siiService.ts
2026-04-08 13:58:46 -04:00

125 lines
3.4 KiB
TypeScript

import axios from 'axios';
import * as cheerio from 'cheerio';
import OpenAI from 'openai';
import dotenv from 'dotenv';
dotenv.config();
const openai = new OpenAI({
apiKey: process.env.OPENAI_API_KEY,
});
const SII_URL = process.env.SII_URL || 'https://zeus.sii.cl/cvc/stc/stc.html';
export class SIIService {
private static async getCaptchaImage(): Promise<Buffer> {
try {
// Create a session and get the main page
const response = await axios.get(SII_URL);
const $ = cheerio.load(response.data);
// Find the CAPTCHA image
const imgTag = $('img#imgcaptcha');
if (!imgTag.length) {
throw new Error('CAPTCHA image not found');
}
// Get the image URL and download it
const imgSrc = imgTag.attr('src');
if (!imgSrc) {
throw new Error('CAPTCHA image source not found');
}
const imgUrl = `https://zeus.sii.cl${imgSrc}`;
const imgResponse = await axios.get(imgUrl, {
responseType: 'arraybuffer'
});
return Buffer.from(imgResponse.data);
} catch (error) {
console.error('Error getting CAPTCHA image:', error);
throw error;
}
}
private static async solveCaptcha(imgBuffer: Buffer): Promise<string> {
try {
const base64Image = imgBuffer.toString('base64');
const response = await openai.chat.completions.create({
model: process.env.OPENAI_MODEL_VISION || "gpt-4-vision-preview",
messages: [
{
role: "system",
content: "You are a CAPTCHA solver."
},
{
role: "user",
content: [
{
type: "text",
text: "What number do you see in this CAPTCHA image? Return only the number."
},
{
type: "image_url",
image_url: {
url: `data:image/jpeg;base64,${base64Image}`
}
}
]
}
],
max_tokens: Number(process.env.OPENAI_MAX_TOKENS) || 10
});
return response.choices[0].message.content?.trim() || '';
} catch (error) {
console.error('Error solving CAPTCHA:', error);
throw error;
}
}
private static async querySII(rut: string, dv: string, captchaText: string): Promise<string> {
try {
const payload = {
RUT: rut,
DV: dv,
codigoCaptcha: captchaText
};
const headers = {
'Referer': SII_URL,
'Content-Type': 'application/x-www-form-urlencoded'
};
const response = await axios.post(SII_URL, new URLSearchParams(payload), { headers });
return response.data;
} catch (error) {
console.error('Error querying SII:', error);
throw error;
}
}
static async getCompanyInfo(rut: string, dv: string): Promise<{
success: boolean;
message: string;
data?: string;
}> {
try {
const captchaImage = await this.getCaptchaImage();
const captchaText = await this.solveCaptcha(captchaImage);
const result = await this.querySII(rut, dv, captchaText);
return {
success: true,
message: 'Successfully retrieved company information',
data: result
};
} catch (error) {
return {
success: false,
message: error instanceof Error ? error.message : 'Failed to get company information'
};
}
}
}