Guia comunitário oficial
Construa conectores como peças bem encaixadas.
Este manual foi feito para programadores da comunidade. A ideia é simples: você copia o modelo, troca os nomes e contratos, implementa o handler, valida localmente e envia um pacote limpo, sem segredos e sem depender de detalhes internos da instalação.
DeclarativoManifesto, formato e catálogo dizem ao sistema o que existe.
ExecutávelO handler recebe uma mensagem JSON e faz o trabalho real.
SeguroSegredos ficam fora do pacote; respostas usam o canal oficial.
Rosa vivo = preencher/adaptarNomes do conector, campos do payload, ações, exemplos, URLs, credenciais de exemplo e mensagens de negócio.
Verde vivo = automático/fixo do kitValores preservados pelo ambiente, correlação recebida, padrões do kit e campos resolvidos pelo canal oficial.
manual-conector.html / visão-geral
O que é um conector
Um conector é uma ponte entre o SISC e um serviço externo: pagamento, CRM, agenda, estoque, OCR, mensageria, planilhas, ERP etc.
Em uma frase: o conector recebe um comando padronizado, valida os dados, chama o serviço externo e devolve um resultado padronizado.
Mapa mental
No pacote real, pense assim:
entrada JSON ──► handler executável ──► serviço externo
▲ │
└──────── resultado pelo canal oficial ◄┘
ManifestoIdentifica o conector e lista seus arquivos.
FormatoDefine campos de entrada e saída.
HandlerExecuta a integração de verdade.
CatálogoDeclara as mensagens públicas aceitas.
manual-conector.html / passo-a-passo
Passo a passo recomendado
Siga esta ordem para evitar retrabalho.
Roteiro de construção
No trabalho real, execute mentalmente esta sequência:
1. Copie o conector-modelo
2. Renomeie para conector-<nome-do-servico>
3. Atualize manifesto, formato e catálogo
4. Implemente o handler
5. Crie uma mensagem de teste segura
6. Rode o validador local
7. Corrija avisos/erros
8. Empacote e envie pelo canal comunitário
1Comece pequeno
Implemente uma operação simples, teste, depois adicione outras.
2Valide sempre
Não espere o final para descobrir que o pacote está fora do padrão.
3Documente como se outra pessoa fosse usar amanhã
Porque provavelmente será exatamente isso que vai acontecer.
manual-conector.html / legenda-de-valores
Legenda: o que você preenche e o que não mexe
Exemplo visual
Nos blocos de código deste manual:
{
"nome": "conector-<seu-servico>",
"handler": "./conectores/conector-<seu-servico>/handlers/<executavel>",
"processoId": "preservado-da-mensagem-recebida",
"respostaA": "mensagem-original-recebida"
}
| Cor | Significado |
|---|
| Rosa | Você deve trocar pelo nome, operação, campo, caminho ou exemplo do seu conector. |
| Verde | Valor que vem do ambiente, da mensagem recebida, do kit ou do canal oficial. Não invente do zero. |
conectores/conector-<nome>/conector-<nome>.json
Manifesto do conector
É a identidade do conector. Ele diz quem o conector é, onde está o handler, qual formato usa e quais arquivos formam o pacote.
Modelo de manifesto
No arquivo real, este tópico aparece assim:
{
"nome": "conector-<seu-servico>",
"titulo": "Conector <Seu Serviço>",
"descricao": "Explique em uma frase qual serviço externo este conector integra.",
"versao": "1.0.0",
"ativo": true,
"tipo": "conector",
"controlador": {
"executavel": "valor-fixo-fornecido-pelo-kit",
"metodoLeitura": "ler-mensagem",
"metodoEnvio": "canal-oficial-de-publicacao",
"handlerLerMensagem": "./conectores/conector-<seu-servico>/handlers/<executavel>"
},
"formatoConector": "conectores/conector-<seu-servico>/formatos/formato-conector-<seu-servico>.json",
"testeSandbox": {
"permitido": true,
"semEfeitoReal": true,
"mensagem": "testes/mensagem-exemplo.json",
"descricao": "Explique por que esta mensagem de teste não envia dados reais nem altera produção."
},
"dependencias": {
"fonteSeguraImportacao": true,
"arquivos": [
{"papel": "manifesto", "origem": "conectores/conector-<seu-servico>/conector-<seu-servico>.json", "destino": "conectores/conector-<seu-servico>/conector-<seu-servico>.json", "obrigatorio": true},
{"papel": "formato", "origem": "conectores/conector-<seu-servico>/formatos/formato-conector-<seu-servico>.json", "destino": "conectores/conector-<seu-servico>/formatos/formato-conector-<seu-servico>.json", "obrigatorio": true},
{"papel": "handler", "origem": "conectores/conector-<seu-servico>/handlers/<executavel>", "destino": "conectores/conector-<seu-servico>/handlers/<executavel>", "obrigatorio": true}
]
}
}
| Campo | Como preencher |
|---|
nome | Use conector- + nome curto em minúsculas e hífens. |
titulo | Nome humano para aparecer em documentação. |
controlador | Mantenha os valores fixos que vêm no modelo e altere apenas o caminho do handler. |
testeSandbox | Declare somente quando a mensagem de teste puder rodar sem efeito real; isso habilita o selo de sandbox no servidor. |
dependencias.arquivos | Liste todo arquivo que precisa viajar no pacote. |
formatos/formato-conector-<nome>.json
Formato do payload
O formato é o contrato entre quem chama e quem executa. Sem ele, cada pessoa imagina um payload diferente.
Modelo de formato
No arquivo real, este tópico aparece assim:
{
"tipo": "formato-conector",
"nome": "formato-conector-<seu-servico>",
"versao": "1.0.0",
"conector": "conector-<seu-servico>",
"descricao": "Contrato de entrada e saída do conector.",
"entrada": {
"modelos": {
"comando-principal": {
"campos": {
"acao": {"tipo": "string", "obrigatorio": true, "valoresAceitos": ["executar"]},
"identificador": {"tipo": "string", "obrigatorio": true},
"opcoes": {"tipo": "object", "obrigatorio": false}
},
"regras": ["acao deve ser executar", "identificador deve existir"],
"exemplo": {"acao": "executar", "identificador": "ABC-123"}
}
}
},
"saida": {
"modelos": {
"resultado": {
"campos": {
"sucesso": {"tipo": "bool", "obrigatorio": true},
"dados": {"tipo": "object", "obrigatorio": false},
"erro": {"tipo": "object", "obrigatorio": false}
}
}
}
}
}
Dica: descreva o payload como se o consumidor nunca tivesse visto seu serviço externo. Campo sem descrição vira dúvida na integração.
handlers/<executavel>
Handler
O handler é o programa executável. Ele recebe o caminho de um arquivo JSON de mensagem, valida tudo e executa a integração.
Esqueleto mínimo em pseudocódigo
No arquivo real, a lógica deve seguir esta forma:
iniciar programa
se quantidade_de_argumentos != 1:
encerrar_com_erro("uso: handler <arquivo-mensagem>")
mensagem = ler_json(argumento_1)
protocolo = mensagem["_protocolo"]
dados = mensagem["payload"]["dados"]
validar campos obrigatórios
carregar configuração segura, se necessário
chamar serviço externo
montar resultado
publicar ou imprimir resposta conforme contrato
encerrar_com_sucesso()
Exemplo mínimo em Python
No arquivo real, poderia ser assim:
#!/usr/bin/env python3
import json, sys
if len(sys.argv) != 2:
print("uso: handler <arquivo-mensagem>", file=sys.stderr)
sys.exit(64)
with open(sys.argv[1], "r", encoding="utf-8") as f:
msg = json.load(f)
dados = msg.get("payload", {}).get("dados", {})
if not isinstance(dados, dict):
print("payload.dados ausente ou inválido", file=sys.stderr)
sys.exit(65)
print(json.dumps({"sucesso": True, "dadosRecebidos": dados}, ensure_ascii=False))
sys.exit(0)
manual-do-conector.html
Manual do seu conector
Cada conector deve ter seu próprio manual para quem vai consumi-lo depois de instalado. Escreva como programador do conector: o leitor precisa conhecer somente o conector, o destino SISC, o idmensagem no catalogo e o contrato de payload.dados.
Não documente bastidor do servidor: o manual do conector não deve citar scripts operacionais, comandos internos de aprovação, caminhos administrativos ou detalhes de instalação do servidor. Essas informações pertencem ao operador SISC, não ao consumidor do conector.
Padrão mínimo de qualidade
No HTML real, inclua seções equivalentes a estas:
<h1>Manual de uso do conector-<seu-servico></h1>
<h2>Identificação</h2> <!-- conector, destino SISC, catalogo, idmensagem -->
<h2>Objetivo</h2> <!-- o que a integração entrega ao consumidor -->
<h2>Operações disponíveis</h2> <!-- tabela: operação, idmensagem, campos, descrição -->
<h2>Payload de entrada</h2> <!-- tabela: campo, tipo, obrigatoriedade, descrição -->
<h2>Exemplo de payload</h2>
<h2>Exemplo de mensagem SISC</h2>
<h2>Saída esperada</h2>
<h2>Programa de exemplo</h2> <!-- caminho, o que demonstra e saída do --self-test -->
<h2>Credenciais necessárias</h2> <!-- sem segredo real; diga o que o ambiente precisa -->
<h2>Erros comuns</h2> <!-- tabela: erro, causa provável, ação -->
<h2>Limites</h2> <!-- timeout, precisão, rate limit, compatibilidade -->
<h2>Segurança de uso</h2> <!-- cuidado com dados sensíveis e idempotencia -->
<h2>Boas práticas para consumidores</h2>
Critérios que o validador cobra
- HTML completo com
<html>, <head>, <body> e CSS próprio de leitura.
- Conteúdo substancial, no padrão do
manual-conector-email.html: não basta uma página curta.
- Ao menos duas tabelas: uma para operações/campos e outra para erros, limites ou contrato.
- Ao menos três blocos de exemplo em
<pre><code>.
- Identificação explícita de
conector-<nome>, conector__conector-<nome>, catalogo e idmensagem.
- Explicação de
payload.dados, saída esperada, credenciais, erros comuns, limites, segurança de uso e idempotencia.
- Programa de exemplo em
conectores/conector-<nome>/exemplos/exemplo-uso.php, documentado no manual, demonstrando uma chamada realista do recurso do conector.
- Nenhum token, senha, chave real, caminho administrativo ou instrução que dependa de detalhes internos do servidor.
Programa de exemplo obrigatório
Além do manual, entregue um programa PHP em conectores/conector-<nome>/exemplos/exemplo-uso.php. Ele deve montar a mensagem ou o payload com o idmensagem do catalogo e os campos reais de payload.dados.
php conectores/conector-<nome>/exemplos/exemplo-uso.php
php conectores/conector-<nome>/exemplos/exemplo-uso.php --self-test
O modo --self-test deve imprimir JSON válido com sucesso:true, conector, idmensagem, payload.dados e saidaEsperada. O validador executa esse modo e confere se o exemplo produz o que declarou produzir.
Como o programador sabe se está bom: copie o nível de detalhamento do conectores/conector-modelo/manual-conector-modelo.html, adapte para seu serviço e rode ./validar-conector. O validador reprova manual raso, genérico, sem exemplo validável ou com bastidor interno do servidor.
catalogo-de-mensagens.json
Catálogo de mensagens
O catálogo declara quais comandos seu conector aceita e como eles aparecem para integrações autorizadas.
Modelo de catálogo
No arquivo real, este tópico aparece assim:
{
"tipo": "catalogo-modulo-mensagens-sisc",
"versao": 1,
"nome": "catalogo-conector-<seu-servico>",
"modulo": "conector-<seu-servico>",
"destino": "conector__conector-<seu-servico>",
"descricao": "Mensagens públicas do conector.",
"mensagens": [
{
"idmensagem": "conector-<seu-servico>.executar",
"publica": true,
"ativo": true,
"nome": "Executar conector <Seu Serviço>",
"destino": "conector__conector-<seu-servico>",
"tipoMensagem": "comando",
"prioridade": "normal",
"idempotenciaObrigatoria": true,
"correlacaoObrigatoria": true
}
]
}
| Campo | Por que importa |
|---|
idmensagem | É o nome público do comando. |
publica | Indica se pode ser chamada por integrações autorizadas. |
idempotenciaObrigatoria | Ajuda a evitar duplicidade em chamadas repetidas. |
correlacaoObrigatoria | Mantém a resposta ligada ao processo original. |
testes/mensagem-exemplo.json
Mensagem de teste
A mensagem de teste prova que o handler consegue ler o envelope e encontrar os dados.
Modelo seguro de teste
No arquivo real, este tópico aparece assim:
{
"_sistema": {"transporte": "pp --api"},
"_protocolo": {
"nome": "siscore-protocolo-objetos",
"versao": 1,
"processoId": "processo-teste-local-0001",
"mensagemId": "teste-conector-<seu-servico>-0001",
"origem": "sistema__operador",
"destino": "conector__conector-<seu-servico>",
"tipo": "comando",
"prioridade": "normal",
"criadoEm": "2026-08-24T00:00:00Z"
},
"payload": {
"idmensagem": "conector-<seu-servico>.executar",
"dados": {
"acao": "executar",
"identificador": "ABC-123"
}
}
}
Atenção: use dados falsos ou ambiente sandbox. Teste local não deve disparar cobrança real, mensagem real ou alteração irreversível.
segredos.sample.json
Segredos e configuração
O pacote comunitário pode conter somente exemplo de configuração. Segredo real nunca viaja no pacote.
Arquivo permitido no pacote
No arquivo real de exemplo, use placeholders:
{
"ativo": false,
"descricao": "Exemplo de configuração. Copiar e preencher somente no ambiente real.",
"servico": {
"endpoint": "https://api.exemplo.invalid",
"timeoutSegundos": 30,
"token": "preencher-no-ambiente-real"
}
}
Regras de ouro
- Nunca envie token, senha, app password, certificado privado ou refresh token real.
- O handler deve falhar com mensagem clara se a configuração real estiver ausente.
- Não escreva segredos em logs.
- Prefira começar com
ativo:false até o operador configurar o ambiente.
execução / contrato-do-handler
Contrato obrigatório do handler
Checklist executável
No pacote real, seu handler deve cumprir:
[x] estar dentro de conectores/<nome>/handlers/
[x] usar caminho relativo seguro, sem / inicial, .., ., // ou barra invertida
[x] ser executável diretamente
[x] se for script, ter shebang na primeira linha
[x] receber exatamente 1 argumento: o caminho do JSON
[x] ler _protocolo e payload.dados do arquivo recebido
[x] validar campos antes de chamar serviço externo
[x] sair com código 0 em sucesso
[x] sair com código diferente de 0 em erro
[x] nunca manipular áreas internas do sistema diretamente
[x] publicar respostas apenas pelo canal oficial do ambiente
Não faça: não dependa de caminho absoluto da sua máquina, não use ../, não execute shell com entrada do usuário e não use arquivos internos da instalação como API. O runtime novo só executa handlers em conectores/<nome>/handlers/ e o sandbox só expõe o segredo do próprio conector.
execução / linguagens-suportadas
Handler em qualquer linguagem
O sistema não exige PHP. Ele exige um executável que cumpra o contrato.
Exemplos de execução
No desenvolvimento real:
# script com shebang
chmod +x conectores/conector-<seu-servico>/handlers/<handler.py>
./conectores/conector-<seu-servico>/handlers/<handler.py> testes/mensagem-exemplo.json
# binário compilado
./conectores/conector-<seu-servico>/handlers/<binario> testes/mensagem-exemplo.json
| Linguagem | Cuidados |
|---|
| Python/Node/PHP/Bash | Use shebang e documente dependências. |
| C/Go/Rust | Envie binário compatível ou instruções claras de compilação. |
| Qualquer linguagem | Valide JSON, trate timeout e não exponha segredos. |
frontend opcional
Front-end é opcional
Um conector pode ser 100% backend. Só crie tela se houver necessidade real de usuário humano preencher formulário ou acionar botão.
Quando houver formulário
No catálogo, descreva a entrada de tela sem expor segredo:
"front-api": [
{
"ativo": false,
"acao": "conector-<seu-servico>.executar.form",
"metodo": "POST",
"csrf": true,
"autenticacao": "sessao-ou-token",
"entrada": {
"identificador": {"tipo": "string", "obrigatorio": true, "max": 120}
},
"dadosSisc": {
"acao": "executar",
"identificador": "$entrada.identificador"
},
"resposta": {"tipo": "json", "atualizar": "conector-<seu-servico>"}
}
]
Regra do objeto visual: o elemento atualizado pelo AJAX deve ter exatamente o nome do conector. Exemplo: conector conector-email atualiza somente id="conector-email" ou name="conector-email".
Importante: navegador nunca deve chamar handler nem acessar configuração sensível. A tela chama somente o canal seguro disponibilizado pelo ambiente.
qualidade / segurança
Segurança
Lista de proibições práticas
Antes de enviar, confirme que NÃO existe:
[ ] senha real no pacote
[ ] token real no pacote
[ ] chave privada no pacote
[ ] link simbólico no pacote
[ ] caminho absoluto da sua máquina
[ ] caminho com .., ., // ou barra invertida
[ ] dependência instalável fora de conectores/<nome>/ ou web-api/
[ ] escrita direta em área interna do sistema
[ ] comando shell com entrada não sanitizada
[ ] log imprimindo Authorization, senha ou token
[ ] operação irreversível sem idempotência
Segurança boa é a que sobrevive ao cansaço: se alguém rodar seu conector às 3h da manhã, ele deve falhar de forma segura e compreensível.
validar-conector
Validação local
O validador existe para proteger você e quem vai instalar seu conector.
Comando de validação
No terminal, rode:
chmod +x validar-conector
chmod +x conectores/conector-<seu-servico>/handlers/<executavel>
./validar-conector
| Status | Significado |
|---|
| OK | Algo foi encontrado e está correto. |
| Aviso | Não bloqueia sempre, mas merece revisão. |
| Erro | Corrija antes de empacotar. |
validador / informações
Informações sobre o validador
O validador é o “inspetor de qualidade” do pacote. Ele não julga se sua regra de negócio é brilhante; ele confere se o conector está organizado, seguro e instalável pela comunidade.
Ideia principal: se o validador aprovar, o pacote tem estrutura mínima, não carrega segredos óbvios e o handler está pronto para ser executado no padrão esperado. A execução real fica para o sandbox do servidor, por meio dos selos operacionais.
O que o validador confere
No funcionamento real, pense nesta lista de verificações:
1. existe exatamente um conector no pacote
2. o nome segue o padrão conector-<seu-servico>
3. o manifesto existe e tem campos obrigatórios
4. o formato existe e declara entrada e saída
5. o catálogo existe e tem mensagem ativa
6. o handler existe, não está vazio e é executável
7. a mensagem de teste existe e possui payload.dados
8. o manual do conector existe e é HTML completo
9. não há segredos reais evidentes no pacote
10. não há caminhos absolutos ou comandos perigosos comuns
| Área | Por que isso importa |
| Estrutura | Garante que outra pessoa consiga abrir o pacote e encontrar cada peça no lugar esperado. |
| Manifesto | Confirma identidade, versão, tipo, dependências e handler declarado. |
| Formato | Evita payload ambíguo. Quem consome o conector precisa saber exatamente o que enviar. |
| Handler | Confirma que o programa pode ser chamado diretamente e que não está vazio. |
| Segurança | Bloqueia envio de senhas reais, tokens conhecidos e chaves privadas evidentes. |
Como interpretar a saída
Uma execução saudável deve se parecer com isto:
VALIDACAO LOCAL DO CONECTOR
Diretorio: pacote-do-conector
Conector: conector-<seu-servico>
[OK] Handler localizado
[OK] Formato validado
[OK] Manual HTML validado
[OK] Catalogo validado
[OK] Mensagem de teste validada
Resumo: 5 OK, 0 aviso(s), 0 erro(s).
Status: APROVADO PARA EMPACOTAMENTO LOCAL.
| Mensagem | O que fazer |
[OK] | Não precisa mexer; aquela checagem passou. |
[AVISO] | Leia com atenção. Pode não bloquear, mas indica documentação, clareza ou compatibilidade a revisar. |
[ERRO] | Bloqueia o envio. Corrija antes de compactar. |
Erros comuns e correções
Quando algo falhar, procure padrões como estes:
ERRO: nome do diretório diferente do nome no manifesto
CORREÇÃO: use o mesmo conector-<seu-servico> em diretório, manifesto, formato e catálogo
ERRO: handler não executável
CORREÇÃO: chmod +x no arquivo do handler
ERRO: formato sem entrada ou saída
CORREÇÃO: declare modelos de entrada e modelo de resultado
ERRO: segredo real encontrado
CORREÇÃO: remova o segredo e deixe apenas arquivo .sample com placeholder
ERRO: mensagem de teste sem payload.dados
CORREÇÃO: coloque os dados de negócio dentro de payload.dados
Importante: o validador é uma rede de proteção, não uma auditoria perfeita. Mesmo aprovado, revise manualmente chamadas externas, permissões, privacidade, idempotência e tratamento de erro.
O que o validador não garante
Aprovação local não significa automaticamente:
[não garante] que a API externa está correta
[não garante] que o serviço externo está online
[não garante] que sua regra de negócio está completa
[não garante] que o runtime existe em todos os servidores
[não garante] que sua integração é segura contra todos os ataques
[não garante] que operações financeiras ou destrutivas têm aprovação humana
Por isso, além de validar, faça teste sandbox, leia os logs sem expor segredo e peça revisão de outra pessoa quando a integração alterar dados, enviar mensagens ou movimentar dinheiro.
empacotar-e-enviar / pacote validado
Como enviar o pacote depois de validado
Depois que o validador aprovar, você não envia arquivos soltos. Você envia um pacote fechado, com nome claro, versão clara e sem lixo de desenvolvimento.
Regra simples: só empacote quando o status final disser aprovado. Se houver erro, corrija. Se houver aviso, revise antes de decidir enviar.
Fluxo correto depois da aprovação
No trabalho real, faça nesta ordem:
1. rode o validador local
2. confirme status aprovado
3. confira se não há segredos reais
4. confira versão e nome do conector
5. gere o arquivo compactado
6. teste se o pacote abre corretamente
7. envie pelo canal comunitário indicado pelo projeto
8. guarde o comprovante/hash/versão enviada
9. aguarde selo-validacao emitido pelo servidor
10. aguarde selo-sandbox emitido pelo testesis
11. somente depois disso o pacote poderá ir para o SISC real
O que acontece no servidor depois do envio
Depois que o pacote chega ao operador SISC:
# no servidor operacional do projeto (não no computador do programador):
./validar-recebidos # gera <pacote>.selo-validacao.json
./testar-sandbox # instala no testesis, faz dryRun + execução segura
./instalar-aprovados # só instala no siscore real se os dois selos conferirem
Os selos são assinados pelo servidor e presos ao sha256 do pacote. Se o pacote for alterado depois, os selos deixam de valer. O servidor também bloqueia o selo-sandbox se SISC_SANDBOX_DESATIVADO estiver definido ou se o testesis não estiver com runtime-conector e sandbox-handler atualizados.
Comando recomendado para gerar pacote
No terminal, a partir da raiz do pacote:
mkdir -p dist
./validar-conector && tar \
--exclude='./dist' \
--exclude='.git' \
--exclude='*.log' \
--exclude='.env' \
-czf dist/conector-<seu-servico>-1.0.0.tar.gz .
O nome do arquivo deve ajudar quem recebe: inclua o nome do conector e a versão. Exemplo: conector-pagamentos-1.0.0.tar.gz.
Formatos aceitos
Use um destes formatos:
dist/conector-<seu-servico>-1.0.0.tar.gz
dist/conector-<seu-servico>-1.0.0.tgz
dist/conector-<seu-servico>-1.0.0.zip
| Formato | Quando usar |
.tar.gz | Preferencial em Linux. Preserva bem permissões de executável. |
.tgz | Mesma ideia do .tar.gz, só com nome menor. |
.zip | Útil quando o desenvolvedor está em Windows, mas confira permissões do handler depois. |
Checklist antes de clicar em enviar
Confira item por item:
[ ] status aprovado no validador
[ ] pacote contém um único conector
[ ] manifesto, formato, catálogo, handler, manual e teste estão presentes
[ ] handler está executável
[ ] não existe senha, token, certificado privado ou arquivo .env real
[ ] arquivos de exemplo usam placeholders seguros
[ ] README/manual explicam objetivo, payload, saída, erros e credenciais
[ ] testeSandbox está declarado com permitido=true, semEfeitoReal=true e descrição clara
[ ] testes/mensagem-exemplo.json não causa cobrança, envio real ou alteração irreversível
[ ] versão do manifesto bate com o nome do pacote
[ ] pacote abre em uma pasta temporária sem erro
Teste rápido do pacote gerado
Antes de enviar, abra em uma pasta temporária:
mkdir -p /tmp/teste-conector
cd /tmp/teste-conector
tar -xzf /caminho/para/dist/conector-<seu-servico>-1.0.0.tar.gz
./validar-conector
Esse teste evita o clássico problema: “na minha pasta funcionava, mas o arquivo enviado ficou incompleto”.
Envio pelo canal comunitário
Envie o pacote validado na página oficial de upload:
https://costarrear.com/gitconectores/upload.php
Na página, informe:
nome do conector: conector-<seu-servico>
versão: 1.0.0
arquivo: dist/conector-<seu-servico>-1.0.0.tar.gz
resumo: o que o conector faz em uma frase
operações: lista curta das ações suportadas
observações: dependências, sandbox, limitações e contato do mantenedor
Não dependa de conversa externa: tudo que o revisor precisa saber deve estar dentro do pacote, principalmente no manual do conector e no README. Se quiser selo-sandbox automático, explique no manifesto por que o teste é sem efeito real.
Depois do envio
Guarde estas informações:
arquivo enviado
versão enviada
data do envio
hash sha256 do pacote
mensagem ou protocolo de recebimento
resultado do selo-validacao
resultado do selo-sandbox
lista de alterações desde a versão anterior
Se precisar reenviar, incremente a versão ou deixe claro que é uma correção do mesmo pacote. Isso evita que a comunidade instale uma versão errada sem perceber.
exemplos/conector-clima/manifestoClima / previsão do tempo: manifesto
Este arquivo identifica o conector de exemplo e mostra quais nomes você deve adaptar se construir uma integração parecida.
Como ficaria
No arquivo real, este tópico apareceria assim:
{
"nome": "conector-clima",
"titulo": "Conector Clima / previsão do tempo",
"descricao": "Integração para clima / previsão do tempo.",
"versao": "1.0.0",
"ativo": true,
"tipo": "conector",
"controlador": {
"metodoLeitura": "ler-mensagem",
"metodoEnvio": "canal-oficial-de-publicacao",
"handlerLerMensagem": "./conectores/conector-clima/handlers/conector-clima"
},
"formatoConector": "conectores/conector-clima/formatos/formato-conector-clima.json"
}
O que adaptar: troque nome, título, descrição, caminho do handler e caminho do formato para o seu serviço real.
exemplos/conector-clima/formatoClima / previsão do tempo: formato do payload
Aqui ficam os campos que o consumidor deve enviar para esta integração funcionar.
Campos do exemplo
No arquivo real, este tópico apareceria assim:
{
"tipo": "formato-conector",
"nome": "formato-conector-clima",
"conector": "conector-clima",
"entrada": {
"modelos": {
"comando-principal": {
"campos": {
"acao": {"tipo": "string", "obrigatorio": true, "valoresAceitos": ["consultar_previsao"]},
"cidade": {"tipo": "string", "obrigatorio": "sim"},
"data": {"tipo": "date", "obrigatorio": "não"},
"unidade": {"tipo": "string", "obrigatorio": "não"}
}
}
}
},
"saida": {"modelos": {"resultado": {"campos": {"sucesso": "bool", "dados": "object", "erro": "object"}}}}
}
| Campo | Tipo | Obrigatório | Explicação |
|---|
cidade | string | sim | Cidade pesquisada, exemplo: São Paulo |
data | date | não | Data opcional no formato AAAA-MM-DD |
unidade | string | não | celsius ou fahrenheit |
exemplos/conector-clima/handlerClima / previsão do tempo: handler
O handler traduz o comando padronizado para a API ou mecanismo externo.
Lógica recomendada
No arquivo real, a lógica seria:
ler arquivo JSON recebido
extrair _protocolo e payload.dados
validar acao == "consultar_previsao"
validar cidade e data
chamar API de clima
normalizar temperatura, chuva e alertas
retornar previsão estruturada pelo canal oficial
encerrar com código 0 em sucesso ou erro claro em falha
Exemplo pertinente em PHP
Abaixo está um exemplo simplificado, mas alinhado com este conector:
#!/usr/bin/env php
<?php
declare(strict_types=1);
function falhar(string $msg, int $codigo = 65): never {
fwrite(STDERR, "conector-clima: ERRO: {$msg}\n");
exit($codigo);
}
function responder(array $dados): never {
echo json_encode($dados, JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES) . PHP_EOL;
exit(0);
}
if ($argc !== 2) falhar('uso: conector-clima <arquivo-mensagem>', 64);
$msg = json_decode(file_get_contents($argv[1]) ?: '', true, 512, JSON_THROW_ON_ERROR);
$dados = $msg['payload']['dados'] ?? null;
if (!is_array($dados)) falhar('payload.dados ausente');
$acao = $dados['acao'] ?? '';
$cidade = trim((string)($dados['cidade'] ?? ''));
$data = trim((string)($dados['data'] ?? date('Y-m-d')));
$unidade = $dados['unidade'] ?? 'celsius';
if ($acao !== 'consultar_previsao') falhar('acao invalida');
if ($cidade === '') falhar('cidade obrigatoria');
if (!preg_match('/^\d{4}-\d{2}-\d{2}$/', $data)) falhar('data deve estar em AAAA-MM-DD');
if (!in_array($unidade, ['celsius', 'fahrenheit'], true)) falhar('unidade invalida');
$config = json_decode(file_get_contents('segredos/conector-clima.json') ?: '{}', true);
$endpoint = rtrim((string)($config['servico']['endpoint'] ?? ''), '/');
$apiKey = (string)($config['servico']['apiKey'] ?? '');
if ($endpoint === '' || $apiKey === '' || str_contains($apiKey, 'preencher')) falhar('configuracao de clima incompleta', 78);
$url = $endpoint . '/previsao?' . http_build_query(['cidade' => $cidade, 'data' => $data, 'unidade' => $unidade]);
$ctx = stream_context_create(['http' => ['timeout' => 20, 'header' => "Authorization: Bearer {$apiKey}\r\n"]]);
$raw = @file_get_contents($url, false, $ctx);
if ($raw === false) falhar('servico de clima indisponivel', 75);
$externo = json_decode($raw, true);
responder([
'sucesso' => true,
'conector' => 'conector-clima',
'cidade' => $cidade,
'data' => $data,
'previsao' => $externo['previsao'] ?? $externo
]);
Cuidado deste conector: baixo risco: normalmente apenas consulta dados externos. Mesmo assim, trate timeout e limite de requisições.
exemplos/conector-clima/manualClima / previsão do tempo: manual do conector
O manual ensina outro programador a consumir este conector sem abrir o código.
Estrutura mínima
No HTML real, inclua:
<h1>Manual do conector-clima</h1>
<h2>Objetivo</h2>
<p>Explicar clima / previsão do tempo.</p>
<h2>Operação principal</h2>
<code>consultar_previsao</code>
<h2>Payload</h2>
<pre>exemplo completo com dados seguros</pre>
<h2>Erros comuns</h2>
exemplos/conector-clima/catálogoClima / previsão do tempo: catálogo
O catálogo declara a mensagem pública que aciona o conector.
Mensagem pública
No arquivo real, este tópico apareceria assim:
{
"tipo": "catalogo-modulo-mensagens-sisc",
"nome": "catalogo-conector-clima",
"modulo": "conector-clima",
"destino": "conector__conector-clima",
"mensagens": [{
"idmensagem": "conector-clima.executar",
"publica": true,
"ativo": true,
"tipoMensagem": "comando",
"prioridade": "normal",
"idempotenciaObrigatoria": true,
"correlacaoObrigatoria": true
}]
}
Use nomes previsíveis. A comunidade deve entender o comando só de ler o idmensagem.
exemplos/conector-clima/mensagem-de-testeClima / previsão do tempo: mensagem de teste
A mensagem de teste permite rodar o handler localmente sem dados reais perigosos.
Payload de teste
No arquivo real, este tópico apareceria assim:
{
"_protocolo": {
"nome": "siscore-protocolo-objetos",
"versao": 1,
"processoId": "processo-teste-local-0001",
"mensagemId": "teste-conector-clima-0001",
"origem": "sistema__operador",
"destino": "conector__conector-clima",
"tipo": "comando",
"prioridade": "normal"
},
"payload": {
"idmensagem": "conector-clima.executar",
"dados": {
"acao": "consultar_previsao",
"cidade": "São Paulo",
"data": "2026-08-25",
"unidade": "celsius"
}
}
}
Boa prática: a mensagem de teste deve ser realista, mas segura. Nada de senha, token ou operação financeira real.
exemplos/conector-clima/segredos.sampleClima / previsão do tempo: segredos de exemplo
Este arquivo é só um molde. O valor real será preenchido apenas no ambiente de instalação.
Sample seguro
No arquivo de exemplo, use placeholders:
{
"ativo": false,
"descricao": "Copiar e preencher somente no ambiente real.",
"servico": {
"endpoint": "https://api.clima.example.invalid",
"apiKey": "preencher-no-ambiente-real",
"timeoutSegundos": 30
}
}
Nunca envie: token real, senha real, chave privada, certificado privado ou qualquer segredo que permita acesso ao serviço externo.
exemplos/conector-crm-leads/manifestoCRM / leads comerciais: manifesto
Este arquivo identifica o conector de exemplo e mostra quais nomes você deve adaptar se construir uma integração parecida.
Como ficaria
No arquivo real, este tópico apareceria assim:
{
"nome": "conector-crm-leads",
"titulo": "Conector CRM / leads comerciais",
"descricao": "Integração para crm / leads comerciais.",
"versao": "1.0.0",
"ativo": true,
"tipo": "conector",
"controlador": {
"metodoLeitura": "ler-mensagem",
"metodoEnvio": "canal-oficial-de-publicacao",
"handlerLerMensagem": "./conectores/conector-crm-leads/handlers/conector-crm-leads"
},
"formatoConector": "conectores/conector-crm-leads/formatos/formato-conector-crm-leads.json"
}
O que adaptar: troque nome, título, descrição, caminho do handler e caminho do formato para o seu serviço real.
exemplos/conector-crm-leads/formatoCRM / leads comerciais: formato do payload
Aqui ficam os campos que o consumidor deve enviar para esta integração funcionar.
Campos do exemplo
No arquivo real, este tópico apareceria assim:
{
"tipo": "formato-conector",
"nome": "formato-conector-crm-leads",
"conector": "conector-crm-leads",
"entrada": {
"modelos": {
"comando-principal": {
"campos": {
"acao": {"tipo": "string", "obrigatorio": true, "valoresAceitos": ["criar_lead"]},
"nome": {"tipo": "string", "obrigatorio": "sim"},
"email": {"tipo": "email", "obrigatorio": "sim"},
"telefone": {"tipo": "string", "obrigatorio": "não"},
"origemLead": {"tipo": "string", "obrigatorio": "não"}
}
}
}
},
"saida": {"modelos": {"resultado": {"campos": {"sucesso": "bool", "dados": "object", "erro": "object"}}}}
}
| Campo | Tipo | Obrigatório | Explicação |
|---|
nome | string | sim | Nome do lead |
email | email | sim | Email usado também para evitar duplicidade |
telefone | string | não | Telefone de contato |
origemLead | string | não | Campanha, formulário ou canal de origem |
exemplos/conector-crm-leads/handlerCRM / leads comerciais: handler
O handler traduz o comando padronizado para a API ou mecanismo externo.
Lógica recomendada
No arquivo real, a lógica seria:
ler arquivo JSON recebido
extrair _protocolo e payload.dados
validar acao == "criar_lead"
validar email
consultar se lead já existe
criar ou atualizar lead
retornar id do lead e status pelo canal oficial
encerrar com código 0 em sucesso ou erro claro em falha
Exemplo pertinente em PHP
Abaixo está um exemplo simplificado, mas alinhado com este conector:
#!/usr/bin/env php
<?php
declare(strict_types=1);
function falhar(string $msg, int $codigo = 65): never {
fwrite(STDERR, "conector-crm-leads: ERRO: {$msg}\n");
exit($codigo);
}
function responder(array $dados): never {
echo json_encode($dados, JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES) . PHP_EOL;
exit(0);
}
function post_json(string $url, array $body, string $token): array {
$ctx = stream_context_create(['http' => [
'method' => 'POST',
'timeout' => 25,
'header' => "Content-Type: application/json\r\nAuthorization: Bearer {$token}\r\n",
'content' => json_encode($body, JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES)
]]);
$raw = @file_get_contents($url, false, $ctx);
if ($raw === false) falhar('CRM indisponivel', 75);
return json_decode($raw, true) ?: [];
}
if ($argc !== 2) falhar('uso: conector-crm-leads <arquivo-mensagem>', 64);
$msg = json_decode(file_get_contents($argv[1]) ?: '', true, 512, JSON_THROW_ON_ERROR);
$dados = $msg['payload']['dados'] ?? null;
if (!is_array($dados)) falhar('payload.dados ausente');
$acao = $dados['acao'] ?? '';
$email = trim((string)($dados['email'] ?? ''));
$nome = trim((string)($dados['nome'] ?? ''));
if (!in_array($acao, ['criar_lead', 'consultar_lead'], true)) falhar('acao invalida');
if (filter_var($email, FILTER_VALIDATE_EMAIL) === false) falhar('email invalido');
if ($acao === 'criar_lead' && $nome === '') falhar('nome obrigatorio para criar lead');
$config = json_decode(file_get_contents('segredos/conector-crm-leads.json') ?: '{}', true);
$endpoint = rtrim((string)($config['servico']['endpoint'] ?? ''), '/');
$token = (string)($config['servico']['token'] ?? '');
if ($endpoint === '' || $token === '' || str_contains($token, 'preencher')) falhar('configuracao de CRM incompleta', 78);
$payloadCrm = [
'email' => $email,
'nome' => $nome,
'telefone' => $dados['telefone'] ?? null,
'origem' => $dados['origemLead'] ?? 'sisc-comunidade',
'idempotencia' => hash('sha256', strtolower($email))
];
$resultado = $acao === 'criar_lead'
? post_json($endpoint . '/leads/upsert', $payloadCrm, $token)
: post_json($endpoint . '/leads/consultar', ['email' => $email], $token);
responder(['sucesso' => true, 'conector' => 'conector-crm-leads', 'resultado' => $resultado]);
Cuidado deste conector: médio: pode criar registros duplicados. Use idempotência baseada em email, documento ou referência externa.
exemplos/conector-crm-leads/manualCRM / leads comerciais: manual do conector
O manual ensina outro programador a consumir este conector sem abrir o código.
Estrutura mínima
No HTML real, inclua:
<h1>Manual do conector-crm-leads</h1>
<h2>Objetivo</h2>
<p>Explicar crm / leads comerciais.</p>
<h2>Operação principal</h2>
<code>criar_lead</code>
<h2>Payload</h2>
<pre>exemplo completo com dados seguros</pre>
<h2>Erros comuns</h2>
exemplos/conector-crm-leads/catálogoCRM / leads comerciais: catálogo
O catálogo declara a mensagem pública que aciona o conector.
Mensagem pública
No arquivo real, este tópico apareceria assim:
{
"tipo": "catalogo-modulo-mensagens-sisc",
"nome": "catalogo-conector-crm-leads",
"modulo": "conector-crm-leads",
"destino": "conector__conector-crm-leads",
"mensagens": [{
"idmensagem": "conector-crm-leads.executar",
"publica": true,
"ativo": true,
"tipoMensagem": "comando",
"prioridade": "normal",
"idempotenciaObrigatoria": true,
"correlacaoObrigatoria": true
}]
}
Use nomes previsíveis. A comunidade deve entender o comando só de ler o idmensagem.
exemplos/conector-crm-leads/mensagem-de-testeCRM / leads comerciais: mensagem de teste
A mensagem de teste permite rodar o handler localmente sem dados reais perigosos.
Payload de teste
No arquivo real, este tópico apareceria assim:
{
"_protocolo": {
"nome": "siscore-protocolo-objetos",
"versao": 1,
"processoId": "processo-teste-local-0001",
"mensagemId": "teste-conector-crm-leads-0001",
"origem": "sistema__operador",
"destino": "conector__conector-crm-leads",
"tipo": "comando",
"prioridade": "normal"
},
"payload": {
"idmensagem": "conector-crm-leads.executar",
"dados": {
"acao": "criar_lead",
"nome": "Maria Cliente",
"email": "maria@example.com",
"telefone": "+5511999999999",
"origemLead": "landing-page"
}
}
}
Boa prática: a mensagem de teste deve ser realista, mas segura. Nada de senha, token ou operação financeira real.
exemplos/conector-crm-leads/segredos.sampleCRM / leads comerciais: segredos de exemplo
Este arquivo é só um molde. O valor real será preenchido apenas no ambiente de instalação.
Sample seguro
No arquivo de exemplo, use placeholders:
{
"ativo": false,
"descricao": "Copiar e preencher somente no ambiente real.",
"servico": {
"endpoint": "https://crm.example.invalid",
"token": "preencher-no-ambiente-real",
"timeoutSegundos": 30
}
}
Nunca envie: token real, senha real, chave privada, certificado privado ou qualquer segredo que permita acesso ao serviço externo.
exemplos/conector-pagamentos/manifestoPagamentos / cobrança: manifesto
Este arquivo identifica o conector de exemplo e mostra quais nomes você deve adaptar se construir uma integração parecida.
Como ficaria
No arquivo real, este tópico apareceria assim:
{
"nome": "conector-pagamentos",
"titulo": "Conector Pagamentos / cobrança",
"descricao": "Integração para pagamentos / cobrança.",
"versao": "1.0.0",
"ativo": true,
"tipo": "conector",
"controlador": {
"metodoLeitura": "ler-mensagem",
"metodoEnvio": "canal-oficial-de-publicacao",
"handlerLerMensagem": "./conectores/conector-pagamentos/handlers/conector-pagamentos"
},
"formatoConector": "conectores/conector-pagamentos/formatos/formato-conector-pagamentos.json"
}
O que adaptar: troque nome, título, descrição, caminho do handler e caminho do formato para o seu serviço real.
exemplos/conector-pagamentos/formatoPagamentos / cobrança: formato do payload
Aqui ficam os campos que o consumidor deve enviar para esta integração funcionar.
Campos do exemplo
No arquivo real, este tópico apareceria assim:
{
"tipo": "formato-conector",
"nome": "formato-conector-pagamentos",
"conector": "conector-pagamentos",
"entrada": {
"modelos": {
"comando-principal": {
"campos": {
"acao": {"tipo": "string", "obrigatorio": true, "valoresAceitos": ["criar_cobranca"]},
"valor": {"tipo": "number", "obrigatorio": "sim"},
"moeda": {"tipo": "string", "obrigatorio": "não"},
"referenciaPedido": {"tipo": "string", "obrigatorio": "sim"},
"vencimento": {"tipo": "date", "obrigatorio": "não"}
}
}
}
},
"saida": {"modelos": {"resultado": {"campos": {"sucesso": "bool", "dados": "object", "erro": "object"}}}}
}
| Campo | Tipo | Obrigatório | Explicação |
|---|
valor | number | sim | Valor positivo da cobrança |
moeda | string | não | Moeda, padrão BRL |
referenciaPedido | string | sim | Chave do pedido para idempotência |
vencimento | date | não | Data limite para pagamento |
exemplos/conector-pagamentos/handlerPagamentos / cobrança: handler
O handler traduz o comando padronizado para a API ou mecanismo externo.
Lógica recomendada
No arquivo real, a lógica seria:
ler arquivo JSON recebido
extrair _protocolo e payload.dados
validar acao == "criar_cobranca"
validar valor monetário
gerar chave idempotente a partir do pedido
criar cobrança no gateway
retornar id, status e link/qr pelo canal oficial
encerrar com código 0 em sucesso ou erro claro em falha
Exemplo pertinente em PHP
Abaixo está um exemplo simplificado, mas alinhado com este conector:
#!/usr/bin/env php
<?php
declare(strict_types=1);
function falhar(string $msg, int $codigo = 65): never {
fwrite(STDERR, "conector-pagamentos: ERRO: {$msg}\n");
exit($codigo);
}
function responder(array $dados): never {
echo json_encode($dados, JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES) . PHP_EOL;
exit(0);
}
function dinheiro(mixed $valor): float {
if (!is_int($valor) && !is_float($valor) && !is_string($valor)) falhar('valor invalido');
$v = (float)$valor;
if ($v <= 0) falhar('valor deve ser positivo');
return round($v, 2);
}
if ($argc !== 2) falhar('uso: conector-pagamentos <arquivo-mensagem>', 64);
$msg = json_decode(file_get_contents($argv[1]) ?: '', true, 512, JSON_THROW_ON_ERROR);
$dados = $msg['payload']['dados'] ?? null;
if (!is_array($dados)) falhar('payload.dados ausente');
$acao = $dados['acao'] ?? '';
$referencia = trim((string)($dados['referenciaPedido'] ?? ''));
if (!in_array($acao, ['criar_cobranca', 'consultar_cobranca', 'cancelar_cobranca'], true)) falhar('acao invalida');
if ($referencia === '') falhar('referenciaPedido obrigatoria');
$config = json_decode(file_get_contents('segredos/conector-pagamentos.json') ?: '{}', true);
$endpoint = rtrim((string)($config['servico']['endpoint'] ?? ''), '/');
$clientId = (string)($config['servico']['clientId'] ?? '');
$clientSecret = (string)($config['servico']['clientSecret'] ?? '');
if ($endpoint === '' || $clientId === '' || $clientSecret === '') falhar('configuracao de pagamento incompleta', 78);
$idempotencia = hash('sha256', $referencia . ':' . $acao);
$body = ['referenciaPedido' => $referencia, 'idempotencia' => $idempotencia];
if ($acao === 'criar_cobranca') {
$body['valor'] = dinheiro($dados['valor'] ?? null);
$body['moeda'] = $dados['moeda'] ?? 'BRL';
$body['vencimento'] = $dados['vencimento'] ?? null;
}
$ctx = stream_context_create(['http' => [
'method' => 'POST',
'timeout' => 30,
'header' => "Content-Type: application/json\r\nIdempotency-Key: {$idempotencia}\r\n",
'content' => json_encode($body, JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES)
]]);
$raw = @file_get_contents($endpoint . '/' . $acao, false, $ctx);
if ($raw === false) falhar('gateway de pagamento indisponivel', 75);
responder(['sucesso' => true, 'conector' => 'conector-pagamentos', 'resultado' => json_decode($raw, true)]);
Cuidado deste conector: alto: pagamento duplicado é problema sério. Nunca crie cobrança sem idempotência e sem referência de negócio.
exemplos/conector-pagamentos/manualPagamentos / cobrança: manual do conector
O manual ensina outro programador a consumir este conector sem abrir o código.
Estrutura mínima
No HTML real, inclua:
<h1>Manual do conector-pagamentos</h1>
<h2>Objetivo</h2>
<p>Explicar pagamentos / cobrança.</p>
<h2>Operação principal</h2>
<code>criar_cobranca</code>
<h2>Payload</h2>
<pre>exemplo completo com dados seguros</pre>
<h2>Erros comuns</h2>
exemplos/conector-pagamentos/catálogoPagamentos / cobrança: catálogo
O catálogo declara a mensagem pública que aciona o conector.
Mensagem pública
No arquivo real, este tópico apareceria assim:
{
"tipo": "catalogo-modulo-mensagens-sisc",
"nome": "catalogo-conector-pagamentos",
"modulo": "conector-pagamentos",
"destino": "conector__conector-pagamentos",
"mensagens": [{
"idmensagem": "conector-pagamentos.executar",
"publica": true,
"ativo": true,
"tipoMensagem": "comando",
"prioridade": "normal",
"idempotenciaObrigatoria": true,
"correlacaoObrigatoria": true
}]
}
Use nomes previsíveis. A comunidade deve entender o comando só de ler o idmensagem.
exemplos/conector-pagamentos/mensagem-de-testePagamentos / cobrança: mensagem de teste
A mensagem de teste permite rodar o handler localmente sem dados reais perigosos.
Payload de teste
No arquivo real, este tópico apareceria assim:
{
"_protocolo": {
"nome": "siscore-protocolo-objetos",
"versao": 1,
"processoId": "processo-teste-local-0001",
"mensagemId": "teste-conector-pagamentos-0001",
"origem": "sistema__operador",
"destino": "conector__conector-pagamentos",
"tipo": "comando",
"prioridade": "normal"
},
"payload": {
"idmensagem": "conector-pagamentos.executar",
"dados": {
"acao": "criar_cobranca",
"valor": 149.90,
"moeda": "BRL",
"referenciaPedido": "PED-987",
"vencimento": "2026-08-30"
}
}
}
Boa prática: a mensagem de teste deve ser realista, mas segura. Nada de senha, token ou operação financeira real.
exemplos/conector-pagamentos/segredos.samplePagamentos / cobrança: segredos de exemplo
Este arquivo é só um molde. O valor real será preenchido apenas no ambiente de instalação.
Sample seguro
No arquivo de exemplo, use placeholders:
{
"ativo": false,
"descricao": "Copiar e preencher somente no ambiente real.",
"servico": {
"endpoint": "https://pagamentos.example.invalid",
"clientId": "preencher-no-ambiente-real",
"clientSecret": "preencher-no-ambiente-real",
"timeoutSegundos": 30
}
}
Nunca envie: token real, senha real, chave privada, certificado privado ou qualquer segredo que permita acesso ao serviço externo.
exemplos/conector-estoque/manifestoEstoque / ERP: manifesto
Este arquivo identifica o conector de exemplo e mostra quais nomes você deve adaptar se construir uma integração parecida.
Como ficaria
No arquivo real, este tópico apareceria assim:
{
"nome": "conector-estoque",
"titulo": "Conector Estoque / ERP",
"descricao": "Integração para estoque / erp.",
"versao": "1.0.0",
"ativo": true,
"tipo": "conector",
"controlador": {
"metodoLeitura": "ler-mensagem",
"metodoEnvio": "canal-oficial-de-publicacao",
"handlerLerMensagem": "./conectores/conector-estoque/handlers/conector-estoque"
},
"formatoConector": "conectores/conector-estoque/formatos/formato-conector-estoque.json"
}
O que adaptar: troque nome, título, descrição, caminho do handler e caminho do formato para o seu serviço real.
exemplos/conector-estoque/formatoEstoque / ERP: formato do payload
Aqui ficam os campos que o consumidor deve enviar para esta integração funcionar.
Campos do exemplo
No arquivo real, este tópico apareceria assim:
{
"tipo": "formato-conector",
"nome": "formato-conector-estoque",
"conector": "conector-estoque",
"entrada": {
"modelos": {
"comando-principal": {
"campos": {
"acao": {"tipo": "string", "obrigatorio": true, "valoresAceitos": ["ajustar_saldo"]},
"sku": {"tipo": "string", "obrigatorio": "sim"},
"quantidade": {"tipo": "int", "obrigatorio": "sim para ajuste"},
"deposito": {"tipo": "string", "obrigatorio": "não"},
"motivo": {"tipo": "string", "obrigatorio": "sim para ajuste"}
}
}
}
},
"saida": {"modelos": {"resultado": {"campos": {"sucesso": "bool", "dados": "object", "erro": "object"}}}}
}
| Campo | Tipo | Obrigatório | Explicação |
|---|
sku | string | sim | Código do produto |
quantidade | int | sim para ajuste | Quantidade final ou delta, conforme regra documentada |
deposito | string | não | Depósito/filial |
motivo | string | sim para ajuste | Justificativa do ajuste |
exemplos/conector-estoque/handlerEstoque / ERP: handler
O handler traduz o comando padronizado para a API ou mecanismo externo.
Lógica recomendada
No arquivo real, a lógica seria:
ler arquivo JSON recebido
extrair _protocolo e payload.dados
validar acao == "ajustar_saldo"
validar SKU
confirmar motivo para operações de escrita
consultar ou ajustar saldo no ERP
retornar saldo atualizado pelo canal oficial
encerrar com código 0 em sucesso ou erro claro em falha
Exemplo pertinente em PHP
Abaixo está um exemplo simplificado, mas alinhado com este conector:
#!/usr/bin/env php
<?php
declare(strict_types=1);
function falhar(string $msg, int $codigo = 65): never {
fwrite(STDERR, "conector-estoque: ERRO: {$msg}\n");
exit($codigo);
}
function responder(array $dados): never {
echo json_encode($dados, JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES) . PHP_EOL;
exit(0);
}
if ($argc !== 2) falhar('uso: conector-estoque <arquivo-mensagem>', 64);
$msg = json_decode(file_get_contents($argv[1]) ?: '', true, 512, JSON_THROW_ON_ERROR);
$dados = $msg['payload']['dados'] ?? null;
if (!is_array($dados)) falhar('payload.dados ausente');
$acao = $dados['acao'] ?? '';
$sku = strtoupper(trim((string)($dados['sku'] ?? '')));
$deposito = trim((string)($dados['deposito'] ?? 'principal'));
if (!in_array($acao, ['consultar_saldo', 'ajustar_saldo'], true)) falhar('acao invalida');
if ($sku === '' || !preg_match('/^[A-Z0-9._-]{2,80}$/', $sku)) falhar('sku invalido');
$body = ['sku' => $sku, 'deposito' => $deposito];
if ($acao === 'ajustar_saldo') {
if (!is_int($dados['quantidade'] ?? null)) falhar('quantidade deve ser inteiro');
$motivo = trim((string)($dados['motivo'] ?? ''));
if ($motivo === '') falhar('motivo obrigatorio para ajuste');
$body['quantidade'] = $dados['quantidade'];
$body['motivo'] = $motivo;
}
$config = json_decode(file_get_contents('segredos/conector-estoque.json') ?: '{}', true);
$endpoint = rtrim((string)($config['servico']['endpoint'] ?? ''), '/');
$token = (string)($config['servico']['token'] ?? '');
if ($endpoint === '' || $token === '') falhar('configuracao de estoque incompleta', 78);
$ctx = stream_context_create(['http' => [
'method' => $acao === 'consultar_saldo' ? 'GET' : 'POST',
'timeout' => 25,
'header' => "Content-Type: application/json\r\nAuthorization: Bearer {$token}\r\n",
'content' => $acao === 'consultar_saldo' ? '' : json_encode($body, JSON_UNESCAPED_UNICODE)
]]);
$url = $acao === 'consultar_saldo'
? $endpoint . '/estoque?' . http_build_query($body)
: $endpoint . '/estoque/ajuste';
$raw = @file_get_contents($url, false, $ctx);
if ($raw === false) falhar('ERP indisponivel', 75);
responder(['sucesso' => true, 'conector' => 'conector-estoque', 'sku' => $sku, 'resultado' => json_decode($raw, true)]);
Cuidado deste conector: alto quando altera saldo. Documente se quantidade é saldo final ou variação, e proteja contra concorrência.
exemplos/conector-estoque/manualEstoque / ERP: manual do conector
O manual ensina outro programador a consumir este conector sem abrir o código.
Estrutura mínima
No HTML real, inclua:
<h1>Manual do conector-estoque</h1>
<h2>Objetivo</h2>
<p>Explicar estoque / erp.</p>
<h2>Operação principal</h2>
<code>ajustar_saldo</code>
<h2>Payload</h2>
<pre>exemplo completo com dados seguros</pre>
<h2>Erros comuns</h2>
exemplos/conector-estoque/catálogoEstoque / ERP: catálogo
O catálogo declara a mensagem pública que aciona o conector.
Mensagem pública
No arquivo real, este tópico apareceria assim:
{
"tipo": "catalogo-modulo-mensagens-sisc",
"nome": "catalogo-conector-estoque",
"modulo": "conector-estoque",
"destino": "conector__conector-estoque",
"mensagens": [{
"idmensagem": "conector-estoque.executar",
"publica": true,
"ativo": true,
"tipoMensagem": "comando",
"prioridade": "normal",
"idempotenciaObrigatoria": true,
"correlacaoObrigatoria": true
}]
}
Use nomes previsíveis. A comunidade deve entender o comando só de ler o idmensagem.
exemplos/conector-estoque/mensagem-de-testeEstoque / ERP: mensagem de teste
A mensagem de teste permite rodar o handler localmente sem dados reais perigosos.
Payload de teste
No arquivo real, este tópico apareceria assim:
{
"_protocolo": {
"nome": "siscore-protocolo-objetos",
"versao": 1,
"processoId": "processo-teste-local-0001",
"mensagemId": "teste-conector-estoque-0001",
"origem": "sistema__operador",
"destino": "conector__conector-estoque",
"tipo": "comando",
"prioridade": "normal"
},
"payload": {
"idmensagem": "conector-estoque.executar",
"dados": {
"acao": "ajustar_saldo",
"sku": "CAMISETA-AZUL-M",
"quantidade": 25,
"deposito": "principal",
"motivo": "inventario"
}
}
}
Boa prática: a mensagem de teste deve ser realista, mas segura. Nada de senha, token ou operação financeira real.
exemplos/conector-estoque/segredos.sampleEstoque / ERP: segredos de exemplo
Este arquivo é só um molde. O valor real será preenchido apenas no ambiente de instalação.
Sample seguro
No arquivo de exemplo, use placeholders:
{
"ativo": false,
"descricao": "Copiar e preencher somente no ambiente real.",
"servico": {
"endpoint": "https://erp.example.invalid",
"token": "preencher-no-ambiente-real",
"timeoutSegundos": 30
}
}
Nunca envie: token real, senha real, chave privada, certificado privado ou qualquer segredo que permita acesso ao serviço externo.
exemplos/conector-documentos-ocr/manifestoDocumentos / OCR: manifesto
Este arquivo identifica o conector de exemplo e mostra quais nomes você deve adaptar se construir uma integração parecida.
Como ficaria
No arquivo real, este tópico apareceria assim:
{
"nome": "conector-documentos-ocr",
"titulo": "Conector Documentos / OCR",
"descricao": "Integração para documentos / ocr.",
"versao": "1.0.0",
"ativo": true,
"tipo": "conector",
"controlador": {
"metodoLeitura": "ler-mensagem",
"metodoEnvio": "canal-oficial-de-publicacao",
"handlerLerMensagem": "./conectores/conector-documentos-ocr/handlers/conector-documentos-ocr"
},
"formatoConector": "conectores/conector-documentos-ocr/formatos/formato-conector-documentos-ocr.json"
}
O que adaptar: troque nome, título, descrição, caminho do handler e caminho do formato para o seu serviço real.
exemplos/conector-documentos-ocr/formatoDocumentos / OCR: formato do payload
Aqui ficam os campos que o consumidor deve enviar para esta integração funcionar.
Campos do exemplo
No arquivo real, este tópico apareceria assim:
{
"tipo": "formato-conector",
"nome": "formato-conector-documentos-ocr",
"conector": "conector-documentos-ocr",
"entrada": {
"modelos": {
"comando-principal": {
"campos": {
"acao": {"tipo": "string", "obrigatorio": true, "valoresAceitos": ["extrair_texto"]},
"arquivo": {"tipo": "string", "obrigatorio": "sim"},
"tipoDocumento": {"tipo": "string", "obrigatorio": "não"},
"idioma": {"tipo": "string", "obrigatorio": "não"},
"extrairCampos": {"tipo": "bool", "obrigatorio": "não"}
}
}
}
},
"saida": {"modelos": {"resultado": {"campos": {"sucesso": "bool", "dados": "object", "erro": "object"}}}}
}
| Campo | Tipo | Obrigatório | Explicação |
|---|
arquivo | string | sim | Caminho permitido ou URL assinada temporária |
tipoDocumento | string | não | contrato, nota, comprovante ou generico |
idioma | string | não | Idioma esperado, padrão pt-BR |
extrairCampos | bool | não | Se deve retornar campos estruturados |
exemplos/conector-documentos-ocr/handlerDocumentos / OCR: handler
O handler traduz o comando padronizado para a API ou mecanismo externo.
Lógica recomendada
No arquivo real, a lógica seria:
ler arquivo JSON recebido
extrair _protocolo e payload.dados
validar acao == "extrair_texto"
validar caminho permitido
validar tamanho e tipo do arquivo
enviar ao OCR externo
retornar texto, campos e confiança pelo canal oficial
encerrar com código 0 em sucesso ou erro claro em falha
Exemplo pertinente em PHP
Abaixo está um exemplo simplificado, mas alinhado com este conector:
#!/usr/bin/env php
<?php
declare(strict_types=1);
function falhar(string $msg, int $codigo = 65): never {
fwrite(STDERR, "conector-documentos-ocr: ERRO: {$msg}\n");
exit($codigo);
}
function responder(array $dados): never {
echo json_encode($dados, JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES) . PHP_EOL;
exit(0);
}
if ($argc !== 2) falhar('uso: conector-documentos-ocr <arquivo-mensagem>', 64);
$msg = json_decode(file_get_contents($argv[1]) ?: '', true, 512, JSON_THROW_ON_ERROR);
$dados = $msg['payload']['dados'] ?? null;
if (!is_array($dados)) falhar('payload.dados ausente');
$acao = $dados['acao'] ?? '';
$arquivo = trim((string)($dados['arquivo'] ?? ''));
$idioma = $dados['idioma'] ?? 'pt-BR';
$tipoDocumento = $dados['tipoDocumento'] ?? 'generico';
if ($acao !== 'extrair_texto') falhar('acao invalida');
if ($arquivo === '' || str_contains($arquivo, '..') || str_starts_with($arquivo, '/')) falhar('arquivo deve ser caminho relativo permitido');
if (!is_file($arquivo) || !is_readable($arquivo)) falhar('arquivo nao encontrado ou sem leitura', 66);
if (filesize($arquivo) > 20 * 1024 * 1024) falhar('arquivo maior que 20MB');
if (!in_array($tipoDocumento, ['contrato', 'nota', 'comprovante', 'generico'], true)) falhar('tipoDocumento invalido');
$config = json_decode(file_get_contents('segredos/conector-documentos-ocr.json') ?: '{}', true);
$endpoint = rtrim((string)($config['servico']['endpoint'] ?? ''), '/');
$apiKey = (string)($config['servico']['apiKey'] ?? '');
if ($endpoint === '' || $apiKey === '') falhar('configuracao OCR incompleta', 78);
$boundary = '----sisc-ocr-' . bin2hex(random_bytes(8));
$conteudo = file_get_contents($arquivo);
$multipart = "--{$boundary}\r\n"
. "Content-Disposition: form-data; name=\"metadata\"\r\n\r\n"
. json_encode(['idioma' => $idioma, 'tipoDocumento' => $tipoDocumento], JSON_UNESCAPED_UNICODE) . "\r\n"
. "--{$boundary}\r\n"
. "Content-Disposition: form-data; name=\"arquivo\"; filename=\"documento\"\r\n"
. "Content-Type: application/octet-stream\r\n\r\n"
. $conteudo . "\r\n--{$boundary}--\r\n";
$ctx = stream_context_create(['http' => [
'method' => 'POST',
'timeout' => 60,
'header' => "Authorization: Bearer {$apiKey}\r\nContent-Type: multipart/form-data; boundary={$boundary}\r\n",
'content' => $multipart
]]);
$raw = @file_get_contents($endpoint . '/extrair', false, $ctx);
if ($raw === false) falhar('servico OCR indisponivel', 75);
responder(['sucesso' => true, 'conector' => 'conector-documentos-ocr', 'resultado' => json_decode($raw, true)]);
Cuidado deste conector: privacidade. Não envie documentos sigilosos a provedor não autorizado; apague temporários e limite tamanho.
exemplos/conector-documentos-ocr/manualDocumentos / OCR: manual do conector
O manual ensina outro programador a consumir este conector sem abrir o código.
Estrutura mínima
No HTML real, inclua:
<h1>Manual do conector-documentos-ocr</h1>
<h2>Objetivo</h2>
<p>Explicar documentos / ocr.</p>
<h2>Operação principal</h2>
<code>extrair_texto</code>
<h2>Payload</h2>
<pre>exemplo completo com dados seguros</pre>
<h2>Erros comuns</h2>
exemplos/conector-documentos-ocr/catálogoDocumentos / OCR: catálogo
O catálogo declara a mensagem pública que aciona o conector.
Mensagem pública
No arquivo real, este tópico apareceria assim:
{
"tipo": "catalogo-modulo-mensagens-sisc",
"nome": "catalogo-conector-documentos-ocr",
"modulo": "conector-documentos-ocr",
"destino": "conector__conector-documentos-ocr",
"mensagens": [{
"idmensagem": "conector-documentos-ocr.executar",
"publica": true,
"ativo": true,
"tipoMensagem": "comando",
"prioridade": "normal",
"idempotenciaObrigatoria": true,
"correlacaoObrigatoria": true
}]
}
Use nomes previsíveis. A comunidade deve entender o comando só de ler o idmensagem.
exemplos/conector-documentos-ocr/mensagem-de-testeDocumentos / OCR: mensagem de teste
A mensagem de teste permite rodar o handler localmente sem dados reais perigosos.
Payload de teste
No arquivo real, este tópico apareceria assim:
{
"_protocolo": {
"nome": "siscore-protocolo-objetos",
"versao": 1,
"processoId": "processo-teste-local-0001",
"mensagemId": "teste-conector-documentos-ocr-0001",
"origem": "sistema__operador",
"destino": "conector__conector-documentos-ocr",
"tipo": "comando",
"prioridade": "normal"
},
"payload": {
"idmensagem": "conector-documentos-ocr.executar",
"dados": {
"acao": "extrair_texto",
"arquivo": "uploads/seguros/doc-123.pdf",
"tipoDocumento": "contrato",
"idioma": "pt-BR",
"extrairCampos": true
}
}
}
Boa prática: a mensagem de teste deve ser realista, mas segura. Nada de senha, token ou operação financeira real.
exemplos/conector-documentos-ocr/segredos.sampleDocumentos / OCR: segredos de exemplo
Este arquivo é só um molde. O valor real será preenchido apenas no ambiente de instalação.
Sample seguro
No arquivo de exemplo, use placeholders:
{
"ativo": false,
"descricao": "Copiar e preencher somente no ambiente real.",
"servico": {
"endpoint": "https://ocr.example.invalid",
"apiKey": "preencher-no-ambiente-real",
"timeoutSegundos": 30
}
}
Nunca envie: token real, senha real, chave privada, certificado privado ou qualquer segredo que permita acesso ao serviço externo.