---
title: "Udalosti — Purchases for Laravel | Roundly"
description: "Desať udalostí životného cyklu — nákupy, predplatné, obdobie odkladu, refundácie a chargebacky — každá nesie model aj výsledok."
url: https://roundly-consulting.com/sk/open-source/navody/purchases-for-laravel/udalosti
language: sk
---

[Všetky balíky](https://roundly-consulting.com/sk/open-source.md)

[Purchases for Laravel](https://roundly-consulting.com/sk/open-source/navody/purchases-for-laravel.md)

# Udalosti

Purchases::handle(), sync(), replay(), úloha vo fronte aj purchases:replay spúšťajú udalosti z RoundlyConsulting\\Purchases\\Events. Každá nesie uložený model a pôvodný ProviderResult ako $event->result:

| Udalosť | Vlastnosť s modelom | Kedy sa spustí |
| --- | --- | --- |
| `PurchaseRecorded` | `$purchase` | Pri každom výsledku nákupu, ktorý pipeline dostane — aj pri opakovaných a zastaraných, preto na ňom objednávky nevybavujte. |
| `PurchaseCompleted` | `$purchase` | Nákup je nový alebo prešiel do stavu Completed. |
| `PurchaseFailed` | `$purchase` | Nákup je nový alebo prešiel do stavu Failed či Canceled. |
| `SubscriptionStarted` | `$subscription` | Predplatné začne: vznikne so stavom Completed alebo do Completed prejde prvýkrát, keď bolo dovtedy len New či Pending (vzniklo pred zaplatením). |
| `SubscriptionRenewed` | `$subscription` | Predplatné, ktoré už predtým platilo, sa vráti do stavu Completed (z pozastavenia, obdobia odkladu či zrušenia alebo pri obnovení pozastaveného predplatného Google) alebo sa mu predĺži ends\_at. |
| `SubscriptionInGracePeriod` | `$subscription` | Prejde do InGracePeriod — platba sa opakuje, prístup zostáva. |
| `SubscriptionCanceled` | `$subscription` | Prejde do stavu Canceled. |
| `SubscriptionExpired` | `$subscription` | Prejde do stavu Failed. |
| `PurchaseRefunded` | `$refund` | Refundácia je nová alebo sa zmenila vrátená suma. |
| `ChargebackReceived` | `$refund` | Chargeback (spor) je nový alebo sa zmenila jeho suma. |

Každý obchod môže notifikáciu doručiť viackrát aj mimo poradia a auditný log sa dá spracovať znova, preto sa udalosti životného cyklu spúšťajú len vtedy, keď sa niečo zmenilo — nový riadok, posunutý stav, obnova, ktorá predĺžila ends\_at, nová vrátená suma. Ukladanie je zoradené podľa času udalosti (pozrite Ukladanie výsledkov), takže opakovane doručená alebo znova spracovaná platba nikdy znova nevybaví refundovanú objednávku. PurchaseRecorded sa spúšťa pri každom výsledku nákupu, ktorý pipeline dostane — aj pri opakovaných a zastaraných —, preto na ňom objednávky nevybavujte; použite PurchaseCompleted. Informatívne notifikácie sa len zaznamenajú do auditu a nič nespustia.

## Počúvanie udalostí

```php
use Illuminate\Support\Facades\Event;
use RoundlyConsulting\Purchases\Events\PurchaseRefunded;
use RoundlyConsulting\Purchases\Events\SubscriptionExpired;
use RoundlyConsulting\Purchases\Events\SubscriptionStarted;

Event::listen(SubscriptionStarted::class, function (SubscriptionStarted $event): void {
    $event->subscription->owner;   // grant access
    $event->result->provider();    // 'apple', 'google' or 'stripe'
});

Event::listen(SubscriptionExpired::class, function (SubscriptionExpired $event): void {
    // revoke access
});

Event::listen(PurchaseRefunded::class, function (PurchaseRefunded $event): void {
    $event->refund->purchase;      // the refunded Purchase, when matched
});
```

## Prepojenie vlastníka

Ukladanie nikdy nenastavuje vlastníka — polymorfný stĺpec owner je voliteľný, pretože notifikácia obchodu nikdy neuvádza, ktorému z vašich používateľov patrí. Prepojte ho v listeneri podľa tokenu účtu, ktorý ste obchodu odovzdali — appAccountToken pri Apple, obfuscatedExternalAccountId pri Google, zákazník (customer) pri Stripe:

```php
use App\Models\User;
use Illuminate\Support\Facades\Event;
use RoundlyConsulting\Purchases\Events\SubscriptionStarted;

Event::listen(function (SubscriptionStarted $event): void {
    $token = $event->result->raw()['data']['transactionInfo']['appAccountToken'] ?? null;   // Apple

    if ($user = User::query()->where('app_account_token', $token)->first()) {
        $event->subscription->owner()->associate($user)->save();
    }
});
```

SubscriptionStarted sa spustí aj vtedy, keď predplatné vytvorené ešte pred zaplatením — v Stripe incomplete (3D Secure, payment\_behavior=default\_incomplete) alebo v Google v stave pending — prvýkrát začne platiť, takže tento listener beží aj pre takéto predplatné. Pozastavené predplatné Google, ktoré sa obnoví, spustí SubscriptionRenewed.

## Odobratie prístupu a integrácie

Úplná refundácia prepne spárovaný nákup na Status::Refunded (čiastočná ho ponechá v stave Completed), takže odobratie prístupu môžete naviazať na PurchaseRefunded a ChargebackReceived. Tie isté udalosti sú miestom na pripísanie či odobratie kreditov, spustenie kampaní po nákupe alebo odosielanie metrík — zapojíte ich vo svojej aplikácii, takže balík zostáva bez týchto závislostí.

Purchases môže stáť aj za platobnou bránou pre shops-for-laravel. Shops strháva platby cez kontrakt PaymentGateway, ktorý naviažete cez shops.payment.gateway. Purchases nikdy platbu nevytvára — číta a overuje to, čo už obchod strhol — takže brána vo vašej aplikácii môže cez poskytovateľa Stripe overiť PaymentIntent, ktorý kupujúci zaplatil pri pokladni, a refundácie vystaviť vlastným volaním. Ani jeden balík nezávisí od druhého:

```php
namespace App\Payments;

use App\Models\CheckoutPayment;
use Illuminate\Support\Facades\Http;
use RoundlyConsulting\Money\Money;
use RoundlyConsulting\Purchases\Providers\Stripe\Enums\PaymentIntentStatus;
use RoundlyConsulting\Purchases\Providers\Stripe\Stripe;
use RoundlyConsulting\Shops\Contracts\PaymentGateway;
use RoundlyConsulting\Shops\Orders\Order;
use RoundlyConsulting\Shops\Payments\PaymentResult;

final class StripeIntentGateway implements PaymentGateway
{
    public function __construct(private Stripe $stripe) {}

    // Confirm the PaymentIntent the buyer paid at checkout — purchases reads it from Stripe.
    public function charge(Order $order): PaymentResult
    {
        $due = $order->gatewayAmount();
        $intent = $this->stripe->paymentIntent($this->intentId($order));

        return $intent->status === PaymentIntentStatus::Succeeded && $intent->amount?->equals($due)
            ? PaymentResult::success($due, $intent->id)
            : PaymentResult::failure($due, 'Payment not confirmed.');
    }

    // purchases never writes to a store: refund with your own call. Stripe's
    // charge.refunded webhook then lands in purchases as a PurchaseRefund.
    public function refund(Order $order, Money $amount): PaymentResult
    {
        $response = Http::withToken(config('purchases.settings.stripe.secret'))->asForm()
            ->post('https://api.stripe.com/v1/refunds', [
                'payment_intent' => $this->intentId($order),
                'amount' => $amount->minorInt(),
            ]);

        return $response->successful()
            ? PaymentResult::success($amount, $response->json('id'))
            : PaymentResult::failure($amount, $response->json('error.message'));
    }

    private function intentId(Order $order): string
    {
        // Your own record of the PaymentIntent confirmed at checkout.
        return CheckoutPayment::query()->where('order_id', $order->getKey())->value('payment_intent');
    }
}

// config/shops.php — or SHOPS_PAYMENT_GATEWAY in .env
'payment' => ['gateway' => \App\Payments\StripeIntentGateway::class],
```

## Prejavte lásku k open source

Tento balík je zadarmo pod licenciou MIT. Ak vám šetrí čas, jednorazový príspevok alebo členstvo na Patreone nám pomôže ho ďalej udržiavať, testovať a dokumentovať.

[Ďalšie spôsoby podpory vrátane kryptomien](https://roundly-consulting.com/sk/podporte-nas.md)

Odoslaním daru súhlasíte s našimi [podmienkami prijímania darov](https://roundly-consulting.com/sk/podmienky-darov.md).

[Podporte našu open-source prácu (otvorí sa v novej karte)](https://donate.stripe.com/dRmeVe8FX5PF1Qd9pXcEw00) [Pridajte sa k nám na Patreone (otvorí sa v novej karte)](https://www.patreon.com/cw/roundly)

## Chcete to zabudovať do svojho produktu?

Naše balíky integrujeme do zákazkových Laravel a AI riešení. Napíšte nám, na čom pracujete, a ozveme sa do 48 hodín.

[Ponuka do 48 hodín](https://roundly-consulting.com/sk/kontakt.md) [Prezrieť všetky balíky](https://roundly-consulting.com/sk/open-source/navody/purchases-for-laravel.md)
