require 'spec_helper' describe Itunes::Receipt do describe '.verify!' do it 'should support sandbox mode' do sandbox_mode do expect do Itunes::Receipt.verify! 'receipt-data' end.to post_to Itunes::ENDPOINT[:sandbox] end end it 'should not pass along shared secret if not set' do fake_json(:invalid) Itunes.shared_secret = nil RestClient.should_receive(:post).with(Itunes.endpoint, {:'receipt-data' => 'receipt-data'}.to_json).and_return("{}") expect do Itunes::Receipt.verify! 'receipt-data' end.to raise_error Itunes::Receipt::VerificationFailed end it 'should pass along shared secret if set' do fake_json(:invalid) Itunes.shared_secret = 'hey' RestClient.should_receive(:post).with(Itunes.endpoint, {:'receipt-data' => 'receipt-data', :password => 'hey'}.to_json).and_return("{}") expect do Itunes::Receipt.verify! 'receipt-data' end.to raise_error Itunes::Receipt::VerificationFailed end context 'when invalid' do before do fake_json :invalid end it 'should raise VerificationFailed' do expect do Itunes::Receipt.verify! 'invalid' end.to raise_error Itunes::Receipt::VerificationFailed end context 'due to a sandbox receipt reply' do before do fake_json :sandboxed sandbox_mode do fake_json :valid end end context 'when sandbox receipt accepted explicitly' do it 'should try and verify the receipt against the sandbox ' do receipt = Itunes::Receipt.verify! 'sandboxed', :allow_sandbox_receipt receipt.should be_instance_of Itunes::Receipt receipt.transaction_id.should == '1000000001479608' receipt.itunes_env.should == :sandbox receipt.sandbox?.should eq true end end context 'otherwise' do it 'should raise SandboxReceiptReceived exception' do expect do Itunes::Receipt.verify! 'sandboxed' end.to raise_error Itunes::Receipt::SandboxReceiptReceived end end end end context 'when valid' do before do fake_json :valid end it 'should not be an application receipt' do receipt = Itunes::Receipt.verify! 'valid_application' receipt.application_receipt?.should == false end it 'should return valid Receipt instance' do receipt = Itunes::Receipt.verify! 'valid' receipt.should be_instance_of Itunes::Receipt receipt.quantity == 1 receipt.product_id.should == 'com.cerego.iknow.30d' receipt.transaction_id.should == '1000000001479608' receipt.purchase_date.should == Time.utc(2011, 2, 17, 6, 20, 57) receipt.bid.should == 'com.cerego.iknow' receipt.bvrs.should == '1.0' receipt.original.quantity.should be_nil receipt.original.transaction_id.should == '1000000001479608' receipt.original.purchase_date.should == Time.utc(2011, 2, 17, 6, 20, 57) receipt.expires_date.should be_nil receipt.receipt_data.should be_nil receipt.itunes_env.should == :production # Those attributes are not returned from iTunes Connect Sandbox receipt.app_item_id.should be_nil receipt.version_external_identifier.should be_nil end end context 'when application receipt' do before do fake_json :valid_application end it 'should be an application receipt' do receipt = Itunes::Receipt.verify! 'valid_application' receipt.application_receipt?.should == true end it 'should return valid Receipt instance' do receipt = Itunes::Receipt.verify! 'valid_application' receipt.bundle_id.should == 'com.tekkinnovations.fars' receipt.application_version.should == '1.80' receipt.in_app.should be_instance_of Array receipt.in_app[0].should be_instance_of Itunes::Receipt receipt.in_app[0].quantity.should == 1 receipt.in_app[0].product_id.should == "com.tekkinnovations.fars.subscription.6.months" receipt.in_app[0].transaction_id.should == "1000000091176126" receipt.in_app[0].purchase_date.should == Time.utc(2013, 11, 26, 5, 58, 48) receipt.in_app[0].original.purchase_date.should == Time.utc(2013, 10, 24, 4, 55, 56) receipt.in_app[1].should be_instance_of Itunes::Receipt receipt.in_app[1].quantity.should == 1 receipt.in_app[1].product_id.should == "com.tekkinnovations.fars.subscription.3.months" receipt.in_app[1].transaction_id.should == "1000000091221097" receipt.in_app[1].purchase_date.should == Time.utc(2013, 11, 26, 5, 58, 48) receipt.in_app[1].original.purchase_date.should == Time.utc(2013, 10, 24, 9, 40, 22) receipt.original.quantity.should be_nil receipt.original.transaction_id.should be_nil receipt.original.purchase_date.should == Time.utc(2013, 8, 1, 7, 00, 00) receipt.original.application_version.should == '1.0' receipt.should be_instance_of Itunes::Receipt receipt.quantity.should be_nil receipt.product_id.should be_nil receipt.transaction_id.should be_nil receipt.purchase_date.should be_nil receipt.bid.should be_nil receipt.bvrs.should be_nil receipt.expires_date.should be_nil receipt.receipt_data.should be_nil receipt.itunes_env.should == :production # Those attributes are not returned from iTunes Connect Sandbox receipt.app_item_id.should be_nil receipt.version_external_identifier.should be_nil end end context 'when autorenew subscription' do before do fake_json :autorenew_subscription end it 'should return valid Receipt instance for autorenew subscription' do original_transaction_id = '1000000057005439' original_purchase_date = Time.utc(2012, 10, 11, 14, 45, 40) receipt = Itunes::Receipt.verify! 'autorenew_subscription' receipt.should be_instance_of Itunes::Receipt receipt.quantity == 1 receipt.product_id.should == 'com.notkeepingitreal.fizzbuzz.subscription.autorenew1m' receipt.transaction_id.should == '1000000055076747' receipt.purchase_date.should == Time.utc(2012, 10, 13, 19, 40, 8) receipt.bid.should == 'com.notkeepingitreal.fizzbuzz' receipt.bvrs.should == '1.0' receipt.original.quantity.should be_nil receipt.original.transaction_id.should == original_transaction_id receipt.original.purchase_date.should == original_purchase_date receipt.expires_date.should == Time.utc(2012, 10, 13, 19, 45, 8) receipt.receipt_data.should be_nil # Those attributes are not returned from iTunes Connect Sandbox receipt.app_item_id.should be_nil receipt.version_external_identifier.should be_nil latest = receipt.latest latest.should be_instance_of Itunes::Receipt latest.quantity == 1 latest.product_id.should == 'com.notkeepingitreal.fizzbuzz.subscription.autorenew1m' latest.transaction_id.should == '1000000052076747' latest.purchase_date.should == Time.utc(2012, 10, 13, 19, 40, 8) latest.expires_date.should == Time.utc(2012, 10, 13, 19, 50, 8) # five minutes after the "old" receipt latest.bid.should == 'com.notkeepingitreal.fizzbuzz' latest.bvrs.should == '1.0' latest.original.quantity.should be_nil latest.original.transaction_id.should == original_transaction_id latest.original.purchase_date.should == original_purchase_date latest.receipt_data.should == 'junk=' # Those attributes are not returned from iTunes Connect Sandbox latest.app_item_id.should be_nil latest.version_external_identifier.should be_nil end end context 'when expired autorenew subscription' do before do fake_json :autorenew_subscription_expired end it 'should raise ExpiredReceiptReceived exception' do expect do Itunes::Receipt.verify! 'autorenew_subscription_expired' end.to raise_error Itunes::Receipt::ExpiredReceiptReceived do |e| e.receipt.should_not be_nil end end end context 'when offline' do before do fake_json :offline end it 'should raise ReceiptServerOffline exception' do expect do Itunes::Receipt.verify! 'offline' end.to raise_error Itunes::Receipt::ReceiptServerOffline end end describe '#latest' do let(:receipt) { Itunes::Receipt.verify! 'receipt-data' } subject { receipt.latest } context 'when latest_receipt_info is a Hash' do before do fake_json :autorenew_subscription end it { should be_a Itunes::Receipt } end context 'when latest_receipt_info is an Array' do before do fake_json :array_of_latest_receipt_info end it { should be_a Array } it 'should include only Itunes::Receipt' do receipt.latest.each do |element| element.should be_a Itunes::Receipt end end end end end end