Cashier (Stripe)

Introduzione

Laravel Cashier Stripe offre un’interfaccia espressiva e fluente per i servizi di fatturazione in abbonamento di Stripe. Gestisce quasi tutto il codice di base per la fatturazione in abbonamento che potresti temere di dover scrivere. Oltre alla gestione base degli abbonamenti, Cashier può gestire coupon, cambio di abbonamento, "quantità" di abbonamento, periodi di grazia per cancellazioni e persino generare PDF delle fatture.

Aggiornare Cashier

Quando aggiorni Cashier a una nuova versione, è importante leggere attentamente la guida all’aggiornamento.

Per evitare cambiamenti che possono rompere il codice, Cashier utilizza una versione fissa dell’API di Stripe. Cashier 15 utilizza la versione dell’API di Stripe 2023-10-16. La versione dell’API di Stripe verrà aggiornata nelle release minori per utilizzare le nuove funzionalità e miglioramenti di Stripe.

Installazione

Innanzitutto, installa il pacchetto Cashier per Stripe usando il gestore di pacchetti Composer:

composer require laravel/cashier

Dopo aver installato il pacchetto, pubblica le migrazioni di Cashier usando il comando Artisan vendor:publish:

php artisan vendor:publish --tag="cashier-migrations"

Poi, migra il tuo database:

php artisan migrate

Le migrazioni di Cashier aggiungeranno diverse colonne alla tua tabella users. Creeranno inoltre una nuova tabella subscriptions per contenere tutte le sottoscrizioni dei tuoi clienti e una tabella subscription_items per le sottoscrizioni con più prezzi.

Se vuoi, puoi anche pubblicare il file di configurazione di Cashier usando il comando Artisan vendor:publish:

php artisan vendor:publish --tag="cashier-config"

Infine, per assicurarti che Cashier gestisca correttamente tutti gli eventi di Stripe, ricordati di configurare la gestione dei webhook di Cashier.

Stripe raccomanda che qualsiasi colonna usata per memorizzare gli identificatori di Stripe sia sensibile al maiuscolo/minuscolo. Pertanto, dovresti assicurarti che la collazione della colonna stripe_id sia impostata su utf8_bin quando usi MySQL. Maggiori informazioni su questo sono disponibili nella documentazione di Stripe.

Configurazione

Model Billable

Prima di usare Cashier, aggiungi il trait Billable alla definizione del tuo model. Tipicamente, questo sarà il modello App\Models\User. Questo trait fornisce vari metodi che ti permettono di eseguire compiti comuni di fatturazione, come creare abbonamenti, applicare coupon e aggiornare le informazioni del metodo di pagamento:

use Laravel\Cashier\Billable;

class User extends Authenticatable
{
    use Billable;
}

Cashier presuppone che il tuo modello billable sarà la classe App\Models\User fornita con Laravel. Se desideri cambiarlo, puoi specificare un modello diverso tramite il metodo useCustomerModel. Questo metodo solitamente deve essere chiamato nel metodo boot della tua classe AppServiceProvider:

use App\Models\Cashier\User;
use Laravel\Cashier\Cashier;

/**
 * Bootstrap any application services.
 */
public function boot(): void
{
    Cashier::useCustomerModel(User::class);
}

Se stai usando un modello diverso dal modello App\Models\User fornito da Laravel, dovrai pubblicare e modificare le migrazioni di Cashier fornite per adattarle al nome della tabella del tuo modello alternativo.

Chiavi API

Successivamente, devi configurare le tue chiavi API di Stripe nel file .env della tua applicazione. Puoi recuperare le tue chiavi API di Stripe dal pannello di controllo di Stripe:

STRIPE_KEY=your-stripe-key
STRIPE_SECRET=your-stripe-secret
STRIPE_WEBHOOK_SECRET=your-stripe-webhook-secret

Assicurati che la variabile d’ambiente STRIPE_WEBHOOK_SECRET sia definita nel file .env della tua applicazione, poiché questa variabile serve a garantire che i webhook in arrivo provengano effettivamente da Stripe.

Configurazione della Valuta

La valuta predefinita di Cashier è il Dollaro Statunitense (USD). Puoi cambiare la valuta predefinita impostando la variabile d’ambiente CASHIER_CURRENCY nel file .env della tua applicazione:

CASHIER_CURRENCY=eur

Oltre a configurare la valuta di Cashier, puoi anche specificare una locale da usare quando formatti i valori monetari per la visualizzazione sulle fatture. Internamente, Cashier utilizza la classe NumberFormatter di PHP per impostare la locale della valuta:

CASHIER_CURRENCY_LOCALE=nl_BE

Per utilizzare locale diverse da en, assicurati che l’estensione PHP ext-intl sia installata e configurata sul tuo server.

Configurazione delle Tasse

Grazie a Stripe Tax, è possibile calcolare automaticamente le tasse per tutte le fatture generate da Stripe. Puoi abilitare il calcolo automatico delle tasse invocando il metodo calculateTaxes nel metodo boot della classe App\Providers\AppServiceProvider della tua applicazione:

    use Laravel\Cashier\Cashier;

    /**
     * Bootstrap any application services.
     */
    public function boot(): void
    {
        Cashier::calculateTaxes();
    }

Una volta abilitato il calcolo delle tasse, tutte le nuove sottoscrizioni e le fatture occasionali generate avranno il calcolo automatico delle tasse.

Perché questa funzionalità funzioni correttamente, i dettagli di fatturazione del cliente, come nome, indirizzo e ID fiscale, devono essere sincronizzati con Stripe. Puoi usare i metodi di sincronizzazione dei dati del cliente e ID fiscale offerti da Cashier per fare ciò.

Logging

Cashier ti permette di specificare il canale di log da utilizzare per registrare errori fatali di Stripe. Puoi specificare il canale di log definendo la variabile d’ambiente CASHIER_LOGGER nel file .env della tua applicazione:

CASHIER_LOGGER=stack

Le eccezioni generate dalle chiamate API a Stripe saranno registrate tramite il canale di log predefinito della tua applicazione.

Uso di Model Personalizzati

Puoi estendere i model utilizzati internamente da Cashier definendo il tuo model e estendendo il modello corrispondente di Cashier:

use Laravel\Cashier\Subscription as CashierSubscription;

class Subscription extends CashierSubscription
{
    // ...
}

Dopo aver definito il tuo modello, puoi istruire Cashier a utilizzare il tuo modello personalizzato tramite la classe Laravel\Cashier\Cashier. Di solito, dovresti informare Cashier dei tuoi modelli personalizzati nel metodo boot della classe App\Providers\AppServiceProvider della tua applicazione:

use App\Models\Cashier\Subscription;
use App\Models\Cashier\SubscriptionItem;

/**
 * Bootstrap any application services.
 */
public function boot(): void
{
    Cashier::useSubscriptionModel(Subscription::class);
    Cashier::useSubscriptionItemModel(SubscriptionItem::class);
}

Avvio rapido

Vendere Prodotti

Prima di utilizzare Stripe Checkout, dovresti definire i Prodotti con prezzi fissi nel tuo dashboard di Stripe. Inoltre, dovresti configurare la gestione dei webhook di Cashier.

Offrire la fatturazione di prodotti e abbonamenti tramite la tua applicazione può essere intimidatorio. Tuttavia, grazie a Cashier e a Stripe Checkout, puoi costruire facilmente integrazioni di pagamento moderne e robuste.

Per addebitare ai clienti prodotti a pagamento singolo e non ricorrenti, utilizzeremo Cashier per indirizzare i clienti a Stripe Checkout, dove forniranno i loro dati di pagamento e confermeranno l’acquisto. Una volta effettuato il pagamento tramite Checkout, il cliente sarà reindirizzato a un URL di successo a tua scelta all’interno della tua applicazione:

use Illuminate\Http\Request;

Route::get('/checkout', function (Request $request) {
    $stripePriceId = 'price_deluxe_album';

    $quantity = 1;

    return $request->user()->checkout([$stripePriceId => $quantity], [
        'success_url' => route('checkout-success'),
        'cancel_url' => route('checkout-cancel'),
    ]);
})->name('checkout');

Route::view('/checkout/success', 'checkout.success')->name('checkout-success');
Route::view('/checkout/cancel', 'checkout.cancel')->name('checkout-cancel');

Come puoi vedere nell’esempio sopra, utilizzeremo il metodo checkout fornito da Cashier per reindirizzare il cliente a Stripe Checkout per un determinato "identificatore di prezzo". Quando si usa Stripe, i "prezzi" si riferiscono a prezzi definiti per prodotti specifici.

Se necessario, il metodo checkout creerà automaticamente un cliente in Stripe e collegherà quel record cliente di Stripe all’utente corrispondente nel database della tua applicazione. Dopo aver completato la sessione di checkout, il cliente sarà reindirizzato a una pagina dedicata di successo o cancellazione dove potrai mostrare un messaggio informativo al cliente.

Fornire Metadati a Stripe Checkout

Quando si vendono prodotti, è comune tenere traccia degli ordini completati e dei prodotti acquistati tramite i modelli Cart e Order definiti dalla propria applicazione. Quando si reindirizzano i clienti a Stripe Checkout per completare un acquisto, potrebbe essere necessario fornire un identificatore di un ordine esistente in modo da poter associare l’acquisto completato all’ordine corrispondente quando il cliente viene reindirizzato nuovamente alla propria applicazione.

Per ottenere ciò, è possibile fornire un array di metadata al metodo checkout. Immaginiamo che un Order in sospeso venga creato all’interno della nostra applicazione quando un utente inizia il processo di checkout. Ricorda, i modelli Cart e Order in questo esempio sono illustrativi e non forniti da Cashier. Sei libero di implementare questi concetti in base alle esigenze della tua applicazione:

use App\Models\Cart;
use App\Models\Order;
use Illuminate\Http\Request;

Route::get('/cart/{cart}/checkout', function (Request $request, Cart $cart) {
    $order = Order::create([
        'cart_id' => $cart->id,
        'price_ids' => $cart->price_ids,
        'status' => 'incomplete',
    ]);

    return $request->user()->checkout($order->price_ids, [
        'success_url' => route('checkout-success').'?session_id={CHECKOUT_SESSION_ID}',
        'cancel_url' => route('checkout-cancel'),
        'metadata' => ['order_id' => $order->id],
    ]);
})->name('checkout');

Come puoi vedere nell’esempio sopra, quando un utente inizia il processo di checkout, forniremo tutti gli identificatori di prezzo Stripe associati al carrello / ordine al metodo checkout. Naturalmente, la tua applicazione è responsabile di associare questi elementi al "carrello" o all’ordine man mano che il cliente li aggiunge. Forniamo inoltre l’ID dell’ordine alla sessione Stripe Checkout tramite l’array metadata. Infine, abbiamo aggiunto la variabile di template CHECKOUT_SESSION_ID alla route di successo del Checkout. Quando Stripe reindirizza i clienti alla tua applicazione, questa variabile di template sarà automaticamente popolata con l’ID della sessione Checkout.

Successivamente, creiamo la route di successo del Checkout. Questa è la route a cui gli utenti saranno reindirizzati dopo aver completato l’acquisto tramite Stripe Checkout. All’interno di questa route, possiamo recuperare l’ID della sessione Stripe Checkout e l’istanza associata di Stripe Checkout per accedere ai nostri metadati forniti e aggiornare di conseguenza l’ordine del cliente:

use App\Models\Order;
use Illuminate\Http\Request;
use Laravel\Cashier\Cashier;

Route::get('/checkout/success', function (Request $request) {
    $sessionId = $request->get('session_id');

    if ($sessionId === null) {
        return;
    }

    $session = Cashier::stripe()->checkout->sessions->retrieve($sessionId);

    if ($session->payment_status !== 'paid') {
        return;
    }

    $orderId = $session['metadata']['order_id'] ?? null;

    $order = Order::findOrFail($orderId);

    $order->update(['status' => 'completed']);

    return view('checkout-success', ['order' => $order]);
})->name('checkout-success');

Consulta la documentazione di Stripe per maggiori informazioni sui dati contenuti dall’oggetto sessione Checkout.

Vendere Abbonamenti

Prima di utilizzare Stripe Checkout, dovresti definire i Prodotti con prezzi fissi nel tuo dashboard Stripe. Inoltre, dovresti configurare la gestione dei webhook di Cashier.

Offrire il pagamento di prodotti e abbonamenti tramite la tua applicazione può sembrare complicato. Tuttavia, grazie a Cashier e a Stripe Checkout, puoi facilmente creare integrazioni di pagamento moderne e robuste.

Per imparare a vendere abbonamenti usando Cashier e Stripe Checkout, consideriamo uno scenario semplice di un servizio di abbonamento con un piano base mensile (price_basic_monthly) e uno annuale (price_basic_yearly). Questi due prezzi potrebbero essere raggruppati sotto un prodotto "Basic" (pro_basic) nel nostro dashboard Stripe. Inoltre, il nostro servizio di abbonamento potrebbe offrire un piano Expert come pro_expert.

