module AppleReceipt::ReceiptParser

ReceiptParser contains helper methods to parse receipt data structures.

Constants

SIGNATURE_LENGTH_MAPPING

Public Instance Methods

parse(input) click to toggle source
# File lib/apple_receipt/receipt_parser.rb, line 20
def parse(input)
  receipt_hash = NextStepParser.parse(input)

  unless Set['signature', 'purchase_info'].subset?(receipt_hash.keys.to_set)
    raise ArgumentError, 'Missing required fields'
  end

  signature_decoded = Base64.decode64(receipt_hash['signature'])
  data_decoded = Base64.decode64(receipt_hash['purchase_info'])

  version, signature, receipt_cert = read_signature(signature_decoded)
  [version, signature, receipt_cert, data_decoded]
end
read_signature(signature_decoded) click to toggle source
# File lib/apple_receipt/receipt_parser.rb, line 34
def read_signature(signature_decoded)
  sig = StringIO.new(signature_decoded)
  version = sig.read(1).unpack('C').first # 8-bit unsigned (unsigned char)

  unless SIGNATURE_LENGTH_MAPPING.keys.include?(version)
    raise ArgumentError, "Unsupported receipt version: #{version}"
  end

  signature = sig.read(SIGNATURE_LENGTH_MAPPING[version])
  cert_size = sig.read(4).unpack('L>')[0] # 32-bit unsigned, big-endian
  receipt_cert = OpenSSL::X509::Certificate.new(sig.read(cert_size))

  [version, signature, receipt_cert]
end