venice 0.5.0 → 0.6.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- 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
|
|