NewWe open-sourced 50+ Laravel packages
Custom AI apps, agents and automation — Roundly ConsultingRoundly
All packages

Open source

Purchases for Laravel

Install
composer require roundly-consulting/purchases-for-laravel
Requires: PHP ^8.4 · Laravel ^12.0|^13.0

Overview

A unified in-app purchase and payments toolkit for Laravel: one API for Apple App Store, Google Play and Stripe purchases and subscriptions. It verifies every store’s signed payload natively, decodes it into one provider-agnostic result, records it as Eloquent models and fires lifecycle events you can listen to — including refunds, chargebacks and grace periods. MIT-licensed and built only on Laravel’s HTTP client and Roundly’s own crypto, enums and money packages — no stripe/stripe-php, no google/apiclient, no third-party SDKs.

What you get

One API, three stores

Apple App Store, Google Play and Stripe behind a single Purchases facade — verify, decode and record in one call.

Native verification

ES256 JWS with pinned Apple certificates, Google’s OAuth2 JWT-bearer grant and Stripe HMAC webhooks — no SDKs.

Unified result contract

Every payload maps to one ProviderResult: type, status, price, dates, line items and the raw payload.

Models, scopes & events

Purchases, subscriptions and refunds as Eloquent models, with lifecycle events for grace periods and chargebacks.

Exact money

Prices as arbitrary-precision Money in minor units, converted with each store’s own rules.

Audit, queue & replay

Log every verified payload, persist on a queue, and replay stored notifications with one command.

Facade, DI or actions

One Purchases facade over an injectable PurchasesManager and public actions, plus a recording fake that still runs the real pipeline.

Documentation

Installation

Install via Composer, publish the publish-only migrations, and optionally publish the config and the webhook routes file.

Configuration

Every config key and env variable — models, providers, audit, queue, webhook routes and Apple, Google and Stripe credentials.

The Purchases facade

Every Purchases facade method — result() and handle() for requests, sync() and replay() for held results, for($owner) and provider lookups.

DI and actions

Inject PurchasesManager instead of calling the facade, or run the action behind handle(), sync() or replay() — the same code either way.

Unified result contract

Every provider maps to one ProviderResult — type, status, ids, price, dates, line items and the raw store payload.

Recording pipeline

How handle(), sync() and replay() turn a result into a Purchase, Subscription or PurchaseRefund — audited, idempotent, events only on change.

Events

Ten lifecycle events — purchases, subscriptions, grace periods, refunds and chargebacks — each carrying the model and the result.

Models & the owner trait

Six swappable Eloquent models, the HasPurchases owner trait, subscription scopes and helpers, and the database schema.

Money & prices

Prices as arbitrary-precision money-for-laravel Money, cast over two columns and converted exactly from each store’s format.

Refunds & chargebacks

Apple, Google and Stripe refunds and disputes decode into PurchaseRefund records linked to the purchase they reverse.

Apple App Store

Verify signed App Store server notifications, look up transactions via the App Store Server API, and map Apple’s states.

Google Play

Verify one-time products and subscriptionsv2 purchases, auto-acknowledge them, and decode real-time developer notifications.

Stripe

Verify Stripe webhook signatures natively, map payment, subscription, invoice and dispute events, and read REST objects.

Signature verification & trust

How each store’s signature is verified — crypto-for-laravel primitives, pinned Apple certificates and a validated clock-skew leeway.

Webhook routes

An opt-in POST /purchases/webhooks/{provider} endpoint that verifies, records, fires events and answers 204.

Queue, audit log & replay

Persist verified notifications on a queue, keep a replayable audit log of every payload, and re-run it with purchases:replay.

Custom providers

Add a payment provider of your own by implementing the Provider contract and returning a GenericResult.

Enums & exceptions

The Status and ResultType enums with select-option and validation helpers, and the package’s exception types.

Artisan commands

Install and configure providers, list their readiness, verify credentials against the live stores, and replay notifications.

Testing

Test purchase flows without real payments or network calls — Purchases::fake() records handle(), sync() and replay(); FakeResult and PayloadFactory.

Requirements

PHP 8.4+ with ext-bcmath, Laravel 12 or 13, and Roundly’s crypto, enums and money packages — no third-party SDKs.

Show your open-source love

This package is free and MIT-licensed. If it saves you time, a one-off donation or a Patreon membership keeps it maintained, tested and documented.

More ways to support, including crypto

By donating, you agree to our donation terms.

Want this built into your product?

We integrate our packages into custom Laravel and AI builds. Tell us what you're working on and we'll reply within 48 hours.