spreedly 1.4.0 → 2.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 (87) hide show
  1. data/.gitignore +8 -0
  2. data/Gemfile +4 -0
  3. data/HISTORY.md +5 -0
  4. data/README.md +362 -29
  5. data/Rakefile +32 -0
  6. data/lib/certs/cacert.pem +7815 -0
  7. data/lib/spreedly.rb +24 -282
  8. data/lib/spreedly/common/errors_parser.rb +15 -0
  9. data/lib/spreedly/common/fields.rb +90 -0
  10. data/lib/spreedly/connection.rb +40 -0
  11. data/lib/spreedly/environment.rb +176 -0
  12. data/lib/spreedly/error.rb +50 -0
  13. data/lib/spreedly/gateway.rb +10 -0
  14. data/lib/spreedly/model.rb +17 -0
  15. data/lib/spreedly/payment_methods/credit_card.rb +9 -0
  16. data/lib/spreedly/payment_methods/payment_method.rb +34 -0
  17. data/lib/spreedly/payment_methods/paypal.rb +7 -0
  18. data/lib/spreedly/payment_methods/sprel.rb +7 -0
  19. data/lib/spreedly/ssl_requester.rb +65 -0
  20. data/lib/spreedly/transactions/add_payment_method.rb +16 -0
  21. data/lib/spreedly/transactions/auth_purchase.rb +17 -0
  22. data/lib/spreedly/transactions/authorization.rb +7 -0
  23. data/lib/spreedly/transactions/capture.rb +14 -0
  24. data/lib/spreedly/transactions/gateway_transaction.rb +31 -0
  25. data/lib/spreedly/transactions/purchase.rb +7 -0
  26. data/lib/spreedly/transactions/redact_payment_method.rb +14 -0
  27. data/lib/spreedly/transactions/refund.rb +14 -0
  28. data/lib/spreedly/transactions/retain_payment_method.rb +14 -0
  29. data/lib/spreedly/transactions/transaction.rb +41 -0
  30. data/lib/spreedly/transactions/void.rb +9 -0
  31. data/lib/spreedly/urls.rb +64 -0
  32. data/lib/spreedly/version.rb +1 -1
  33. data/spreedly.gemspec +29 -0
  34. data/test/credentials/credentials.yml +9 -0
  35. data/test/credentials/test_credentials.rb +43 -0
  36. data/test/helpers/assertions.rb +29 -0
  37. data/test/helpers/communication_helper.rb +31 -0
  38. data/test/helpers/creation_helper.rb +26 -0
  39. data/test/helpers/stub_response.rb +18 -0
  40. data/test/remote/remote_add_credit_card_test.rb +62 -0
  41. data/test/remote/remote_add_gateway_test.rb +30 -0
  42. data/test/remote/remote_authorize_test.rb +48 -0
  43. data/test/remote/remote_capture_test.rb +71 -0
  44. data/test/remote/remote_find_gateway_test.rb +31 -0
  45. data/test/remote/remote_find_payment_method_test.rb +29 -0
  46. data/test/remote/remote_find_transaction_test.rb +33 -0
  47. data/test/remote/remote_list_transactions_test.rb +36 -0
  48. data/test/remote/remote_purchase_test.rb +69 -0
  49. data/test/remote/remote_redact_test.rb +38 -0
  50. data/test/remote/remote_refund_test.rb +65 -0
  51. data/test/remote/remote_retain_test.rb +39 -0
  52. data/test/remote/remote_void_test.rb +64 -0
  53. data/test/test_helper.rb +23 -0
  54. data/test/unit/add_credit_card_test.rb +74 -0
  55. data/test/unit/add_gateway_test.rb +26 -0
  56. data/test/unit/authorize_test.rb +87 -0
  57. data/test/unit/capture_test.rb +91 -0
  58. data/test/unit/environment_test.rb +18 -0
  59. data/test/unit/fields_test.rb +75 -0
  60. data/test/unit/find_gateway_test.rb +28 -0
  61. data/test/unit/find_payment_method_test.rb +90 -0
  62. data/test/unit/find_transaction_test.rb +31 -0
  63. data/test/unit/list_transactions_test.rb +46 -0
  64. data/test/unit/purchase_test.rb +95 -0
  65. data/test/unit/redact_payment_method_test.rb +51 -0
  66. data/test/unit/refund_test.rb +91 -0
  67. data/test/unit/response_stubs/add_credit_card_stubs.rb +43 -0
  68. data/test/unit/response_stubs/add_gateway_stubs.rb +39 -0
  69. data/test/unit/response_stubs/authorization_stubs.rb +139 -0
  70. data/test/unit/response_stubs/capture_stubs.rb +87 -0
  71. data/test/unit/response_stubs/find_gateway_stubs.rb +38 -0
  72. data/test/unit/response_stubs/find_payment_method_stubs.rb +108 -0
  73. data/test/unit/response_stubs/find_transaction_stubs.rb +43 -0
  74. data/test/unit/response_stubs/list_transactions_stubs.rb +110 -0
  75. data/test/unit/response_stubs/purchase_stubs.rb +139 -0
  76. data/test/unit/response_stubs/redact_payment_method_stubs.rb +54 -0
  77. data/test/unit/response_stubs/refund_stubs.rb +87 -0
  78. data/test/unit/response_stubs/retain_payment_method_stubs.rb +85 -0
  79. data/test/unit/response_stubs/void_stubs.rb +79 -0
  80. data/test/unit/retain_payment_method_test.rb +44 -0
  81. data/test/unit/timeout_test.rb +20 -0
  82. data/test/unit/void_test.rb +96 -0
  83. metadata +215 -29
  84. checksums.yaml +0 -15
  85. data/lib/spreedly/common.rb +0 -44
  86. data/lib/spreedly/mock.rb +0 -221
  87. data/lib/spreedly/test_hacks.rb +0 -27
