DEV Community

Gabriel Maximiniano
Gabriel Maximiniano

Posted on • Edited on

6 2

Laravel + PayPal - Parte 1: Criando projeto

Recentemente eu participei em um projeto da empresa júnior InfoAlto na qual precisava de um módulo de pagamentos do tipo assinatura, o cliente tinha preferência por utilizar o PayPal como gatway de pagamento e isso me trouxe algumas dificuldades. Foi o segundo projeto que fiz na qual tive contato com meios de pagamento (realizei um anteriormente que tinha um checkout porém utilizando o pagseguro) e eu não tinha noção de como funcionava os pagamentos recorrentes, além disso, uma documentação um pouco confusa entre versões da API do PayPal e um SDK para PHP desatualizado serviram como dificuldades para eu conseguir seguir com o projeto. Como eu não consegui encontrar muito conteúdo em português que me ensinasse a fazer o que precisava, decidi compartilhar o que consegui aprender. Por isso vou criar um pequeno projeto de venda/aluguel de filmes (algo similar ao youtube movies) e assinatura (como a netflix) e compartilhar com uma série de posts.

Edit: código foi atualizado para a versão 8 do laravel. Isso não implica em nenhuma mudança grave do que foi feito nessa parte

Criando o projeto

O primeiro passo é criar o projeto com o comando laravel new com o nome do projeto, no meu caso vou chamar de laravel_paypal:

laravel new laravel_paypal

Configurando banco de dados

Após o projeto ser criado, vamos configurar o nosso arquivo .env para fazer a conexão com o banco de dados

DB_CONNECTION=mysql
DB_HOST=127.0.0.1
DB_PORT=3306
DB_DATABASE=nome_banco
DB_USERNAME=nome_usuario
DB_PASSWORD=senha_usuario
Enter fullscreen mode Exit fullscreen mode

Com isso, vamos criar 2 migrations novas para a nossa aplicação, sendo elas: movies e movie_user

Migration movies

A tabela movies vai ser responsável por guardar as informações dos filmes disponíveis na plataforma

php artisan make:migration create_movies_table

O código da função up fica assim:

    public function up()
    {
        Schema::create('movies', function (Blueprint $table) {
            $table->id();
            $table->string("title");
            $table->string("image");
            $table->text("overview");
            $table->float("purchase_price")->nullable();
            $table->float("rental_price")->nullable();
            $table->timestamps();
        });
    }
Enter fullscreen mode Exit fullscreen mode
  • Campo title: é do tipo string (varchar no banco de dados) e guarda o título do filme;
  • Campo image: é do tipo string (varchar no banco de dados) e guarda a URI da thumb do filme;
  • Campo overview: é do tipo text e guarda o resumo ou sinopse do filme;
  • Campo purchase_price: é tipo float e guarda o preço de compra do filme, se ele for nulo o filme não tem a opção de compra disponível;
  • Campo rental_price: é do tipo float e guarda o preço de aluguel do filme, se ele for nulo o filme não tem a opção de aluguel disponível.

Migration movie_user

A tabela movie_user vai ser responsável por armazenar o relacionamento entre um usuário e um filme

php artisan make:migration create_movie_user_table

O código da função up fica assim:

    public function up()
    {
        Schema::create('movie_user', function (Blueprint $table) {
            $table->id();
            $table->bigInteger("user_id");
            $table->bigInteger("movie_id");
            $table->dateTime("expires_at")->nullable();
            $table->dateTime("acquired_in");
        });
    }
Enter fullscreen mode Exit fullscreen mode
  • Campo user_id: é do tipo big int e guarda o ID do usuário;
  • Campo movie_id: é do tipo big int e guarda o ID do filme;
  • Campo expires_at: é do tipo datetime e guarda a data de expiração do aluguel do filme, se for nulo indica que o usuário fez a compra do filme;
  • Campo acquired_in: é tipo datetime e guarda a data que o usuário adquiriu aquele filme, sendo aluguel ou compra.

Migration user

Por padrão o Laravel já disponibiliza uma migration que cria a tabela users, por isso nós não precisamos criar-lá.

Agora que já temos nossas migrations é só rodar com o comando:

php artisan migrate

Criando Models e Seeder

