{"id":15916867,"url":"https://github.com/aporat/store-receipt-validator","last_synced_at":"2025-05-13T22:08:12.131Z","repository":{"id":12298542,"uuid":"14928361","full_name":"aporat/store-receipt-validator","owner":"aporat","description":"PHP receipt validator for Apple iTunes, Google Play and Amazon App Store","archived":false,"fork":false,"pushed_at":"2025-05-06T01:04:46.000Z","size":1007,"stargazers_count":640,"open_issues_count":1,"forks_count":151,"subscribers_count":22,"default_branch":"main","last_synced_at":"2025-05-07T21:40:14.626Z","etag":null,"topics":["amazon","app-store","apple","in-app-purchases","itunes","php","receipt","receipt-validation","validation"],"latest_commit_sha":null,"homepage":"","language":"PHP","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/aporat.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":".github/FUNDING.yml","license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null},"funding":{"github":"aporat"}},"created_at":"2013-12-04T15:57:08.000Z","updated_at":"2025-05-06T16:54:10.000Z","dependencies_parsed_at":"2025-02-21T02:00:29.186Z","dependency_job_id":"964d9299-2ca8-46f7-90e0-678ef22e94a4","html_url":"https://github.com/aporat/store-receipt-validator","commit_stats":{"total_commits":218,"total_committers":47,"mean_commits":4.638297872340425,"dds":0.7247706422018348,"last_synced_commit":"0791b760dc4b9473d80782b85954eff15372212c"},"previous_names":[],"tags_count":50,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/aporat%2Fstore-receipt-validator","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/aporat%2Fstore-receipt-validator/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/aporat%2Fstore-receipt-validator/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/aporat%2Fstore-receipt-validator/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/aporat","download_url":"https://codeload.github.com/aporat/store-receipt-validator/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":253176434,"owners_count":21866142,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["amazon","app-store","apple","in-app-purchases","itunes","php","receipt","receipt-validation","validation"],"created_at":"2024-10-06T18:05:57.057Z","updated_at":"2025-05-13T22:08:07.082Z","avatar_url":"https://github.com/aporat.png","language":"PHP","funding_links":["https://github.com/sponsors/aporat"],"categories":[],"sub_categories":[],"readme":"\n# store-receipt-validator\n\n[![Latest Stable Version](https://img.shields.io/packagist/v/aporat/store-receipt-validator.svg?style=flat-square\u0026logo=composer)](https://packagist.org/packages/aporat/store-receipt-validator)\n[![Downloads](https://img.shields.io/packagist/dt/aporat/store-receipt-validator.svg?style=flat-square\u0026logo=composer)](https://packagist.org/packages/aporat/store-receipt-validator)\n[![Codecov](https://img.shields.io/codecov/c/github/aporat/store-receipt-validator?style=flat-square)](https://codecov.io/github/aporat/store-receipt-validator)\n![GitHub Actions](https://img.shields.io/github/actions/workflow/status/aporat/store-receipt-validator/ci.yml?style=flat-square)\n[![License](https://img.shields.io/packagist/l/aporat/store-receipt-validator.svg?style=flat-square)](LICENSE)\n\nA 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.\n\n---\n\n## 📦 Requirements\n\n- PHP \u003e= 8.3\n\n## 📥 Installation\n\n```bash\ncomposer require aporat/store-receipt-validator\n```\n\n---\n\n## 🚀 Quick Start\n\n### 📲 Apple App Store Server API\n\n```php\nuse ReceiptValidator\\AppleAppStore\\ReceiptUtility;\nuse ReceiptValidator\\AppleAppStore\\Validator as AppleValidator;\nuse ReceiptValidator\\Environment;\n\n// Credentials\n$signingKey = file_get_contents($root . '/examples/SubscriptionKey_RA9DAYVX3X.p8');\n$keyId = 'RA9DAYVX3X';\n$issuerId = 'xxxxxx-xxxx-xxxx-xxxx-xxxxxxx';\n$bundleId = 'com.myapp';\n\n$receiptBase64Data = '...'; // your app receipt here\n$transactionId = ReceiptUtility::extractTransactionIdFromAppReceipt($receiptBase64Data);\n\n$validator = new AppleValidator(\n    signingKey: $signingKey,\n    keyId: $keyId,\n    issuerId: $issuerId,\n    bundleId: $bundleId,\n    environment: Environment::PRODUCTION\n);\n\ntry {\n    $response = $validator-\u003esetTransactionId($transactionId)-\u003evalidate();\n} catch (Exception $e) {\n    echo 'Error validating transaction: ' . $e-\u003egetMessage() . PHP_EOL;\n    exit(1);\n}\n\necho 'Validation successful.' . PHP_EOL;\necho 'Bundle ID: ' . $response-\u003egetBundleId() . PHP_EOL;\necho 'App Apple ID: ' . $response-\u003egetAppAppleId() . PHP_EOL;\n\nforeach ($response-\u003egetTransactions() as $transaction) {\n    echo 'getProductId: ' . $transaction-\u003egetProductId() . PHP_EOL;\n    echo 'getTransactionId: ' . $transaction-\u003egetTransactionId() . PHP_EOL;\n\n    if ($transaction-\u003egetPurchaseDate() != null) {\n        echo 'getPurchaseDate: ' . $transaction-\u003egetPurchaseDate()-\u003etoIso8601String() . PHP_EOL;\n    }\n}\n```\n\n### 🍏 Apple iTunes (Deprecated)\n\n```php\nuse ReceiptValidator\\Environment;\nuse ReceiptValidator\\iTunes\\Validator as iTunesValidator;\n\n$validator = new iTunesValidator(Environment::PRODUCTION);\n\ntry {\n    $response = $validator-\u003esetSharedSecret('SHARED_SECRET')-\u003esetReceiptData('BASE64_RECEIPT')-\u003evalidate();\n} catch (Exception $e) {\n    echo 'got error = ' . $e-\u003egetMessage() . PHP_EOL;\n    echo $e-\u003egetTraceAsString() . PHP_EOL;\n    exit;\n}\n\necho 'Receipt is valid.' . PHP_EOL;\n\necho 'getBundleId: ' . $response-\u003egetBundleId() . PHP_EOL;\n\nforeach ($response-\u003egetPurchases() as $purchase) {\n    echo 'getProductId: ' . $purchase-\u003egetProductId() . PHP_EOL;\n    echo 'getTransactionId: ' . $purchase-\u003egetTransactionId() . PHP_EOL;\n\n    if ($purchase-\u003egetPurchaseDate() != null) {\n        echo 'getPurchaseDate: ' . $purchase-\u003egetPurchaseDate()-\u003etoIso8601String() . PHP_EOL;\n    }\n}\n```\n\n---\n\n### 🛒 Amazon App Store\n\n```php\nuse ReceiptValidator\\Amazon\\Validator;\nuse ReceiptValidator\\Amazon\\Response;\n\n$validator = new Validator();\n\ntry {\n    $response = $validator-\u003esetDeveloperSecret('SECRET')-\u003esetReceiptId('RECEIPT_ID')-\u003esetUserId('USER_ID')-\u003evalidate();\n} catch (Exception $e) {\n    echo 'got error = ' . $e-\u003egetMessage() . PHP_EOL;\n    echo $e-\u003egetTraceAsString() . PHP_EOL;\n    exit;\n}\n\necho 'Receipt is valid.' . PHP_EOL;\n\nforeach ($response-\u003egetPurchases() as $purchase) {\n    echo 'getProductId: ' . $purchase-\u003egetProductId() . PHP_EOL;\n\n    if ($purchase-\u003egetPurchaseDate() != null) {\n        echo 'getPurchaseDate: ' . $purchase-\u003egetPurchaseDate()-\u003etoIso8601String() . PHP_EOL;\n    }\n}\n\n```\n\n### 📬 Apple App Store Server Notifications\n\n#### 🔔 V2 Notifications (App Store Server API)\n\n```php\nuse ReceiptValidator\\AppleAppStore\\ServerNotification;\nuse ReceiptValidator\\Exceptions\\ValidationException;\n\npublic function subscriptions(Request $request): JsonResponse {\n    \n    try {\n        $notification = new ServerNotification($request-\u003eall());\n    \n        echo 'Type: ' . $notification-\u003egetNotificationType()-\u003evalue . PHP_EOL;\n        echo 'Subtype: ' . ($notification-\u003egetSubtype()?-\u003evalue ?? 'N/A') . PHP_EOL;\n        echo 'Bundle: ' . $notification-\u003egetBundleId() . PHP_EOL;\n    \n        $tx = $notification-\u003egetTransaction();\n        if ($tx !== null) {\n            echo 'Transaction ID: ' . $tx-\u003egetTransactionId() . PHP_EOL;\n        }\n    \n        $renewalInfo = $notification-\u003egetRenewalInfo();\n        if ($renewalInfo !== null) {\n            echo 'Auto Renew Product: ' . $renewalInfo-\u003egetAutoRenewProductId() . PHP_EOL;\n        }\n    } catch (ValidationException $e) {\n        echo 'Invalid notification: ' . $e-\u003egetMessage();\n    }\n}\n```\n\n#### 🔔 V1 Notifications (iTunes) (Deprecated)\n\n```php\nuse ReceiptValidator\\iTunes\\ServerNotification;\nuse ReceiptValidator\\Exceptions\\ValidationException;\n\npublic function subscriptions(Request $request): JsonResponse {\n    $sharedSecret = 'your_shared_secret';\n    \n    try {\n        $notification = new ServerNotification($request-\u003eall(), $sharedSecret);\n    \n        echo 'Type: ' . $notification-\u003egetNotificationType()-\u003evalue . PHP_EOL;\n        echo 'Bundle: ' . $notification-\u003egetBundleId() . PHP_EOL;\n    \n        $latestReceipt = $notification-\u003egetLatestReceipt();\n        $transactions = $latestReceipt-\u003egetTransactions();\n    \n        foreach ($transactions as $tx) {\n            echo 'Transaction ID: ' . $tx-\u003egetTransactionId() . PHP_EOL;\n        }\n    } catch (ValidationException $e) {\n        echo 'Invalid notification: ' . $e-\u003egetMessage();\n    }\n}\n```\n\n---\n\n## 🧪 Testing\n\n```bash\ncomposer test\ncomposer check  # Run code style checks (PHP_CodeSniffer)\ncomposer analyze  # Run static analysis (PHPStan)\n```\n\n---\n\n## 🙌 Contributing\n\nContributions are welcome! Feel free to:\n- Fork this repo\n- Create a feature branch\n- Submit a pull request\n\nFound a bug or want a new feature? [Open an issue](https://github.com/aporat/store-receipt-validator/issues)\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Faporat%2Fstore-receipt-validator","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Faporat%2Fstore-receipt-validator","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Faporat%2Fstore-receipt-validator/lists"}