# Apple Receipt [![Gem Version](https://badge.fury.io/rb/apple_receipt.svg)](https://badge.fury.io/rb/apple_receipt) [![Build Status](https://travis-ci.org/koenrh/apple_receipt.svg?branch=master)](https://travis-ci.org/koenrh/apple_receipt) [![Dependency Status](https://beta.gemnasium.com/badges/github.com/koenrh/apple_receipt.svg)](https://beta.gemnasium.com/projects/github.com/koenrh/apple_receipt) This gem allows you to read and verify Apple receipts. It was originally built to locally (server-side) verify the validity of receipts that are embedded in [Status Update Notifications](https://developer.apple.com/library/content/documentation/NetworkingInternet/Conceptual/StoreKitGuide/Chapters/Subscriptions.html#//apple_ref/doc/uid/TP40008267-CH7-SW13). These receipts have a different format than [documented](https://developer.apple.com/library/content/releasenotes/General/ValidateAppStoreReceipt/Chapters/ValidateLocally.html#//apple_ref/doc/uid/TP40010573-CH1-SW2) App Store receipts you might be familiar with, which are [PKCS #7](https://tools.ietf.org/html/rfc2315) containers with a payload (receipt data) encoded using [ASN.1](https://www.itu.int/itu-t/recommendations/rec.aspx?rec=X.690). :warning: Note that this only covers the receipt data (signed data). You should not rely on (local) verification for data that is in the notification object, but not in the receipt (e.g. `notification_type`). ## Installation Add this line to your application's Gemfile: ```ruby gem 'apple_receipt' ``` And then execute: bundle Or install it yourself as: gem install apple_receipt ## Usage ```ruby require 'apple_receipt' # Check receipt's validity (certificate chain, and signature) receipt_raw = File.read('./receipt.txt') receipt = AppleReceipt::Receipt.new(receipt_raw) receipt.valid? # => true # Read receipt's data (data in example shortened for brevity) receipt.purchase_info # => { # "quantity"=>"1", # "expires-date-formatted"=>"2018-01-23 17:03:44 Etc/GMT", # "is-in-intro-offer-period"=>"false", # "is-trial-period"=>"false", # "item-id"=>"1190360447", # "app-item-id"=>"947936149", # "transaction-id"=>"160000408504141", # "web-order-line-item-id"=>"160000011000001", # "bid"=>"com.foo.bar", # "product-id"=>"com.foo.bar.monthly", # "purchase-date"=>"2017-12-23 17:03:44 Etc/GMT", # "original-purchase-date"=>"2017-12-23 17:03:53 Etc/GMT" # } ``` ## Apple receipts A receipt is encoded as base64, and is formatted as a [NeXTSTEP](https://en.wikipedia.org/wiki/Property_list#NeXTSTEP) dictionary: ``` { "signature" = "[base64-encoded signature]"; "purchase-info" = "[base64-encoded purchase data]"; "pod" = "[integer]"; "signing-status" = "0"; } ``` ### Signature The `signature` entry contains base64-encoded binary data, which has the following layout: - **1 byte** - Receipt version (e.g. version 3). - **128 bytes** (version 2) or **256 bytes** (version 3) - Signature. - **4 bytes** - Length (in number of bytes) of the certificate. - **N bytes** - DER-encoded certificate. The version 2 and 3 receipt certificates are signed, respectively, by: - **Apple iTunes Store Certification Authority** (version 2) - Serial: 26 (`0x1a`) - Subject: `C=US, O=Apple Inc., OU=Apple Certification Authority, CN=Apple iTunes Store Certification Authority` - **Apple Worldwide Developer Relations Certification Authority** (version 3) - Serial: 134752589830791184 (`0x1debcc4396da010`) - Subject: `C=US, O=Apple Inc., OU=Apple Worldwide Developer Relations, CN=Apple Worldwide Developer Relations Certification Authority` Both certificates chain up to: - **Apple Root CA** - Serial: 2 (`0x2`) - Subject: `C=US, O=Apple Inc., OU=Apple Certification Authority, CN=Apple Root CA` ### Purchase info The `purchase-info` entry contains a base64-encoded NeXTSTEP dictionary that contains the actual receipt data (purchase info). ## Contributing Bug reports and pull requests are welcome on [GitHub](https://github.com/koenrh/apple_receipt). This project is intended to be a safe, welcoming space for collaboration, and contributors are expected to adhere to the [Contributor Covenant](https://www.contributor-covenant.org) code of conduct. ## License The gem is available as open source under the terms of the [ISC License](https://opensource.org/licenses/ISC).