spreedly 1.4.0 → 2.0.0

Sign up to get free protection for your applications and to get access to all the features.
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