---
title: "Google Play — Purchases for Laravel | Roundly"
description: "Overujte jednorazové produkty a nákupy subscriptionsv2, automaticky ich potvrdzujte a dekódujte real-time developer notifikácie."
url: https://roundly-consulting.com/sk/open-source/navody/purchases-for-laravel/google-play
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)

# Google Play

Poskytovateľ Google (id google) overuje nákupy cez Play Developer API a autentifikuje sa servisným účtom cez natívny OAuth2 JWT-bearer grant s cache prístupových tokenov. Real-time developer notifikácie doručené cez Pub/Sub sa dekódujú do typovaného DeveloperNotification:

```php
use RoundlyConsulting\Purchases\Facades\Purchases;
use RoundlyConsulting\Purchases\Providers\Google\Google;

$google = app(Google::class);

$product = $google->product('coins.100', $purchaseToken);   // ProductPurchase
$product->orderId;
$product->purchaseTime;                                     // ?Carbon

$subscription = $google->subscription($purchaseToken);      // SubscriptionPurchase (acknowledged by default)
$subscription->subscriptionState;                           // ?SubscriptionState
$subscription->expiryTime();                                // ?Carbon
$subscription->price();                                     // ?Money — sum of the line items

$google->acknowledgeSubscription($purchaseToken, $subscription->productId());   // manual acknowledgement
$google->notification($request);                            // DeveloperNotification (RTDN)

// A token your app sent up ({purchaseToken, productId?}), verified and mapped — then recorded.
Purchases::sync($google->callbackResult($request));
```

## Pravidlá overenia

- product() vyhodí VerificationException, ak nákup nie je v stave zakúpený.
- subscription() vyhodí VerificationException, len ak predplatné expirovalo. Zrušené predplatné — s vypnutým automatickým obnovením — si prístup ponechá do expirácie, takže overenie prejde a obnovenie nákupu funguje.
- Obe metódy nákup v Google potvrdia, ak je acknowledge zapnuté (predvolene) a nákup ešte potvrdený nie je. Predplatné sa potvrdzuje cez purchases.subscriptions.acknowledge v Play Developer API s identifikátorom produktu (subscriptionsv2 metódu acknowledge nemá). Nastavením PURCHASES\_GOOGLE\_ACKNOWLEDGE=false to vypnete a acknowledgeSubscription($token, $subscriptionId) voláte sami. Každé potvrdenie posiela ako telo JSON objekt ({}), ako to Google vyžaduje.
- Každý segment cesty v Play Developer API — package name, identifikátor produktu, identifikátor predplatného, token — je percentuálne zakódovaný a prázdny segment, . alebo .. sa odmietne („Malformed Google id.“) ešte pred volaním Google, takže podvrhnutá hodnota sa nedostane na iný endpoint.
- product() a subscription() sú priame vyhľadania: chybová odpoveď Google zostane ako RequestException z HTTP klienta.

## Autentifikácia RTDN pushov

Pub/Sub push je obyčajný HTTPS POST, ktorý môže podvrhnúť ktokoľvek, preto notification() a result() — a teda aj handle() a webhook routa — každú požiadavku bez ohľadu na jej telo najprv autentifikujú ako push, a to bezpečne v predvolenom stave: bez konfigurácie sa odmietne každý push (routa vráti 400). V Google Cloud upravte push subscription, zapnite autentifikáciu so servisným účtom a audience a nastavte tie isté dve hodnoty:

```bash
# Google Cloud: push subscription → Enable authentication (service account + audience)
PURCHASES_GOOGLE_PUSH_AUDIENCE=https://your-app.test/purchases/webhooks/google
PURCHASES_GOOGLE_PUSH_SERVICE_ACCOUNT=rtdn-push@my-project.iam.gserviceaccount.com

# Optional, alone or on top: …/webhooks/google?token=<secret>
PURCHASES_GOOGLE_PUSH_TOKEN=

# Only when something upstream already authenticated the message
PURCHASES_GOOGLE_PUSH_AUTHENTICATE=true
```

OIDC token z hlavičky Authorization: Bearer každého pushu sa potom overí cez crypto-for-laravel — podpis RS256 voči JWKS od Google (v cache, pri rotácii kľúča načítaný znova najviac raz za minútu), vydavateľ accounts.google.com, audience, e-mail servisného účtu, email\_verified a expirácia. Voliteľný tajný ?token= sa porovnáva v konštantnom čase. PURCHASES\_GOOGLE\_PUSH\_AUTHENTICATE=false nastavte len vtedy, keď už overené správy odovzdáva do Purchases::handle() váš vlastný pull subscriber.

