Ir para o conteúdo
Icepick.pt

Autoridade Tributária - Utilização de webservice com SSL

Mensagens Recomendadas

Icepick.pt

Como muitos de vós devem saber, entra em vigor a 1 de Maio de 2013 o webservice da Autoridade Tributária para reporte em tempo real dos documentos de transporte emitidos. Estou a tratar da implementação dessa funcionalidade numa plataforma de faturação escrita em PHP e tenho várias dificuldades em que vou precisar de ajuda nos próximos dias, a diversos níveis. A primeira de todas é o estabelecimento da ligação segura com o servidor da AT, em:

https://servicos.portaldasfinancas.gov.pt:400/sgdtws/documentosTransporte

Já recebi da AT:

- uma chave pública, materializada no ficheiro 'chavePublica.cer'

- um certificado materializado no ficheiro 'certificado.pfx'

Também já tenho a extensão openssl activa no meu servidor, que é linux. Teóricamente seria só consultar a documentação sobre a extensão que existe no PHP.net e mais uns quantos tutoriais online, que deveria chegar lá. O problema é que a extensão está muito mal documentada em termos de exemplos práticos, e a carga técnica sobre criptografia é de tal forma grande que quem não está habituado fica completamente perdido.

Então, o que eu preciso:

- que alguém me explique a funcionalidade destes dois ficheiros;

- como é que eu os utilizo em conjunto com a extensão openssl do php para estabelecer a ligação segura, por onde vai ser enviada depois a informação ( esta será uma guerra para depois...)

Partilhar esta mensagem


Ligação para a mensagem
Partilhar noutros sites
Icepick.pt

Já consegui alguns avanços.

Descobri que a ligação é feita com a extensão cURL, e que esta não utiliza o certificado no formato 'pfx'.

Então, primeiro há que converter o certificado para o formato 'pem' recorrendo à linha de comando. O comando é:

$ openssl pkcs12 -in certificadoAntigo.pfx -out novoCertificado.pem

Isto gera um novo certificado no formato 'pem'. Pelo caminho pede para utilizar uma password fornecida com o certificado 'pfx'. Pede também para que estabeleçam uma password para utilização com o certificado 'pem'.

Ultrapassado com sucesso este passo, certifiquem-se que o script de PHP tem permissões de acesso ao novo certificado gerado.

De seguida vem o código.


$url = "https://servicos.portaldasfinancas.gov.pt:400/sgdtws/documentosTransporte%22;
$pemfile = 'novoCertificado.pem';
$keyfile='chavePublica.cer';
$cert_password = 'xxxxxxxxxx';

$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_HTTP_VERSION, 1.1);
curl_setopt($ch, CURLOPT_PORT, 443);

curl_setopt($ch, CURLOPT_VERBOSE, 1);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, FALSE);
curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 0);

curl_setopt($ch, CURLOPT_FAILonerror, 0);

curl_setopt($ch, CURLOPT_SSLCERT, $pemfile);
curl_setopt($ch, CURLOPT_SSLCERTTYPE, 'PEM');
curl_setopt($ch, CURLOPT_SSLCERTPASSWD, $cert_password );


curl_setopt($ch, CURLOPT_SSLKEY, $keyfile);
curl_setopt($ch, CURLOPT_SSLKEYPASSWD, $cert_password);


curl_setopt($ch, CURLOPT_CUSTOMREQUEST, "POST");
curl_setopt($ch, CURLOPT_POST, 1);
curl_setopt($ch, CURLOPT_HTTPHEADER, array('Content-Type: text/xml'));
curl_setopt($ch, CURLOPT_POSTFIELDS, 'qualquer_coisa');

$output = curl_exec($ch);

if(!$output) {echo "Curl Error : " . curl_error($ch);}
else {echo htmlentities($output);}

Quando testo o código, recebo a seguinte mensagem de erro cURL:

unable to set private key file: 'ChavePublica.cer' type PEM

Alguém me explica como corrigir isto?

Partilhar esta mensagem


Ligação para a mensagem
Partilhar noutros sites
pmg

De acordo com um post no Stack Overflow experimenta meter o path completo no $pemfile

// ...
$pemfile = '/home/Icepick/htdocs/secure/novoCertificado.pem';
// ...

Editado por pmg

What have you tried?

Não respondo a dúvidas por PM

A minha bola de cristal está para compor; deve ficar pronta para a semana.