Com as tabelas do banco criado está na hora de criarmos e configurarmos as Models e começar a popular o banco de dados

Model Movie

php artisan make:model Movie

E o código da model fica assim:

class Movie extends Model
{
    protected $fillable = [
        "title", "image", "overview", "purchase_price", "rental_price"
    ];

    public function users() {
        $this->belongsToMany("App\User");
    }
}
Enter fullscreen mode Exit fullscreen mode
  • No atributo fillable colocamos todos os campos da tabela movies que é permitido inserir e fazer alterações;
  • Na função users() criamos um relacionamento N:N com a Model User

Model User

Por padrão a model User já vem na criação do projeto Laravel, por isso a unica alteração que vamos fazer é criar o relacionamento N:N com a Model Movie, adicionando a seguinte função na model:

    public function movies() {
        $this->belongToMany("App\Movie");
    }
Enter fullscreen mode Exit fullscreen mode

Lembrando que por padrão, o Laravel irá utilizar como tabela intermediária para esse relacionamento a tabela que criamos com a migration movie_user

Populando o banco de dados

Para iniciar com a nossa aplicação, vamos popular a tabela movies com alguns filmes, para isso precisamos primeiro criar um seeder com o comando:

php artisan make:seeder MoviesTableSeeder

O código desse seeder fica assim:

<?php

use Illuminate\Database\Seeder;
use App\Movie;

