clisitef-dll
v0.1.3
Published
Biblioteca Node.js/TypeScript para integração TEF via CliSiTef (Software Express) usando koffi (FFI). Carrega a DLL de 32 ou 64 bits conforme a arquitetura do processo e oferece controle completo do fluxo interativo de pagamento com a maquineta/pinpad.
Maintainers
Readme
clisitef-dll
Biblioteca Node.js + TypeScript para integração TEF via CliSiTef (Software Express),
usando koffi (FFI) para chamar as DLLs nativas. Carrega
automaticamente a DLL de 32 ou 64 bits conforme a arquitetura do processo e
oferece controle completo do fluxo interativo de pagamento com a maquineta/pinpad.
Baseada na Interface Simplificada (funções
*SiTefInterativo) do CliSiTef versão7.0.117.112.r12.
Como funciona
A CliSiTef usa um modelo interativo: você inicia uma função (venda, cancelamento,
etc.) e depois chama ContinuaFuncaoSiTefInterativo em loop. A cada volta a DLL
devolve um comando dizendo o que a automação deve fazer (exibir mensagem, coletar
um campo, mostrar menu, perguntar sim/não, gravar um campo de resultado...). Esta lib
encapsula esse loop e expõe um handler com callbacks para cada situação.
configure() -> ConfiguraIntSiTefInterativoEx
transacao() -> IniciaFuncaoSiTefInterativo + loop ContinuaFuncaoSiTefInterativo
confirmar() -> FinalizaTransacaoSiTefInterativo (confirma = 1)
desfazer() -> FinalizaTransacaoSiTefInterativo (confirma = 0)⚠️ 32 vs 64 bits (leia antes!)
- O
kofficarrega a DLL dentro do processo Node. Um processo Node x64 só carrega a DLL de 64 bits (CliSiTef64I.dll); um Node 32 bits (ia32) só carrega a de 32 bits (CliSiTef32I.dll). - A escolha é feita por
process.arch— não pela arquitetura do Windows. - Seu Node atual: rode
node -p "process.arch". Se forx64, será usada a DLL de 64 bits. - Para usar a DLL de 32 bits, rode um Node 32 bits (ou faça uma ponte fora de processo).
As DLLs NÃO acompanham o pacote. Você informa a pasta onde elas estão via
dllDir (ou o caminho completo via dllPath). Essa pasta deve conter a DLL
principal (CliSiTef64I.dll / CliSiTef32I.dll) e as dependências
(libcurl*, libemv*, QREncode*). A lib adiciona esse diretório ao PATH do
processo para que as dependências sejam resolvidas.
Somente Windows.
Instalação
npm install
npm run buildDependências: koffi (runtime), typescript/@types/node (dev).
Uso
import { CliSiTef, SiTefFunction, SiTefField } from 'clisitef-dll';
const tef = new CliSiTef({
dllDir: 'C:/clisitef', // pasta com as DLLs (obrigatório)
});
console.log(tef.info); // { arch, dllPath }
tef.configure({
enderecoSiTef: '127.0.0.1', // SiTef local
codigoLoja: '00000000',
numeroTerminal: 'AMB00001',
});
try {
const r = await tef.transacao(
{ funcao: SiTefFunction.Credito, valor: 10.5, operador: 'CAIXA01' },
{
onMessage: (m) => console.log(`[${m.target}] ${m.text}`),
onField: (f) => console.log(`campo ${f.type} = ${f.value}`),
confirm: (msg) => true, // responde sim/não
menu: (req) => 0, // escolhe opção
field: (req) => '...', // digita um campo (ou 'cancelar')
waitKey: () => {},
interrupt: () => false,
},
);
if (r.sucesso) {
console.log('NSU:', r.campo(SiTefField.NsuSiTef));
console.log('Autorização:', r.campo(SiTefField.CodigoAutorizacao));
r.confirmar(); // após imprimir o comprovante
} else {
console.error(r.returnCode, r.descricao);
}
} catch (err) {
// Um callback lançou: a transação já foi abortada limpa; só tratamos o erro.
console.error('Transação abortada:', err);
} finally {
tef.close();
}Exemplo interativo completo (com readline): examples/venda.ts.
API
new CliSiTef(options)
options.dllDir— diretório das DLLs (obrigatório; as DLLs não vêm no pacote).options.dllPath— caminho completo da DLL principal (alternativa adllDir).
É obrigatório informar
dllDiroudllPath— caso contrário o construtor lança erro.
configure(config)
Mapeia ConfiguraIntSiTefInterativoEx. Lança erro se o retorno ≠ 0.
enderecoSiTef,codigoLoja,numeroTerminal,parametrosAdicionais?,reservado?.
transacao(params, handler) => Promise<TransactionResult>
params.funcao—SiTefFunctionou número (0 = pagamento genérico, 2 = débito, 3 = crédito, 200 = cancelamento, 110 = administrativo, ...).params.valor— número (ex.:10.5→"10,50") ou string já formatada (vírgula decimal, 2 casas).params.cupomFiscal?,dataFiscal?(AAAAMMDD),horaFiscal?(HHMMSS),operador?,parametrosAdicionais?.
Helpers de transação (atalhos sobre transacao)
Todos têm a forma (params?, handler?) => Promise<TransactionResult>, onde
params é igual ao de transacao sem funcao (TransacaoParams):
| método | função | uso |
|---|---|---|
| cancelamento(params?, handler?) | 200 | cancelar/estornar uma venda (informe valor/data/NSU originais pelo fluxo) |
| reimpressao(params?, handler?) | 112 | reimprimir comprovante |
| fechamento(params?, handler?) | 999 | fechamento de lote/dia |
| administrativo(params?, handler?) | 110 | menu de funções gerenciais |
await tef.cancelamento({ valor: 10.5, operador: 'CAIXA01' }, handler);
await tef.fechamento({}, handler);InteractionHandler (todos opcionais)
| callback | comandos CliSiTef | retorno esperado |
|---|---|---|
| onMessage({target,text,cabecalho}) | 1, 2, 3, 15 | — |
| onClear(target) | 11–14, 16 | — |
| onMenuTitle(title) | 4 | — |
| onField({type,value}) | 0 (campos de resultado) | — |
| confirm(message) | 20 | boolean | 'voltar' | 'cancelar' |
| menu(req) | 21, 42 | número/string da opção | 'voltar' | 'cancelar' |
| field(req) | 29, 30, 31, 34, 35, 41 | string | 'voltar' | 'cancelar' |
| waitKey(message) | 22 | — |
| interrupt() | 23 | boolean (default false) |
Callbacks de coleta não implementados assumem
'cancelar'(o loop nunca trava).'voltar'→Continua = 1(campo anterior);'cancelar'→Continua = -1(encerra).
Cancelar é com
'cancelar', não fechando recursos. Para abortar a transação, faça um callback retornar'cancelar'— o loop manda o sinalEncerraao SiTef e sai limpo. Não feche recursos usados pelos callbacks (ex.:readline) por baixo do loop: o próximo comando da DLL chamaria o callback de novo e ele lançaria (ex.:ERR_USE_AFTER_CLOSE). Use um flag de cancelamento que faça os callbacks retornarem'cancelar'.
TransactionResult
returnCode,sucesso,descricao.campos: { type, value }[]— todos os campos de resultado.campo(type)— último valor de umTipoCampo(vejaSiTefField).confirmar(cupom?, data?, hora?)—FinalizaTransacaoSiTefInterativo(1, ...)(só se sucesso).desfazer(cupom?, data?, hora?)—FinalizaTransacaoSiTefInterativo(0, ...).
mensagemPinpad(texto, opts?)
EscreveMensagemPermanentePinPad (se disponível na DLL). Mensagem de runtime.
opts.centralizar— centraliza cada linha (|quebra linha).opts.largura(default 16).- Mensagem vazia (
'') limpa o display.
Mensagem padrão de repouso (CliSiTef.ini)
A mensagem de repouso do pinpad vem da chave [PinPad] MensagemPadrao do
CliSiTef.ini e é aplicada pela própria CliSiTef (não passa por mensagemPinpad).
Para defini-la (com centralização opcional), edite o .ini antes de
configure():
import { definirMensagemPadrao, lerMensagemPadrao } from 'clisitef-dll';
definirMensagemPadrao('C:/clisitef/CliSiTef.ini', 'Ambar Energia|Bem-vindo', {
centralizar: true, // largura: 16 (default)
});
lerMensagemPadrao('C:/clisitef/CliSiTef.ini'); // -> " Ambar Energia| Bem-vindo"A edição preserva a estrutura/comentários do arquivo e respeita o encoding
Latin-1. Cria a seção/chave se não existirem (criarSeNaoExistir: false para
exigir que o arquivo já exista).
⚠️ Alguns modelos de pinpad removem espaços à esquerda ao exibir a
MensagemPadraodo.ini. Se a centralização não aparecer no seu equipamento, use a mensagem de runtimetef.mensagemPinpad(texto, { centralizar: true }).
Campos de resultado úteis (SiTefField)
100/101/102 forma de pagamento · 105 data/hora · 131 instituição ·
132 tipo de cartão · 133 NSU SiTef · 134 NSU host · 135 autorização ·
136 BIN · 157 estabelecimento · 158 rede. (Tabela completa de TipoCampo na
documentação oficial.)
Notas importantes
- Confirmação obrigatória: transações de cartão ficam pendentes no SiTef até
você chamar
confirmar()(após imprimir o comprovante) oudesfazer(). Não deixe de finalizar. - Erro em callback aborta limpo: se um callback do
InteractionHandlerlançar exceção durante a transação, a lib encerra o fluxo interativo (sinalEncerra, sem deixar a transação pendente no SiTef) e a Promise detransacao()rejeita com um erro claro (a exceção original fica em.cause). Por isso, envolva a chamada emtry/catch. CliSiTef.inié lido do diretório de trabalho do processo. Ajuste porta do pinpad, logs etc. (há exemplos emdlls/.../CliSiTef.ini).- Encoding: strings trafegam em Latin-1/Windows-1252 (acentuação preservada automaticamente).
- Homologação: o
CliSiTef.iniincluso está comEmAmbienteDeHomologacao=1.
Referências (Software Express — Portal do Desenvolvedor)
- Especificação Técnica CliSiTef
- Início da transação de Pagamento
- Continuação do processo de coleta iterativo
- Tabela de códigos de Comando
- Tabela de códigos de funções
- Tabela de valores para TipoCampo
Licença
MIT (o código desta lib). As DLLs do CliSiTef são da Software Express e regidas pelas
suas próprias licenças — veja os arquivos em dlls/.
