Retorno Automático PagSeguro em PHP/MySQL funcionando

outubro 14th, 2009 por Diogo Dourado (XiS) Leave a reply »

Que o PagSeguro é realmente um dos melhores meios de pagamento da web, isso ninguem dúvida. Mas como integra-lo ao seu sistema de e-commerce? O site de ajuda do PagSeguro tenta ser claro e explicativo, mas o fato é, o script disponível no site simplismente não funciona.

Vamos aos erros…

No script PHP do PagSeguro eles usam uma função que se chama, tep_not_null() que não é uma função nativa do PHP, ou seja, o seu script não irá funcionar. Esta função pode ser encontrada no OsCommerce (que não recomendo) ou em outros scripts pela internet. Bola fora, porque este exemplo dado por eles serve justamente para implantar em outros sistemas, ja que os modulos para esses scripts prontos estão disponíveis no proprio site.

Erro apresentado: Fatal error: Call to undefined function tep_not_null() in /teste/pagseguro.php on line 53

… existem outras melhorias que podem ser feitas no script PHP oferecido pelo PagSeguro, não irei comentar, irei implementar mais abaixo, ok?

No script de criação de tabelas MySQL do PagSeguro existe alguns erros básicos e curiosidades tambem. O primeiro é o seguinte, para que existe a tabela PagSeguroTransacoesProdutos sendo que em nenhum dos scripts de linguagem oferecidos por ele existe a inclusão de dados nesta tabela? Com certeza fail. Na outra tabela PagSeguroTransacoes, esta sim é utilizada, mesmo assim com erros gritantes. Como por exemplo, o campo TransacaoID como chave primaria. Porque erro? Porque o PagSeguro faz um post cada vez que é atualizado a transação, desta maneira que esta apenas a primeira inclusão será feita no MySQL, as confirmações de pagamento, cancelamento ou outro status diferente da transação que será postado posteriormente serão ignoradas pelo MySQL pois so pode existir um registro com cada chave primária. Trocando em miudos, você não sabe quem pagou ou não, pois a transanção não será atualizada.

Erro apresentado: #1062 – Duplicate entry ‘TransacaoID’ for key 1

Ta bom ou quer mais? Mais? tem muita coisa, como falta de um campo data para saber quando aconteceu a confirmação, um campo de flag para saber o que você ja atualizou no sistema ou não, etc. Essas implementações eu irei fazer a seguir.

Coloquei o dedo na ferida, e agora? E agora vamos a…

Implementação

Tentei comentar o código de forma simples e sucinta, então qualquer explicação seria chuver no molhado, vamos lá.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
<?
##############################################################
#                         CONFIGURAÇÕES
##############################################################

$retorno_site = 'http://www.exemplo.com.br/compra_efedutada.html';  // Site para onde o usuário vai ser redirecionado
$retorno_token = '000000000000000000000000000'; // Token gerado pelo PagSeguro

$retorno_host = 'localhost'; // Local da base de dados MySql
$retorno_database = 'basededados'; // Nome da base de dados MySql
$retorno_usuario = 'usuario'; // Usuario com acesso a base de dados MySql
$retorno_senha = 'senha';  // Senha de acesso a base de dados MySql


###############################################################
#              NÃO ALTERE DESTA LINHA PARA BAIXO
################################################################

$lnk = mysql_connect($retorno_host, $retorno_usuario, $retorno_senha) or die ('Nao foi possível conectar ao MySql: ' . mysql_error());
mysql_select_db($retorno_database, $lnk) or die ('Nao foi possível ao banco de dados selecionado no MySql: ' . mysql_error());

// Validando dados no PagSeguro

$PagSeguro = 'Comando=validar';
$PagSeguro .= '&Token=' . $retorno_token;
$Cabecalho = "Retorno PagSeguro";

foreach ($_POST as $key => $value)
{
 $value = urlencode(stripslashes($value));
 $PagSeguro .= "&$key=$value";
}

if (function_exists('curl_exec'))
{
 $curl = true;
}
elseif ( (PHP_VERSION >= 4.3) && ($fp = @fsockopen ('ssl://pagseguro.uol.com.br', 443, $errno, $errstr, 30)) )
{
 $fsocket = true;
}
elseif ($fp = @fsockopen('pagseguro.uol.com.br', 80, $errno, $errstr, 30))
{
 $fsocket = true;
}

