Google Play Billing
A managed Real-Time Developer Notifications endpoint — Pub/Sub ingestion, service-account lookups against the Play Developer API, idempotent events, and a normalised lifecycle stream that speaks the same shape as Apple and Stripe.
Ship the integration in minutes with the Stubkit SDK — the receipt flow, retries, and idempotency are handled server-side.
// Stubkit ingests Google Play RTDN messages through a Pub/Sub push
// subscription, looks up the authoritative purchase state via the Google
// Play Developer API, and emits normalised lifecycle events to your server.
import { Stubkit } from '@stubkit/js';
const stubkit = new Stubkit({ apiKey: process.env.STUBKIT_SECRET_KEY });
// Same handler, same event shape, regardless of whether the purchase
// originated on Apple, Google, or Stripe.
app.post('/webhooks/stubkit', async (req, res) => {
const event = stubkit.verifyWebhook(req.body, req.headers['stubkit-signature']);
if (event.type === 'subscription.activated') {
await grantEntitlement(event.data.user_id, event.data.entitlement);
} else if (event.type === 'subscription.canceled') {
await revokeEntitlement(event.data.user_id, event.data.entitlement);
}
res.sendStatus(200);
});RTDN is Google Play's push channel for subscription and one-time purchase lifecycle events. Instead of polling the Play Developer API, Google pushes a Pub/Sub message to a topic you own whenever a subscription changes state — renewal, hold, paused, canceled, expired, recovered, or deferred.
Yes. Each app gets a managed Pub/Sub subscription URL. Paste the package name and topic ID into the Play Console, and Stubkit's push handler receives every notification directly — no Google Cloud project or service account management on your side.
On every RTDN message, Stubkit calls the Google Play Developer API with a per-account service account to fetch the authoritative purchase record. The RTDN payload alone is not treated as authoritative — the subscription state is always reconciled against Google's API response before updating your entitlement.
Every RTDN event is keyed on Google's purchaseToken with a unique constraint, so duplicate messages (which Google regularly sends) are de-duplicated server-side. Your backend never sees the same event twice.
Stubkit tracks the full lifecycle — onHold, paused, inGracePeriod, revoked, restarted — and translates it into entitlement-level granted / revoked state with a reason field. You receive a single normalised event per lifecycle transition.
Yes. Every Stubkit app has a sandbox environment wired up to internal test tracks, so test subscriptions are processed identically to production but kept in a separate event stream. Switching between environments is a single dashboard toggle.
Free forever on the starter tier. Full SDK support for iOS, Android, web, and server environments.
Start freeAlready integrated? See pricing