lib/itunes/receipt.rb in itunes-receipt-0.1.1 vs lib/itunes/receipt.rb in itunes-receipt-0.1.2

- old
+ new

@@ -8,12 +8,15 @@ @status = attributes[:status] super attributes[:exception] end end + class SandboxReceiptReceived < VerificationFailed; end; + + # expires_date, receipt_data, and latest (receipt) will only appear for autorenew subscription products - attr_reader :quantity, :product_id, :transaction_id, :purchase_date, :app_item_id, :version_external_identifier, :bid, :bvrs, :original, :expires_date, :receipt_data, :latest + attr_reader :quantity, :product_id, :transaction_id, :purchase_date, :app_item_id, :version_external_identifier, :bid, :bvrs, :original, :expires_date, :receipt_data, :latest, :itunes_env def initialize(attributes = {}) receipt_attributes = attributes.with_indifferent_access[:receipt] if receipt_attributes[:quantity] @quantity = receipt_attributes[:quantity].to_i @@ -40,24 +43,53 @@ full_receipt_data = attributes[:latest_receipt] # should also be in the top-level hash if attributes[:latest_receipt_info] is there, but this won't break if it isn't @latest = self.class.new(:receipt => attributes[:latest_receipt_info], :latest_receipt => full_receipt_data, :receipt_type => :latest) end @expires_date = Time.at(receipt_attributes[:expires_date].to_i / 1000) if receipt_attributes[:expires_date] @receipt_data = attributes[:latest_receipt] if attributes[:receipt_type] == :latest # it feels wrong to include the receipt_data for the latest receipt on anything other than the latest receipt + + @itunes_env = attributes[:itunes_env] || Itunes.itunes_env end - def self.verify!(receipt_data) + def self.verify!(receipt_data, allow_sandbox_receipt = false) request_data = {:'receipt-data' => receipt_data} request_data.merge!(:password => Itunes.shared_secret) if Itunes.shared_secret + response = post_to_endpoint(request_data) + begin + successful_response(response) + rescue SandboxReceiptReceived => e + # Retry with sandbox, as per: + # http://developer.apple.com/library/ios/#technotes/tn2259/_index.html + # FAQ#16 + if allow_sandbox_receipt + sandbox_response = post_to_endpoint(request_data, Itunes::ENDPOINT[:sandbox]) + successful_response( + sandbox_response.merge(:itunes_env => :sandbox) + ) + else + raise e + end + end + end + + private + + def self.post_to_endpoint(request_data, endpoint = Itunes.endpoint) response = RestClient.post( - Itunes.endpoint, + endpoint, request_data.to_json ) response = JSON.parse(response).with_indifferent_access + end + + def self.successful_response(response) case response[:status] when 0 new response + when 21007 + raise SandboxReceiptReceived.new(response) else raise VerificationFailed.new(response) end end + end end