All Projects → IdeasOnCanvas → Appreceiptvalidator

IdeasOnCanvas / Appreceiptvalidator

Licence: apache-2.0
Parse and validate App Store receipt files

Programming Languages

swift
15916 projects

Projects that are alternatives of or similar to Appreceiptvalidator

istore
一个 Openwrt 标准的软件中心,纯脚本实现,只依赖Openwrt标准组件。支持其它固件开发者集成到自己的固件里面。更方便入门用户搜索安装插件。The iStore is a app store for OpenWRT
Stars: ✭ 483 (+82.26%)
Mutual labels:  appstore
EasyWords
苹果商店上架项目, on app store, for MacOS, mac开源, mac open source
Stars: ✭ 116 (-56.23%)
Mutual labels:  appstore
WWDC
🌈 𝐖𝐖𝐃𝐂 𝐒𝐞𝐬𝐬𝐢𝐨𝐧 𝐍𝐨𝐭𝐞𝐬 👩🏻‍💻 ✨
Stars: ✭ 31 (-88.3%)
Mutual labels:  appstore
CoreJSON
Core Foundation, libyajl based JSON support.
Stars: ✭ 48 (-81.89%)
Mutual labels:  appstore
app-certificate-requests
🎖 Repository for requesting app certificates
Stars: ✭ 23 (-91.32%)
Mutual labels:  appstore
SSAppUpdater
SSAppUpdater is an open-source framework that compares the current version of the app with the store version and returns the essential details of it like app URL, new app version number, new release note, etc. So you can either redirect or notify the user to update their app.
Stars: ✭ 58 (-78.11%)
Mutual labels:  appstore
Obfuscator
iOS工程混淆器是围绕混淆iOS代码过审上架为目标构建出来的 Mac 软件。为应对苹果『4.3-代码重复条款』和『2.1条款』,混淆器通过内置苹果应用分类相关的百万词库修改工程中的文件/目录名、变量属性名和方法名、修改资源的hash、注入强关系强调用的方法代码,注入有调用关系的混淆类文件等手段达到大幅提高马甲包过审率的目的。除此之外,软件内置了一键提交审核、实时查看app的审核状态并嵌入了几个开发效率工具如本地化工具、提取Assets资源、替换AppIcon等。(另外:我们提供马甲包开发、tf签名等服务,有意请🤙 联系QQ:2480619280)
Stars: ✭ 39 (-85.28%)
Mutual labels:  appstore
react-native-appstore-version-checker
[Deprecated] A react native module to fetch the version of latest app from android playstore or apple app store
Stars: ✭ 88 (-66.79%)
Mutual labels:  appstore
ranepa timetable
Custom RANEPA mobile client on Flutter
Stars: ✭ 39 (-85.28%)
Mutual labels:  appstore
app-screenshot-builder
Play Store and App Store application screenshot builder
Stars: ✭ 26 (-90.19%)
Mutual labels:  appstore
ipatool
Command-line tool that allows searching and downloading app packages (known as ipa files) from the iOS App Store
Stars: ✭ 2,438 (+820%)
Mutual labels:  appstore
pi-ware
Pi-Ware is an app store inspired by Botspots pi-apps for the Raspberry Pi that allows you to install apps that you generally can't get from the official repos and/or without an extra amount of work.
Stars: ✭ 34 (-87.17%)
Mutual labels:  appstore
IndieApps
A platform to showcase your side projects/apps
Stars: ✭ 23 (-91.32%)
Mutual labels:  appstore
apprankings
App Store Rankings Scraper
Stars: ✭ 37 (-86.04%)
Mutual labels:  appstore
spring-boot-payment-starter
google play 和 appstore 服务端支付校验
Stars: ✭ 21 (-92.08%)
Mutual labels:  appstore
framework7-appstore-react
iOS App Store UI
Stars: ✭ 78 (-70.57%)
Mutual labels:  appstore
react-native-app-review
React Native module to request users to leave an app review.
Stars: ✭ 36 (-86.42%)
Mutual labels:  appstore
RateKit
📦RateKit for macOS
Stars: ✭ 28 (-89.43%)
Mutual labels:  appstore
cider
Submit your builds to the Apple App Store in seconds
Stars: ✭ 19 (-92.83%)
Mutual labels:  appstore
nodejs-searchitunes
Lightweight node.js module to quickly search Apple's iTunes Store for music, movies, apps, etc.
Stars: ✭ 25 (-90.57%)
Mutual labels:  appstore