if ($curl == true)
{
 $ch = curl_init();

 curl_setopt($ch, CURLOPT_URL, 'https://pagseguro.uol.com.br/Security/NPI/Default.aspx');
 curl_setopt($ch, CURLOPT_POST, true);
 curl_setopt($ch, CURLOPT_POSTFIELDS, $PagSeguro);
 curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
 curl_setopt($ch, CURLOPT_HEADER, false);
 curl_setopt($ch, CURLOPT_TIMEOUT, 30);
 curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);

  curl_setopt($ch, CURLOPT_URL, 'https://pagseguro.uol.com.br/Security/NPI/Default.aspx');
  $resp = curl_exec($ch);

 curl_close($ch);
 $confirma = (strcmp ($resp, "VERIFICADO") == 0);
}
elseif ($fsocket == true)
{
 $Cabecalho  = "POST /Security/NPI/Default.aspx HTTP/1.0\r\n";
 $Cabecalho .= "Content-Type: application/x-www-form-urlencoded\r\n";
 $Cabecalho .= "Content-Length: " . strlen($PagSeguro) . "\r\n\r\n";

 if ($fp || $errno>0)
 {
    fputs ($fp, $Cabecalho . $PagSeguro);
    $confirma = false;
    $resp = '';
    while (!feof($fp))
    {
       $res = @fgets ($fp, 1024);
       $resp .= $res;
       if (strcmp ($res, "VERIFICADO") == 0)
       {
          $confirma=true;
          break;
       }
    }
    fclose ($fp);
 }
 else
 {
    echo "$errstr ($errno)<br />\n";
 }
}


if ($confirma) {

 // Recebendo Dados
 $TransacaoID = $_POST['TransacaoID'];
 $VendedorEmail  = $_POST['VendedorEmail'];
 $Referencia = $_POST['Referencia'];
 $TipoFrete = $_POST['TipoFrete'];
 $ValorFrete = $_POST['ValorFrete'];
 $Extras = $_POST['Extras'];
 $Anotacao = $_POST['Anotacao'];
 $TipoPagamento = $_POST['TipoPagamento'];
 $StatusTransacao = $_POST['StatusTransacao'];
 $CliNome = $_POST['CliNome'];
 $CliEmail = $_POST['CliEmail'];
 $CliEndereco = $_POST['CliEndereco'];
 $CliNumero = $_POST['CliNumero'];
 $CliComplemento = $_POST['CliComplemento'];
 $CliBairro = $_POST['CliBairro'];
 $CliCidade = $_POST['CliCidade'];
 $CliEstado = $_POST['CliEstado'];
 $CliCEP = $_POST['CliCEP'];
 $CliTelefone = $_POST['CliTelefone'];
 $NumItens = $_POST['NumItens'];
 
 // Gravando Dados
mysql_query("INSERT into PagSeguroTransacoes SET
    TransacaoID='$TransacaoID',
    VendedorEmail='$VendedorEmail',
    Referencia='$Referencia',  
    TipoFrete='$TipoFrete',
    ValorFrete='$ValorFrete',  
    Extras='$Extras',  
    Anotacao='$Anotacao',  
    TipoPagamento='$TipoPagamento',
    StatusTransacao='$StatusTransacao',
    CliNome='$CliNome',
    CliEmail='$CliEmail',  
    CliEndereco='$CliEndereco',
    CliNumero='$CliNumero',
    CliComplemento='$CliComplemento',  
    CliBairro='$CliBairro',
    CliCidade='$CliCidade',
    CliEstado='$CliEstado',
    CliCEP='$CliCEP',  
    CliTelefone='$CliTelefone',
    NumItens='$NumItens',  
    Data=now();"
);

}

Header("Location: $retorno_site"); exit();
?>

Basicamente, ele se conecta no MySQL, depois checa através do CURL se foi realmente o PagSeguro que enviou a postagem, recebe os dados via post e grava os dados na tabela.