checksums.yaml DELETED
@@ -1,15 +0,0 @@
1
- ---
2
- !binary "U0hBMQ==":
3
- metadata.gz: !binary |-
4
- NWQ5NjM1NzgyZTBkYWJjY2I1MDM0ZDExMzJiMjIyNTExNjg2ODQ5MA==
5
- data.tar.gz: !binary |-
6
- NmMyNjUyZTIxNDNiYzAwZjVjNzgwZDRkYzk0MjRkMWNiODkzNmZjOQ==
7
- !binary "U0hBNTEy":
8
- metadata.gz: !binary |-
9
- YmExNTYxMDhlYjdlZGZjZDYxOGE2Y2Q4MTcwNjlmN2M3NWYxYzE2N2FiMGI3
10
- YWQ4NjY0OTRhYmViN2IxNWJhNmU4M2ZkYjJlM2I2ODRhMmZlYzM0ZGRhMzU2
11
- NzhiMzc4NzUzOGI4MzNhYmIyNmZiYTFkYzgzOTk4YTdjYTcyYTk=
12
- data.tar.gz: !binary |-
13
- YzZmMDVlYjNhOWQ4NTg3ZTAzNjJjMTE3ZTgzNzViZTYwYTVmYmUzMTZmMzFi
14
- NWZlZWY0NjJmYjllZDI5YTJhMzMyMmYzMjdlYTNkZjYxNTk5YTIxM2U5ODkw
15
- NmVjMmI3YzU3OGE4NDkwOWRhNzAxYWNjMzhiZjQ2ODc3OTQyMjA=
@@ -1,44 +0,0 @@
1
- Dir[File.dirname(__FILE__) + '/../../vendor/*'].each do |directory|
2
- next unless File.directory?(directory)
3
- $LOAD_PATH.unshift File.expand_path(directory + '/lib')
4
- end
5
-
6
- require 'uri'
7
- require 'bigdecimal'
8
-
9
- require 'spreedly/version'
10
-
11
- module Spreedly
12
- # Generates a subscribe url for the given user id and plan.
13
- # Options:
14
- # :screen_name => a screen name for the user (shows up in the admin UI)
15
- # :email => pre-populate the email field
16
- # :first_name => pre-populate the first name field
17
- # :last_name => pre-populate the last name field
18
- def self.subscribe_url(id, plan, options={})
19
- %w(screen_name email first_name last_name return_url).each do |option|
20
- options[option.to_sym] &&= URI.escape(options[option.to_sym])
21
- end
22
-
23
- screen_name = options.delete(:screen_name)
24
- params = %w(email first_name last_name return_url).select{|e| options[e.to_sym]}.collect{|e| "#{e}=#{options[e.to_sym]}"}.join('&')
25
-
26
- url = "https://spreedly.com/#{site_name}/subscribers/#{id}/subscribe/#{plan}"
27
- url << "/#{screen_name}" if screen_name
28
- url << '?' << params unless params == ''
29
-
30
- url
31
- end
32
-
33
- # Generates an edit subscriber for the given subscriber token. The
34
- # token is returned with the subscriber info (i.e. by
35
- # Subscriber.find).
36
- def self.edit_subscriber_url(token, return_url = nil)
37
- "https://spreedly.com/#{site_name}/subscriber_accounts/#{token}" +
38
- if return_url
39
- "?return_url=#{URI.escape(return_url)}"
40
- else
41
- ''
42
- end
43
- end
44
- end
data/lib/spreedly/mock.rb DELETED
@@ -1,221 +0,0 @@
1
- require 'spreedly/common'
2
-
3
- raise "Real Spreedly already required!" if defined?(Spreedly::REAL)
4
-
5
- module Spreedly
6
- MOCK = "mock"
7
-
8
- def self.configure(name, token)
9
- @site_name = name
10
- end
11
-
12
- def self.site_name
13
- @site_name
14
- end
15
-
16
- class Resource
17
- def self.attributes
18
- @attributes ||= {}
19
- end
20
-
21
- def self.attributes=(value)
22
- @attributes = value
23
- end
24
-
25
- attr_reader :attributes
26
- def initialize(params={})
27
- @attributes = self.class.attributes.inject({}){|a,(k,v)| a[k.to_sym] = v.call; a}
28
- params.each {|k,v| @attributes[k.to_sym] = v }
29
- end
30
-
31
- def id
32
- @attributes[:id]
33
- end
34
-
35
- def method_missing(method, *args)
36
- if method.to_s =~ /\?$/
37
- send(method.to_s[0..-2], *args)
38
- elsif @attributes.include?(method)
39
- @attributes[method]
40
- else
41
- super
42
- end
43
- end
44
- end
45
-
46
- class Subscriber < Resource
47
- self.attributes = {
48
- :created_at => proc{Time.now},
49
- :token => proc{(rand * 1000).round},
50
- :active => proc{false},
51
- :store_credit => proc{BigDecimal("0.0")},
52
- :active_until => proc{nil},
53
- :feature_level => proc{""},
54
- :on_trial => proc{false},
55
- :recurring => proc{false},
56
- :eligible_for_free_trial => proc{false}
57
- }
58
-
59
- def self.wipe! # :nodoc: all
60
- @subscribers = nil
61
- end
62
-
63
- def self.create!(id, *args) # :nodoc: all
64
- optional_attrs = args.last.is_a?(::Hash) ? args.pop : {}
65
- email, screen_name = args
66
- sub = new({:customer_id => id, :email => email, :screen_name => screen_name}.merge(optional_attrs))
67
-
68
- if subscribers[sub.id]
69
- raise "Could not create subscriber: already exists."
70
- end
71
-
72
- subscribers[sub.id] = sub
73
- sub
74
- end
75
-
76
- def self.delete!(id)
77
- subscribers.delete(id)
78
- end
79
-
80
- def self.find(id)
81
- subscribers[id]
82
- end
83
-
84
- def self.subscribers
85
- @subscribers ||= {}
86
- end
87
-
88
- def self.all
89
- @subscribers.values
90
- end
91
-
92
- def initialize(params={})
93
- super
94
- if !id || id == ''
95
- raise "Could not create subscriber: Customer ID can't be blank."
96
- end
97
- @invoices ||= []
98
- end
99
-
100
- def id
101
- @attributes[:customer_id]
102
- end
103
-
104
- def update(args)
105
- args.each_pair do |key, value|
106
- if @attributes.has_key?(key)
107
- @attributes[key] = value
108
- end
109
- end
110
- end
111
-
112
- def comp(quantity, units, feature_level=nil)
113
- raise "Could not comp subscriber: no longer exists." unless self.class.find(id)
114
- raise "Could not comp subscriber: validation failed." unless units && quantity
115
- current_active_until = (active_until || Time.now)
116
- @attributes[:active_until] = case units
117
- when 'days'
118
- current_active_until + (quantity.to_i * 86400)
119
- when 'months'
120
- current_active_until + (quantity.to_i * 30 * 86400)
121
- end
122
- @attributes[:feature_level] = feature_level if feature_level
123
- @attributes[:active] = true
124
- end
125
-
126
- def activate_free_trial(plan_id)
127
- raise "Could not activate free trial for subscriber: validation failed. missing subscription plan id" unless plan_id
128
- raise "Could not active free trial for subscriber: subscriber or subscription plan no longer exists." unless self.class.find(id) && SubscriptionPlan.find(plan_id)
129
- raise "Could not activate free trial for subscriber: subscription plan either 1) isn't a free trial, 2) the subscriber is not eligible for a free trial, or 3) the subscription plan is not enabled." if (on_trial? and !eligible_for_free_trial?)
130
- @attributes[:on_trial] = true
131
- plan = SubscriptionPlan.find(plan_id)
132
- comp(plan.duration_quantity, plan.duration_units, plan.feature_level)
133
- end
134
-
135
- def allow_free_trial
136
- @attributes[:eligible_for_free_trial] = true
137
- end
138
-
139
- def stop_auto_renew
140
- raise "Could not stop auto renew for subscriber: subscriber does not exist." unless self.class.find(id)
141
- @attributes[:recurring] = false
142
- end
143
-
144
- def subscribe(plan_id, card_number="4222222222222")
145
- plan = SubscriptionPlan.find(plan_id)
146
- @invoices.unshift(Invoice.new(
147
- amount: (@invoices.select{|invoice| invoice.closed?}.size > 0 ? 0 : plan.amount),
148
- closed: false
149
- ))
150
-
151
- return unless card_number == "4222222222222"
152
-
153
- @invoices.first.attributes[:closed] = true
154
- @attributes[:recurring] = true
155
- comp(plan.duration_quantity, plan.duration_units, plan.feature_level)
156
- end
157
-
158
- def add_fee(args)
159
- raise "Unprocessable Entity" unless (args.keys & [:amount, :group, :name]).size == 3
160
- raise "Unprocessable Entity" unless active?
161
- nil
162
- end
163
-
164
- def invoices
165
- @invoices
166
- end
167
-
168
- def last_successful_invoice
169
- @invoices.detect{|invoice| invoice.closed?}
170
- end
171
- end
172
-
173
- class Invoice < Resource
174
- end
175
-
176
- class SubscriptionPlan < Resource
177
- self.attributes = {
178
- :plan_type => proc{'regular'},
179
- :feature_level => proc{''}
180
- }
181
-
182
- def self.all
183
- plans.values
184
- end
185
-
186
- def self.find(id)
187
- plans[id.to_i]
188
- end
189
-
190
- def self.plans
191
- @plans ||= {
192
- 1 => new(
193
- :id => 1,
194
- :name => 'Default mock plan',
195
- :duration_quantity => 1,
196
- :duration_units => 'days',
197
- :amount => 6
198
- ),
199
- 2 => new(
200
- :id => 2,
201
- :name => 'Test Free Trial Plan',
202
- :plan_type => 'free_trial',
203
- :duration_quantity => 1,
204
- :duration_units => 'days',
205
- :amount => 11
206
- ),
207
- 3 => new(
208
- :id => 3,
209
- :name => 'Test Regular Plan',
210
- :duration_quantity => 1,
211
- :duration_units => 'days',
212
- :amount => 17
213
- )
214
- }
215
- end
216
-
217
- def trial?
218
- (plan_type == "free_trial")
219
- end
220
- end
221
- end
@@ -1,27 +0,0 @@
1
- require 'mechanize'
2
-
3
- module Spreedly
4
- class Subscriber
5
- # This method is *strictly* for use when testing, and will
6
- # probably only work against a test Spreedly site anyhow.
7
- def subscribe(plan_id, card_number="4222222222222")
8
- agent = Mechanize.new
9
- page = agent.get(Spreedly.subscribe_url(id, plan_id))
10
- page = page.forms.first.submit
11
- form = page.forms.first
12
- form['credit_card[first_name]'] = 'Joe'
13
- form['credit_card[last_name]'] = 'Bob'
14
- form['subscriber[email]'] = 'joe@example.com'
15
- form['credit_card[number]'] = card_number
16
- form['credit_card[card_type]'] = 'visa'
17
- form['credit_card[verification_value]'] = '234'
18
- form['credit_card[month]'] = '1'
19
- form['credit_card[year]'] = '2024'
20
- page = form.click_button
21
-
22
- if card_number == "4222222222222"
23
- raise "Subscription didn't go through" unless page.title == "Thank you!"
24
- end
25
- end
26
- end
27
- end