NFe B2B de saída

14
Getting Started Newsletters Store Search the Community Welcome, Guest Login Register Products Services & Support About SCN Downloads Industries Training & Education Partnership Developer Center Lines of Business University Alliances Events & Webinars Innovation Added by Ricardo Guedes, last edited by Ricardo Guedes on Dec 14, 2011 Português (Portuguese) / / SAP NFE NFe B2B de saída - Enviando NFes por Email, WebService e Arquivo (ou FTP) 1. Introdução 1.1 Detalhes 1.1.1 Área(s) de Aplicação 1.1.2 Autor 1.1.3 Referências 1.1.4 Colaboração 1.2 Cenário 2. Preparação 2.1 Etapas da solução 3. Desenvolvimento ABAP 3.1 Tabela para armazenar os dados 3.2 RFC para busca dos dados 4. Integration Repository 4.1 Criação do Softw are Component Version (SWCV) 4.2 Message Mapping 4.2.1 User-Defined Function (UDF) 4.2.2 Message Mapping do Enhanced Receiver Determination 4.3 Interface Mapping 5. Desenvolvimento Java 5.1 Criação do Adapter Module 6. Integration Directory 6.1 Criação das Party's e Communication Channels 6.2 Cenário NTB2B 7. Testes 1. Introdução 1.1 Detalhes 1.1.1 Área(s) de Aplicação Nota Fiscal Eletrônica - NFe (SLL-NFE 1.0) SAP Process Integration (PI) 7.0 1.1.2 Autor Ricardo Guedes Created on: 12/02/2008 Biografia do(s) Autor(es): Trabalho na Neoris desde 06/2007 como consultor de SAP PI e SAP Portal onde atuo em projetos de Nota Fiscal Eletrônica, de integrações de sistemas SAP/não-SAP e implantação de portais corporativos. 1.1.3 Referências Configuração do B2B de NFe usando RFC Lookup Configuração do Enhanced Receiver Determination Thread do Fórum com a discussão sobre este tema 1.1.4 Colaboração Colaboraram para o desenvolvimento desta solução: Raphael Xavier Henrique Pinto 1.2 Cenário Em diversos projetos de implantação de Nota Fiscal Eletrônica (NFe) faz-se necessário o envio dos arquivos XML das NFes para os clientes. Para que os envios possam ser feitos por diversas formas e não apenas uma, desenvolvimentos adicionais são necessários aos já criados para os envios por apenas uma forma. Qualquer item que venha a melhorar a solução será bem vindo. 2. Preparação

description

NFe B2B de saída - Enviando NFes por Email, WebService e Arquivo (ou FTP)

Transcript of NFe B2B de saída

Page 1: NFe B2B de saída

Getting Started Newsletters Store

Search the Community

Welcome, Guest Login Register

Products Services & Support About SCN Downloads

Industries Training & Education Partnership Developer Center

Lines of Business University Alliances Events & Webinars Innovation

Added by Ricardo Guedes, last edited by Ricardo Guedes on Dec 14, 2011

Português (Portuguese) / … / SAP NFE

NFe B2B de saída - Enviando NFes por Email, WebService e Arquivo (ou FTP)

1. Introdução

1.1 Detalhes

1.1.1 Área(s) de Aplicação

1.1.2 Autor

1.1.3 Referências

1.1.4 Colaboração

1.2 Cenário

2. Preparação

2.1 Etapas da solução

3. Desenvolvimento ABAP

3.1 Tabela para armazenar os dados

3.2 RFC para busca dos dados

4. Integration Repository

4.1 Criação do Softw are Component Version (SWCV)

4.2 Message Mapping

4.2.1 User-Defined Function (UDF)

4.2.2 Message Mapping do Enhanced Receiver Determination

4.3 Interface Mapping

5. Desenvolvimento Java

5.1 Criação do Adapter Module

6. Integration Directory

6.1 Criação das Party's e Communication Channels

6.2 Cenário NTB2B

7. Testes

1. Introdução

1.1 Detalhes

1.1.1 Área(s) de Aplicação

Nota Fiscal Eletrônica - NFe (SLL-NFE 1.0)

SAP Process Integration (PI) 7.0

1.1.2 Autor

Ricardo Guedes

Created on: 12/02/2008

Biografia do(s) Autor(es):

Trabalho na Neoris desde 06/2007 como consultor de SAP PI e SAP Portal onde atuo em projetos de Nota Fiscal Eletrônica, de integrações de sistemas SAP/não-SAP e implantação de portais corporativos.

1.1.3 Referências

Configuração do B2B de NFe usando RFC Lookup