AppReceiptValidator

Carthage Compatible Platforms iOS, macOS Language Swift License Apache 2.0 + OpenSSL Build Status Twitter: @hannesoid

An iOS and macOS library intended for dealing with App Store receipts, offering basic local retrieval, validation and parsing of receipt files.

Provides Demo Apps on iOS and macOS to inspect receipt files.

Integration with Carthage

Add this line to your Cartfile.

github "IdeasOnCanvas/AppReceiptValidator"

Usage in Code

Apple advises to write your own code for receipt validation, and build and link OpenSSL statically to your app target. Anyways this repo might be a starting point for you, or be used as a dependency at your own risk, or might just be helpful for you to inspect receipts.

Just parsing a receipt

let receiptValidator = AppReceiptValidator()

let installedReceipt = receiptValidator.parseReceipt(origin: .installedInMainBundle)

let customReceipt = receiptValidator.parseReceipt(origin: .data(dataFromSomewhere))

Result may look like this:

Receipt(
    bundleIdentifier: com.some.bundleidentifier,
    bundleIdData: BVWNwKILNEWPOJWELKWEF=,
    appVersion: 1,
    opaqueValue: xN1AVLC2Gge+tYX2qELgSA==,
    sha1Hash: LgoRW+rBxXAjpb03NJlVqa2Z200=,
    originalAppVersion: 1.0,
    receiptCreationDate: 2015-08-13T07:50:46Z,
    expirationDate: nil,
    inAppPurchaseReceipts: [
    InAppPurchaseReceipt(
        quantity: nil,
        productIdentifier: consumable,
        transactionIdentifier: 1000000166865231,
        originalTransactionIdentifier: 1000000166865231,
        purchaseDate: 2015-08-07T20:37:55Z,
        originalPurchaseDate: 2015-08-07T20:37:55Z,
        subscriptionExpirationDate: nil,
        cancellationDate: nil,
        webOrderLineItemId: nil
    ),
    InAppPurchaseReceipt(
        quantity: nil,
        productIdentifier: monthly,
        transactionIdentifier: 1000000166965150,
        originalTransactionIdentifier: 1000000166965150,
        purchaseDate: 2015-08-10T06:49:32Z,
        originalPurchaseDate: 2015-08-10T06:49:33Z,
        subscriptionExpirationDate: 2015-08-10T06:54:32Z,
        cancellationDate: nil,
        webOrderLineItemId: nil
    )
    ]
)

Receipt is Equatable, so you can do comparisons in Unit Tests. There are also some opt-in unofficial attributes, but this is experimental and should not be used in production.

Validating a receipt's signature and hash

// Full validation of signature and hash based on installed receipt
let result = receiptValidator.validateReceipt()

switch result {
    case .success(let receipt, let receiptData, let deviceIdentifier):
    print("receipt validated and parsed: \(receipt)")
    print("the retrieved receipt file's data was: \(receiptData.count) bytes")
    print("the retrieved deviceIdentifier is: \(deviceIdentifier)")
    case .error(let validationError, let receiptData, let deviceIdentifier):
    print("receipt not valid: \(validationError)")
    // receiptData and deviceIdentifier are optional and might still have been retrieved
}

Customize validation dependencies or steps

Take AppReceiptValidator.Parameters.default and customize it, then pass it to validateReceipt(parameters:), like so:

// Customizing validation parameters with configuration block, base on .default
let parameters = AppReceiptValidator.Parameters.default.with {
    $0.receiptOrigin = .data(myData)
    $0.shouldValidateSignaturePresence = false // skip signature presence validation
    $0.signatureValidation = .skip // skip signature authenticity validation
    $0.shouldValidateHash = false // skip hash validation
    $0.deviceIdentifier = .data(myCustomDeviceIdentifierData)

    // validate some string properties, this can also be done 
    // independently with validateProperties(receipt:, validations:)
    // There are also shorthands for comparing with main bundle's 
    // info.plist, e.g. bundleIdMatchingMainBundle and friends.
    // Note that appVersion meaning is platform specific.
    $0.propertyValidations = [
        .string(\.bundleIdentifier, expected: "my.bundle.identifier"),
        .string(\.appVersion, expected: "123"),
        .string(\.originalAppVersion, expected: "1")
    ]
}