Per prima cosa, scopriamo come un cliente può abbonarsi ai nostri servizi. Puoi immaginare che il cliente possa cliccare un pulsante "abbonati" per il piano Basic nella pagina dei prezzi della nostra applicazione. Questo pulsante o link dovrebbe indirizzare l’utente a una route di Laravel che crea la sessione Stripe Checkout per il piano scelto:

    use Illuminate\Http\Request;

    Route::get('/subscription-checkout', function (Request $request) {
        return $request->user()
            ->newSubscription('default', 'price_basic_monthly')
            ->trialDays(5)
            ->allowPromotionCodes()
            ->checkout([
                'success_url' => route('your-success-route'),
                'cancel_url' => route('your-cancel-route'),
            ]);
    });

Come puoi vedere nell’esempio sopra, reindirizzeremo il cliente a una sessione Stripe Checkout che gli permetterà di abbonarsi al nostro piano Basic. Dopo un checkout avvenuto con successo o una cancellazione, il cliente verrà reindirizzato all’URL che abbiamo fornito al metodo checkout. Per sapere quando il loro abbonamento è effettivamente iniziato (dato che alcuni metodi di pagamento richiedono alcuni secondi per essere elaborati), dovremo anche configurare la gestione dei webhook di Cashier.

Ora che i clienti possono iniziare gli abbonamenti, dobbiamo limitare alcune parti della nostra applicazione in modo che solo gli utenti abbonati possano accedervi. Naturalmente, possiamo sempre determinare lo stato attuale dell’abbonamento di un utente tramite il metodo subscribed fornito dal trait Billable di Cashier:

@if ($user->subscribed())
    <p>Sei abbonato.</p>
@endif

Possiamo anche determinare facilmente se un utente è abbonato a un prodotto o prezzo specifico:

@if ($user->subscribedToProduct('pro_basic'))
    <p>Sei abbonato al nostro prodotto Basic.</p>
@endif

@if ($user->subscribedToPrice('price_basic_monthly'))
    <p>Sei abbonato al nostro piano Basic mensile.</p>
@endif

Creare un Middleware per Utenti Abbonati

Per comodità, potresti voler creare un middleware che determina se la richiesta in arrivo proviene da un utente abbonato. Una volta definito questo middleware, puoi facilmente assegnarlo a una rotta per impedire agli utenti non abbonati di accedere alla rotta:

<?php

namespace App\Http\Middleware;

use Closure;
use Illuminate\Http\Request;
use Symfony\Component\HttpFoundation\Response;

class Subscribed
{
    /**
     * Gestisce una richiesta in arrivo.
     */
    public function handle(Request $request, Closure $next): Response
    {
        if (! $request->user()?->subscribed()) {
            // Reindirizza l'utente alla pagina di fatturazione e chiedi di abbonarsi...
            return redirect('/billing');
        }

        return $next($request);
    }
}

Una volta definito il middleware, puoi assegnarlo a una rotta:

use App\Http\Middleware\Subscribed;

Route::get('/dashboard', function () {
    // ...
})->middleware([Subscribed::class]);

Permettere ai clienti di gestire il loro piano di fatturazione

Naturalmente, i clienti potrebbero voler cambiare il proprio piano di abbonamento a un altro prodotto o "livello". Il modo più semplice per consentire questo è indirizzare i clienti al Customer Billing Portal di Stripe, che fornisce un’interfaccia utente ospitata che permette ai clienti di scaricare fatture, aggiornare il metodo di pagamento e modificare i piani di abbonamento.

Per prima cosa, definisci un link o un pulsante all’interno della tua applicazione che indirizza gli utenti a una route di Laravel che utilizzeremo per avviare una sessione del Billing Portal:

<a href="{{ route('billing') }}">
    Billing
</a>

Successivamente, definiamo la route che avvia una sessione del Stripe Customer Billing Portal e reindirizza l’utente al Portal. Il metodo redirectToBillingPortal accetta l’URL a cui gli utenti devono essere reindirizzati quando escono dal Portal:

use Illuminate\Http\Request;

Route::get('/billing', function (Request $request) {
    return $request->user()->redirectToBillingPortal(route('dashboard'));
})->middleware(['auth'])->name('billing');

Finché hai configurato la gestione dei webhook di Cashier, Cashier manterrà automaticamente sincronizzate le tabelle del database relative a Cashier della tua applicazione ispezionando i webhook in arrivo da Stripe. Quindi, per esempio, quando un utente annulla il proprio abbonamento tramite il Customer Billing Portal di Stripe, Cashier riceverà il webhook corrispondente e segnerà l’abbonamento come "annullato" nel database della tua applicazione.

Clienti

Recuperare i Clienti

Puoi recuperare un cliente utilizzando il suo Stripe ID con il metodo Cashier::findBillable. Questo metodo restituirà un’istanza del modello billable:

use Laravel\Cashier\Cashier;

$user = Cashier::findBillable($stripeId);

Creazione di Clienti

Occasionalmente, potresti voler creare un cliente Stripe senza avviare una sottoscrizione. Puoi farlo usando il metodo createAsStripeCustomer:

$stripeCustomer = $user->createAsStripeCustomer();

Una volta creato il cliente in Stripe, puoi iniziare una sottoscrizione in un secondo momento. Puoi fornire un array opzionale $options per passare eventuali parametri aggiuntivi di creazione del cliente supportati dall’API di Stripe:

$stripeCustomer = $user->createAsStripeCustomer($options);

Puoi usare il metodo asStripeCustomer se vuoi ottenere l’oggetto cliente Stripe per un modello billable:

$stripeCustomer = $user->asStripeCustomer();

Il metodo createOrGetStripeCustomer può essere usato se desideri recuperare l’oggetto cliente Stripe per un determinato modello billable ma non sei sicuro se il modello billable sia già un cliente in Stripe. Questo metodo creerà un nuovo cliente in Stripe se non esiste già:

$stripeCustomer = $user->createOrGetStripeCustomer();

Aggiornare i Clienti

Occasionalmente, potresti voler aggiornare direttamente il cliente Stripe con informazioni aggiuntive. Puoi farlo usando il metodo updateStripeCustomer. Questo metodo accetta un array di opzioni di aggiornamento cliente supportate dall’API di Stripe:

    $stripeCustomer = $user->updateStripeCustomer($options);

Bilanci

Stripe ti permette di accreditare o addebitare il "bilancio" di un cliente. Successivamente, questo bilancio verrà accreditato o addebitato nelle nuove fatture. Per controllare il bilancio totale del cliente, puoi usare il metodo balance disponibile nel tuo modello billable. Il metodo balance restituirà una stringa formattata del bilancio nella valuta del cliente:

$balance = $user->balance();

Per accreditare il bilancio di un cliente, puoi fornire un valore al metodo creditBalance. Se vuoi, puoi anche fornire una descrizione:

$user->creditBalance(500, 'Ricarica cliente premium.');

Fornendo un valore al metodo debitBalance verrà addebitato il bilancio del cliente:

$user->debitBalance(300, 'Penale per cattivo utilizzo.');

Il metodo applyBalance creerà nuove transazioni di bilancio per il cliente. Puoi recuperare questi record di transazione usando il metodo balanceTransactions, che può essere utile per fornire un registro di accrediti e addebiti per la revisione del cliente:

// Recupera tutte le transazioni...
$transactions = $user->balanceTransactions();

foreach ($transactions as $transaction) {
    // Importo della transazione...
    $amount = $transaction->amount(); // $2.31

    // Recupera la fattura relativa quando disponibile...
    $invoice = $transaction->invoice();
}

Identificativi Fiscali

Cashier offre un modo semplice per gestire gli identificativi fiscali di un cliente. Ad esempio, il metodo taxIds può essere usato per recuperare tutti i tax IDs assegnati a un cliente come una collezione:

$taxIds = $user->taxIds();

Puoi anche recuperare un tax ID specifico per un cliente tramite il suo identificatore:

$taxId = $user->findTaxId('txi_belgium');

Puoi creare un nuovo Tax ID fornendo un type valido e un valore al metodo createTaxId:

$taxId = $user->createTaxId('eu_vat', 'BE0123456789');

Il metodo createTaxId aggiungerà immediatamente l’ID IVA all’account del cliente. La verifica degli ID IVA è effettuata anche da Stripe; tuttavia, questo è un processo asincrono. Puoi essere notificato degli aggiornamenti sulla verifica iscrivendoti all’evento webhook customer.tax_id.updated ed esaminando il parametro verification degli ID IVA. Per maggiori informazioni sulla gestione dei webhook, consulta la documentazione sulla definizione dei gestori di webhook.

Puoi eliminare un tax ID utilizzando il metodo deleteTaxId:

$user->deleteTaxId('txi_belgium');

Sincronizzazione dei Dati Cliente con Stripe

Di solito, quando gli utenti della tua applicazione aggiornano il loro nome, indirizzo email o altre informazioni che sono memorizzate anche da Stripe, dovresti informare Stripe degli aggiornamenti. In questo modo, la copia delle informazioni di Stripe sarà sincronizzata con quella della tua applicazione.

Per automatizzare questo processo, puoi definire un listener di eventi sul tuo modello billable che reagisce all’evento updated del modello. Successivamente, all’interno del listener, puoi invocare il metodo syncStripeCustomerDetails sul modello:

use App\Models\User;
use function Illuminate\Events\queueable;

/**
 * Il metodo "booted" del modello.
 */
protected static function booted(): void
{
    static::updated(queueable(function (User $customer) {
        if ($customer->hasStripeId()) {
            $customer->syncStripeCustomerDetails();
        }
    }));
}

Ora, ogni volta che il modello cliente viene aggiornato, le sue informazioni saranno sincronizzate con Stripe. Per comodità, Cashier sincronizzerà automaticamente le informazioni del cliente con Stripe alla creazione iniziale del cliente.

Puoi personalizzare le colonne usate per sincronizzare le informazioni del cliente con Stripe sovrascrivendo diversi metodi forniti da Cashier. Ad esempio, puoi sovrascrivere il metodo stripeName per personalizzare l’attributo che dovrebbe essere considerato il "nome" del cliente quando Cashier sincronizza le informazioni del cliente con Stripe:

/**
 * Ottieni il nome del cliente che dovrebbe essere sincronizzato con Stripe.
 */
public function stripeName(): string|null
{
    return $this->company_name;
}

Allo stesso modo, puoi sovrascrivere i metodi stripeEmail, stripePhone, stripeAddress e stripePreferredLocales. Questi metodi sincronizzeranno le informazioni con i loro corrispondenti parametri del cliente quando aggiorni l’oggetto cliente di Stripe. Se desideri avere il controllo totale sul processo di sincronizzazione delle informazioni del cliente, puoi sovrascrivere il metodo syncStripeCustomerDetails.

Portale di Fatturazione

Stripe offre un modo semplice per configurare un portale di fatturazione in modo che i tuoi clienti possano gestire il loro abbonamento, i metodi di pagamento e visualizzare la loro cronologia delle fatture. Puoi reindirizzare i tuoi utenti al portale di fatturazione invocando il metodo redirectToBillingPortal sul modello billable da un controller o da una route:

use Illuminate\Http\Request;

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

Per impostazione predefinita, quando l’utente ha finito di gestire il suo abbonamento, potrà tornare alla route home della tua applicazione tramite un link all’interno del portale di fatturazione di Stripe. Puoi fornire un URL personalizzato a cui l’utente dovrebbe tornare passando l’URL come argomento al metodo redirectToBillingPortal:

use Illuminate\Http\Request;

Route::get('/billing-portal', function (Request $request) {
    return $request->user()->redirectToBillingPortal(route('billing'));
});

Se desideri generare l’URL del portale di fatturazione senza generare una risposta di reindirizzamento HTTP, puoi invocare il metodo billingPortalUrl:

$url = $request->user()->billingPortalUrl(route('billing'));

Metodi di Pagamento

Conservare i Metodi di Pagamento

Per creare abbonamenti o effettuare addebiti "una tantum" con Stripe, devi conservare un metodo di pagamento e recuperare il suo identificatore da Stripe. L’approccio per fare questo varia a seconda che tu voglia usare il metodo di pagamento per abbonamenti o per addebiti singoli, quindi esamineremo entrambe le opzioni qui di seguito.

Metodi di Pagamento per Sottoscrizioni

Quando si memorizzano le informazioni della carta di credito di un cliente per un uso futuro da parte di un abbonamento, è necessario utilizzare l’API "Setup Intents" di Stripe per raccogliere in modo sicuro i dettagli del metodo di pagamento del cliente. Un "Setup Intent" indica a Stripe l’intenzione di addebitare il metodo di pagamento del cliente. Il trait Billable di Cashier include il metodo createSetupIntent per creare facilmente un nuovo Setup Intent. Dovresti invocare questo metodo dalla route o controller che renderizzerà il modulo per raccogliere i dettagli del metodo di pagamento del cliente:

    return view('update-payment-method', [
        'intent' => $user->createSetupIntent()
    ]);

Dopo aver creato il Setup Intent e passato alla vista, dovresti allegare il suo segreto all’elemento che raccoglierà il metodo di pagamento. Ad esempio, considera questo modulo per "aggiornare il metodo di pagamento":

<input id="card-holder-name" type="text">

<!-- Stripe Elements Placeholder -->
<div id="card-element"></div>

