Look Fantastic PT 728X90

Call of Duty: Mobile

SEPA XML CODE

C2B - Prestação de Serviços a Clientes Registo Normalizado (XML) SEPA


A criação da SEPA (Single Euro Payments Area - Área Única de Pagamentos em Euros) permitiu o reforço da integração europeia e o estabelecimento de um mercado único de pagamentos de retalho. Atualmente, o espaço SEPA abrange, para além dos Estados-Membros da UE, a Islândia, o Liechtenstein, o Mónaco, a Noruega, San Marino e a Suíça. Neste espaço, os agentes económicos podem efetuar e receber pagamentos em euros, dentro de cada país e entre países, sob as mesmas condições, direitos e obrigações.
Na concretização deste objetivo, a SEPA disponibiliza instrumentos de pagamento pan-europeus, como Transferências a Crédito (SCT) e Débitos Diretos (SEPA DD), cujo funcionamento assenta em standards, procedimentos e, na medida do possível, infraestruturas comuns a todos os participantes.
Os modelos técnicos e de negócio são definidos pelo European Payments Council (EPC), nos Rulebooks e nas respetivas Implementation Guidelines (disponíveis em www.europeanpaymentscouncil.eu). Estes modelos baseiam-se nas especificações técnicas da Norma ISO20022 e visam assegurar um processamento automatizado de transferências a crédito e de cobranças.
Cabe aos bancos a responsabilidade de implementar um canal Customer-to-Bank (C2B) compatível com a SEPA, seguindo as recomendações do EPC de utilização de mensagens standard da norma ISO20022 XML definidas nas SEPA C2B Implementation Guidelines e disponibilizar aos seus clientes o layout de ficheiro a utilizar.
Neste enquadramento, visando facilitar a ligação entre o cliente e o banco, a comunidade bancária portuguesa desenvolveu um formato harmonizado de comunicação, aplicável às Transferências a Crédito SEPA e aos Débitos Diretos SEPA. O presente documento descreve esse padrão, para utilização na relação Cliente - Banco pelas instituições aderentes da comunidade bancária nacional.
A utilização de um layout harmonizado apresenta claros benefícios para a comunicação C2B (em especial para as empresas e organismos da Administração Pública), propondo-se: (i) obviar à multiplicidade de formatos utilizados pelos clientes na sua relação com os bancos para a iniciação de instruções de pagamento; e (ii) oferecer às empresas e organismos da Administração Pública uma solução de comunicação eficiente e vantajosa em termos de custos.


Visto o relativo a documentação e estruturação do ficheiro XML, podemos avançar com a solução que implementei para os pagamentos dos ordenados dos funcionários na empresa onde a data de hoje encontro-me a prestar serviços.

Vou partir do principio de que temos uma tabela com todos os dados dos funcionários da empresa. Vamos ter que adicionar mais dois (2) campos, que são o IBAN e o BIC (Swift) da conta do funcionário.
No meu caso programei tudo num reporte ao qual dei o nome "Ficheiro Banco", o mesmo tem um "Request Page" com o seguinte desenho

Ficheiro Banco
MS NAV 2009 R2 - Report 60003 Ficheiro Banco

No desenho do reporte temos um DataItem com a tabela onde se encontra armazenado os dados do processamento dos ordenados, abrimos o editor de código C/AL e programamos as seguintes instruções:

Pagamento Remuneracoes3 - OnPreDataItem()

IF vCartao THEN
  CurrReport.SKIP;
IF ((Filetype = Filetype::"0")OR(Filetype = Filetype::PS2)OR(Bank = '')) THEN
  CurrReport.SKIP;

Mov   :=48; // Numero da linha onde iniciam os pagamentos
Contar:=0;  // Total empregados processados
Total :=0;  // Total EUR Processado
IF DataLanc=0D THEN BEGIN;
  MESSAGE(Text60400);
  CurrReport.QUIT;
END;

