Weave Code
Weaver
Helps Laravel developers discover, compare, and choose open-source packages. See popularity, security, maintainers, and scores at a glance to make better decisions.
Feedback
Share your thoughts, report bugs, or suggest improvements.
Subject
Message

Appstore Server Notifications Laravel Package

szohan/appstore-server-notifications

A Laravel package for handling Apple App Store Server Notifications. Receive webhook callbacks, decode signed notification payloads, and process subscription and transaction events in your PHP application.

View on GitHub
Deep Wiki
Context7

Getting Started

  1. Install and publish config

    composer require szohan/appstore-server-notifications
    php artisan vendor:publish --provider="Szohan\AppStoreServerNotifications\ServiceProvider"
    

    The exact publish tag is worth checking in the README — packages this small often publish a single appstore.php config file. Look there first for the route path, environment toggle (sandbox vs. production), and your bundle ID.

  2. Configure the essentials — minimally you need your Apple bundle ID and a flag for which Apple environment the endpoint is serving. Set these in .env rather than editing config directly, especially if you plan to run sandbox and production endpoints from the same codebase.

  3. Find the route. The package is a "request handler," so the main value is a pre-wired POST endpoint (something like /appstore/notifications). Check routes/ in the package or php artisan route:list | grep -i app — you'll either need to register it yourself or it's auto-loaded. Confirm before wiring it into App Store Connect.

  4. Wire it into App Store Connect. Under App Information → App Store Server Notifications, set the Sandbox URL to your staging endpoint and the Production URL to your live one. Start with sandbox — this is where you'll iterate.

  5. First use case: receive a DID_RENEW or INITIAL_BUY notification, decode the payload, and log it. That's the smallest useful loop. Once you can see a decoded payload in storage/logs/laravel.log, you're ready to build real handlers.

Implementation Patterns

Event-listener dispatch. Most packages in this category decode the JWS payload and dispatch an event (or expose a callback) keyed on notificationType. Rather than one giant switch, register dedicated listeners per type: SUBSCRIBED, DID_RENEW, EXPIRED, DID_FAIL_TO_RENEW, REFUND, GRACE_PERIOD_EXPIRED. Keep them small and let a shared subscription-state service do the actual mutation.

Persist first, process second. Always write the raw notification (with its notificationUUID) to an apple_notifications table before doing any work. This gives you an audit trail, a replay mechanism if you break a handler, and — critically — an idempotency key. Use notificationUUID as a unique index; Apple retries aggressively and you will see duplicates.

Reconcile, don't reimplement. Notifications are a hint that something changed, not a source of truth for entitlement. Use the transactionId / originalTransactionId in the payload to look up your local subscription record and reconcile. When in doubt, call the App Store Server API to fetch the current transaction state — never derive "is this user still subscribed?" purely from the notification type.

Queue the side effects. The endpoint handler should verify the payload, persist it, and return 200 — nothing more. Dispatch jobs for emails, entitlement flips, dunning emails, refund handling. This keeps the request fast (Apple times out) and lets you retry failures internally rather than relying on Apple's retry window.

Test with a real payload. App Store Connect has a "Request a Test Notification" button — use it. Also keep a fixture of a real signed payload in tests/ and feed it through your handler with a mocked verifier so you can unit-test listeners without hitting Apple.

Gotchas and Tips

  • Never trust the body without verifying the JWS. The outer signedPayload is a JWS signed by Apple. Verify against Apple's root certificates (AppleRootCA-G3.cer etc.). If the package does this for you, good — confirm it, because some lightweight handlers only base64-decode and call it a day. That's a security hole.
  • It's nested JWS, not a single layer. For V2 notifications, signedPayload decodes to a JSON object with data.signedTransactionInfo and data.signedRenewalInfo, each of which is another JWS that needs independent decoding. If your handler assumes one flat payload, you'll get garbled data.
  • Apple retries on any non-2xx, and on timeouts. Return 200 as fast as possible. If your handler throws, wrap it — an uncaught exception bubbles up as a 500 and you'll get the same notification re-delivered for hours.
  • Duplicates are normal. At-least-once delivery. Idempotency via notificationUUID is not optional.
  • Sandbox vs. production is not just a URL. The payload's environment field tells you which Apple environment sent it. A sandbox notification landing on your production endpoint means misconfiguration — reject or log loudly.
  • Certificate rotation. Apple rotates root CAs. If the package pins a certificate at install time, you'll silently break in a year. Prefer implementations that fetch Apple's certs dynamically or at least document the update path.
  • Adoption risk. Zero stars and zero dependents means: pin the exact version in composer.json, read the package source before relying on it, and have a plan B. Apple's official apple/app-store-server-library-php is the safest fallback if the package stalls — it handles JWS verification and the notification schema authoritatively.
  • Debugging tip: if verification fails and you can't tell why, log the raw signedPayload alongside the exception. Payloads are large; truncate in logs but keep the full version in a dead-letter table. You'll need it to reproduce.
Weaver

How can I help you explore Laravel packages today?

Conversation history is not saved when not logged in.
Prompt
Add packages to context
No packages found.
socialdept/tenant-domains
tautvydasr/blade-class-names
socialdept/color-scales
maherelgamil/controller
coleus/widgets
coleus/table
coleus/users
coleus/music
coleus/health
coleus/calendar
coleus/notes
coleus/support
coleus/settings
coleus/apps
seampact/laravel
emmyconceptng/laravel-ng-postcode
jjsquady/round-robin
skyraptor/chatter
edlugz/sasapay
abbasudo/artisan-route