… mas que tabela? Ahh sim… vamos a criação da tabela do MySQL.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
CREATE TABLE `PagSeguroTransacoes` (
  `TransacaoID` varchar(36) NOT NULL,
  `VendedorEmail` varchar(200) NOT NULL,
  `Referencia` varchar(200) default NULL,
  `TipoFrete` char(2) default NULL,
  `ValorFrete` decimal(10,2) default NULL,
  `Extras` decimal(10,2) default NULL,
  `Anotacao` text,
  `TipoPagamento` varchar(50) NOT NULL,
  `StatusTransacao` varchar(50) NOT NULL,
  `CliNome` varchar(200) NOT NULL,
  `CliEmail` varchar(200) NOT NULL,
  `CliEndereco` varchar(200) NOT NULL,
  `CliNumero` varchar(10) default NULL,
  `CliComplemento` varchar(100) default NULL,
  `CliBairro` varchar(100) NOT NULL,
  `CliCidade` varchar(100) NOT NULL,
  `CliEstado` char(2) NOT NULL,
  `CliCEP` varchar(9) NOT NULL,
  `CliTelefone` varchar(14) default NULL,
  `NumItens` int(11) NOT NULL,
  `Data` datetime NOT NULL,
  `status` tinyint(1) unsigned NOT NULL default '0',
  UNIQUE KEY `TransacaoID` (`TransacaoID`,`StatusTransacao`),
  KEY `Referencia` (`Referencia`),
  KEY `status` (`status`)
) ENGINE=MyISAM DEFAULT CHARSET=latin1;

Na tabela acima todos os campos são basicamente os dados recebidos do PagSeguro. Existem mais campos adicionais que vem em POST tambem que não quis colocar, se você tiver conhecimento basta ler o manual do PagSeguro e adicionar os campos.

Os indices que coloquei foram 3. O primeiro de tipo UNIQUE em TransacaoID e StatusTransacao para evitar que um registro seja enviado mais de uma vez, isso pode ocorrer em servidores com conexão lenta, é melhor remediar, pois estamos falando de transações financeiras. Os outros dois são indices de chave (KEY) apenas, para indexar e deixar sua busca pelos registros mais rapidas. O primeiro é na Referencia, campo que você envia ao PagSeguro na hora da compra para vincular o pagamento a ele, seria nossa chave. O segundo é um campo criado por mim, status que nada mais é que uma flag que uso no meu sistema, para saber quando ja usei aquele registro ou não, por padrão, todos os registros inseridos tem status zero.

Legal ter o código aberto no blog, mas eu gosto de facilidade quando busco em outros blogs, por isso a partir de hoje, qualquer código estará disponivel tambem para download.

download Faça download do código aqui.

… bem, acho que depois de um longo tempo sem atualizar o blog devido a uma cirurgia de redução de estomago (vou falar sobre isso depois), é uma postagem importante e relevante para os desenvolvedores da área. Espero que tenham gostado.

Have Fun!

Advertisement

