spook_and_pay 0.2.6.alpha → 0.2.7.alpha
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/lib/spook_and_pay/credit_card.rb +71 -1
- data/lib/spook_and_pay/providers/base.rb +95 -6
- data/lib/spook_and_pay/providers/spreedly.rb +42 -4
- data/lib/spook_and_pay/transaction.rb +12 -9
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 0bd84aa5f8a08e720cb7eb6140911be472d923ee
|
4
|
+
data.tar.gz: c9345a68d16c46d723812c9934f561c3ce5513ec
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 045d465056dce7c1025c4c04b7dca6e4f504b2203c86f3ea52b86f40ede6b919db556c312fe25b5477e47304846eb48e294ee94c9e3edaecec46354ea0d48106
|
7
|
+
data.tar.gz: 7b9e0f4368ce879baf32b3a20f4b41ba1d1f3164ae3a44f69d83ffb7c0b6ab4a8835281da3aa67c9a80171a8f8a70dc7144a7d0473baf327c851b2286c3ac5c1
|
@@ -6,6 +6,14 @@ module SpookAndPay
|
|
6
6
|
# This module adds the ::attr_erroring_reader to this class
|
7
7
|
extend SpookAndPay::ErroringReader
|
8
8
|
|
9
|
+
# An error raised when trying to perform an action on a card that has
|
10
|
+
# invalid details or has expired.
|
11
|
+
class InvalidCardError < StandardError
|
12
|
+
def to_s
|
13
|
+
"The action cannot be performed, this card is invalid or expired."
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
9
17
|
# The basic attributes of the credit card.
|
10
18
|
attr_reader :provider, :id, :raw
|
11
19
|
|
@@ -60,12 +68,58 @@ module SpookAndPay
|
|
60
68
|
end
|
61
69
|
end
|
62
70
|
|
71
|
+
# Checks to see if funds can be credited to a card. Depends on the
|
72
|
+
# gateway/provider supporting crediting and having a valid card.
|
73
|
+
#
|
74
|
+
# @return [true, false]
|
75
|
+
def can_credit?
|
76
|
+
provider.supports_credit? and valid? and !expired?
|
77
|
+
end
|
78
|
+
|
79
|
+
# Checks to see if this card can be authorized against the specified
|
80
|
+
# gateway.
|
81
|
+
#
|
82
|
+
# @return [true, false]
|
83
|
+
def can_authorize?
|
84
|
+
provider.supports_authorize? and valid? and !expired?
|
85
|
+
end
|
86
|
+
|
87
|
+
# Checks to see if this card can be used for a purchase against the
|
88
|
+
# underlying gateway.
|
89
|
+
#
|
90
|
+
# @return [true, false]
|
91
|
+
def can_purchase?
|
92
|
+
provider.supports_purchase? and valid? and !expired?
|
93
|
+
end
|
94
|
+
|
95
|
+
# Checks to see if the provider/gateway supports the deletion of credit
|
96
|
+
# card details.
|
97
|
+
#
|
98
|
+
# @return [true, false]
|
99
|
+
def can_delete?
|
100
|
+
provider.supports_delete?
|
101
|
+
end
|
102
|
+
|
103
|
+
# Credits the specified amount to the card.
|
104
|
+
#
|
105
|
+
# @param [String, Numeric] amount
|
106
|
+
# @return SpookAndPay::Result
|
107
|
+
# @raises SpookAndPay::Providers::Base::NotSupportedError
|
108
|
+
# @raises SpookAndPay::CreditCard::InvalidCardError
|
109
|
+
def credit!(amount)
|
110
|
+
verify_action
|
111
|
+
provider.credit_via_credit_card(self, amount)
|
112
|
+
end
|
113
|
+
|
63
114
|
# Authorizes a payment of the specified amount. This generates a new
|
64
115
|
# transaction that must be later settled.
|
65
116
|
#
|
66
117
|
# @param [String, Numeric] amount
|
67
118
|
# @return SpookAndPay::Result
|
119
|
+
# @raises SpookAndPay::Providers::Base::NotSupportedError
|
120
|
+
# @raises SpookAndPay::CreditCard::InvalidCardError
|
68
121
|
def authorize!(amount)
|
122
|
+
verify_action
|
69
123
|
provider.authorize_via_credit_card(self, amount)
|
70
124
|
end
|
71
125
|
|
@@ -73,13 +127,17 @@ module SpookAndPay
|
|
73
127
|
#
|
74
128
|
# @param [String, Numeric] amount
|
75
129
|
# @return SpookAndPay::Result
|
130
|
+
# @raises SpookAndPay::Providers::Base::NotSupportedError
|
131
|
+
# @raises SpookAndPay::CreditCard::InvalidCardError
|
76
132
|
def purchase!(amount)
|
133
|
+
verify_action
|
77
134
|
provider.purchase_via_credit_card(self, amount)
|
78
135
|
end
|
79
136
|
|
80
137
|
# Deletes the credit card from the provider's vault.
|
81
138
|
#
|
82
|
-
# @return
|
139
|
+
# @return SpookAndPay::Result
|
140
|
+
# @raises SpookAndPay::Providers::Base::NotSupportedError
|
83
141
|
def delete!
|
84
142
|
provider.delete_credit_card(self)
|
85
143
|
end
|
@@ -98,5 +156,17 @@ module SpookAndPay
|
|
98
156
|
def expired?
|
99
157
|
expired
|
100
158
|
end
|
159
|
+
|
160
|
+
private
|
161
|
+
|
162
|
+
|
163
|
+
# A helper method which validates any actions — authorize, credit etc. —
|
164
|
+
# and where the card is expired or has invalid details, raises an error.
|
165
|
+
#
|
166
|
+
# @return nil
|
167
|
+
# @raises SpookAndPay::CreditCard::InvalidCardError
|
168
|
+
def verify_action
|
169
|
+
raise InvalidCardError if expired? or !valid?
|
170
|
+
end
|
101
171
|
end
|
102
172
|
end
|
@@ -118,7 +118,7 @@ module SpookAndPay
|
|
118
118
|
# @param [SpookAndPay::Transaction, String] id
|
119
119
|
# @return SpookAndPay::Result
|
120
120
|
def capture_transaction(id)
|
121
|
-
|
121
|
+
check_support('capture')
|
122
122
|
end
|
123
123
|
|
124
124
|
# Refunds the amount of money captured in a transaction.
|
@@ -129,7 +129,16 @@ module SpookAndPay
|
|
129
129
|
# @param [SpookAndPay::Transaction, String] id
|
130
130
|
# @return SpookAndPay::Result
|
131
131
|
def refund_transaction(id)
|
132
|
-
|
132
|
+
check_support('refund')
|
133
|
+
end
|
134
|
+
|
135
|
+
# Checks to see if purchasing is supported. This is dependent on the payment
|
136
|
+
# provider. The default implementation simply returns true. Specific
|
137
|
+
# implementations should over-ride this method.
|
138
|
+
#
|
139
|
+
# @return [true, false]
|
140
|
+
def supports_purchase?
|
141
|
+
true
|
133
142
|
end
|
134
143
|
|
135
144
|
# Checks to see if voiding is supported. This is dependent on the payment
|
@@ -141,6 +150,51 @@ module SpookAndPay
|
|
141
150
|
true
|
142
151
|
end
|
143
152
|
|
153
|
+
# Checks to see if crediting is supported. This is dependent on the payment
|
154
|
+
# provider. The default implementation simply returns true. Specific
|
155
|
+
# implementations should over-ride this method.
|
156
|
+
#
|
157
|
+
# @return [true, false]
|
158
|
+
def supports_credit?
|
159
|
+
true
|
160
|
+
end
|
161
|
+
|
162
|
+
# Checks to see if refunding is supported. This is dependent on the payment
|
163
|
+
# provider. The default implementation simply returns true. Specific
|
164
|
+
# implementations should over-ride this method.
|
165
|
+
#
|
166
|
+
# @return [true, false]
|
167
|
+
def supports_refund?
|
168
|
+
true
|
169
|
+
end
|
170
|
+
|
171
|
+
# Checks to see if capturing is supported. This is dependent on the payment
|
172
|
+
# provider. The default implementation simply returns true. Specific
|
173
|
+
# implementations should over-ride this method.
|
174
|
+
#
|
175
|
+
# @return [true, false]
|
176
|
+
def supports_capture?
|
177
|
+
true
|
178
|
+
end
|
179
|
+
|
180
|
+
# Checks to see if authorizing is supported. This is dependent on the payment
|
181
|
+
# provider. The default implementation simply returns true. Specific
|
182
|
+
# implementations should over-ride this method.
|
183
|
+
#
|
184
|
+
# @return [true, false]
|
185
|
+
def supports_authorize?
|
186
|
+
true
|
187
|
+
end
|
188
|
+
|
189
|
+
# Checks to see if the deletion of payment details is supported. This is
|
190
|
+
# dependent on the payment provider. The default implementation simply
|
191
|
+
# returns true. Specific implementations should over-ride this method.
|
192
|
+
#
|
193
|
+
# @return [true, false]
|
194
|
+
def supports_delete?
|
195
|
+
true
|
196
|
+
end
|
197
|
+
|
144
198
|
# Voids an authorization.
|
145
199
|
#
|
146
200
|
# This should not be called directly. Instead, use the #void! method
|
@@ -151,7 +205,7 @@ module SpookAndPay
|
|
151
205
|
# @api private
|
152
206
|
# @abstract Subclass to implement
|
153
207
|
def void_transaction(id)
|
154
|
-
|
208
|
+
check_support('void')
|
155
209
|
end
|
156
210
|
|
157
211
|
# Authorizes a payment against a credit card
|
@@ -165,7 +219,21 @@ module SpookAndPay
|
|
165
219
|
# @api private
|
166
220
|
# @abstract Subclass to implement
|
167
221
|
def authorize_via_credit_card(id, amount)
|
168
|
-
|
222
|
+
check_support('authorize')
|
223
|
+
end
|
224
|
+
|
225
|
+
# Credits funds to a credit card
|
226
|
+
#
|
227
|
+
# This should not be called directly. Instead, use the #authorize! method
|
228
|
+
# provided by a CreditCard instance.
|
229
|
+
#
|
230
|
+
# @param [SpookAndPay::CreditCard, String] id
|
231
|
+
# @param [String, Numeric] amount in dollars
|
232
|
+
# @return SpookAndPay::Result
|
233
|
+
# @api private
|
234
|
+
# @abstract Subclass to implement
|
235
|
+
def credit_via_credit_card(id, amount)
|
236
|
+
check_support('credit')
|
169
237
|
end
|
170
238
|
|
171
239
|
# Creates a purchase against a credit card.
|
@@ -179,7 +247,7 @@ module SpookAndPay
|
|
179
247
|
# @api private
|
180
248
|
# @abstract Subclass to implement
|
181
249
|
def purchase_via_credit_card(id, amount)
|
182
|
-
|
250
|
+
check_support('purchase')
|
183
251
|
end
|
184
252
|
|
185
253
|
# Removes payment details from the provider's vault.
|
@@ -192,11 +260,32 @@ module SpookAndPay
|
|
192
260
|
# @api private
|
193
261
|
# @abstract Subclass to implement
|
194
262
|
def delete_credit_card(id)
|
195
|
-
|
263
|
+
check_support('delete')
|
196
264
|
end
|
197
265
|
|
198
266
|
private
|
199
267
|
|
268
|
+
# Checks to see if a particular action is defined as being supported and
|
269
|
+
# raises the appropriate error.
|
270
|
+
#
|
271
|
+
# The basic semantics is this; if someone implementing a provider says an
|
272
|
+
# action is supported via a #supports_*? predicate, this method should
|
273
|
+
# never be called, so we raise NotImplementedError. Otherwise they are
|
274
|
+
# saying it's not supported and the appropriate response is to raise a
|
275
|
+
# NotSupportedError.
|
276
|
+
#
|
277
|
+
# @param String action
|
278
|
+
# @return nil
|
279
|
+
# @raises NotSupportedError
|
280
|
+
# @raises NotImplementedError
|
281
|
+
def check_support(action)
|
282
|
+
if send(:"supports_#{action}?")
|
283
|
+
raise NotImplementedError
|
284
|
+
else
|
285
|
+
raise NotSupportedError
|
286
|
+
end
|
287
|
+
end
|
288
|
+
|
200
289
|
# Extracts the credit card id from it's argument. This is is to help with
|
201
290
|
# methods that accept either a card instance of an id.
|
202
291
|
#
|
@@ -49,11 +49,17 @@ module SpookAndPay
|
|
49
49
|
# @param Hash opts
|
50
50
|
# @return Hash
|
51
51
|
def prepare_payment_submission(redirect_url, opts = {})
|
52
|
-
{
|
52
|
+
config = {
|
53
53
|
:url => spreedly.transparent_redirect_form_action,
|
54
54
|
:field_names => self.class::FORM_FIELD_NAMES,
|
55
55
|
:hidden_fields => {:redirect_url => redirect_url, :environment_key => spreedly.key}
|
56
56
|
}
|
57
|
+
|
58
|
+
if opts[:token]
|
59
|
+
config[:hidden_fields][:payment_method_token] = opts[:token]
|
60
|
+
end
|
61
|
+
|
62
|
+
config
|
57
63
|
end
|
58
64
|
|
59
65
|
# Confirms the submission of payment details to Spreedly Core.
|
@@ -115,10 +121,30 @@ module SpookAndPay
|
|
115
121
|
# spreedly gem, check it.
|
116
122
|
::Spreedly::Gateway.send(:field, :characteristics)
|
117
123
|
|
124
|
+
def supports_purchase?
|
125
|
+
check_support_for('supports_purchase')
|
126
|
+
end
|
127
|
+
|
118
128
|
def supports_void?
|
119
|
-
|
120
|
-
|
121
|
-
|
129
|
+
check_support_for('supports_void')
|
130
|
+
end
|
131
|
+
|
132
|
+
def supports_credit?
|
133
|
+
false
|
134
|
+
end
|
135
|
+
|
136
|
+
def supports_capture?
|
137
|
+
check_support_for('supports_capture')
|
138
|
+
end
|
139
|
+
|
140
|
+
def supports_authorize?
|
141
|
+
check_support_for('supports_authorize')
|
142
|
+
end
|
143
|
+
|
144
|
+
def supports_delete?
|
145
|
+
# This does not check the gateway, since the redaction is specific to
|
146
|
+
# Spreedly's store, not the gateway.
|
147
|
+
true
|
122
148
|
end
|
123
149
|
|
124
150
|
def authorize_via_credit_card(id, amount)
|
@@ -138,6 +164,18 @@ module SpookAndPay
|
|
138
164
|
|
139
165
|
private
|
140
166
|
|
167
|
+
# Retrieves the gateway from Spreedly and then inspects the response to
|
168
|
+
# see what features it supports. This is a helper for the #supports_*?
|
169
|
+
# predicates.
|
170
|
+
#
|
171
|
+
# @param String path
|
172
|
+
# @return [true, false]
|
173
|
+
def check_support_for(path)
|
174
|
+
gateway = spreedly.find_gateway(gateway_token)
|
175
|
+
node = Nokogiri::XML::DocumentFragment.parse(gateway.characteristics)
|
176
|
+
node.xpath(".//#{path}").inner_html.strip == 'true'
|
177
|
+
end
|
178
|
+
|
141
179
|
# Takes the result of running a transaction against a Spreedly gateway
|
142
180
|
# and coerces it into a SpookAndPay::Result
|
143
181
|
#
|
@@ -96,7 +96,7 @@ module SpookAndPay
|
|
96
96
|
#
|
97
97
|
# @return [true, false]
|
98
98
|
def can_refund?
|
99
|
-
|
99
|
+
settled? and provider.supports_refund?
|
100
100
|
end
|
101
101
|
|
102
102
|
# A predicate for checking if a transaction can be captured. Only true if
|
@@ -104,7 +104,7 @@ module SpookAndPay
|
|
104
104
|
#
|
105
105
|
# @return [true, false]
|
106
106
|
def can_capture?
|
107
|
-
|
107
|
+
authorized? and provider.supports_capture?
|
108
108
|
end
|
109
109
|
|
110
110
|
# A predicate for checking if a transaction can be voided. Only true if
|
@@ -112,7 +112,7 @@ module SpookAndPay
|
|
112
112
|
#
|
113
113
|
# @return [true, false]
|
114
114
|
def can_void?
|
115
|
-
(
|
115
|
+
(authorized? or settling?) and provider.supports_void?
|
116
116
|
end
|
117
117
|
|
118
118
|
# Refunds the transaction. The related credit card will be credited for
|
@@ -120,9 +120,10 @@ module SpookAndPay
|
|
120
120
|
# authorizations.
|
121
121
|
#
|
122
122
|
# @return SpookAndPay::Result
|
123
|
-
# @raises InvalidActionError
|
123
|
+
# @raises SpookAndPay::Transaction::InvalidActionError
|
124
|
+
# @raises SpookAndPay::Providers::Base::NotSupportedError
|
124
125
|
def refund!
|
125
|
-
raise InvalidActionError.new(id, :refund, status) unless
|
126
|
+
raise InvalidActionError.new(id, :refund, status) unless settled?
|
126
127
|
provider.refund_transaction(self)
|
127
128
|
end
|
128
129
|
|
@@ -130,9 +131,10 @@ module SpookAndPay
|
|
130
131
|
# authorized and will fail if the transaction is already captured.
|
131
132
|
#
|
132
133
|
# @return SpookAndPay::Result
|
133
|
-
# @raises InvalidActionError
|
134
|
+
# @raises SpookAndPay::Transaction::InvalidActionError
|
135
|
+
# @raises SpookAndPay::Providers::Base::NotSupportedError
|
134
136
|
def capture!
|
135
|
-
raise InvalidActionError.new(id, :capture, status) unless
|
137
|
+
raise InvalidActionError.new(id, :capture, status) unless authorized?
|
136
138
|
provider.capture_transaction(self)
|
137
139
|
end
|
138
140
|
|
@@ -140,9 +142,10 @@ module SpookAndPay
|
|
140
142
|
# authorized status. Otherwise it must be refunded.
|
141
143
|
#
|
142
144
|
# @return SpookAndPay::Result
|
143
|
-
# @raises InvalidActionError
|
145
|
+
# @raises SpookAndPay::Transaction::InvalidActionError
|
146
|
+
# @raises SpookAndPay::Providers::Base::NotSupportedError
|
144
147
|
def void!
|
145
|
-
raise InvalidActionError.new(id, :void, status) unless
|
148
|
+
raise InvalidActionError.new(id, :void, status) unless authorized? or settling?
|
146
149
|
provider.void_transaction(self)
|
147
150
|
end
|
148
151
|
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: spook_and_pay
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.2.
|
4
|
+
version: 0.2.7.alpha
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Luke Sutton
|
@@ -9,7 +9,7 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date:
|
12
|
+
date: 2014-01-13 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: braintree
|