<button id="card-button" data-secret="{{ $intent->client_secret }}">
    Update Payment Method
</button>

Successivamente, la libreria Stripe.js può essere utilizzata per aggiungere un Stripe Element al modulo e raccogliere in modo sicuro i dettagli del pagamento del cliente:

<script src="https://js.stripe.com/v3/"></script>

<script>
    const stripe = Stripe('stripe-public-key');

    const elements = stripe.elements();
    const cardElement = elements.create('card');

    cardElement.mount('#card-element');
</script>

Successivamente, la carta può essere verificata e un "identifier del metodo di pagamento" sicuro può essere recuperato da Stripe utilizzando il metodo confirmCardSetup di Stripe:

const cardHolderName = document.getElementById('card-holder-name');
const cardButton = document.getElementById('card-button');
const clientSecret = cardButton.dataset.secret;

cardButton.addEventListener('click', async (e) => {
    const { setupIntent, error } = await stripe.confirmCardSetup(
        clientSecret, {
            payment_method: {
                card: cardElement,
                billing_details: { name: cardHolderName.value }
            }
        }
    );

    if (error) {
        // Display "error.message" to the user...
    } else {
        // The card has been verified successfully...
    }
});

Dopo che la carta è stata verificata da Stripe, puoi passare l’identificatore setupIntent.payment_method risultante alla tua applicazione Laravel, dove può essere associato al cliente. Il metodo di pagamento può essere aggiunto come nuovo metodo di pagamento oppure utilizzato per aggiornare il metodo di pagamento predefinito. Puoi anche utilizzare immediatamente l’identificatore del metodo di pagamento per creare un nuovo abbonamento.

Se desideri ulteriori informazioni sui Setup Intents e sulla raccolta dei dettagli del pagamento dei clienti, consulta questa panoramica fornita da Stripe.

Metodi di Pagamento per Addebiti Singoli

Quando effettui un addebito singolo sul metodo di pagamento di un cliente, useremo l’identificativo del metodo di pagamento solo una volta. A causa delle limitazioni di Stripe, non puoi utilizzare il metodo di pagamento predefinito memorizzato di un cliente per addebiti singoli. Devi permettere al cliente di inserire i dettagli del metodo di pagamento utilizzando la libreria Stripe.js. Ad esempio, considera il seguente modulo:

<input id="card-holder-name" type="text">

<!-- Stripe Elements Placeholder -->
<div id="card-element"></div>

<button id="card-button">
    Process Payment
</button>

Dopo aver definito un modulo del genere, puoi usare la libreria Stripe.js per aggiungere un Stripe Element al modulo e raccogliere in modo sicuro i dettagli di pagamento del cliente:

<script src="https://js.stripe.com/v3/"></script>

<script>
    const stripe = Stripe('stripe-public-key');

    const elements = stripe.elements();
    const cardElement = elements.create('card');

    cardElement.mount('#card-element');
</script>

Successivamente, la carta può essere verificata e un "identificativo del metodo di pagamento" può essere recuperato da Stripe utilizzando il metodo createPaymentMethod di Stripe:

const cardHolderName = document.getElementById('card-holder-name');
const cardButton = document.getElementById('card-button');

cardButton.addEventListener('click', async (e) => {
    const { paymentMethod, error } = await stripe.createPaymentMethod(
        'card', cardElement, {
            billing_details: { name: cardHolderName.value }
        }
    );

    if (error) {
        // Mostra "error.message" all'utente...
    } else {
        // La carta è stata verificata con successo...
    }
});

Se la carta viene verificata con successo, puoi passare paymentMethod.id alla tua applicazione Laravel e procedere con un addebito singolo.

Ottenere i Metodi di Pagamento

Il metodo paymentMethods sull’istanza del modello billable restituisce una collezione di istanze Laravel\Cashier\PaymentMethod:

$paymentMethods = $user->paymentMethods();

Per impostazione predefinita, questo metodo restituirà metodi di pagamento di ogni tipo. Per ottenere metodi di pagamento di un tipo specifico, puoi passare il type come argomento al metodo:

$paymentMethods = $user->paymentMethods('sepa_debit');

Per ottenere il metodo di pagamento predefinito del cliente, puoi utilizzare il metodo defaultPaymentMethod:

$paymentMethod = $user->defaultPaymentMethod();

Puoi recuperare un metodo di pagamento specifico associato al modello billable utilizzando il metodo findPaymentMethod:

$paymentMethod = $user->findPaymentMethod($paymentMethodId);

Presenza del Metodo di Pagamento

Per determinare se un modello billable ha un metodo di pagamento predefinito collegato al suo account, invoca il metodo hasDefaultPaymentMethod:

if ($user->hasDefaultPaymentMethod()) {
    // ...
}

Puoi usare il metodo hasPaymentMethod per verificare se un modello billable ha almeno un metodo di pagamento collegato al suo account:

if ($user->hasPaymentMethod()) {
    // ...
}

Questo metodo verificherà se il modello billable ha qualsiasi metodo di pagamento. Per determinare se esiste un metodo di pagamento di un tipo specifico per il modello, puoi passare il type come argomento al metodo:

if ($user->hasPaymentMethod('sepa_debit')) {
    // ...
}

Aggiornamento del Metodo di Pagamento Predefinito

Il metodo updateDefaultPaymentMethod può essere utilizzato per aggiornare le informazioni del metodo di pagamento predefinito di un cliente. Questo metodo accetta un identificatore del metodo di pagamento di Stripe e assegnerà il nuovo metodo di pagamento come metodo di fatturazione predefinito:

    $user->updateDefaultPaymentMethod($paymentMethod);

Per sincronizzare le informazioni del tuo metodo di pagamento predefinito con quelle del metodo di pagamento predefinito del cliente su Stripe, puoi usare il metodo updateDefaultPaymentMethodFromStripe:

    $user->updateDefaultPaymentMethodFromStripe();

Il metodo di pagamento predefinito di un cliente può essere utilizzato solo per la fatturazione e la creazione di nuovi abbonamenti. A causa delle limitazioni imposte da Stripe, non può essere usato per addebiti singoli.

Aggiungere Metodi di Pagamento

Per aggiungere un nuovo metodo di pagamento, puoi chiamare il metodo addPaymentMethod sul modello billable, passando l’identificatore del metodo di pagamento:

$user->addPaymentMethod($paymentMethod);

Per sapere come recuperare gli identificatori dei metodi di pagamento, consulta la documentazione sul salvataggio dei metodi di pagamento.

Eliminare i Metodi di Pagamento

Per eliminare un metodo di pagamento, puoi chiamare il metodo delete sull’istanza Laravel\Cashier\PaymentMethod che desideri eliminare:

$paymentMethod->delete();

Il metodo deletePaymentMethod eliminerà un metodo di pagamento specifico dal modello billable:

$user->deletePaymentMethod('pm_visa');

Il metodo deletePaymentMethods eliminerà tutte le informazioni sui metodi di pagamento per il modello billable:

$user->deletePaymentMethods();

Per impostazione predefinita, questo metodo eliminerà i metodi di pagamento di ogni tipo. Per eliminare i metodi di pagamento di un tipo specifico, puoi passare il type come argomento al metodo:

$user->deletePaymentMethods('sepa_debit');

Se un utente ha un abbonamento attivo, la tua applicazione non dovrebbe permettergli di eliminare il metodo di pagamento predefinito.

Sottoscrizioni

Le sottoscrizioni permettono di configurare pagamenti ricorrenti per i tuoi clienti. Le sottoscrizioni Stripe gestite da Cashier supportano diversi prezzi, quantità di sottoscrizione, periodi di prova e altro ancora.

Creare Abbonamenti

Per creare un abbonamento, prima recupera un’istanza del tuo modello billable, che di solito sarà un’istanza di App\Models\User. Una volta che hai recuperato l’istanza del modello, puoi usare il metodo newSubscription per creare l’abbonamento del modello:

use Illuminate\Http\Request;

Route::post('/user/subscribe', function (Request $request) {
    $request->user()->newSubscription(
        'default', 'price_monthly'
    )->create($request->paymentMethodId);

    // ...
});

Il primo argomento passato al metodo newSubscription dovrebbe essere il tipo interno dell’abbonamento. Se la tua applicazione offre solo un abbonamento, potresti chiamarlo default o primary. Questo tipo di abbonamento è solo per uso interno dell’applicazione e non è destinato ad essere mostrato agli utenti. Inoltre, non dovrebbe contenere spazi e non dovrebbe mai essere cambiato dopo aver creato l’abbonamento. Il secondo argomento è il prezzo specifico a cui l’utente si sta abbonando. Questo valore dovrebbe corrispondere all’identificatore del prezzo in Stripe.

Il metodo create, che accetta un identificatore del metodo di pagamento di Stripe o un oggetto PaymentMethod di Stripe, avvierà l’abbonamento e aggiornerà il tuo database con l’ID cliente Stripe del modello billable e altre informazioni di fatturazione rilevanti.

Passare direttamente un identificatore del metodo di pagamento al metodo create dell’abbonamento aggiungerà automaticamente il metodo di pagamento ai metodi di pagamento memorizzati dell’utente.

Raccogliere Pagamenti Ricorrenti tramite Email di Fattura

Invece di raccogliere automaticamente i pagamenti ricorrenti di un cliente, puoi chiedere a Stripe di inviare una fattura via email al cliente ogni volta che il pagamento ricorrente è dovuto. In questo modo, il cliente può pagare manualmente la fattura una volta ricevuta. Il cliente non deve fornire un metodo di pagamento in anticipo quando raccogli pagamenti ricorrenti tramite fatture:

    $user->newSubscription('default', 'price_monthly')->createAndSendInvoice();

Il tempo a disposizione del cliente per pagare la fattura prima che l’abbonamento venga annullato è determinato dall’opzione days_until_due. Per impostazione predefinita, è di 30 giorni; tuttavia, puoi fornire un valore specifico per questa opzione se lo desideri:

    $user->newSubscription('default', 'price_monthly')->createAndSendInvoice([], [
        'days_until_due' => 30
    ]);

Quantità

Se desideri impostare una quantity specifica per il prezzo quando crei l’abbonamento, dovresti invocare il metodo quantity sul builder dell’abbonamento prima di creare l’abbonamento:

    $user->newSubscription('default', 'price_monthly')
         ->quantity(5)
         ->create($paymentMethod);

Dettagli Aggiuntivi

Se vuoi specificare opzioni aggiuntive per cliente o abbonamento supportate da Stripe, puoi farlo passando questi parametri come secondo e terzo argomento al metodo create:

    $user->newSubscription('default', 'price_monthly')->create($paymentMethod, [
        'email' => $email,
    ], [
        'metadata' => ['note' => 'Some extra information.'],
    ]);

Coupon

Se vuoi applicare un coupon durante la creazione dell’abbonamento, puoi usare il metodo withCoupon:

$user->newSubscription('default', 'price_monthly')
     ->withCoupon('code')
     ->create($paymentMethod);

Oppure, se desideri applicare un codice promozionale di Stripe, puoi usare il metodo withPromotionCode:

$user->newSubscription('default', 'price_monthly')
     ->withPromotionCode('promo_code_id')
     ->create($paymentMethod);

L’ID del codice promozionale fornito dovrebbe essere l’ID API di Stripe assegnato al codice promozionale e non il codice promozionale visibile ai clienti. Se hai bisogno di trovare un ID di codice promozionale basato su un codice promozionale visibile ai clienti, puoi usare il metodo findPromotionCode:

// Trova un ID di codice promozionale tramite il suo codice visibile ai clienti...
$promotionCode = $user->findPromotionCode('SUMMERSALE');

// Trova un ID di codice promozionale attivo tramite il suo codice visibile ai clienti...
$promotionCode = $user->findActivePromotionCode('SUMMERSALE');

Nell’esempio sopra, l’oggetto $promotionCode restituito è un’istanza di Laravel\Cashier\PromotionCode. Questa classe decora un oggetto Stripe\PromotionCode sottostante. Puoi recuperare il coupon relativo al codice promozionale invocando il metodo coupon:

$coupon = $user->findPromotionCode('SUMMERSALE')->coupon();

L’istanza del coupon ti permette di determinare l’ammontare dello sconto e se il coupon rappresenta uno sconto fisso o percentuale:

if ($coupon->isPercentage()) {
    return $coupon->percentOff().'%'; // 21.5%
} else {
    return $coupon->amountOff(); // $5.99
}

Puoi anche recuperare gli sconti attualmente applicati a un cliente o a un abbonamento:

$discount = $billable->discount();

$discount = $subscription->discount();

Le istanze di Laravel\Cashier\Discount restituite decorano un’istanza dell’oggetto Stripe\Discount sottostante. Puoi recuperare il coupon relativo a questo sconto invocando il metodo coupon:

$coupon = $subscription->discount()->coupon();

Se desideri applicare un nuovo coupon o codice promozionale a un cliente o a un abbonamento, puoi farlo tramite i metodi applyCoupon o applyPromotionCode:

$billable->applyCoupon('coupon_id');
$billable->applyPromotionCode('promotion_code_id');

$subscription->applyCoupon('coupon_id');
$subscription->applyPromotionCode('promotion_code_id');

