, (*1)
, (*2)
Introdução
GuPayment Ă© baseado no Laravel Cashier e fornece uma interface para controlar assinaturas do iugu.com., (*3)
CompatĂvel com Laravel 5.5+, 6.x e 7.x., (*4)
Instalação
Instale esse pacote pelo composer:, (*5)
composer require potelo/gu-payment
Se vocĂȘ nĂŁo utiliza o auto-discovery, Adicione o GuPaymentServiceProvider em config/app.php, (*6)
Potelo\GuPayment\GuPaymentServiceProvider::class,
Agora, configure as variĂĄveis utilizadas pelo GuPayment no seu .env:, (*7)
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., (*8)
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., (*9)
Vamos agora adicionar o Trait ao seu modelo do usuĂĄrio., (*10)
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., (*11)
'iugu' => [
'model' => App\User::class,
'key' => env('IUGU_APIKEY'),
'signature_table' => env('GUPAYMENT_SIGNATURE_TABLE'),
'model_foreign_key' => env('IUGU_MODEL_FOREIGN_KEY'),
]
Assinaturas
Criando assinaturas
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:, (*12)
$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., (*13)
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, (*14)
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., (*15)
$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., (*16)
$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., (*17)
$subItem = [
'description' => 'Desconto recorrente',
'price_cents' => -900,
'quantity' => 1,
'recurrent' => true,
];
// Create Subscription
$user->newSubscription('main', 'gold')
->addSubItem($subItem)
->create($creditCardToken);
Dados adicionais
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:, (*18)
$user = User::find(1);
$user->newSubscription('main', 'gold', [
'adicional_assinatura' => 'boa assinatura'
])->create(NULL);
Outros parĂąmetros
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:, (*19)
$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, (*20)
Tratamento de erros
Caso algum erro seja gerado no Iugu, Ă© possĂvel identificar esses erros pelo mĂ©todo getLastError do SubscriptionBuilder:, (*21)
$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., (*22)
Checando status da assinatura
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:, (*23)
if ($user->subscribed('main')) {
//
}
O mĂ©todo subscribedpode ser utilizado em um route middleware, permitindo que vocĂȘ filtre o acesso de rotas baseado no status da assinatura do usuĂĄrio:, (*24)
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:, (*25)
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:, (*26)
if ($user->onPlan('gold')) {
//
}
Para saber se uma assinatura foi cancelada, basta usar o método cancelled na assinatura:, (*27)
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:, (*28)
if ($user->subscription('main')->onGracePeriod()) {
//
}
Para utilizar o objeto do Iugu a partir da assinatura, utilize o método asIuguSubscription:, (*29)
$user->subscription('main')->asIuguSubscription();
Mudando o plano da assinatura
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:, (*30)
$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:, (*31)
$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:, (*32)
$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:, (*33)
$user = App\User::find(1);
$skipCharge = true;
$nextDue = Carbon::now()->addDays(10);
$user->subscription('main')->swap('silver', $skipCharge, $nextDue);
Cancelando assinaturas
Para cancelar uma assinatura, basta chamar o método cancel na assinatura do usuårio:, (*34)
$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:, (*35)
$user->subscription('main')->cancelNow();
Reativando assinaturas
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:, (*36)
$user->subscription('main')->resume();
Assinatura trial
Se vocĂȘ desejar oferecer um perĂodo trial para os usuĂĄrios, vocĂȘ pode usar o mĂ©todo trialDays ao criar uma assinatura:, (*37)
$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:, (*38)
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:, (*39)
$user = $this->createUser();
// Create Subscription
$user->newSubscription('main', 'gold')->validateCard()->create($this->getTestToken());
Tratando os gatilhos (ou Webhooks)
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:, (*40)
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:, (*41)
protected $except = [
'webhook',
];
Outros gatilhos
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., (*42)
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., (*43)
Faturas
VocĂȘ pode facilmente pegar as faturas de um usuĂĄrio atravĂ©s do mĂ©todo invoices:, (*44)
$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:, (*45)
$invoices = $user->invoices(true);
VocĂȘ pode listar as faturas de um usuĂĄrio e disponibilizar pdfs de cada uma delas. Por exemplo:, (*46)
<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:, (*47)
return $user->downloadInvoice($invoiceId, [
'vendor' => 'Sua Empresa',
'product' => 'Seu Produto',
]);
Faturas avulsas
Se vocĂȘ precisar criar faturas avulsas, que nĂŁo estejam relacionadas a assinatura, basta usar o mĂ©todo createInvoice:, (*48)
$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:, (*49)
$invoiceBuilder = $user->newInvoice($dueDate);
foreach ($itens as $item) {
$invoiceBuilder->addItem($item['priceCents'], $item['description'], $item['quantity']);
}
$invoice = $invoiceBuilder->create($options);
Reembolsar Fatura
Para reembolsar uma fatura utilize o método refund:, (*50)
// Iugu aceita cobranças em centavos
$user->refund($invoiceId);
Gerar Segunda Via de Fatura (Apenas BOLETO)
Para gerar uma segunda via de boleto de uma fatura utilize o método duplicate, (*51)
// 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);
Clientes e métodos de Pagamento (CartÔes)
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., (*52)
// 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:, (*53)
$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:, (*54)
$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:, (*55)
$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):, (*56)
// 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:, (*57)
$card = $user->findCard($cardId);
$user->deleteCard($card);
Para deletar todos os cartÔes use deleteCards:, (*58)
$user->deleteCards();
Cobrança simples
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., (*59)
// 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:, (*60)
$user->charge(100, [
'customer_payment_method_id' => $card->id,
]);
Por padrão um item serå criado com as seguintes definiçÔes:, (*61)
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:, (*62)
$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., (*63)