Window.OPEN('#1#################################\\'+'Nº empregado               #2######\');
CompanyInfo.GET;
vDia:=FORMAT(DATE2DMY(DataLanc,1),0,'<Precision,0:0><Standard Format,1>');
vMês:=FORMAT(DATE2DMY(DataLanc,2),0,'<Precision,0:0><Standard Format,1>');
IF STRLEN(vDia)=1 THEN vDia:='0'+vDia;
IF STRLEN(vMês)=1 THEN vMês:='0'+vMês;
vAno:=FORMAT(DATE2DMY(DataLanc,3),0,'<Precision,0:0><Standard Format,1>');
IF DataLanc = TODAY THEN
  vTime := COPYSTR(FORMAT(TIME),1,8)
ELSE
  vTime := '08:00:00';

vDate := vAno+'-'+vMês+'-'+vDia+'T'+vTime;
//vDate := DELCHR(FORMAT(vDate),'=',' ');
vDate := CONVERTSTR(vDate,' ','0');
CLEAR(xmldoc);
CLEAR(xmlnode);
CLEAR(xmlnode2);
CLEAR(newnode);
PmtInfId := '';

CREATE(xmldoc,TRUE);

xmldoc.loadXML('<?xml version="1.0" encoding="UTF-8"?><Document></Document>');
xmlnode := xmldoc.documentElement;
AddAttribute(xmlnode,'xmlns:xsi','http://www.w3.org/2001/XMLSchema-instance');
AddAttribute(xmlnode,'xmlns','urn:iso:std:iso:20022:tech:xsd:pain.001.001.03');

newnode    := xmldoc.createNode(1,'CstmrCdtTrfInitn','');
xmlnode.appendChild(newnode);
xmlnode2   := xmlnode.selectSingleNode('CstmrCdtTrfInitn');

newnode    := xmldoc.createNode(1,'GrpHdr','');
xmlnode2.appendChild(newnode);
  xmlnode2   := xmlnode.selectSingleNode('CstmrCdtTrfInitn/GrpHdr');
    newnode    := xmldoc.createNode(1,'MsgId','');
    newnode.text := 'Grupel-'+vDate;
    xmlnode2.appendChild(newnode);
    newnode    := xmldoc.createNode(1,'CreDtTm','');
    newnode.text := vDate;
    xmlnode2.appendChild(newnode);
    newnode    := xmldoc.createNode(1,'NbOfTxs','');
    xmlnode2.appendChild(newnode);
    newnode    := xmldoc.createNode(1,'CtrlSum','');
    xmlnode2.appendChild(newnode);
    newnode    := xmldoc.createNode(1,'InitgPty','');
    xmlnode2.appendChild(newnode);
    xmlnode2   := xmlnode.selectSingleNode('CstmrCdtTrfInitn/GrpHdr/InitgPty');
      newnode    := xmldoc.createNode(1,'Nm','');
      newnode.text := CompanyInfo.Name;
      xmlnode2.appendChild(newnode);
      newnode    := xmldoc.createNode(1,'Id','');
      //newnode.text := CompanyInfo.Name;
      xmlnode2.appendChild(newnode);
      xmlnode2   := xmlnode.selectSingleNode('CstmrCdtTrfInitn/GrpHdr/InitgPty/Id');
        newnode    := xmldoc.createNode(1,'PrvtId','');
        xmlnode2.appendChild(newnode);
        xmlnode2   := xmlnode.selectSingleNode('CstmrCdtTrfInitn/GrpHdr/InitgPty/Id/PrvtId');
          newnode    := xmldoc.createNode(1,'Othr','');
          xmlnode2.appendChild(newnode);
          xmlnode2   := xmlnode.selectSingleNode('CstmrCdtTrfInitn/GrpHdr/InitgPty/Id/PrvtId/Othr');
            newnode    := xmldoc.createNode(1,'Id','');
            newnode.text := '46082810001';
            xmlnode2.appendChild(newnode);


xmlnode2   := xmlnode.selectSingleNode('CstmrCdtTrfInitn');
newnode    := xmldoc.createNode(1,'PmtInf','');
xmlnode2.appendChild(newnode);
  xmlnode2   := xmlnode.selectSingleNode('CstmrCdtTrfInitn/PmtInf');
    newnode    := xmldoc.createNode(1,'PmtInfId','');
    xmlnode2.appendChild(newnode);
    newnode    := xmldoc.createNode(1,'PmtMtd','');
    newnode.text := 'TRF';
    xmlnode2.appendChild(newnode);
    newnode    := xmldoc.createNode(1,'NbOfTxs','');
    xmlnode2.appendChild(newnode);
    newnode    := xmldoc.createNode(1,'CtrlSum','');
    xmlnode2.appendChild(newnode);
    newnode    := xmldoc.createNode(1,'PmtTpInf','');
    xmlnode2.appendChild(newnode);
    xmlnode2   := xmlnode.selectSingleNode('CstmrCdtTrfInitn/PmtInf/PmtTpInf');
      newnode    := xmldoc.createNode(1,'CtgyPurp','');
      xmlnode2.appendChild(newnode);
      xmlnode2   := xmlnode.selectSingleNode('CstmrCdtTrfInitn/PmtInf/PmtTpInf/CtgyPurp');
        newnode    := xmldoc.createNode(1,'Cd','');
        newnode.text := 'SUPP';
        xmlnode2.appendChild(newnode);
    xmlnode2   := xmlnode.selectSingleNode('CstmrCdtTrfInitn/PmtInf');
      newnode    := xmldoc.createNode(1,'ReqdExctnDt','');
      newnode.text := vAno+'-'+vMês+'-'+vDia;
      xmlnode2.appendChild(newnode);
      newnode    := xmldoc.createNode(1,'Dbtr','');
      xmlnode2.appendChild(newnode);
      xmlnode2   := xmlnode.selectSingleNode('CstmrCdtTrfInitn/PmtInf/Dbtr');
        newnode    := xmldoc.createNode(1,'Nm','');
        newnode.text := CompanyInfo.Name;
        xmlnode2.appendChild(newnode);
        newnode    := xmldoc.createNode(1,'PstlAdr','');
        xmlnode2.appendChild(newnode);
        xmlnode2   := xmlnode.selectSingleNode('CstmrCdtTrfInitn/PmtInf/Dbtr/PstlAdr');
        newnode    := xmldoc.createNode(1,'Ctry','');
        newnode.text := 'PT';
        xmlnode2.appendChild(newnode);
        newnode    := xmldoc.createNode(1,'AdrLine','');
        newnode.text := CompanyInfo.Address+', '+CompanyInfo."Post Code"+' '+CompanyInfo.County+
        ', '+CompanyInfo.City;
        xmlnode2.appendChild(newnode);
    xmlnode2   := xmlnode.selectSingleNode('CstmrCdtTrfInitn/PmtInf');
      newnode    := xmldoc.createNode(1,'DbtrAcct','');
      xmlnode2.appendChild(newnode);
      xmlnode2   := xmlnode.selectSingleNode('CstmrCdtTrfInitn/PmtInf/DbtrAcct');
        newnode    := xmldoc.createNode(1,'Id','');
        xmlnode2.appendChild(newnode);
        xmlnode2   := xmlnode.selectSingleNode('CstmrCdtTrfInitn/PmtInf/DbtrAcct/Id');
          newnode    := xmldoc.createNode(1,'IBAN','');
          newnode.text := IBANEmpresa;
          xmlnode2.appendChild(newnode);
    xmlnode2   := xmlnode.selectSingleNode('CstmrCdtTrfInitn/PmtInf');
      newnode    := xmldoc.createNode(1,'DbtrAgt','');
      xmlnode2.appendChild(newnode);
      xmlnode2   := xmlnode.selectSingleNode('CstmrCdtTrfInitn/PmtInf/DbtrAgt');
        newnode    := xmldoc.createNode(1,'FinInstnId','');
        xmlnode2.appendChild(newnode);
        xmlnode2   := xmlnode.selectSingleNode('CstmrCdtTrfInitn/PmtInf/DbtrAgt/FinInstnId');
          newnode    := xmldoc.createNode(1,'BIC','');
          newnode.text := SWIFTEmpresa;
          xmlnode2.appendChild(newnode);

Pagamento Remuneracoes3 - OnAfterGetRecord()

IF vCartao THEN
  CurrReport.SKIP;
IF ((Filetype = Filetype::"0")OR(Filetype = Filetype::PS2)OR(Bank = '')) THEN
  CurrReport.SKIP;

Window.UPDATE(1,'');
Window.UPDATE(2,'');

Window.UPDATE(1,"Empregado Descr");
Window.UPDATE(2,"Cod Empregado");

IF NOT ("Processar para Ficheiro Transf") THEN BEGIN
  CurrReport.SKIP;
END;
IF PmtInfId = '' THEN
  PmtInfId := "No. Processamento";

CLEAR(escravo);
escravo.GET("Cod Empregado");
xmlnode2   := xmlnode.selectSingleNode('CstmrCdtTrfInitn/PmtInf');
newnode    := xmldoc.createNode(1,'CdtTrfTxInf','');
xmlnode2.appendChild(newnode);
AddAttribute(newnode,'ID',FORMAT(Contar));
  root := '[@ID = "'+FORMAT(Contar)+'"]';
  xmlnode2   := xmlnode.selectSingleNode('CstmrCdtTrfInitn/PmtInf/CdtTrfTxInf'+root);
  newnode    := xmldoc.createNode(1,'PmtId','');
  xmlnode2.appendChild(newnode);
  xmlnode2   := xmlnode.selectSingleNode('CstmrCdtTrfInitn/PmtInf/CdtTrfTxInf'+root+'/PmtId');
    newnode    := xmldoc.createNode(1,'EndToEndId','');
    newnode.text := "No. Processamento";
    xmlnode2.appendChild(newnode);

  xmlnode2   := xmlnode.selectSingleNode('CstmrCdtTrfInitn/PmtInf/CdtTrfTxInf'+root);
    newnode    := xmldoc.createNode(1,'Amt','');
    xmlnode2.appendChild(newnode);
    xmlnode2   := xmlnode.selectSingleNode('CstmrCdtTrfInitn/PmtInf/CdtTrfTxInf'+root+'/Amt');
      newnode    := xmldoc.createNode(1,'InstdAmt','');
      newnode.text := CONVERTSTR(DELCHR(DELCHR(FORMAT("Valor Bruto Total"),'=',' '),'=','.'),',','.');
      xmlnode2.appendChild(newnode);
      xmlnode2   := xmlnode.selectSingleNode('CstmrCdtTrfInitn/PmtInf/CdtTrfTxInf'+root+'/Amt/InstdAmt');
      AddAttribute(xmlnode2,'Ccy','EUR');

  xmlnode2   := xmlnode.selectSingleNode('CstmrCdtTrfInitn/PmtInf/CdtTrfTxInf'+root);
    newnode    := xmldoc.createNode(1,'CdtrAgt','');
    xmlnode2.appendChild(newnode);
    xmlnode2   := xmlnode.selectSingleNode('CstmrCdtTrfInitn/PmtInf/CdtTrfTxInf'+root+'/CdtrAgt');
      newnode    := xmldoc.createNode(1,'FinInstnId','');
      xmlnode2.appendChild(newnode);
      xmlnode2   := xmlnode.selectSingleNode('CstmrCdtTrfInitn/PmtInf/CdtTrfTxInf'+root+'/CdtrAgt/FinInstnId');
        newnode    := xmldoc.createNode(1,'BIC','');
        newnode.text := escravo."Swift Banco";
        xmlnode2.appendChild(newnode);

  xmlnode2   := xmlnode.selectSingleNode('CstmrCdtTrfInitn/PmtInf/CdtTrfTxInf'+root);
    newnode    := xmldoc.createNode(1,'Cdtr','');
    xmlnode2.appendChild(newnode);
    xmlnode2   := xmlnode.selectSingleNode('CstmrCdtTrfInitn/PmtInf/CdtTrfTxInf'+root+'/Cdtr');
      newnode    := xmldoc.createNode(1,'Nm','');
      newnode.text := "Empregado Descr";
      xmlnode2.appendChild(newnode);
      newnode    := xmldoc.createNode(1,'PstlAdr','');
      xmlnode2.appendChild(newnode);
      xmlnode2   := xmlnode.selectSingleNode('CstmrCdtTrfInitn/PmtInf/CdtTrfTxInf'+root+'/Cdtr/PstlAdr');
        newnode    := xmldoc.createNode(1,'Ctry','');
        IF escravo."Country/Region Code" <> '' THEN
          newnode.text := escravo."Country/Region Code";
        IF escravo."Country/Region Code" = '' THEN
          newnode.text := 'PT';
        xmlnode2.appendChild(newnode);
       newnode    := xmldoc.createNode(1,'AdrLine','');
        newnode.text := escravo.Address;
        xmlnode2.appendChild(newnode);
        newnode    := xmldoc.createNode(1,'AdrLine','');
        newnode.text := escravo."Post Code"+' '+escravo.County+', '+escravo.City+' '+escravo."Country/Region Code";
        xmlnode2.appendChild(newnode);


  xmlnode2   := xmlnode.selectSingleNode('CstmrCdtTrfInitn/PmtInf/CdtTrfTxInf'+root);
    newnode    := xmldoc.createNode(1,'CdtrAcct','');
    xmlnode2.appendChild(newnode);
    xmlnode2   := xmlnode.selectSingleNode('CstmrCdtTrfInitn/PmtInf/CdtTrfTxInf'+root+'/CdtrAcct');
      newnode    := xmldoc.createNode(1,'Id','');
      xmlnode2.appendChild(newnode);
      xmlnode2   := xmlnode.selectSingleNode('CstmrCdtTrfInitn/PmtInf/CdtTrfTxInf'+root+'/CdtrAcct/Id');
        newnode    := xmldoc.createNode(1,'IBAN','');
        newnode.text := escravo."IBAN Banco";
        xmlnode2.appendChild(newnode);

  xmlnode2   := xmlnode.selectSingleNode('CstmrCdtTrfInitn/PmtInf/CdtTrfTxInf'+root);
    newnode    := xmldoc.createNode(1,'RmtInf','');
    xmlnode2.appendChild(newnode);
    xmlnode2   := xmlnode.selectSingleNode('CstmrCdtTrfInitn/PmtInf/CdtTrfTxInf'+root+'/RmtInf');
      newnode    := xmldoc.createNode(1,'Strd','');
      xmlnode2.appendChild(newnode);
      xmlnode2   := xmlnode.selectSingleNode('CstmrCdtTrfInitn/PmtInf/CdtTrfTxInf'+root+'/RmtInf/Strd');
        newnode    := xmldoc.createNode(1,'CdtrRefInf','');
        xmlnode2.appendChild(newnode);
        xmlnode2   := xmlnode.selectSingleNode('CstmrCdtTrfInitn/PmtInf/CdtTrfTxInf'+root+'/RmtInf/Strd/CdtrRefInf');
          newnode    := xmldoc.createNode(1,'Tp','');
          xmlnode2.appendChild(newnode);
         xmlnode2   := xmlnode.selectSingleNode('CstmrCdtTrfInitn/PmtInf/CdtTrfTxInf'+root+'/RmtInf/Strd/CdtrRefInf/Tp');
            newnode    := xmldoc.createNode(1,'CdOrPrtry','');
            xmlnode2.appendChild(newnode);
            xmlnode2   := xmlnode.selectSingleNode('CstmrCdtTrfInitn/PmtInf/CdtTrfTxInf'+root
            +'/RmtInf/Strd/CdtrRefInf/Tp/'+'CdOrPrtry');
              newnode    := xmldoc.createNode(1,'Cd','');
              newnode.text := 'SCOR';
              xmlnode2.appendChild(newnode);
         xmlnode2   := xmlnode.selectSingleNode('CstmrCdtTrfInitn/PmtInf/CdtTrfTxInf'+root+'/RmtInf/Strd/CdtrRefInf/Tp');
            newnode    := xmldoc.createNode(1,'Issr','');
            newnode.text := COPYSTR("Empregado Descr",1,34);
            xmlnode2.appendChild(newnode);
        xmlnode2   := xmlnode.selectSingleNode('CstmrCdtTrfInitn/PmtInf/CdtTrfTxInf'+root+'/RmtInf/Strd/CdtrRefInf');
          newnode    := xmldoc.createNode(1,'Ref','');
          newnode.text := "No. Processamento";
          xmlnode2.appendChild(newnode);
Mov   := Mov+1;
Contar:= Contar+1;
Total += "Valor Bruto Total";

Pagamento Remuneracoes3 - OnPostDataItem()


IF vCartao THEN
  CurrReport.SKIP;
IF ((Filetype = Filetype::"0")OR(Filetype = Filetype::PS2)OR(Bank = '')) THEN
  CurrReport.SKIP;

xmlnode2      := xmlnode.selectSingleNode('CstmrCdtTrfInitn/GrpHdr/NbOfTxs');
xmlnode2.text := FORMAT(Contar);
xmlnode2      := xmlnode.selectSingleNode('CstmrCdtTrfInitn/GrpHdr/CtrlSum');
xmlnode2.text := CONVERTSTR(DELCHR(DELCHR(FORMAT(Total),'=',' '),'=','.'),',','.');
xmlnode2      := xmlnode.selectSingleNode('CstmrCdtTrfInitn/PmtInf/PmtInfId');
xmlnode2.text := PmtInfId;
xmlnode2      := xmlnode.selectSingleNode('CstmrCdtTrfInitn/PmtInf/NbOfTxs');
xmlnode2.text := FORMAT(Contar);
xmlnode2      := xmlnode.selectSingleNode('CstmrCdtTrfInitn/PmtInf/CtrlSum');
xmlnode2.text := CONVERTSTR(DELCHR(DELCHR(FORMAT(Total),'=',' '),'=','.'),',','.');

Window.CLOSE;
MESSAGE('Foram criadas %1 linha(s) de movimento',Contar);
xmldoc.save('c:\temp\001-001-03-'+CompanyInfo.Name+'('+vAno+'-'+vMês+'-'+vDia+')'+'.xml');
ToFile := '001-001-03-'+CompanyInfo.Name+'('+vAno+'-'+vMês+'-'+vDia+')'+'.xml';

xmlread('c:\temp\001-001-03-'+CompanyInfo.Name+'('+vAno+'-'+vMês+'-'+vDia+')'+'.xml');

DOWNLOAD('c:\temp\001-001-03-'+CompanyInfo.Name+'('+vAno+'-'+vMês+'-'+vDia+')'+'.xml',Text014,'%temp%',Text015,ToFile);
CLEARALL;

AddAttribute(VAR XMLAttNode : Automation "'Microsoft XML, v6.0'.IXMLDOMNode";AttributeName : Text[180];AttributeValue : Text[180])

NewAttributeNode := XMLAttNode.ownerDocument.createAttribute(AttributeName);
IF AttributeValue <> '' THEN BEGIN
  NewAttributeNode.value := AttributeValue;
  XMLAttNode.attributes.setNamedItem(NewAttributeNode);
END;


xmlread(ficheiro : Text[250])

ffile.OPEN(ficheiro);
ffile.CREATEINSTREAM(strInStream);

IF ISCLEAR(xmldomDoc) THEN CREATE(xmldomDoc);

xmldomDoc.load(strInStream);

xmldomDoc.getElementsByTagName('CstmrCdtTrfInitn').item(0).attributes.removeNamedItem('xmlns');

xmlNodeList  := xmldomDoc.getElementsByTagName('CstmrCdtTrfInitn/PmtInf/CdtTrfTxInf');

FOR i:=0 TO xmlNodeList.length()-1 DO BEGIN
  xmlNodeList.item(i).attributes.removeNamedItem('ID');
END;

ffile.CLOSE;
xmldomDoc.save(ficheiro);

Comentarios

Entradas populares