spook_and_pay 0.2.6.alpha → 0.2.7.alpha
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.
- 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
|