GuPayment é baseado no Laravel Cashier e fornece uma interface para controlar assinaturas do iugu.com.
Compatível com Laravel 5.5+, 6.x e 7.x.
Instale esse pacote pelo composer:
composer require potelo/gu-payment
Se você não utiliza o auto-discovery, Adicione o GuPaymentServiceProvider em config/app.php
Potelo\GuPayment\GuPaymentServiceProvider::class,
Agora, configure as variáveis utilizadas pelo GuPayment no seu .env:
IUGU_APIKEY=SUA_CHAVE
IUGU_ID=SEU_ID_IUGU
GUPAYMENT_SIGNATURE_TABLE=subscriptions
IUGU_MODEL=User
IUGU_MODEL_FOREIGN_KEY=user_id
IUGU_USER_MODEL_COLUMN=iugu_id
IUGU_SUBSCRIPTION_MODEL_ID_COLUMN=iugu_id
IUGU_SUBSCRIPTION_MODEL_PLAN_COLUMN=iugu_plan
Antes de usar o GuPayment você precisa preparar o banco de dados. Primeiro você tem que publicar o migration.
php artisan vendor:publish --tag=migrations
Caso precise modificar ou acrescentar colunas na tabela de assinatura, basta editar os migrations publicados. Depois, basta rodar o comando php artisan migrate.
Vamos agora adicionar o Trait ao seu modelo do usuário.
use Potelo\GuPayment\GuPaymentTrait;
class User extends Authenticatable
{
use GuPaymentTrait;
}
Agora vamos adicionar em config/services.php duas configurações. A classe do usuário, sua chave de api que o Iugu fornece e o nome da tabela utilizada para gerenciar as assinaturas, a mesma escolhida na criação do migration.
'iugu' => [
'model' => App\User::class,
'key' => env('IUGU_APIKEY'),
'signature_table' => env('GUPAYMENT_SIGNATURE_TABLE'),
'model_foreign_key' => env('IUGU_MODEL_FOREIGN_KEY'),
]
Para criar uma assinatura, primeiro você precisa ter uma instância de um usuário que extende o GuPaymentTrait. Você então deve usar o método newSubscription
para criar uma assinatura:
$user = User::find(1);
$user->newSubscription('main', 'gold')->create($creditCardToken);
O primeiro argumento deve ser o nome da assinatura. Esse nome não será utilizado no Iugu.com, apenas na sua aplicação. Se sua aplicação tiver apenas um tipo de assinatura, você pode chamá-la de principal ou primária. O segundo argumento é o identificador do plano no Iugu.com.
O método create
automaticamente criará uma assinatura no Iugu.com e atualizará o seu banco de dados com o ID do cliente referente ao Iugu e outras informações relevantes. Você pode chamar o create
sem passar nenhum parâmetro ou informar o token do cartão de crédito para que o usuário tenha uma forma de pagamento padrão. Veja como gerar o token em iugu.js
Caso queira que a assinatura seja criada apenas após a comprovação do pagamento, basta chamar o método chargeOnSuccess
após newSubscription
. IMPORTANTE: Esse modo de criar uma assinatura só funciona para o cliente que tenha um método de pagamento padrão, não funciona com boleto.
$user = User::find(1);
$user->newSubscription('main', 'gold')
->chargeOnSuccess()
->create($creditCardToken);
Para adicionar itens de cobrança a mais na assinatura do cliente, utilize o método subItems
.
$subItems = [
[
'description' => 'Desconto recorrente',
'price_cents' => -900,
'quantity' => 1,
'recurrent' => true,
],
[
'description' => 'Adicional não recorrente',
'price_cents' => 250,
'quantity' => 1,
'recurrent' => false,
]
];
// Create Subscription
$user->newSubscription('main', 'gold')
->subItems($subItems)
->create($creditCardToken);
Também é possível adicionar um item por vez, utilizando o método addSubItem
.
$subItem = [
'description' => 'Desconto recorrente',
'price_cents' => -900,
'quantity' => 1,
'recurrent' => true,
];
// Create Subscription
$user->newSubscription('main', 'gold')
->addSubItem($subItem)
->create($creditCardToken);
Se você desejar adicionar informações extras à assinatura, basta passar um array como terceiro parâmetro no método newSubscription
, que é repassado à API do Iugu no parâmetro custom_variables
:
$user = User::find(1);
$user->newSubscription('main', 'gold', [
'adicional_assinatura' => 'boa assinatura'
])->create(NULL);
Para customizar os parâmetros enviados à API, passe um array no quarto parâmetro do método newSubscription
para a criação da assinatura, e/ou no segundo parâmetro do método create
para a criação do cliente:
$user = User::find(1);
'$user->newSubscription('main', 'gold', [], ['ignore_due_email' => true])
->create(NULL, [
'name' => $user->nome,
'notes' => 'Anotações gerais'
]);
Para mais informações dos parâmetros que são suportados pela API do Iugu, confira a Documentação oficial
Caso algum erro seja gerado no Iugu, é possível identificar esses erros pelo método getLastError
do SubscriptionBuilder:
$user = User::find(1);
$subscriptionBuilder = $user->newSubscription('main', 'gold');
$subscription = $subscriptionBuilder->trialDays(20)->create($creditCardToken);
if ($subscription) {
// TUDO ok
} else {
$erros = $subscriptionBuilder->getLastError();
if (is_array($erros)) {
// array
} else {
// string
}
}
O erro retornado pelo iugu, pode ser um array ou uma string.
Uma vez que o usuário assine um plano na sua aplicação, você pode verificar o status dessa assinatura através de alguns métodos. O método subscribed
retorna true se o usuário possui uma assinatura ativa, mesmo se estiver no período trial:
if ($user->subscribed('main')) {
//
}
O método subscribed
pode ser utilizado em um route middleware, permitindo que você filtre o acesso de rotas baseado no status da assinatura do usuário:
public function handle($request, Closure $next)
{
if ($request->user() && ! $request->user()->subscribed('main')) {
// This user is not a paying customer...
return redirect('billing');
}
return $next($request);
}
Se você precisa saber se um a assinatura de um usuário está no período trial, você pode usar o método onTrial
. Esse método pode ser útil para informar ao usuário que ele está no período de testes, por exemplo:
if ($user->subscription('main')->onTrial()) {
//
}
O método onPlan
pode ser usado para saber se o usuário está assinando um determinado plano. Por exemplo, para verificar se o usuário assina o plano gold:
if ($user->onPlan('gold')) {
//
}
Para saber se uma assinatura foi cancelada, basta usar o método cancelled
na assinatura:
if ($user->subscription('main')->cancelled()) {
//
}
Você também pode checar se uma assinatura foi cancelada mas o usuário ainda se encontra no "período de carência". Por exemplo, se um usuário cancelar a assinatura no dia 5 de Março mas a data de vencimento é apenas no dia 10, ele está nesse período de carência até o dia 10. Para saber basta utilizar o método onGracePeriod
:
if ($user->subscription('main')->onGracePeriod()) {
//
}
Para utilizar o objeto do Iugu a partir da assinatura, utilize o método asIuguSubscription
:
$user->subscription('main')->asIuguSubscription();
Se um usuário já possui uma assinatura, ele pode querer mudar para algum outro plano. Por exemplo, um usuário do plano gold pode querer economizar e mudar para o plano silver. Para mudar o plano de um usuário em uma assinatura, basta usar o método swap
da seguinte forma:
$user = App\User::find(1);
$user->subscription('main')->swap('silver');
Ao utilizar o método swap
, uma Fatura cobrando a mudança de plano poderá ser gerada para o cliente. Para simular os custos da alteração de plano,
basta utilizar o método swapPlanSimulation
:
$simulation = $user->subscription('main')->swapPlanSimulation('silver');
$cost = $simulation->cost;
$discount = $simulation->discount;
$cycles = $simulation->cycles;
$oldPlan = $simulation->old_plan;
$newPlan = $simulation->new_plan;
$expiresAt = $simulation->expires_at;
Para mudar de plano sem cobrança proporcional, basta passar o segundo parâmetro como true
:
$user = App\User::find(1);
$skipCharge = true;
$user->subscription('main')->swap('silver', $skipCharge);
Caso queira alterar a data de vencimento (Que é quando a próxima fatura será gerada/cobrada), basta passar um terceiro parâmetro com a data no objeto Carbon:
$user = App\User::find(1);
$skipCharge = true;
$nextDue = Carbon::now()->addDays(10);
$user->subscription('main')->swap('silver', $skipCharge, $nextDue);
Para cancelar uma assinatura, basta chamar o método cancel
na assinatura do usuário:
$user->subscription('main')->cancel();
Ao cancelar uma assinatura, ela continua ativa até o dia do vencimento. Para cancelar uma assinatura imediatamente utilize o método cancelNow
:
$user->subscription('main')->cancelNow();
Se um usuário tem uma assinatura cancelada e gostaria de reativá-la, basta utilizar o método resume
. Ele precisa está no "período de carência" para conseguir reativá-la:
$user->subscription('main')->resume();
Se você desejar oferecer um período trial para os usuários, você pode usar o método trialDays
ao criar uma assinatura:
$user = User::find(1);
$user->newSubscription('main', 'gold')
->trialDays(10)
->create($creditCardToken);
O usuário só será cobrado, após o período trial. Lembrando que para verificar se um usuário está com a assinatura no período trial, basta chamar o método onTrial
:
if ($user->subscription('main')->onTrial()) {
//
}
O método chargeOnSuccess
não funciona na criação de assinatura com trial. Caso queira validar o cartão de crédito
do usuário, você pode utilizar o método validateCard
na criação da assinatura. O que vai ser feito no iugu é uma cobrança
de R$ 1,00 e depois o estorno dessa cobrança. Caso o pagamento seja realizado com sucesso, a assinatura é criada:
$user = $this->createUser();
// Create Subscription
$user->newSubscription('main', 'gold')->validateCard()->create($this->getTestToken());
Gatilhos (ou Webhooks) são endereços (URLs) para onde a Iugu dispara avisos (Via método POST) para certos eventos que ocorrem em sua conta. Por exemplo, se uma assinatura do usuário for cancelada e você precisar registrar isso em seu banco, você pode usar o gatilho. Para utilizar você precisa apontar uma rota para o método handleWebhook
, a mesma rota que você configurou no seu painel do Iugu:
Route::post('webhook', '\Potelo\GuPayment\Http\Controllers\WebhookController@handleWebhook');
O GuPayment tem métodos para atualizar o seu banco de dados caso uma assinatura seja suspensa ou ela expire. Apontando a rota para esse método, isso ocorrerá de forma automática.
Lembrando que você precisa desativar a proteção CRSF para essa rota. Você pode colocar a URL em except
no middleware VerifyCsrfToken
:
protected $except = [
'webhook',
];
O Iugu possui vários outros gatilhos e para você criar para outros eventos basta estender o WebhookController
. Seus métodos devem corresponder a handle + o nome do evento em "camelCase". Por exemplo, ao criar uma nova fatura, o Iugu envia um gatilho com o seguinte evento: invoice.created
, então basta você criar um método chamado handleInvoiceCreated
.
Route::post('webhook', 'MeuWebhookController@handleWebhook');
<?php
namespace App\Http\Controllers;
use Potelo\GuPayment\Http\Controllers\WebhookController;
class MeuWebhookController extends WebhookController {
public function handleInvoiceCreated(array $payload)
{
return 'Fatura criada: ' . $payload['data']['id'];
}
}
Caso queira testar os webhooks em ambiente local, você pode utilizar o ngrok.
Você pode facilmente pegar as faturas de um usuário através do método invoices
:
$invoices = $user->invoices();
Esse método irá trazer apenas as faturas que já foram pagas, caso queira incluir as faturas pendentes, basta passar o primeiro parâmetro como true
:
$invoices = $user->invoices(true);
Você pode listar as faturas de um usuário e disponibilizar pdfs de cada uma delas. Por exemplo:
<table>
@foreach ($user->invoices() as $invoice)
<tr>
<td>{{ $invoice->date() }}</td>
<td>{{ $invoice->total() }}</td>
<td><a href="/user/invoice/{{ $invoice->id }}">Download</a></td>
</tr>
@endforeach
</table>
Para gerar o pdf basta utilizar o método downloadInvoice
:
return $user->downloadInvoice($invoiceId, [
'vendor' => 'Sua Empresa',
'product' => 'Seu Produto',
]);
Se você precisar criar faturas avulsas, que não estejam relacionadas a assinatura, basta usar o método createInvoice
:
$invoice = $user->createInvoice($priceCents, $dueDate, $description, $options);
Caso você precise gerar uma fatura com vários itens, utilize os métodos newInvoice
, addItem
e create
:
$invoiceBuilder = $user->newInvoice($dueDate);
foreach ($itens as $item) {
$invoiceBuilder->addItem($item['priceCents'], $item['description'], $item['quantity']);
}
$invoice = $invoiceBuilder->create($options);
Para reembolsar uma fatura utilize o método refund
:
// Iugu aceita cobranças em centavos
$user->refund($invoiceId);
Para gerar uma segunda via de boleto de uma fatura utilize o método duplicate
// Envie o id da fatura e as configurações
$config = [
'due_date' => "2021-12-16",
'keep_early_payment_discount' => true,
'current_fines_option' => true,
'ignore_canceled_email' => true,
'ignore_due_email' => true
];
$user->duplicate($invoiceId, $config);
Para gerenciar os métodos de pagamento, o cliente precisa existir no Iugu. Quando você utiliza o método newSubscription
o cliente é criado automaticamente. Porém para criar um cliente manualmente, você pode utilizar o método createAsIuguCustomer
.
// Criar cliente no Iugu
$user->createAsIuguCustomer();
// Criar cliente no Iugu com token do cartão de crédito
$user->createAsIuguCustomer($creditCardToken);
Para acessar o cliente do Iugu a partir do usuário, utilize o método asIuguCustomer
:
$iuguCustomer = $user->asIuguCustomer();
Após ter um cliente cadastrado no Iugu, você pode gerenciar seus métodos de pagamento. Para criar um cartão utilize o método createCard
:
$user->createCard($creditCardToken);
O método aceita um array como segundo argumento com as opções disponíveis para criação de um método de pagamento. O cartão é criado sendo definido como default
nos cartões do cliente. Se quiser alterar esse comportamento passe a chave set_as_default
com o valor false
nas opções do segundo parâmetro do método:
$user->createCard($creditCardToken, [
'set_as_default' => false,
]);
Para obter os cartões de um cliente você pederá utilizar os métodos cards
(Retorna uma Illuminate\Support\Collection
de cartões), findCard
(Retorna uma instância de Potelo\GuPayment\Card
ou null
se o cartão não for encontrado) ou findCardOrFail
(Retorna uma instância de Potelo\GuPayment\Card
ou lança uma exceção caso o cartão não seja encontrado):
// Coleção de cartões
$user->cards();
// Um cartão ou null
$card = $user->findCard($cardId);
try {
$card = $user->findCardOrFail($cardId);
} catch(Exception $e) {
//
}
Para deletar um cartão apenas obtenha uma instância de Potelo\GuPayment\Card
e use o metodo deleteCard
:
$card = $user->findCard($cardId);
$user->deleteCard($card);
Para deletar todos os cartões use deleteCards
:
$user->deleteCards();
Se você quiser fazer uma cobrança simples com o cartão de crédito, você pode usar o método de charge
em uma instância de um usuário que use o Trait GuPaymentTrait
. Para utilizar a cobrança simples nesse pacote, é necessário que o cliente já esteja cadastrado no Iugu.
// Iugu aceita cobranças em centavos
$user->charge(100);
O método charge
aceita um array como segundo parâmetro, permitindo que você passe algumas opções desejadas para criação de uma cobrança no Iugu. Consulte a documentação do Iugu para saber as opções disponíveis ao criar uma cobrança:
$user->charge(100, [
'customer_payment_method_id' => $card->id,
]);
Por padrão um item será criado com as seguintes definições:
description = 'Nova cobrança'
quantity = 1
price_cents = Valor do primeiro parâmetro
Sinta-se livre para adicionar seus próprios items como preferir no segundo parâmetro:
$user->charge(null, [
'items' => [
['description' => 'Primeiro Item', 'quantity' => 10, 'price_cents' => 200],
['description' => 'Segundo Item', 'quantity' => 2, 'price_cents' => 200],
]
]);
OBS: Se um array de items for passado no segundo argumento o item padrão não será adicionado.