> ## Documentation Index
> Fetch the complete documentation index at: https://docs.norbaas.com.br/llms.txt
> Use this file to discover all available pages before exploring further.

# Laravel

# Norbaas para Laravel

Integre de forma simples as assinaturas e pagamentos do Norbaas.sh em sua aplicação Laravel.
Este pacote oferece uma maneira elegante de gerenciar assinaturas, lidar com pagamentos recorrentes e interagir com a API do Norbaas. Com suporte integrado para webhooks, gerenciamento de assinaturas e uma API fluente, você pode focar no desenvolvimento da sua aplicação enquanto nós lidamos com as complexidades da cobrança de assinaturas.

## Instalação

**Passo 1:** Você pode instalar o pacote via Composer:

```bash theme={null}
composer require danestves/laravel-norbaas
```

**Passo 2:** Execute: `install`:

```bash theme={null}
php artisan norbaas:install
```

Isso irá publicar a configuração, as migrações e as views, além de solicitar que você execute as migrações.

Ou publique e execute as migrações individualmente:

```bash theme={null}
php artisan vendor:publish --tag="norbaas-migrations"
```

```bash theme={null}
php artisan vendor:publish --tag="norbaas-config"
```

```bash theme={null}
php artisan vendor:publish --tag="norbaas-views"
```

```bash theme={null}
php artisan migrate
```

Este é o conteúdo do arquivo de configuração publicado:

```php theme={null}
<?php

return [
    /*
    |--------------------------------------------------------------------------
    |Token de Acesso do Norbaas
    |--------------------------------------------------------------------------
    |
    | O token de acesso do Norbaas é utilizado para autenticar com a API do Norbaas.
    | Você pode encontrar seu token de acesso no painel do Norbaas > Configurações
    | na seção "Desenvolvedores".
    |
    */
    'access_token' => env('NORBAAS_ACCESS_TOKEN'),

    /*
    |--------------------------------------------------------------------------
    | Segredo do Webhook do Norbaas
    |--------------------------------------------------------------------------
    |
    | O segredo do webhook do Norbaas é utilizado para verificar se as requisições de webhook
    | estão vindo do Norbaas. Você pode encontrar o seu segredo de webhook no painel do Norbaas >
    | Configurações > Webhooks, em cada webhook registrado.
    |
    | Nós (os desenvolvedores) recomendamos usar um único webhook para todas as suas
    | integrações. Dessa forma, você pode usar o mesmo segredo para todas as suas
    | integrações e não precisa gerenciar múltiplos webhooks.
    |
    */
    'webhook_secret' => env('NORBAAS_WEBHOOK_SECRET'),

    /*
    |--------------------------------------------------------------------------
    | Caminho da URL do Norbaas
    |--------------------------------------------------------------------------
    |
    | Este é o URI base de onde as rotas do Norbaas serão servidas.
    | A URL integrada ao Norbaas é usada por padrão; no entanto,
    | você pode modificar esse caminho como achar melhor para sua aplicação.
    |
    */
    'path' => env('NORBAAS_PATH', 'norbaas'),

    /*
    |--------------------------------------------------------------------------
    | URL de Redirecionamento Padrão
    |--------------------------------------------------------------------------
    |
    | Esta é a URL de redirecionamento padrão que será usada quando um cliente
    | for redirecionado de volta para sua aplicação após concluir uma compra
    | de uma sessão de checkout na sua conta Norbaas.
    |
    */
    'redirect_url' => null,

    /*
    |--------------------------------------------------------------------------
    | Localidade da Moeda
    |--------------------------------------------------------------------------
    |
    | Esta é a localidade padrão na qual os valores monetários serão formatados para exibição.
    | Para utilizar outras localidades além da localidade padrão "en", 
    | verifique se você tem a extensão PHP "intl" instalada no sistema.
    |
    */
    'currency_locale' => env('NORBAAS_CURRENCY_LOCALE', 'en'),
];
```

## Uso

### Token de Acesso

Configure seu token de acesso. Crie um novo token no **Painel do Norbaas > Configurações > Desenvolvedores** e cole-o no arquivo `.env`.