Ricorda di usare l’ID API di Stripe assegnato al codice promozionale e non il codice promozionale visibile ai clienti. È possibile applicare un solo coupon o codice promozionale a un cliente o a un abbonamento alla volta.

Per ulteriori informazioni su questo argomento, consulta la documentazione di Stripe riguardo ai coupon e ai codici promozionali.

Aggiungere Abbonamenti

Se desideri aggiungere un abbonamento a un cliente che ha già un metodo di pagamento predefinito, puoi invocare il metodo add sul builder dell’abbonamento:

use App\Models\User;

$user = User::find(1);

$user->newSubscription('default', 'price_monthly')->add();

Creare Abbonamenti dal Dashboard di Stripe

Puoi creare abbonamenti direttamente dal dashboard di Stripe. In questo modo, Cashier sincronizzerà i nuovi abbonamenti aggiunti e assegnerà loro un tipo di default. Per personalizzare il tipo di abbonamento assegnato agli abbonamenti creati dal dashboard, definisci i gestori degli eventi webhook.

Inoltre, puoi creare solo un tipo di abbonamento tramite il dashboard di Stripe. Se la tua applicazione offre più abbonamenti con tipi diversi, solo un tipo di abbonamento può essere aggiunto tramite il dashboard di Stripe.

Infine, assicurati sempre di aggiungere un solo abbonamento attivo per ogni tipo di abbonamento offerto dalla tua applicazione. Se un cliente ha due abbonamenti default, Cashier utilizzerà solo l’abbonamento aggiunto più di recente, anche se entrambi verranno sincronizzati con il database della tua applicazione.

Verifica dello stato dell’abbonamento

Una volta che un cliente è abbonato alla tua applicazione, puoi facilmente controllare il suo stato di abbonamento utilizzando diversi metodi comodi. Innanzitutto, il metodo subscribed restituisce true se il cliente ha un abbonamento attivo, anche se l’abbonamento è attualmente nel periodo di prova. Il metodo subscribed accetta il tipo di abbonamento come primo argomento:

if ($user->subscribed('default')) {
    // ...
}

Il metodo subscribed è anche un’ottima candidata per un middleware di route, permettendoti di filtrare l’accesso alle route e ai controller in base allo stato di abbonamento dell’utente:

<?php

namespace App\Http\Middleware;

use Closure;
use Illuminate\Http\Request;
use Symfony\Component\HttpFoundation\Response;

class EnsureUserIsSubscribed
{
    /**
     * Gestisce una richiesta in arrivo.
     *
     * @param  \Closure(\Illuminate\Http\Request): (\Symfony\Component\HttpFoundation\Response)  $next
     */
    public function handle(Request $request, Closure $next): Response
    {
        if ($request->user() && ! $request->user()->subscribed('default')) {
            // Questo utente non è un cliente pagante...
            return redirect('/billing');
        }

        return $next($request);
    }
}

Se vuoi determinare se un utente è ancora nel periodo di prova, puoi usare il metodo onTrial. Questo metodo può essere utile per capire se devi mostrare un avviso all’utente che è ancora nel periodo di prova:

if ($user->subscription('default')->onTrial()) {
    // ...
}

Il metodo subscribedToProduct può essere utilizzato per determinare se l’utente è abbonato a un determinato prodotto basandosi sull’identificativo del prodotto in Stripe. In Stripe, i prodotti sono collezioni di prezzi. In questo esempio, determineremo se l’abbonamento default dell’utente è attivamente abbonato al prodotto "premium" dell’applicazione. L’identificativo del prodotto Stripe fornito deve corrispondere a uno degli identificativi dei tuoi prodotti nel dashboard di Stripe:

if ($user->subscribedToProduct('prod_premium', 'default')) {
    // ...
}

Passando un array al metodo subscribedToProduct, puoi determinare se l’abbonamento default dell’utente è attivamente abbonato ai prodotti "basic" o "premium" dell’applicazione:

if ($user->subscribedToProduct(['prod_basic', 'prod_premium'], 'default')) {
    // ...
}

Il metodo subscribedToPrice può essere usato per determinare se l’abbonamento di un cliente corrisponde a un determinativo ID prezzo:

if ($user->subscribedToPrice('price_basic_monthly', 'default')) {
    // ...
}

Il metodo recurring può essere usato per determinare se l’utente è attualmente abbonato e non è più nel periodo di prova:

if ($user->subscription('default')->recurring()) {
    // ...
}

Se un utente ha due abbonamenti dello stesso tipo, il metodo subscription restituirà sempre l’abbonamento più recente. Ad esempio, un utente potrebbe avere due record di abbonamento di tipo default; tuttavia, uno degli abbonamenti potrebbe essere un abbonamento vecchio e scaduto, mentre l’altro è l’abbonamento attivo corrente. L’abbonamento più recente sarà sempre restituito mentre gli abbonamenti più vecchi vengono mantenuti nel database per una revisione storica.

Stato della Sottoscrizione Cancellata

Per determinare se l’utente è stato un abbonato attivo ma ha cancellato la sua sottoscrizione, puoi usare il metodo canceled:

if ($user->subscription('default')->canceled()) {
    // ...
}

Puoi anche verificare se un utente ha cancellato la propria sottoscrizione ma è ancora nel "periodo di grazia" fino alla scadenza completa della sottoscrizione. Ad esempio, se un utente cancella una sottoscrizione il 5 marzo che era originariamente prevista per scadere il 10 marzo, l’utente è nel "periodo di grazia" fino al 10 marzo. Nota che il metodo subscribed restituisce ancora true durante questo periodo:

if ($user->subscription('default')->onGracePeriod()) {
    // ...
}

Per determinare se l’utente ha cancellato la propria sottoscrizione e non è più nel "periodo di grazia", puoi usare il metodo ended:

if ($user->subscription('default')->ended()) {
    // ...
}

Stato Incompleto e Scaduto

Se un abbonamento richiede un’azione di pagamento secondaria dopo la creazione, l’abbonamento sarà contrassegnato come incomplete. Gli stati degli abbonamenti sono memorizzati nella colonna stripe_status della tabella subscriptions del database di Cashier.

Allo stesso modo, se è richiesta un’azione di pagamento secondaria durante il cambio dei prezzi, l’abbonamento sarà contrassegnato come past_due. Quando il tuo abbonamento è in uno di questi stati, non sarà attivo finché il cliente non avrà confermato il pagamento. Determinare se un abbonamento ha un pagamento incompleto può essere fatto utilizzando il metodo hasIncompletePayment sul modello billable o su un’istanza di abbonamento:

if ($user->hasIncompletePayment('default')) {
    // ...
}

if ($user->subscription('default')->hasIncompletePayment()) {
    // ...
}

Quando un abbonamento ha un pagamento incompleto, dovresti indirizzare l’utente alla pagina di conferma del pagamento di Cashier, passando l’identificatore latestPayment. Puoi usare il metodo latestPayment disponibile sull’istanza dell’abbonamento per recuperare questo identificatore:

<a href="{{ route('cashier.payment', $subscription->latestPayment()->id) }}">
    Please confirm your payment.
</a>

Se desideri che l’abbonamento sia ancora considerato attivo quando è in uno stato past_due o incomplete, puoi usare i metodi keepPastDueSubscriptionsActive e keepIncompleteSubscriptionsActive forniti da Cashier. Tipicamente, questi metodi dovrebbero essere chiamati nel metodo register del tuo App\Providers\AppServiceProvider:

use Laravel\Cashier\Cashier;

/**
 * Registra i servizi dell'applicazione.
 */
public function register(): void
{
    Cashier::keepPastDueSubscriptionsActive();
    Cashier::keepIncompleteSubscriptionsActive();
}

Quando un abbonamento è in stato incomplete, non può essere modificato finché il pagamento non viene confermato. Pertanto, i metodi swap e updateQuantity genereranno un’eccezione quando l’abbonamento è in stato incomplete.

Scope delle Sottoscrizioni

La maggior parte degli stati delle sottoscrizioni sono disponibili come scope delle query, permettendoti di interrogare facilmente il database per le sottoscrizioni in uno stato particolare:

// Ottieni tutte le sottoscrizioni attive...
$subscriptions = Subscription::query()->active()->get();

// Ottieni tutte le sottoscrizioni cancellate di un utente...
$subscriptions = $user->subscriptions()->canceled()->get();

Una lista completa degli scope disponibili è riportata di seguito:

Subscription::query()->active();
Subscription::query()->canceled();
Subscription::query()->ended();
Subscription::query()->incomplete();
Subscription::query()->notCanceled();
Subscription::query()->notOnGracePeriod();
Subscription::query()->notOnTrial();
Subscription::query()->onGracePeriod();
Subscription::query()->onTrial();
Subscription::query()->pastDue();
Subscription::query()->recurring();

Modificare i Prezzi

Dopo che un cliente si è abbonato alla tua applicazione, potrebbe occasionalmente voler cambiare il prezzo dell’abbonamento. Per passare a un nuovo prezzo, fornisci l’identificatore del prezzo di Stripe al metodo swap. Quando si cambiano i prezzi, si assume che l’utente voglia riattivare il proprio abbonamento se era stato precedentemente cancellato. L’identificatore del prezzo fornito dovrebbe corrispondere a un identificatore di prezzo Stripe disponibile nella dashboard di Stripe:

    use App\Models\User;

    $user = App\Models\User::find(1);

    $user->subscription('default')->swap('price_yearly');

Se il cliente è in periodo di prova, il periodo di prova sarà mantenuto. Inoltre, se esiste una "quantity" per l’abbonamento, quella quantità sarà mantenuta.

Se desideri cambiare i prezzi e annullare qualsiasi periodo di prova attualmente in corso per il cliente, puoi invocare il metodo skipTrial:

    $user->subscription('default')
            ->skipTrial()
            ->swap('price_yearly');

Se desideri cambiare i prezzi e fatturare immediatamente il cliente invece di aspettare il prossimo ciclo di fatturazione, puoi usare il metodo swapAndInvoice:

    $user = User::find(1);

    $user->subscription('default')->swapAndInvoice('price_yearly');

Proratazioni

Di default, Stripe effettua una proratazione dei costi quando si cambia prezzo. Il metodo noProrate può essere utilizzato per aggiornare il prezzo dell’abbonamento senza proratazione dei costi:

$user->subscription('default')->noProrate()->swap('price_yearly');

Per maggiori informazioni sulla proratazione degli abbonamenti, consulta la documentazione di Stripe.

Eseguire il metodo noProrate prima del metodo swapAndInvoice non avrà effetto sulla proratazione. Verrà sempre emessa una fattura.

Quantità dell’Abbonamento

A volte gli abbonamenti sono influenzati dalla "quantità". Ad esempio, un’applicazione di gestione progetti potrebbe addebitare $10 al mese per progetto. Puoi usare i metodi incrementQuantity e decrementQuantity per aumentare o diminuire facilmente la quantità del tuo abbonamento:

use App\Models\User;

$user = User::find(1);

$user->subscription('default')->incrementQuantity();

// Aggiungi cinque alla quantità attuale dell'abbonamento...
$user->subscription('default')->incrementQuantity(5);

$user->subscription('default')->decrementQuantity();

// Sottrai cinque dalla quantità attuale dell'abbonamento...
$user->subscription('default')->decrementQuantity(5);

In alternativa, puoi impostare una quantità specifica usando il metodo updateQuantity:

$user->subscription('default')->updateQuantity(10);

Il metodo noProrate può essere usato per aggiornare la quantità dell’abbonamento senza proporzionare i costi:

$user->subscription('default')->noProrate()->updateQuantity(10);

Per maggiori informazioni sulle quantità degli abbonamenti, consulta la documentazione di Stripe.

Quantità per Abbonamenti con Più Prodotti

Se il tuo abbonamento è un abbonamento con più prodotti, dovresti passare l’ID del prezzo di cui desideri incrementare o decrementare la quantità come secondo argomento ai metodi increment / decrement:

    $user->subscription('default')->incrementQuantity(1, 'price_chat');

Abbonamenti con Prodotti Multipli

Abbonamento con prodotti multipli ti permette di assegnare più prodotti di fatturazione a un singolo abbonamento. Ad esempio, immagina di creare un’applicazione di assistenza clienti "helpdesk" che ha un prezzo base di abbonamento di $10 al mese ma offre un prodotto aggiuntivo di chat live per $15 in più al mese. Le informazioni per gli abbonamenti con più prodotti sono memorizzate nella tabella subscription_items del database di Cashier.

Puoi specificare più prodotti per un determinato abbonamento passando un array di prezzi come secondo argomento al metodo newSubscription:

use Illuminate\Http\Request;

Route::post('/user/subscribe', function (Request $request) {
    $request->user()->newSubscription('default', [
        'price_monthly',
        'price_chat',
    ])->create($request->paymentMethodId);

    // ...
});

Nell’esempio sopra, il cliente avrà due prezzi associati al loro abbonamento default. Entrambi i prezzi saranno addebitati nei loro rispettivi intervalli di fatturazione. Se necessario, puoi usare il metodo quantity per indicare una quantità specifica per ogni prezzo:

$user = User::find(1);

