Checkout transparente com PagSeguro no seu APP Rails

post-pagseguro2
Introdução

Integrar a sua aplicação com um meio de pagamento pode ser uma tarefa difícil e frustrante, porém na maior parte dos APPs com fins lucrativos é necessário ter uma maneira de receber dinheiro do usuário pelo sistema.

Neste Post eu falo sobre a integração do Rails com o checkout transparente do PagSeguro (Pagamento todo feito na nossa plataforma, sem redirecionar para o PagSeguro), vamos percorrer todo o caminho, passando pela criação do HTML, JS, dos Controllers e models, deploy para o Heroku e por fim o teste na plataforma do PagSeguro.

Vamos lá \o/

O que vamos aprender
  1. Como criar a estrutura para pegar os dados de pagamento do usuário
  2. Como enviar a solicitação de Pagamento para o PagSeguro
  3. Como Subir nossa aplicação para o Heroku
  4. Como receber as notificações do PagSeguro
  5. Como testar tudo isto 🙂

Ingredientes
  • Ruby 2.3.1
  • Rails 5
  • Devise (Gem)
  • bootstrap-sass (Gem)
  • pagseguro-oficial (Gem)
  • Heroku
Objetivos

Vamos começar criando a plataforma para criar novos produtos para que o usuário possa escolher um e ir para a tela de pagamento onde ele vai colocar seus dados de pagamentos e nós vamos via javascript chamar o PagSeguro para pegar as Opções de pagamento (Parcelamento), depois vamos subir nosso APP no heroku para ter uma URL válida para que o PagSeguro possa nos enviar notificações com o status do pagamento e por fim vamos listar todos os pedidos de pagamento do sistema e verificar se o status realmente mudou baseado nas chamadas do PagSeguro.

Passo a Passo
  1. Criação da conta no PagSeguro
  2. Criação da estrutura do Projeto
  3. Inclusão do Javascript
  4. Recebendo notificações
  5. Subindo para o Heroku
  6. Testando tudo isto 🙂
