keycae-ts 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +96 -0
- package/dist/index.d.ts +145 -0
- package/dist/index.js +119 -0
- package/package.json +31 -0
- package/src/index.ts +243 -0
- package/tsconfig.json +15 -0
package/README.md
ADDED
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
# keycae-ts 🚀
|
|
2
|
+
|
|
3
|
+
Cliente SDK oficial en **TypeScript** y **JavaScript** para interactuar con la plataforma de **KeyCAE.ar** y emitir facturación electrónica oficial homologada ante **ARCA (ex AFIP)** de forma simple y resiliente.
|
|
4
|
+
|
|
5
|
+
## Instalación
|
|
6
|
+
|
|
7
|
+
Instala el SDK en tu proyecto Node.js/TypeScript:
|
|
8
|
+
|
|
9
|
+
```bash
|
|
10
|
+
npm install keycae-ts
|
|
11
|
+
# O usando yarn / pnpm
|
|
12
|
+
yarn add keycae-ts
|
|
13
|
+
pnpm add keycae-ts
|
|
14
|
+
```
|
|
15
|
+
|
|
16
|
+
## Inicio Rápido (Modelo A: Delegación Directa ⭐)
|
|
17
|
+
|
|
18
|
+
Esta es la forma recomendada por defecto. En minutos podés facturar sin lidiar con llaves privadas o subir archivos de certificados.
|
|
19
|
+
|
|
20
|
+
```typescript
|
|
21
|
+
import { KeyCaeClient } from 'keycae-ts';
|
|
22
|
+
|
|
23
|
+
// 1. Inicializar el cliente con tu API Key
|
|
24
|
+
const client = new KeyCaeClient('sk_test_tu_api_key_aqui');
|
|
25
|
+
|
|
26
|
+
async function main() {
|
|
27
|
+
try {
|
|
28
|
+
// 2. Registrar la delegación (previamente debés adherir el servicio en el portal de ARCA al CUIT representante 20254459306)
|
|
29
|
+
console.log('Iniciando delegación directa...');
|
|
30
|
+
const delegation = await client.createDelegation({
|
|
31
|
+
cuit: '20254459306',
|
|
32
|
+
organization: 'Digital Media S.A.'
|
|
33
|
+
});
|
|
34
|
+
|
|
35
|
+
console.log(`Estado inicial de delegación: ${delegation.status}`);
|
|
36
|
+
|
|
37
|
+
// 3. Emitir una factura electrónica homologada (con CAE y PDF)
|
|
38
|
+
console.log('Emitiendo factura fiscal...');
|
|
39
|
+
const invoice = await client.emitInvoice({
|
|
40
|
+
cuit_emisor: '20254459306',
|
|
41
|
+
punto_de_venta: 1,
|
|
42
|
+
tipo_comprobante: 'C',
|
|
43
|
+
receptor: {
|
|
44
|
+
tipo_doc: 'DNI',
|
|
45
|
+
nro_doc: '35987654'
|
|
46
|
+
},
|
|
47
|
+
conceptos: [
|
|
48
|
+
{
|
|
49
|
+
descripcion: 'Servicios de Consultoría de Software',
|
|
50
|
+
precio: 150000.00
|
|
51
|
+
}
|
|
52
|
+
]
|
|
53
|
+
}, 'idempotency_key_factura_42'); // Idempotency key para prevenir duplicaciones de red
|
|
54
|
+
|
|
55
|
+
console.log('¡Factura autorizada exitosamente!');
|
|
56
|
+
console.log(`Comprobante: Nro. ${invoice.numero_factura}`);
|
|
57
|
+
console.log(`CAE Otorgado: ${invoice.cae}`);
|
|
58
|
+
console.log(`Vencimiento CAE: ${invoice.cae_vencimiento}`);
|
|
59
|
+
console.log(`PDF de Impresión: ${invoice.url_pdf}`);
|
|
60
|
+
console.log(`Código QR Fiscal: ${invoice.url_qr}`);
|
|
61
|
+
|
|
62
|
+
} catch (error) {
|
|
63
|
+
console.error('Error durante la operación:', error);
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
main();
|
|
68
|
+
```
|
|
69
|
+
|
|
70
|
+
## Notificaciones en Tiempo Real (Telegram Alerts)
|
|
71
|
+
|
|
72
|
+
Configurá tu bot de Telegram a través de la API para recibir alertas móviles al instante de cada comprobante emitido:
|
|
73
|
+
|
|
74
|
+
```typescript
|
|
75
|
+
import { KeyCaeClient } from 'keycae-ts';
|
|
76
|
+
|
|
77
|
+
const client = new KeyCaeClient('sk_test_tu_api_key_aqui');
|
|
78
|
+
|
|
79
|
+
async function setupAlerts() {
|
|
80
|
+
// Guardar configuración del Bot
|
|
81
|
+
await client.saveTelegramSettings({
|
|
82
|
+
telegram_bot_token: '123456789:ABCdefGhIjKlMnOpQrStUvWxYz_TOKEN',
|
|
83
|
+
telegram_chat_id: '987654321'
|
|
84
|
+
});
|
|
85
|
+
|
|
86
|
+
// Consultar configuración actual (retorna enmascarada)
|
|
87
|
+
const settings = await client.getTelegramSettings();
|
|
88
|
+
console.log('Ajustes de alertas activos:', settings);
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
setupAlerts();
|
|
92
|
+
```
|
|
93
|
+
|
|
94
|
+
## Licencia
|
|
95
|
+
|
|
96
|
+
MIT
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,145 @@
|
|
|
1
|
+
export interface TaxpayerResponse {
|
|
2
|
+
cuit: string;
|
|
3
|
+
nombre: string;
|
|
4
|
+
tipo_persona: string;
|
|
5
|
+
categoria_monotributo?: string;
|
|
6
|
+
es_iva_inscripto: boolean;
|
|
7
|
+
estado: string;
|
|
8
|
+
}
|
|
9
|
+
export interface InvoiceReceptor {
|
|
10
|
+
tipo_doc: 'DNI' | 'CUIT' | 'CUIL' | 'PASAPORTE';
|
|
11
|
+
nro_doc: string;
|
|
12
|
+
}
|
|
13
|
+
export interface InvoiceItem {
|
|
14
|
+
descripcion: string;
|
|
15
|
+
precio: number;
|
|
16
|
+
}
|
|
17
|
+
export interface InvoiceInput {
|
|
18
|
+
cuit_emisor: string;
|
|
19
|
+
punto_de_venta: number;
|
|
20
|
+
tipo_comprobante: 'A' | 'B' | 'C' | 'M';
|
|
21
|
+
receptor: InvoiceReceptor;
|
|
22
|
+
conceptos: InvoiceItem[];
|
|
23
|
+
brand_logo_url?: string;
|
|
24
|
+
brand_color?: string;
|
|
25
|
+
}
|
|
26
|
+
export interface InvoiceResponse {
|
|
27
|
+
id: string;
|
|
28
|
+
cuit_emisor: string;
|
|
29
|
+
punto_de_venta: number;
|
|
30
|
+
tipo_comprobante: string;
|
|
31
|
+
numero_factura: number;
|
|
32
|
+
cae: string;
|
|
33
|
+
cae_vencimiento: string;
|
|
34
|
+
url_pdf: string;
|
|
35
|
+
url_qr: string;
|
|
36
|
+
total: number;
|
|
37
|
+
}
|
|
38
|
+
export interface BillingStatusResponse {
|
|
39
|
+
cuit: string;
|
|
40
|
+
plan: string;
|
|
41
|
+
invoicesEmitted: number;
|
|
42
|
+
monthlyLimit: number;
|
|
43
|
+
status: string;
|
|
44
|
+
billingPeriodStart: string;
|
|
45
|
+
percentageConsumed: number;
|
|
46
|
+
overageCost: number;
|
|
47
|
+
currency: string;
|
|
48
|
+
}
|
|
49
|
+
export interface TelegramSettingsInput {
|
|
50
|
+
telegram_bot_token: string;
|
|
51
|
+
telegram_chat_id: string;
|
|
52
|
+
}
|
|
53
|
+
export interface TelegramSettingsResponse {
|
|
54
|
+
telegram_bot_token: string;
|
|
55
|
+
telegram_chat_id: string;
|
|
56
|
+
has_credentials: boolean;
|
|
57
|
+
}
|
|
58
|
+
export interface DelegationInput {
|
|
59
|
+
cuit: string;
|
|
60
|
+
organization: string;
|
|
61
|
+
}
|
|
62
|
+
export interface DelegationResponse {
|
|
63
|
+
id: string;
|
|
64
|
+
status: 'pending' | 'accepted' | 'rejected';
|
|
65
|
+
cuit: string;
|
|
66
|
+
organization: string;
|
|
67
|
+
representativeCuit: string;
|
|
68
|
+
representativeOrg: string;
|
|
69
|
+
createdAt: string;
|
|
70
|
+
acceptedAt?: string;
|
|
71
|
+
}
|
|
72
|
+
export interface KmsCredentialInput {
|
|
73
|
+
cuit: string;
|
|
74
|
+
organization: string;
|
|
75
|
+
common_name?: string;
|
|
76
|
+
}
|
|
77
|
+
export interface KmsCredentialResponse {
|
|
78
|
+
id: string;
|
|
79
|
+
cuit: string;
|
|
80
|
+
organization: string;
|
|
81
|
+
common_name: string;
|
|
82
|
+
status: string;
|
|
83
|
+
csr_pem?: string;
|
|
84
|
+
created_at: string;
|
|
85
|
+
}
|
|
86
|
+
export interface KmsImportInput {
|
|
87
|
+
cuit: string;
|
|
88
|
+
organization: string;
|
|
89
|
+
certificate: string;
|
|
90
|
+
private_key: string;
|
|
91
|
+
}
|
|
92
|
+
export declare class KeyCaeClient {
|
|
93
|
+
private apiKey;
|
|
94
|
+
private baseUrl;
|
|
95
|
+
constructor(apiKey: string, baseUrl?: string);
|
|
96
|
+
private request;
|
|
97
|
+
/**
|
|
98
|
+
* Consultar Contribuyente en Padrón ARCA
|
|
99
|
+
*/
|
|
100
|
+
getTaxpayer(cuit: string): Promise<TaxpayerResponse>;
|
|
101
|
+
/**
|
|
102
|
+
* Registrar / Iniciar Direct Delegation
|
|
103
|
+
*/
|
|
104
|
+
createDelegation(data: DelegationInput): Promise<DelegationResponse>;
|
|
105
|
+
/**
|
|
106
|
+
* Consultar Estado de Delegación Directa
|
|
107
|
+
*/
|
|
108
|
+
checkDelegationStatus(): Promise<DelegationResponse>;
|
|
109
|
+
/**
|
|
110
|
+
* Crear Bóveda de Claves KMS & Generar CSR
|
|
111
|
+
*/
|
|
112
|
+
createCredential(data: KmsCredentialInput): Promise<KmsCredentialResponse>;
|
|
113
|
+
/**
|
|
114
|
+
* Importar Credenciales de Firma Existentes (.key y .crt)
|
|
115
|
+
*/
|
|
116
|
+
importCredential(data: KmsImportInput): Promise<KmsCredentialResponse>;
|
|
117
|
+
/**
|
|
118
|
+
* Activar Bóveda KMS con Certificado ARCA (.crt)
|
|
119
|
+
*/
|
|
120
|
+
activateCredential(id: string, certificatePem: string): Promise<any>;
|
|
121
|
+
/**
|
|
122
|
+
* Eliminar Bóveda de Claves KMS de forma física y segura
|
|
123
|
+
*/
|
|
124
|
+
deleteCredential(id: string): Promise<any>;
|
|
125
|
+
/**
|
|
126
|
+
* Emitir Factura Electrónica Homologada (CAE)
|
|
127
|
+
*/
|
|
128
|
+
emitInvoice(data: InvoiceInput, idempotencyKey?: string): Promise<InvoiceResponse>;
|
|
129
|
+
/**
|
|
130
|
+
* Descargar PDF de Factura (Retorna el Stream / ArrayBuffer)
|
|
131
|
+
*/
|
|
132
|
+
getInvoicePdfBuffer(id: string): Promise<Buffer>;
|
|
133
|
+
/**
|
|
134
|
+
* Obtener Consumos y Estado del Plan (Billing)
|
|
135
|
+
*/
|
|
136
|
+
getBillingStatus(): Promise<BillingStatusResponse>;
|
|
137
|
+
/**
|
|
138
|
+
* Obtener Ajustes de Telegram por Tenant
|
|
139
|
+
*/
|
|
140
|
+
getTelegramSettings(): Promise<TelegramSettingsResponse>;
|
|
141
|
+
/**
|
|
142
|
+
* Guardar / Actualizar Ajustes de Telegram
|
|
143
|
+
*/
|
|
144
|
+
saveTelegramSettings(data: TelegramSettingsInput): Promise<any>;
|
|
145
|
+
}
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,119 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.KeyCaeClient = void 0;
|
|
7
|
+
const node_fetch_1 = __importDefault(require("node-fetch"));
|
|
8
|
+
class KeyCaeClient {
|
|
9
|
+
constructor(apiKey, baseUrl = 'https://api.keycae.ar') {
|
|
10
|
+
this.apiKey = apiKey;
|
|
11
|
+
this.baseUrl = baseUrl;
|
|
12
|
+
}
|
|
13
|
+
async request(method, path, body, idempotencyKey) {
|
|
14
|
+
const headers = {
|
|
15
|
+
'Authorization': `Bearer ${this.apiKey}`,
|
|
16
|
+
'Content-Type': 'application/json'
|
|
17
|
+
};
|
|
18
|
+
if (idempotencyKey) {
|
|
19
|
+
headers['Idempotency-Key'] = idempotencyKey;
|
|
20
|
+
}
|
|
21
|
+
const response = await (0, node_fetch_1.default)(`${this.baseUrl}${path}`, {
|
|
22
|
+
method,
|
|
23
|
+
headers,
|
|
24
|
+
body: body ? JSON.stringify(body) : undefined
|
|
25
|
+
});
|
|
26
|
+
if (!response.ok) {
|
|
27
|
+
let errorDetails = '';
|
|
28
|
+
try {
|
|
29
|
+
errorDetails = await response.text();
|
|
30
|
+
}
|
|
31
|
+
catch (e) { }
|
|
32
|
+
throw new Error(`KeyCAE API Error (${response.status}): ${errorDetails || response.statusText}`);
|
|
33
|
+
}
|
|
34
|
+
return response.json();
|
|
35
|
+
}
|
|
36
|
+
/**
|
|
37
|
+
* Consultar Contribuyente en Padrón ARCA
|
|
38
|
+
*/
|
|
39
|
+
async getTaxpayer(cuit) {
|
|
40
|
+
return this.request('GET', `/v1/taxpayers/${cuit}`);
|
|
41
|
+
}
|
|
42
|
+
/**
|
|
43
|
+
* Registrar / Iniciar Direct Delegation
|
|
44
|
+
*/
|
|
45
|
+
async createDelegation(data) {
|
|
46
|
+
return this.request('POST', '/v1/delegations', data);
|
|
47
|
+
}
|
|
48
|
+
/**
|
|
49
|
+
* Consultar Estado de Delegación Directa
|
|
50
|
+
*/
|
|
51
|
+
async checkDelegationStatus() {
|
|
52
|
+
return this.request('GET', '/v1/delegations/status');
|
|
53
|
+
}
|
|
54
|
+
/**
|
|
55
|
+
* Crear Bóveda de Claves KMS & Generar CSR
|
|
56
|
+
*/
|
|
57
|
+
async createCredential(data) {
|
|
58
|
+
return this.request('POST', '/v1/credentials', data);
|
|
59
|
+
}
|
|
60
|
+
/**
|
|
61
|
+
* Importar Credenciales de Firma Existentes (.key y .crt)
|
|
62
|
+
*/
|
|
63
|
+
async importCredential(data) {
|
|
64
|
+
return this.request('POST', '/v1/credentials/import', data);
|
|
65
|
+
}
|
|
66
|
+
/**
|
|
67
|
+
* Activar Bóveda KMS con Certificado ARCA (.crt)
|
|
68
|
+
*/
|
|
69
|
+
async activateCredential(id, certificatePem) {
|
|
70
|
+
return this.request('POST', `/v1/credentials/${id}/certificate`, { certificate: certificatePem });
|
|
71
|
+
}
|
|
72
|
+
/**
|
|
73
|
+
* Eliminar Bóveda de Claves KMS de forma física y segura
|
|
74
|
+
*/
|
|
75
|
+
async deleteCredential(id) {
|
|
76
|
+
return this.request('DELETE', `/v1/credentials/${id}`);
|
|
77
|
+
}
|
|
78
|
+
/**
|
|
79
|
+
* Emitir Factura Electrónica Homologada (CAE)
|
|
80
|
+
*/
|
|
81
|
+
async emitInvoice(data, idempotencyKey) {
|
|
82
|
+
return this.request('POST', '/v1/invoices', data, idempotencyKey);
|
|
83
|
+
}
|
|
84
|
+
/**
|
|
85
|
+
* Descargar PDF de Factura (Retorna el Stream / ArrayBuffer)
|
|
86
|
+
*/
|
|
87
|
+
async getInvoicePdfBuffer(id) {
|
|
88
|
+
const response = await (0, node_fetch_1.default)(`${this.baseUrl}/v1/invoices/${id}/pdf`, {
|
|
89
|
+
method: 'GET',
|
|
90
|
+
headers: {
|
|
91
|
+
'Authorization': `Bearer ${this.apiKey}`
|
|
92
|
+
}
|
|
93
|
+
});
|
|
94
|
+
if (!response.ok) {
|
|
95
|
+
throw new Error(`Failed to fetch PDF (${response.status})`);
|
|
96
|
+
}
|
|
97
|
+
const arrayBuffer = await response.arrayBuffer();
|
|
98
|
+
return Buffer.from(arrayBuffer);
|
|
99
|
+
}
|
|
100
|
+
/**
|
|
101
|
+
* Obtener Consumos y Estado del Plan (Billing)
|
|
102
|
+
*/
|
|
103
|
+
async getBillingStatus() {
|
|
104
|
+
return this.request('GET', '/v1/billing/status');
|
|
105
|
+
}
|
|
106
|
+
/**
|
|
107
|
+
* Obtener Ajustes de Telegram por Tenant
|
|
108
|
+
*/
|
|
109
|
+
async getTelegramSettings() {
|
|
110
|
+
return this.request('GET', '/v1/settings/telegram');
|
|
111
|
+
}
|
|
112
|
+
/**
|
|
113
|
+
* Guardar / Actualizar Ajustes de Telegram
|
|
114
|
+
*/
|
|
115
|
+
async saveTelegramSettings(data) {
|
|
116
|
+
return this.request('POST', '/v1/settings/telegram', data);
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
exports.KeyCaeClient = KeyCaeClient;
|
package/package.json
ADDED
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "keycae-ts",
|
|
3
|
+
"version": "1.0.0",
|
|
4
|
+
"description": "Official TypeScript & JavaScript SDK client for KeyCAE.ar impositive compliance API (ARCA)",
|
|
5
|
+
"main": "dist/index.js",
|
|
6
|
+
"types": "dist/index.d.ts",
|
|
7
|
+
"scripts": {
|
|
8
|
+
"build": "tsc",
|
|
9
|
+
"prepublishOnly": "npm run build"
|
|
10
|
+
},
|
|
11
|
+
"keywords": [
|
|
12
|
+
"arca",
|
|
13
|
+
"afip",
|
|
14
|
+
"factura-electronica",
|
|
15
|
+
"compliance",
|
|
16
|
+
"sdk",
|
|
17
|
+
"client",
|
|
18
|
+
"keycae",
|
|
19
|
+
"argentina"
|
|
20
|
+
],
|
|
21
|
+
"author": "KeyCAE Community",
|
|
22
|
+
"license": "MIT",
|
|
23
|
+
"dependencies": {
|
|
24
|
+
"node-fetch": "^2.6.9"
|
|
25
|
+
},
|
|
26
|
+
"devDependencies": {
|
|
27
|
+
"@types/node": "^18.15.11",
|
|
28
|
+
"@types/node-fetch": "^2.6.3",
|
|
29
|
+
"typescript": "^5.0.4"
|
|
30
|
+
}
|
|
31
|
+
}
|
package/src/index.ts
ADDED
|
@@ -0,0 +1,243 @@
|
|
|
1
|
+
import fetch from 'node-fetch';
|
|
2
|
+
|
|
3
|
+
export interface TaxpayerResponse {
|
|
4
|
+
cuit: string;
|
|
5
|
+
nombre: string;
|
|
6
|
+
tipo_persona: string;
|
|
7
|
+
categoria_monotributo?: string;
|
|
8
|
+
es_iva_inscripto: boolean;
|
|
9
|
+
estado: string;
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
export interface InvoiceReceptor {
|
|
13
|
+
tipo_doc: 'DNI' | 'CUIT' | 'CUIL' | 'PASAPORTE';
|
|
14
|
+
nro_doc: string;
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
export interface InvoiceItem {
|
|
18
|
+
descripcion: string;
|
|
19
|
+
precio: number;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
export interface InvoiceInput {
|
|
23
|
+
cuit_emisor: string;
|
|
24
|
+
punto_de_venta: number;
|
|
25
|
+
tipo_comprobante: 'A' | 'B' | 'C' | 'M';
|
|
26
|
+
receptor: InvoiceReceptor;
|
|
27
|
+
conceptos: InvoiceItem[];
|
|
28
|
+
brand_logo_url?: string;
|
|
29
|
+
brand_color?: string;
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
export interface InvoiceResponse {
|
|
33
|
+
id: string;
|
|
34
|
+
cuit_emisor: string;
|
|
35
|
+
punto_de_venta: number;
|
|
36
|
+
tipo_comprobante: string;
|
|
37
|
+
numero_factura: number;
|
|
38
|
+
cae: string;
|
|
39
|
+
cae_vencimiento: string;
|
|
40
|
+
url_pdf: string;
|
|
41
|
+
url_qr: string;
|
|
42
|
+
total: number;
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
export interface BillingStatusResponse {
|
|
46
|
+
cuit: string;
|
|
47
|
+
plan: string;
|
|
48
|
+
invoicesEmitted: number;
|
|
49
|
+
monthlyLimit: number;
|
|
50
|
+
status: string;
|
|
51
|
+
billingPeriodStart: string;
|
|
52
|
+
percentageConsumed: number;
|
|
53
|
+
overageCost: number;
|
|
54
|
+
currency: string;
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
export interface TelegramSettingsInput {
|
|
58
|
+
telegram_bot_token: string;
|
|
59
|
+
telegram_chat_id: string;
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
export interface TelegramSettingsResponse {
|
|
63
|
+
telegram_bot_token: string;
|
|
64
|
+
telegram_chat_id: string;
|
|
65
|
+
has_credentials: boolean;
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
export interface DelegationInput {
|
|
69
|
+
cuit: string;
|
|
70
|
+
organization: string;
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
export interface DelegationResponse {
|
|
74
|
+
id: string;
|
|
75
|
+
status: 'pending' | 'accepted' | 'rejected';
|
|
76
|
+
cuit: string;
|
|
77
|
+
organization: string;
|
|
78
|
+
representativeCuit: string;
|
|
79
|
+
representativeOrg: string;
|
|
80
|
+
createdAt: string;
|
|
81
|
+
acceptedAt?: string;
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
export interface KmsCredentialInput {
|
|
85
|
+
cuit: string;
|
|
86
|
+
organization: string;
|
|
87
|
+
common_name?: string;
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
export interface KmsCredentialResponse {
|
|
91
|
+
id: string;
|
|
92
|
+
cuit: string;
|
|
93
|
+
organization: string;
|
|
94
|
+
common_name: string;
|
|
95
|
+
status: string;
|
|
96
|
+
csr_pem?: string;
|
|
97
|
+
created_at: string;
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
export interface KmsImportInput {
|
|
101
|
+
cuit: string;
|
|
102
|
+
organization: string;
|
|
103
|
+
certificate: string;
|
|
104
|
+
private_key: string;
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
export class KeyCaeClient {
|
|
108
|
+
private apiKey: string;
|
|
109
|
+
private baseUrl: string;
|
|
110
|
+
|
|
111
|
+
constructor(apiKey: string, baseUrl: string = 'https://api.keycae.ar') {
|
|
112
|
+
this.apiKey = apiKey;
|
|
113
|
+
this.baseUrl = baseUrl;
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
private async request<T>(
|
|
117
|
+
method: string,
|
|
118
|
+
path: string,
|
|
119
|
+
body?: any,
|
|
120
|
+
idempotencyKey?: string
|
|
121
|
+
): Promise<T> {
|
|
122
|
+
const headers: Record<string, string> = {
|
|
123
|
+
'Authorization': `Bearer ${this.apiKey}`,
|
|
124
|
+
'Content-Type': 'application/json'
|
|
125
|
+
};
|
|
126
|
+
|
|
127
|
+
if (idempotencyKey) {
|
|
128
|
+
headers['Idempotency-Key'] = idempotencyKey;
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
const response = await fetch(`${this.baseUrl}${path}`, {
|
|
132
|
+
method,
|
|
133
|
+
headers,
|
|
134
|
+
body: body ? JSON.stringify(body) : undefined
|
|
135
|
+
});
|
|
136
|
+
|
|
137
|
+
if (!response.ok) {
|
|
138
|
+
let errorDetails = '';
|
|
139
|
+
try {
|
|
140
|
+
errorDetails = await response.text();
|
|
141
|
+
} catch (e) {}
|
|
142
|
+
throw new Error(`KeyCAE API Error (${response.status}): ${errorDetails || response.statusText}`);
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
return response.json() as Promise<T>;
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
/**
|
|
149
|
+
* Consultar Contribuyente en Padrón ARCA
|
|
150
|
+
*/
|
|
151
|
+
async getTaxpayer(cuit: string): Promise<TaxpayerResponse> {
|
|
152
|
+
return this.request<TaxpayerResponse>('GET', `/v1/taxpayers/${cuit}`);
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
/**
|
|
156
|
+
* Registrar / Iniciar Direct Delegation
|
|
157
|
+
*/
|
|
158
|
+
async createDelegation(data: DelegationInput): Promise<DelegationResponse> {
|
|
159
|
+
return this.request<DelegationResponse>('POST', '/v1/delegations', data);
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
/**
|
|
163
|
+
* Consultar Estado de Delegación Directa
|
|
164
|
+
*/
|
|
165
|
+
async checkDelegationStatus(): Promise<DelegationResponse> {
|
|
166
|
+
return this.request<DelegationResponse>('GET', '/v1/delegations/status');
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
/**
|
|
170
|
+
* Crear Bóveda de Claves KMS & Generar CSR
|
|
171
|
+
*/
|
|
172
|
+
async createCredential(data: KmsCredentialInput): Promise<KmsCredentialResponse> {
|
|
173
|
+
return this.request<KmsCredentialResponse>('POST', '/v1/credentials', data);
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
/**
|
|
177
|
+
* Importar Credenciales de Firma Existentes (.key y .crt)
|
|
178
|
+
*/
|
|
179
|
+
async importCredential(data: KmsImportInput): Promise<KmsCredentialResponse> {
|
|
180
|
+
return this.request<KmsCredentialResponse>('POST', '/v1/credentials/import', data);
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
/**
|
|
184
|
+
* Activar Bóveda KMS con Certificado ARCA (.crt)
|
|
185
|
+
*/
|
|
186
|
+
async activateCredential(id: string, certificatePem: string): Promise<any> {
|
|
187
|
+
return this.request<any>('POST', `/v1/credentials/${id}/certificate`, { certificate: certificatePem });
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
/**
|
|
191
|
+
* Eliminar Bóveda de Claves KMS de forma física y segura
|
|
192
|
+
*/
|
|
193
|
+
async deleteCredential(id: string): Promise<any> {
|
|
194
|
+
return this.request<any>('DELETE', `/v1/credentials/${id}`);
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
/**
|
|
198
|
+
* Emitir Factura Electrónica Homologada (CAE)
|
|
199
|
+
*/
|
|
200
|
+
async emitInvoice(data: InvoiceInput, idempotencyKey?: string): Promise<InvoiceResponse> {
|
|
201
|
+
return this.request<InvoiceResponse>('POST', '/v1/invoices', data, idempotencyKey);
|
|
202
|
+
}
|
|
203
|
+
|
|
204
|
+
/**
|
|
205
|
+
* Descargar PDF de Factura (Retorna el Stream / ArrayBuffer)
|
|
206
|
+
*/
|
|
207
|
+
async getInvoicePdfBuffer(id: string): Promise<Buffer> {
|
|
208
|
+
const response = await fetch(`${this.baseUrl}/v1/invoices/${id}/pdf`, {
|
|
209
|
+
method: 'GET',
|
|
210
|
+
headers: {
|
|
211
|
+
'Authorization': `Bearer ${this.apiKey}`
|
|
212
|
+
}
|
|
213
|
+
});
|
|
214
|
+
|
|
215
|
+
if (!response.ok) {
|
|
216
|
+
throw new Error(`Failed to fetch PDF (${response.status})`);
|
|
217
|
+
}
|
|
218
|
+
|
|
219
|
+
const arrayBuffer = await response.arrayBuffer();
|
|
220
|
+
return Buffer.from(arrayBuffer);
|
|
221
|
+
}
|
|
222
|
+
|
|
223
|
+
/**
|
|
224
|
+
* Obtener Consumos y Estado del Plan (Billing)
|
|
225
|
+
*/
|
|
226
|
+
async getBillingStatus(): Promise<BillingStatusResponse> {
|
|
227
|
+
return this.request<BillingStatusResponse>('GET', '/v1/billing/status');
|
|
228
|
+
}
|
|
229
|
+
|
|
230
|
+
/**
|
|
231
|
+
* Obtener Ajustes de Telegram por Tenant
|
|
232
|
+
*/
|
|
233
|
+
async getTelegramSettings(): Promise<TelegramSettingsResponse> {
|
|
234
|
+
return this.request<TelegramSettingsResponse>('GET', '/v1/settings/telegram');
|
|
235
|
+
}
|
|
236
|
+
|
|
237
|
+
/**
|
|
238
|
+
* Guardar / Actualizar Ajustes de Telegram
|
|
239
|
+
*/
|
|
240
|
+
async saveTelegramSettings(data: TelegramSettingsInput): Promise<any> {
|
|
241
|
+
return this.request<any>('POST', '/v1/settings/telegram', data);
|
|
242
|
+
}
|
|
243
|
+
}
|
package/tsconfig.json
ADDED
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
{
|
|
2
|
+
"compilerOptions": {
|
|
3
|
+
"target": "ES2020",
|
|
4
|
+
"module": "commonjs",
|
|
5
|
+
"lib": ["es6", "dom"],
|
|
6
|
+
"declaration": true,
|
|
7
|
+
"outDir": "./dist",
|
|
8
|
+
"rootDir": "./src",
|
|
9
|
+
"strict": true,
|
|
10
|
+
"esModuleInterop": true,
|
|
11
|
+
"skipLibCheck": true,
|
|
12
|
+
"forceConsistentCasingInFileNames": true
|
|
13
|
+
},
|
|
14
|
+
"include": ["src/**/*"]
|
|
15
|
+
}
|