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. These receipts have a different format than the documented App Store receipts you might be familiar with, which are PKCS #7 containers with a payload (receipt data) encoded using ASN.1.
notification_type
).
Add this line to your application's Gemfile:
gem 'apple_receipt'
And then execute:
bundle
Or install it yourself as:
gem install apple_receipt
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"
# }
A receipt is encoded as base64, and is formatted as a NeXTSTEP dictionary:
{
"signature" = "[base64-encoded signature]";
"purchase-info" = "[base64-encoded purchase data]";
"pod" = "[integer]";
"signing-status" = "0";
}
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
- Serial: 26 (
- 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
- Serial: 134752589830791184 (
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
- Serial: 2 (
The purchase-info
entry contains a base64-encoded NeXTSTEP dictionary that contains
the actual receipt data (purchase info).
First, the signing certificate is parsed from the signature binary data. The validation of the receipt works as follows.
- Verify that the signing certificate is valid, i.e. it is not expired, and it chains up to either of the bundled Apple root certificates.
- Verify that the signature over the signed data (version number and receipt data) is signed by the private key that correspond to the public key that is in the signing certificate.
Bug reports and pull requests are welcome on GitHub. This project is intended to be a safe, welcoming space for collaboration, and contributors are expected to adhere to the Contributor Covenant code of conduct.
The gem is available as open source under the terms of the ISC License.