$user->newSubscription('default', ['price_monthly', 'price_chat'])
    ->quantity(5, 'price_chat')
    ->create($paymentMethod);

Se desideri aggiungere un altro prezzo a un abbonamento esistente, puoi invocare il metodo addPrice dell’abbonamento:

$user = User::find(1);

$user->subscription('default')->addPrice('price_chat');

L’esempio sopra aggiungerà il nuovo prezzo e al cliente verrà addebitato nel prossimo ciclo di fatturazione. Se desideri addebitare il cliente immediatamente puoi usare il metodo addPriceAndInvoice:

$user->subscription('default')->addPriceAndInvoice('price_chat');

Se desideri aggiungere un prezzo con una quantità specifica, puoi passare la quantità come secondo argomento dei metodi addPrice o addPriceAndInvoice:

$user = User::find(1);

$user->subscription('default')->addPrice('price_chat', 5);

Puoi rimuovere prezzi dagli abbonamenti usando il metodo removePrice:

$user->subscription('default')->removePrice('price_chat');

Non puoi rimuovere l’ultimo prezzo di un abbonamento. Invece, dovresti semplicemente cancellare l’abbonamento.

Cambiare i Prezzi

Puoi cambiare i prezzi associati a un abbonamento con più prodotti. Ad esempio, immagina che un cliente abbia un abbonamento price_basic con un prodotto aggiuntivo price_chat e desideri aggiornare il cliente da price_basic a price_pro:

    use App\Models\User;

    $user = User::find(1);

    $user->subscription('default')->swap(['price_pro', 'price_chat']);

Eseguendo l’esempio sopra, l’elemento di abbonamento con price_basic viene eliminato e quello con price_chat viene mantenuto. Inoltre, viene creato un nuovo elemento di abbonamento per price_pro.

Puoi anche specificare le opzioni degli elementi di abbonamento passando un array di coppie chiave/valore al metodo swap. Ad esempio, potresti aver bisogno di specificare le quantità dei prezzi dell’abbonamento:

    $user = User::find(1);

    $user->subscription('default')->swap([
        'price_pro' => ['quantity' => 5],
        'price_chat'
    ]);

Se vuoi cambiare un solo prezzo in un abbonamento, puoi farlo usando il metodo swap direttamente sull’elemento di abbonamento. Questo approccio è particolarmente utile se vuoi mantenere tutti i metadata esistenti sugli altri prezzi dell’abbonamento:

    $user = User::find(1);

    $user->subscription('default')
            ->findItemOrFail('price_basic')
            ->swap('price_pro');

Prorate

Di default, Stripe applica le prorate quando si aggiungono o si rimuovono prezzi da un abbonamento con più prodotti. Se desideri effettuare un aggiustamento del prezzo senza prorata, puoi concatenare il metodo noProrate all’operazione sul prezzo:

    $user->subscription('default')->noProrate()->removePrice('price_chat');

Quantità

Se desideri aggiornare le quantità sui prezzi delle singole sottoscrizioni, puoi farlo utilizzando i metodi di quantità esistenti passando l’ID del prezzo come argomento aggiuntivo al metodo:

    $user = User::find(1);

    $user->subscription('default')->incrementQuantity(5, 'price_chat');

    $user->subscription('default')->decrementQuantity(3, 'price_chat');

    $user->subscription('default')->updateQuantity(10, 'price_chat');

Quando una sottoscrizione ha più prezzi, gli attributi stripe_price e quantity sul modello Subscription saranno null. Per accedere agli attributi dei singoli prezzi, dovresti usare la relazione items disponibile sul modello Subscription.

Elementi di Abbonamento

Quando un abbonamento ha più prezzi, avrà diversi "elementi" di abbonamento memorizzati nella tabella subscription_items del tuo database. Puoi accedervi tramite la relazione items sull’abbonamento:

use App\Models\User;

$user = User::find(1);

$subscriptionItem = $user->subscription('default')->items->first();

// Recupera il prezzo e la quantità di Stripe per un elemento specifico...
$stripePrice = $subscriptionItem->stripe_price;
$quantity = $subscriptionItem->quantity;

Puoi anche recuperare un prezzo specifico utilizzando il metodo findItemOrFail:

$user = User::find(1);

$subscriptionItem = $user->subscription('default')->findItemOrFail('price_chat');

Abbonamenti Multipli

Stripe permette ai tuoi clienti di avere più abbonamenti contemporaneamente. Ad esempio, potresti gestire una palestra che offre un abbonamento per il nuoto e uno per il sollevamento pesi, e ogni abbonamento potrebbe avere prezzi differenti. Naturalmente, i clienti dovrebbero poter abbonarsi a uno o entrambi i piani.

Quando la tua applicazione crea abbonamenti, puoi fornire il tipo di abbonamento al metodo newSubscription. Il tipo può essere qualsiasi stringa che rappresenta il tipo di abbonamento che l’utente sta iniziando:

use Illuminate\Http\Request;

Route::post('/swimming/subscribe', function (Request $request) {
    $request->user()->newSubscription('swimming')
        ->price('price_swimming_monthly')
        ->create($request->paymentMethodId);

    // ...
});

In questo esempio, abbiamo avviato un abbonamento mensile per il nuoto per il cliente. Tuttavia, potrebbe voler passare a un abbonamento annuale in un secondo momento. Quando si modifica l’abbonamento del cliente, possiamo semplicemente cambiare il prezzo sull’abbonamento swimming:

$user->subscription('swimming')->swap('price_swimming_yearly');

Naturalmente, puoi anche annullare completamente l’abbonamento:

$user->subscription('swimming')->cancel();

Fatturazione Basata sull’Uso

La fatturazione basata sull’uso permette di addebitare i clienti in base all’utilizzo del prodotto durante un ciclo di fatturazione. Ad esempio, potresti addebitare i clienti in base al numero di messaggi di testo o email che inviano ogni mese.

Per iniziare a utilizzare la fatturazione basata sull’uso, devi prima creare un nuovo prodotto nel tuo dashboard di Stripe con un modello di fatturazione basato sull’uso e un meter. Dopo aver creato il meter, memorizza il nome dell’evento associato e l’ID del meter, che ti serviranno per segnalare e recuperare l’utilizzo. Poi, utilizza il metodo meteredPrice per aggiungere l’ID del prezzo misurato a una sottoscrizione del cliente:

    use Illuminate\Http\Request;

    Route::post('/user/subscribe', function (Request $request) {
        $request->user()->newSubscription('default')
            ->meteredPrice('price_metered')
            ->create($request->paymentMethodId);

        // ...
    });

Puoi anche avviare una sottoscrizione misurata tramite Stripe Checkout:

    $checkout = Auth::user()
            ->newSubscription('default', [])
            ->meteredPrice('price_metered')
            ->checkout();

    return view('your-checkout-view', [
        'checkout' => $checkout,
    ]);

Report dell’utilizzo

Man mano che i tuoi clienti utilizzano la tua applicazione, dovrai segnalare il loro utilizzo a Stripe in modo che possano essere fatturati correttamente. Per segnalare l’utilizzo di un evento misurato, puoi usare il metodo reportMeterEvent sul tuo modello Billable:

$user = User::find(1);

$user->reportMeterEvent('emails-sent');

Per impostazione predefinita, viene aggiunta una "quantità di utilizzo" di 1 al periodo di fatturazione. In alternativa, puoi passare una quantità specifica di "utilizzo" da aggiungere all’utilizzo del cliente per il periodo di fatturazione:

$user = User::find(1);

$user->reportMeterEvent('emails-sent', quantity: 15);

Per recuperare il riepilogo degli eventi di un cliente per un contatore, puoi utilizzare il metodo meterEventSummaries di un’istanza Billable:

$user = User::find(1);

$meterUsage = $user->meterEventSummaries($meterId);

$meterUsage->first()->aggregated_value // 10

Per ulteriori informazioni sui riepiloghi degli eventi dei contatori, consulta la documentazione dell’oggetto Meter Event Summary di Stripe.

Per elencare tutti i contatori, puoi utilizzare il metodo meters di un’istanza Billable:

$user = User::find(1);

$user->meters();

Tasse sulle Sottoscrizioni

Invece di calcolare manualmente le aliquote fiscali, puoi calcolare automaticamente le tasse con Stripe Tax.

Per specificare le aliquote fiscali che un utente paga su una sottoscrizione, devi implementare il metodo taxRates sul tuo modello billable e restituire un array contenente gli ID delle aliquote fiscali di Stripe. Puoi definire queste aliquote fiscali nel tuo dashboard Stripe:

/**
 * Le aliquote fiscali che si applicano alle sottoscrizioni del cliente.
 *
 * @return array<int, string>
 */
public function taxRates(): array
{
    return ['txr_id'];
}

Il metodo taxRates ti permette di applicare un’aliquota fiscale per ogni cliente, utile se hai utenti in diversi paesi con diverse aliquote fiscali.

Se offri sottoscrizioni con più prodotti, puoi definire aliquote fiscali diverse per ogni prezzo implementando un metodo priceTaxRates sul tuo modello billable:

/**
 * Le aliquote fiscali che si applicano alle sottoscrizioni del cliente.
 *
 * @return array<string, array<int, string>>
 */
public function priceTaxRates(): array
{
    return [
        'price_monthly' => ['txr_id'],
    ];
}

Il metodo taxRates si applica solo agli addebiti delle sottoscrizioni. Se usi Cashier per effettuare addebiti "una tantum", dovrai specificare manualmente l’aliquota fiscale in quel momento.

Sincronizzazione delle aliquote fiscali

Quando modifichi gli ID delle aliquote fiscali codificati restituiti dal metodo taxRates, le impostazioni fiscali delle sottoscrizioni esistenti per l’utente rimarranno invariate. Se desideri aggiornare il valore fiscale delle sottoscrizioni esistenti con i nuovi valori di taxRates, dovresti chiamare il metodo syncTaxRates sull’istanza della sottoscrizione dell’utente:

    $user->subscription('default')->syncTaxRates();

Questo sincronizzerà anche le aliquote fiscali degli articoli per una sottoscrizione con più prodotti. Se la tua applicazione offre sottoscrizioni con più prodotti, assicurati che il tuo modello billable implementi il metodo priceTaxRates discusso sopra.

Esenzione Fiscale

Cashier offre anche i metodi isNotTaxExempt, isTaxExempt e reverseChargeApplies per determinare se il cliente è esente da tasse. Questi metodi chiameranno l’API di Stripe per verificare lo stato di esenzione fiscale di un cliente:

use App\Models\User;

$user = User::find(1);

$user->isTaxExempt();
$user->isNotTaxExempt();
$user->reverseChargeApplies();

Questi metodi sono disponibili anche su qualsiasi oggetto Laravel\Cashier\Invoice. Tuttavia, quando vengono invocati su un oggetto Invoice, i metodi determineranno lo stato di esenzione al momento della creazione della fattura.

Data di Ancoraggio dell’Abbonamento

Di default, l’ancoraggio del ciclo di fatturazione è la data in cui l’abbonamento è stato creato o, se viene utilizzato un periodo di prova, la data in cui termina la prova. Se desideri modificare la data di ancoraggio della fatturazione, puoi usare il metodo anchorBillingCycleOn:

use Illuminate\Http\Request;

Route::post('/user/subscribe', function (Request $request) {
    $anchor = Carbon::parse('first day of next month');

    $request->user()->newSubscription('default', 'price_monthly')
                ->anchorBillingCycleOn($anchor->startOfDay())
                ->create($request->paymentMethodId);

    // ...
});

Per maggiori informazioni sulla gestione dei cicli di fatturazione degli abbonamenti, consulta la documentazione sul ciclo di fatturazione di Stripe

Cancellazione degli Abbonamenti

Per cancellare un abbonamento, chiama il metodo cancel sull’abbonamento dell’utente:

    $user->subscription('default')->cancel();

Quando un abbonamento viene cancellato, Cashier imposterà automaticamente la colonna ends_at nella tua tabella subscriptions del database. Questa colonna viene utilizzata per sapere quando il metodo subscribed dovrebbe iniziare a restituire false.

Ad esempio, se un cliente cancella un abbonamento il 1° marzo, ma l’abbonamento non era previsto per terminare fino al 5 marzo, il metodo subscribed continuerà a restituire true fino al 5 marzo. Questo accade perché solitamente a un utente è permesso continuare a usare un’applicazione fino alla fine del ciclo di fatturazione.

Puoi determinare se un utente ha cancellato il proprio abbonamento ma è ancora nel suo "periodo di grazia" usando il metodo onGracePeriod:

    if ($user->subscription('default')->onGracePeriod()) {
        // ...
    }

Se desideri cancellare un abbonamento immediatamente, chiama il metodo cancelNow sull’abbonamento dell’utente:

    $user->subscription('default')->cancelNow();

Se desideri cancellare un abbonamento immediatamente e fatturare qualsiasi utilizzo misurato rimanente non fatturato o nuovi elementi di fattura di prorata in sospeso, chiama il metodo cancelNowAndInvoice sull’abbonamento dell’utente:

    $user->subscription('default')->cancelNowAndInvoice();

