Вы находитесь на странице: 1из 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
Portugus (Portuguese) / / SAP NFE
NFe B2B de sada - Enviando NFes por Email, WebService e Arquivo (ou FTP)
1. Introduo
1.1 Detalhes
1.1.1 rea(s) de Aplicao
1.1.2 Autor
1.1.3 Ref erncias
1.1.4 Colaborao
1.2 Cenrio
2. Preparao
2.1 Etapas da soluo
3. Desenvolvimento ABAP
3.1 Tabela para armazenar os dados
3.2 RFC para busca dos dados
4. Integration Repository
4.1 Criao do Sof tware Component Version (SWCV)
4.2 Message Mapping
4.2.1 User-Def ined Function (UDF)
4.2.2 Message Mapping do Enhanced Receiver Determination
4.3 Interf ace Mapping
5. Desenvolvimento Java
5.1 Criao do Adapter Module
6. Integration Directory
6.1 Criao das Party's e Communication Channels
6.2 Cenrio NTB2B
7. Testes
1. Introduo
1.1 Detalhes
1.1.1 rea(s) de Aplicao
Nota Fiscal Eletrnica - NFe (SLL-NFE1.0)
SAPProcess 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 SAPPI e SAPPortal onde atuo em projetos de Nota Fiscal Eletrnica, de integraes de sistemas SAP/no-SAPe implantao de portais corporativos.
1.1.3 Referncias
Conf igurao do B2B de NFe usando RFC Lookup
Conf igurao do Enhanced Receiver Determination
Thread do Frum com a discusso sobre este tema
1.1.4 Colaborao
Colaboraram para o desenvolvimento desta soluo:
Raphael Xavier
Henrique Pinto
1.2 Cenrio
Em diversos projetos de implantao de Nota Fiscal Eletrnica (NFe) f az-se necessrio o envio dos arquivos XML das NFes para os clientes. Para que os envios possam ser f eitos por diversas f ormas e
no apenas uma, desenvolvimentos adicionais so necessrios aos j criados para os envios por apenas uma f orma.
Qualquer item que venha a melhorar a soluo ser bem vindo.
2. Preparao
2. Preparao
2.1 Etapas da soluo
Para implementar esta soluo, sero necessrias:
Tabela para armazenar os dados necessrios ref erentes a cada uma das f ormas de envio. Por exemplo, endereo de e-mail, link do WebService, pasta de destino para o arquivo, etc;
RFC para buscar os dados;
Cenrio do B2B de sada (NTB2B);
Alterao da User-Def ined Function (UDF) do message mapping do cenrio 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.
Conf igurar e implementar o Adapter Specif ic Message Attributes (ASMA) para passar os parmetros para os adaptadores dinamicamente;
Implementar o Enhanced Receiver Determination para escolher dinamicamente qual servio receber a mensagem;
3. Desenvolvimento ABAP
3.1 Tabela para armazenar os dados
necessria a utilizao de uma tabela para armazenar as inf ormaes sobre qual f orma o cliente deseja receber os XMLs de NFes emitidas.
Como necessrio utilizar os campos CNPJ e B2B Ativo, a sugesto extender a tabela /XNFE/TB2B, f azendo os includes de acordo com a necessidade. Neste caso, f oram 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;
Usurio (para logar no WebService);
Senha (para logar no WebService).
3.2 RFC para busca dos dados
Esta a mesma RFC como a criada no cenrio tradicional de B2B de sada, porm, alm 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 f acilitar, crie um programa e uma transao para f azer a manuteno dos dados adicionais desta tabela
4. Integration Repository
4.1 Criao do Software Component Version (SWCV)
Fazer a criao do SWCV assim como no cenrio normal de um B2B. Vide a rea de ref erncias que indica a criao de um cenrio de B2B.
4.2 Message Mapping
O message mapping ter uma dif erena: uma quarta varivel f oi adicionada, pois ao mesmo tempo da RFC Lookup, f oi f eita a leitura do XML para identif icar a chave de acesso da NFe emitida, assim o nome
do arquivo poderia ser determinado.
4.2.1 User-Defined Function (UDF)
Para os cenrios de envio de XML via B2B por e-mail f oi criada uma RFC Lookup para que, durante o message mapping, seja f eita uma chamada RFC criada anteriormente, passando como parmetro de
entrada o CNPJ do destinatrio e obtendo como retorno os campos adicionais da tabela, com os dados ref erentes opo de recebimento das NFes pelo cliente.
O cdigo 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 = "nfe@nfe.com.br";
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());
}


//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");
4.2.2 Message Mapping do Enhanced Receiver Determination
Para def inir qual servio receber a mensagem, utilizamos o recurso Enhanced Receiver Determination. Para isso, criamos o seguinte message mapping. Para o campo "Party" adicionamos a constante
ref erente party ref erente ao B2B, que ser vista mais adiante:
Para o campo "Service", criar outro UDF com RFC Lookup, para que, de acordo com a f orma de recebimento escolhida, ele determine qual servio 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;
O cdigo utilizado para o UDF pode ser visto a seguir (desta vez, a varivel que recebe a string do XML no se f az necessria)::
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
4.3 Interface Mapping
Criar um interf ace mapping que tem como mensagem de origem a Message Intef ace "NTB2B_procNFe_OB" e como destino o Message Interf ace "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;
5. Desenvolvimento Java
5.1 Criao do Adapter Module
Nesta parte necessrio desenvolver um cdigo em Java. Ele relativamente simples de ser implementado. O cdigo 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) {
Em caso de dvidas de como criar um Adapter Module, acesse a pgina de Como Criar um Adapter Module na seo Ref erncias. Aps compilar o cdigo, f azer o deploy do mesmo no SDM (lembrando que
para este desenvolvimento utilizamos o PI 7.0).
6. Integration Directory
6.1 Criao das Party's e Communication Channels
Criar uma Party para o B2B. Ela abrigar todas as f ormas de envio de NFe, neste caso, EMAIL, FILE(para arquivo ou FTP) e WEBSERVICEe um receiver communication channel para cada caso:
As conf iguraes dos communication channels f oram f eitas conf orme as f iguras a seguir (Notem que os f lags para utilizao do ASMA esto ativos, assim os parmetros que determinamos como
dinmicos podem ser enviados aos adaptadores):
Mail Adapter (note na aba Module a importao 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;

}

}
SOAPAdapter:
File Adapter:
6.2 Cenrio NTB2B
Criadas as Party's, Services e Adapters (communication channels) para cada uma das trs f ormas de envio, alterar o parmetro "Type of Receiver Determination" para "Extended" no Receiver
Determination e escolher o Interf ace Mapping criado anteriormente:
7. Testes
Para testar cada um dos cenrios, ativar o B2B para um determinado CNPJ e na tabela criada, colocar qual a f orma de envio que deseja enviar o XML.
Envio via E-Mail:
Envio via WebService:
Envio via Arquivo:
No labels
2 Comments
Fabio Fernandes
Parabns Guedes.
Excelente trabalho sobre NFEe na disseminao do WIKI em portugus.
Abs,
Fbio Fernandes
Diretor Neoris / SAPMentor
Fernando Ros
Excelente trabalho Guedes.
Adorei a qualidade das inf ormaes d pra implementar sem ter que buscar inf ormaes complementares em outras f ontes.
Abraos, Fernando Da Rs
Follow SCN
Contact Us SAP Help Portal
Privacy Terms of Use Legal Disclosure Copyright

Вам также может понравиться