Torna os teus tópicos mais atractivos e legíveis usando a tag CODE para colorir o código!

Partilhar esta mensagem


Ligação para a mensagem
Partilhar noutros sites
Icepick.pt

@pmg, obrigado pela dica.

Experimentei colocar o caminho absoluto para o certificado como indicaste, mas sem sucesso. Depois achei estranho o post do stack overflow, porque o meu script parecia encontrar o certificado mesmo com um caminho relativo. Para testar, adulterei o caminho e tornei-o inválido, e a mensagem mudou imediatamente:

unable to use client certificate (no key found or wrong pass phrase?)

Conclusão: ao contrário do que diz o post do Stack Overflow, a cURL não precisa do caminho absoluto para utilizar o certificado.O meu script encontra-o mesmo com um caminho relativo. O que acontece é que não consegue realizar o passo que se segue: utilizar a chave.

Só por causa das dúvidas, experimentei o caminho absoluto na chave também, mas sem sucesso. Definitivamente, o problema não está na utilização do caminho.

De volta à analise do erro original reparei num pormenor:

unable to set private key file: 'chavePublicaAT.cer' type PEM

A Autoridade Tributária enviou-me uma chave pública com o certificado, mas o script está a contar com a utilização de uma chave privada.

Poderá ser daqui? Qual é lógica de utilização deste conjunto? É que eu não tenho a chave privada, quem a tem é a Autoridade Tributária ...

Partilhar esta mensagem


Ligação para a mensagem
Partilhar noutros sites
eSkiSo

Tens de extrair o TestesWebServices.pfx para .pem (Chave + Certificado) com o OpenSSL

- Extrair a chave privada para PEM ( Password: TESTEwebservice )

Código :

openssl pkcs12 -in TestesWebServices.pfx -nocerts -out pfxKey.pem

-Extrair o certificado

Código :

openssl pkcs12 -in TestesWebServices.pfx -clcerts -nokeys -out pfxcert.pem

$SoapAction = "https://servicos.portaldasfinancas.gov.pt:701/sgdtws/documentosTransporte/";
//$SoapAction = "https://servicos.portaldasfinancas.gov.pt:401/sgdtws/documentosTransporte/";
$Action = "https://servicos.portaldasfinancas.gov.pt:701/sgdtws/documentosTransporte";
//Action = "https://servicos.portaldasfinancas.gov.pt:401/sgdtws/documentosTransporte";
$cert_pem = 'pfxcert.pem'; //Caminho completo para o pfxcert.pem ou so o nome se estiver na mesma pasta
$key_pem  = 'pfxKey.pem'; //Caminho completo para o pfxKey.pem ou so o nome se estiver na mesma pasta

$pass_cert = 'TESTEwebservice';

               $curl = curl_init(trim($Action));  


               curl_setopt($curl, CURLOPT_FRESH_CONNECT, TRUE);
               curl_setopt($curl, CURLOPT_HTTPHEADER,array(
                       'Content-Type:text/xml;Charset=UTF-8',
                       'Accept: text/xml',
                       'Cache-Control: no-cache',
                       'SoapAction='.$SoapAction
               ));
               curl_setopt($curl, CURLOPT_URL, trim($Action));
               curl_setopt($curl, CURLOPT_SSLVERSION, 3);
               curl_setopt($curl, CURLOPT_VERBOSE, TRUE); // para ver o que se passa...
               curl_setopt($curl, CURLOPT_AUTOREFERER, TRUE);
               curl_setopt($curl, CURLOPT_POST, 1);
               curl_setopt($curl, CURLOPT_POSTFIELDS, $xml);
               curl_setopt($curl, CURLOPT_FOLLOWLOCATION, 1);
               curl_setopt($curl, CURLOPT_SSLCERT, $cert_pem); // o certificado em formato PEM (.pem)
               curl_setopt($curl, CURLOPT_SSLCERTTYPE, 'PEM');
               curl_setopt($curl, CURLOPT_SSLCERTPASSWD, $pass_cert);
               curl_setopt($curl, CURLOPT_SSLKEY, $key_pem);
               curl_setopt($curl, CURLOPT_SSLKEYPASSWD, $pass_cert);
               curl_setopt($curl, CURLOPT_SSLKEYTYPE, 'PEM');
               curl_setopt($curl, CURLOPT_RETURNTRANSFER, 1);  

               $response = curl_exec($curl);  
               $info = curl_getinfo($curl);