Puoi anche scegliere di cancellare l’abbonamento in un momento specifico:

    $user->subscription('default')->cancelAt(
        now()->addDays(10)
    );

Infine, dovresti sempre cancellare gli abbonamenti degli utenti prima di eliminare il modello utente associato:

    $user->subscription('default')->cancelNow();

    $user->delete();

Riprendere le Sottoscrizioni

Se un cliente ha annullato la sua sottoscrizione e desideri riprenderla, puoi invocare il metodo resume sulla sottoscrizione. Il cliente deve essere ancora nel suo "periodo di grazia" per poter riprendere una sottoscrizione:

    $user->subscription('default')->resume();

Se il cliente annulla una sottoscrizione e poi la riprende prima che la sottoscrizione sia completamente scaduta, non verrà addebitato immediatamente. Invece, la sua sottoscrizione sarà riattivata e verrà fatturato nel ciclo di fatturazione originale.

Prove di abbonamento

Con il Metodo di Pagamento Iniziale

Se desideri offrire periodi di prova ai tuoi clienti raccogliendo comunque le informazioni del metodo di pagamento in anticipo, dovresti usare il metodo trialDays quando crei le tue sottoscrizioni:

use Illuminate\Http\Request;

Route::post('/user/subscribe', function (Request $request) {
    $request->user()->newSubscription('default', 'price_monthly')
                ->trialDays(10)
                ->create($request->paymentMethodId);

    // ...
});

Questo metodo imposterà la data di fine del periodo di prova nel record della sottoscrizione nel database e istruirà Stripe a non iniziare la fatturazione al cliente fino a dopo questa data. Quando usi il metodo trialDays, Cashier sovrascriverà qualsiasi periodo di prova predefinito configurato per il prezzo in Stripe.

Se la sottoscrizione del cliente non viene cancellata prima della data di fine del periodo di prova, verrà addebitato non appena la prova scade. Assicurati quindi di informare i tuoi utenti della data di fine della prova.

Il metodo trialUntil ti permette di fornire un’istanza DateTime che specifica quando dovrebbe terminare il periodo di prova:

use Carbon\Carbon;

$user->newSubscription('default', 'price_monthly')
            ->trialUntil(Carbon::now()->addDays(10))
            ->create($paymentMethod);

Puoi verificare se un utente è ancora nel periodo di prova usando il metodo onTrial dell’istanza utente o il metodo onTrial dell’istanza sottoscrizione. I due esempi seguenti sono equivalenti:

if ($user->onTrial('default')) {
    // ...
}

if ($user->subscription('default')->onTrial()) {
    // ...
}

Puoi usare il metodo endTrial per terminare immediatamente una prova della sottoscrizione:

$user->subscription('default')->endTrial();

Per determinare se una prova esistente è scaduta, puoi usare i metodi hasExpiredTrial:

if ($user->hasExpiredTrial('default')) {
    // ...
}

if ($user->subscription('default')->hasExpiredTrial()) {
    // ...
}

Definire i giorni di prova in Stripe / Cashier

Puoi scegliere di definire quanti giorni di prova ricevono i tuoi prezzi nel dashboard di Stripe oppure passarli sempre esplicitamente utilizzando Cashier. Se scegli di definire i giorni di prova dei tuoi prezzi in Stripe, dovresti essere consapevole che le nuove sottoscrizioni, comprese quelle per un cliente che aveva una sottoscrizione in passato, riceveranno sempre un periodo di prova a meno che non chiami esplicitamente il metodo skipTrial().

Senza Metodo di Pagamento Iniziale

Se desideri offrire periodi di prova senza raccogliere le informazioni del metodo di pagamento dell’utente inizialmente, puoi impostare la colonna trial_ends_at nel record dell’utente alla data di fine della prova desiderata. Questo di solito viene fatto durante la registrazione dell’utente:

use App\Models\User;

$user = User::create([
    // ...
    'trial_ends_at' => now()->addDays(10),
]);

Assicurati di aggiungere un date cast per l’attributo trial_ends_at all’interno della definizione della classe del tuo modello billable.

Cashier si riferisce a questo tipo di prova come "generic trial", poiché non è collegato a nessuna sottoscrizione esistente. Il metodo onTrial sull’istanza del modello billable restituirà true se la data attuale non supera il valore di trial_ends_at:

if ($user->onTrial()) {
    // L'utente è nel periodo di prova...
}

Una volta che sei pronto a creare una sottoscrizione effettiva per l’utente, puoi utilizzare il metodo newSubscription come al solito:

$user = User::find(1);

$user->newSubscription('default', 'price_monthly')->create($paymentMethod);

Per recuperare la data di fine della prova dell’utente, puoi usare il metodo trialEndsAt. Questo metodo restituirà un’istanza di data Carbon se l’utente è in prova o null se non lo è. Puoi anche passare un parametro di tipo sottoscrizione opzionale se desideri ottenere la data di fine della prova per una specifica sottoscrizione diversa da quella predefinita:

if ($user->onTrial()) {
    $trialEndsAt = $user->trialEndsAt('main');
}

Puoi anche usare il metodo onGenericTrial se desideri sapere specificamente se l’utente è nel periodo di prova "generic" e non ha ancora creato una sottoscrizione effettiva:

if ($user->onGenericTrial()) {
    // L'utente è nel periodo di prova "generic"...
}

Estendere le Prove

Il metodo extendTrial ti permette di estendere il periodo di prova di un abbonamento dopo che l’abbonamento è stato creato. Se la prova è già scaduta e il cliente sta già pagando per l’abbonamento, puoi comunque offrirgli una prova estesa. Il tempo trascorso nel periodo di prova verrà detratto dalla prossima fattura del cliente:

    use App\Models\User;

    $subscription = User::find(1)->subscription('default');

    // Termina la prova tra 7 giorni...
    $subscription->extendTrial(
        now()->addDays(7)
    );

    // Aggiungi ulteriori 5 giorni alla prova...
    $subscription->extendTrial(
        $subscription->trial_ends_at->addDays(5)
    );

Gestire i Webhook di Stripe

Puoi usare la Stripe CLI per testare i webhook durante lo sviluppo locale.

Stripe può notificare alla tua applicazione una varietà di eventi tramite webhook. Per impostazione predefinita, una rotta che punta al controller webhook di Cashier viene registrata automaticamente dal service provider di Cashier. Questo controller gestirà tutte le richieste webhook in arrivo.

Per impostazione predefinita, il controller webhook di Cashier gestisce automaticamente la cancellazione degli abbonamenti che hanno troppi pagamenti falliti (come definito dalle tue impostazioni Stripe), aggiornamenti dei clienti, cancellazioni dei clienti, aggiornamenti degli abbonamenti e modifiche ai metodi di pagamento; tuttavia, come vedremo presto, puoi estendere questo controller per gestire qualsiasi evento webhook di Stripe tu voglia.

Per assicurarti che la tua applicazione possa gestire i webhook di Stripe, assicurati di configurare l’URL del webhook nel pannello di controllo di Stripe. Per impostazione predefinita, il controller webhook di Cashier risponde al percorso URL /stripe/webhook. L’elenco completo dei webhook che dovresti abilitare nel pannello di controllo di Stripe è:

  • customer.subscription.created
  • customer.subscription.updated
  • customer.subscription.deleted
  • customer.updated
  • customer.deleted
  • payment_method.automatically_updated
  • invoice.payment_action_required
  • invoice.payment_succeeded

Per comodità, Cashier include un comando Artisan cashier:webhook. Questo comando creerà un webhook in Stripe che ascolta tutti gli eventi richiesti da Cashier:

php artisan cashier:webhook

Per impostazione predefinita, il webhook creato punterà all’URL definito dalla variabile d’ambiente APP_URL e alla rotta cashier.webhook inclusa in Cashier. Puoi fornire l’opzione --url quando esegui il comando se desideri usare un URL diverso:

php artisan cashier:webhook --url "https://example.com/stripe/webhook"

Il webhook creato utilizzerà la versione dell’API di Stripe con cui la tua versione di Cashier è compatibile. Se desideri usare una versione diversa di Stripe, puoi fornire l’opzione --api-version:

php artisan cashier:webhook --api-version="2019-12-03"

Dopo la creazione, il webhook sarà attivo immediatamente. Se desideri creare il webhook ma tenerlo disabilitato fino a quando non sei pronto, puoi fornire l’opzione --disabled quando esegui il comando:

php artisan cashier:webhook --disabled

Assicurati di proteggere le richieste webhook in arrivo da Stripe con il middleware di verifica della firma webhook incluso in Cashier.

Webhook e Protezione CSRF

Poiché i webhook di Stripe devono bypassare la protezione CSRF di Laravel, devi assicurarti che Laravel non tenti di convalidare il token CSRF per i webhook in arrivo da Stripe. Per fare ciò, dovresti escludere stripe/* dalla protezione CSRF nel file bootstrap/app.php della tua applicazione:

    ->withMiddleware(function (Middleware $middleware) {
        $middleware->validateCsrfTokens(except: [
            'stripe/*',
        ]);
    })

Definire i gestori di eventi Webhook

Cashier gestisce automaticamente le cancellazioni delle sottoscrizioni per addebiti falliti e altri eventi webhook comuni di Stripe. Tuttavia, se hai eventi webhook aggiuntivi che desideri gestire, puoi farlo ascoltando i seguenti eventi dispatchati da Cashier:

  • Laravel\Cashier\Events\WebhookReceived
  • Laravel\Cashier\Events\WebhookHandled

Entrambi gli eventi contengono l’intero payload del webhook di Stripe. Ad esempio, se desideri gestire il webhook invoice.payment_succeeded, puoi registrare un listener che gestirà l’evento:

<?php

namespace App\Listeners;

use Laravel\Cashier\Events\WebhookReceived;

class StripeEventListener
{
    /**
     * Gestire i webhook ricevuti da Stripe.
     */
    public function handle(WebhookReceived $event): void
    {
        if ($event->payload['type'] === 'invoice.payment_succeeded') {
            // Gestire l'evento in arrivo...
        }
    }
}

Verifica delle firme dei Webhook

Per proteggere i tuoi webhook, puoi utilizzare le firme dei webhook di Stripe. Per comodità, Cashier include automaticamente un middleware che valida che la richiesta webhook di Stripe in arrivo sia valida.

Per abilitare la verifica del webhook, assicurati che la variabile d’ambiente STRIPE_WEBHOOK_SECRET sia impostata nel file .env della tua applicazione. Il secret del webhook può essere recuperato dal dashboard del tuo account Stripe.

Addebiti Singoli

Addebito Semplice

Se desideri effettuare un addebito una tantum su un cliente, puoi usare il metodo charge su un’istanza del modello billable. Dovrai fornire un identificativo del metodo di pagamento come secondo argomento del metodo charge:

    use Illuminate\Http\Request;

    Route::post('/purchase', function (Request $request) {
        $stripeCharge = $request->user()->charge(
            100, $request->paymentMethodId
        );

        // ...
    });

Il metodo charge accetta un array come terzo argomento, permettendoti di passare qualsiasi opzione desideri alla creazione dell’addebito sottostante di Stripe. Ulteriori informazioni riguardo alle opzioni disponibili quando si creano addebiti possono essere trovate nella documentazione di Stripe:

    $user->charge(100, $paymentMethod, [
        'custom_option' => $value,
    ]);

Puoi anche usare il metodo charge senza un cliente o utente sottostante. Per fare ciò, invoca il metodo charge su una nuova istanza del modello billable della tua applicazione:

    use App\Models\User;

    $stripeCharge = (new User)->charge(100, $paymentMethod);

Il metodo charge genererà un’eccezione se l’addebito fallisce. Se l’addebito ha successo, verrà restituita un’istanza di Laravel\Cashier\Payment dal metodo:

    try {
        $payment = $user->charge(100, $paymentMethod);
    } catch (Exception $e) {
        // ...
    }

Il metodo charge accetta l’importo del pagamento nel denominatore più basso della valuta utilizzata dalla tua applicazione. Ad esempio, se i clienti pagano in Dollari Americani, gli importi devono essere specificati in centesimi.

Addebitare tramite Fattura

A volte potrebbe essere necessario effettuare un addebito una tantum e offrire una fattura PDF al tuo cliente. Il metodo invoicePrice ti permette di fare proprio questo. Ad esempio, fatturiamo a un cliente cinque nuove magliette:

    $user->invoicePrice('price_tshirt', 5);

La fattura verrà addebitata immediatamente sul metodo di pagamento predefinito dell’utente. Il metodo invoicePrice accetta anche un array come terzo argomento. Questo array contiene le opzioni di fatturazione per l’elemento della fattura. Il quarto argomento accettato dal metodo è anch’esso un array che deve contenere le opzioni di fatturazione per la fattura stessa:

    $user->invoicePrice('price_tshirt', 5, [
        'discounts' => [
            ['coupon' => 'SUMMER21SALE']
        ],
    ], [
        'default_tax_rates' => ['txr_id'],
    ]);

In modo simile a invoicePrice, puoi usare il metodo tabPrice per creare un addebito una tantum per più articoli (fino a 250 articoli per fattura) aggiungendoli al "conto" del cliente e poi fatturando il cliente. Ad esempio, possiamo fatturare a un cliente cinque magliette e due tazze:

    $user->tabPrice('price_tshirt', 5);
    $user->tabPrice('price_mug', 2);
    $user->invoice();

