folked-venice 0.5.0.1

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,39 @@
1
+ require 'spec_helper'
2
+
3
+ describe Venice::PendingRenewalInfo do
4
+ describe '.new' do
5
+ let(:attributes) do
6
+ {
7
+ 'auto_renew_product_id' => 'com.foo.product1',
8
+ 'original_transaction_id' => '37xxxxxxxxx89',
9
+ 'product_id' => 'com.foo.product1',
10
+ 'auto_renew_status' => '0',
11
+ 'is_in_billing_retry_period' => '0',
12
+ 'expiration_intent' => '1'
13
+ }
14
+ end
15
+
16
+ subject(:pending_info) do
17
+ described_class.new(attributes)
18
+ end
19
+
20
+ it 'parses the attributes correctly' do
21
+ expect(subject.expiration_intent).to eql(1)
22
+ expect(subject.auto_renew_status).to eql(0)
23
+ expect(subject.auto_renew_product_id).to eql('com.foo.product1')
24
+ expect(subject.is_in_billing_retry_period).to eql(false)
25
+ expect(subject.product_id).to eql('com.foo.product1')
26
+ expect(subject.original_json_data).to eql(attributes)
27
+ end
28
+
29
+ it 'outputs attributes in hash' do
30
+ expect(subject.to_hash).to eql(expiration_intent: 1,
31
+ auto_renew_status: 0,
32
+ auto_renew_product_id: 'com.foo.product1',
33
+ is_in_billing_retry_period: false,
34
+ product_id: 'com.foo.product1',
35
+ price_consent_status: nil,
36
+ cancellation_reason: nil)
37
+ end
38
+ end
39
+ end
data/spec/receipt ADDED
@@ -0,0 +1 @@
1
+ ewoJInNpZ25hdHVyZSIgPSAiQXBNVUJDODZBbHpOaWtWNVl0clpBTWlKUWJLOEVkZVhrNjNrV0JBWHpsQzhkWEd1anE0N1puSVlLb0ZFMW9OL0ZTOGNYbEZmcDlZWHQ5aU1CZEwyNTBsUlJtaU5HYnloaXRyeVlWQVFvcmkzMlc5YVIwVDhML2FZVkJkZlcrT3kvUXlQWkVtb05LeGhudDJXTlNVRG9VaFo4Wis0cFA3MHBlNWtVUWxiZElWaEFBQURWekNDQTFNd2dnSTdvQU1DQVFJQ0NHVVVrVTNaV0FTMU1BMEdDU3FHU0liM0RRRUJCUVVBTUg4eEN6QUpCZ05WQkFZVEFsVlRNUk13RVFZRFZRUUtEQXBCY0hCc1pTQkpibU11TVNZd0pBWURWUVFMREIxQmNIQnNaU0JEWlhKMGFXWnBZMkYwYVc5dUlFRjFkR2h2Y21sMGVURXpNREVHQTFVRUF3d3FRWEJ3YkdVZ2FWUjFibVZ6SUZOMGIzSmxJRU5sY25ScFptbGpZWFJwYjI0Z1FYVjBhRzl5YVhSNU1CNFhEVEE1TURZeE5USXlNRFUxTmxvWERURTBNRFl4TkRJeU1EVTFObG93WkRFak1DRUdBMVVFQXd3YVVIVnlZMmhoYzJWU1pXTmxhWEIwUTJWeWRHbG1hV05oZEdVeEd6QVpCZ05WQkFzTUVrRndjR3hsSUdsVWRXNWxjeUJUZEc5eVpURVRNQkVHQTFVRUNnd0tRWEJ3YkdVZ1NXNWpMakVMTUFrR0ExVUVCaE1DVlZNd2daOHdEUVlKS29aSWh2Y05BUUVCQlFBRGdZMEFNSUdKQW9HQkFNclJqRjJjdDRJclNkaVRDaGFJMGc4cHd2L2NtSHM4cC9Sd1YvcnQvOTFYS1ZoTmw0WElCaW1LalFRTmZnSHNEczZ5anUrK0RyS0pFN3VLc3BoTWRkS1lmRkU1ckdYc0FkQkVqQndSSXhleFRldngzSExFRkdBdDFtb0t4NTA5ZGh4dGlJZERnSnYyWWFWczQ5QjB1SnZOZHk2U01xTk5MSHNETHpEUzlvWkhBZ01CQUFHamNqQndNQXdHQTFVZEV3RUIvd1FDTUFBd0h3WURWUjBqQkJnd0ZvQVVOaDNvNHAyQzBnRVl0VEpyRHRkREM1RllRem93RGdZRFZSMFBBUUgvQkFRREFnZUFNQjBHQTFVZERnUVdCQlNwZzRQeUdVakZQaEpYQ0JUTXphTittVjhrOVRBUUJnb3Foa2lHOTJOa0JnVUJCQUlGQURBTkJna3Foa2lHOXcwQkFRVUZBQU9DQVFFQUVhU2JQanRtTjRDL0lCM1FFcEszMlJ4YWNDRFhkVlhBZVZSZVM1RmFaeGMrdDg4cFFQOTNCaUF4dmRXLzNlVFNNR1k1RmJlQVlMM2V0cVA1Z204d3JGb2pYMGlreVZSU3RRKy9BUTBLRWp0cUIwN2tMczlRVWU4Y3pSOFVHZmRNMUV1bVYvVWd2RGQ0TndOWXhMUU1nNFdUUWZna1FRVnk4R1had1ZIZ2JFL1VDNlk3MDUzcEdYQms1MU5QTTN3b3hoZDNnU1JMdlhqK2xvSHNTdGNURXFlOXBCRHBtRzUrc2s0dHcrR0szR01lRU41LytlMVFUOW5wL0tsMW5qK2FCdzdDMHhzeTBiRm5hQWQxY1NTNnhkb3J5L0NVdk02Z3RLc21uT09kcVRlc2JwMGJzOHNuNldxczBDOWRnY3hSSHVPTVoydG04bnBMVW03YXJnT1N6UT09IjsKCSJwdXJjaGFzZS1pbmZvIiA9ICJld29KSW05eWFXZHBibUZzTFhCMWNtTm9ZWE5sTFdSaGRHVXRjSE4wSWlBOUlDSXlNREV5TFRBMExUTXdJREE0T2pBMU9qVTFJRUZ0WlhKcFkyRXZURzl6WDBGdVoyVnNaWE1pT3dvSkltOXlhV2RwYm1Gc0xYUnlZVzV6WVdOMGFXOXVMV2xrSWlBOUlDSXhNREF3TURBd01EUTJNVGM0T0RFM0lqc0tDU0ppZG5KeklpQTlJQ0l5TURFeU1EUXlOeUk3Q2draWRISmhibk5oWTNScGIyNHRhV1FpSUQwZ0lqRXdNREF3TURBd05EWXhOemc0TVRjaU93b0pJbkYxWVc1MGFYUjVJaUE5SUNJeElqc0tDU0p2Y21sbmFXNWhiQzF3ZFhKamFHRnpaUzFrWVhSbExXMXpJaUE5SUNJeE16TTFOems0TXpVMU9EWTRJanNLQ1NKd2NtOWtkV04wTFdsa0lpQTlJQ0pqYjIwdWJXbHVaRzF2WW1Gd2NDNWtiM2R1Ykc5aFpDSTdDZ2tpYVhSbGJTMXBaQ0lnUFNBaU5USXhNVEk1T0RFeUlqc0tDU0ppYVdRaUlEMGdJbU52YlM1dGFXNWtiVzlpWVhCd0xrMXBibVJOYjJJaU93b0pJbkIxY21Ob1lYTmxMV1JoZEdVdGJYTWlJRDBnSWpFek16VTNPVGd6TlRVNE5qZ2lPd29KSW5CMWNtTm9ZWE5sTFdSaGRHVWlJRDBnSWpJd01USXRNRFF0TXpBZ01UVTZNRFU2TlRVZ1JYUmpMMGROVkNJN0Nna2ljSFZ5WTJoaGMyVXRaR0YwWlMxd2MzUWlJRDBnSWpJd01USXRNRFF0TXpBZ01EZzZNRFU2TlRVZ1FXMWxjbWxqWVM5TWIzTmZRVzVuWld4bGN5STdDZ2tpYjNKcFoybHVZV3d0Y0hWeVkyaGhjMlV0WkdGMFpTSWdQU0FpTWpBeE1pMHdOQzB6TUNBeE5Ub3dOVG8xTlNCRmRHTXZSMDFVSWpzS2ZRPT0iOwoJImVudmlyb25tZW50IiA9ICJTYW5kYm94IjsKCSJwb2QiID0gIjEwMCI7Cgkic2lnbmluZy1zdGF0dXMiID0gIjAiOwp9
@@ -0,0 +1,191 @@
1
+ require 'spec_helper'
2
+
3
+ describe Venice::Receipt do
4
+ describe 'parsing the response' do
5
+ let(:response) do
6
+ {
7
+ 'status' => 0,
8
+ 'environment' => 'Production',
9
+ 'receipt' => {
10
+ 'receipt_type' => 'Production',
11
+ 'adam_id' => 7654321,
12
+ 'bundle_id' => 'com.foo.bar',
13
+ 'application_version' => '2',
14
+ 'download_id' => 1234567,
15
+ 'receipt_creation_date' => '2014-06-04 23:20:47 Etc/GMT',
16
+ 'receipt_creation_date_ms' => '1401924047883',
17
+ 'receipt_creation_date_pst' => '2014-06-04 16:20:47 America/Los_Angeles',
18
+ 'request_date' => '2014-06-04 23:20:47 Etc/GMT',
19
+ 'request_date_ms' => '1401924047883',
20
+ 'request_date_pst' => '2014-06-04 16:20:47 America/Los_Angeles',
21
+ 'original_purchase_date' => '2014-05-17 02:09:45 Etc/GMT',
22
+ 'original_purchase_date_ms' => '1400292585000',
23
+ 'original_purchase_date_pst' => '2014-05-16 19:09:45 America/Los_Angeles',
24
+ 'original_application_version' => '1',
25
+ 'expiration_date' => '1401924047883',
26
+ 'in_app' => [
27
+ {
28
+ 'quantity' => '1',
29
+ 'product_id' => 'com.foo.product1',
30
+ 'transaction_id' => '1000000070107111',
31
+ 'original_transaction_id' => '1000000061051111',
32
+ 'web_order_line_item_id' => '1000000026812043',
33
+ 'purchase_date' => '2014-05-28 14:47:53 Etc/GMT',
34
+ 'purchase_date_ms' => '1401288473000',
35
+ 'purchase_date_pst' => '2014-05-28 07:47:53 America/Los_Angeles',
36
+ 'original_purchase_date' => '2014-05-28 14:47:53 Etc/GMT',
37
+ 'original_purchase_date_ms' => '1401288473000',
38
+ 'original_purchase_date_pst' => '2014-05-28 07:47:53 America/Los_Angeles',
39
+ 'expires_date' => '2014-06-28 14:47:53 Etc/GMT',
40
+ 'is_trial_period' => 'false'
41
+ }
42
+ ],
43
+ 'original_json_response' => {
44
+ 'pending_renewal_info' => [
45
+ {
46
+ 'auto_renew_product_id' => 'com.foo.product1',
47
+ 'original_transaction_id' => '37xxxxxxxxx89',
48
+ 'product_id' => 'com.foo.product1',
49
+ 'auto_renew_status' => '0',
50
+ 'is_in_billing_retry_period' => '0',
51
+ 'expiration_intent' => '1'
52
+ }
53
+ ]
54
+ }
55
+ }
56
+ }
57
+ end
58
+
59
+ subject { Venice::Receipt.new(response['receipt']) }
60
+
61
+ its(:bundle_id) { 'com.foo.bar' }
62
+ its(:application_version) { '2' }
63
+ its(:in_app) { should be_instance_of Array }
64
+ its(:original_application_version) { '1' }
65
+ its(:original_purchase_date) { should be_instance_of DateTime }
66
+ its(:expires_at) { should be_instance_of DateTime }
67
+ its(:receipt_type) { 'Production' }
68
+ its(:receipt_created_at) { should be_instance_of DateTime }
69
+ its(:adam_id) { 7654321 }
70
+ its(:download_id) { 1234567 }
71
+ its(:requested_at) { should be_instance_of DateTime }
72
+
73
+ describe '.verify!' do
74
+ subject { described_class.verify!('asdf') }
75
+
76
+ before do
77
+ Venice::Client.any_instance.stub(:json_response_from_verifying_data).and_return(response)
78
+ end
79
+
80
+ it 'creates the receipt' do
81
+ expect(subject).to be_an_instance_of(Venice::Receipt)
82
+ end
83
+
84
+ describe 'retrying VerificationError' do
85
+ let(:retryable_error_response) do
86
+ {
87
+ 'status' => 21000,
88
+ 'receipt' => {},
89
+ 'is_retryable' => true
90
+ }
91
+ end
92
+
93
+ let(:error_response) do
94
+ {
95
+ 'status' => 21000,
96
+ 'receipt' => {},
97
+ 'is_retryable' => false
98
+ }
99
+ end
100
+
101
+ context 'with a retryable error response' do
102
+ before do
103
+ Venice::Client.any_instance.stub(:json_response_from_verifying_data).and_return(retryable_error_response, response)
104
+ end
105
+
106
+ it 'creates the receipt' do
107
+ expect(subject).to be_an_instance_of(Venice::Receipt)
108
+ end
109
+ end
110
+
111
+ context 'with 4 retryable error responses' do
112
+ before do
113
+ Venice::Client.any_instance.stub(:json_response_from_verifying_data).and_return(
114
+ retryable_error_response,
115
+ retryable_error_response,
116
+ retryable_error_response,
117
+ retryable_error_response,
118
+ response
119
+ )
120
+ end
121
+
122
+ it { expect { subject }.to raise_error(Venice::Receipt::VerificationError) }
123
+ end
124
+
125
+ context 'with a not retryable error response' do
126
+ before do
127
+ Venice::Client.any_instance.stub(:json_response_from_verifying_data).and_return(error_response, response)
128
+ end
129
+
130
+ it { expect { subject }.to raise_error(Venice::Receipt::VerificationError) }
131
+ end
132
+ end
133
+
134
+ describe 'retrying http error' do
135
+ def stub_json_response_from_verifying_data(returns)
136
+ counter = 0
137
+ Venice::Client.any_instance.stub(:json_response_from_verifying_data) do
138
+ begin
139
+ returns[counter].call
140
+ ensure
141
+ counter += 1
142
+ end
143
+ end
144
+ end
145
+
146
+ context 'given 3 http errors' do
147
+ before do
148
+ returns = [
149
+ -> { raise(Net::ReadTimeout) },
150
+ -> { raise(OpenSSL::SSL::SSLError) },
151
+ -> { raise(Errno::ECONNRESET) },
152
+ -> { response }
153
+ ]
154
+ stub_json_response_from_verifying_data(returns)
155
+ end
156
+
157
+ it 'creates the receipt' do
158
+ expect(subject).to be_an_instance_of(Venice::Receipt)
159
+ end
160
+ end
161
+
162
+ context 'given 4 Net::ReadTimeout' do
163
+ before do
164
+ returns = [
165
+ -> { raise(Net::ReadTimeout) },
166
+ -> { raise(Net::ReadTimeout) },
167
+ -> { raise(Net::ReadTimeout) },
168
+ -> { raise(Net::ReadTimeout) },
169
+ -> { response }
170
+ ]
171
+ stub_json_response_from_verifying_data(returns)
172
+ end
173
+
174
+ it 'raises http error' do
175
+ expect { subject }.to raise_error(Net::ReadTimeout)
176
+ end
177
+ end
178
+ end
179
+ end
180
+
181
+ it 'parses the pending rerenewal information' do
182
+ expect(subject.to_hash[:pending_renewal_info]).to eql([{ expiration_intent: 1,
183
+ auto_renew_status: 0,
184
+ auto_renew_product_id: 'com.foo.product1',
185
+ is_in_billing_retry_period: false,
186
+ product_id: 'com.foo.product1',
187
+ price_consent_status: nil,
188
+ cancellation_reason: nil }])
189
+ end
190
+ end
191
+ end
@@ -0,0 +1,18 @@
1
+ unless ENV['CI']
2
+ require 'simplecov'
3
+
4
+ SimpleCov.start do
5
+ add_filter 'spec'
6
+ add_filter '.bundle'
7
+ end
8
+ end
9
+
10
+ require 'venice'
11
+ require 'rspec'
12
+ require 'rspec/its'
13
+
14
+ RSpec.configure do |config|
15
+ config.mock_with :rspec do |mocks|
16
+ mocks.yield_receiver_to_any_instance_implementation_blocks = false
17
+ end
18
+ end
metadata ADDED
@@ -0,0 +1,165 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: folked-venice
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.5.0.1
5
+ platform: ruby
6
+ authors:
7
+ - daiki.sekiguchi
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2019-02-14 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: commander
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: '4.1'
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: '4.1'
27
+ - !ruby/object:Gem::Dependency
28
+ name: json
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - ">="
32
+ - !ruby/object:Gem::Version
33
+ version: '0'
34
+ type: :runtime
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - ">="
39
+ - !ruby/object:Gem::Version
40
+ version: '0'
41
+ - !ruby/object:Gem::Dependency
42
+ name: terminal-table
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - "~>"
46
+ - !ruby/object:Gem::Version
47
+ version: '1.4'
48
+ type: :runtime
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - "~>"
53
+ - !ruby/object:Gem::Version
54
+ version: '1.4'
55
+ - !ruby/object:Gem::Dependency
56
+ name: rake
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - ">="
60
+ - !ruby/object:Gem::Version
61
+ version: '0'
62
+ type: :development
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - ">="
67
+ - !ruby/object:Gem::Version
68
+ version: '0'
69
+ - !ruby/object:Gem::Dependency
70
+ name: rspec
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - "~>"
74
+ - !ruby/object:Gem::Version
75
+ version: '3.6'
76
+ type: :development
77
+ prerelease: false
78
+ version_requirements: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - "~>"
81
+ - !ruby/object:Gem::Version
82
+ version: '3.6'
83
+ - !ruby/object:Gem::Dependency
84
+ name: rspec-its
85
+ requirement: !ruby/object:Gem::Requirement
86
+ requirements:
87
+ - - "~>"
88
+ - !ruby/object:Gem::Version
89
+ version: '1.2'
90
+ type: :development
91
+ prerelease: false
92
+ version_requirements: !ruby/object:Gem::Requirement
93
+ requirements:
94
+ - - "~>"
95
+ - !ruby/object:Gem::Version
96
+ version: '1.2'
97
+ - !ruby/object:Gem::Dependency
98
+ name: simplecov
99
+ requirement: !ruby/object:Gem::Requirement
100
+ requirements:
101
+ - - ">="
102
+ - !ruby/object:Gem::Version
103
+ version: '0'
104
+ type: :development
105
+ prerelease: false
106
+ version_requirements: !ruby/object:Gem::Requirement
107
+ requirements:
108
+ - - ">="
109
+ - !ruby/object:Gem::Version
110
+ version: '0'
111
+ description: Ruby Gem for In-App Purchase Receipt Verification
112
+ email: sekiseki0213@gmail.com
113
+ executables:
114
+ - iap
115
+ extensions: []
116
+ extra_rdoc_files: []
117
+ files:
118
+ - "./Gemfile"
119
+ - "./LICENSE"
120
+ - "./README.md"
121
+ - "./Rakefile"
122
+ - "./daiki44.gemspec"
123
+ - "./lib/venice.rb"
124
+ - "./lib/venice/client.rb"
125
+ - "./lib/venice/in_app_receipt.rb"
126
+ - "./lib/venice/pending_renewal_info.rb"
127
+ - "./lib/venice/receipt.rb"
128
+ - "./lib/venice/version.rb"
129
+ - bin/iap
130
+ - spec/client_spec.rb
131
+ - spec/in_app_receipt_spec.rb
132
+ - spec/pending_renewal_info_spec.rb
133
+ - spec/receipt
134
+ - spec/receipt_spec.rb
135
+ - spec/spec_helper.rb
136
+ homepage: https://daiki-sekiguchi.com
137
+ licenses:
138
+ - MIT
139
+ metadata: {}
140
+ post_install_message:
141
+ rdoc_options: []
142
+ require_paths:
143
+ - lib
144
+ required_ruby_version: !ruby/object:Gem::Requirement
145
+ requirements:
146
+ - - ">="
147
+ - !ruby/object:Gem::Version
148
+ version: '0'
149
+ required_rubygems_version: !ruby/object:Gem::Requirement
150
+ requirements:
151
+ - - ">="
152
+ - !ruby/object:Gem::Version
153
+ version: '0'
154
+ requirements: []
155
+ rubygems_version: 3.0.2
156
+ signing_key:
157
+ specification_version: 4
158
+ summary: iTunes In-App Purchase Receipt Verification
159
+ test_files:
160
+ - spec/client_spec.rb
161
+ - spec/in_app_receipt_spec.rb
162
+ - spec/pending_renewal_info_spec.rb
163
+ - spec/receipt
164
+ - spec/receipt_spec.rb
165
+ - spec/spec_helper.rb