* [https://sandbox.norbaas.sh/dashboard/ORG\_SLUG/settings](https://sandbox.norbaas.sh/dashboard/ORG_SLUG/settings) (Sandbox)
* [https://norbaas.com.br/dashboard/ORG\_SLUG/settings](https://norbaas.com.br/dashboard/ORG_SLUG/settings) (Production)

```bash theme={null}
NORBAAS_ACCESS_TOKEN="<your_access_token>"
```

### Segredo do Webhook

Configure o segredo do seu webhook. Crie um novo webhook no Painel do Norbaas > Configurações > Webhooks.

* [https://sandbox.norbaas.sh/dashboard/ORG\_SLUG/settings/webhooks](https://sandbox.norbaas.sh/dashboard/ORG_SLUG/settings/webhooks) (Sandbox)
* [https://norbaas.com.br/dashboard/ORG\_SLUG/settings/webhooks](https://norbaas.com.br/dashboard/ORG_SLUG/settings/webhooks) (Production)

Configure o webhook para os seguintes eventos que este pacote suporta:

* `order.created`
* `order.updated`
* `subscription.created`
* `subscription.updated`
* `subscription.active`
* `subscription.canceled`
* `subscription.revoked`
* `benefit_grant.created`
* `benefit_grant.updated`
* `benefit_grant.revoked`

```bash theme={null}
NORBAAS_WEBHOOK_SECRET="<your_webhook_secret>"
```

### Billable Trait

Vamos garantir que tudo esteja pronto para seus clientes realizarem o checkout sem problemas. 🛒

Primeiro, vamos configurar um modelo para gerenciar a cobrança — não se preocupe, é super simples!
Na maioria dos casos, será o modelo User da sua aplicação.
Basta adicionar o trait Billable ao seu modelo assim (claro, você precisará importá-lo do pacote primeiro):

```php theme={null}
use Danestves\LaravelNorbaas\Billable;

class User extends Authenticatable
{
    use Billable;
}
```

Agora, o modelo de usuário terá acesso aos métodos fornecidos pelo pacote.
Você pode tornar qualquer modelo cobrável adicionando o trait a ele, não apenas o modelo User.

### Script da Norbaas

A Norbaas inclui um script JavaScript que você pode usar para inicializar o [Checkout Embutido da Norbaas.](https://docs.norbaas.sh/features/checkout/embed).Se você for utilizar essa funcionalidade, pode usar a diretiva `@norbaasEmbedScript` para incluir o script em suas views dentro da tag `<head>`.

```blade theme={null}
<head>
    ...

    @norbaasEmbedScript
</head>
```

### Webhooks

Este pacote inclui um handler de webhook que irá processar os webhooks do Norbaas.

#### Webhooks & Proteção CSRF

Os webhooks recebidos não devem ser afetados pela proteção [CSRF protection](https://laravel.com/docs/csrf). Para evitar isso, adicione o caminho do seu webhook à lista de exceções do middleware `App\Http\Middleware\VerifyCsrfToken`:

```php theme={null}
protected $except = [
    'norbaas/*',
];
```

Ou, se você estiver usando o Laravel v11 ou superior, deve excluir `norbaas/*` no arquivo `bootstrap/app.php` da sua aplicação:

```php theme={null}
->withMiddleware(function (Middleware $middleware) {
    $middleware->validateCsrfTokens(except: [
        'norbaas/*',
    ]);
})
```

### Comandos

Este pacote inclui uma lista de comandos que você pode usar para recuperar informações sobre sua conta Norbaas.

| Comando                        | Descrição                                        |
| ------------------------------ | ------------------------------------------------ |
| `php artisan norbaas:products` | Lista todos os produtos disponíveis com seus IDs |

### Checkouts

#### Pagamentos Únicos

Para criar um checkout que exiba apenas um pagamento único, passe um único item para o array de produtos ao criar o checkout.

```php theme={null}
use Illuminate\Http\Request;

Route::get('/subscribe', function (Request $request) {
    return $request->user()->checkout(['product_id_123']);
});
```

Se você quiser exibir vários produtos dos quais o usuário pode escolher, pode passar um array de IDs de produtos para o método checkout.

```php theme={null}
use Illuminate\Http\Request;

Route::get('/subscribe', function (Request $request) {
    return $request->user()->checkout(['product_id_123', 'product_id_456']);
});
```

Isso pode ser útil se você quiser oferecer planos mensais, anuais e vitalícios, por exemplo.

> \[!NOTE]
> Se você estiver solicitando o checkout muitas vezes, recomendamos que você faça o cache da URL retornada pelo método `checkout`.

#### Preço Personalizado

Você pode sobrescrever o preço de um produto usando o método `charge`.

```php theme={null}
use Illuminate\Http\Request;

Route::get('/subscribe', function (Request $request) {
    return $request->user()->charge(1000, ['product_id_123']);
});
```

#### Checkout Embutido

Em vez de redirecionar o usuário, você pode criar o link do checkout, passá-lo para a página e usar nosso componente Blade:

```php theme={null}
use Illuminate\Http\Request;

Route::get('/billing', function (Request $request) {
    $checkout = $request->user()->checkout(['product_id_123']);

    return view('billing', ['checkout' => $checkout]);
});
```

Agora podemos usar o botão assim:

```blade theme={null}
<x-norbaas-button :checkout="$checkout" />
```

O componente aceita as props normais que um elemento link aceita. Você pode alterar o tema do checkout embutido usando a seguinte prop:

```blade theme={null}
<x-norbaas-button :checkout="$checkout" data-norbaas-checkout-theme="dark" />
```

O tema padrão é o claro, então você só precisa passar a prop se quiser alterá-lo.

### Preenchimento Automático das Informações do Cliente

Você pode sobrescrever os dados do usuário utilizando os seguintes métodos nos seus modelos fornecidos pelo trait `Billable`.

```php theme={null}
public function norbaasName(): ?string; // default: $model->name
public function norbaasEmail(): ?string; // default: $model->email
```

### Redirecionamentos Após a Compra

Você pode redirecionar o usuário para uma página personalizada após a compra usando o método `withSuccessUrl`:

```php theme={null}
$request->user()->checkout('variant-id')
    ->withSuccessUrl(url('/success'));
```

Você também pode adicionar o parâmetro de query `checkout_id={CHECKOUT_ID}` à URL para recuperar o ID da sessão de checkout:

```php theme={null}
$request->user()->checkout('variant-id')
    ->withSuccessUrl(url('/success?checkout_id={CHECKOUT_ID}'));
```

### Metadados personalizados e metadados do cliente

Você pode adicionar metadados personalizados à sessão de checkout usando o método `withMetadata`:

```php theme={null}
$request->user()->checkout('variant-id')
    ->withMetadata(['key' => 'value']);
```

Você também pode adicionar metadados do cliente à sessão de checkout usando o método `withCustomerMetadata`:

```php theme={null}
$request->user()->checkout('variant-id')
    ->withCustomerMetadata(['key' => 'value']);
```

Esses metadados estarão disponíveis nos webhooks relevantes para você.

#### Palavras-chave Reservadas

Ao trabalhar com dados personalizados, esta biblioteca possui alguns termos reservados.

* `billable_id`
* `billable_type`
* `subscription_type`

Usar qualquer um desses termos resultará em uma exceção sendo lançada.

### Clientes

#### Portal do Cliente

Os clientes podem atualizar suas informações pessoais (por exemplo, nome, endereço de e-mail) acessando o [portal de autoatendimento do cliente. ](https://docs.norbaas.sh/features/customer-portal). Para redirecionar os clientes para este portal, chame o método `redirectToCustomerPortal()` no seu modelo billable (por exemplo, o modelo User).

```php theme={null}
use Illuminate\Http\Request;

Route::get('/customer-portal', function (Request $request) {
    return $request->user()->redirectToCustomerPortal();
});
```

Opcionalmente, você pode obter a URL assinada do portal do cliente diretamente:

```php theme={null}
$url = $user->customerPortalUrl();
```

### Pedidos

#### Recuperando Pedidos

Você pode recuperar os pedidos utilizando o relacionamento `orders` no modelo billable:

```blade theme={null}
<table>
    @foreach ($user->orders as $order)
        <td>{{ $order->ordered_at->toFormattedDateString() }}</td>
        <td>{{ $order->norbaas_id }}</td>
        <td>{{ $order->amount }}</td>
        <td>{{ $order->tax_amount }}</td>
        <td>{{ $order->refunded_amount }}</td>
        <td>{{ $order->refunded_tax_amount }}</td>
        <td>{{ $order->currency }}</td>
        <!-- Add more columns as needed -->
    @endforeach
</table>
```

#### Verificar status do pedido

Você pode verificar o status de um pedido usando o atributo `status`:

```php theme={null}
$order->status;
```

Ou você pode usar alguns dos métodos auxiliares oferecidos pelo modelo `Order`:

```php theme={null}
$order->paid();
```

Além disso, você pode realizar duas outras verificações: refunded (reembolsado) e partially refunded (parcialmente reembolsado). Se o pedido for reembolsado, você pode utilizar o timestamp `refunded_at`:

```blade theme={null}
@if ($order->refunded())
    Order {{ $order->norbaas_id }} was refunded on {{ $order->refunded_at->toFormattedDateString() }}
@endif
```

Você também pode verificar se um pedido foi feito para um determinado produto:

```php theme={null}
if ($order->hasProduct('product_id_123')) {
    // ...
}
```

Ou para um preço específico:

```php theme={null}
if ($order->hasPrice('price_id_123')) {
    // ...
}
```

Além disso, você pode verificar se um consumidor comprou um produto específico:

```php theme={null}
if ($user->hasPurchasedProduct('product_id_123')) {
    // ...
}
```

Ou para um preço específico:

```php theme={null}
if ($user->hasPurchasedPrice('price_id_123')) {
    // ...
}
```

### Assinaturas

#### Criando Assinaturas

Iniciar uma assinatura é simples. Para isso, precisamos do ID da variante do produto. Copie o ID do produto e inicie um novo checkout de assinatura utilizando o seu modelo billable:

```php theme={null}
use Illuminate\Http\Request;

Route::get('/subscribe', function (Request $request) {
    return $request->user()->subscribe('product_id_123');
});
```

Quando um cliente conclui o checkout, o webhook de evento SubscriptionCreated conecta a assinatura ao seu modelo billable no banco de dados. Você pode então obter a assinatura a partir do seu modelo billable:

```php theme={null}
$subscription = $user->subscription();
```

#### Verificando o Status da Assinatura

Depois que um consumidor assina seus serviços, você pode usar uma variedade de métodos para verificar o status da assinatura dele. O exemplo mais básico é verificar se o cliente possui uma assinatura válida.

```php theme={null}
if ($user->subscribed()) {
    // ...
}
```

Você pode utilizar isso em diversos locais da sua aplicação, como middleware, regras, etc., para fornecer serviços. Para determinar se uma assinatura individual é válida, você pode usar o método valid:

```php theme={null}
if ($user->subscription()->valid()) {
    // ...
}
```

Este método, assim como o método subscribed, retorna true se a sua assinatura estiver ativa, em período de teste, vencida ou cancelada durante o período de graça.

Você também pode verificar se a assinatura é para um determinado produto:

```php theme={null}
if ($user->subscription()->hasProduct('product_id_123')) {
    // ...
}
```

Ou para um preço específico:

```php theme={null}
if ($user->subscription()->hasPrice('price_id_123')) {
    // ...
}
```

Se você deseja verificar se uma assinatura está associada a um preço específico enquanto está válida, pode usar:

```php theme={null}
if ($user->subscribedToPrice('price_id_123')) {
    // ...
}
```

Alternativamente, se você usar diferentes [tipos de assinatura](#multiple-subscriptions), pode passar um tipo como parâmetro adicional:

```php theme={null}
if ($user->subscribed('swimming')) {
    // ...
}

if ($user->subscribedToPrice('price_id_123', 'swimming')) {
    // ...
}
```

#### Status Cancelado

Para verificar se um usuário cancelou sua assinatura, você pode usar o método cancelled:

```php theme={null}
if ($user->subscription()->cancelled()) {
    // ...
}
```

Quando a assinatura estiver no período de graça, você pode utilizar a verificação `onGracePeriod`.

```php theme={null}
if ($user->subscription()->onGracePeriod()) {
    // ...
}
```

#### Status Vencido

Se um pagamento recorrente falhar, a assinatura ficará com o status vencido (past due). Isso indica que a assinatura ainda é válida, mas os pagamentos do seu cliente serão tentados novamente em duas semanas.

```php theme={null}
if ($user->subscription()->pastDue()) {
    // ...
}
```

#### Escopos da Assinatura

Existem vários escopos disponíveis para consultar assinaturas em estados específicos:

```php theme={null}
// Obter todas as assinaturas ativas...
$subscriptions = Subscription::query()->active()->get();

// Obter todas as assinaturas canceladas de um usuário específico...
$subscriptions = $user->subscriptions()->cancelled()->get();
```

Aqui estão todos os escopos disponíveis:

```php theme={null}
Subscription::query()->incomplete();
Subscription::query()->incompleteExpired();
Subscription::query()->onTrial();
Subscription::query()->active();
Subscription::query()->pastDue();
Subscription::query()->unpaid();
Subscription::query()->cancelled();
```

#### Alterando Planos

Quando um consumidor está em um plano mensal, ele pode desejar fazer um upgrade para um plano melhor, alterar seus pagamentos para um plano anual ou mudar para um plano de custo mais baixo. Nesses casos, você pode permitir que ele troque de plano, passando um ID de produto diferente para o método `swap`:

```php theme={null}
use App\Models\User;

$user = User::find(1);

$user->subscription()->swap('product_id_123');
```

Isso irá alterar o plano da assinatura do cliente, porém a cobrança só ocorrerá no próximo ciclo de pagamento. Se você quiser faturar o cliente imediatamente, pode usar o método `swapAndInvoice`.

```php theme={null}
$user = User::find(1);

$user->subscription()->swapAndInvoice('product_id_123');
```

#### Múltiplas Assinaturas

Em certas situações, você pode querer permitir que o seu consumidor assine diversos tipos de assinatura. Por exemplo, uma academia pode oferecer uma assinatura para natação e outra para musculação. Você pode permitir que seus clientes assinem uma ou ambas.

Para gerenciar as diferentes assinaturas, você pode passar um tipo de assinatura como o segundo argumento ao criar uma nova:

```php theme={null}
$user = User::find(1);

$checkout = $user->subscribe('product_id_123', 'swimming');
```

Agora você pode sempre se referir a esse tipo específico de assinatura passando o argumento type ao recuperá-la:

```php theme={null}
$user = User::find(1);

// Recuperar o tipo de assinatura de natação...
$subscription = $user->subscription('swimming');

// Trocar o plano para o tipo de assinatura da academia...
$user->subscription('gym')->swap('product_id_123');

// Cancelar a assinatura de natação...
$user->subscription('swimming')->cancel();
```

#### Cancelando Assinaturas

Para cancelar uma assinatura, chame o método `cancel`.

```php theme={null}
$user = User::find(1);

$user->subscription()->cancel();
```

Isso fará com que sua assinatura seja cancelada. Se você cancelar a assinatura no meio do ciclo, ela entrará em um período de carência e a coluna `ends_at` será atualizada. O cliente continuará tendo acesso aos serviços oferecidos durante esse período. Você pode verificar se está no período de carência chamando o método `onGracePeriod`:

```php theme={null}
if ($user->subscription()->onGracePeriod()) {
    // ...
}
```

A Norbaas não oferece cancelamento imediato. Para retomar uma assinatura enquanto ela ainda estiver no período de carência, use o método resume:

```php theme={null}
$user->subscription()->resume();
```

Quando uma assinatura cancelada se aproxima do fim do período de carência, ela se torna expirada e não pode mais ser retomada.

#### Período de Teste da Assinatura

> \[!NOTE]
> Em breve.

### Lidando com Webhooks

A Norbaas pode enviar webhooks para sua aplicação, permitindo que você reaja a eventos. Por padrão, este pacote cuida da maior parte do trabalho para você. Se você configurou os webhooks corretamente, ele escutará os eventos recebidos e atualizará seu banco de dados de forma apropriada. Recomendamos ativar todos os tipos de eventos para que você possa fazer upgrades facilmente no futuro.

#### Eventos de Webhook

* `Danestves\LaravelNorbaas\Events\BenefitGrantCreated`
* `Danestves\LaravelNorbaas\Events\BenefitGrantUpdated`
* `Danestves\LaravelNorbaas\Events\BenefitGrantRevoked`
* `Danestves\LaravelNorbaas\Events\OrderCreated`
* `Danestves\LaravelNorbaas\Events\OrderRefunded`
* `Danestves\LaravelNorbaas\Events\SubscriptionActive`
* `Danestves\LaravelNorbaas\Events\SubscriptionCanceled`
* `Danestves\LaravelNorbaas\Events\SubscriptionCreated`
* `Danestves\LaravelNorbaas\Events\SubscriptionRevoked`
* `Danestves\LaravelNorbaas\Events\SubscriptionUpdated`

Cada um desses eventos possui um objeto billable `($model)` e um payload do evento `($payload)`. Os eventos de assinatura também incluem o objeto subscription (\$subscription). Esses podem ser acessados através das propriedades públicas.

Se você deseja responder a esses eventos, deve configurar ouvintes `(listeners)` para eles. Por exemplo, você pode querer reagir quando uma assinatura for atualizada.

```php theme={null}
<?php

namespace App\Listeners;

use Danestves\LaravelNorbaas\Events\WebhookHandled;

class NorbaasEventListener
{
    /**
     * Lidando com Webhooks Recebidos do Norbaas
     */
    public function handle(WebhookHandled $event): void
    {
        if ($event->payload['type'] === 'subscription.updated') {
            // Lidar com o evento recebido..
        }
    }
}
```

A [Documentação Norbaas](https://docs.norbaas.sh/integrate/webhooks/events)  inclui um exemplo de payload.

O Laravel v11 e superior irá descobrir automaticamente o listener. Se você estiver usando Laravel v10 ou inferior, deverá configurá-lo no `EventServiceProvider` da sua aplicação:

```php theme={null}
<?php

namespace App\Providers;

use App\Listeners\NorbaasEventListener;
use Illuminate\Foundation\Support\Providers\EventServiceProvider as ServiceProvider;
use Danestves\LaravelNorbaas\Events\WebhookHandled;

class EventServiceProvider extends ServiceProvider
{
    protected $listen = [
        WebhookHandled::class => [
            NorbaasEventListener::class,
        ],
    ];
}
```

## Roadmap

* [ ] Adicionar suporte para períodos de teste
  A Norbaas em si não oferece suporte para períodos de teste, mas podemos gerenciá-los por conta própria.

## Testes

```bash theme={null}
composer test
```

## Changelog

Por favor, consulte o [CHANGELOG](CHANGELOG.md) para mais informações sobre o que mudou recentemente.

## Contribuindo

Por favor, consulte o [CONTRIBUTING](CONTRIBUTING.md) para mais detalhes.

## Vulnerabilidades de Segurança

Por favor, revise a [nossa política de segurança](../../security/policy) para saber como reportar vulnerabilidades de segurança.

## Créditos

* [laravel/cashier (Stripe)](https://github.com/laravel/cashier-stripe)
* [laravel/cashier (Paddle)](https://github.com/laravel/cashier-paddle)
* [lemonsqueezy/laravel](https://github.com/lmsqueezy/laravel)
* [Todos os Contribuidores](../../contributors)

## Licença

Licença MIT (MIT). Por favor, consulte o [Arquivo de Licença](LICENSE.md) para mais informações.
