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