NovinkaZverejnili sme 50+ Laravel balíkov ako open source
Custom AI apps, agents and automation — Roundly ConsultingRoundly
Všetky balíky

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:

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.
  • Identifikátory produktov aj tokeny sa do každej cesty API vkladajú percentuálne zakódované, takže podvrhnutá hodnota sa nedostane na iný endpoint.

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:

# 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=[email protected]

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

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():

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

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á, zlyhá aj push 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.

Mapovanie notifikácií

Typ notifikácie GoogleStav
Recovered, Renewed, Purchased, Restarted, Canceled (vypnuté automatické obnovenie — prístup trvá do expirácie)Completed
InGracePeriodInGracePeriod
OnHold, PausedOnHold
PendingPurchaseCanceledCanceled
Revoked, stornovaný nákup (výsledok typu Refund)Refunded
ExpiredFailed
Deferred, PriceChangeConfirmed, PauseScheduleChanged, ItemsChanged, CancellationScheduled, PriceChangeUpdated, PriceStepUpConsentUpdatedInformatí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

Odoslaním daru súhlasíte s našimi podmienkami prijímania darov.

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.