defmodule ReceiptDecoder do @moduledoc """ Decode iOS App receipt """ alias ReceiptDecoder.Extractor alias ReceiptDecoder.Parser alias ReceiptDecoder.Verifier alias ReceiptDecoder.AppReceipt @doc """ Decode iOS App receipt ## Example ```elixir iex> ReceiptDecoder.decode(BASE64_ENCODED_RECEIPT) {:ok, %ReceiptDecoder.AppReceipt{application_version: "1241", bundle_id: "com.sumiapp.GridDiary", creation_date: ~N[2014-09-02 03:29:06], environment: "ProductionSandbox", expiration_date: nil, in_apps: [%ReceiptDecoder.IAPReceipt{cancellation_date: nil, expires_date: nil, original_purchase_date: ~N[2014-08-04 06:24:51], original_transaction_id: "1000000118990828", product_id: "com.sumiapp.GridDiary.pro", purchase_date: ~N[2014-09-02 03:29:06], quantity: 1, transaction_id: "1000000118990828", web_order_line_item_id: 0}, %ReceiptDecoder.IAPReceipt{cancellation_date: nil, expires_date: nil, original_purchase_date: ~N[2014-09-02 03:29:06], original_transaction_id: "1000000122102348", product_id: "com.sumiapp.griddiary.test", purchase_date: ~N[2014-09-02 03:29:06], quantity: 1, transaction_id: "1000000122102348", web_order_line_item_id: 0}], opaque_value: <<55, 223, 114, 56, 138, 79, 247, 183, 9, 37, 209, 28, 7, 147, 201, 131>>, original_application_version: "1.0", sha1_hash: <<253, 23, 138, 194, 193, 253, 204, 39, 239, 220, 43, 200, 223, 213, 74, 210, 39, 101, 79, 47>>}} ``` """ @spec decode(String.t()) :: {:ok, AppReceipt.t()} | {:error, any} def decode(base64_receipt) do with {:ok, receipt} <- Extractor.decode_receipt(base64_receipt), :ok <- Verifier.verify(receipt), {:ok, payload} <- Extractor.extract_payload(receipt), {:ok, app_receipt} <- Parser.parse_payload(payload) do {:ok, app_receipt} else err -> err end end end