{"id":1783,"url":"https://github.com/tikhop/TPInAppReceipt","last_synced_at":"2025-08-06T16:31:26.014Z","repository":{"id":45334692,"uuid":"69627072","full_name":"tikhop/TPInAppReceipt","owner":"tikhop","description":"Reading and Validating In App Purchase Receipt Locally.","archived":false,"fork":false,"pushed_at":"2024-10-24T18:33:21.000Z","size":31419,"stargazers_count":640,"open_issues_count":7,"forks_count":95,"subscribers_count":19,"default_branch":"master","last_synced_at":"2024-11-30T21:22:02.370Z","etag":null,"topics":["asn1","catalyst","cocoapods","in-app-purchase","in-app-receipt","ios","macos","osx","payment","pkcs7","purchase","receipt","receipt-validation","receipt-verification","storekit","swift","swift5","verify"],"latest_commit_sha":null,"homepage":"","language":"Swift","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/tikhop.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":"CONTRIBUTING.md","funding":null,"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}},"created_at":"2016-09-30T02:40:24.000Z","updated_at":"2024-11-25T09:55:59.000Z","dependencies_parsed_at":"2022-08-19T05:01:58.312Z","dependency_job_id":"e44f2a3e-2fb4-4c24-b348-77f18c040a5a","html_url":"https://github.com/tikhop/TPInAppReceipt","commit_stats":{"total_commits":319,"total_committers":17,"mean_commits":"18.764705882352942","dds":"0.26645768025078365","last_synced_commit":"e135055eaeba5a52874b7f9b290f42890cbe981f"},"previous_names":[],"tags_count":65,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/tikhop%2FTPInAppReceipt","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/tikhop%2FTPInAppReceipt/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/tikhop%2FTPInAppReceipt/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/tikhop%2FTPInAppReceipt/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/tikhop","download_url":"https://codeload.github.com/tikhop/TPInAppReceipt/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":228923696,"owners_count":17992567,"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":["asn1","catalyst","cocoapods","in-app-purchase","in-app-receipt","ios","macos","osx","payment","pkcs7","purchase","receipt","receipt-validation","receipt-verification","storekit","swift","swift5","verify"],"created_at":"2024-01-05T20:15:55.714Z","updated_at":"2024-12-09T16:31:04.838Z","avatar_url":"https://github.com/tikhop.png","language":"Swift","readme":"\u003cp align=\"center\"\u003e\n  \u003cimg height=\"160\" src=\"https://github.com/tikhop/TPInAppReceipt/blob/master/www/logo.png\" /\u003e\n\u003c/p\u003e\n\n\n# TPInAppReceipt\n\n![Swift](https://github.com/tikhop/TPInAppReceipt/workflows/Swift/badge.svg?branch=master)\n[![CocoaPods Compatible](https://img.shields.io/cocoapods/v/TPInAppReceipt.svg)](https://cocoapods.org/pods/TPInAppReceipt)\n[![Swift Package Manager compatible](https://img.shields.io/badge/Swift%20Package%20Manager-compatible-brightgreen.svg)](https://github.com/apple/swift-package-manager)\n[![Platform](https://img.shields.io/cocoapods/p/TPInAppReceipt.svg?style=flat)]()\n[![GitHub license](https://img.shields.io/badge/license-MIT-blue.svg)](https://raw.githubusercontent.com/tikhop/TPInAppReceipt/master/LICENSE)\n\nTPInAppReceipt is a lightweight, pure-Swift library for reading and validating Apple In App Purchase Receipt locally.\n\n## Features\n\n- [x] Read all In-App Receipt Attributes\n- [x] Validate In-App Purchase Receipt (Signature, Bundle Version and Identifier, Hash)\n- [x] Determine Eligibility for Introductory Offer\n- [x] Use with StoreKitTest\n- [x] Use in Objective-C projects\n\nInstallation\n------------\n\n\u003e Note: [TPInAppReceipt in Objective-C project](https://github.com/tikhop/TPInAppReceipt/blob/master/Documentation/UseInObjCProject.md) - If you want to use TPInAppReceipt in Objective-C project please follow this guide. \n\n### CocoaPods\n\nTo integrate TPInAppReceipt into your project using CocoaPods, specify it in your `Podfile`:\n\n```ruby\nplatform :ios, '12.0'\n\ntarget 'YOUR_TARGET' do\n  use_frameworks!\n\n  pod 'TPInAppReceipt'\nend\n\n```\n\nThen, run the following command:\n\n```bash\n$ pod install\n```\n\nIn any swift file you'd like to use TPInAppReceipt, import the framework with `import TPInAppReceipt`.\n\n### Swift Package Manager\n\nTo integrate using Apple's Swift package manager, add the following as a dependency to your `Package.swift`:\n\n```swift\n.package(url: \"https://github.com/tikhop/TPInAppReceipt.git\", .upToNextMajor(from: \"3.0.0\"))\n```\n\nThen, specify `\"TPInAppReceipt\"` as a dependency of the Target in which you wish to use TPInAppReceipt.\n\nLastly, run the following command:\n```swift\nswift package update\n```\n\n### Requirements\n\n- iOS 12.0+ / OSX 10.13+\n- Swift 5.9+\n\nUsage\n-------------\n\n### Working With a Receipt\n\nThe [`InAppReceipt`](https://tikhop.github.io/TPInAppReceipt/Classes/InAppReceipt.html) object encapsulates information about a receipt and the purchases associated with it. To validate In-App Purchase Receipt you must create an `InAppReceipt` object.\n\n#### Initializing Receipt\n\nTo create [`InAppReceipt`](https://tikhop.github.io/TPInAppReceipt/Classes/InAppReceipt.html) object you can either provide a raw receipt data or initialize a local receipt.\n\n```swift\ndo {\n  /// Initialize receipt\n  let receipt = try InAppReceipt.localReceipt() \n  // let receipt = try InAppReceipt() // Returns local receipt \n  \n  // let receiptData: Data = ...\n  // let receipt = try InAppReceipt.receipt(from: receiptData)\n  \n} catch {\n  print(error)\n}\n\n\n```\n\n#### Validating Receipt\n\n`TPInAppReceipt` provides a variety of convenience methods for validating In-App Purchase Receipt:\n\n```swift\n\n/// Verify hash \ntry? receipt.verifyHash()\n\n/// Verify bundle identifier\ntry? receipt.verifyBundleIdentifier()\n\n/// Verify bundle version\ntry? receipt.verifyBundleVersion()\n\n/// Verify signature\ntry? receipt.verifySignature()\n\n/// Validate all at once \ndo {\n  try receipt.verify()\n} catch IARError.validationFailed(reason: .hashValidation) {\n  // Do smth\n} catch IARError.validationFailed(reason: .bundleIdentifierVerification) {\n  // Do smth\n} catch IARError.validationFailed(reason: .signatureValidation) {\n  // Do smth\n} catch {\n  // Do smth\n}\n\n```\n\n\u003e NOTE: Apple recommends to perform receipt validation right after your app is launched. For additional security, you may repeat this check periodically while your application is running.\n\u003e NOTE: If validation fails in iOS, try to refresh the receipt first.\n\n#### Determining Eligibility for Introductory Offer  \n\nIf your App offers introductory pricing for auto-renewable subscriptions, you will need to dispay the correct price, either the intro or regular price.   \nThe [`InAppReceipt`](https://tikhop.github.io/TPInAppReceipt/Classes/InAppReceipt.html) class provides an interface for determining introductory price eligibility. At the simplest, just provide a `Set`  of product identifiers that belong to the same subscription group:\n\n```swift\n// Check whether user is eligible for any products within the same subscription group \nvar isEligible = receipt.isEligibleForIntroductoryOffer(for: [\"com.test.product.bronze\", \"com.test.product.silver\", \"com.test.product.gold\"])\n```\n\n\u003e Note: To determine if a user is eligible for an introductory offer, you must initialize and validate receipt first and only then check for eligibility.\n\n\n#### Reading Receipt\n\n```swift\n/// Initialize receipt\nlet receipt = try! InAppReceipt.localReceipt() \n\n/// Base64 Encoded Receipt\nlet base64Receipt = receipt.base64\n  \n/// Check whether receipt contains any purchases\nlet hasPurchases = receipt.hasPurchases\n\n/// All auto renewable `InAppPurchase`s,\nlet purchases: [InAppPurchase] = receipt.autoRenewablePurchases \n\n/// all ACTIVE auto renewable `InAppPurchase`s,\nlet activePurchases: [InAppPurchase] = receipt.activeAutoRenewableSubscriptionPurchases \n\n```\n\n#### Useful methods\n\n```swift\n\n// Retrieve Original TransactionIdentifier for Product Name\nreceipt.originalTransactionIdentifier(ofProductIdentifier: subscriptionName)\n\n// Retrieve Active Auto Renewable Subscription's Purchases for Product Name and Specific Date\nreceipt.activeAutoRenewableSubscriptionPurchases(ofProductIdentifier: subscriptionName, forDate: Date())\n\n// Retrieve All Purchases for Product Name\nreceipt.purchases(ofProductIdentifier: subscriptionName)\n\n```\n\n#### Refreshing/Requesting Receipt\n\nWhen necessary, use this method to ensure the receipt you are working with is up-to-date. \n\n```swift\nInAppReceipt.refresh { (error) in\n  if let err = error\n  {\n    print(err)\n  } else {\n    initializeReceipt()\n  }\n}\n\n```\n\n## Essential Reading\n* [Apple - About Receipt Validation](https://developer.apple.com/library/content/releasenotes/General/ValidateAppStoreReceipt/Introduction.html)\n* [Apple - Receipt Validation Programming Guide](https://developer.apple.com/library/content/releasenotes/General/ValidateAppStoreReceipt/Chapters/ReceiptFields.html#//apple_ref/doc/uid/TP40010573-CH106-SW1)\n* [Apple - Validating Receipts Locally](https://developer.apple.com/library/content/releasenotes/General/ValidateAppStoreReceipt/Chapters/ValidateLocally.html)\n* [fluffy.es - Tutorial: Read and validate in-app purchase receipt locally using TPInAppReceipt](https://fluffy.es/in-app-purchase-receipt-local/)\n* [objc.io - Receipt Validation](https://www.objc.io/issues/17-security/receipt-validation/)\n\n\n## License\n\nTPInAppReceipt is released under an MIT license. See [LICENSE](https://github.com/tikhop/TPInAppReceipt/blob/master/LICENSE) for more information.\n","funding_links":[],"categories":["Payments","Libs","UI [🔝](#readme)"],"sub_categories":["Other Parsing","UI","Other free courses"],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ftikhop%2FTPInAppReceipt","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Ftikhop%2FTPInAppReceipt","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ftikhop%2FTPInAppReceipt/lists"}