## Len notifikácie vašej aplikácie

Autentifikácia pushu dokazuje, že správu poslal Google, nie to, ktorej aplikácie sa týka. RTDN, ktorej packageName nie je váš PURCHASES\_GOOGLE\_PACKAGE\_NAME — iná aplikácia na zdieľanej téme Pub/Sub alebo notifikácia bez uvedeného package name —, je informatívny výsledok Notification: zaznamená sa do auditu a dostane odpoveď 204, nikdy sa neuplatní, nevyhľadáva sa pod vašou aplikáciou a znova sa nedoručí.

## Nákupné tokeny z klienta

Nákupný token z klienta nie je push, preto ho webhook routa nikdy neprijme. Overte ho vo vlastnej autentifikovanej route cez product(), subscription() alebo callbackResult() — purchaseToken spolu s productId pre jednorazový produkt, samotný purchaseToken pre predplatné — a uložte ho cez Purchases::sync():

```php
use RoundlyConsulting\Purchases\Facades\Purchases;
use RoundlyConsulting\Purchases\Providers\Google\Google;

// In your own authenticated route — never the webhook route:
// { "purchaseToken": "…", "productId": "coins.100" }   → one-time product
// { "purchaseToken": "…" }                              → subscription
$model = Purchases::sync(app(Google::class)->callbackResult($request));
```

callback() aj callbackResult() odmietnu chýbajúci, prázdny alebo nereťazcový purchaseToken a productId, ktoré je prítomné, no nie je reťazcom, ešte pred volaním Google; chýbajúce alebo prázdne productId znamená predplatné. Token, ktorý Google odmietne s 4xx — 400 neznámy, 410 už neplatný —, je tiež VerificationException, kým odmietnuté prístupové údaje, nesprávne package\_name, limity požiadaviek a výpadky zostanú RequestException: pozrite Callbacky z klienta.

## Notifikácie o predplatnom

RTDN hovorí len to, že sa predplatné zmenilo — bez expirácie, objednávky či ceny. Preto sa každá RTDN, ktorá mení stav predplatného (zakúpené, obnovené, obnovené po výpadku platby, znova spustené, zrušené, obdobie odkladu, pozastavené, expirované …), uloží podľa aktuálneho stavu predplatného v subscriptionsv2, ktorý balík načíta servisným účtom, ako odporúča Google: obnova posunie ends\_at dopredu a spustí SubscriptionRenewed. Toto čítanie je len GET — cesta RTDN nikdy nepotvrdzuje nákup, pretože nevie, ktorému z vašich používateľov patrí. Ak čítanie zlyhá — akoukoľvek chybovou odpoveďou okrem 410 alebo nedostupnosťou Google —, push skončí chybou 500 a Pub/Sub ho doručí znova; predplatné, ktoré Google už neeviduje (410 Gone), sa uloží len z RTDN. Prístupové údaje servisného účtu sú preto potrebné aj pre RTDN. RTDN s tokenom . alebo .. sa odmietne (400) ešte pred volaním Google.

## Mapovanie notifikácií

| Typ notifikácie Google | Stav |
| --- | --- |
| Recovered, Renewed, Purchased, Restarted, Canceled (vypnuté automatické obnovenie — prístup trvá do expirácie) | `Completed` |
| InGracePeriod | `InGracePeriod` |
| OnHold, Paused | `OnHold` |
| PendingPurchaseCanceled | `Canceled` |
| Revoked, stornovaný nákup (výsledok typu Refund) | `Refunded` |
| Expired | `Failed` |
| Deferred, PriceChangeConfirmed, PauseScheduleChanged, ItemsChanged, CancellationScheduled, PriceChangeUpdated, PriceStepUpConsentUpdated | Informatívne — len audit, nikdy sa neuplatní |

Zrušené predplatné Google — SUBSCRIPTION\_CANCELED, vypnuté automatické obnovenie — zostane v stave Completed, kým ho neukončí jeho ends\_at. Aktívnym prestane byť len expirované predplatné.

Cena predplatného je súčet opakovaných cien jeho položiek (predplatené plány cenu nemajú). Jednorazové produkty v Play Developer API cenu nenesú, preto ich price() zostáva null.

## 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)
