paid 0.1.0 → 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (64) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +5 -1
  3. data/.travis.yml +16 -0
  4. data/History.txt +4 -0
  5. data/README.md +58 -0
  6. data/Rakefile +9 -29
  7. data/VERSION +1 -0
  8. data/bin/paid-console +7 -0
  9. data/gemfiles/default-with-activesupport.gemfile +10 -0
  10. data/gemfiles/json.gemfile +12 -0
  11. data/gemfiles/yajl.gemfile +12 -0
  12. data/lib/paid.rb +129 -177
  13. data/lib/paid/account.rb +14 -1
  14. data/lib/paid/api_class.rb +336 -0
  15. data/lib/paid/api_list.rb +47 -0
  16. data/lib/paid/api_resource.rb +8 -25
  17. data/lib/paid/api_singleton.rb +5 -0
  18. data/lib/paid/customer.rb +36 -21
  19. data/lib/paid/errors/api_error.rb +6 -0
  20. data/lib/paid/event.rb +22 -1
  21. data/lib/paid/invoice.rb +16 -21
  22. data/lib/paid/plan.rb +18 -2
  23. data/lib/paid/subscription.rb +17 -11
  24. data/lib/paid/transaction.rb +19 -12
  25. data/lib/paid/util.rb +53 -106
  26. data/lib/paid/version.rb +1 -1
  27. data/paid.gemspec +10 -11
  28. data/tasks/api_test.rb +187 -0
  29. data/test/mock_resource.rb +69 -0
  30. data/test/paid/account_test.rb +41 -4
  31. data/test/paid/api_class_test.rb +412 -0
  32. data/test/paid/api_list_test.rb +17 -0
  33. data/test/paid/api_resource_test.rb +13 -343
  34. data/test/paid/api_singleton_test.rb +12 -0
  35. data/test/paid/authentication_test.rb +50 -0
  36. data/test/paid/customer_test.rb +189 -29
  37. data/test/paid/event_test.rb +74 -0
  38. data/test/paid/invoice_test.rb +101 -20
  39. data/test/paid/plan_test.rb +84 -8
  40. data/test/paid/status_codes_test.rb +63 -0
  41. data/test/paid/subscription_test.rb +100 -20
  42. data/test/paid/transaction_test.rb +110 -37
  43. data/test/paid/util_test.rb +15 -24
  44. data/test/test_data.rb +144 -93
  45. data/test/test_helper.rb +6 -4
  46. metadata +32 -26
  47. data/Gemfile.lock +0 -54
  48. data/README.rdoc +0 -35
  49. data/lib/data/ca-certificates.crt +0 -0
  50. data/lib/paid/alias.rb +0 -16
  51. data/lib/paid/api_operations/create.rb +0 -17
  52. data/lib/paid/api_operations/delete.rb +0 -11
  53. data/lib/paid/api_operations/list.rb +0 -17
  54. data/lib/paid/api_operations/update.rb +0 -57
  55. data/lib/paid/certificate_blacklist.rb +0 -55
  56. data/lib/paid/list_object.rb +0 -37
  57. data/lib/paid/paid_object.rb +0 -187
  58. data/lib/paid/singleton_api_resource.rb +0 -20
  59. data/lib/tasks/paid_tasks.rake +0 -4
  60. data/test/paid/alias_test.rb +0 -22
  61. data/test/paid/certificate_blacklist_test.rb +0 -18
  62. data/test/paid/list_object_test.rb +0 -16
  63. data/test/paid/paid_object_test.rb +0 -27
  64. data/test/paid/properties_test.rb +0 -103
data/test/test_helper.rb CHANGED
@@ -4,6 +4,7 @@ require 'mocha/setup'
4
4
  require 'stringio'
5
5
  require 'shoulda'
6
6
  require File.expand_path('../test_data', __FILE__)
7
+ require File.expand_path('../mock_resource', __FILE__)
7
8
 
8
9
  # monkeypatch request methods
9
10
  module Paid
@@ -14,12 +15,13 @@ module Paid
14
15
  end
15
16
 