class MoviesTableSeeder extends Seeder
{
    /**
     * Run the database seeds.
     *
     * @return void
     */
    public function run()
    {
        Movie::insert([
            [
                "title" => "Homem de Ferro",
                "image" => "https://m.media-amazon.com/images/M/MV5BMTczNTI2ODUwOF5BMl5BanBnXkFtZTcwMTU0NTIzMw@@._V1_UX182_CR0,0,182,268_AL_.jpg",
                "overview" => "Depois de ser mantido em cativeiro em uma caverna afegã, o engenheiro bilionário Tony Stark cria uma armadura única e armada para combater o mal.",
                "purchase_price" => 12.99,
                "rental_price" => 40.99
            ],
            [
                "title" => "O Incrível Hulk",
                "image" => "https://m.media-amazon.com/images/M/MV5BMTUyNzk3MjA1OF5BMl5BanBnXkFtZTcwMTE1Njg2MQ@@._V1_UX182_CR0,0,182,268_AL_.jpg",
                "overview" => "Bruce Banner, um cientista em fuga do governo dos EUA, deve encontrar uma cura para o monstro em que se transforma, sempre que perde a paciência.",
                "purchase_price" => 12.99,
                "rental_price" => 40.99
            ],
            [
                "title" => "Homem de Ferro 2",
                "image" => "https://m.media-amazon.com/images/M/MV5BMTM0MDgwNjMyMl5BMl5BanBnXkFtZTcwNTg3NzAzMw@@._V1_UX182_CR0,0,182,268_AL_.jpg",
                "overview" => "Com o mundo agora ciente de sua identidade como Homem de Ferro, Tony Stark deve enfrentar tanto sua saúde em declínio quanto um homem louco e vingativo, ligado ao legado de seu pai.",
                "purchase_price" => 12.99,
                "rental_price" => 40.99
            ],
            [
                "title" => "Thor",
                "image" => "https://m.media-amazon.com/images/M/MV5BOGE4NzU1YTAtNzA3Mi00ZTA2LTg2YmYtMDJmMThiMjlkYjg2XkEyXkFqcGdeQXVyNTgzMDMzMTg@._V1_UX182_CR0,0,182,268_AL_.jpg",
                "overview" => "O poderoso, mas arrogante deus Thor, é expulso de Asgard para viver entre os humanos em Midgard (Terra), onde ele logo se torna um dos seus melhores defensores.",
                "purchase_price" => 12.99,
                "rental_price" => 40.99
            ],
            [
                "title" => "Capitão América: O Primeiro Vingador",
                "image" => "https://m.media-amazon.com/images/M/MV5BOGE4NzU1YTAtNzA3Mi00ZTA2LTg2YmYtMDJmMThiMjlkYjg2XkEyXkFqcGdeQXVyNTgzMDMzMTg@._V1_UX182_CR0,0,182,268_AL_.jpg",
                "overview" => "Steve Rogers, um soldado militar rejeitado, se transforma no Capitão América depois de tomar uma dose de um 'soro de super-soldado'. Mas ser Capitão América tem um preço, enquanto ele tenta derrubar um traficante de guerra e uma organização terrorista.",
                "purchase_price" => 12.99,
                "rental_price" => 40.99
            ],
            [
                "title" => "Os Vingadores",
                "image" => "https://m.media-amazon.com/images/M/MV5BNDYxNjQyMjAtNTdiOS00NGYwLWFmNTAtNThmYjU5ZGI2YTI1XkEyXkFqcGdeQXVyMTMxODk2OTU@._V1_UX182_CR0,0,182,268_AL_.jpg",
                "overview" => "Os heróis mais poderosos da Terra devem se unir e aprender a lutar em equipe, se quiserem impedir que o travesso Loki e seu exército alienígena escravizem a humanidade.",
                "purchase_price" => 12.99,
                "rental_price" => 40.99
            ],
            [
                "title" => "Homem de Ferro 3",
                "image" => "https://m.media-amazon.com/images/M/MV5BMjE5MzcyNjk1M15BMl5BanBnXkFtZTcwMjQ4MjcxOQ@@._V1_UY268_CR3,0,182,268_AL_.jpg",
                "overview" => "Quando o mundo de Tony Stark é dilacerado por um terrorista formidável chamado Mandarin, ele inicia uma odisseia de reconstrução e retribuição.",
                "purchase_price" => 12.99,
                "rental_price" => 40.99
            ],
            [
                "title" => "Thor: O Mundo Sombrio",
                "image" => "https://m.media-amazon.com/images/M/MV5BMTQyNzAwOTUxOF5BMl5BanBnXkFtZTcwMTE0OTc5OQ@@._V1_UY268_CR3,0,182,268_AL_.jpg",
                "overview" => "Quando os Elfos Negros tentam mergulhar o universo na escuridão, Thor deve embarcar em uma jornada perigosa e pessoal que o reunirá com a médica Jane Foster.",
                "purchase_price" => 12.99,
                "rental_price" => 40.99
            ],
            [
                "title" => "Capitão América: O Soldado Invernal",
                "image" => "https://m.media-amazon.com/images/M/MV5BMzA2NDkwODAwM15BMl5BanBnXkFtZTgwODk5MTgzMTE@._V1_UY268_CR1,0,182,268_AL_.jpg",
                "overview" => "Enquanto Steve Rogers luta para abraçar seu papel no mundo moderno, ele se une a um colega dos Vingadores e da S.H.I.E.L.D, a Viúva Negra, para combater uma nova ameaça da história: um assassino conhecido como Soldado Invernal.",
                "purchase_price" => 12.99,
                "rental_price" => 40.99
            ],
            [
                "title" => "Guardiões da Galáxia",
                "image" => "https://m.media-amazon.com/images/M/MV5BMTAwMjU5OTgxNjZeQTJeQWpwZ15BbWU4MDUxNDYxODEx._V1_UX182_CR0,0,182,268_AL_.jpg",
                "overview" => "Um grupo de criminosos intergaláticos deve se unir para parar um guerreiro fanático com planos de limpar o universo.",
                "purchase_price" => 12.99,
                "rental_price" => 40.99
            ],
            [
                "title" => "Vingadores: Era de Ultron",
                "image" => "https://m.media-amazon.com/images/M/MV5BMTM4OGJmNWMtOTM4Ni00NTE3LTg3MDItZmQxYjc4N2JhNmUxXkEyXkFqcGdeQXVyNTgzMDMzMTg@._V1_UX182_CR0,0,182,268_AL_.jpg",
                "overview" => "Quando Tony Stark e Bruce Banner tentam iniciar um programa de manutenção da paz adormecido chamado Ultron, as coisas saem terrivelmente erradas e cabe aos heróis mais poderosos da Terra impedir que o vilão Ultron decida executar seu plano terrível.",
                "purchase_price" => 12.99,
                "rental_price" => 40.99
            ]
        ]);
    }
}

Enter fullscreen mode Exit fullscreen mode

E antes de rodar nosso seeder temos que inserir ele dentro do arquivo DatabaseSeeder.php:

class DatabaseSeeder extends Seeder
{
    /**
     * Seed the application's database.
     *
     * @return void
     */
    public function run()
    {
        $this->call(MoviesTableSeeder::class);
    }
}
Enter fullscreen mode Exit fullscreen mode

Com isso só rodar o seguinte comando que nosso banco estará populado:

php artisan db:seed

Criando a página inicial do sistema

Para criar a página inicial do sistema, vamos utilizar o módulo de login do Laravel. Se você está acostumando com a versão 5 do Laravel pode estranhar um pouco, pois antes bastava executar o comando php artisan make:auth e todo o módulo de login estava pronto. Porém na versão 6 isso começou a mudar, e agora na versão 7 é possível escolher entre 3 tipos de frameworks frontend para fazer a interface de sua aplicação. Como esse tutorial está mais focado em integrar o paypal com o laravel vou utlizar o bootstrap como framework frontend.

Primeiro, temos que instalar o pacote de interfaces do Laravel:

composer require laravel/ui

Após a instalação escolhemos a opção do bootstrap:

php artisan ui bootstrap --auth

Após esse comando, o laravel irá adicionar vários arquivos, como migrations, controllers, views, etc. Como ele cria uma nova migration é bom rodar o php artisan migrate novamente.

Para conseguir utilizar o pacote é necessário ter o npm instalado e executar o seguinte comando:

npm install && npm run dev

Para baixar o node e npm só acessar esse link

Configurando Controller E Views

Nesse inicio só iremos disponibilizar para view home todos os filmes salvos no banco de dados, com isso, o código do HomeController fica assim:

<?php

namespace App\Http\Controllers;

use Illuminate\Http\Request;
use App\Movie;

class HomeController extends Controller
{
    /**
     * Create a new controller instance.
     *
     * @return void
     */
    public function __construct()
    {
        $this->middleware('auth');
    }

    /**
     * Show the application dashboard.
     *
     * @return \Illuminate\Contracts\Support\Renderable
     */
    public function index()
    {
        $movies = Movie::all();
        return view('home', ['movies' => $movies]);
    }
}

Enter fullscreen mode Exit fullscreen mode

A view home fica assim:

@extends('layouts.app')

@section('content')
<div class="container">
    <div class="row justify-content-center">
        <div class="col-md-12">
            <div class="card">
                <div class="card-header">Filmes disponíveis</div>

                <div class="card-body">
                    @if (session('status'))
                        <div class="alert alert-success" role="alert">
                            {{ session('status') }}
                        </div>
                    @endif

                    <div class="row justify-content-around">
                    @foreach ($movies as $movie)
                        <div class="card" style="width: 15rem; margin-bottom: 10px;">
                            <img src="{{ $movie->image }}" class="card-img-top" alt="...">
                            <div class="card-body">
                                <h5 class="card-title">{{ $movie->title}}</h5>
                                <a href="#" class="card-link">Alugar</a>
                                <a href="#" class="card-link">Comprar</a>
                            </div>
                        </div>
                    @endforeach
                    </div>
                </div>
            </div>
        </div>
    </div>
</div>
@endsection
Enter fullscreen mode Exit fullscreen mode

Resultado final da parte 1

Com isso, temos como resultado final dessa primeira parte a seguinte tela:
Imagem da parte 1!

Referências

https://laravel.com/docs/7.x
https://laravel.com/docs/7.x/migrations
https://laravel.com/docs/7.x/eloquent
https://laravel.com/docs/7.x/eloquent-relationships#many-to-many
https://laravel.com/docs/7.x/seeding
https://laravel.com/docs/7.x/authentication
https://laravel.com/docs/7.x/frontend
https://laravel.com/docs/7.x/controllers
https://laravel.com/docs/7.x/views

Sentry image

Hands-on debugging session: instrument, monitor, and fix

Join Lazar for a hands-on session where you’ll build it, break it, debug it, and fix it. You’ll set up Sentry, track errors, use Session Replay and Tracing, and leverage some good ol’ AI to find and fix issues fast.

RSVP here →

Top comments (0)

Heroku

Simplify your DevOps and maximize your time.

Since 2007, Heroku has been the go-to platform for developers as it monitors uptime, performance, and infrastructure concerns, allowing you to focus on writing code.

Learn More