Alternativamente, puoi usare il metodo invoiceFor per effettuare un addebito "una tantum" sul metodo di pagamento predefinito del cliente:

    $user->invoiceFor('One Time Fee', 500);

Sebbene il metodo invoiceFor sia disponibile per te, è raccomandato utilizzare i metodi invoicePrice e tabPrice con prezzi predefiniti. In questo modo, avrai accesso a migliori analisi e dati nel tuo dashboard Stripe riguardo le tue vendite per prodotto.

I metodi invoice, invoicePrice e invoiceFor creeranno una fattura Stripe che riproverà gli addebiti falliti. Se non desideri che le fatture ripetano gli addebiti non riusciti, dovrai chiuderle utilizzando l’API di Stripe dopo il primo addebito fallito.

Creazione di Payment Intents

Puoi creare un nuovo payment intent di Stripe invocando il metodo pay su un’istanza di modello billable. Chiamando questo metodo verrà creato un payment intent che è avvolto in un’istanza Laravel\Cashier\Payment:

use Illuminate\Http\Request;

Route::post('/pay', function (Request $request) {
    $payment = $request->user()->pay(
        $request->get('amount')
    );

    return $payment->client_secret;
});

Dopo aver creato il payment intent, puoi restituire il client secret al frontend della tua applicazione in modo che l’utente possa completare il pagamento nel proprio browser. Per saperne di più sulla costruzione di flussi di pagamento completi utilizzando i payment intents di Stripe, consulta la documentazione di Stripe.

Quando usi il metodo pay, i metodi di pagamento predefiniti abilitati nel tuo dashboard di Stripe saranno disponibili per il cliente. In alternativa, se desideri consentire solo alcuni metodi di pagamento specifici, puoi usare il metodo payWith:

use Illuminate\Http\Request;

Route::post('/pay', function (Request $request) {
    $payment = $request->user()->payWith(
        $request->get('amount'), ['card', 'bancontact']
    );

    return $payment->client_secret;
});

I metodi pay e payWith accettano l’importo del pagamento nel denominatore più basso della valuta utilizzata dalla tua applicazione. Ad esempio, se i clienti pagano in dollari statunitensi, gli importi devono essere specificati in penny.

Rimborso delle Commissioni

Se devi rimborsare una commissione Stripe, puoi usare il metodo refund. Questo metodo accetta il payment intent ID di Stripe come primo argomento:

$payment = $user->charge(100, $paymentMethodId);

$user->refund($payment->id);

Fatture

Recupero delle Fatture

Puoi facilmente recuperare un array delle fatture di un modello billable usando il metodo invoices. Il metodo invoices restituisce una collezione di istanze di Laravel\Cashier\Invoice:

    $invoices = $user->invoices();

Se vuoi includere le fatture in sospeso nei risultati, puoi usare il metodo invoicesIncludingPending:

    $invoices = $user->invoicesIncludingPending();

Puoi usare il metodo findInvoice per recuperare una fattura specifica tramite il suo ID:

    $invoice = $user->findInvoice($invoiceId);

Visualizzazione delle Informazioni della Fattura

Quando elenchi le fatture per il cliente, puoi usare i metodi della fattura per mostrare le informazioni rilevanti. Ad esempio, potresti voler elencare ogni fattura in una tabella, permettendo all’utente di scaricarle facilmente:

    <table>
        @foreach ($invoices as $invoice)
            <tr>
                <td>{{ $invoice->date()->toFormattedDateString() }}</td>
                <td>{{ $invoice->total() }}</td>
                <td><a href="/user/invoice/{{ $invoice->id }}">Download</a></td>
            </tr>
        @endforeach
    </table>

Fatture Future

Per ottenere la fattura prossima di un cliente, puoi usare il metodo upcomingInvoice:

    $invoice = $user->upcomingInvoice();

Allo stesso modo, se il cliente ha più abbonamenti, puoi anche ottenere la fattura prossima per un abbonamento specifico:

    $invoice = $user->subscription('default')->upcomingInvoice();

Anteprima delle Fatture di Abbonamento

Usando il metodo previewInvoice, puoi visualizzare un’anteprima di una fattura prima di modificare i prezzi. Questo ti permetterà di vedere come sarà la fattura del tuo cliente quando verrà effettuata una determinata modifica del prezzo:

$invoice = $user->subscription('default')->previewInvoice('price_yearly');

Puoi passare un array di prezzi al metodo previewInvoice per visualizzare in anteprima fatture con più nuovi prezzi:

$invoice = $user->subscription('default')->previewInvoice(['price_yearly', 'price_metered']);

Generazione di PDF per le Fatture

Prima di generare i PDF delle fatture, devi usare Composer per installare la libreria Dompdf, che è il renderer predefinito delle fatture per Cashier:

composer require dompdf/dompdf

All’interno di una route o di un controller, puoi usare il metodo downloadInvoice per generare un download PDF di una determinata fattura. Questo metodo genererà automaticamente la risposta HTTP necessaria per scaricare la fattura:

    use Illuminate\Http\Request;

    Route::get('/user/invoice/{invoice}', function (Request $request, string $invoiceId) {
        return $request->user()->downloadInvoice($invoiceId);
    });

Per impostazione predefinita, tutti i dati della fattura provengono dai dati del cliente e della fattura memorizzati in Stripe. Il nome del file si basa sul valore di configurazione app.name. Tuttavia, puoi personalizzare alcuni di questi dati fornendo un array come secondo argomento al metodo downloadInvoice. Questo array ti permette di personalizzare informazioni come i dettagli della tua azienda e del prodotto:

    return $request->user()->downloadInvoice($invoiceId, [
        'vendor' => 'Your Company',
        'product' => 'Your Product',
        'street' => 'Main Str. 1',
        'location' => '2000 Antwerp, Belgio',
        'phone' => '+32 499 00 00 00',
        'email' => 'info@example.com',
        'url' => 'https://example.com',
        'vendorVat' => 'BE123456789',
    ]);

Il metodo downloadInvoice consente anche di specificare un nome file personalizzato tramite il suo terzo argomento. Questo nome sarà automaticamente suffisso con .pdf:

    return $request->user()->downloadInvoice($invoiceId, [], 'my-invoice');

Renderer Personalizzato delle Fatture

Cashier consente anche di utilizzare un renderer personalizzato delle fatture. Per impostazione predefinita, Cashier utilizza l’implementazione DompdfInvoiceRenderer, che sfrutta la libreria PHP dompdf per generare le fatture di Cashier. Tuttavia, puoi utilizzare qualsiasi renderer desideri implementando l’interfaccia Laravel\Cashier\Contracts\InvoiceRenderer. Ad esempio, potresti voler generare un PDF della fattura utilizzando una chiamata API a un servizio di rendering PDF di terze parti:

    use Illuminate\Support\Facades\Http;
    use Laravel\Cashier\Contracts\InvoiceRenderer;
    use Laravel\Cashier\Invoice;

    class ApiInvoiceRenderer implements InvoiceRenderer
    {
        /**
         * Render the given invoice and return the raw PDF bytes.
         */
        public function render(Invoice $invoice, array $data = [], array $options = []): string
        {
            $html = $invoice->view($data)->render();

            return Http::get('https://example.com/html-to-pdf', ['html' => $html])->get()->body();
        }
    }

Una volta che hai implementato il contratto del renderer delle fatture, dovresti aggiornare il valore di configurazione cashier.invoices.renderer nel file di configurazione config/cashier.php della tua applicazione. Questo valore di configurazione deve essere impostato sul nome della classe della tua implementazione del renderer personalizzato.

Checkout

Cashier Stripe fornisce anche il supporto per Stripe Checkout. Stripe Checkout semplifica l’implementazione di pagine personalizzate per accettare pagamenti offrendo una pagina di pagamento predefinita e ospitata.

Questa documentazione contiene le informazioni per iniziare a usare Stripe Checkout con Cashier. Per saperne di più su Stripe Checkout, considera di consultare anche la documentazione di Stripe su Checkout.

Acquisti di Prodotti

Puoi effettuare un checkout per un prodotto esistente creato nel tuo dashboard Stripe utilizzando il metodo checkout su un modello billable. Il metodo checkout avvierà una nuova sessione di Stripe Checkout. Per impostazione predefinita, è necessario passare un ID Prezzo di Stripe:

use Illuminate\Http\Request;

Route::get('/product-checkout', function (Request $request) {
    return $request->user()->checkout('price_tshirt');
});

Se necessario, puoi anche specificare una quantità del prodotto:

use Illuminate\Http\Request;

Route::get('/product-checkout', function (Request $request) {
    return $request->user()->checkout(['price_tshirt' => 15]);
});

Quando un cliente visita questa rotta, verrà reindirizzato alla pagina di Checkout di Stripe. Per impostazione predefinita, quando un utente completa con successo o annulla un acquisto, verrà reindirizzato alla tua rotta home, ma puoi specificare URL di callback personalizzati usando le opzioni success_url e cancel_url:

use Illuminate\Http\Request;

Route::get('/product-checkout', function (Request $request) {
    return $request->user()->checkout(['price_tshirt' => 1], [
        'success_url' => route('your-success-route'),
        'cancel_url' => route('your-cancel-route'),
    ]);
});

Quando definisci l’opzione success_url per il checkout, puoi istruire Stripe ad aggiungere l’ID della sessione di checkout come parametro della stringa di query quando invoca il tuo URL. Per farlo, aggiungi la stringa letterale {CHECKOUT_SESSION_ID} alla stringa di query del tuo success_url. Stripe sostituirà questo segnaposto con l’effettivo ID della sessione di checkout:

use Illuminate\Http\Request;
use Stripe\Checkout\Session;
use Stripe\Customer;

Route::get('/product-checkout', function (Request $request) {
    return $request->user()->checkout(['price_tshirt' => 1], [
        'success_url' => route('checkout-success').'?session_id={CHECKOUT_SESSION_ID}',
        'cancel_url' => route('checkout-cancel'),
    ]);
});

Route::get('/checkout-success', function (Request $request) {
    $checkoutSession = $request->user()->stripe()->checkout->sessions->retrieve($request->get('session_id'));

    return view('checkout.success', ['checkoutSession' => $checkoutSession]);
})->name('checkout-success');

Codici Promozionali

Di default, Stripe Checkout non consente codici promozionali riscattabili dagli utenti. Fortunatamente, c’è un modo semplice per abilitarli nella tua pagina di Checkout. Per farlo, puoi usare il metodo allowPromotionCodes:

use Illuminate\Http\Request;

Route::get('/product-checkout', function (Request $request) {
    return $request->user()
        ->allowPromotionCodes()
        ->checkout('price_tshirt');
});

Single Charge Checkouts

Puoi anche effettuare un addebito semplice per un prodotto ad-hoc che non è stato creato nel tuo dashboard Stripe. Per farlo, puoi usare il metodo checkoutCharge su un modello billable e passare un importo addebitabile, un nome del prodotto e una quantità opzionale. Quando un cliente visita questa rotta, verrà reindirizzato alla pagina di Checkout di Stripe:

use Illuminate\Http\Request;

Route::get('/charge-checkout', function (Request $request) {
    return $request->user()->checkoutCharge(1200, 'T-Shirt', 5);
});

Quando usi il metodo checkoutCharge, Stripe creerà sempre un nuovo prodotto e prezzo nel tuo dashboard Stripe. Pertanto, consigliamo di creare i prodotti in anticipo nel tuo dashboard Stripe e usare invece il metodo checkout.

Subscription Checkouts

Utilizzare Stripe Checkout per gli abbonamenti richiede di abilitare il webhook customer.subscription.created nel tuo dashboard di Stripe. Questo webhook creerà il record dell’abbonamento nel tuo database e memorizzerà tutti gli elementi rilevanti dell’abbonamento.

Puoi anche usare Stripe Checkout per avviare abbonamenti. Dopo aver definito il tuo abbonamento con i metodi del builder di abbonamenti di Cashier, puoi chiamare il metodo checkout. Quando un cliente visita questa route, verrà reindirizzato alla pagina di Checkout di Stripe:

    use Illuminate\Http\Request;

    Route::get('/subscription-checkout', function (Request $request) {
        return $request->user()
            ->newSubscription('default', 'price_monthly')
            ->checkout();
    });

Come nei checkout dei prodotti, puoi personalizzare gli URL di successo e cancellazione:

    use Illuminate\Http\Request;

    Route::get('/subscription-checkout', function (Request $request) {
        return $request->user()
            ->newSubscription('default', 'price_monthly')
            ->checkout([
                'success_url' => route('your-success-route'),
                'cancel_url' => route('your-cancel-route'),
            ]);
    });

Naturalmente, puoi anche abilitare i codici promozionali per i subscription checkouts:

    use Illuminate\Http\Request;

    Route::get('/subscription-checkout', function (Request $request) {
        return $request->user()
            ->newSubscription('default', 'price_monthly')
            ->allowPromotionCodes()
            ->checkout();
    });