16
17
  def self.execute_request(opts)
17
- get_params = (opts[:headers] || {})[:params]
18
+ headers = opts[:headers]
18
19
  post_params = opts[:payload]
19
20
  case opts[:method]
20
- when :get then @mock_rest_client.get opts[:url], get_params, post_params
21
- when :post then @mock_rest_client.post opts[:url], get_params, post_params
22
- when :delete then @mock_rest_client.delete opts[:url], get_params, post_params
21
+ when :get then @mock_rest_client.get opts[:url], headers, post_params
22
+ when :put then @mock_rest_client.put opts[:url], headers, post_params
23
+ when :post then @mock_rest_client.post opts[:url], headers, post_params
24
+ when :delete then @mock_rest_client.delete opts[:url], headers, post_params
23
25
  end
24
26
  end
25
27
  end
metadata CHANGED
@@ -1,14 +1,15 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: paid
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.0
4
+ version: 1.0.0
5
5
  platform: ruby
6
6
  authors:
7
+ - Jon Calhoun
7
8
  - Ryan Jackson
8
9
  autorequire:
9
10
  bindir: bin
10
11
  cert_chain: []
11
- date: 2015-02-27 00:00:00.000000000 Z
12
+ date: 2015-03-09 00:00:00.000000000 Z
12
13
  dependencies:
13
14
  - !ruby/object:Gem::Dependency
14
15
  name: rest-client
@@ -117,27 +118,31 @@ dependencies:
117
118
  description: Paid is the programmatic way to manage payments. See https://paidapi.com
118
119
  for details.
119
120
  email:
121
+ - joncalhoun@gmail.com
120
122
  - ryan@paidapi.com
121
- executables: []
123
+ executables:
124
+ - paid-console
122
125
  extensions: []
123
126
  extra_rdoc_files: []
124
127
  files:
125
128
  - ".gitignore"
129
+ - ".travis.yml"
126
130
  - Gemfile
127
- - Gemfile.lock
131
+ - History.txt
128
132
  - MIT-LICENSE
129
- - README.rdoc
133
+ - README.md
130
134
  - Rakefile
131
- - lib/data/ca-certificates.crt
135
+ - VERSION
136
+ - bin/paid-console
137
+ - gemfiles/default-with-activesupport.gemfile
138
+ - gemfiles/json.gemfile
139
+ - gemfiles/yajl.gemfile
132
140
  - lib/paid.rb
133
141
  - lib/paid/account.rb
134
- - lib/paid/alias.rb
135
- - lib/paid/api_operations/create.rb
136
- - lib/paid/api_operations/delete.rb
137
- - lib/paid/api_operations/list.rb
138
- - lib/paid/api_operations/update.rb
142
+ - lib/paid/api_class.rb
143
+ - lib/paid/api_list.rb
139
144
  - lib/paid/api_resource.rb
140
- - lib/paid/certificate_blacklist.rb
145
+ - lib/paid/api_singleton.rb
141
146
  - lib/paid/customer.rb
142
147
  - lib/paid/errors/api_connection_error.rb
143
148
  - lib/paid/errors/api_error.rb
@@ -146,26 +151,25 @@ files:
146
151
  - lib/paid/errors/paid_error.rb
147
152
  - lib/paid/event.rb
148
153
  - lib/paid/invoice.rb
149
- - lib/paid/list_object.rb
150
- - lib/paid/paid_object.rb
151
154
  - lib/paid/plan.rb
152
- - lib/paid/singleton_api_resource.rb
153
155
  - lib/paid/subscription.rb
154
156
  - lib/paid/transaction.rb
155
157
  - lib/paid/util.rb
156
158
  - lib/paid/version.rb
157
- - lib/tasks/paid_tasks.rake
158
159
  - paid.gemspec
160
+ - tasks/api_test.rb
161
+ - test/mock_resource.rb
159
162
  - test/paid/account_test.rb
160
- - test/paid/alias_test.rb
163
+ - test/paid/api_class_test.rb
164
+ - test/paid/api_list_test.rb
161
165
  - test/paid/api_resource_test.rb
