Ir para o conteúdo

Rankings


Conteúdo Popular

A mostrar o conteúdo com mais reputação desde 24-03-2018 em todas as áreas

  1. 4 pontos
    Derrerter, também recebi esse exemplo acompanhado da seguinte comunicação Cá está. É obrigatório mas não foi apresentada nenhuma informação, decreto lei ou portaria, sobre o assunto. Típico.
  2. 4 pontos
    Se alguém usar .NET, o seguinte link poderá ter interesse: https://github.com/UblSharp/UblSharp
  3. 4 pontos
    Eis as informações que conseguir reunir: ASSOFT: https://www.assoft.org/pt/noticias/78/norma-europeia-de-fatura-eletronica http://vexillum.pt/fatura-eletronica/ The eInvoicing Workshop https://www.cen.eu/work/areas/ICT/eBusiness/Pages/eInvoicing.aspx Um site holandês dedicado ao E-Invoicing, onde encontrei documentos e informação técnica valiosa: https://eeiplatform.com/category/standards/ LINKS: (NOTA: estas informações são MAIS DETALHADAS do que a treta do DVD vendido pelo IPQ) http://eur-lex.europa.eu/legal-content/EN/TXT/?uri=COM:2017:590:FIN http://eur-lex.europa.eu/legal-content/EN/ALL/?uri=CELEX%3A32014L0055 https://standards.cen.eu/dyn/www/f?p=204:7:0::::FSP_ORG_ID:1883209&cs=1E81C9C833655EEDC7010C8D0A2FB786C https://github.com/CenPC434 http://docs.oasis-open.org/ubl/os-UBL-2.1/UBL-2.1.html http://docs.oasis-open.org/ubl/os-UBL-2.1/UBL-2.1.zip http://www.unece.org/cefact/xml_schemas/index http://www.unece.org/fileadmin/DAM/cefact/xml_schemas/D16B_SCRDM__Subset__CII.zip https://github.com/phax/peppol-validation-engine/ GLOSSARY Term Description CEN = Comité Européen de Normalisation – European Committee for Standardization CEN/TC = CEN Technical Committee – working group CII = UN/CEFACT Cross Industry Invoice – XML representation of an invoice CIUS = Core Invoice User Specification – A specification based on EN 16931-1:2017 that defines certain elements more narrow EN = European Norm – has tighter binding than TR and TS EN 16931 = European Norm instance with ID 16931 – this is the EN that contains the semantic data model for electronic invoices in Europe TR = Technical Recommendation – has lower binding than EN and TS TS = Technical Specification – binding between EN and TR
  4. 3 pontos
    Afinal nada disto é novo para o fisco!!! Veja-se a implementação do MESMO sistema para a Faturação Electrónica de Medicamentos e Cuidados Farmacêuticos: https://www.ccf.min-saude.pt/portal/page/portal/estrutura/documentacaoPublica/ACSS/ACSS_AF_Facturacao_Electronica_Medicamentos_Main_v20180606.pdf UBL 2.0, com extensões específicas, com assinatura do XML, e envio através de WEBSERVICE!
  5. 3 pontos
    Aparentemente a letra da lei permite essa interpretação. Para a AT isso não deve ter problema nenhum porque a chave primária deles não deve ser o InvoiceNo, mas sim o IdDocumento. Além disso, cada SAFT só pode ter documentos de 1 ano, seja o ano completo ou seja parcial. No meu caso não dá porque a chave primária que uso é "Tipo+Serie+Numero", mas para dar bastaria alterar para "year(data)+Tipo+Serie+Numero". Por outro lado, para o utilizador, não vejo qualquer vantagem nisso, pois só iria dar confusão com os respetivos clientes. Para identificar uma fatura, além de dar o numero e a série também iria ter de dar a data. Quando a AT diz "... por um período não inferior a um ano fiscal …" o que quer dizer é que uma série criada no início do ano deve ser, por regra, utilizada pelo menos até ao fim do ano, em vez de serem, por exemplo, mensais. Por exemplo, na contabilidade é comum criarem-se diários (pastas) em que se separam documentos por tipo do género "vendas", "compras", "bancos", etc. Dentro de cada um desses diários a numeração é também sequencial. O problema é que muitas vezes os documentos chegam muito tarde á mão do contabilista, especialmente faturas e notas de crédito de fornecedores que, não sendo emitidas pela empresa, não se consegue controlar. A forma de dar a volta a isso é reiniciar a numeração todos os meses. Assim, ainda que já estejam lançados documentos de Setembro, podes sempre acrescentar mais um lançamento em Julho de uma fatura que o empresário se esqueceu de entregar. Ou se estiveres a conferir um extrato bancário de Janeiro e verificares que te esqueceste de lançar um documento que até tinhas de ir buscar ao homebanking, nunca terás o problema de falta de numero para inseri-lo no respetivo mês.
  6. 3 pontos
    Dá uma olhada no TIdleTimer, um irmão do TTimer sugerido pelo @thoga31 específico para lidar com inactividade. http://lazarus-ccr.sourceforge.net/docs/lcl/extctrls/tidletimer.html Assim não tens de te preocupar com multi-threading nem verificação dos inicios e fins de processos, pois o componente trata disso por ti.
  7. 3 pontos
    Estou até meio que sem saber o que responder a essa história do professor, pelo que vou deixar para último... 😕 Isso é outra coisa... Ninguém nasce ensinado, e o paradigma OOP é radicalmente diferente do Imperativo. Muitas pessoas (sim, programadores de Java também) não fazem a mais pálida ideia de como se programa realmente em OOP. Acham que programar orientado a objectos é... fazer objectos. É muito mais. Todo o conceito muda, a forma de pensar tem de mudar também, ou apenas terão objectos a fazer o papel de armazéns de código. Recomendo, para entender o conceito OOP, o livro Object Thinking (David West). Não tem nada a ver com Pascal, Java, etc. É um livro para expandir um conceito. Alguns exemplos usados estão em SmallTalk, mas poderiam estar em qualquer outra, visto que são só exemplos para entender o conceito. Já programei muito em Imperativo, e programei muito mais em 'Imperativo com Objectos' - e pensava como os outros que estava a fazer OOP. Actualmente prefiro programar em "OOP a sério", e com anos disto considero que ainda tenho muito para aprender. É uma evolução constante para quem quer realmente aprender, mas dependendo do tipo de software que se quer criar, vale a pena o esforço. As Units do Pascal, que depois chamas na secção Uses, são apenas uma das formas de reutilizar código. Um simples procedimento é uma forma de reutilizar. Um objecto, uma framework - há várias formas de reutilizar código, e podem e devem ser usadas em Pascal (ou qualquer outra LP). Sempre que no teu código usares copy/paste, quase de certeza estás na presença de uma situação onde um qualquer método de reutilização de código se faz necessário. Isso já virou piada entre os programadores de Pascal... Pessoas que nunca tocaram no Pascal a reclamarem dele é motivo para rir. Pessoas que tentam comparar o Standard Pascal - uma LP de 1974 formalizada em 1983, com um conjunto limitado de funcionalidades visto que era uma linguagem pensada para uso académico - com LPs actuais com funcionalidades actuais. Obviamente, nesta comparação, Pascal perde. O que falta a essa malta é aprender a não comparar alhos com bugalhos. Querem comprar com uma LP actual? Então comparem com Delphi actual. E mesmo quando comparam o Pascal 'actual', em vez de compararem linguagens, comparam compiladores - e geralmente acham boa ideia comparar com PascalZIM, que, sem desprimor ao seu criador, é muito fraquinho, tendo apenas uma pequena parte das funcionalidades do Pascal. Bem... Tem de ser, vamos a isto: Se ele disse mesmo isto, podes por favor dizer-lhe que ele é burro que nem uma porta, que não tem competência para ser professor de informática, muito menos de programação, e muito provavelmente não devia ser autorizado nem a operar uma calculadora de bolso... Podes dizer que fui eu que disse! A divisão do código em segmentos menores - sejam métodos, funções, procedimentos, rotinas, units, módulos, ou o que quiseres chamar-lhe - não é 'típico de programadores de Delphi'. É típico de quem sabe programar, seja em que linguagem for. Colocar todo o código no bloco principal? A sério? Até o Basic evoluiu para além disso. Imagina criar um projecto com milhões de linhas de código, todas no bloco principal. Ui, que lindo seria. Se esse é o teu professor, a minha sugestão é fazeres tudo ao contrário do que ele mandar. Aprendes mais a limpar o pó a livros de lógica e algoritmia do que a ser ensinado por quem quer que seja que te diga isso.
  8. 3 pontos
    O Application.ProcessMessages é largamente usado para 'desenrascar' esse problema, mas o seu uso não é sem custos... Este método serve para 'avisar' o programa para processar as mensagens (duh! ) que estão na queue do Windows, independentemente de quais são e do risco associado à execução de mensagens fora de ordem. Antes de mais, uma explicação simplista do que são 'mensagens': O GUI do Windows funciona porque os seus elementos enviam mensagens uns aos outros com indicação do que querem fazer. Por exemplo, quando clicas num botão, é enviada uma mensagem para o componente encarregue de alterar o aspecto visual do botão (que o faz parecer 'pressionado' visualmente) que por sua vez manda uma mensagem à form para se redesenhar para que o novo aspecto seja mostrado, há uma mensagem a dar iniciação do trabalho do botão, etc. Ao fazer ProcessMessages, estás a forçar a main thread do programa a executar tudo o que estiver na fila, e isto tem, de entre outras, as seguintes consequências: Estás a parar temporariamente a execução da tarefa principal, obrigando-a a demorar mais tempo Estás a mandar executar mensagens a meio da tarefa, sem saber quais as mensagens que lá estão nem os problemas que a sua execução forçada pode causar. No caso, a tua ideia faz com que ele pare a leitura dos dados, actualize o UI ao processar as mensagens de actualização que estão pendentes, e volta a ler, e voltar a parar, e por aí fora até completar a leitura. Como à primeira vista, isto funciona, muita gente o faz. O que muitos desconhecem é que, ao fazer isto, podem estar com uma simples linha a introduzir bugs no programa, bugs esses que são de detecção extremamente difícil pois existem pela execução de mensagens fora da ordem correcta. O caso é tal que podes correr um programa e dar tudo bem, voltas a correr sem alterar nada e os bugs manifestam-se, voltas a correr e está tudo bem, voltas a correr e aparecem bugs completamente diferentes dos primeiros. Ou seja, o pesadelo de qualquer programador. Por outro lado, dependendo das mensagens pendentes, o resultado pode nem ser o esperado, e não resolve sequer o problema inicial. Podes agora 'resolver' assim, e noutro programa em que te depares com um problema semelhante, resolves usar o mesmo, mas nesse outro programa não funcionar, por um qualquer motivo. Isto retira-te a previsibilidade das soluções, o que te obrigará a perder tempo à procura da solução de cada vez que te surgir o problema. E se o utilizador for dado a clicar à toa enquanto espera, como há tantos por aí, o resultado é muitas vezes o crash do programa, porque independentemente de lhe mandarmos processar as mensagens, a thread continua a ser só uma, e nem sempre com capacidade de fazer tudo o que lhe pedem. Nota: Não estou com isto a dizer que nunca se deve usar o ProcessMessages, ou que no teu caso não resolva o problema sem introduzir outros. Tudo depende do código circundante ao ProcessMessages. E mesmo quando os bugs aparecem, podem ser coisas tão banais quanto uma barra de progresso que anda para a frente e depois volta atrás, para depois voltar pra frente, não afectando nada de especial senão o aspecto visual. Mas há casos bem mais graves, o que me leva a recomendar que quem não saiba exactamente o que está a acontecer, ignore o 'remendo' que é o ProcessMessages, em favor de uma solução mais previsível, como o uso de multi-threading. Nota 2: Multi-threading não é, no entanto, um mar de rosas. É preciso perder algum tempo para sequer começar a ter ideia do ninho de ratos que aquilo é. No entanto, a partir do momento que saibas usar e implementares com as devidas protecções, é mais previsível e consistente do que correr mensagens desconhecidas a meio de uma tarefa.
  9. 3 pontos
    Realmente, o Portal da AT está tão modificado que não se consegue encontrar nada à primeira. Aqui vai o link: https://www.acesso.gov.pt/gestaoDeUtilizadores/consulta?partID=PFAP
  10. 3 pontos
    isso é o operador ternário. imagina um if, mas que "retorna" um valor. olha para a estrutura do operador ternário: <expr1> ? <expr2> : <expr3> agora é necessário como a linguagem processa essa expressão (toda a combinação acima descrita): - caso o valor de expr1 for verdadeiro, então o resultado do operador ternário é o resultado da expr2, caso contrário, será expr3.
  11. 2 pontos
    Ah! E esqueci-me de referir o mais importante que vinha no e-mail, a cereja em cima do bolo,
  12. 2 pontos
    Boas, Aqui está um exemplo enviado pela Infraestruturas de Portugal, para os seus fornecedores. https://www.dropbox.com/s/mnoayplcdr10tmc/exemplo_ubl2.1.xml?dl=0
  13. 2 pontos
    MarcoLopes, essas referencias que apresentas são situações especificas aplicadas exclusivamente ao sector da saúde. Sim, o CCF que é o centro de conferência de facturas passou a receber a relação de facturas de cuidados de saude prestados por empresas privadas ao SNS através de ficheiros XML com uma estrutura "básica" do standard UBL. A prescrição de receitas electrónicas também já é uma realidade no SNS e a utilização de webservices nos cuidados respiratórios, por exemplo, é uma realidade. Mas isso aplica-se apenas ao sector da saúde. E a instituição que "lida" com estes sistemas é o SPMS (Serviços partilhados do Ministério da Saúde). Eu sei porque já desenvolvi alguns sistemas específicos de ligação aos sistemas deles. Mas no caso da factura electrónica obrigatória por norma europeia penso que não terá nada a ver com o caso da saúde. Eventualmente o standard a adoptar será o mesmo (UBL) mas nem isso é garantido. Acho que vamos ter que aguardar por publicação de legislação. E pelo "andar da carruagem" tenho sérias duvidas que seja aplicado já a partir de Janeiro/2019. PS: Se for igual ao do CCF posso adiantar já que é bastante complexo envolvendo inclusive, além da assinatura digital do XML, conversões para Base64String e comunicação com webservices com autenticação através de tokens. Parece o "Fort Knox" americano :D...
  14. 2 pontos
    Parece que começa a haver mais alguma informação. Segundo a itinsight vamos adoptar o formato UBL 2.1 https://www.itinsight.pt/news/inovacao/ministerio-das-financas-adota-formato-ubl-21-para-contratos-publicos Agora é esperar pela publicação oficial e ir preparando o jarro do café ...
  15. 2 pontos
    @Tonecas, só quero terminar sugerindo que estudes melhor a sintaxe das estruturas essenciais do Pascal. Se quiseres material adicional, tens este Tutorial. Cumprimentos.
  16. 2 pontos
    Boas! É melhor alterarem o NOME do TÓPICO para Factura Electrónica na Administração Pública (porque é um modelo completamente à parte!) A ASSOFT disponibilizou um suporte com os ficheiros técnicos fornecidos que estão na posse do IPQ. Eis o email enviado aos associados: Sobre o conteúdo técnico da informação VENDIDA!!!! pelo IPQ, posso dizer que, não serve de grande coisa!!!! É um TOTAL E COMPETO ENGODO. Nem sequer os formatos técnicos são disponibilizados em XSD e/ou WSDL. Estive a saltar de site em site, e existem países que fornecem informações muito detalhadas sobre o processo de adopção, documentação TÉCNICA RELEVANTE, etc, mas sobre PORTUGAL, não faço ideia como está a ser implementado o serviço! É inqualificável esta falta de clareza e informação sobre um assunto tão importante!
  17. 2 pontos
    O despacho 8632/2014 é claro: Ou seja, uma série para todos os tipos de documentos. Só em casos justificados, nomeadamente por necessidades comerciais, poderá utilizar mais que uma série. Por exemplo, se tiver vários estabelecimentos, pontos de faturação, houver quebra no funcionamento (teve de suspender a série em utilização e iniciar uma nova), etc.
  18. 2 pontos
    Bom dia Fabio, posso tentar ajudar nas tuas duvidas, mas convém consultares a documentação oficial da AT: http://info.portaldasfinancas.gov.pt/pt/apoio_contribuinte/Pages/certificacao-de-software.aspx http://info.portaldasfinancas.gov.pt/pt/apoio_contribuinte/SAFT_PT/Paginas/news-saf-t-pt.aspx 1. a) A melhor forma de teres a certeza do formato é analisares o ficheiro de validação do SAF-T para o campo DocumentNumber. Mas basicamente a série é uma forma de identificar unicamente a numeração. Por exemplo podes ter a série por posto e juntas o ano, ficando P12018 (ex: FR P12018/1). Não podes ter o caracter de espaço na série. b) O código hash é gerado com a chave privada, usando alguns campos do documento (dataemissão;datahorasistema;numero;total;hashdocanterior). No caso do primeiro documento, como não tens documento anterior, omites esse conteúdo. Essa parte de extrair 4 caracteres do hash será apenas na impressão do documento para entregar ao cliente. c) Não entendi a duvida mas os documentos fechados e assinados não podem ser alterados. d) Todos os documentos que possam ser entregues a clientes têm de ser assinados (faturas, contas, etc). O prazo de envio do SAF-T é atualmente até ao dia 20 do mês seguinte. e) Para cancelamento de algum produto, deve ser feita uma nota de crédito. A anulação julgo que só em casos extremos (por exemplo, engano no NIF) 2. Esse erro indica que estás a exportar um produto (com o código MO) na parte dos documentos, que não referenciaste no inicio do SAF-T, na parte dos produtos 3. Não tenho conhecimento se existe alguma API que facilite, mas tenta ver o tópico SAFT-PT: debate de dúvidas e ideias no forum, tem lá bastante informação que ajudou-me na altura que fiz. Espero que ajude, nelsonr
  19. 2 pontos
    Eish, ainda levam os dois com a bengala... É 2018, não 1956! Poupem nos comandos, p.f. readln(linha); if UpCase(linha) = 'SIM' then begin // doçura de código end;
  20. 2 pontos
    @passarito, estamos em 2018, não em 1978 😂 A função upcase pode ser usada com caracteres e strings. readln(linha); linha := UpCase(linha); if linha = 'SIM' then begin // doçura de código end;
  21. 2 pontos
    Olá xambas. O que quero dizer é que fiz o POST do XML diretamente para o Endpoint. Uma coisa importante com o servidor de testes é que, da minha experiência, só funciona com o user de testes (por favor confirma). 'at_username' => '599999993/37', 'at_password' => 'testes1234' Peguei no teu XML, fiz algumas alterações e consegui que o teu XML passasse. Aqui estão as diferenças entre ambos: https://www.diffchecker.com/tmTqCSnF (antigo do lado direito e novo do lado esquerdo). Repara que, apesar de tu veres um erro genérico (Internal Server Error) quer dizer que no fundo há um erro mais detalhado que não consegues ver. Possivelmente esse erro é aquele que indiquei da estrutura do XML. Sugiro também que o programa que gera o XML retire espaços em branco e newlines do XML http://www.webtoolkitonline.com/xml-minifier.html <?xml version="1.0" encoding="UTF-8"?><S:Envelope xmlns:S="http://schemas.xmlsoap.org/soap/envelope/" xmlns:doc="https://servicos.portaldasfinancas.gov.pt/sgdtws/documentosTransporte/"><S:Header><wss:Security xmlns:wss="http://schemas.xmlsoap.org/ws/2002/12/secext"><wss:UsernameToken><wss:Username>xxxxxxxxx/1</wss:Username><wss:Password>N4rXr+dB2ukThO75sSUblA==</wss:Password><wss:Nonce>IOcKjb7C5YI9vCtHQQ/eh4gOLnwMpYIloKoQx3qRNfmuy5CKorxKg4Sgy7BKNzS8IbtRlXjlMNY8rywYVoNbji4tsRy+6FsTM6tOP5P/f39xPUXG23B2xqHFX7LQ9ZLb1WBsdwA7G3EPl49gQCVQF5QWIzbu9TrkVraVR5ACWJx2h6YlXlOT/IO7KpN+z6htRhvWR2VrXwd7Vuku+eOxQSPfq/V+hLszWLwcJJnNQjuVsGDFV0Q/PPW9roN+6yIGaeATQbc07OtZdYLENz0gGDW7isdmttpFWhZ9t85Bsge8JDmWyl/XI9AV9ZULL1EZ+euWRfYmvboSGcLTvlUoeQ==</wss:Nonce><wss:Created>UL4jE55BGauN4C0eDKgA6a0Iq9gB8UE1VAvk0nXpKdM=</wss:Created></wss:UsernameToken></wss:Security></S:Header><S:Body><doc:envioDocumentoTransporteRequestElem><TaxRegistrationNumber>123456789</TaxRegistrationNumber><CompanyName>SHM Eng.</CompanyName><CompanyAddress><Addressdetail>Rua Tal, Sitio Tal</Addressdetail><City>São Jorge da Murronhanha</City><PostalCode>4444-555</PostalCode><Country>PT</Country></CompanyAddress><DocumentNumber>GT SERIE0/99990</DocumentNumber><MovementStatus>N</MovementStatus><MovementDate>2017-03-01</MovementDate><MovementType>GT</MovementType><CustomerTaxID>599999993</CustomerTaxID><CustomerAddress><Addressdetail>RUA JOSÉ PEREIRA DO NASCIMENTO, Nº 51 LUANDA</Addressdetail><City>LUANDA</City><PostalCode>4444-555</PostalCode><Country/></CustomerAddress><CustomerName>CASAIS ANGOLA, ENGENHARIA E CONSTRUÇÃO SA</CustomerName><AddressTo><Addressdetail>Endereço1 Endereço2</Addressdetail><City>Localidade</City><PostalCode>4444-555</PostalCode><Country>PT</Country></AddressTo><AddressFrom><Addressdetail>Rua Tal, Sitio Tal</Addressdetail><City>São Jorge da Murronhanha</City><PostalCode>4444-555</PostalCode><Country>PT</Country></AddressFrom><MovementEndTime>2018-06-13T17:38:00</MovementEndTime><MovementStartTime>2018-06-13T13:38:00</MovementStartTime><VehicleID>LD-50-36-EW</VehicleID><Line><ProductDescription>C35/45 S4 D20</ProductDescription><Quantity>7</Quantity><UnitOfMeasure>M3</UnitOfMeasure><UnitPrice>0</UnitPrice></Line></doc:envioDocumentoTransporteRequestElem></S:Body></S:Envelope> Experimenta efetuar as alterações no teu programa que gera o XML para ficar de acordo com aquilo que eu também alterei. Se quiseres experimentar algo que funcione coloquei numas páginas atrás código PHP para as guias de transporte.
  22. 2 pontos
    não és obrigado, no entanto torna tudo mais simples.... o teu problema actual é que estás a executar o código de processamento do envio do formulário quando ainda estás a apresentar-lo
  23. 2 pontos
    Não que tenha grande interesse para a discussão em causa, mas mais para conhecimento, através da base de dados do IMT (consulta pela matrícula da viatura) consegues ver o nome e morada do proprietário, NIF, tipo e número do documento de identificação. Caso queiras saber o nome de uma pessoa pelo NIF vais ao portal das finanças e vais a Consultar/ Identificação de clientes/fornecedores e consegues ver o nome, o serviço de finanças e os dados relativos à actividade.
  24. 2 pontos
    That error is usually returned when your clock time is not in sync with theirs. To ensure this, you should always sync yours with Observatório Astronómico de Lisboa, using their ntp servers. Another possible cause, might be that their servers are on heavy loading, taking to long to parse your request, resulting also in a clock time difference between the time you issue the request and the time it is processed.
  25. 2 pontos
    Olá a todos! Estamos a tentar usar os Webservices referentes ao STADA Exportação. Finalmente hoje enviaram-nos um certificado para o sistema de testes sem o WSDL (apesar de já o ter pedido) e foi assim que cheguei a este fórum através do nome do ficheiro do certificado. Alguém tem experiência com o STADA Exportação ou consegue arranjar o WSDL? Para adiantar a parte da autenticação estou a tentar enviar umas faturas para o ambiente de testes e estou sempre a obter o famoso <?xml version='1.0' ?> <env:Envelope xmlns:env='http://schemas.xmlsoap.org/soap/envelope/'> <env:Body> <env:Fault> <faultcode>env:Client</faultcode> <faultstring>Internal Error</faultstring> </env:Fault> </env:Body> </env:Envelope> Hoje estive na luta e consegui finalmente enviar alguma coisa para o servidor de testes. Basicamente a luz acendeu quando passei o parâmetro encoding com UTF-8 nas opções de encoding do SoapClient e devolveu um erro diferente de Internal Error. A partir daí foi dar marteladas atrás de marteladas, ler coisas neste tópico, tratar da autenticação e embrulhar Para quem esteja a chegar agora e trabalhe com PHP fica aqui o código com o SoapClient e phpseclib (não usa mcrypt que foi descontinuado nas versões mais recentes e é considerado inseguro). Este exemplo é para as guias de transporte. Eu vou estar a trabalhar com outros webservices que não estão no site das finanças referentes ao STADA Exportação portanto espero que a autenticação seja igual!! Neste caso estou a usar composer para instalar a dependência do phpseclib portanto terão de adaptar ao vosso código! 1. Obter os certificados do Portal das Finanças. 2. Pegar no ficheiro TesteWebservices.pfx, converter para o formato PEM e copiar o resultado para uma pasta acessível pelo vosso script (no meu caso a pasta certs). A password é TESTEwebservice. O comando irá retirar a password do ficheiro portanto não será necessária no código. openssl pkcs12 -in TesteWebservices.pfx -out TesteWebservices.pem -nodes 3. Copiar o ficheiro da chave pública da AT que está no link indicado no número 1 para a pasta do vosso script. 4. Personalizar o código em baixo com as vossas credenciais, caminhos e endpoints no array $options. <?php require 'vendor/autoload.php'; use phpseclib\Crypt\AES; use phpseclib\Crypt\Random; use phpseclib\Crypt\RSA; use phpseclib\File\X509; $transport = new stdClass(); $transport->TaxRegistrationNumber = '599999993'; $transport->CompanyName = 'Nome Empresa Lda'; $transport->CompanyAddress = new stdClass(); $transport->CompanyAddress->Addressdetail = 'Rua da Empresa, 123'; $transport->CompanyAddress->City = 'Maia'; $transport->CompanyAddress->PostalCode = '4470-263'; $transport->CompanyAddress->Country = 'PT'; $transport->DocumentNumber = bin2hex(openssl_random_pseudo_bytes(8)); $transport->MovementStatus = 'N'; $transport->MovementDate = date('Y-m-d'); $transport->MovementType = 'GT'; $transport->CustomerName = 'Nome Cliente Lda'; $transport->CustomerTaxID = 599999993; $transport->CustomerAddress = new stdClass(); $transport->CustomerAddress->Addressdetail = 'Local'; $transport->CustomerAddress->City = 'Lisboa'; $transport->CustomerAddress->PostalCode = '2775-089'; $transport->CustomerAddress->Country = 'PT'; $transport->AddressFrom = new stdClass(); $transport->AddressFrom->Addressdetail = 'Local carga'; $transport->AddressFrom->City = 'Maia'; $transport->AddressFrom->PostalCode = '4470-263'; $transport->AddressFrom->Country = 'PT'; $transport->AddressTo = new stdClass(); $transport->AddressTo->Addressdetail = 'Local entrega'; $transport->AddressTo->City = 'Lisboa'; $transport->AddressTo->PostalCode = '2775-089'; $transport->AddressTo->Country = 'PT'; $transport->VehicleID = '00-00-KK'; $transport->MovementStartTime = date('Y-m-d\TH:i:s', mktime(date('H') + 1, date('i'), 0, date('m'), date('d'), date('Y'))); $transport->MovementEndTime = date('Y-m-d\TH:i:s', mktime(date('H') + 5, date('i'), 0, date('m'), date('d'), date('Y'))); $transport->Line = []; $transport->Line[] = (function () { $line = new stdClass(); $line->ProductDescription = 'prod1'; $line->Quantity = 1; $line->UnitOfMeasure = 'Kg'; $line->UnitPrice = 11; return $line; })(); $transport->Line[] = (function () { $line = new stdClass(); $line->ProductDescription = 'prod2'; $line->Quantity = 1; $line->UnitOfMeasure = 'Kg'; $line->UnitPrice = 12; return $line; })(); $wsdl = 'wsdl/documentosTransporte.wsdl'; $options = [ 'local_cert' => 'certs/TesteWebservices.pem', 'encoding' => 'utf-8', 'soap_version' => SOAP_1_2, 'at_username' => '599999993/37', 'at_password' => 'testes1234', 'at_public_key' => 'certs/ChavePublicaAT.cer', 'location' => 'https://servicos.portaldasfinancas.gov.pt:701/sgdtws/documentosTransporte', 'uri' => 'https://servicos.portaldasfinancas.gov.pt:701/sgdtws/documentosTransporte', ]; $client = new SoapClientAT($wsdl, $options); var_dump($client->envioDocumentoTransporte($transport)); /** * Class SoapClientAT */ class SoapClientAT extends SoapClient { /** * @var array|null */ private $options = null; /** * SoapClientAT constructor. * @param string $wsdl * @param array $options */ public function __construct($wsdl, $options) { $this->options = $options; parent::__construct($wsdl, $options); } /** * @param DOMDocument $document * @return DOMElement */ private function createHeaderNode($document) { $publicKey = $this->options['at_public_key']; if (is_file($publicKey)) { $publicKey = file_get_contents($publicKey); } $key = Random::string(16); $certificate = new X509(); $certificate->loadX509($publicKey); $rsa = new RSA(); $rsa->loadKey($certificate->getPublicKey()); $rsa->setEncryptionMode(RSA::ENCRYPTION_PKCS1); $nonce = $rsa->encrypt($key); $cipher = new AES(AES::MODE_ECB); $cipher->setKey($key); $password = $cipher->encrypt($this->options['at_password']); $created = $cipher->encrypt(gmdate('Y-m-d\TH:i:s\Z')); $usernameToken = $document->createElement('wss:UsernameToken'); $usernameTokenData = [ 'wss:Username' => $this->options['at_username'], 'wss:Password' => base64_encode($password), 'wss:Nonce' => base64_encode($nonce), 'wss:Created' => base64_encode($created), ]; foreach ($usernameTokenData as $tag => $value) { $usernameToken->appendChild($document->createElement($tag, $value)); } $security = $document->createElement('wss:Security'); $security->appendChild($usernameToken); $security->setAttributeNS('http://www.w3.org/2000/xmlns/', 'xmlns:wss', 'http://schemas.xmlsoap.org/ws/2002/12/secext' ); $header = $document->createElement('env:Header'); $header->appendChild($security); return $header; } /** * @param $request * @return string */ private function embedHeader($request) { $document = new DOMDocument(); $document->preserveWhiteSpace = true; $document->loadXML($request); $body = $document->getElementsByTagName('Body')->item(0); $header = $this->createHeaderNode($document); $envelope = $document->getElementsByTagName('Envelope'); $envelope->item(0)->insertBefore($header, $body); // Must change the namespace of the Envelope tag to match the one specified in the WSDL otherwise we'll get // an HTTP 500 Error with the text "Internal Error" $envelope->item(0)->setAttributeNS( 'http://www.w3.org/2000/xmlns/', 'xmlns:env', 'http://schemas.xmlsoap.org/soap/envelope/' ); return $document->saveXML(); } /** * @param string $request * @param string $location * @param string $action * @param int $version * @param int $one_way * * @return string */ public function __doRequest($request, $location, $action, $version, $one_way = 0) { $request = $this->embedHeader($request); return parent::__doRequest($request, $location, $action, $version, $one_way); } } Cumprimentos, Ricardo
×

Aviso Sobre Cookies

Ao usar este site você aceita os nossos Termos de Uso e Política de Privacidade. Este site usa cookies para disponibilizar funcionalidades personalizadas. Para mais informações visite esta página.