Sfortunatamente, Stripe Checkout non supporta tutte le opzioni di fatturazione degli abbonamenti durante l’avvio degli abbonamenti. Utilizzare il metodo anchorBillingCycleOn sul builder dell’abbonamento, impostare il comportamento delle prorate o impostare il comportamento del pagamento non avrà alcun effetto durante le sessioni di Stripe Checkout. Consulta la documentazione dell’API Stripe Checkout Session per vedere quali parametri sono disponibili.

Stripe Checkout e Periodi di Prova

Naturalmente, puoi definire un periodo di prova quando crei un abbonamento che verrà completato utilizzando Stripe Checkout:

$checkout = Auth::user()->newSubscription('default', 'price_monthly')
    ->trialDays(3)
    ->checkout();

Tuttavia, il periodo di prova deve essere di almeno 48 ore, che è il tempo minimo supportato da Stripe Checkout.

Abbonamenti e Webhooks

Ricorda che Stripe e Cashier aggiornano lo stato degli abbonamenti tramite webhooks, quindi è possibile che un abbonamento non sia ancora attivo quando il cliente torna nell’applicazione dopo aver inserito le informazioni di pagamento. Per gestire questa situazione, potresti mostrare un messaggio che informa l’utente che il pagamento o l’abbonamento è in sospeso.

Raccogliere i Tax IDs

Checkout supporta anche la raccolta del Tax ID di un cliente. Per abilitare questa funzionalità in una sessione di checkout, invoca il metodo collectTaxIds quando crei la sessione:

    $checkout = $user->collectTaxIds()->checkout('price_tshirt');

Quando questo metodo viene invocato, ai clienti sarà disponibile una nuova casella di controllo che permette loro di indicare se stanno acquistando come azienda. In tal caso, avranno l’opportunità di fornire il loro numero di Tax ID.

Se hai già configurato la raccolta automatica delle tasse nel service provider della tua applicazione, questa funzionalità sarà abilitata automaticamente e non è necessario invocare il metodo collectTaxIds.

Guest Checkout

Usando il metodo Checkout::guest, puoi avviare sessioni di checkout per gli ospiti della tua applicazione che non hanno un "account":

use Illuminate\Http\Request;
use Laravel\Cashier\Checkout;

Route::get('/product-checkout', function (Request $request) {
    return Checkout::guest()->create('price_tshirt', [
        'success_url' => route('your-success-route'),
        'cancel_url' => route('your-cancel-route'),
    ]);
});

Analogamente alla creazione di sessioni di checkout per utenti esistenti, puoi utilizzare metodi aggiuntivi disponibili sull’istanza Laravel\Cashier\CheckoutBuilder per personalizzare la sessione di checkout per gli ospiti:

use Illuminate\Http\Request;
use Laravel\Cashier\Checkout;

Route::get('/product-checkout', function (Request $request) {
    return Checkout::guest()
        ->withPromotionCode('promo-code')
        ->create('price_tshirt', [
            'success_url' => route('your-success-route'),
            'cancel_url' => route('your-cancel-route'),
        ]);
});

Dopo aver completato un checkout come ospite, Stripe può inviare un evento webhook checkout.session.completed. Assicurati di configurare il tuo webhook Stripe per inviare questo evento alla tua applicazione. Una volta abilitato il webhook nel dashboard di Stripe, puoi gestire il webhook con Cashier. L’oggetto contenuto nel payload del webhook sarà un checkout object che puoi esaminare per completare l’ordine del tuo cliente.

Gestione dei Pagamenti Falliti

A volte i pagamenti per abbonamenti o addebiti singoli possono fallire. Quando ciò accade, Cashier lancerà un’eccezione Laravel\Cashier\Exceptions\IncompletePayment che ti informa dell’accaduto. Dopo aver catturato questa eccezione, hai due opzioni su come procedere.

Innanzitutto, potresti reindirizzare il cliente alla pagina dedicata di conferma del pagamento inclusa con Cashier. Questa pagina ha già una route nominata associata registrata tramite il service provider di Cashier. Quindi, puoi catturare l’eccezione IncompletePayment e reindirizzare l’utente alla pagina di conferma del pagamento:

use Laravel\Cashier\Exceptions\IncompletePayment;

try {
    $subscription = $user->newSubscription('default', 'price_monthly')
                            ->create($paymentMethod);
} catch (IncompletePayment $exception) {
    return redirect()->route(
        'cashier.payment',
        [$exception->payment->id, 'redirect' => route('home')]
    );
}

Nella pagina di conferma del pagamento, il cliente sarà invitato a inserire nuovamente le informazioni della propria carta di credito e a eseguire eventuali azioni aggiuntive richieste da Stripe, come la conferma "3D Secure". Dopo aver confermato il pagamento, l’utente sarà reindirizzato all’URL fornito dal parametro redirect specificato sopra. Al momento del reindirizzamento, alle query string saranno aggiunte le variabili message (stringa) e success (intero). La pagina di pagamento supporta attualmente i seguenti tipi di metodi di pagamento:

  • Carte di Credito
  • Alipay
  • Bancontact
  • BECS Direct Debit
  • EPS
  • Giropay
  • iDEAL
  • SEPA Direct Debit

In alternativa, potresti lasciare che Stripe gestisca la conferma del pagamento per te. In questo caso, invece di reindirizzare alla pagina di conferma del pagamento, puoi configurare le email di fatturazione automatica di Stripe nel tuo dashboard di Stripe. Tuttavia, se viene catturata un’eccezione IncompletePayment, dovresti comunque informare l’utente che riceverà un’email con ulteriori istruzioni per la conferma del pagamento.

Le eccezioni di pagamento possono essere generate per i seguenti metodi: charge, invoiceFor e invoice sui modelli che utilizzano il trait Billable. Quando si interagisce con gli abbonamenti, il metodo create sul SubscriptionBuilder, e i metodi incrementAndInvoice e swapAndInvoice sui modelli Subscription e SubscriptionItem possono generare eccezioni di pagamento incompleto.

Per determinare se un abbonamento esistente ha un pagamento incompleto, puoi utilizzare il metodo hasIncompletePayment sul modello billable o su un’istanza di abbonamento:

if ($user->hasIncompletePayment('default')) {
    // ...
}

if ($user->subscription('default')->hasIncompletePayment()) {
    // ...
}

Puoi determinare lo stato specifico di un pagamento incompleto ispezionando la proprietà payment sull’istanza dell’eccezione:

use Laravel\Cashier\Exceptions\IncompletePayment;

try {
    $user->charge(1000, 'pm_card_threeDSecure2Required');
} catch (IncompletePayment $exception) {
    // Ottieni lo stato dell'intento di pagamento...
    $exception->payment->status;

    // Verifica condizioni specifiche...
    if ($exception->payment->requiresPaymentMethod()) {
        // ...
    } elseif ($exception->payment->requiresConfirmation()) {
        // ...
    }
}

Conferma dei Pagamenti

Alcuni metodi di pagamento richiedono dati aggiuntivi per confermare i pagamenti. Ad esempio, i metodi di pagamento SEPA richiedono dati aggiuntivi come il "mandato" durante il processo di pagamento. Puoi fornire questi dati a Cashier utilizzando il metodo withPaymentConfirmationOptions:

$subscription->withPaymentConfirmationOptions([
    'mandate_data' => '...',
])->swap('price_xxx');

Puoi consultare la documentazione dell’API Stripe per rivedere tutte le opzioni accettate durante la conferma dei pagamenti.

Strong Customer Authentication

Se la tua azienda o uno dei tuoi clienti si trova in Europa, dovrai rispettare le normative dell’UE sulla Strong Customer Authentication (SCA). Queste regole sono state introdotte nel settembre 2019 dall’Unione Europea per prevenire frodi nei pagamenti. Fortunatamente, Stripe e Cashier sono pronti per creare applicazioni conformi alla SCA.

Prima di iniziare, consulta la guida di Stripe su PSD2 e SCA e la loro documentazione sulle nuove API SCA.

Pagamenti che Richiedono Conferma Aggiuntiva

Le normative SCA spesso richiedono una verifica aggiuntiva per confermare e processare un pagamento. Quando ciò accade, Cashier lancerà un’eccezione Laravel\Cashier\Exceptions\IncompletePayment che ti informa che è necessaria una verifica extra. Maggiori informazioni su come gestire queste eccezioni possono essere trovate nella documentazione su gestire i pagamenti falliti.

Le schermate di conferma del pagamento presentate da Stripe o Cashier possono essere personalizzate in base al flusso di pagamento di una banca o emittente di carte specifica e possono includere conferma aggiuntiva della carta, un addebito temporaneo di piccolo importo, autenticazione su dispositivo separato o altre forme di verifica.

Stato Incompleto e Scaduto

Quando un pagamento necessita di ulteriore conferma, l’abbonamento rimarrà in uno stato incomplete o past_due come indicato dalla colonna del database stripe_status. Cashier attiverà automaticamente l’abbonamento del cliente non appena la conferma del pagamento sarà completata e la tua applicazione sarà notificata da Stripe tramite webhook della sua conclusione.

Per ulteriori informazioni sugli stati incomplete e past_due, consulta la nostra documentazione aggiuntiva su questi stati.

Notifiche di Pagamento Off-Session

Poiché le normative SCA richiedono ai clienti di verificare occasionalmente i propri dettagli di pagamento anche mentre l’abbonamento è attivo, Cashier può inviare una notifica al cliente quando è necessaria la conferma del pagamento off-session. Ad esempio, ciò può verificarsi quando un abbonamento si rinnova. La notifica di pagamento di Cashier può essere attivata impostando la variabile d’ambiente CASHIER_PAYMENT_NOTIFICATION su una classe di notifica. Per impostazione predefinita, questa notifica è disabilitata. Naturalmente, Cashier include una classe di notifica che puoi utilizzare per questo scopo, ma puoi fornire la tua classe di notifica se lo desideri:

CASHIER_PAYMENT_NOTIFICATION=Laravel\Cashier\Notifications\ConfirmPayment

Per garantire che le notifiche di conferma del pagamento off-session vengano consegnate, verifica che i webhook di Stripe siano configurati per la tua applicazione e che il webhook invoice.payment_action_required sia abilitato nel tuo dashboard di Stripe. Inoltre, il tuo modello Billable dovrebbe utilizzare anche il trait Illuminate\Notifications\Notifiable di Laravel.

Le notifiche verranno inviate anche quando i clienti effettuano manualmente un pagamento che richiede ulteriori conferme. Sfortunatamente, non esiste un modo per Stripe di sapere se il pagamento è stato fatto manualmente o "off-session". Tuttavia, un cliente vedrà semplicemente un messaggio di "Pagamento Effettuato con Successo" se visita la pagina di pagamento dopo aver già confermato il proprio pagamento. Il cliente non potrà accidentalmente confermare lo stesso pagamento due volte e incorrere in un addebito secondario accidentale.

Stripe SDK

Molti oggetti di Cashier sono wrapper attorno agli oggetti dello Stripe SDK. Se vuoi interagire direttamente con gli oggetti Stripe, puoi recuperarli facilmente usando il metodo asStripe:

$stripeSubscription = $subscription->asStripeSubscription();

$stripeSubscription->application_fee_percent = 5;

$stripeSubscription->save();

Puoi anche utilizzare il metodo updateStripeSubscription per aggiornare direttamente una sottoscrizione Stripe:

$subscription->updateStripeSubscription(['application_fee_percent' => 5]);

Puoi usare il metodo stripe sulla classe Cashier se desideri utilizzare direttamente il client Stripe\StripeClient. Ad esempio, potresti usare questo metodo per accedere all’istanza di StripeClient e ottenere una lista di prezzi dal tuo account Stripe:

use Laravel\Cashier\Cashier;

$prices = Cashier::stripe()->prices->all();

Testing

Quando testi un’applicazione che utilizza Cashier, puoi simulare le richieste HTTP effettive all’API di Stripe; tuttavia, questo richiede di riimplementare parzialmente il comportamento di Cashier. Perciò, consigliamo di permettere ai tuoi test di interagire direttamente con l’API di Stripe. Anche se è più lento, ti dà maggiore sicurezza che l’applicazione funzioni come previsto e i test lenti possono essere inseriti nel proprio gruppo di test Pest/PHPUnit.

Durante i test, ricorda che Cashier ha già una ottima suite di test, quindi dovresti concentrarti solo sul testare il flusso di abbonamento e pagamento della tua applicazione e non ogni comportamento sottostante di Cashier.

Per iniziare, aggiungi la versione testing del tuo segreto Stripe al file phpunit.xml:

    <env name="STRIPE_SECRET" value="sk_test_<your-key>"/>

Ora, ogni volta che interagisci con Cashier durante i test, verranno inviate richieste API effettive all’ambiente di testing di Stripe. Per comodità, dovresti precompilare il tuo account di testing Stripe con abbonamenti/prezzi che puoi utilizzare durante i test.

Per testare una varietà di scenari di fatturazione, come rifiuti e fallimenti delle carte di credito, puoi utilizzare l’ampia gamma di numeri di carte di test e token forniti da Stripe.

Lascia un commento

Lascia un commento

Il tuo indirizzo email non sarà pubblicato. I campi obbligatori sono contrassegnati *