...

Editado por eSkiSo

Os meus programas em http://www.eskiso.net

Partilhar esta mensagem


Ligação para a mensagem
Partilhar noutros sites
Jorge Lima

Boas, o PDF dos gajos tem um exemplo completo para o Header mas não para o Body. Alguém pode dar um exemplo de um pedido SOAP que efectivamente funcione?

Partilhar esta mensagem


Ligação para a mensagem
Partilhar noutros sites
eSkiSo

Boas,

Primeiro precisas de ter o openssl ( openssl.org ) e gerar o ficheiros .key e .csr

openssl req -new -subj "/C=PT/ST=Distrito da Sede/L=Local da Sede/O=Empresa /OU=Departamento de Informatica/CN=555555555/emailAddress=informatica@empresa.pt" -newkey rsa:2048 -nodes -out 555555555.csr -keyout 555555555.key

Para testar fazes:

openssl req -text -noout -in 555555555.csr

Abres o ficheiro .csr com o bloco de notas e copias o texto que lá esta.

Vais a https://faturas.portaldasfinancas.gov.pt/consultarPedidosAdesao.action

Fazes login e vais aonde diz "Aderir ao envio por webservice" (disponivel na pagina de produtores de software (link em baixo à direita))

Clicar no botão verde que diz "Aderir ao Serviço" -> "Efectuar Novo Pedido" e colar texto copiado do ficheiro .csr para a caixa de texto CSR (Certificate Signing Request)

Fazer check no "Aceito os termos ...."

Clicar em "Aderir".

Depois colocas o ficheiro recevido por email do pessoal da certificacão (.cer) e o ficheiro .key criado anterioremente e fazes os seguintes comandos:

//criar PFX - quando pedir pasword, colocar uma

openssl pkcs12 -export -in #######.cer -inkey #######.key -out #######.pfx

//criar o pfxKey.pm - vai pedir password 3 vezes é sempre a mesma

openssl pkcs12 -in ########.pfx -nocerts -out pfxKey.pem

//criar o pfxcert.pem - quando perdir password é a que colocaste antes

openssl pkcs12 -in ######.pfx -clcerts -nokeys -out pfxcert.pem

Boa sorte =D

Boas eSkiSo o ficheiro "ChavePublicaAT.cer" que utilizaste, foi-te facultado pela AT ou foi criado a partir do .pfx?

Esse ficheiro encontras neste tópico

https://www.portugal-a-programar.pt/topic/57734-utilizar-webservices-da-at/page__st__6020?do=findComment?comment=578028

  • Voto 1

Os meus programas em http://www.eskiso.net

Partilhar esta mensagem


Ligação para a mensagem
Partilhar noutros sites
robotical

Testei o teu codigo com "ChavePublicaAT.cer" que me foi enviado em resposta ao pedido de utilizador de testes obtenho o seguinte erro:

Curl error: Unknown SSL protocol error in connection to servicos.portaldasfinancas.gov.pt:701

apanhaste algo semelhante?

Estou utilizar $username= "599999993/0037"; $password= "testes1234";

Desde ja obrigado pela disponibilidade!

Partilhar esta mensagem


Ligação para a mensagem
Partilhar noutros sites
eSkiSo

Que versão é que tens do PHP, do CURL e do SSL?

Usa este codigo para ver:

<?php
$version = curl_version();
echo "CURL Version: ".$version['version']."<br>";
echo "CURL SSL Version: ". $version['ssl_version']."<br>";
echo "PHP Version: ".phpversion();


Os meus programas em http://www.eskiso.net

Partilhar esta mensagem


Ligação para a mensagem
Partilhar noutros sites
robotical

CURL Version: 7.35.0

CURL SSL Version: OpenSSL/1.0.1f

PHP Version: 5.5.9-1ubuntu4.5

No .conf do apache tiveste que efetuar alguma alteração ou adicionar os certificados?

Partilhar esta mensagem


Ligação para a mensagem
Partilhar noutros sites
robotical

Acho estranho ao testar o mesmo pedido com os link de produçao(401) mas com da datas de 2013, obtenho erro:

Curl error: SSL certificate problem, verify that the CA cert is OK. Details: error:14090086:SSL routines:SSL3_GET_SERVER_CERTIFICATE:certificate verify failed

