activemerchant 1.29.1 → 1.33.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.
- data/CHANGELOG +137 -0
- data/CONTRIBUTORS +43 -0
- data/README.md +59 -51
- data/lib/active_merchant/billing/check.rb +15 -14
- data/lib/active_merchant/billing/credit_card.rb +9 -5
- data/lib/active_merchant/billing/credit_card_formatting.rb +8 -8
- data/lib/active_merchant/billing/gateway.rb +2 -2
- data/lib/active_merchant/billing/gateways/authorize_net.rb +36 -8
- data/lib/active_merchant/billing/gateways/authorize_net_cim.rb +17 -5
- data/lib/active_merchant/billing/gateways/balanced.rb +9 -3
- data/lib/active_merchant/billing/gateways/banwire.rb +15 -1
- data/lib/active_merchant/billing/gateways/barclays_epdq.rb +8 -1
- data/lib/active_merchant/billing/gateways/beanstream/beanstream_core.rb +7 -2
- data/lib/active_merchant/billing/gateways/beanstream.rb +26 -24
- data/lib/active_merchant/billing/gateways/blue_pay.rb +201 -185
- data/lib/active_merchant/billing/gateways/bogus.rb +1 -1
- data/lib/active_merchant/billing/gateways/braintree_blue.rb +6 -2
- data/lib/active_merchant/billing/gateways/card_stream_modern.rb +155 -0
- data/lib/active_merchant/billing/gateways/cc5.rb +156 -0
- data/lib/active_merchant/billing/gateways/cyber_source.rb +55 -22
- data/lib/active_merchant/billing/gateways/data_cash.rb +3 -3
- data/lib/active_merchant/billing/gateways/evo_ca.rb +308 -0
- data/lib/active_merchant/billing/gateways/eway.rb +114 -171
- data/lib/active_merchant/billing/gateways/eway_managed.rb +52 -22
- data/lib/active_merchant/billing/gateways/finansbank.rb +22 -0
- data/lib/active_merchant/billing/gateways/firstdata_e4.rb +314 -0
- data/lib/active_merchant/billing/gateways/garanti.rb +0 -4
- data/lib/active_merchant/billing/gateways/ideal_rabobank.rb +13 -2
- data/lib/active_merchant/billing/gateways/iridium.rb +8 -2
- data/lib/active_merchant/billing/gateways/litle.rb +354 -105
- data/lib/active_merchant/billing/gateways/merchant_e_solutions.rb +27 -6
- data/lib/active_merchant/billing/gateways/merchant_ware.rb +44 -9
- data/lib/active_merchant/billing/gateways/merchant_warrior.rb +190 -0
- data/lib/active_merchant/billing/gateways/moneris.rb +3 -5
- data/lib/active_merchant/billing/gateways/moneris_us.rb +1 -1
- data/lib/active_merchant/billing/gateways/nab_transact.rb +20 -3
- data/lib/active_merchant/billing/gateways/net_registry.rb +8 -3
- data/lib/active_merchant/billing/gateways/netaxept.rb +65 -117
- data/lib/active_merchant/billing/gateways/netbilling.rb +1 -0
- data/lib/active_merchant/billing/gateways/netpay.rb +223 -0
- data/lib/active_merchant/billing/gateways/ogone.rb +7 -5
- data/lib/active_merchant/billing/gateways/optimal_payment.rb +43 -18
- data/lib/active_merchant/billing/gateways/orbital.rb +190 -53
- data/lib/active_merchant/billing/gateways/payflow/payflow_common_api.rb +14 -11
- data/lib/active_merchant/billing/gateways/payment_express.rb +62 -1
- data/lib/active_merchant/billing/gateways/paymill.rb +179 -0
- data/lib/active_merchant/billing/gateways/paypal/paypal_common_api.rb +12 -7
- data/lib/active_merchant/billing/gateways/paypal/paypal_express_response.rb +14 -9
- data/lib/active_merchant/billing/gateways/paypal_express.rb +42 -18
- data/lib/active_merchant/billing/gateways/pin.rb +165 -0
- data/lib/active_merchant/billing/gateways/qbms.rb +3 -2
- data/lib/active_merchant/billing/gateways/quickpay.rb +66 -28
- data/lib/active_merchant/billing/gateways/sage/sage_bankcard.rb +16 -11
- data/lib/active_merchant/billing/gateways/sage/sage_core.rb +1 -1
- data/lib/active_merchant/billing/gateways/sage/sage_virtual_check.rb +21 -16
- data/lib/active_merchant/billing/gateways/sage.rb +10 -5
- data/lib/active_merchant/billing/gateways/sage_pay.rb +7 -0
- data/lib/active_merchant/billing/gateways/smart_ps.rb +1 -1
- data/lib/active_merchant/billing/gateways/spreedly_core.rb +233 -0
- data/lib/active_merchant/billing/gateways/stripe.rb +25 -11
- data/lib/active_merchant/billing/gateways/transnational.rb +239 -0
- data/lib/active_merchant/billing/gateways/usa_epay_advanced.rb +9 -4
- data/lib/active_merchant/billing/gateways/webpay.rb +8 -0
- data/lib/active_merchant/billing/gateways/wirecard.rb +15 -9
- data/lib/active_merchant/billing/gateways/worldpay.rb +60 -24
- data/lib/active_merchant/billing/integrations/direc_pay/status.rb +1 -1
- data/lib/active_merchant/billing/integrations/direc_pay.rb +1 -1
- data/lib/active_merchant/billing/integrations/dwolla/common.rb +21 -0
- data/lib/active_merchant/billing/integrations/dwolla/helper.rb +15 -6
- data/lib/active_merchant/billing/integrations/dwolla/notification.rb +11 -6
- data/lib/active_merchant/billing/integrations/dwolla/return.rb +12 -4
- data/lib/active_merchant/billing/integrations/dwolla.rb +5 -12
- data/lib/active_merchant/billing/integrations/notification.rb +13 -8
- data/lib/active_merchant/billing/integrations/payflow_link/helper.rb +19 -3
- data/lib/active_merchant/billing/integrations/paypal/notification.rb +39 -31
- data/lib/active_merchant/billing/integrations/payu_in/helper.rb +74 -0
- data/lib/active_merchant/billing/integrations/payu_in/notification.rb +167 -0
- data/lib/active_merchant/billing/integrations/payu_in/return.rb +53 -0
- data/lib/active_merchant/billing/integrations/payu_in.rb +43 -0
- data/lib/active_merchant/billing/integrations/pxpay/helper.rb +1 -0
- data/lib/active_merchant/billing/integrations/quickpay/helper.rb +13 -10
- data/lib/active_merchant/billing/integrations/quickpay/notification.rb +78 -15
- data/lib/active_merchant/billing/integrations/rbkmoney/helper.rb +23 -0
- data/lib/active_merchant/billing/integrations/rbkmoney/notification.rb +91 -0
- data/lib/active_merchant/billing/integrations/rbkmoney.rb +17 -0
- data/lib/active_merchant/billing/integrations/robokassa/common.rb +1 -1
- data/lib/active_merchant/billing/integrations/sage_pay_form/helper.rb +7 -3
- data/lib/active_merchant/billing/integrations/world_pay.rb +15 -8
- data/lib/active_merchant/version.rb +1 -1
- data.tar.gz.sig +0 -0
- metadata +124 -50
- metadata.gz.sig +0 -0
|
@@ -37,7 +37,7 @@ module ActiveMerchant #:nodoc:
|
|
|
37
37
|
self.test_url = 'https://www.testlitle.com/sandbox/communicator/online'
|
|
38
38
|
self.live_url = 'https://payments.litle.com/vap/communicator/online'
|
|
39
39
|
|
|
40
|
-
LITLE_SCHEMA_VERSION
|
|
40
|
+
LITLE_SCHEMA_VERSION = '8.13'
|
|
41
41
|
|
|
42
42
|
# The countries the gateway supports merchants from as 2 digit ISO country codes
|
|
43
43
|
self.supported_countries = ['US']
|
|
@@ -46,10 +46,10 @@ module ActiveMerchant #:nodoc:
|
|
|
46
46
|
self.supported_cardtypes = [:visa, :master, :american_express, :discover, :diners_club, :jcb]
|
|
47
47
|
|
|
48
48
|
# The homepage URL of the gateway
|
|
49
|
-
self.homepage_url
|
|
49
|
+
self.homepage_url = 'http://www.litle.com/'
|
|
50
50
|
|
|
51
51
|
# The name of the gateway
|
|
52
|
-
self.display_name
|
|
52
|
+
self.display_name = 'Litle & Co.'
|
|
53
53
|
|
|
54
54
|
self.default_currency = 'USD'
|
|
55
55
|
|
|
@@ -71,63 +71,76 @@ module ActiveMerchant #:nodoc:
|
|
|
71
71
|
super
|
|
72
72
|
end
|
|
73
73
|
|
|
74
|
-
def authorize(money,
|
|
75
|
-
to_pass =
|
|
74
|
+
def authorize(money, creditcard_or_token, options = {})
|
|
75
|
+
to_pass = build_authorize_request(money, creditcard_or_token, options)
|
|
76
76
|
build_response(:authorization, @litle.authorization(to_pass))
|
|
77
77
|
end
|
|
78
78
|
|
|
79
|
-
def purchase(money,
|
|
80
|
-
to_pass =
|
|
79
|
+
def purchase(money, creditcard_or_token, options = {})
|
|
80
|
+
to_pass = build_purchase_request(money, creditcard_or_token, options)
|
|
81
81
|
build_response(:sale, @litle.sale(to_pass))
|
|
82
82
|
end
|
|
83
83
|
|
|
84
84
|
def capture(money, authorization, options = {})
|
|
85
|
-
|
|
85
|
+
transaction_id, kind = split_authorization(authorization)
|
|
86
|
+
to_pass = create_capture_hash(money, transaction_id, options)
|
|
86
87
|
build_response(:capture, @litle.capture(to_pass))
|
|
87
88
|
end
|
|
88
89
|
|
|
90
|
+
# Note: Litle requires that authorization requests be voided via auth_reversal
|
|
91
|
+
# and other requests via void. To maintain the same interface as the other
|
|
92
|
+
# gateways the transaction_id and the kind of transaction are concatenated
|
|
93
|
+
# together with a ; separator (e.g. 1234;authorization)
|
|
94
|
+
#
|
|
95
|
+
# A partial auth_reversal can be accomplished by passing :amount as an option
|
|
89
96
|
def void(identification, options = {})
|
|
90
|
-
|
|
91
|
-
|
|
97
|
+
transaction_id, kind = split_authorization(identification)
|
|
98
|
+
if(kind == 'authorization')
|
|
99
|
+
to_pass = create_auth_reversal_hash(transaction_id, options[:amount], options)
|
|
100
|
+
build_response(:authReversal, @litle.auth_reversal(to_pass))
|
|
101
|
+
else
|
|
102
|
+
to_pass = create_void_hash(transaction_id, options)
|
|
103
|
+
build_response(:void, @litle.void(to_pass))
|
|
104
|
+
end
|
|
92
105
|
end
|
|
93
106
|
|
|
94
|
-
def credit(money,
|
|
95
|
-
to_pass =
|
|
107
|
+
def credit(money, identification_or_token, options = {})
|
|
108
|
+
to_pass = build_credit_request(money, identification_or_token, options)
|
|
96
109
|
build_response(:credit, @litle.credit(to_pass))
|
|
97
110
|
end
|
|
98
111
|
|
|
99
112
|
def store(creditcard, options = {})
|
|
100
113
|
to_pass = create_token_hash(creditcard, options)
|
|
101
|
-
build_response(:registerToken, @litle.register_token_request(to_pass), %w(801 802))
|
|
114
|
+
build_response(:registerToken, @litle.register_token_request(to_pass), %w(000 801 802))
|
|
102
115
|
end
|
|
103
116
|
|
|
104
117
|
private
|
|
105
118
|
|
|
106
119
|
CARD_TYPE = {
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
120
|
+
'visa' => 'VI',
|
|
121
|
+
'master' => 'MC',
|
|
122
|
+
'american_express' => 'AX',
|
|
123
|
+
'discover' => 'DI',
|
|
124
|
+
'jcb' => 'DI',
|
|
125
|
+
'diners_club' => 'DI'
|
|
113
126
|
}
|
|
114
127
|
|
|
115
128
|
AVS_RESPONSE_CODE = {
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
129
|
+
'00' => 'Y',
|
|
130
|
+
'01' => 'X',
|
|
131
|
+
'02' => 'D',
|
|
132
|
+
'10' => 'Z',
|
|
133
|
+
'11' => 'W',
|
|
134
|
+
'12' => 'A',
|
|
135
|
+
'13' => 'A',
|
|
136
|
+
'14' => 'P',
|
|
137
|
+
'20' => 'N',
|
|
138
|
+
'30' => 'S',
|
|
139
|
+
'31' => 'R',
|
|
140
|
+
'32' => 'U',
|
|
141
|
+
'33' => 'R',
|
|
142
|
+
'34' => 'I',
|
|
143
|
+
'40' => 'E'
|
|
131
144
|
}
|
|
132
145
|
|
|
133
146
|
def url
|
|
@@ -140,69 +153,153 @@ module ActiveMerchant #:nodoc:
|
|
|
140
153
|
response = Hash.from_xml(litle_response.raw_xml.to_s)['litleOnlineResponse']
|
|
141
154
|
|
|
142
155
|
if response['response'] == "0"
|
|
143
|
-
detail
|
|
144
|
-
fraud
|
|
156
|
+
detail = response["#{kind}Response"]
|
|
157
|
+
fraud = fraud_result(detail)
|
|
145
158
|
Response.new(
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
159
|
+
valid_responses.include?(detail['response']),
|
|
160
|
+
detail['message'],
|
|
161
|
+
{ :litleOnlineResponse => response },
|
|
162
|
+
:authorization => authorization_from(detail, kind),
|
|
163
|
+
:avs_result => { :code => fraud['avs'] },
|
|
164
|
+
:cvv_result => fraud['cvv'],
|
|
165
|
+
:test => test?
|
|
153
166
|
)
|
|
154
167
|
else
|
|
155
168
|
Response.new(false, response['message'], :litleOnlineResponse => response, :test => test?)
|
|
156
169
|
end
|
|
157
170
|
end
|
|
158
171
|
|
|
159
|
-
|
|
160
|
-
|
|
172
|
+
# Generates an authorization string of the appropriate id and the kind of transaction
|
|
173
|
+
# See #void for how the kind is used
|
|
174
|
+
def authorization_from(litle_response, kind)
|
|
175
|
+
case kind
|
|
176
|
+
when :registerToken
|
|
177
|
+
authorization = litle_response['litleToken']
|
|
178
|
+
else
|
|
179
|
+
authorization = [litle_response['litleTxnId'], kind.to_s].join(";")
|
|
180
|
+
end
|
|
181
|
+
end
|
|
182
|
+
|
|
183
|
+
def split_authorization(authorization)
|
|
184
|
+
transaction_id, kind = authorization.to_s.split(';')
|
|
185
|
+
[transaction_id, kind]
|
|
186
|
+
end
|
|
187
|
+
|
|
188
|
+
def build_authorize_request(money, creditcard_or_token, options)
|
|
189
|
+
payment_method = build_payment_method(creditcard_or_token, options)
|
|
190
|
+
|
|
191
|
+
hash = create_hash(money, options)
|
|
192
|
+
|
|
193
|
+
add_creditcard_or_cardtoken_hash(hash, payment_method)
|
|
194
|
+
|
|
195
|
+
hash
|
|
196
|
+
end
|
|
197
|
+
|
|
198
|
+
def build_purchase_request(money, creditcard_or_token, options)
|
|
199
|
+
payment_method = build_payment_method(creditcard_or_token, options)
|
|
200
|
+
|
|
201
|
+
hash = create_hash(money, options)
|
|
202
|
+
|
|
203
|
+
add_creditcard_or_cardtoken_hash(hash, payment_method)
|
|
204
|
+
|
|
205
|
+
hash
|
|
206
|
+
end
|
|
207
|
+
|
|
208
|
+
def build_credit_request(money, identification_or_token, options)
|
|
209
|
+
payment_method = build_payment_method(identification_or_token, options)
|
|
210
|
+
|
|
211
|
+
hash = create_hash(money, options)
|
|
212
|
+
|
|
213
|
+
add_identification_or_cardtoken_hash(hash, payment_method)
|
|
214
|
+
|
|
215
|
+
unless payment_method.is_a?(LitleCardToken)
|
|
216
|
+
hash['orderSource'] = nil
|
|
217
|
+
hash['orderId'] = nil
|
|
218
|
+
end
|
|
219
|
+
|
|
220
|
+
hash
|
|
221
|
+
end
|
|
222
|
+
|
|
223
|
+
def build_payment_method(payment_method, options)
|
|
224
|
+
result = payment_method
|
|
225
|
+
|
|
226
|
+
# Build instance of the LitleCardToken class for internal use if this is a token request.
|
|
227
|
+
if payment_method.is_a?(String) && options.has_key?(:token)
|
|
228
|
+
result = LitleCardToken.new(:token => payment_method)
|
|
229
|
+
result.month = options[:token][:month]
|
|
230
|
+
result.year = options[:token][:year]
|
|
231
|
+
result.verification_value = options[:token][:verification_value]
|
|
232
|
+
result.brand = options[:token][:brand]
|
|
233
|
+
end
|
|
234
|
+
|
|
235
|
+
result
|
|
236
|
+
end
|
|
161
237
|
|
|
162
|
-
|
|
238
|
+
def add_creditcard_or_cardtoken_hash(hash, creditcard_or_cardtoken)
|
|
239
|
+
if creditcard_or_cardtoken.is_a?(LitleCardToken)
|
|
240
|
+
add_cardtoken_hash(hash, creditcard_or_cardtoken)
|
|
241
|
+
else
|
|
242
|
+
add_creditcard_hash(hash, creditcard_or_cardtoken)
|
|
243
|
+
end
|
|
244
|
+
end
|
|
163
245
|
|
|
164
|
-
|
|
165
|
-
|
|
246
|
+
def add_identification_or_cardtoken_hash(hash, identification_or_cardtoken)
|
|
247
|
+
if identification_or_cardtoken.is_a?(LitleCardToken)
|
|
248
|
+
add_cardtoken_hash(hash, identification_or_cardtoken)
|
|
166
249
|
else
|
|
167
|
-
|
|
250
|
+
transaction_id, kind = split_authorization(identification_or_cardtoken)
|
|
251
|
+
hash['litleTxnId'] = transaction_id
|
|
168
252
|
end
|
|
253
|
+
end
|
|
254
|
+
|
|
255
|
+
def add_cardtoken_hash(hash, cardtoken)
|
|
256
|
+
token_info = {}
|
|
257
|
+
token_info['litleToken'] = cardtoken.token
|
|
258
|
+
token_info['expDate'] = cardtoken.exp_date if cardtoken.exp_date?
|
|
259
|
+
token_info['cardValidationNum'] = cardtoken.verification_value unless cardtoken.verification_value.blank?
|
|
260
|
+
token_info['type'] = cardtoken.type unless cardtoken.type.blank?
|
|
261
|
+
|
|
262
|
+
hash['token'] = token_info
|
|
263
|
+
hash
|
|
264
|
+
end
|
|
169
265
|
|
|
170
|
-
|
|
266
|
+
def add_creditcard_hash(hash, creditcard)
|
|
267
|
+
cc_type = CARD_TYPE[creditcard.brand]
|
|
268
|
+
exp_date_yr = creditcard.year.to_s[2..3]
|
|
269
|
+
exp_date_mo = '%02d' % creditcard.month.to_i
|
|
270
|
+
exp_date = exp_date_mo + exp_date_yr
|
|
171
271
|
|
|
172
272
|
card_info = {
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
273
|
+
'type' => cc_type,
|
|
274
|
+
'number' => creditcard.number,
|
|
275
|
+
'expDate' => exp_date,
|
|
276
|
+
'cardValidationNum' => creditcard.verification_value
|
|
177
277
|
}
|
|
178
278
|
|
|
179
|
-
hash = create_hash(money, options)
|
|
180
279
|
hash['card'] = card_info
|
|
181
280
|
hash
|
|
182
281
|
end
|
|
183
282
|
|
|
184
283
|
def create_capture_hash(money, authorization, options)
|
|
185
|
-
hash
|
|
284
|
+
hash = create_hash(money, options)
|
|
186
285
|
hash['litleTxnId'] = authorization
|
|
187
286
|
hash
|
|
188
287
|
end
|
|
189
288
|
|
|
190
|
-
def create_credit_hash(money, identification, options)
|
|
191
|
-
hash = create_hash(money, options)
|
|
192
|
-
hash['litleTxnId'] = identification
|
|
193
|
-
hash['orderSource'] = nil
|
|
194
|
-
hash['orderId'] = nil
|
|
195
|
-
hash
|
|
196
|
-
end
|
|
197
|
-
|
|
198
289
|
def create_token_hash(creditcard, options)
|
|
199
|
-
hash
|
|
290
|
+
hash = create_hash(0, options)
|
|
200
291
|
hash['accountNumber'] = creditcard.number
|
|
201
292
|
hash
|
|
202
293
|
end
|
|
203
294
|
|
|
204
295
|
def create_void_hash(identification, options)
|
|
205
|
-
hash
|
|
296
|
+
hash = create_hash(nil, options)
|
|
297
|
+
hash['litleTxnId'] = identification
|
|
298
|
+
hash
|
|
299
|
+
end
|
|
300
|
+
|
|
301
|
+
def create_auth_reversal_hash(identification, money, options)
|
|
302
|
+
hash = create_hash(money, options)
|
|
206
303
|
hash['litleTxnId'] = identification
|
|
207
304
|
hash
|
|
208
305
|
end
|
|
@@ -224,54 +321,54 @@ module ActiveMerchant #:nodoc:
|
|
|
224
321
|
|
|
225
322
|
if options[:billing_address]
|
|
226
323
|
bill_to_address = {
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
324
|
+
'name' => options[:billing_address][:name],
|
|
325
|
+
'companyName' => options[:billing_address][:company],
|
|
326
|
+
'addressLine1' => options[:billing_address][:address1],
|
|
327
|
+
'addressLine2' => options[:billing_address][:address2],
|
|
328
|
+
'city' => options[:billing_address][:city],
|
|
329
|
+
'state' => options[:billing_address][:state],
|
|
330
|
+
'zip' => options[:billing_address][:zip],
|
|
331
|
+
'country' => options[:billing_address][:country],
|
|
332
|
+
'email' => options[:email],
|
|
333
|
+
'phone' => options[:billing_address][:phone]
|
|
237
334
|
}
|
|
238
335
|
end
|
|
239
336
|
if options[:shipping_address]
|
|
240
337
|
ship_to_address = {
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
338
|
+
'name' => options[:shipping_address][:name],
|
|
339
|
+
'companyName' => options[:shipping_address][:company],
|
|
340
|
+
'addressLine1' => options[:shipping_address][:address1],
|
|
341
|
+
'addressLine2' => options[:shipping_address][:address2],
|
|
342
|
+
'city' => options[:shipping_address][:city],
|
|
343
|
+
'state' => options[:shipping_address][:state],
|
|
344
|
+
'zip' => options[:shipping_address][:zip],
|
|
345
|
+
'country' => options[:shipping_address][:country],
|
|
346
|
+
'email' => options[:email],
|
|
347
|
+
'phone' => options[:shipping_address][:phone]
|
|
251
348
|
}
|
|
252
349
|
end
|
|
253
350
|
|
|
254
351
|
hash = {
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
352
|
+
'billToAddress' => bill_to_address,
|
|
353
|
+
'shipToAddress' => ship_to_address,
|
|
354
|
+
'orderId' => (options[:order_id] || @options[:order_id]),
|
|
355
|
+
'customerId' => options[:customer],
|
|
356
|
+
'reportGroup' => (options[:merchant] || @options[:merchant]),
|
|
357
|
+
'merchantId' => (options[:merchant_id] || @options[:merchant_id]),
|
|
358
|
+
'orderSource' => (options[:order_source] || 'ecommerce'),
|
|
359
|
+
'enhancedData' => enhanced_data,
|
|
360
|
+
'fraudCheckType' => fraud_check_type,
|
|
361
|
+
'user' => (options[:user] || @options[:user]),
|
|
362
|
+
'password' => (options[:password] || @options[:password]),
|
|
363
|
+
'version' => (options[:version] || @options[:version]),
|
|
364
|
+
'url' => (options[:url] || url),
|
|
365
|
+
'proxy_addr' => (options[:proxy_addr] || @options[:proxy_addr]),
|
|
366
|
+
'proxy_port' => (options[:proxy_port] || @options[:proxy_port]),
|
|
367
|
+
'id' => (options[:id] || options[:order_id] || @options[:order_id])
|
|
271
368
|
}
|
|
272
369
|
|
|
273
|
-
if(
|
|
274
|
-
hash.merge!({'amount' => money})
|
|
370
|
+
if (!money.nil? && money.to_s.length > 0)
|
|
371
|
+
hash.merge!({ 'amount' => money })
|
|
275
372
|
end
|
|
276
373
|
hash
|
|
277
374
|
end
|
|
@@ -284,7 +381,159 @@ module ActiveMerchant #:nodoc:
|
|
|
284
381
|
|
|
285
382
|
avs_to_pass = AVS_RESPONSE_CODE[result['avsResult']] unless result['avsResult'].blank?
|
|
286
383
|
end
|
|
287
|
-
{'cvv'=>cvv_to_pass, 'avs'=>avs_to_pass}
|
|
384
|
+
{ 'cvv' => cvv_to_pass, 'avs' => avs_to_pass }
|
|
385
|
+
end
|
|
386
|
+
|
|
387
|
+
# A +LitleCardToken+ object represents a tokenized credit card, and is capable of validating the various
|
|
388
|
+
# data associated with these.
|
|
389
|
+
#
|
|
390
|
+
# == Example Usage
|
|
391
|
+
# token = LitleCardToken.new(
|
|
392
|
+
# :token => '1234567890123456',
|
|
393
|
+
# :month => '9',
|
|
394
|
+
# :year => '2010',
|
|
395
|
+
# :brand => 'visa',
|
|
396
|
+
# :verification_value => '123'
|
|
397
|
+
# )
|
|
398
|
+
#
|
|
399
|
+
# token.valid? # => true
|
|
400
|
+
# cc.exp_date # => 0910
|
|
401
|
+
#
|
|
402
|
+
class LitleCardToken
|
|
403
|
+
include Validateable
|
|
404
|
+
|
|
405
|
+
# Returns or sets the token. (required)
|
|
406
|
+
#
|
|
407
|
+
# @return [String]
|
|
408
|
+
attr_accessor :token
|
|
409
|
+
|
|
410
|
+
# Returns or sets the expiry month for the card associated with token. (optional)
|
|
411
|
+
#
|
|
412
|
+
# @return [Integer]
|
|
413
|
+
attr_accessor :month
|
|
414
|
+
|
|
415
|
+
# Returns or sets the expiry year for the card associated with token. (optional)
|
|
416
|
+
#
|
|
417
|
+
# @return [Integer]
|
|
418
|
+
attr_accessor :year
|
|
419
|
+
|
|
420
|
+
# Returns or sets the card verification value. (optional)
|
|
421
|
+
#
|
|
422
|
+
# @return [String] the verification value
|
|
423
|
+
attr_accessor :verification_value
|
|
424
|
+
|
|
425
|
+
# Returns or sets the credit card brand. (optional)
|
|
426
|
+
#
|
|
427
|
+
# Valid card types are
|
|
428
|
+
#
|
|
429
|
+
# * +'visa'+
|
|
430
|
+
# * +'master'+
|
|
431
|
+
# * +'discover'+
|
|
432
|
+
# * +'american_express'+
|
|
433
|
+
# * +'diners_club'+
|
|
434
|
+
# * +'jcb'+
|
|
435
|
+
# * +'switch'+
|
|
436
|
+
# * +'solo'+
|
|
437
|
+
# * +'dankort'+
|
|
438
|
+
# * +'maestro'+
|
|
439
|
+
# * +'forbrugsforeningen'+
|
|
440
|
+
# * +'laser'+
|
|
441
|
+
#
|
|
442
|
+
# @return (String) the credit card brand
|
|
443
|
+
attr_accessor :brand
|
|
444
|
+
|
|
445
|
+
# Returns the Litle credit card type identifier.
|
|
446
|
+
#
|
|
447
|
+
# @return (String) the credit card type identifier
|
|
448
|
+
def type
|
|
449
|
+
CARD_TYPE[brand] unless brand.blank?
|
|
450
|
+
end
|
|
451
|
+
|
|
452
|
+
# Returns true if the expiration date is set.
|
|
453
|
+
#
|
|
454
|
+
# @return (Boolean)
|
|
455
|
+
def exp_date?
|
|
456
|
+
!month.to_i.zero? && !year.to_i.zero?
|
|
457
|
+
end
|
|
458
|
+
|
|
459
|
+
# Returns the card token expiration date in MMYY format.
|
|
460
|
+
#
|
|
461
|
+
# @return (String) the expiration date in MMYY format
|
|
462
|
+
def exp_date
|
|
463
|
+
result = ''
|
|
464
|
+
if exp_date?
|
|
465
|
+
exp_date_yr = year.to_s[2..3]
|
|
466
|
+
exp_date_mo = '%02d' % month.to_i
|
|
467
|
+
|
|
468
|
+
result = exp_date_mo + exp_date_yr
|
|
469
|
+
end
|
|
470
|
+
result
|
|
471
|
+
end
|
|
472
|
+
|
|
473
|
+
# Validates the card token details.
|
|
474
|
+
#
|
|
475
|
+
# Any validation errors are added to the {#errors} attribute.
|
|
476
|
+
def validate
|
|
477
|
+
validate_card_token
|
|
478
|
+
validate_expiration_date
|
|
479
|
+
validate_card_brand
|
|
480
|
+
end
|
|
481
|
+
|
|
482
|
+
def check?
|
|
483
|
+
false
|
|
484
|
+
end
|
|
485
|
+
|
|
486
|
+
private
|
|
487
|
+
|
|
488
|
+
CARD_TYPE = {
|
|
489
|
+
'visa' => 'VI',
|
|
490
|
+
'master' => 'MC',
|
|
491
|
+
'american_express' => 'AX',
|
|
492
|
+
'discover' => 'DI',
|
|
493
|
+
'jcb' => 'DI',
|
|
494
|
+
'diners_club' => 'DI'
|
|
495
|
+
}
|
|
496
|
+
|
|
497
|
+
def before_validate #:nodoc:
|
|
498
|
+
self.month = month.to_i
|
|
499
|
+
self.year = year.to_i
|
|
500
|
+
end
|
|
501
|
+
|
|
502
|
+
# Litle XML Reference Guide 1.8.2
|
|
503
|
+
#
|
|
504
|
+
# The length of the original card number is reflected in the token, so a
|
|
505
|
+
# submitted 16-digit number results in a 16-digit token. Also, all tokens
|
|
506
|
+
# use only numeric characters, so you do not have to change your
|
|
507
|
+
# systems to accept alpha-numeric characters.
|
|
508
|
+
#
|
|
509
|
+
# The credit card token numbers themselves have two parts.
|
|
510
|
+
# The last four digits match the last four digits of the card number.
|
|
511
|
+
# The remaining digits (length can vary based upon original card number
|
|
512
|
+
# length) are a randomly generated.
|
|
513
|
+
def validate_card_token #:nodoc:
|
|
514
|
+
if token.to_s.length < 12 || token.to_s.match(/\A\d+\Z/).nil?
|
|
515
|
+
errors.add :token, "is not a valid card token"
|
|
516
|
+
end
|
|
517
|
+
end
|
|
518
|
+
|
|
519
|
+
def validate_expiration_date #:nodoc:
|
|
520
|
+
if !month.to_i.zero? || !year.to_i.zero?
|
|
521
|
+
errors.add :month, "is not a valid month" unless valid_month?(month)
|
|
522
|
+
errors.add :year, "is not a valid year" unless valid_expiry_year?(year)
|
|
523
|
+
end
|
|
524
|
+
end
|
|
525
|
+
|
|
526
|
+
def validate_card_brand #:nodoc:
|
|
527
|
+
errors.add :brand, "is invalid" unless brand.blank? || CreditCard.card_companies.keys.include?(brand)
|
|
528
|
+
end
|
|
529
|
+
|
|
530
|
+
def valid_month?(month)
|
|
531
|
+
(1..12).include?(month.to_i)
|
|
532
|
+
end
|
|
533
|
+
|
|
534
|
+
def valid_expiry_year?(year)
|
|
535
|
+
year.to_s =~ /\A\d{4}\Z/ && year.to_i > 1987
|
|
536
|
+
end
|
|
288
537
|
end
|
|
289
538
|
end
|
|
290
539
|
end
|
|
@@ -23,6 +23,8 @@ module ActiveMerchant #:nodoc:
|
|
|
23
23
|
|
|
24
24
|
def authorize(money, creditcard_or_card_id, options = {})
|
|
25
25
|
post = {}
|
|
26
|
+
post[:client_reference_number] = options[:customer] if options.has_key?(:customer)
|
|
27
|
+
post[:moto_ecommerce_ind] = options[:moto_ecommerce_ind] if options.has_key?(:moto_ecommerce_ind)
|
|
26
28
|
add_invoice(post, options)
|
|
27
29
|
add_payment_source(post, creditcard_or_card_id, options)
|
|
28
30
|
add_address(post, options)
|
|
@@ -31,6 +33,8 @@ module ActiveMerchant #:nodoc:
|
|
|
31
33
|
|
|
32
34
|
def purchase(money, creditcard_or_card_id, options = {})
|
|
33
35
|
post = {}
|
|
36
|
+
post[:client_reference_number] = options[:customer] if options.has_key?(:customer)
|
|
37
|
+
post[:moto_ecommerce_ind] = options[:moto_ecommerce_ind] if options.has_key?(:moto_ecommerce_ind)
|
|
34
38
|
add_invoice(post, options)
|
|
35
39
|
add_payment_source(post, creditcard_or_card_id, options)
|
|
36
40
|
add_address(post, options)
|
|
@@ -40,33 +44,48 @@ module ActiveMerchant #:nodoc:
|
|
|
40
44
|
def capture(money, transaction_id, options = {})
|
|
41
45
|
post ={}
|
|
42
46
|
post[:transaction_id] = transaction_id
|
|
47
|
+
post[:client_reference_number] = options[:customer] if options.has_key?(:customer)
|
|
43
48
|
commit('S', money, post)
|
|
44
49
|
end
|
|
45
50
|
|
|
46
51
|
def store(creditcard, options = {})
|
|
47
52
|
post = {}
|
|
53
|
+
post[:client_reference_number] = options[:customer] if options.has_key?(:customer)
|
|
48
54
|
add_creditcard(post, creditcard, options)
|
|
49
55
|
commit('T', nil, post)
|
|
50
56
|
end
|
|
51
57
|
|
|
52
58
|
def unstore(card_id)
|
|
53
59
|
post = {}
|
|
60
|
+
post[:client_reference_number] = options[:customer] if options.has_key?(:customer)
|
|
54
61
|
post[:card_id] = card_id
|
|
55
62
|
commit('X', nil, post)
|
|
56
63
|
end
|
|
57
64
|
|
|
58
65
|
def refund(money, identification, options = {})
|
|
59
|
-
|
|
66
|
+
post = {}
|
|
67
|
+
post[:transaction_id] = identification
|
|
68
|
+
post[:client_reference_number] = options[:customer] if options.has_key?(:customer)
|
|
69
|
+
options.delete(:customer)
|
|
70
|
+
options.delete(:billing_address)
|
|
71
|
+
commit('U', money, options.merge(post))
|
|
60
72
|
end
|
|
61
73
|
|
|
62
74
|
def credit(money, creditcard_or_card_id, options = {})
|
|
63
75
|
post = {}
|
|
76
|
+
post[:client_reference_number] = options[:customer] if options.has_key?(:customer)
|
|
77
|
+
add_invoice(post, options)
|
|
64
78
|
add_payment_source(post, creditcard_or_card_id, options)
|
|
65
79
|
commit('C', money, post)
|
|
66
80
|
end
|
|
67
81
|
|
|
68
82
|
def void(transaction_id, options = {})
|
|
69
|
-
|
|
83
|
+
post = {}
|
|
84
|
+
post[:transaction_id] = transaction_id
|
|
85
|
+
post[:client_reference_number] = options[:customer] if options.has_key?(:customer)
|
|
86
|
+
options.delete(:customer)
|
|
87
|
+
options.delete(:billing_address)
|
|
88
|
+
commit('V', nil, options.merge(post))
|
|
70
89
|
end
|
|
71
90
|
|
|
72
91
|
private
|
|
@@ -111,11 +130,15 @@ module ActiveMerchant #:nodoc:
|
|
|
111
130
|
end
|
|
112
131
|
|
|
113
132
|
def commit(action, money, parameters)
|
|
114
|
-
|
|
115
133
|
url = test? ? self.test_url : self.live_url
|
|
116
134
|
parameters[:transaction_amount] = amount(money) if money unless action == 'V'
|
|
117
135
|
|
|
118
|
-
|
|
136
|
+
|
|
137
|
+
response = begin
|
|
138
|
+
parse( ssl_post(url, post_data(action,parameters)) )
|
|
139
|
+
rescue ActiveMerchant::ResponseError => e
|
|
140
|
+
{ "error_code" => "404", "auth_response_text" => e.to_s }
|
|
141
|
+
end
|
|
119
142
|
|
|
120
143
|
Response.new(response["error_code"] == "000", message_from(response), response,
|
|
121
144
|
:authorization => response["transaction_id"],
|
|
@@ -123,7 +146,6 @@ module ActiveMerchant #:nodoc:
|
|
|
123
146
|
:cvv_result => response["cvv2_result"],
|
|
124
147
|
:avs_result => { :code => response["avs_result"] }
|
|
125
148
|
)
|
|
126
|
-
|
|
127
149
|
end
|
|
128
150
|
|
|
129
151
|
def expdate(creditcard)
|
|
@@ -152,4 +174,3 @@ module ActiveMerchant #:nodoc:
|
|
|
152
174
|
end
|
|
153
175
|
end
|
|
154
176
|
end
|
|
155
|
-
|