paid 0.1.0 → 1.0.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.
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