let result = AppReceiptValidator().validate(parameters: parameters)

// switch on result

Demo Apps

Paste base64-encoded receipt data into the macOS or iOS demo app to see what AppReceiptValidator parses from it. The macOS App supports:

  • Drag n Drop an application or its receipt file onto it to inspect

Drag n Drop Applications on macOS

StoreKit Hints

This framework currently doesn't deal with StoreKit. But the receipt file might not exist at all. What now?

If you have no receipt (happens in development builds) or your receipt is invalid, see resources on how to update it using StoreKit functionality. Known caveats:

  • SKReceiptRefreshRequest might not complete on certain macOS Versions, but reliable on iOS - openradar
  • SKPaymentQueue.restoreCompletedTransactions() might not update the the receipt, especially if no IAPs were made or the receipt is valid - openradar
  • exit(173) only works on macOS
  • Make some kind of purchase, i.e. App Store transaction, to update it
  • Each mechanism of receipt refresh will be intrusive to the user, mostly asking for AppleID password.
  • Apple advises to write your own code for receipt validation, and build and link OpenSSL statically to your app target. Anyways this repo might be a starting point for you.
  • Also have a look at SwiftyStoreKit for dealing with StoreKit, interpretation of receipts, server-verification, and more

How it Works

AppReceiptValidator Uses OpenSSL

OpenSSL is used for PKCS#7 container parsing and signature validation, and also for parsing the ASN1 payload of the PKCS#7, which contains the receipts attributes.

Other Options

Alternatives to PKCS#7 of OpenSSL
  • Security.framework - CMSDecoder for PKCS#7 interaction only available on macOS, AppStoreReceiptChecker uses this.
  • BoringSSL instead of OpenSSL, seems included as frameworks in modern iOS and macOS, but not officially supported?
Alternatives to ASN1 of OpenSSL
Validation Server to Server

An app can send its receipt file to a backend from where Apples receipt API can be called. See Resources.

Advantages doing it locally:

  • Works offline
  • Validation mechanisms can be adjusted
  • Can be parsed without validation

Resources

Updating Apple Root Certificate

For convenience, AppReceiptValidator contains a copy of apples root certificate to validate the signature against. If uncomfortable with this, you can specify your own by changing the parameters like this:

let myParameters = AppReceiptValidator.Parameters.default.with {
    $0.signatureValidation = .shouldValidate(.data(myAppleRootCertData))
}

Updating OpenSSL

For convenience, AppReceiptValidator contains a pre-built binaries of OpenSSL. The AppReceiptValidator.modulemap exposes these only on demand via import AppReceiptValidator.OpenSSL. If you are not comfortable using pre-built binary or want to update OpenSSL:

  1. build or find prebuilt static libraries for iOS and macOS. They can for example be obtained from the OpenSSL-Universal Pod. To build, you might download the openssl sources and use his gist.
  2. Replace the OpenSSL related .a and .h files in the project
  3. After replacing the files, make sure the .h files use direct includes like #include "asn1.h" instead of #include "<OpenSSL/ans1.h>". In Xcode regex-batch-replace #(\s*)include <openssl\/([^>]+)> with #$1include "$2"
  4. Make sure the OpenSSL related headers are in the private headers of the framework AppReceiptValidator iOS and AppReceiptValidator macOS targets respectively
  5. Make sure the OpenSSL related headers are listed in the AppReceiptValidator.modulemap file

Anybody want to automate this, or find a more elegant way?

Credits

AppReceiptValidator is brought to you by IdeasOnCanvas GmbH, the creator of MindNode for iOS, macOS & watchOS.

Note that the project description data, including the texts, logos, images, and/or trademarks, for each open source project belongs to its rightful owner. If you wish to add or remove any projects, please contact us at [email protected].