26 comments

  1. Tárcio Zemel disse:

    Excelente, mesmo! :-D

    Envia para o pessoal do PagSeguro isso. De repente eles arrumam para melhorar a qualidade do serviço deles.

    Sabia que existe um plugin do PagSeguro, ne? Então. Durante o trabalho “descobri” que é possível alterar os valores que colocamos para o produto pelo Firebug e o valor escolhido realmente passa para o sistema deles. Se alguém o estiver usando numa loja de informática, por exemplo, eu consigo pegar um boleto de um PC por R$1,00…

    Entramos em contato por TEL com a empresa que desenvolveu o plugin alertando isso. Já deve ter uns 15 dias que a atendente disse que retornaria e nada…

  2. Bruno disse:

    Olá Diogo!

    Gostei muito do seu post, mas poderia me tirar uma dúvida? Estou iniciando um site de acesso restrito e gostaria de enviar um e-mail com o link de acesso para o cliente assim que o pagamento for liberado pelo pagseguro. Sabe me dizer como faço isso?

    Obrigado e boa sorte na sua recuperação!

    Bruno Lima.

  3. Irineu Jr disse:

    Opa.. Parabens… eu ia fazer o mesmo… limpar o código do pagseguro.. mas pelo jeito vc ja fez isso.
    Obrigado

  4. Francisco disse:

    Rapaz…

    Tirei o dia hoje para ler tudo a respeito do pagseguro, pois pretendo coloca-lo em meu site, este seu tutorial está bacana d+, parabens.

    Estou adicionado ao meu favorito para depois ler cuidadosamente e verificar se consigo implantar esta rotina descrita por você no meu site, haja visto que não sou programador, e por ter sido “enrolado” uma centena de vezes, estou tentando fazer algumas coisas sozinho.

    Espero conseguir sem ter que contratar um programador para faze-lo.

    fraternal abraço e mlehoras pós cirurgia.

  5. Jose Antonio disse:

    Ola diogo, tudo bem? muito bom seu artigo, funcionou certinho. Estou tentando implementar pra na hora em que receber o post do pagseguro, verificar se o status esta aprovado ou não, caso esteja aprovado enviar automaticamente um email ao cliente, mas não estou conseguindo, tem como me ajudar?

  6. Duranti disse:

    Cara, muito bom esse tutorial!
    Ajudou muito mesmo!
    Mas não está dando erro quando vc tem mais que um tipo de produto no carrinho? Ele está retornando apenas o primeiro da lista!
    Valew!

  7. paulo Antunes disse:

    Oi
    Primeiro muito obrigado por tudo
    Funciona tudo excelente.
    Mas se eu precisar do nome do curso, no pagseguro a variável é ProdID_x ProdDescricao_x , adicionei na tabela da base de dados e no código php para inserir e não funcionou….podias me dizer o que se pode passar quanto a isso?

  8. Felipe Salum disse:

    Oi Diogo, tem uma maneira pra testar o retorno automatico sem ter que fazer uma compra ou doacao pro site? :)

  9. Felipe disse:

    Infelizmente não funcionou………….já não sei o que é…

  10. Dri Viaro disse:

    oi, passei pra conhecer seu blog, e desejar boa semana
    bjss

    aguardo sua visita :)

  11. JUNIOR disse:

    vc é o cara! excelente script..

  12. Francisco, qualquer dúvida, é so dizer.

  13. Bruno, so voce da um include dentro do processo do PagSeguro. O meu funciona assim, se tiver alguma duvida, diz ae.

  14. Tarcio, é verdade. Mas para isso, basta voce checar os valores antes de liberar o pagamento.

  15. Marcela disse:

    Nossa, há quanto tempo não venho aqui, apesar de não me interessar, gostei do tutorial, bem explicado afinal!
    Bom, retorne ao meu blog e veja como ele está ficando *-*
    Deixe um comentário se possível.
    Abç. Maa

  16. Valeu aí Dourado, meu parente hehehe, ficou muito bom

  17. e ae Marcela, tudo joia? Valeu ae.. certamente irei visitar o seu blog! :)

  18. e ae Daniel… da família é? Bacana demais! =)

  19. ritesh disse:

    ola, tdo bom?
    procurei pelo teu email aqui, mas nao encontrei, eu tou precisando de uma ajuda tua, programo tb em PHP e uso a base de dados MySql, sera q podias me mandar um email pra agente cnversar?
    muito Obrigado.

  20. Pribena disse:

    Olá Diogo! Estou com um probleminha tá funcionando mas ao continuar comprando ele não acrescenta os produtos só aumenta a quantidade, porque?

  21. Ritesh, enviado! :)

  22. Pribena, O script foi desenvolvido para pegar apenas o total de produtos e valor da compra. Voce deve fazer uma rotina para ele pegar todos os produtos. Recomendo criar outra tabela para isso e relacionar. Leia a documentação do Pagseguro para maiores informações.

  23. Pribena disse:

    Então … resolvi o problema de parar de adicionar só a quantidade mas agora ele não está adicionando os outros produtos! por que?

  24. Allison disse:

    Muito bom posto Diogo.

    Mas me esclareça uma dúvida por gentileza.

    Uma vez que a compra já foi efetuada e os protudos também já foram inseridos em meus banco de dados, como faço para consultar o status da transação no PagSeguro ?

    Já tentei de inúmeras maneiras mas o PagSeguro não me retorna tal informação.

    Você já desenvolveu alguma maneira ?

    Abraços.

  25. Allison disse:

    Diogo,

    Consegui a resposta.

    Tenho um código já implementado do PagSeguro e gostaria de compartilhar com você.

    Pode entrar em contato comigo ?

    allison@eside.com.br

    Obrigado.

  26. O codigo esta exposto acima, basta implantar. ;)

Deixe uma resposta