Compartilhamento de Documentos de Nota Fiscal
Esta funcionalidade permite aos usuários baixar e compartilhar arquivos XML e PDF de notas fiscais diretamente pelo aplicativo móvel, facilitando o envio de documentos fiscais para contadores, clientes ou outros sistemas.
Visão Geral
O sistema de compartilhamento de documentos integra-se aos fluxos existentes de visualização de vendas e pedidos, oferecendo duas opções principais nos menus de ações:
- "IMPRIMIR NOTA FISCAL" - Para compartilhamento de PDF (DANFE)
- "COMPARTILHAR NF (XML)" - Para compartilhamento de XML
Características Principais
- 📄 Múltiplos formatos - XML e PDF (DANFE)
- 📱 Compartilhamento nativo através do sistema operacional
- 🔐 Autenticação segura usando credenciais em cache
- 📊 Feedback visual com toast messages
- 🔄 Integração múltipla em diversos componentes
- 🎯 Modal de seleção para PDFs com opções customizáveis
Onde Encontrar
A funcionalidade está disponível nos seguintes locais:
| Localização | Componente | Contexto |
|---|---|---|
| Componente CS Order | cs-order.tsx | Visualização de pedidos |
| Preview de Pedidos | order-preview.navigator.tsx | Navegação de preview |
| Detalhes de Vendas | sales-details.screen.tsx | Tela de detalhes completos |
| Card de Vendas | sales-card.tsx | Lista de vendas |
Como Usar
Para o Usuário Final
Compartilhamento XML
- Acesse qualquer tela com informações de vendas/pedidos
- Toque no menu de ações (geralmente representado por três pontos)
- Selecione a opção "COMPARTILHAR NF (XML)"
- Aguarde o processamento (toast de carregamento aparecerá)
- Escolha o aplicativo de destino no menu de compartilhamento nativo
Compartilhamento PDF (DANFE)
- Acesse qualquer tela com informações de vendas/pedidos
- Toque no menu de ações ou no botão de compartilhar
- Selecione "IMPRIMIR NOTA FISCAL" (ou "GERAR CÓPIA DA NOTA FISCAL" para Junco)
- Aguarde a pré-visualização do PDF
- Toque no ícone de compartilhar , no canto superior direito
- Aguarde o processamento e compartilhe
Implementação Técnica
Serviço XML
O serviço de XML está localizado em src/services/get-sale-xml.service.ts:
import RNFS from "react-native-fs";
import { axios } from "./api";
import { CacheService } from "./cache.service";
import Share from "react-native-share";
import Toast from "react-native-toast-message";
export const getSaleXML = async ({
NUNOTANF,
}: {
NUNOTANF: string | number;
}) => {
try {
const cache = await CacheService.getAuthCache();
if (!cache)
throw new Error("Não foi possível gerar o XML: credenciais inválidas");
const response = await axios.get(`/ppid/${NUNOTANF}/viewXML`, {
responseType: "arraybuffer",
auth: {
username: cache.user,
password: cache.password,
},
});
const xmlData = response?.data;
if (!xmlData || xmlData.byteLength === 0) {
throw new Error("Não foi possível gerar o XML: resposta vazia");
}
return xmlData;
} catch (error) {
console.error("Erro ao baixar XML:", error);
throw error;
}
};
Função de Compartilhamento
export const handleDownloadXML = async ({
NUNOTANF,
}: {
NUNOTANF: string | number;
}) => {
try {
// Exibe toast de carregamento
Toast.show({
type: "info",
text1: "Aguarde...",
text2: "Gerando arquivo XML para compartilhamento",
autoHide: false,
});
const xmlData = await getSaleXML({ NUNOTANF });
const fileName = `venda-${NUNOTANF}.xml`;
const path = `${RNFS.DocumentDirectoryPath}/${fileName}`;
await RNFS.writeFile(path, Buffer.from(xmlData).toString(), "utf8");
await Share.open({
url: `file://${path}`,
type: "application/xml",
filename: fileName,
});
Toast.hide();
Toast.show({
type: "success",
text1: "Sucesso",
text2: "Arquivo XML compartilhado!",
visibilityTime: 2000,
});
} catch (error) {
Toast.hide();
Toast.show({
type: "error",
text1: "Erro ao compartilhar XML",
text2: "Tente novamente",
visibilityTime: 3000,
});
console.log("Erro ao compartilhar XML:", error);
}
};
Serviço PDF
O serviço de PDF está localizado em src/services/pdf.service.ts no namespace PDFService:
export async function getDanfeCookieAndHeaders(
credentials,
danfeNuNota,
useToken
) {
try {
let bearer = "";
if (useToken) {
const res = await getToken(credentials);
if (res.status == 200) {
bearer = res.data.data.Token;
bearer = bearer.replace(/^Bearer\s/, "");
}
}
let cookie = await api.getDanfeCookie(credentials);
cookie = cookie.data.responseBody.jsessionid.$;
let res = await getDanfeHeaders(cookie, danfeNuNota, bearer);
const dataToSend = {
reqStatus: res,
cookie: cookie,
isDanfe: true,
danfeNuNota: danfeNuNota,
};
if (bearer.length > 0) {
dataToSend.bearer = bearer;
}
return dataToSend;
} catch (e) {
Toast.show({
type: "error",
text1: "Erro",
text2: "Erro ao Consultar ERP",
autoHide: true,
onPress: () => Toast.hide(),
});
throw new Error(e.message);
}
}
Componente de Compartilhamento PDF
O componente OrderPDFShare (src/components/cs-order/order-pdf-share/order-pdf-share.tsx) gerencia a interface de seleção e compartilhamento de PDFs:
interface OrderPDFShareProps {
danfeData?: any;
visible: boolean;
onBackdropPress: () => void;
onSelect: (currentPdfData: any, index: any) => Promise<void>;
boletoData: CompanyPedidoPDF[];
reportData: CompanyPedidoPDF[];
saleId: string;
isOffline: boolean;
}
Integração nos Componentes
Para integrar as funcionalidades em um novo componente:
XML
import { handleDownloadXML } from "../../services/get-sale-xml.service";
// 1. Adicione a opção no menu de dados
data.push({
DESCRICAO: "COMPARTILHAR NF (XML)",
DANFE: sale.NUNOTANF,
});
// 2. Adicione a verificação condicional no handler
if (currentPdfData.DESCRICAO.includes("XML")) {
await handleDownloadXML({ NUNOTANF: currentPdfData.DANFE });
return;
}
PDF
import { PDFService } from "../../services/pdf.service";
import SelectReportPdfModal from "./selectReportPdfModal";
import { OrderPDFShare } from "./order-pdf-share/order-pdf-share";
// 1. Adicione a opção no menu de dados
data.push({
DESCRICAO: isJunco ? "GERAR CÓPIA DA NOTA FISCAL" : "IMPRIMIR NOTA FISCAL",
DANFE: sale.NUNOTANF.toString(),
});
// 2. No handler, processe PDF normalmente
if (currentPdfData.DANFE) {
try {
pdfReqBody = await PDFService.getDanfeCookieAndHeaders(
credentials,
mergedPdfData[index].DANFE,
UTILAPIGATEWAY === "S"
);
// Abrir modal de seleção ou processar diretamente
} catch (error) {
// Tratamento de erro
}
}
Dependências
Para XML
- react-native-fs: Para manipulação de arquivos no sistema
- react-native-share: Para compartilhamento nativo
- react-native-toast-message: Para feedback visual
Para PDF
- @ui-kitten/components: Para componentes de interface (Modal, Select, etc.)
- react-native-toast-message: Para feedback visual
- PDFService: Serviço interno para processamento de PDFs
- OrderPDFShare: Componente para seleção de opções de PDF
Estados e Feedback
Toast Messages
| Tipo | Título | Descrição | Duração |
|---|---|---|---|
info | "Aguarde..." | "Gerando arquivo XML para compartilhamento" | Infinito |
success | "Sucesso" | "Arquivo XML compartilhado!" | 2 segundos |
error | "Erro ao compartilhar XML" | "Tente novamente" | 3 segundos |
Tratamento de Erros
O sistema trata os seguintes cenários de erro:
- Credenciais inválidas: Cache de autenticação não encontrado
- Resposta vazia: API retorna dados vazios ou inválidos
- Erro de rede: Problemas de conectividade
- Erro de sistema: Problemas com arquivos ou compartilhamento
API Endpoints
GET /ppid/:NUNOTANF/viewXML
Endpoint responsável por retornar o arquivo XML da nota fiscal.
Parâmetros
- NUNOTANF (path): Número da nota fiscal
Headers
- Authorization: Basic Auth usando credenciais em cache
Response
- Content-Type:
application/xml - Body: ArrayBuffer contendo dados XML
PDF Endpoints
POST /getDanfeCookie
Obtém cookie de sessão para autenticação de PDFs.
POST /getDanfeHeaders
Obtém headers necessários para geração de DANFE.
GET /getToken
Obtém token Bearer quando UTILAPIGATEWAY === 'S'.
Parâmetros PDF
- credentials: Credenciais de autenticação
- danfeNuNota: Número da nota fiscal
- useToken: Boolean indicando se deve usar token Bearer
Troubleshooting
Problemas Comuns
XML
-
"Credenciais inválidas"
- Causa: Cache de autenticação expirado ou corrompido
- Solução: Solicitar que o usuário faça login novamente
-
"Resposta vazia"
- Causa: Nota fiscal não possui XML disponível ou erro no servidor
- Solução: Verificar se a nota fiscal foi processada corretamente
-
Menu de compartilhamento não abre
- Causa: Problemas com a biblioteca react-native-share
- Solução: Verificar se as permissões estão configuradas no Android/iOS
PDF
-
"Erro ao Consultar ERP"
- Causa: Problemas na comunicação com o servidor ERP
- Solução: Verificar conectividade e credenciais
-
Modal não abre
- Causa: Problemas nos dados ou estado do componente
- Solução: Verificar se
reportSelectDataestá populado
-
PDF não é gerado
- Causa: Problemas com cookies, headers ou token
- Solução: Verificar logs do PDFService e configurações do gateway
Debugging
XML
console.log("NUNOTANF:", NUNOTANF);
console.log("XML Data length:", xmlData?.byteLength);
console.log("File path:", path);
PDF
console.log("PDF Request Body:", pdfReqBody);
console.log("Merged PDF Data:", mergedPdfData);
console.log("Use Token:", UTILAPIGATEWAY === "S");
console.log("Current PDF Data:", currentPdfData);
Melhorias Futuras
Possíveis Evoluções
XML
- Cache de XMLs: Armazenar XMLs baixados para evitar downloads repetidos
- Visualização prévia: Permitir visualizar o conteúdo XML antes do compartilhamento
Otimizações Técnicas
- Background processing: Processamento em background para melhor UX
- Retry automático: Tentativas automáticas em caso de falha
- Progress indicator: Indicador de progresso para downloads grandes
Changelog
| Versão | Data | Alterações |
|---|---|---|
| 1.0.0 | 2024-01-XX | Implementação inicial da funcionalidade |
Última atualização: 10/10/2025 Responsável: Denis L M Cravo