162
- - test/paid/certificate_blacklist_test.rb
166
+ - test/paid/api_singleton_test.rb
167
+ - test/paid/authentication_test.rb
163
168
  - test/paid/customer_test.rb
169
+ - test/paid/event_test.rb
164
170
  - test/paid/invoice_test.rb
165
- - test/paid/list_object_test.rb
166
- - test/paid/paid_object_test.rb
167
171
  - test/paid/plan_test.rb
168
- - test/paid/properties_test.rb
172
+ - test/paid/status_codes_test.rb
169
173
  - test/paid/subscription_test.rb
170
174
  - test/paid/transaction_test.rb
171
175
  - test/paid/util_test.rb
@@ -196,16 +200,18 @@ signing_key:
196
200
  specification_version: 4
197
201
  summary: Ruby bindings for Paid API
198
202
  test_files:
203
+ - test/mock_resource.rb
199
204
  - test/paid/account_test.rb
200
- - test/paid/alias_test.rb
205
+ - test/paid/api_class_test.rb
206
+ - test/paid/api_list_test.rb
201
207
  - test/paid/api_resource_test.rb
202
- - test/paid/certificate_blacklist_test.rb
208
+ - test/paid/api_singleton_test.rb
209
+ - test/paid/authentication_test.rb
203
210
  - test/paid/customer_test.rb
211
+ - test/paid/event_test.rb
204
212
  - test/paid/invoice_test.rb
205
- - test/paid/list_object_test.rb
206
- - test/paid/paid_object_test.rb
207
213
  - test/paid/plan_test.rb
208
- - test/paid/properties_test.rb
214
+ - test/paid/status_codes_test.rb
209
215
  - test/paid/subscription_test.rb
210
216
  - test/paid/transaction_test.rb
211
217
  - test/paid/util_test.rb
