aporat / store-receipt-validator
PHP receipt validator for Apple iTunes, Google Play and Amazon App Store
Fund package maintenance!
aporat
Installs: 3 464 178
Dependents: 7
Suggesters: 0
Security: 0
Stars: 640
Watchers: 23
Forks: 151
Open Issues: 1
Requires
- php: ^8.3
- ext-json: *
- ext-openssl: *
- guzzlehttp/guzzle: ^7.0
- lcobucci/clock: ^3.3
- lcobucci/jwt: ^5.5
- nesbot/carbon: ^2.72.6|^3.0
- phpseclib/phpseclib: ^3.0
Requires (Dev)
- mockery/mockery: ^1.6
- phpstan/phpstan: ^1.11
- phpunit/phpunit: ^12.0
- squizlabs/php_codesniffer: ^3.6
Suggests
- codecov/codecov-php: Helps send coverage reports to codecov.io
- dev-main
- 6.0.4
- 6.0.2
- 6.0.0
- 5.0.1
- 5.0.0
- 4.4.3
- 4.4.2
- 4.4.1
- 4.4.0
- 4.3.0
- 4.2.0
- 4.1.0
- 4.0.3
- 4.0.2
- 4.0.1
- 4.0.0
- 3.5.0
- 3.4.1
- 3.4.0
- 3.3.0
- 3.2.0
- 3.1.0
- 3.0.0
- 2.2.0
- 2.1.0
- 2.0.6
- 2.0.4
- 2.0.2
- 2.0.0
- 1.5.0
- 1.4.1
- 1.4.0
- 1.3.1
- 1.3.0
- 1.2.1
- 1.2.0
- 1.1.1
- 1.1.0
- 1.0.13
- 1.0.12
- 1.0.11
- 1.0.10
- 1.0.9
- 1.0.8
- 1.0.7
- 1.0.6
- 1.0.5
- 1.0.4
- 1.0.2
- 1.0.0
This package is auto-updated.
Last update: 2025-04-22 18:11:33 UTC
README
A modern PHP library for validating in-app purchase receipts from Apple iTunes, and Amazon App Store. Supports production and sandbox environments with detailed response parsing.
๐ฆ Requirements
- PHP >= 8.3
๐ฅ Installation
composer require aporat/store-receipt-validator
๐ Quick Start
๐ฒ Apple App Store Server API
use ReceiptValidator\AppleAppStore\ReceiptUtility; use ReceiptValidator\AppleAppStore\Validator as AppleValidator; use ReceiptValidator\Environment; // Credentials $signingKey = file_get_contents($root . '/examples/SubscriptionKey_RA9DAYVX3X.p8'); $keyId = 'RA9DAYVX3X'; $issuerId = 'xxxxxx-xxxx-xxxx-xxxx-xxxxxxx'; $bundleId = 'com.myapp'; $receiptBase64Data = '...'; // your app receipt here $transactionId = ReceiptUtility::extractTransactionIdFromAppReceipt($receiptBase64Data); $validator = new AppleValidator( signingKey: $signingKey, keyId: $keyId, issuerId: $issuerId, bundleId: $bundleId, environment: Environment::PRODUCTION ); try { $response = $validator->setTransactionId($transactionId)->validate(); } catch (Exception $e) { echo 'Error validating transaction: ' . $e->getMessage() . PHP_EOL; exit(1); } echo 'Validation successful.' . PHP_EOL; echo 'Bundle ID: ' . $response->getBundleId() . PHP_EOL; echo 'App Apple ID: ' . $response->getAppAppleId() . PHP_EOL; foreach ($response->getTransactions() as $transaction) { echo 'getProductId: ' . $transaction->getProductId() . PHP_EOL; echo 'getTransactionId: ' . $transaction->getTransactionId() . PHP_EOL; if ($transaction->getPurchaseDate() != null) { echo 'getPurchaseDate: ' . $transaction->getPurchaseDate()->toIso8601String() . PHP_EOL; } }
๐ Apple iTunes (Deprecated)
use ReceiptValidator\Environment; use ReceiptValidator\iTunes\Validator as iTunesValidator; $validator = new iTunesValidator(Environment::PRODUCTION); try { $response = $validator->setSharedSecret('SHARED_SECRET')->setReceiptData('BASE64_RECEIPT')->validate(); } catch (Exception $e) { echo 'got error = ' . $e->getMessage() . PHP_EOL; echo $e->getTraceAsString() . PHP_EOL; exit; } echo 'Receipt is valid.' . PHP_EOL; echo 'getBundleId: ' . $response->getBundleId() . PHP_EOL; foreach ($response->getPurchases() as $purchase) { echo 'getProductId: ' . $purchase->getProductId() . PHP_EOL; echo 'getTransactionId: ' . $purchase->getTransactionId() . PHP_EOL; if ($purchase->getPurchaseDate() != null) { echo 'getPurchaseDate: ' . $purchase->getPurchaseDate()->toIso8601String() . PHP_EOL; } }
๐ Amazon App Store
use ReceiptValidator\Amazon\Validator; use ReceiptValidator\Amazon\Response; $validator = new Validator(); try { $response = $validator->setDeveloperSecret('SECRET')->setReceiptId('RECEIPT_ID')->setUserId('USER_ID')->validate(); } catch (Exception $e) { echo 'got error = ' . $e->getMessage() . PHP_EOL; echo $e->getTraceAsString() . PHP_EOL; exit; } echo 'Receipt is valid.' . PHP_EOL; foreach ($response->getPurchases() as $purchase) { echo 'getProductId: ' . $purchase->getProductId() . PHP_EOL; if ($purchase->getPurchaseDate() != null) { echo 'getPurchaseDate: ' . $purchase->getPurchaseDate()->toIso8601String() . PHP_EOL; } }
๐ฌ Apple App Store Server Notifications
๐ V2 Notifications (App Store Server API)
use ReceiptValidator\AppleAppStore\ServerNotification; use ReceiptValidator\Exceptions\ValidationException; public function subscriptions(Request $request): JsonResponse { try { $notification = new ServerNotification($request->all()); echo 'Type: ' . $notification->getNotificationType()->value . PHP_EOL; echo 'Subtype: ' . ($notification->getSubtype()?->value ?? 'N/A') . PHP_EOL; echo 'Bundle: ' . $notification->getBundleId() . PHP_EOL; $tx = $notification->getTransaction(); if ($tx !== null) { echo 'Transaction ID: ' . $tx->getTransactionId() . PHP_EOL; } $renewalInfo = $notification->getRenewalInfo(); if ($renewalInfo !== null) { echo 'Auto Renew Product: ' . $renewalInfo->getAutoRenewProductId() . PHP_EOL; } } catch (ValidationException $e) { echo 'Invalid notification: ' . $e->getMessage(); } }
๐ V1 Notifications (iTunes) (Deprecated)
use ReceiptValidator\iTunes\ServerNotification; use ReceiptValidator\Exceptions\ValidationException; public function subscriptions(Request $request): JsonResponse { $sharedSecret = 'your_shared_secret'; try { $notification = new ServerNotification($request->all(), $sharedSecret); echo 'Type: ' . $notification->getNotificationType()->value . PHP_EOL; echo 'Bundle: ' . $notification->getBundleId() . PHP_EOL; $latestReceipt = $notification->getLatestReceipt(); $transactions = $latestReceipt->getTransactions(); foreach ($transactions as $tx) { echo 'Transaction ID: ' . $tx->getTransactionId() . PHP_EOL; } } catch (ValidationException $e) { echo 'Invalid notification: ' . $e->getMessage(); } }
๐งช Testing
composer test composer check # Run code style checks (PHP_CodeSniffer) composer analyze # Run static analysis (PHPStan)
๐ Contributing
Contributions are welcome! Feel free to:
- Fork this repo
- Create a feature branch
- Submit a pull request
Found a bug or want a new feature? Open an issue