Partilhar esta mensagem


Ligação para a mensagem
Partilhar noutros sites
robotical

Verifica a data do certificado, pode ter expirado

Endereços de testes não estão a funcionar só com os 401 !!

UM GRANDE OBRIGADO !!!!

Partilhar esta mensagem


Ligação para a mensagem
Partilhar noutros sites
Sant0s

E

Testei o teu codigo com "ChavePublicaAT.cer" que me foi enviado em resposta ao pedido de utilizador de testes obtenho o seguinte erro:

Curl error: Unknown SSL protocol error in connection to servicos.portaldasfinancas.gov.pt:701

apanhaste algo semelhante?

Estou utilizar $username= "599999993/0037"; $password= "testes1234";

Desde ja obrigado pela disponibilidade!

Estou com o mesmo problema o de testes não está a funcionar..

(mesmo depois de já ter gerado o pem e o cert com o novo pfx)

Editado por Sant0s

Partilhar esta mensagem


Ligação para a mensagem
Partilhar noutros sites
blacksnacke

Boas Pessoal,

Já consegui comunicar, no entanto obtenho este erro com php:

Unknown SSL protocol error in connection to servicos.portaldasfinancas.gov.pt:701

Testei o teu codigo com "ChavePublicaAT.cer" que me foi enviado em resposta ao pedido de utilizador de testes obtenho o seguinte erro:

Curl error: Unknown SSL protocol error in connection to servicos.portaldasfinancas.gov.pt:701

apanhaste algo semelhante?

Estou utilizar $username= "599999993/0037"; $password= "testes1234";

Desde ja obrigado pela disponibilidade!

Como resolveu?

Estou com mesmo problema...

Partilhar esta mensagem


Ligação para a mensagem
Partilhar noutros sites
iznougudpt

Eu também continuo coo o erro do

Unknown SSL protocol error in connection to servicos.portaldasfinancas.gov.pt:701

quer em Windows quer em Linux. Alguém que tenha tido este erro já o conseguiu resolver?

Partilhar esta mensagem


Ligação para a mensagem
Partilhar noutros sites
apocsantos

Boa noite,

Tenta usar a versão 7.33.0-3 do curl, pois existe um bug conhecido que causa precisamente esse erro.

Cordiais cumprimentos,

Apocsantos


"A paciência é uma das coisas que se aprendeu na era do 48k" O respeito é como a escrita de código, uma vez perdido, dificilmente se retoma o habito"

assinatura.jpg

Partilhar esta mensagem


Ligação para a mensagem
Partilhar noutros sites
Sant0s

Já alguém conseguiu comunicar para o URL de testes? Em produção tenho tudo bem mas em testes estou com o erro:

Unknown SSL protocol error

 

 

 

Editado por Sant0s

Partilhar esta mensagem


Ligação para a mensagem
Partilhar noutros sites
Nuno Bagulho Marques

Bom dia!

Utilizei o código do @eSkiSo ( e desde já obrigado). Fiz as alterações recomendadas, nomeadamente a alteração do formato do certificado, mas não consigo ligar ao web-servivce

não obtenho nenhuma resposta, depois da instrução

$response = curl_exec($curl);  

resultado vem em branco

Alguma ajuda? Obrigado

Partilhar esta mensagem


Ligação para a mensagem
Partilhar noutros sites
Nuno Bagulho Marques
Em 21/08/2017 às 12:19, Nuno Bagulho Marques disse:

Bom dia!

Utilizei o código do @eSkiSo ( e desde já obrigado). Fiz as alterações recomendadas, nomeadamente a alteração do formato do certificado, mas não consigo ligar ao web-servivce

não obtenho nenhuma resposta, depois da instrução

$response = curl_exec($curl);  

resultado vem em branco

Alguma ajuda? Obrigado

progredi...

agora obtenho Unable to load client key

como passo do ficheiro saPubKey.jks para ChavePublicaAT.cer ... ou não preciso disto para nada?

já tentei extrair com o keytool, mas nada - pede uma password

Partilhar esta mensagem


Ligação para a mensagem
Partilhar noutros sites

Crie uma conta ou ligue-se para comentar

Só membros podem comentar

Criar nova conta

Registe para ter uma conta na nossa comunidade. É fácil!

Registar nova conta

Entra

Já tem conta? Inicie sessão aqui.

Entrar Agora

×

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.