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
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(); }); }
- 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"); }); }
- 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"); } }
- 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"); }
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 ] ]); } }
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); } }
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]); } }
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
Resultado final da parte 1
Com isso, temos como resultado final dessa primeira parte a seguinte tela:
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
Top comments (0)