data/Gemfile.lock DELETED
@@ -1,54 +0,0 @@
1
- PATH
2
- remote: .
3
- specs:
4
- paid (0.1.0)
5
- json (~> 1.8.1)
6
- mime-types (>= 1.25, < 3.0)
7
- rest-client (~> 1.4)
8
-
9
- GEM
10
- remote: https://rubygems.org/
11
- specs:
12
- activesupport (4.2.0)
13
- i18n (~> 0.7)
14
- json (~> 1.7, >= 1.7.7)
15
- minitest (~> 5.1)
16
- thread_safe (~> 0.3, >= 0.3.4)
17
- tzinfo (~> 1.1)
18
- bourne (1.5.0)
19
- mocha (>= 0.13.2, < 0.15)
20
- i18n (0.7.0)
21
- json (1.8.2)
22
- metaclass (0.0.4)
23
- mime-types (2.4.3)
24
- minitest (5.5.1)
25
- mocha (0.13.3)
26
- metaclass (~> 0.0.1)
27
- netrc (0.10.2)
28
- power_assert (0.2.2)
29
- rake (10.4.2)
30
- rest-client (1.7.2)
31
- mime-types (>= 1.16, < 3.0)
32
- netrc (~> 0.7)
33
- shoulda (3.4.0)
34
- shoulda-context (~> 1.0, >= 1.0.1)
35
- shoulda-matchers (~> 1.0, >= 1.4.1)
36
- shoulda-context (1.2.1)
37
- shoulda-matchers (1.5.6)
38
- activesupport (>= 3.0.0)
39
- bourne (~> 1.3)
40
- test-unit (3.0.9)
41
- power_assert
42
- thread_safe (0.3.4)
43
- tzinfo (1.2.2)
44
- thread_safe (~> 0.1)
45
-
46
- PLATFORMS
47
- ruby
48
-
49
- DEPENDENCIES
50
- mocha (~> 0.13.2)
51
- paid!
52
- rake
53
- shoulda (~> 3.4.0)
54
- test-unit
data/README.rdoc DELETED
@@ -1,35 +0,0 @@
1
- = Paid Ruby bindings
2
-
3
- == Installation
4
-
5
- gem 'paid'
6
-
7
- == Requirements
8
-
9
- * Ruby 1.8.7 or above. (Ruby 1.8.6 may work if you load
10
- ActiveSupport.) For Ruby versions before 1.9.2, you'll need to add this to your Gemfile:
11
-
12
- if Gem::Version.new(RUBY_VERSION) < Gem::Version.new('1.9.2')
13
- gem 'rest-client', '~> 1.6.8'
14
- end
15
-
16
-
17
- * rest-client, json
18
-
19
- == Mirrors
20
-
21
- The paid gem is mirrored on Rubygems, so you should be able to
22
- install it via <tt>gem install paid</tt> if desired.
23
-
24
- Note that if you are installing via bundler, you should be sure to use the https
25
- rubygems source in your Gemfile, as any gems fetched over http could potentially be
26
- compromised in transit and alter the code of gems fetched securely over https:
27
-
28
- source 'https://rubygems.org'
29
-
30
- gem 'rails'
31
- gem 'paid'
32
-
33
- == Development
34
-
35
- Test cases can be run with: `bundle exec rake test`
File without changes
data/lib/paid/alias.rb DELETED
@@ -1,16 +0,0 @@
1
- module Paid
2
- class Alias < APIResource
3
- include Paid::APIOperations::Update
4
-
5
- def self.retrieve(id, api_key=nil)
6
- customer_alias = super(id, api_key)
7
- if customer_alias.respond_to? "error"
8
- customer_alias
9
- else
10
- instance = Paid::Customer.new(customer_alias.id, api_key)
11
- instance.refresh
12
- instance
13
- end
14
- end
15
- end
16
- end
@@ -1,17 +0,0 @@
1
- module Paid
2
- module APIOperations
3
- module Create
4
- module ClassMethods
5
- def create(params={}, opts={})
6
- api_key, headers = Util.parse_opts(opts)
7
- response, api_key = Paid.request(:post, self.api_url, api_key, params, headers)
8
- Util.convert_to_paid_object(response, api_key)
9
- end
10
- end
11
-
12
- def self.included(base)
13
- base.extend(ClassMethods)
14
- end
15
- end
16
- end
17
- end
@@ -1,11 +0,0 @@
1
- module Paid
2
- module APIOperations
3
- module Delete
4
- def delete(params = {}, opts={})
5
- api_key, headers = Util.parse_opts(opts)
6
- response, api_key = Paid.request(:delete, api_url, api_key || @api_key, params, headers)
7
- refresh_from(response, api_key)
8
- end
9
- end
10
- end
11
- end
@@ -1,17 +0,0 @@
1
- module Paid
2
- module APIOperations
3
- module List
4
- module ClassMethods
5
- def all(filters={}, opts={})
6
- api_key, headers = Util.parse_opts(opts)
7
- response, api_key = Paid.request(:get, api_url, api_key, filters, headers)
8
- Util.convert_to_paid_object(response, api_key)
9
- end
10
- end
11
-
12
- def self.included(base)
13
- base.extend(ClassMethods)
14
- end
15
- end
16
- end
17
- end
@@ -1,57 +0,0 @@
1
- module Paid
2
- module APIOperations
3
- module Update
4
- def save(opts={})
5
- values = serialize_params(self).merge(opts)
6
-
7
- if @values[:properties]
8
- values[:properties] = serialize_properties
9
- end
10
-
11
- if values.length > 0
12
- values.delete(:id)
13
-
14
- response, api_key = Paid.request(:post, api_url, @api_key, values)
15
- refresh_from(response, api_key)
16
- end
17
- self
18
- end
19
-
20
- def serialize_properties
21
- if @unsaved_values.include?(:properties)
22
- # the properties object has been reassigned
23
- # i.e. as object.properties = {key => val}
24
- properties_update = @values[:properties] # new hash
25
- new_keys = properties_update.keys.map(&:to_sym)
26
- # remove keys at the server, but not known locally
27
- keys_to_unset = @previous_properties.keys - new_keys
28
- keys_to_unset.each {|key| properties_update[key] = ''}
29
-
30
- properties_update
31
- else
32
- # properties is a PaidObject, and can be serialized normally
33
- serialize_params(@values[:properties])
34
- end
35
- end
36
-
37
- def serialize_params(obj)
38
- case obj
39
- when nil
40
- ''
41
- when PaidObject
42
- unsaved_keys = obj.instance_variable_get(:@unsaved_values)
43
- obj_values = obj.instance_variable_get(:@values)
44
- update_hash = {}
45
-
46
- unsaved_keys.each do |k|
47
- update_hash[k] = serialize_params(obj_values[k])
48
- end
49
-
50
- update_hash
51
- else
52
- obj
53
- end
54
- end
55
- end
56
- end
57
- end
@@ -1,55 +0,0 @@
1
- require 'uri'
2
- require 'digest/sha1'
3
-
4
- module Paid
5
- module CertificateBlacklist
6
-
7
- BLACKLIST = {
8
- "api.paidapi.com" => [
9
- '',
10
- ],
11
- "revoked.paidapi.com" => [
12
- '',
13
- ]
14
- }
15
-
16
- # Preflight the SSL certificate presented by the backend. This isn't 100%
17
- # bulletproof, in that we're not actually validating the transport used to
18
- # communicate with Paid, merely that the first attempt to does not use a
19
- # revoked certificate.
20
-
21
- # Unfortunately the interface to OpenSSL doesn't make it easy to check the
22
- # certificate before sending potentially sensitive data on the wire. This
23
- # approach raises the bar for an attacker significantly.
24
-
25
- def self.check_ssl_cert(uri, ca_file)
26
- uri = URI.parse(uri)
27
-
28
- sock = TCPSocket.new(uri.host, uri.port)
29
- ctx = OpenSSL::SSL::SSLContext.new
30
- ctx.set_params(:verify_mode => OpenSSL::SSL::VERIFY_PEER,
31
- :ca_file => ca_file)
32
-
33
- socket = OpenSSL::SSL::SSLSocket.new(sock, ctx)
34
- socket.connect
35
-
36
- certificate = socket.peer_cert.to_der
37
- fingerprint = Digest::SHA1.hexdigest(certificate)
38
-
39
- if blacklisted_certs = BLACKLIST[uri.host]
40
- if blacklisted_certs.include?(fingerprint)
41
- raise APIConnectionError.new(
42
- "Invalid server certificate. You tried to connect to a server that" +
43
- "has a revoked SSL certificate, which means we cannot securely send" +
44
- "data to that server. Please email support@paidapi.com if you need" +
45
- "help connecting to the correct API server."
46
- )
47
- end
48
- end
49
-
50
- socket.close
51
-
52
- return true
53
- end
54
- end
55
- end
@@ -1,37 +0,0 @@
1
- module Paid
2
- class ListObject < PaidObject
3
-
4
- def [](k)
5
- case k
6
- when String, Symbol
7
- super
8
- else
9
- raise ArgumentError.new("You tried to access the #{k.inspect} index, but ListObject types only support String keys. (HINT: List calls return an object with a 'data' (which is the data array). You likely want to call #data[#{k.inspect}])")
10
- end
11
- end
12
-
13
- def each(&blk)
14
- self.data.each(&blk)
15
- end
16
-
17
- def retrieve(id, api_key=nil)
18
- api_key ||= @api_key
19
- response, api_key = Paid.request(:get,"#{url}/#{CGI.escape(id)}", api_key)
20
- Util.convert_to_paid_object(response, api_key)
21
- end
22
-
23
- def create(params={}, opts={})
24
- api_key, headers = Util.parse_opts(opts)
25
- api_key ||= @api_key
26
- response, api_key = Paid.request(:post, url, api_key, params, headers)
27
- Util.convert_to_paid_object(response, api_key)
28
- end
29
-
30
- def all(params={}, opts={})
31
- api_key, headers = Util.parse_opts(opts)
32
- api_key ||= @api_key
33
- response, api_key = Paid.request(:get, url, api_key, params, headers)
34
- Util.convert_to_paid_object(response, api_key)
35
- end
36
- end
37
- end