venice 0.4.1 → 0.4.2

Sign up to get free protection for your applications and to get access to all the features.
@@ -9,6 +9,7 @@ module Venice
9
9
  class Client
10
10
  attr_accessor :verification_url
11
11
  attr_writer :shared_secret
12
+ attr_writer :exclude_old_transactions
12
13
 
13
14
  class << self
14
15
  def development
@@ -31,13 +32,13 @@ module Venice
31
32
  def verify!(data, options = {})
32
33
  @verification_url ||= ITUNES_DEVELOPMENT_RECEIPT_VERIFICATION_ENDPOINT
33
34
  @shared_secret = options[:shared_secret] if options[:shared_secret]
35
+ @exclude_old_transactions = options[:exclude_old_transactions] if options[:exclude_old_transactions]
34
36
 
35
- json = json_response_from_verifying_data(data)
36
- status = json['status'].to_i
37
- receipt_attributes = json['receipt'].dup
37
+ json = json_response_from_verifying_data(data, options)
38
+ receipt_attributes = json['receipt'].dup if json['receipt']
38
39
  receipt_attributes['original_json_response'] = json if receipt_attributes
39
40
 
40
- case status
41
+ case json['status'].to_i
41
42
  when 0, 21006
42
43
  receipt = Receipt.new(receipt_attributes)
43
44
 
@@ -55,32 +56,46 @@ module Venice
55
56
 
56
57
  return receipt
57
58
  else
58
- raise Receipt::VerificationError.new(status, receipt)
59
+ raise Receipt::VerificationError, json
59
60
  end
60
61
  end
61
62
 
62
63
  private
63
64
 
64
- def json_response_from_verifying_data(data)
65
+ def json_response_from_verifying_data(data, options = {})
65
66
  parameters = {
66
67
  'receipt-data' => data
67
68
  }
68
69
 
69
70
  parameters['password'] = @shared_secret if @shared_secret
71
+ parameters['exclude-old-transactions'] = @exclude_old_transactions if @exclude_old_transactions
70
72
 
71
73
  uri = URI(@verification_url)
72
74
  http = Net::HTTP.new(uri.host, uri.port)
73
75
  http.use_ssl = true
74
76
  http.verify_mode = OpenSSL::SSL::VERIFY_PEER
75
77
 
78
+ http.open_timeout = options[:open_timeout] if options[:open_timeout]
79
+ http.read_timeout = options[:read_timeout] if options[:read_timeout]
80
+
76
81
  request = Net::HTTP::Post.new(uri.request_uri)
77
82
  request['Accept'] = 'application/json'
78
83
  request['Content-Type'] = 'application/json'
79
84
  request.body = parameters.to_json
80
85
 
81
- response = http.request(request)
86
+ begin
87
+ response = http.request(request)
88
+ rescue Timeout::Error
89
+ raise TimeoutError
90
+ end
82
91
 
83
92
  JSON.parse(response.body)
84
93
  end
85
94
  end
95
+
96
+ class Client::TimeoutError < Timeout::Error
97
+ def message
98
+ 'The App Store timed out.'
99
+ end
100
+ end
86
101
  end
@@ -94,7 +94,9 @@ module Venice
94
94
 
95
95
  class << self
96
96
  def verify(data, options = {})
97
- verify!(data, options) rescue false
97
+ verify!(data, options)
98
+ rescue VerificationError, Client::TimeoutError
99
+ false
98
100
  end
99
101
 
100
102
  def verify!(data, options = {})
@@ -121,16 +123,22 @@ module Venice
121
123
  end
122
124
 
123
125
  class VerificationError < StandardError
124
- attr_accessor :code
125
- attr_accessor :receipt
126
+ attr_accessor :json
126
127
 
127
- def initialize(code, receipt)
128
- @code = Integer(code)
129
- @receipt = receipt
128
+ def initialize(json)
129
+ @json = json
130
+ end
131
+
132
+ def code
133
+ Integer(json['status'])
134
+ end
135
+
136
+ def retryable?
137
+ json['is-retryable']
130
138
  end
131
139
 
132
140
  def message
133
- case @code
141
+ case code
134
142
  when 21000
135
143
  'The App Store could not read the JSON object you provided.'
136
144
  when 21002
@@ -152,7 +160,7 @@ module Venice
152
160
  when 21100..21199
153
161
  'Internal data access error.'
154
162
  else
155
- "Unknown Error: #{@code}"
163
+ "Unknown Error: #{code}"
156
164
  end
157
165
  end
158
166
  end
@@ -1,3 +1,3 @@
1
1
  module Venice
2
- VERSION = '0.4.1'
2
+ VERSION = '0.4.2'
3
3
  end
@@ -112,5 +112,50 @@ describe Venice::Client do
112
112
  receipt.latest_receipt_info.should_not be_nil
113
113
  end
114
114
  end
115
+
116
+ context 'with an error response' do
117
+ before do
118
+ client.stub(:json_response_from_verifying_data).and_return(response)
119
+ end
120
+
121
+ let(:response) do
122
+ {
123
+ 'status' => 21000,
124
+ 'receipt' => {}
125
+ }
126
+ end
127
+
128
+ it 'raises a VerificationError' do
129
+ expect do
130
+ client.verify!('asdf')
131
+ end.to raise_error(Venice::Receipt::VerificationError) do |error|
132
+ expect(error.json).to eq(response)
133
+ expect(error.code).to eq(21000)
134
+ expect(error).not_to be_retryable
135
+ end
136
+ end
137
+ end
138
+
139
+ context 'with a retryable error response' do
140
+ before do
141
+ client.stub(:json_response_from_verifying_data).and_return(response)
142
+ end
143
+
144
+ let(:response) do
145
+ {
146
+ 'status' => 21000,
147
+ 'receipt' => {},
148
+ 'is-retryable' => true
149
+ }
150
+ end
151
+
152
+ it 'raises a VerificationError' do
153
+ expect do
154
+ client.verify!('asdf')
155
+ end.to raise_error(Venice::Receipt::VerificationError) do |error|
156
+ expect(error).to be_retryable
157
+ end
158
+ end
159
+ end
115
160
  end
116
161
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: venice
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.4.1
4
+ version: 0.4.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - Mattt Thompson
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2017-11-17 00:00:00.000000000 Z
11
+ date: 2017-12-21 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: commander