Mãos à Obra \o/
Parte 1 – Criação da conta no PagSeguro
  1. Caso você ainda não possua uma conta no PagSeguro acesse esse link (https://pagseguro.uol.com.br/registration/registration.jhtml?tipo=cadastro#!vendedor) e crie uma conta.
    PagSeguro Rails
  2. O PagSeguro vai enviar um email de confirmação, basta ir até sua caixa de email e confirmar 🙂
  3. Agora acesse seu Painel de sandbox (clicando nesse link) e clique em vendedor no menu lateral, guarde seu token para usarmos no projeto para autenticar nossa aplicação no PagSeguro.
    captura-de-tela-de-2017-01-06-15-30-14
  4. Pronto \o/
Parte 2 – Criação da estrutura do Projeto 
  1. Crie o Projeto (Vamos usar o database como PostgreSQL para subirmos nosso APP no heroku)
    1
    
    rails new pagseguro --database=postgresql
  2. Inclua as Gems que vamos usar no seu Gemfile:
    1
    2
    3
    
    gem 'bootstrap-sass'
    gem "pagseguro-oficial", "~> 2.5.0"
    gem "devise"
  3. Instale as Gems rodando:
    1
    
    bundle
  4. Configure seu arquivo ‘config/database.yml’ com as credenciais para acessar o seu banco postgreSQL instalado na sua máquina. (Caso você não saiba como instalar o postgreSQL, veja aqui https://www.digitalocean.com/community/tutorials/how-to-setup-ruby-on-rails-with-postgres)
  5. Gere seus scaffolds para poder incluir novos produtos e usuários:
    1
    2
    
    rails g scaffold product title:string price:decimal description:text
    rails g scaffold user name:string
  6. Agora crie o model e o controller order para podermos armazenar as transações do nosso sistema:
    1
    2
    
    rails g model order product_id:integer price:integer status:string buyer_name:string reference:string
    rails g controller order new create index
  7. Agora vamos até o model Order e vamos colocar a associação com o Produto, em “/app/models/order.rb” acrescente a seguinte linha:
    belongs_to :product
  8. No Model Product vamos colocar a associação com o Model Order, em “/app/models/product.rb” coloque a seguinte linha:
    has_many :orders
  9. Agora vamos gerar nosso Controller Home onde vai ficar a nossa lista de Produtos que o usuário pode comprar:
    rails g controller home index
  10. No Arquivo “/app/controller/home_controller.rb” substitua o conteúdo por:
    class HomeController < ApplicationController
      skip_before_filter :authenticate_user!, :only => :index
     
      def index
        @products = Product.all
      end
    end
  11. Agora para preparamos nossa View Home Index para mostrar a lista de Produtos e o botão de compra substitua o conteúdo do aqui ‘/app/views/home/index.html.erb’ por:
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    
    <h4>Nossos Produtos:</h4>
    <hr />
    <br />
    <% @products.each do |product| %>
      <p>Nome: <%= product.title %></p>
      <p>Preço: R$<%= product.price %></p>
      <p>Descrição: <%= product.description %></p>
      <td><%= link_to 'Comprar Produto', order_new_path(product_id: product.id), class: 'btn btn-success' %></td>
      <hr />
    <% end %>
  12. No nosso arquivo ‘config/routes.rb’, substitua a linha ‘get ‘home/index’ por:
    1
    
    root to: 'home#index'
  13. E ainda no routes.rb substitua a linha “get ‘order/create’ por:”
    1
    
    post 'order/create'
  14. Instale o devise, rodando:
    1
    
    rails generate devise:install
  15. Agora para incluir o devise no nosso user, rode:
    1
    
    rails generate devise User
  16. Crie o banco de dados e rode as migrations:
    1
    
    rake db:create &amp;&amp; rake db:migrate
  17. Agora coloque a seguinte linha no arquivo ‘app/controllers/application_controller.rb’ após a linha ‘class ApplicationController < ActionController::Base' e antes da linha 'end':
    1
    
    before_action :authenticate_user!
  18. Agora inclua o bootstrap no seu projeto, no arquivo ‘app/assets/javascripts/application.js’ substitua o conteúdo por:
    1
    2
    3
    4
    
    //= require jquery
    //= require jquery_ujs
    //= require bootstrap-sprockets
    //= require_tree .
  19. Renomeie seu arquivo ‘app/assets/stylesheets/application.css’ para ‘app/assets/stylesheets/application.scss’
  20. Agora substitua o conteúdo deste arquivo por:
    1
    2
    
    @import "bootstrap-sprockets";
    @import "bootstrap";
  21. Vamos criar nosso Form de pagamento, substitua o conteúdo da sua view ‘app/views/order/new.html.erb’ por:
    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
    147
    148
    149
    150
    151
    152
    153
    154
    
    <div class="container">
       <div class="row">
         <h2 class="col-md-4 col-md-offset-4">Finalize sua compra</h2>
       </div>
       <legend>Dados do Produto</legend>
       <p>Nome: <%= @product.title %></p>
       <p>Preço: $<%= @product.price %></p>
       <p>Descrição: <%= @product.description %></p>
       <input id='price' type="hidden" value="210">
       <div id="payment_datas">
       <form class="form-horizontal" role="form" action="/order/create" method="POST">
         <div id='payment-datas'>
           <div>
             <input type="hidden" name="product_id" value="<%= @product.id %>">
             <input type="hidden" name="card_token" id="card_token" />
             <input type="hidden" name="sender_hash" id="sender_hash" />
             <input type="hidden" name="session_id" id="session_id" value="<%= @session_id %>" />
             <%= csrf_meta_tag %>
           </div>
           <fieldset>
             <legend>Dados Pessoais do Comprador</legend>
             <div class="form-group">
               <label class="col-sm-3 control-label">Nome</label>
               <div class="col-sm-4">
                 <input type="text" class="form-control" name='name' placeholder="exp: José Paulo" required>
               </div>
             </div>
             <div class="form-group">
               <label class="col-sm-3 control-label">Email</label>
               <div class="col-sm-4">
                 <input type="text" class="form-control" name='email' placeholder="exp: c56048717318@sandbox.pagseguro.com.br" required>
               </div>
               *No sandbox use o email: c56048717318@sandbox.pagseguro.com.br
             </div>
             <div class="form-group">
               <label class="col-sm-3 control-label">Cpf</label>
               <div class="col-sm-2">
                 <input type="text" class="form-control" name='cpf' placeholder="39813476548" required>
               </div>
               * Não use . ou - no CPF ou trate isso :)
             </div>
             <div class="form-group">
               <label class="col-sm-3 control-label">Telefone</label>
               <div class="col-sm-1">
                 <input type="text" class="form-control" name='phone_code' placeholder="11" required>
               </div>
               <div class="col-sm-2">
                 <input type="text" class="form-control" name='phone_number' placeholder="997874567" required>
               </div>
             </div>
             <div class="form-group">
               <label class="col-sm-3 control-label">Data de Nascimento</label>
               <div class="col-sm-2">
                 <input type="text" class="form-control" name='birthday' placeholder="10/10/1991" required>
               </div>
             </div>
           </fieldset>
           <fieldset>
             <legend>Dados do Cartão</legend>
             <div class="form-group">
               <label class="col-sm-3 control-label">Name on Card</label>
               <div class="col-sm-4">
                 <input type="text" class="form-control" name='card_name' id='card-name' placeholder="Card Holder's Name" required>
               </div>
             </div>
             <div class="form-group">
               <label class="col-sm-3 control-label" for="card-number">Card Number</label>
               <div class="col-sm-4">
                 <input type="text" class="form-control" name='card-number' id='card-number' placeholder="Debit/Credit Card Number" required>
               </div>
               <div class="col-sm-1">
                 <span id="card-flag"></span>
               </div>
             </div>
             <div class="form-group">
               <label class="col-sm-3 control-label">Expiration Date</label>
               <div class="col-sm-9">
                 <div class="row">
                   <div class="col-xs-3">
                     <select class="form-control col-sm-2" name='card-month' id='card-month' required>
                       <option>Month</option>
                       <option value="01">Jan (01)</option>
                       <option value="02">Feb (02)</option>
                       <option value="03">Mar (03)</option>
                       <option value="04">Apr (04)</option>
                       <option value="05">May (05)</option>
                       <option value="06">June (06)</option>
                       <option value="07">July (07)</option>
                       <option value="08">Aug (08)</option>
                       <option value="09">Sep (09)</option>
                       <option value="10">Oct (10)</option>
                       <option value="11">Nov (11)</option>
                       <option value="12">Dec (12)</option>
                     </select>
                   </div>
                   <div class="col-xs-3">
                     <select class="form-control" name='card-year' id='card-year' required>
                       <option value="2016">2016</option>
                       <option value="2017">2017</option>
                       <option value="2018">2018</option>
                       <option value="2019">2019</option>
                       <option value="2010">2020</option>
                       <option value="2021">2021</option>
                       <option value="2022">2022</option>
                       <option value="2023">2023</option>
                       <option value="2024">2024</option>
                       <option value="2025">2025</option>
                       <option value="2026">2026</option>
                       <option value="2027">2027</option>
                       <option value="2028">2028</option>
                       <option value="2029">2029</option>
                       <option value="2030">2030</option>
                     </select>
                   </div>
                 </div>
               </div>
             </div>
             <div class="form-group" id="card-cvv-box" style="display: none">
               <label class="col-sm-3 control-label">Card CVV</label>
               <div class="col-sm-3">
                 <input type="text" class="form-control" name='card-cvv' id='card-cvv' placeholder="Security Code">
               </div>
             </div>
             <div class="form-group" id="card-options-box" style="display: none">
               <hr />
               <label class="col-sm-3 control-label">Payment Options (parcelamentos)</label>
               <div class="col-sm-3">
                 <select class="form-control col-sm-2" id="card-options">
                 </select>
               </div>
               <hr />
             </div>
             <div class="form-group">
               <div class="col-sm-offset-3 col-sm-9">
                 <button type="button" class="btn btn-success" id="buy-button">Confirmar dados do cartão</button>
               </div>
             </div>
           </fieldset>
         </div>
         <div id='finish-buy' style="display: none">
           <fieldset>
             <legend>Confirmar Pagamento</legend>
             <div class="form-group">
               <div class="col-sm-offset-3 col-sm-9">
                 <%= csrf_meta_tags %>
                 <button type="submit" class="btn btn-success" id="buy-button">Finalizar Compra</button>
                 <button type="button" class="btn btn-primary" id="edit-payment">Editar Meio de Pagamento</button>
               </div>
             </div>
           </fieldset>
         </div>
       </form>
     </div>
    </div>
  22. Vamos criar nossa listagem de orders (pedidos de compras), substitua o conteúdo da sua view ‘app/views/order/index.html.erb’ por:
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    
     
    <h4>Orders list:</h4>
    <br />
    <% @orders.each do |order| %>
      <p>Product Name: <%= order.product.title %></p>
      <p>User: <%= order.buyer_name %></p>
      <p>Status: <%= order.status %></p>
      <hr />
    <% end %>
     
    <a href="/products">Produtos</a>
  23. Altere seu arquivo ‘/app/views/layout/application.html.erb’ para incluir o javascript do checkout transparente do PagSeguro, seu arquivo deve ficar assim:
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    
    <!DOCTYPE html>
    <html>
      <head>
        <title>Pagseguro</title>
        <%= csrf_meta_tags %>
        <%= stylesheet_link_tag    'application', media: 'all', 'data-turbolinks-track': 'reload' %>
        <%= javascript_include_tag 'application', 'data-turbolinks-track': 'reload' %>
        <script type="text/javascript" src="https://stc.sandbox.pagseguro.uol.com.br/pagseguro/api/v2/checkout/pagseguro.directpayment.js"></script>
      </head>
      <body>
        <%= yield %>
      </body>
    </html>

    *Lembrando que caso você queira usar em Production o link para o javascript de production do checkout transparente do Pagseguro é: https://stc.pagseguro.uol.com.br/pagseguro/api/v2/checkout/pagseguro.directpayment.js

  24. Agora no seu ‘app/controllers/order_controller.rb’ vamos colocar nosso métodos para criar um novo pagamento e para listar os pagamentos, substitua o conteúdo do seu controller pelo abaixo (Leia os comentários no código para entender o que foi feito):
    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
    
    class OrderController < ApplicationController
      protect_from_forgery
     
      # Gerar um Token de sessão para nosso pagamento
      def new
        @product = Product.find(params[:product_id])
        @session_id = (PagSeguro::Session.create).id
      end
     
      # Enviar nosso pagamento para o Pagseguro
      def create
        @product = Product.find(params[:product_id])
     
        payment = PagSeguro::CreditCardTransactionRequest.new
        payment.notification_url = "https://secret-wave-53573.herokuapp.com/notification  "
        payment.payment_mode = "gateway"
     
        # Aqui vão os itens que serão cobrados na transação, caso você tenha multiplos itens
        # em um carrinho altere aqui para incluir sua lista de itens
        payment.items << {
          id: @product.id,
          description: @product.description,
          amount: @product.price,
          weight: 0
        }
     
        # Criando uma referencia para a nossa ORDER
        reference = "REF_#{(0...8).map { (65 + rand(26)).chr }.join}_#{@product.id}"
        payment.reference = reference
        payment.sender = {
          hash: params[:sender_hash],
          name: params[:name],
          email: params[:email]
        }
     
        payment.credit_card_token = params[:card_token]
        payment.holder = {
         name: params[:card_name],
         birth_date: params[:birthday],
         document: {
           type: "CPF",
           value: params[:cpf]
         },
         phone: {
           area_code: params[:phone_code],
           number: params[:phone_number]
         }
        }
     
        payment.installment = {
         value: @product.price,
         quantity: 1
        }
     
        puts "=> REQUEST"
        puts PagSeguro::TransactionRequest::RequestSerializer.new(payment).to_params
        puts
     
        payment.create
     
        # Cria uma Order para registro das transações
        Order.create(product_id: @product.id, buyer_name: params[:name], reference: reference, status: 'pending')
     
        if payment.errors.any?
         puts "=> ERRORS"
         puts payment.errors.join("\n")
         render plain: "Erro No Pagamento #{payment.errors.join("\n")}"
        else
         puts "=> Transaction"
         puts "  code: #{payment.code}"
         puts "  reference: #{payment.reference}"
         puts "  type: #{payment.type_id}"
         puts "  payment link: #{payment.payment_link}"
         puts "  status: #{payment.status}"
         puts "  payment method type: #{payment.payment_method}"
         puts "  created at: #{payment.created_at}"
         puts "  updated at: #{payment.updated_at}"
         puts "  gross amount: #{payment.gross_amount.to_f}"
         puts "  discount amount: #{payment.discount_amount.to_f}"
         puts "  net amount: #{payment.net_amount.to_f}"
         puts "  extra amount: #{payment.extra_amount.to_f}"
         puts "  installment count: #{payment.installment_count}"
     
         puts "    => Items"
         puts "      items count: #{payment.items.size}"
         payment.items.each do |item|
           puts "      item id: #{item.id}"
           puts "      description: #{item.description}"
           puts "      quantity: #{item.quantity}"
           puts "      amount: #{item.amount.to_f}"
         end
     
         puts "    => Sender"
         puts "      name: #{payment.sender.name}"
         puts "      email: #{payment.sender.email}"
         puts "      phone: (#{payment.sender.phone.area_code}) #{payment.sender.phone.number}"
         puts "      document: #{payment.sender.document}: #{payment.sender.document}"
         render plain: "Sucesso, seu pagamento será processado :)"
        end
     
      end
     
      def index
        @orders = Order.all
      end
    end
  25. Rode o projeto:
    1
    
    rails s
  26. Crie um User pelo form do devise para ser o administrador da loja acessando no browser ‘http://localhost:3000/users/sign_up‘:
    captura-de-tela-de-2017-01-06-16-27-24
  27. Agora crie um Product acessando no browser ‘http://localhost:3000/products/new‘:
    captura-de-tela-de-2017-01-06-16-33-58
  28. Agora você precisa criar um initializer para configurar seu PagSeguro. Crie um arquivo no seguinte path ‘app/config/pagseguro.rb’, cole o código abaixo e coloque suas credenciais:
    1
    2
    3
    4
    5
    6
    
    PagSeguro.configure do |config|
      config.token       = "SEU_TOKEN_DO_PAGSEGURO"
      config.email       = "SEU_EMAIL"
      config.environment = :sandbox # ou :sandbox. O padrão é production.
      config.encoding    = "UTF-8"
    end
  29. Agora rode seu servidor:
    1
    
    rails s
  30. No browser acesse ‘http://localhost:3000‘ e clique em comprar em algum produto da lista.
    captura-de-tela-de-2017-01-06-17-35-48
  31. A estrutura do nosso App está pronta, agora vamos incluir nosso JavaScript.
Parte 3 – Inclusão do JavaScript
  1. Crie um arquivo em ‘/app/assets/javascripts/pagseguro.js’ e cole o seguinte código dentro dele (lembre-se de ler os comentários no código para entender as funções):
    $( document ).ready(function() {
      // Inicia o PagSeguro
      PagSeguroDirectPayment.setSessionId($("#session_id").val());
     
      // Verifica se existe um cartão preenchido
      card_flag();
     
      // Pega o Sender Hash e o Card Token quando o usuário confirma os dados do cartão
      $("#buy-button").click(function() {
        $('#sender_hash').val(PagSeguroDirectPayment.getSenderHash());
     
        var params = {
         cardNumber: $("#card-number").val(),
         cvv: $("#card-cvv").val(),
         expirationMonth: $("#card-month").val(),
         expirationYear: $("#card-year").val(),
         success: function (response) {
           //token gerado, esse deve ser usado na chamada da API do Checkout Transparente
           $('#card_token').val(response['card']['token']);
           $('#payment-datas').hide();
           $('#finish-buy').fadeIn();
         },
         error: function (response) {
           alert('As informações sobre o cartão estão incorretas')
         }
        }
     
        PagSeguroDirectPayment.createCardToken(params);
      });
     
      // Muda do step de finalização para o step de edição do meio de pagamento
      $("#edit-payment").click(function() {
        $('#finish-buy').hide();
        $('#payment-datas').fadeIn();
      });
     
      // Verifica informações sobre o cartão digitado como a bandeira
      //, tamanho do cvv, se possui expiração de é internacional e etc
      $("#card-number").on('input', function() {
        card_flag();
      });
    })
     
     
    function card_flag()
    {
      PagSeguroDirectPayment.getBrand({
       cardBin: $("#card-number").val(),
       success: function (response) {
         console.log(response);
         //Coloca qual a bandeira ao lado do numero
         $("#card-flag").html(response['brand']['name']);
         $("#card-flag").show();
         //Mostra as opções de parcelamento (passando o preço e a bandeira)
         showPaymentOptions(response['brand']['name'], $("#price").val());
         $("#card-options-box").show();
         //Mostra o campo CVV se o cartão exigir
         if(response['brand']['cvvSize'] > 0){$("#card-cvv-box").show();}
       },
       error: function (response) {
         console.log($("#card-number").val());
         console.log(response);
         $("#card-flag").hide();
         $("#card-cvv-box").hide();
         $("#card-options-box").hide();
       }
      });
    }
     
    //Função para pegar o token do cartão de crédito que será usado no checkout
    function getCardToken(card_number, cvv, month, year){
      console.log(month);
      console.log(year);
      var params = {
        cardNumber: card_number,
        cvv: cvv,
        expirationMonth: month,
        expirationYear: year,
        success: function (response) {
          console.log(response);
        },
        error: function (response) {
          console.log(response);
        }
      }
     
      PagSeguroDirectPayment.createCardToken(params);
    }
     
    // Função para mostrar opções de pagamento para o usuário
    function showPaymentOptions(flag, price)
    {
      PagSeguroDirectPayment.getInstallments({
       amount: price,
       brand: flag,
       success: function (response) {
         $("#card-options").html("");
         $.each( response['installments'][flag], function( index, value ){
           $("#card-options")
           .append($("<option></option>")
                      .attr("value",value['quantity'])
                      .text("$"+value['installmentAmount']+" x "+value['quantity']+" - total: $"+value['totalAmount']));
         });
       },
       error: function (response) {
         console.log(response);
       },
       complete: function (response) {
         //tratamento comum para todas chamadas
       }
     });
    }
  2. Agora rode novamente seu projeto:
    1
    
    rails s
  3. Acesse no seu browser ‘http://localhost:3000‘ e clique em comprar.
  4. Na página de finalização do pedido que abriu simule colocar um cartão de crédito (use os dados de sandbox, número 411111111111, cvv 123, email c56048717318@sandbox.pagseguro.com.br)
  5. Note que agora o js coloca a bandeira do cartão, mostra o cvv caso o cartão precise e mostra a segunda sessão depois dos dados:
    captura-de-tela-de-2017-01-06-21-32-57
Parte 4 – Recebendo Notificações

Sempre que uma transação muda de status no PagSeguro ele chama nossa aplicação através da URL de notificação que colocamos no método create do controller Order. Nesta parte nós vamos configurar um Controller para receber essa chamada e alterar o status do nosso Order baseado nisto.

  1. Vamos primeiro criar o Controller, rode:
    rails g controller notification create --skip-template-engine
  2. Agora coloque o seguinte conteúdo dentro do Controller que foi criado em “/app/controller/notification_controller.rb”:
    class NotificationController < ApplicationController
      skip_before_filter :authenticate_user!, :only => :create
      protect_from_forgery
     
      def create
        transaction = PagSeguro::Transaction.find_by_notification_code(params[:notificationCode])
        status = ['Aguardando Pagamento', 'Em análise', 'Paga', 'Disponível', 'Em disputa', 'Devolvida', 'Cancelada']
     
        if transaction.errors.empty?
          order = Order.where(reference: transaction.reference).last
          order.status = status[transaction.status.id.to_i - 1]
          order.save
        end
     
          render nothing: true, status: 200
      end
    end
  3. Agora no nosso arquivo “config/routes.rb” substitua esta rota “get ‘notification/create'” pela rota abaixo:
    post 'notification', to: 'notification#create'

    Pronto, agora nós precisamos subir nosso APP para o heroku para pegar a URL que usaremos para as notificações, vamos lá \o/

Parte 5 – Subindo para o Heroku

Vamos subir nosso App para o heroku para que tenhamos uma URL válida para receber as notificações do PagSeguro:

  1. Visite no seu browser: https://signup.heroku.com/
  2. Crie uma conta caso você não possua.
    captura-de-tela-de-2016-12-17-19-31-06
  3. Instale o heroku cli caso você não possua e faça o login (Para aprender a instalar acesse https://devcenter.heroku.com/articles/heroku-cli)
  4. Agora precisamos instalar o git no nosso repositório e fazer o commit das nossas mudanças, rode:
    1
    
    git init

    depois rode:

    1
    
    git add .

    depois rode:

    1
    
    git commit -m 'PagSeguro'
  5. Para criar nosso projeto no heroku rode:
    1
    
    heroku create
  6. Note que agora que você criou o APP ele mostrou no console a URL do seu projeto, guarde essa URL para podermos acessar e também para usarmos para receber a notificação:
    captura-de-tela-de-2017-01-06-19-00-00
    * Neste caso nossa URL está em azul (https://secret-wave-53573.herokuapp.com/)
  7. Agora antes de prosseguirmos, vá no seu arquivo “/app/controllers/order_controler.rb” e no método create dentro desta linha ” payment.notification_url = “sua_url_do_heroku/notification” ” coloque a URL  para o seu projeto no heroku + /notification.
  8. Finalmente suba seu app rodando:
    1
    
    git push heroku master
  9. Agora rode as migrations do seu projeto:
    1
    
    heroku run rake db:migrate
  10. \o/ Pronto, finalmente nosso pequeno site que aceita pagamentos está no ar
Parte 6 – Testando Tudo Isto

Agora vamos fazer um teste para ver se está tudo funcionando como gostaríamos, como este é apenas um exemplo vamos testar em sandbox, então vamos ter que finalizar o pagamento manualmente pelo sandbox do PagSeguro.

  1. Visite a URL do seu site no heroku que você pegou no passo anterior, acesse a raiz dela. No meu caso https://secret-wave-53573.herokuapp.com/
    captura-de-tela-de-2017-01-06-19-14-03
    *Está vazio porque ainda não criamos nenhum produto
  2. Agora visite no seu browser url_do_seu_projeto_no_heroku/users/sign_up e crie uma conta para seu administrador do sistema (Em uma aplicação real você teria que impedir que outras pessoas criassem contas de administrador, mas estamos só fazendo um exemplo):
    captura-de-tela-de-2017-01-06-19-16-05
  3. Agora você foi redirecionado para a página de criação de produtos, mas caso tenha fechado a Aba visite url_do_seu_projeto_no_heroku/products
  4. Usando esse CRUD, crie novos produtos com valores e nomes diferentes para poder testar depois:
    captura-de-tela-de-2017-01-06-19-21-15
  5. Agora abra uma Aba anônima para usar um usuário que não está logado e visite a raiz do seu site no heroku, no meu caso https://secret-wave-53573.herokuapp.com/.
  6. Veja que a lista de produtos que você criou está lá, agora escolha um e clique em “Comprar Produto”:
    captura-de-tela-de-2017-01-06-20-18-25
  7. Agora na página de pagamento preencha todos os campos, para o numero do cartão você pode usar:
    4111111111111111, para o cvv: 123 e para o CPF: 588.147.884-30.
    captura-de-tela-de-2017-01-06-20-24-02
  8. Pronto, agora finalize a compra \o/
  9. Visite a página que lista as suas orders (pedidos de compra) nessa URL url_do_seu_projeto_no_heroku/order/index
    captura-de-tela-de-2017-01-06-20-57-37
  10. Como nós estamos na sandbox do PagSeguro, o pagamento não será concluído sozinho :(. Mas em um caso real ele seria concluído quando a operadora de cartão liberasse e o PagSeguro chamaria nosso Controller de notificação. Como ele não vai fazer isso, vamos fazer manualmente.
  11. Visite a página de transações do Pagseguro clicando aqui, e note que a transação que você acaba de fazer está lá:
    captura-de-tela-de-2017-01-06-20-38-14
  12. Clique na transação, e quando aparecer o menu clique em “alterar” para alterar manualmente o status da transação.
    captura-de-tela-de-2017-01-06-20-39-44
  13. Altere para “Pago” e dê ok.
  14. Agora vamos visitar novamente nossa página com a listagem dos orders e ver se o status mudou, visite a página: url_do_seu_projeto_no_heroku/order/index
    captura-de-tela-de-2017-01-06-21-05-42
  15. Sucesso \o/, recebemos a notificação, verificamos se ela era verdadeira, verificamos o conteúdo dele e alteramos o status do pagamento. Finalmente conseguimos fazer nosso sistema de pagamento funcionar, parabéns!

 

CONCLUSÃO

Conseguimos criar nosso pequeno APP com sistema de pagamento, como você pode ter notado é um longo caminho mesmo quando simplificamos algumas partes, mas se você está construindo um APP que precisa receber dinheiro não tem jeito, vai ter que desenvolver essa parte no seu APP, espero que com esse tutorial se torne mais fácil.

Com algumas configurações a mais poderíamos também receber via Boleto que é uma das modalidades do PagSeguro. Caso você queira um Post futuro onde acrescentamos isso deixa um comentário abaixo 🙂

Nesse exemplo nós usamos a sandbox do PagSeguro que é a simulação da integração com o sistema real e simplificamos várias partes para acelerar o processo, quando você desenvolver seu projeto para production usando um meio de pagamento, inclua filtros nos inputs, verificações e meios para que sua aplicação seja segura.

Para saber mais acesse a documentação oficial do PagSeguro clicando aqui.

Como de costume o Código completo da aplicação está no Github, caso você queria clonar o código, clique aqui. Aproveita e me segue lá \o/

Se você ficou com dúvidas ou tem sugestões de posts para o Blog comenta aí em baixo ou me adiciona no Facebook clicando aqui.

Muito Obrigado,
Sua presença aqui é uma honra para mim,
Leonardo Scorza 🙂

Deixe seu Feedback!

Comentários