venice 0.5.0 → 0.6.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/Gemfile.lock +22 -22
- data/README.md +1 -0
- data/coverage/index.html +749 -526
- data/lib/venice/client.rb +11 -1
- data/lib/venice/in_app_receipt.rb +15 -1
- data/lib/venice/pending_renewal_info.rb +4 -0
- data/lib/venice/receipt.rb +17 -0
- data/lib/venice/version.rb +1 -1
- data/spec/fixtures/receipt_expired_cancelled.json +56 -0
- data/spec/fixtures/receipt_not_expired_cancelled.json +51 -0
- data/spec/in_app_receipt_spec.rb +4 -0
- data/spec/pending_renewal_info_spec.rb +1 -0
- data/spec/receipt_spec.rb +108 -57
- metadata +7 -4
data/lib/venice/client.rb
CHANGED
@@ -95,7 +95,11 @@ module Venice
|
|
95
95
|
raise TimeoutError
|
96
96
|
end
|
97
97
|
|
98
|
-
|
98
|
+
begin
|
99
|
+
JSON.parse(response.body)
|
100
|
+
rescue JSON::ParserError
|
101
|
+
raise InvalidResponseError
|
102
|
+
end
|
99
103
|
end
|
100
104
|
end
|
101
105
|
|
@@ -104,4 +108,10 @@ module Venice
|
|
104
108
|
'The App Store timed out.'
|
105
109
|
end
|
106
110
|
end
|
111
|
+
|
112
|
+
class Client::InvalidResponseError < StandardError
|
113
|
+
def message
|
114
|
+
'The App Store returned invalid response'
|
115
|
+
end
|
116
|
+
end
|
107
117
|
end
|
@@ -5,6 +5,9 @@ module Venice
|
|
5
5
|
# For detailed explanations on these keys/values, see
|
6
6
|
# https://developer.apple.com/library/ios/releasenotes/General/ValidateAppStoreReceipt/Chapters/ReceiptFields.html#//apple_ref/doc/uid/TP40010573-CH106-SW12
|
7
7
|
|
8
|
+
# Original JSON data returned from Apple for an InAppReceipt object.
|
9
|
+
attr_reader :original_json_data
|
10
|
+
|
8
11
|
# The number of items purchased. This value corresponds to the quantity property of
|
9
12
|
# the SKPayment object stored in the transaction’s payment property.
|
10
13
|
attr_reader :quantity
|
@@ -44,9 +47,18 @@ module Venice
|
|
44
47
|
attr_reader :expires_at
|
45
48
|
|
46
49
|
# For a transaction that was canceled by Apple customer support, the time and date of the cancellation.
|
50
|
+
# For an auto-renewable subscription plan that was upgraded, the time and date of the upgrade transaction.
|
47
51
|
attr_reader :cancellation_at
|
48
52
|
|
53
|
+
# Only present for auto-renewable subscription receipts. Value is true if the customer’s subscription is
|
54
|
+
# currently in the free trial period, false if not, nil if key is not present on receipt.
|
55
|
+
attr_reader :is_trial_period
|
56
|
+
# Only present for auto-renewable subscription receipts. Value is true if the customer’s subscription is
|
57
|
+
# currently in an introductory price period, false if not, nil if key is not present on receipt.
|
58
|
+
attr_reader :is_in_intro_offer_period
|
59
|
+
|
49
60
|
def initialize(attributes = {})
|
61
|
+
@original_json_data = attributes
|
50
62
|
@quantity = Integer(attributes['quantity']) if attributes['quantity']
|
51
63
|
@product_id = attributes['product_id']
|
52
64
|
@transaction_id = attributes['transaction_id']
|
@@ -54,7 +66,8 @@ module Venice
|
|
54
66
|
@purchased_at = DateTime.parse(attributes['purchase_date']) if attributes['purchase_date']
|
55
67
|
@app_item_id = attributes['app_item_id']
|
56
68
|
@version_external_identifier = attributes['version_external_identifier']
|
57
|
-
@is_trial_period = attributes['is_trial_period'].to_s == 'true'
|
69
|
+
@is_trial_period = attributes['is_trial_period'].to_s == 'true' if attributes['is_trial_period']
|
70
|
+
@is_in_intro_offer_period = attributes['is_in_intro_offer_period'] == 'true' if attributes['is_in_intro_offer_period']
|
58
71
|
|
59
72
|
# expires_date is in ms since the Epoch, Time.at expects seconds
|
60
73
|
if attributes['expires_date_ms']
|
@@ -88,6 +101,7 @@ module Venice
|
|
88
101
|
app_item_id: @app_item_id,
|
89
102
|
version_external_identifier: @version_external_identifier,
|
90
103
|
is_trial_period: @is_trial_period,
|
104
|
+
is_in_intro_offer_period: @is_in_intro_offer_period,
|
91
105
|
expires_at: (@expires_at.httpdate rescue nil),
|
92
106
|
cancellation_at: (@cancellation_at.httpdate rescue nil)
|
93
107
|
}
|
@@ -1,5 +1,8 @@
|
|
1
1
|
module Venice
|
2
2
|
class PendingRenewalInfo
|
3
|
+
# Original JSON data returned from Apple for a PendingRenewalInfo object.
|
4
|
+
attr_reader :original_json_data
|
5
|
+
|
3
6
|
# For an expired subscription, the reason for the subscription expiration.
|
4
7
|
# This key is only present for a receipt containing an expired auto-renewable subscription.
|
5
8
|
attr_reader :expiration_intent
|
@@ -29,6 +32,7 @@ module Venice
|
|
29
32
|
attr_reader :cancellation_reason
|
30
33
|
|
31
34
|
def initialize(attributes)
|
35
|
+
@original_json_data = attributes
|
32
36
|
@expiration_intent = Integer(attributes['expiration_intent']) if attributes['expiration_intent']
|
33
37
|
@auto_renew_status = Integer(attributes['auto_renew_status']) if attributes['auto_renew_status']
|
34
38
|
@auto_renew_product_id = attributes['auto_renew_product_id']
|
data/lib/venice/receipt.rb
CHANGED
@@ -2,6 +2,8 @@ require 'time'
|
|
2
2
|
|
3
3
|
module Venice
|
4
4
|
class Receipt
|
5
|
+
MAX_RE_VERIFY_COUNT = 3
|
6
|
+
|
5
7
|
# For detailed explanations on these keys/values, see
|
6
8
|
# https://developer.apple.com/library/ios/releasenotes/General/ValidateAppStoreReceipt/Chapters/ReceiptFields.html#//apple_ref/doc/uid/TP40010573-CH106-SW1
|
7
9
|
|
@@ -29,6 +31,7 @@ module Venice
|
|
29
31
|
attr_reader :download_id
|
30
32
|
attr_reader :requested_at
|
31
33
|
attr_reader :receipt_created_at
|
34
|
+
attr_reader :expiration_intent
|
32
35
|
|
33
36
|
# Original json response from AppStore
|
34
37
|
attr_reader :original_json_response
|
@@ -56,6 +59,7 @@ module Venice
|
|
56
59
|
@download_id = attributes['download_id']
|
57
60
|
@requested_at = DateTime.parse(attributes['request_date']) if attributes['request_date']
|
58
61
|
@receipt_created_at = DateTime.parse(attributes['receipt_creation_date']) if attributes['receipt_creation_date']
|
62
|
+
@expiration_intent = Integer(original_json_response['expiration_intent']) if original_json_response['expiration_intent']
|
59
63
|
|
60
64
|
@in_app = []
|
61
65
|
if attributes['in_app']
|
@@ -105,6 +109,7 @@ module Venice
|
|
105
109
|
def verify!(data, options = {})
|
106
110
|
client = Client.production
|
107
111
|
|
112
|
+
retry_count = 0
|
108
113
|
begin
|
109
114
|
client.verify!(data, options)
|
110
115
|
rescue VerificationError => error
|
@@ -116,8 +121,20 @@ module Venice
|
|
116
121
|
client = Client.production
|
117
122
|
retry
|
118
123
|
else
|
124
|
+
retry_count += 1
|
125
|
+
if error.retryable? && retry_count <= MAX_RE_VERIFY_COUNT
|
126
|
+
retry
|
127
|
+
end
|
128
|
+
|
119
129
|
raise error
|
120
130
|
end
|
131
|
+
rescue Net::ReadTimeout, Timeout::Error, OpenSSL::SSL::SSLError,
|
132
|
+
Errno::ECONNRESET, Errno::ECONNABORTED, Errno::EPIPE
|
133
|
+
# verifyReceipt is idempotent so we can retry it.
|
134
|
+
# Net::Http has retry logic for some idempotent http methods but it verifyReceipt is POST.
|
135
|
+
retry_count += 1
|
136
|
+
retry if retry_count <= MAX_RE_VERIFY_COUNT
|
137
|
+
raise
|
121
138
|
end
|
122
139
|
end
|
123
140
|
|
data/lib/venice/version.rb
CHANGED
@@ -0,0 +1,56 @@
|
|
1
|
+
{
|
2
|
+
"auto_renew_status": 0,
|
3
|
+
"latest_expired_receipt_info": {
|
4
|
+
"original_purchase_date_pst": "2019-02-09 22:49:48 America/Los_Angeles",
|
5
|
+
"quantity": "1",
|
6
|
+
"unique_vendor_identifier": "88DE8B5A-0B5C-48F6-A014-CBA8A07858BC",
|
7
|
+
"bvrs": "13",
|
8
|
+
"expires_date_formatted": "2019-02-17 06:49:48 Etc/GMT",
|
9
|
+
"is_in_intro_offer_period": "false",
|
10
|
+
"purchase_date_ms": "1549781388000",
|
11
|
+
"expires_date_formatted_pst": "2019-02-16 22:49:48 America/Los_Angeles",
|
12
|
+
"is_trial_period": "true",
|
13
|
+
"item_id": "1450637621",
|
14
|
+
"unique_identifier": "00008020-001624500AF2002E",
|
15
|
+
"original_transaction_id": "140000527258824",
|
16
|
+
"expires_date": "1550386188000",
|
17
|
+
"app_item_id": "1387514950",
|
18
|
+
"transaction_id": "140000527258824",
|
19
|
+
"web_order_line_item_id": "140000151774411",
|
20
|
+
"bid": "com.foo.bar",
|
21
|
+
"product_id": "com.foo.product1",
|
22
|
+
"purchase_date": "2019-02-10 06:49:48 Etc/GMT",
|
23
|
+
"original_purchase_date": "2019-02-10 06:49:48 Etc/GMT",
|
24
|
+
"purchase_date_pst": "2019-02-09 22:49:48 America/Los_Angeles",
|
25
|
+
"original_purchase_date_ms": "1549781388000"
|
26
|
+
},
|
27
|
+
"status": 21006,
|
28
|
+
"auto_renew_product_id": "com.foo.product1",
|
29
|
+
"receipt": {
|
30
|
+
"original_purchase_date_pst": "2019-02-09 22:49:48 America/Los_Angeles",
|
31
|
+
"quantity": "1",
|
32
|
+
"unique_vendor_identifier": "88DE8B5A-0B5C-48F6-A014-CBA8A07858BC",
|
33
|
+
"bvrs": "68",
|
34
|
+
"expires_date_formatted": "2019-02-17 06:49:48 Etc/GMT",
|
35
|
+
"is_in_intro_offer_period": "false",
|
36
|
+
"purchase_date_ms": "1549781388000",
|
37
|
+
"expires_date_formatted_pst": "2019-02-16 22:49:48 America/Los_Angeles",
|
38
|
+
"is_trial_period": "true",
|
39
|
+
"item_id": "1450637621",
|
40
|
+
"unique_identifier": "00008020-001624500AF2002E",
|
41
|
+
"original_transaction_id": "140000527258824",
|
42
|
+
"expires_date": "1550386188000",
|
43
|
+
"app_item_id": "1387514950",
|
44
|
+
"transaction_id": "140000527258824",
|
45
|
+
"web_order_line_item_id": "140000151774411",
|
46
|
+
"version_external_identifier": "827235835",
|
47
|
+
"product_id": "com.foo.product1",
|
48
|
+
"purchase_date": "2019-02-10 06:49:48 Etc/GMT",
|
49
|
+
"original_purchase_date": "2019-02-10 06:49:48 Etc/GMT",
|
50
|
+
"purchase_date_pst": "2019-02-09 22:49:48 America/Los_Angeles",
|
51
|
+
"bid": "com.foo.bar",
|
52
|
+
"original_purchase_date_ms": "1549781388000"
|
53
|
+
},
|
54
|
+
"expiration_intent": "1",
|
55
|
+
"is_in_billing_retry_period": "0"
|
56
|
+
}
|
@@ -0,0 +1,51 @@
|
|
1
|
+
{
|
2
|
+
"status": 0,
|
3
|
+
"environment": "Production",
|
4
|
+
"receipt": {
|
5
|
+
"receipt_type": "Production",
|
6
|
+
"adam_id": 7654321,
|
7
|
+
"bundle_id": "com.foo.bar",
|
8
|
+
"application_version": "2",
|
9
|
+
"download_id": 1234567,
|
10
|
+
"receipt_creation_date": "2014-06-04 23:20:47 Etc/GMT",
|
11
|
+
"receipt_creation_date_ms": "1401924047883",
|
12
|
+
"receipt_creation_date_pst": "2014-06-04 16:20:47 America/Los_Angeles",
|
13
|
+
"request_date": "2014-06-04 23:20:47 Etc/GMT",
|
14
|
+
"request_date_ms": "1401924047883",
|
15
|
+
"request_date_pst": "2014-06-04 16:20:47 America/Los_Angeles",
|
16
|
+
"original_purchase_date": "2014-05-17 02:09:45 Etc/GMT",
|
17
|
+
"original_purchase_date_ms": "1400292585000",
|
18
|
+
"original_purchase_date_pst": "2014-05-16 19:09:45 America/Los_Angeles",
|
19
|
+
"original_application_version": "1",
|
20
|
+
"expiration_date": "1401924047883",
|
21
|
+
"in_app": [
|
22
|
+
{
|
23
|
+
"quantity": "1",
|
24
|
+
"product_id": "com.foo.product1",
|
25
|
+
"transaction_id": "1000000070107111",
|
26
|
+
"original_transaction_id": "1000000061051111",
|
27
|
+
"web_order_line_item_id": "1000000026812043",
|
28
|
+
"purchase_date": "2014-05-28 14:47:53 Etc/GMT",
|
29
|
+
"purchase_date_ms": "1401288473000",
|
30
|
+
"purchase_date_pst": "2014-05-28 07:47:53 America/Los_Angeles",
|
31
|
+
"original_purchase_date": "2014-05-28 14:47:53 Etc/GMT",
|
32
|
+
"original_purchase_date_ms": "1401288473000",
|
33
|
+
"original_purchase_date_pst": "2014-05-28 07:47:53 America/Los_Angeles",
|
34
|
+
"expires_date": "2014-06-28 14:47:53 Etc/GMT",
|
35
|
+
"is_trial_period": "false"
|
36
|
+
}
|
37
|
+
],
|
38
|
+
"original_json_response": {
|
39
|
+
"pending_renewal_info": [
|
40
|
+
{
|
41
|
+
"auto_renew_product_id": "com.foo.product1",
|
42
|
+
"original_transaction_id": "37xxxxxxxxx89",
|
43
|
+
"product_id": "com.foo.product1",
|
44
|
+
"auto_renew_status": "0",
|
45
|
+
"is_in_billing_retry_period": "0",
|
46
|
+
"expiration_intent": "1"
|
47
|
+
}
|
48
|
+
]
|
49
|
+
}
|
50
|
+
}
|
51
|
+
}
|
data/spec/in_app_receipt_spec.rb
CHANGED
@@ -16,6 +16,7 @@ describe Venice::InAppReceipt do
|
|
16
16
|
'original_purchase_date_ms' => '1401288473000',
|
17
17
|
'original_purchase_date_pst' => '2014-05-28 07:47:53 America/Los_Angeles',
|
18
18
|
'is_trial_period' => 'false',
|
19
|
+
'is_in_intro_offer_period' => 'true',
|
19
20
|
'version_external_identifier' => '123',
|
20
21
|
'app_item_id' => 'com.foo.app1',
|
21
22
|
'expires_date' => '2014-06-28 07:47:53 America/Los_Angeles',
|
@@ -35,8 +36,10 @@ describe Venice::InAppReceipt do
|
|
35
36
|
its(:app_item_id) { 'com.foo.app1' }
|
36
37
|
its(:version_external_identifier) { '123' }
|
37
38
|
its(:is_trial_period) { false }
|
39
|
+
its(:is_in_intro_offer_period) { true }
|
38
40
|
its(:original) { should be_instance_of Venice::InAppReceipt }
|
39
41
|
its(:expires_at) { should be_instance_of Time }
|
42
|
+
its(:original_json_data) { attributes }
|
40
43
|
|
41
44
|
it "should parse the 'original' attributes" do
|
42
45
|
subject.original.should be_instance_of Venice::InAppReceipt
|
@@ -56,6 +59,7 @@ describe Venice::InAppReceipt do
|
|
56
59
|
transaction_id: '1000000070107235',
|
57
60
|
web_order_line_item_id: '1000000026812043',
|
58
61
|
is_trial_period: false,
|
62
|
+
is_in_intro_offer_period: true,
|
59
63
|
purchase_date: 'Wed, 28 May 2014 14:47:53 GMT',
|
60
64
|
original_purchase_date: 'Wed, 28 May 2014 14:47:53 GMT')
|
61
65
|
end
|
@@ -23,6 +23,7 @@ describe Venice::PendingRenewalInfo do
|
|
23
23
|
expect(subject.auto_renew_product_id).to eql('com.foo.product1')
|
24
24
|
expect(subject.is_in_billing_retry_period).to eql(false)
|
25
25
|
expect(subject.product_id).to eql('com.foo.product1')
|
26
|
+
expect(subject.original_json_data).to eql(attributes)
|
26
27
|
end
|
27
28
|
|
28
29
|
it 'outputs attributes in hash' do
|
data/spec/receipt_spec.rb
CHANGED
@@ -2,59 +2,7 @@ require 'spec_helper'
|
|
2
2
|
|
3
3
|
describe Venice::Receipt do
|
4
4
|
describe 'parsing the response' do
|
5
|
-
let(:response)
|
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
|
5
|
+
let(:response) { JSON.parse(File.read('./spec/fixtures/receipt_not_expired_cancelled.json')) }
|
58
6
|
|
59
7
|
subject { Venice::Receipt.new(response['receipt']) }
|
60
8
|
|
@@ -69,16 +17,119 @@ describe Venice::Receipt do
|
|
69
17
|
its(:adam_id) { 7654321 }
|
70
18
|
its(:download_id) { 1234567 }
|
71
19
|
its(:requested_at) { should be_instance_of DateTime }
|
20
|
+
its(:expiration_intent) { nil }
|
21
|
+
|
22
|
+
context 'response is for expired cancelled receipt' do
|
23
|
+
let(:response) { JSON.parse(File.read('./spec/fixtures/receipt_expired_cancelled.json')) }
|
24
|
+
|
25
|
+
its(:expiration_intent) { 1 }
|
26
|
+
end
|
27
|
+
|
28
|
+
describe '.verify!' do
|
29
|
+
subject { described_class.verify!('asdf') }
|
72
30
|
|
73
|
-
describe '#verify!' do
|
74
31
|
before do
|
75
32
|
Venice::Client.any_instance.stub(:json_response_from_verifying_data).and_return(response)
|
76
33
|
end
|
77
34
|
|
78
|
-
|
35
|
+
it 'creates the receipt' do
|
36
|
+
expect(subject).to be_an_instance_of(Venice::Receipt)
|
37
|
+
end
|
38
|
+
|
39
|
+
describe 'retrying VerificationError' do
|
40
|
+
let(:retryable_error_response) do
|
41
|
+
{
|
42
|
+
'status' => 21000,
|
43
|
+
'receipt' => {},
|
44
|
+
'is_retryable' => true
|
45
|
+
}
|
46
|
+
end
|
47
|
+
|
48
|
+
let(:error_response) do
|
49
|
+
{
|
50
|
+
'status' => 21000,
|
51
|
+
'receipt' => {},
|
52
|
+
'is_retryable' => false
|
53
|
+
}
|
54
|
+
end
|
55
|
+
|
56
|
+
context 'with a retryable error response' do
|
57
|
+
before do
|
58
|
+
Venice::Client.any_instance.stub(:json_response_from_verifying_data).and_return(retryable_error_response, response)
|
59
|
+
end
|
60
|
+
|
61
|
+
it 'creates the receipt' do
|
62
|
+
expect(subject).to be_an_instance_of(Venice::Receipt)
|
63
|
+
end
|
64
|
+
end
|
65
|
+
|
66
|
+
context 'with 4 retryable error responses' do
|
67
|
+
before do
|
68
|
+
Venice::Client.any_instance.stub(:json_response_from_verifying_data).and_return(
|
69
|
+
retryable_error_response,
|
70
|
+
retryable_error_response,
|
71
|
+
retryable_error_response,
|
72
|
+
retryable_error_response,
|
73
|
+
response
|
74
|
+
)
|
75
|
+
end
|
76
|
+
|
77
|
+
it { expect { subject }.to raise_error(Venice::Receipt::VerificationError) }
|
78
|
+
end
|
79
|
+
|
80
|
+
context 'with a not retryable error response' do
|
81
|
+
before do
|
82
|
+
Venice::Client.any_instance.stub(:json_response_from_verifying_data).and_return(error_response, response)
|
83
|
+
end
|
84
|
+
|
85
|
+
it { expect { subject }.to raise_error(Venice::Receipt::VerificationError) }
|
86
|
+
end
|
87
|
+
end
|
88
|
+
|
89
|
+
describe 'retrying http error' do
|
90
|
+
def stub_json_response_from_verifying_data(returns)
|
91
|
+
counter = 0
|
92
|
+
Venice::Client.any_instance.stub(:json_response_from_verifying_data) do
|
93
|
+
begin
|
94
|
+
returns[counter].call
|
95
|
+
ensure
|
96
|
+
counter += 1
|
97
|
+
end
|
98
|
+
end
|
99
|
+
end
|
100
|
+
|
101
|
+
context 'given 3 http errors' do
|
102
|
+
before do
|
103
|
+
returns = [
|
104
|
+
-> { raise(Net::ReadTimeout) },
|
105
|
+
-> { raise(OpenSSL::SSL::SSLError) },
|
106
|
+
-> { raise(Errno::ECONNRESET) },
|
107
|
+
-> { response }
|
108
|
+
]
|
109
|
+
stub_json_response_from_verifying_data(returns)
|
110
|
+
end
|
111
|
+
|
112
|
+
it 'creates the receipt' do
|
113
|
+
expect(subject).to be_an_instance_of(Venice::Receipt)
|
114
|
+
end
|
115
|
+
end
|
116
|
+
|
117
|
+
context 'given 4 Net::ReadTimeout' do
|
118
|
+
before do
|
119
|
+
returns = [
|
120
|
+
-> { raise(Net::ReadTimeout) },
|
121
|
+
-> { raise(Net::ReadTimeout) },
|
122
|
+
-> { raise(Net::ReadTimeout) },
|
123
|
+
-> { raise(Net::ReadTimeout) },
|
124
|
+
-> { response }
|
125
|
+
]
|
126
|
+
stub_json_response_from_verifying_data(returns)
|
127
|
+
end
|
79
128
|
|
80
|
-
|
81
|
-
|
129
|
+
it 'raises http error' do
|
130
|
+
expect { subject }.to raise_error(Net::ReadTimeout)
|
131
|
+
end
|
132
|
+
end
|
82
133
|
end
|
83
134
|
end
|
84
135
|
|