Configuração do Enhanced Receiver Determination

Thread do Fórum com a discussão sobre este tema

1.1.4 Colaboração

Colaboraram para o desenvolvimento desta solução:

Raphael Xavier

Henrique Pinto

1.2 Cenário

Em diversos projetos de implantação de Nota Fiscal Eletrônica (NFe) faz-se necessário o envio dos arquivos XML das NFes para os clientes. Para que os envios possam ser feitos por diversas formas e

não apenas uma, desenvolvimentos adicionais são necessários aos já criados para os envios por apenas uma forma.

Qualquer item que venha a melhorar a solução será bem vindo.

2. Preparação

Page 2: NFe B2B de saída

2. Preparação

2.1 Etapas da solução

Para implementar esta solução, serão necessárias:

Tabela para armazenar os dados necessários referentes a cada uma das formas de envio. Por exemplo, endereço de e-mail, link do WebService, pasta de destino para o arquivo, etc;

RFC para buscar os dados;

Cenário do B2B de saída (NTB2B);

Alteração da User-Defined Function (UDF) do message mapping do cenário de B2B;

Criar um Adapter Module para trocar o nome do arquivo anexo do e-mail e inserir um texto no corpo do e-mail.

Configurar e implementar o Adapter Specif ic Message Attributes (ASMA) para passar os parâmetros para os adaptadores dinamicamente;

Implementar o Enhanced Receiver Determination para escolher dinamicamente qual serviço receberá a mensagem;

3. Desenvolvimento ABAP

3.1 Tabela para armazenar os dados

É necessária a utilização de uma tabela para armazenar as informações sobre qual forma o cliente deseja receber os XMLs de NFes emitidas.

Como é necessário utilizar os campos CNPJ e B2B Ativo, a sugestão é extender a tabela /XNFE/TB2B, fazendo os includes de acordo com a necessidade. Neste caso, foram adicionados os seguintes

campos:

Nome (para melhor identif icar os clientes na tabela);

Forma de envio (1-E-mail, 2-WebService e 3-Arquivo);

E-mail;

Pasta;

URL do WebService;

Action do WebService;

Usuário (para logar no WebService);

Senha (para logar no WebService).

3.2 RFC para busca dos dados

Esta é a mesma RFC como a criada no cenário tradicional de B2B de saída, porém, além o campo de e-mail que ela costuma retormar, adicionar os outros campos desejados no retorno da RFC para que

eles sejam utilizados no UDF.

Para facilitar, crie um programa e uma transação para fazer a manutenção dos dados adicionais desta tabela

Page 3: NFe B2B de saída

4. Integration Repository

4.1 Criação do Software Component Version (SWCV)

Fazer a criação do SWCV assim como no cenário normal de um B2B. Vide a área de referências que indica a criação de um cenário de B2B.

4.2 Message Mapping

O message mapping terá uma diferença: uma quarta variável foi adicionada, pois ao mesmo tempo da RFC Lookup, foi feita a leitura do XML para identif icar a chave de acesso da NFe emitida, assim o nome

do arquivo poderia ser determinado.

Page 4: NFe B2B de saída

4.2.1 User-Defined Function (UDF)

Para os cenários de envio de XML via B2B por e-mail foi criada uma RFC Lookup para que, durante o message mapping, seja feita uma chamada à RFC criada anteriormente, passando como parâmetro de

entrada o CNPJ do destinatário e obtendo como retorno os campos adicionais da tabela, com os dados referentes à opção de recebimento das NFes pelo cliente.

O código utilizado para o UDF pode ser visto a seguir:

public String retornaDados(String cnpj,String busSystem,String commChannel,String xml,Container container){

imports

com.sap.aii.mapping.api.*;com.sap.aii.mapping.lookup.*;java.util.Map;javax.xml.parsers.*;java.io.*;org.w3c.dom.*;

java.util.Map map;

AbstractTrace trace = container.getTrace();

Channel channel = null;

RfcAccessor accessor = null;

map = container.getTransformationParameters();

//envia a NFe para um administrador no caso de falha

String email = "[email protected]";

int forma = 0;

String pastaDestino = "";

String webserviceUrl = "";

String webserviceUsuario = "";

String webserviceAction = "";

try {

// Retorna o Communication Channel

channel = LookupService.getChannel(busSystem, commChannel);

trace.addWarning("Channel: " + channel);

// Get a RFC accessor for the channel

accessor = LookupService.getRfcAccessor(channel);

// Define a Mensagem de requisicao para a RFC

String req = "<ns0:ZPIF_NFE_CLIENTE xmlns:ns0='urn:sap-com:document:sap:rfc:functions'><ZCNPJ>" + cnpj + "</ZCNPJ>

</ns0:ZPIF_NFE_CLIENTE>";

// Create the xml inputstream

InputStream inputStream = new ByteArrayInputStream(req.getBytes("UTF-8"));

// Create xml payload

XmlPayload payload = LookupService.getXmlPayload(inputStream);

// Execute lookup

XmlPayload result = accessor.call(payload);

// Get the response

InputStream resp = result.getContent();

// Parse the response

//Campo ZFORMA

DocumentBuilder builder = DocumentBuilderFactory.newInstance().newDocumentBuilder();

Document doc = builder.parse(resp);

Node nodeForma = (Node) doc.getElementsByTagName("ZFORMA").item(0);

if (nodeForma.hasChildNodes() && !nodeForma.getFirstChild().getNodeValue().equals("")) {

forma = Integer.parseInt(nodeForma.getFirstChild().getNodeValue());

}

Page 5: NFe B2B de saída

//Campo ZEMAIL

Node nodeEmail = (Node) doc.getElementsByTagName("ZEMAIL").item(0);

if (nodeEmail.hasChildNodes() && !nodeEmail.getFirstChild().getNodeValue().equals("")) {

email = nodeEmail.getFirstChild().getNodeValue();

}

//Campo ZPASTA_DESTINO

Node nodePasta = (Node) doc.getElementsByTagName("ZPASTA_DESTINO").item(0);

if (nodePasta.hasChildNodes() && !nodePasta.getFirstChild().getNodeValue().equals("")) {

pastaDestino = nodePasta.getFirstChild().getNodeValue();

}

//Campo ZWEBSERVICE_URL

Node nodeUrl = (Node) doc.getElementsByTagName("ZWEBSERVICE_URL").item(0);

if (nodeUrl.hasChildNodes() && !nodeUrl.getFirstChild().getNodeValue().equals("")) {

webserviceUrl = nodeUrl.getFirstChild().getNodeValue();

}

//Campo ZWEBSERVICE_USUARIO

Node nodeUsuario = (Node) doc.getElementsByTagName("ZWEBSERVICE_USU").item(0);

if (nodeUsuario.hasChildNodes() && !nodeUsuario.getFirstChild().getNodeValue().equals("")) {

webserviceUsuario = nodeUsuario.getFirstChild().getNodeValue();

}

//Campo ZWEBSERVICE_ACTION

Node nodeAction = (Node) doc.getElementsByTagName("ZWEBSERVICE_ACT").item(0);

if (nodeAction.hasChildNodes() && !nodeAction.getFirstChild().getNodeValue().equals("")) {

webserviceAction = nodeAction.getFirstChild().getNodeValue();

}

} catch (Exception e) {

trace.addWarning("Falha na RFC: " + e);

} finally {

// Close the accessor in order to free resources.

if (accessor!=null) {

try {

accessor.close();

} catch (Exception e) {

trace.addWarning("Erro ao finalizar o accessor: " + e);

}

}

}

// Definir qual rota o XML sera enviado

if (forma == 1){

// Envio via E-MAIL

int posicaoId = xml.indexOf("Id=");

String chaveAcesso = xml.substring(posicaoId + 7, posicaoId + 51);

String filename = chaveAcesso + ".xml";

map.put(StreamTransformationConstants.RECEIVER_SERVICE, "EMAIL");

// Preenche o dynamic configuration para o campo "para" no mail adapter

DynamicConfigurationKey toKey = DynamicConfigurationKey.create("http://sap.com/xi/XI/System/Mail", "THeaderTO");

DynamicConfigurationKey attachfilenameKey = DynamicConfigurationKey.create("http://sap.com/xi/XI/System/File",

"FileName");

DynamicConfiguration conf = (DynamicConfiguration)

container.getTransformationParameters().get(StreamTransformationConstants.DYNAMIC_CONFIGURATION);

conf.put(toKey, email);

conf.put(attachfilenameKey, filename);

}

else if(forma == 2){

// Envio via WEBSERVICE

map.put(StreamTransformationConstants.RECEIVER_SERVICE, "WEBSERVICE");

// Preenche o dynamic configuration para os parametros do SOAP adapter

DynamicConfigurationKey urlKey = DynamicConfigurationKey.create("http://sap.com/xi/XI/System/SOAP",

"TServerLocation");

Page 6: NFe B2B de saída

4.2.2 Message Mapping do Enhanced Receiver Determination

Para definir qual serviço receberá a mensagem, utilizamos o recurso Enhanced Receiver Determination. Para isso, criamos o seguinte message mapping. Para o campo "Party" adicionamos a constante

referente à party referente ao B2B, que será vista mais adiante:

Para o campo "Service", criar outro UDF com RFC Lookup, para que, de acordo com a forma de recebimento escolhida, ele determine qual serviço receberá a mensagem:

DynamicConfigurationKey userKey = DynamicConfigurationKey.create("http://sap.com/xi/XI/System/SOAP", "TAuthKey");

DynamicConfigurationKey actionKey = DynamicConfigurationKey.create("http://sap.com/xi/XI/System/SOAP",

"THeaderSOAPACTION");

DynamicConfiguration conf = (DynamicConfiguration)

container.getTransformationParameters().get(StreamTransformationConstants.DYNAMIC_CONFIGURATION);

conf.put(urlKey, webserviceUrl);

conf.put(userKey, webserviceUsuario);

conf.put(actionKey, webserviceAction);

}

else if (forma == 3){

// Envio via Arquivo

int posicaoId = xml.indexOf("Id=");

String chaveAcesso = xml.substring(posicaoId + 7, posicaoId + 51);

String filename = chaveAcesso + ".xml";

map.put(StreamTransformationConstants.RECEIVER_SERVICE, "FILE");

// Preenche o dynamic configuration para os parametros do File adapter

DynamicConfigurationKey filenameKey = DynamicConfigurationKey.create("http://sap.com/xi/XI/System/File",

"FileName");

DynamicConfigurationKey pastadestinoKey = DynamicConfigurationKey.create("http://sap.com/xi/XI/System/File",

"Directory");

DynamicConfiguration conf = (DynamicConfiguration)

container.getTransformationParameters().get(StreamTransformationConstants.DYNAMIC_CONFIGURATION);

conf.put(filenameKey, filename);

conf.put(pastadestinoKey, pastaDestino);

}

// Since this is a dummy mapping, return the same value from input

return cnpj;

Page 7: NFe B2B de saída

O código utilizado para o UDF pode ser visto a seguir (desta vez, a variável que recebe a string do XML não se faz necessária)::

java.util.Map map;

AbstractTrace trace = container.getTrace();

Channel channel = null;

RfcAccessor accessor = null;

map = container.getTransformationParameters();

int forma = 0;

String servico = "";

try {

// Retorna o Communication Channel

channel = LookupService.getChannel(busSystem, commChannel);

// Get a RFC accessor for the channel

accessor = LookupService.getRfcAccessor(channel);

// Define a Mensagem de requisicao para a RFC

String req = "<ns0:ZPIF_NFE_CLIENTE xmlns:ns0='urn:sap-com:document:sap:rfc:functions'><ZCNPJ>" + cnpj + "</ZCNPJ>

</ns0:ZPIF_NFE_CLIENTE>";

// Create the xml inputstream

InputStream inputStream = new ByteArrayInputStream(req.getBytes("UTF-8"));

// Create xml payload

XmlPayload payload = LookupService.getXmlPayload(inputStream);

// Execute lookup

Page 8: NFe B2B de saída

4.3 Interface Mapping

Criar um interface mapping que tem como mensagem de origem a Message Inteface "NTB2B_procNFe_OB" e como destino o Message Interface "ReceiverDetermination", encontrado no namespace

"http://sap.com/xi/XI/System":

// Execute lookup

XmlPayload result = accessor.call(payload);

// Get the response

InputStream resp = result.getContent();

// Parse the response

//Campo ZFORMA

DocumentBuilder builder = DocumentBuilderFactory.newInstance().newDocumentBuilder();

Document doc = builder.parse(resp);

Node nodeForma = (Node) doc.getElementsByTagName("ZFORMA").item(0);

if (nodeForma.hasChildNodes() && \!nodeForma.getFirstChild().getNodeValue().equals("")) {

forma = Integer.parseInt(nodeForma.getFirstChild().getNodeValue());

}

} catch (Exception e) {

trace.addWarning("Falha na RFC: " + e);

} finally {

// Close the accessor in order to free resources.

if (accessor\!=null) {

try {

accessor.close();

} catch (Exception e) {

trace.addWarning("Erro ao finalizar o accessor: " + e);

}

}

}

// Definir qual rota o XML sera enviado

if (forma == 1){

// Envio via E-MAIL

servico = "EMAIL";

}

else if(forma == 2){

// Envio via WEBSERVICE

servico = "WEBSERVICE";

}

else if (forma == 3){

// Envio via Arquivo

servico = "FILE";

}

return servico;

Page 9: NFe B2B de saída

5. Desenvolvimento Java

5.1 Criação do Adapter Module

Nesta parte é necessário desenvolver um código em Java. Ele é relativamente simples de ser implementado. O código pode ser visto a seguir:

package br.com.neoris.nfe.attachment;

import com.sap.aii.af.mp.module.*;

import com.sap.aii.af.ra.ms.api.*;

import com.sap.aii.af.service.auditlog.*;

import javax.ejb.*;

public class SetAttachmentNameBean implements SessionBean, Module {

private SessionContext myContext;

private AuditMessageKey amk;

public SetAttachmentNameBean() { }

public void ejbRemove() { }

public void ejbActivate() {}

public void ejbPassivate() { }

public void setSessionContext(SessionContext context) {

myContext = context;

}

public void ejbCreate() throws CreateException {

}

public ModuleData process(ModuleContext moduleContext, ModuleData inputModuleData) throws ModuleException {

Message msg = (Message) inputModuleData.getPrincipalData();

if (msg.getMessageDirection() == MessageDirection.INBOUND) {

amk = new AuditMessageKey(msg.getMessageId(), AuditDirection.INBOUND);

} else {

amk = new AuditMessageKey(msg.getMessageId(), AuditDirection.OUTBOUND);

}

Audit.addAuditLogEntry(amk, AuditLogStatus.SUCCESS, "NFe: Entrando no modulo para definir nome do arquivo...");

try {

Payload text = msg.getDocument();

byte xmlContent[] = text.getContent();

String fileName = msg.getMessageProperty("http://sap.com/xi/XI/System/File", "FileName");

StringBuffer content = new StringBuffer();

content.append("Prezado cliente, \r\n\r\n");

content.append("Segue arquivo anexo referente a sua Nota Fiscal Eletr\u00F4nica.\r\n\r\n");

content.append("\r\n\r\n");

content.append("Att,\r\n");

content.append("Nome da Empresa\r\n");

content.append("Ramo de Atividade");

text.setContent(content.toString().getBytes("UTF-8"));

text.setContentType("text/plain;charset=\"UTF-8\";");

Payload payload = msg.createPayload();

payload.setContent(xmlContent);

if (fileName == null) {

Page 10: NFe B2B de saída

Em caso de dúvidas de como criar um Adapter Module, acesse a página de Como Criar um Adapter Module na seção Referências. Após compilar o código, fazer o deploy do mesmo no SDM (lembrando que

para este desenvolvimento utilizamos o PI 7.0).

6. Integration Directory

6.1 Criação das Party's e Communication Channels

Criar uma Party para o B2B. Ela abrigará todas as formas de envio de NFe, neste caso, EMAIL, FILE (para arquivo ou FTP) e WEBSERVICE e um receiver communication channel para cada caso:

As configurações dos communication channels foram feitas conforme as f iguras a seguir (Notem que os f lags para utilização do ASMA estão ativos, assim os parâmetros que determinamos como

dinâmicos podem ser enviados aos adaptadores):

Mail Adapter (note na aba Module a importação do Custom Adapter Module criado anteriormente):

if (fileName == null) {

fileName = "default.xml";

}

payload.setContentType("application/xml");

payload.setName(fileName);

payload.setDescription(fileName);

msg.addAttachment(payload);

inputModuleData.setPrincipalData(msg);

} catch (Exception e) {

throw new ModuleException(e);

}

return inputModuleData;

}

}

Page 11: NFe B2B de saída

SOAP Adapter:

Page 12: NFe B2B de saída

File Adapter:

Page 13: NFe B2B de saída

6.2 Cenário NTB2B

Criadas as Party's, Services e Adapters (communication channels) para cada uma das três formas de envio, alterar o parâmetro "Type of Receiver Determination" para "Extended" no Receiver

Determination e escolher o Interface Mapping criado anteriormente:

Page 14: NFe B2B de saída

7. TestesPara testar cada um dos cenários, ativar o B2B para um determinado CNPJ e na tabela criada, colocar qual a forma de envio que deseja enviar o XML.

Envio via E-Mail:

Envio via WebService:

Envio via Arquivo:

No labels

2 Comments

Fabio Fernandes

Parabéns Guedes.

Excelente trabalho sobre NFE e na disseminação do WIKI em português.

Abs,

Fábio Fernandes

Diretor Neoris / SAP Mentor

Fernando Ros

Excelente trabalho Guedes.

Adorei a qualidade das informações dá pra implementar sem ter que buscar informações complementares em outras fontes.

Abraços, Fernando Da Rós

Follow SCNContact Us SAP Help Portal

Privacy Terms of Use Legal Disclosure Copyright