activemerchant 1.42.7 → 1.42.8
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 +5 -13
- checksums.yaml.gz.sig +0 -0
- data.tar.gz.sig +2 -3
- data/CHANGELOG +10 -0
- data/lib/active_merchant/billing/gateways/cecabank.rb +6 -6
- data/lib/active_merchant/billing/gateways/iridium.rb +173 -0
- data/lib/active_merchant/billing/gateways/litle.rb +196 -456
- data/lib/active_merchant/billing/gateways/paypal_express_common.rb +1 -1
- data/lib/active_merchant/billing/gateways/wirecard.rb +7 -2
- data/lib/active_merchant/billing/integrations/action_view_helper.rb +1 -1
- data/lib/active_merchant/billing/integrations/citrus.rb +0 -23
- data/lib/active_merchant/billing/integrations/citrus/helper.rb +17 -0
- data/lib/active_merchant/billing/integrations/helper.rb +27 -21
- data/lib/active_merchant/billing/integrations/mollie_ideal.rb +98 -0
- data/lib/active_merchant/billing/integrations/mollie_ideal/helper.rb +67 -0
- data/lib/active_merchant/billing/integrations/mollie_ideal/notification.rb +69 -0
- data/lib/active_merchant/billing/integrations/mollie_ideal/return.rb +10 -0
- data/lib/active_merchant/billing/integrations/universal.rb +23 -0
- data/lib/active_merchant/billing/integrations/universal/helper.rb +76 -0
- data/lib/active_merchant/billing/integrations/universal/notification.rb +52 -0
- data/lib/active_merchant/billing/integrations/universal/return.rb +18 -0
- data/lib/active_merchant/version.rb +1 -1
- metadata +120 -120
- metadata.gz.sig +0 -0
checksums.yaml
CHANGED
|
@@ -1,15 +1,7 @@
|
|
|
1
1
|
---
|
|
2
|
-
|
|
3
|
-
metadata.gz:
|
|
4
|
-
|
|
5
|
-
data.tar.gz: !binary |-
|
|
6
|
-
ZTFjN2I2ZjQ3ZTdkZTIwZWY0ZGY0OTFhNzhjOTkwYWIxNDFlYTI3OA==
|
|
2
|
+
SHA1:
|
|
3
|
+
metadata.gz: 81edb8d2513f065dd9170ead1d0d6f72d4fc39c8
|
|
4
|
+
data.tar.gz: b14933f6c29ebd5ed555e12238a29828a959687a
|
|
7
5
|
SHA512:
|
|
8
|
-
metadata.gz:
|
|
9
|
-
|
|
10
|
-
Y2I3ZDVhYjkzZDA4NTAyYjk0ZDU3ZjZkODAyMmEzOWVjMjg1OTJlNmRiYzg4
|
|
11
|
-
YTQ5YTc4ZGRjMmVmZGU5N2ZlMWI0MjdiNmRjZjUyZmVlN2NhMzU=
|
|
12
|
-
data.tar.gz: !binary |-
|
|
13
|
-
YTY3ZGViYTg2MTIxOTFhZmFhMzE5Y2JiZmYxNzZlMzMzMDJhNDYwNTA1OTE0
|
|
14
|
-
ZDEzNWQ1OGYyZjJkOTM5ODE0OGViNGFiNmFmNjg3NDczMmQyOTI1OWYyMDZi
|
|
15
|
-
ZTZjYzVkZWM5ZTFhNzhkOGU4MTc3YWY1NGI3OWMyM2Q0OGIzYTA=
|
|
6
|
+
metadata.gz: 9350271f4a9016fd5c8d0113def4e0ec6a654578d63d824b07647a59128110f6b9bd2a33c3205ad2c89debe1b013b555d08cbd51e68b2333a24a0f98a7a20326
|
|
7
|
+
data.tar.gz: 3ce7cf004ee44048d02e6805dd2b63808c104a6cad0d42980246707fb8d50a302d4798c63ced00a2ff7526bedf93e84dfd88ebf2adac2326f10a5a51666bc32c
|
checksums.yaml.gz.sig
CHANGED
|
Binary file
|
data.tar.gz.sig
CHANGED
|
@@ -1,3 +1,2 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
,�!8TD)�(�J3��"��;�"i�l���5�B�
|
|
1
|
+
e��k�M����6Q�)Q ��*ki-1P������{��2\v2����68B��kU�?i����]CE1m����\�3�Jh�`�T�4���U���n�œM������B�S����u�zL�u������e2Q�b"ͯu��7<��S���^A-��j�n+/}n/U.R �'>>lޡvy��o�>���?i#]Q�\$z
|
|
2
|
+
��c���"P����q�x�i�[(�Wa�u�[��t)J�(�Tx���;
|
data/CHANGELOG
CHANGED
|
@@ -1,5 +1,15 @@
|
|
|
1
1
|
= ActiveMerchant CHANGELOG
|
|
2
2
|
|
|
3
|
+
== Version 1.42.8 (April 4, 2014)
|
|
4
|
+
|
|
5
|
+
* Cecabank: Handle invalid xml response body [duff]
|
|
6
|
+
* Wirecard: Capture error code in the response [duff]
|
|
7
|
+
* Litle: Remove gem dependency [duff]
|
|
8
|
+
* Litle: Fix case of missing address parts [duff]
|
|
9
|
+
* Universal: Add universal offsite API implementation [bslobodin]
|
|
10
|
+
* Iridium: Add more currencies [bslobodin]
|
|
11
|
+
* iDeal: Add Mollie iDeal offsite implementation [wvanbergen, maartenvg]
|
|
12
|
+
|
|
3
13
|
== Version 1.42.7 (March 18, 2014)
|
|
4
14
|
|
|
5
15
|
* SagePay: Add support for ReferrerID [markabe]
|
|
@@ -113,30 +113,24 @@ module ActiveMerchant #:nodoc:
|
|
|
113
113
|
root = REXML::Document.new(body).root
|
|
114
114
|
|
|
115
115
|
response[:success] = (root.attributes['valor'] == "OK")
|
|
116
|
-
|
|
117
|
-
#common params to all responses
|
|
118
116
|
response[:date] = root.attributes['fecha']
|
|
119
117
|
response[:operation_number] = root.attributes['numeroOperacion']
|
|
120
118
|
response[:message] = root.attributes['valor']
|
|
121
119
|
|
|
122
|
-
#success
|
|
123
120
|
if root.elements['OPERACION']
|
|
124
121
|
response[:operation_type] = root.elements['OPERACION'].attributes['tipo']
|
|
125
122
|
response[:amount] = root.elements['OPERACION/importe'].text.strip
|
|
126
123
|
end
|
|
127
124
|
|
|
128
|
-
#optional params
|
|
129
125
|
response[:description] = root.elements['OPERACION/descripcion'].text if root.elements['OPERACION/descripcion']
|
|
130
126
|
response[:authorization_number] = root.elements['OPERACION/numeroAutorizacion'].text if root.elements['OPERACION/numeroAutorizacion']
|
|
131
127
|
response[:reference] = root.elements['OPERACION/referencia'].text if root.elements['OPERACION/referencia']
|
|
132
128
|
response[:pan] = root.elements['OPERACION/pan'].text if root.elements['OPERACION/pan']
|
|
133
129
|
|
|
134
130
|
if root.elements['ERROR']
|
|
135
|
-
#error
|
|
136
131
|
response[:error_code] = root.elements['ERROR/codigo'].text
|
|
137
132
|
response[:error_message] = root.elements['ERROR/descripcion'].text
|
|
138
133
|
else
|
|
139
|
-
#authorization
|
|
140
134
|
if("000" == root.elements['OPERACION'].attributes['numeroOperacion'])
|
|
141
135
|
if(root.elements['OPERACION/numeroAutorizacion'])
|
|
142
136
|
response[:authorization] = root.elements['OPERACION/numeroAutorizacion'].text
|
|
@@ -146,6 +140,12 @@ module ActiveMerchant #:nodoc:
|
|
|
146
140
|
end
|
|
147
141
|
end
|
|
148
142
|
|
|
143
|
+
return response
|
|
144
|
+
|
|
145
|
+
rescue REXML::ParseException => e
|
|
146
|
+
response[:success] = false
|
|
147
|
+
response[:message] = "Unable to parse the response."
|
|
148
|
+
response[:error_message] = e.message
|
|
149
149
|
response
|
|
150
150
|
end
|
|
151
151
|
|
|
@@ -24,13 +24,186 @@ module ActiveMerchant #:nodoc:
|
|
|
24
24
|
self.display_name = 'Iridium'
|
|
25
25
|
|
|
26
26
|
CURRENCY_CODES = {
|
|
27
|
+
"AED" => '784',
|
|
28
|
+
"AFN" => '971',
|
|
29
|
+
"ALL" => '008',
|
|
30
|
+
"AMD" => '051',
|
|
31
|
+
"ANG" => '532',
|
|
32
|
+
"AOA" => '973',
|
|
33
|
+
"ARS" => '032',
|
|
27
34
|
"AUD" => '036',
|
|
35
|
+
"AWG" => '533',
|
|
36
|
+
"AZN" => '944',
|
|
37
|
+
"BAM" => '977',
|
|
38
|
+
"BBD" => '052',
|
|
39
|
+
"BDT" => '050',
|
|
40
|
+
"BGN" => '975',
|
|
41
|
+
"BHD" => '048',
|
|
42
|
+
"BIF" => '108',
|
|
43
|
+
"BMD" => '060',
|
|
44
|
+
"BND" => '096',
|
|
45
|
+
"BOB" => '068',
|
|
46
|
+
"BOV" => '984',
|
|
47
|
+
"BRL" => '986',
|
|
48
|
+
"BSD" => '044',
|
|
49
|
+
"BTN" => '064',
|
|
50
|
+
"BWP" => '072',
|
|
51
|
+
"BYR" => '974',
|
|
52
|
+
"BZD" => '084',
|
|
28
53
|
"CAD" => '124',
|
|
54
|
+
"CDF" => '976',
|
|
55
|
+
"CHE" => '947',
|
|
56
|
+
"CHF" => '756',
|
|
57
|
+
"CHW" => '948',
|
|
58
|
+
"CLF" => '990',
|
|
59
|
+
"CLP" => '152',
|
|
60
|
+
"CNY" => '156',
|
|
61
|
+
"COP" => '170',
|
|
62
|
+
"COU" => '970',
|
|
63
|
+
"CRC" => '188',
|
|
64
|
+
"CUP" => '192',
|
|
65
|
+
"CVE" => '132',
|
|
66
|
+
"CYP" => '196',
|
|
67
|
+
"CZK" => '203',
|
|
68
|
+
"DJF" => '262',
|
|
69
|
+
"DKK" => '208',
|
|
70
|
+
"DOP" => '214',
|
|
71
|
+
"DZD" => '012',
|
|
72
|
+
"EEK" => '233',
|
|
73
|
+
"EGP" => '818',
|
|
74
|
+
"ERN" => '232',
|
|
75
|
+
"ETB" => '230',
|
|
29
76
|
"EUR" => '978',
|
|
77
|
+
"FJD" => '242',
|
|
78
|
+
"FKP" => '238',
|
|
30
79
|
"GBP" => '826',
|
|
80
|
+
"GEL" => '981',
|
|
81
|
+
"GHS" => '288',
|
|
82
|
+
"GIP" => '292',
|
|
83
|
+
"GMD" => '270',
|
|
84
|
+
"GNF" => '324',
|
|
85
|
+
"GTQ" => '320',
|
|
86
|
+
"GYD" => '328',
|
|
87
|
+
"HKD" => '344',
|
|
88
|
+
"HNL" => '340',
|
|
89
|
+
"HRK" => '191',
|
|
90
|
+
"HTG" => '332',
|
|
91
|
+
"HUF" => '348',
|
|
92
|
+
"IDR" => '360',
|
|
93
|
+
"ILS" => '376',
|
|
94
|
+
"INR" => '356',
|
|
95
|
+
"IQD" => '368',
|
|
96
|
+
"IRR" => '364',
|
|
97
|
+
"ISK" => '352',
|
|
98
|
+
"JMD" => '388',
|
|
99
|
+
"JOD" => '400',
|
|
100
|
+
"JPY" => '392',
|
|
101
|
+
"KES" => '404',
|
|
102
|
+
"KGS" => '417',
|
|
103
|
+
"KHR" => '116',
|
|
104
|
+
"KMF" => '174',
|
|
105
|
+
"KPW" => '408',
|
|
106
|
+
"KRW" => '410',
|
|
107
|
+
"KWD" => '414',
|
|
108
|
+
"KYD" => '136',
|
|
109
|
+
"KZT" => '398',
|
|
110
|
+
"LAK" => '418',
|
|
111
|
+
"LBP" => '422',
|
|
112
|
+
"LKR" => '144',
|
|
113
|
+
"LRD" => '430',
|
|
114
|
+
"LSL" => '426',
|
|
115
|
+
"LTL" => '440',
|
|
116
|
+
"LVL" => '428',
|
|
117
|
+
"LYD" => '434',
|
|
118
|
+
"MAD" => '504',
|
|
119
|
+
"MDL" => '498',
|
|
120
|
+
"MGA" => '969',
|
|
121
|
+
"MKD" => '807',
|
|
122
|
+
"MMK" => '104',
|
|
123
|
+
"MNT" => '496',
|
|
124
|
+
"MOP" => '446',
|
|
125
|
+
"MRO" => '478',
|
|
126
|
+
"MTL" => '470',
|
|
127
|
+
"MUR" => '480',
|
|
128
|
+
"MVR" => '462',
|
|
129
|
+
"MWK" => '454',
|
|
31
130
|
"MXN" => '484',
|
|
131
|
+
"MXV" => '979',
|
|
132
|
+
"MYR" => '458',
|
|
133
|
+
"MZN" => '943',
|
|
134
|
+
"NAD" => '516',
|
|
135
|
+
"NGN" => '566',
|
|
136
|
+
"NIO" => '558',
|
|
137
|
+
"NOK" => '578',
|
|
138
|
+
"NPR" => '524',
|
|
32
139
|
"NZD" => '554',
|
|
140
|
+
"OMR" => '512',
|
|
141
|
+
"PAB" => '590',
|
|
142
|
+
"PEN" => '604',
|
|
143
|
+
"PGK" => '598',
|
|
144
|
+
"PHP" => '608',
|
|
145
|
+
"PKR" => '586',
|
|
146
|
+
"PLN" => '985',
|
|
147
|
+
"PYG" => '600',
|
|
148
|
+
"QAR" => '634',
|
|
149
|
+
"ROL" => '642',
|
|
150
|
+
"RON" => '946',
|
|
151
|
+
"RSD" => '941',
|
|
152
|
+
"RUB" => '643',
|
|
153
|
+
"RWF" => '646',
|
|
154
|
+
"SAR" => '682',
|
|
155
|
+
"SBD" => '090',
|
|
156
|
+
"SCR" => '690',
|
|
157
|
+
"SDG" => '938',
|
|
158
|
+
"SEK" => '752',
|
|
159
|
+
"SGD" => '702',
|
|
160
|
+
"SHP" => '654',
|
|
161
|
+
"SKK" => '703',
|
|
162
|
+
"SLL" => '694',
|
|
163
|
+
"SOS" => '706',
|
|
164
|
+
"SRD" => '968',
|
|
165
|
+
"STD" => '678',
|
|
166
|
+
"SYP" => '760',
|
|
167
|
+
"SZL" => '748',
|
|
168
|
+
"THB" => '764',
|
|
169
|
+
"TJS" => '972',
|
|
170
|
+
"TMM" => '795',
|
|
171
|
+
"TND" => '788',
|
|
172
|
+
"TOP" => '776',
|
|
173
|
+
"TRY" => '949',
|
|
174
|
+
"TTD" => '780',
|
|
175
|
+
"TWD" => '901',
|
|
176
|
+
"TZS" => '834',
|
|
177
|
+
"UAH" => '980',
|
|
178
|
+
"UGX" => '800',
|
|
33
179
|
"USD" => '840',
|
|
180
|
+
"USN" => '997',
|
|
181
|
+
"USS" => '998',
|
|
182
|
+
"UYU" => '858',
|
|
183
|
+
"UZS" => '860',
|
|
184
|
+
"VEB" => '862',
|
|
185
|
+
"VND" => '704',
|
|
186
|
+
"VUV" => '548',
|
|
187
|
+
"WST" => '882',
|
|
188
|
+
"XAF" => '950',
|
|
189
|
+
"XAG" => '961',
|
|
190
|
+
"XAU" => '959',
|
|
191
|
+
"XBA" => '955',
|
|
192
|
+
"XBB" => '956',
|
|
193
|
+
"XBC" => '957',
|
|
194
|
+
"XBD" => '958',
|
|
195
|
+
"XCD" => '951',
|
|
196
|
+
"XDR" => '960',
|
|
197
|
+
"XOF" => '952',
|
|
198
|
+
"XPD" => '964',
|
|
199
|
+
"XPF" => '953',
|
|
200
|
+
"XPT" => '962',
|
|
201
|
+
"XTS" => '963',
|
|
202
|
+
"XXX" => '999',
|
|
203
|
+
"YER" => '886',
|
|
204
|
+
"ZAR" => '710',
|
|
205
|
+
"ZMK" => '894',
|
|
206
|
+
"ZWD" => '716',
|
|
34
207
|
}
|
|
35
208
|
|
|
36
209
|
def initialize(options = {})
|
|
@@ -1,141 +1,119 @@
|
|
|
1
|
+
require 'nokogiri'
|
|
2
|
+
|
|
1
3
|
module ActiveMerchant #:nodoc:
|
|
2
4
|
module Billing #:nodoc:
|
|
3
5
|
class LitleGateway < Gateway
|
|
4
|
-
|
|
5
|
-
# * <tt>:merchant_id</tt> - Merchant Id assigned by Litle
|
|
6
|
-
# * <tt>:user</tt> - Username assigned by Litle
|
|
7
|
-
# * <tt>:password</tt> - Password assigned by Litle
|
|
8
|
-
# * <tt>:version</tt> - The version of the api you are using (eg, '8.10')
|
|
9
|
-
# * <tt>:proxy_addr</tt> - Proxy address - nil if not needed
|
|
10
|
-
# * <tt>:proxy_port</tt> - Proxy port - nil if not needed
|
|
11
|
-
# * <tt>:url</tt> - URL assigned by Litle (for testing, use the sandbox)
|
|
12
|
-
#
|
|
13
|
-
# Standard Active Merchant options
|
|
14
|
-
# * <tt>:order_id</tt> - The order number
|
|
15
|
-
# * <tt>:ip</tt> - The IP address of the customer making the purchase
|
|
16
|
-
# * <tt>:customer</tt> - The name, customer number, or other information that identifies the customer
|
|
17
|
-
# * <tt>:invoice</tt> - The invoice number
|
|
18
|
-
# * <tt>:merchant</tt> - The name or description of the merchant offering the product
|
|
19
|
-
# * <tt>:description</tt> - A description of the transaction
|
|
20
|
-
# * <tt>:email</tt> - The email address of the customer
|
|
21
|
-
# * <tt>:currency</tt> - The currency of the transaction. Only important when you are using a currency that is not the default with a gateway that supports multiple currencies.
|
|
22
|
-
# * <tt>:billing_address</tt> - A hash containing the billing address of the customer.
|
|
23
|
-
# * <tt>:shipping_address</tt> - A hash containing the shipping address of the customer.
|
|
24
|
-
#
|
|
25
|
-
# The <tt>:billing_address</tt>, and <tt>:shipping_address</tt> hashes can have the following keys:
|
|
26
|
-
#
|
|
27
|
-
# * <tt>:name</tt> - The full name of the customer.
|
|
28
|
-
# * <tt>:company</tt> - The company name of the customer.
|
|
29
|
-
# * <tt>:address1</tt> - The primary street address of the customer.
|
|
30
|
-
# * <tt>:address2</tt> - Additional line of address information.
|
|
31
|
-
# * <tt>:city</tt> - The city of the customer.
|
|
32
|
-
# * <tt>:state</tt> - The state of the customer. The 2 digit code for US and Canadian addresses. The full name of the state or province for foreign addresses.
|
|
33
|
-
# * <tt>:country</tt> - The [ISO 3166-1-alpha-2 code](http://www.iso.org/iso/country_codes/iso_3166_code_lists/english_country_names_and_code_elements.htm) for the customer.
|
|
34
|
-
# * <tt>:zip</tt> - The zip or postal code of the customer.
|
|
35
|
-
# * <tt>:phone</tt> - The phone number of the customer.
|
|
6
|
+
SCHEMA_VERSION = '8.18'
|
|
36
7
|
|
|
37
8
|
self.test_url = 'https://www.testlitle.com/sandbox/communicator/online'
|
|
38
9
|
self.live_url = 'https://payments.litle.com/vap/communicator/online'
|
|
39
10
|
|
|
40
|
-
LITLE_SCHEMA_VERSION = '8.13'
|
|
41
|
-
|
|
42
|
-
# The countries the gateway supports merchants from as 2 digit ISO country codes
|
|
43
11
|
self.supported_countries = ['US']
|
|
44
|
-
|
|
45
|
-
# The card types supported by the payment gateway
|
|
12
|
+
self.default_currency = 'USD'
|
|
46
13
|
self.supported_cardtypes = [:visa, :master, :american_express, :discover, :diners_club, :jcb]
|
|
47
14
|
|
|
48
|
-
|
|
49
|
-
self.
|
|
50
|
-
|
|
51
|
-
# The name of the gateway
|
|
52
|
-
self.display_name = 'Litle & Co.'
|
|
15
|
+
self.homepage_url = 'http://www.litle.com/'
|
|
16
|
+
self.display_name = 'Litle & Co.'
|
|
53
17
|
|
|
54
|
-
|
|
18
|
+
# Public: Create a new Litle gateway.
|
|
19
|
+
#
|
|
20
|
+
# options - A hash of options:
|
|
21
|
+
# :login - The user.
|
|
22
|
+
# :password - The password.
|
|
23
|
+
# :merchant_id - The merchant id.
|
|
24
|
+
def initialize(options={})
|
|
25
|
+
requires!(options, :login, :password, :merchant_id)
|
|
26
|
+
super
|
|
27
|
+
end
|
|
55
28
|
|
|
56
|
-
def
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
29
|
+
def purchase(money, payment_method, options={})
|
|
30
|
+
request = build_xml_request do |doc|
|
|
31
|
+
add_authentication(doc)
|
|
32
|
+
doc.sale(transaction_attributes(options)) do
|
|
33
|
+
add_auth_purchase_params(doc, money, payment_method, options)
|
|
34
|
+
end
|
|
61
35
|
end
|
|
62
36
|
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
37
|
+
commit(:sale, request)
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
def authorize(money, payment_method, options={})
|
|
41
|
+
request = build_xml_request do |doc|
|
|
42
|
+
add_authentication(doc)
|
|
43
|
+
doc.authorization(transaction_attributes(options)) do
|
|
44
|
+
add_auth_purchase_params(doc, money, payment_method, options)
|
|
45
|
+
end
|
|
69
46
|
end
|
|
70
47
|
|
|
71
|
-
|
|
48
|
+
commit(:authorization, request)
|
|
49
|
+
end
|
|
72
50
|
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
options[:user] ||= options[:login]
|
|
51
|
+
def capture(money, authorization, options={})
|
|
52
|
+
transaction_id, kind = split_authorization(authorization)
|
|
76
53
|
|
|
77
|
-
|
|
54
|
+
request = build_xml_request do |doc|
|
|
55
|
+
add_authentication(doc)
|
|
56
|
+
doc.capture_(transaction_attributes(options)) do
|
|
57
|
+
doc.litleTxnId(transaction_id)
|
|
58
|
+
doc.amount(money) if money
|
|
59
|
+
end
|
|
60
|
+
end
|
|
78
61
|
|
|
79
|
-
|
|
62
|
+
commit(:capture, request)
|
|
80
63
|
end
|
|
81
64
|
|
|
82
|
-
def
|
|
83
|
-
|
|
84
|
-
|
|
65
|
+
def credit(money, authorization, options = {})
|
|
66
|
+
deprecated CREDIT_DEPRECATION_MESSAGE
|
|
67
|
+
refund(money, authorization, options)
|
|
85
68
|
end
|
|
86
69
|
|
|
87
|
-
def
|
|
88
|
-
|
|
89
|
-
|
|
70
|
+
def refund(money, authorization, options={})
|
|
71
|
+
transaction_id, kind = split_authorization(authorization)
|
|
72
|
+
|
|
73
|
+
request = build_xml_request do |doc|
|
|
74
|
+
add_authentication(doc)
|
|
75
|
+
doc.credit(transaction_attributes(options)) do
|
|
76
|
+
doc.litleTxnId(transaction_id)
|
|
77
|
+
doc.amount(money) if money
|
|
78
|
+
end
|
|
79
|
+
end
|
|
80
|
+
|
|
81
|
+
commit(:credit, request)
|
|
90
82
|
end
|
|
91
83
|
|
|
92
|
-
def
|
|
84
|
+
def void(authorization, options={})
|
|
93
85
|
transaction_id, kind = split_authorization(authorization)
|
|
94
|
-
to_pass = create_capture_hash(money, transaction_id, options)
|
|
95
|
-
build_response(:capture, @litle.capture(to_pass))
|
|
96
|
-
end
|
|
97
86
|
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
# A partial auth_reversal can be accomplished by passing :amount as an option
|
|
104
|
-
def void(identification, options = {})
|
|
105
|
-
transaction_id, kind = split_authorization(identification)
|
|
106
|
-
if(kind == 'authorization')
|
|
107
|
-
to_pass = create_auth_reversal_hash(transaction_id, options[:amount], options)
|
|
108
|
-
build_response(:authReversal, @litle.auth_reversal(to_pass))
|
|
109
|
-
else
|
|
110
|
-
to_pass = create_void_hash(transaction_id, options)
|
|
111
|
-
build_response(:void, @litle.void(to_pass))
|
|
87
|
+
request = build_xml_request do |doc|
|
|
88
|
+
add_authentication(doc)
|
|
89
|
+
doc.send(void_type(kind), transaction_attributes(options)) do
|
|
90
|
+
doc.litleTxnId(transaction_id)
|
|
91
|
+
end
|
|
112
92
|
end
|
|
113
|
-
end
|
|
114
93
|
|
|
115
|
-
|
|
116
|
-
to_pass = build_credit_request(money, authorization, options)
|
|
117
|
-
build_response(:credit, @litle.credit(to_pass))
|
|
94
|
+
commit(void_type(kind), request)
|
|
118
95
|
end
|
|
119
96
|
|
|
120
|
-
def
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
97
|
+
def store(creditcard, options = {})
|
|
98
|
+
request = build_xml_request do |doc|
|
|
99
|
+
add_authentication(doc)
|
|
100
|
+
doc.registerTokenRequest(transaction_attributes(options)) do
|
|
101
|
+
doc.orderId(truncated(options[:order_id]))
|
|
102
|
+
doc.accountNumber(creditcard.number)
|
|
103
|
+
end
|
|
104
|
+
end
|
|
124
105
|
|
|
125
|
-
|
|
126
|
-
to_pass = create_token_hash(creditcard_or_paypage_registration_id, options)
|
|
127
|
-
build_response(:registerToken, @litle.register_token_request(to_pass), %w(000 801 802))
|
|
106
|
+
commit(:registerToken, request)
|
|
128
107
|
end
|
|
129
108
|
|
|
130
109
|
private
|
|
131
|
-
|
|
132
110
|
CARD_TYPE = {
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
111
|
+
'visa' => 'VI',
|
|
112
|
+
'master' => 'MC',
|
|
113
|
+
'american_express' => 'AX',
|
|
114
|
+
'discover' => 'DI',
|
|
115
|
+
'jcb' => 'JC',
|
|
116
|
+
'diners_club' => 'DC'
|
|
139
117
|
}
|
|
140
118
|
|
|
141
119
|
AVS_RESPONSE_CODE = {
|
|
@@ -156,410 +134,172 @@ module ActiveMerchant #:nodoc:
|
|
|
156
134
|
'40' => 'E'
|
|
157
135
|
}
|
|
158
136
|
|
|
159
|
-
def
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
test? ? self.test_url : self.live_url
|
|
163
|
-
end
|
|
164
|
-
|
|
165
|
-
def build_response(kind, litle_response, valid_responses=%w(000))
|
|
166
|
-
response = Hash.from_xml(litle_response.raw_xml.to_s)['litleOnlineResponse']
|
|
167
|
-
|
|
168
|
-
if response['response'] == "0"
|
|
169
|
-
detail = response["#{kind}Response"]
|
|
170
|
-
fraud = fraud_result(detail)
|
|
171
|
-
Response.new(
|
|
172
|
-
valid_responses.include?(detail['response']),
|
|
173
|
-
detail['message'],
|
|
174
|
-
{ litleOnlineResponse: response, response_code: detail['response'] },
|
|
175
|
-
authorization: authorization_from(detail, kind),
|
|
176
|
-
avs_result: { :code => fraud['avs'] },
|
|
177
|
-
cvv_result: fraud['cvv'],
|
|
178
|
-
test: test?
|
|
179
|
-
)
|
|
180
|
-
else
|
|
181
|
-
Response.new(false, response['message'], :litleOnlineResponse => response, :test => test?)
|
|
182
|
-
end
|
|
137
|
+
def void_type(kind)
|
|
138
|
+
(kind == 'authorization') ? :authReversal : :void
|
|
183
139
|
end
|
|
184
140
|
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
when :registerToken
|
|
190
|
-
authorization = litle_response['litleToken']
|
|
191
|
-
else
|
|
192
|
-
authorization = [litle_response['litleTxnId'], kind.to_s].join(";")
|
|
141
|
+
def add_authentication(doc)
|
|
142
|
+
doc.authentication do
|
|
143
|
+
doc.user(@options[:login])
|
|
144
|
+
doc.password(@options[:password])
|
|
193
145
|
end
|
|
194
146
|
end
|
|
195
147
|
|
|
196
|
-
def
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
hash = create_hash(money, options)
|
|
205
|
-
|
|
206
|
-
add_creditcard_or_cardtoken_hash(hash, payment_method)
|
|
207
|
-
|
|
208
|
-
hash
|
|
148
|
+
def add_auth_purchase_params(doc, money, payment_method, options)
|
|
149
|
+
doc.orderId(truncated(options[:order_id]))
|
|
150
|
+
doc.amount(money)
|
|
151
|
+
doc.orderSource('ecommerce')
|
|
152
|
+
add_billing_address(doc, payment_method, options)
|
|
153
|
+
add_shipping_address(doc, payment_method, options)
|
|
154
|
+
add_payment_method(doc, payment_method)
|
|
209
155
|
end
|
|
210
156
|
|
|
211
|
-
def
|
|
212
|
-
payment_method
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
157
|
+
def add_payment_method(doc, payment_method)
|
|
158
|
+
if payment_method.is_a?(String)
|
|
159
|
+
doc.token do
|
|
160
|
+
doc.litleToken(payment_method)
|
|
161
|
+
end
|
|
162
|
+
else
|
|
163
|
+
doc.card do
|
|
164
|
+
doc.type_(CARD_TYPE[payment_method.brand])
|
|
165
|
+
doc.number(payment_method.number)
|
|
166
|
+
doc.expDate(exp_date(payment_method))
|
|
167
|
+
doc.cardValidationNum(payment_method.verification_value)
|
|
168
|
+
end
|
|
169
|
+
end
|
|
219
170
|
end
|
|
220
171
|
|
|
221
|
-
def
|
|
222
|
-
|
|
172
|
+
def add_billing_address(doc, payment_method, options)
|
|
173
|
+
return if payment_method.is_a?(String)
|
|
223
174
|
|
|
224
|
-
|
|
175
|
+
doc.billToAddress do
|
|
176
|
+
doc.name(payment_method.name)
|
|
177
|
+
doc.email(options[:email]) if options[:email]
|
|
225
178
|
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
unless payment_method.is_a?(LitleCardToken)
|
|
229
|
-
hash['orderSource'] = nil
|
|
230
|
-
hash['orderId'] = nil
|
|
179
|
+
add_address(doc, options[:billing_address])
|
|
231
180
|
end
|
|
232
|
-
|
|
233
|
-
hash
|
|
234
181
|
end
|
|
235
182
|
|
|
236
|
-
def
|
|
237
|
-
|
|
183
|
+
def add_shipping_address(doc, payment_method, options)
|
|
184
|
+
return if payment_method.is_a?(String)
|
|
238
185
|
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
result = LitleCardToken.new(:token => payment_method)
|
|
242
|
-
result.month = options[:token][:month]
|
|
243
|
-
result.year = options[:token][:year]
|
|
244
|
-
result.verification_value = options[:token][:verification_value]
|
|
245
|
-
result.brand = options[:token][:brand]
|
|
186
|
+
doc.shipToAddress do
|
|
187
|
+
add_address(doc, options[:shipping_address])
|
|
246
188
|
end
|
|
247
|
-
|
|
248
|
-
result
|
|
249
189
|
end
|
|
250
190
|
|
|
251
|
-
def
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
191
|
+
def add_address(doc, address)
|
|
192
|
+
return unless address
|
|
193
|
+
|
|
194
|
+
doc.companyName(address[:company]) unless address[:company].blank?
|
|
195
|
+
doc.addressLine1(address[:address1]) unless address[:address1].blank?
|
|
196
|
+
doc.addressLine2(address[:address2]) unless address[:address2].blank?
|
|
197
|
+
doc.city(address[:city]) unless address[:city].blank?
|
|
198
|
+
doc.state(address[:state]) unless address[:state].blank?
|
|
199
|
+
doc.zip(address[:zip]) unless address[:zip].blank?
|
|
200
|
+
doc.country(address[:country]) unless address[:country].blank?
|
|
201
|
+
doc.phone(address[:phone]) unless address[:phone].blank?
|
|
257
202
|
end
|
|
258
203
|
|
|
259
|
-
def
|
|
260
|
-
|
|
261
|
-
add_cardtoken_hash(hash, identification_or_cardtoken)
|
|
262
|
-
else
|
|
263
|
-
transaction_id, kind = split_authorization(identification_or_cardtoken)
|
|
264
|
-
hash['litleTxnId'] = transaction_id
|
|
265
|
-
end
|
|
204
|
+
def exp_date(payment_method)
|
|
205
|
+
"#{format(payment_method.month, :two_digits)}#{format(payment_method.year, :two_digits)}"
|
|
266
206
|
end
|
|
267
207
|
|
|
268
|
-
def
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
208
|
+
def parse(kind, xml)
|
|
209
|
+
parsed = {}
|
|
210
|
+
|
|
211
|
+
doc = Nokogiri::XML(xml).remove_namespaces!
|
|
212
|
+
doc.xpath("//litleOnlineResponse/#{kind}Response/*").each do |node|
|
|
213
|
+
if (node.elements.empty?)
|
|
214
|
+
parsed[node.name.to_sym] = node.text
|
|
215
|
+
else
|
|
216
|
+
node.elements.each do |childnode|
|
|
217
|
+
name = "#{node.name}_#{childnode.name}"
|
|
218
|
+
parsed[name.to_sym] = childnode.text
|
|
219
|
+
end
|
|
220
|
+
end
|
|
221
|
+
end
|
|
274
222
|
|
|
275
|
-
|
|
276
|
-
hash
|
|
223
|
+
parsed
|
|
277
224
|
end
|
|
278
225
|
|
|
279
|
-
def
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
'number' => creditcard.number,
|
|
288
|
-
'expDate' => exp_date,
|
|
289
|
-
'cardValidationNum' => creditcard.verification_value
|
|
226
|
+
def commit(kind, request)
|
|
227
|
+
parsed = parse(kind, ssl_post(url, request, headers))
|
|
228
|
+
|
|
229
|
+
options = {
|
|
230
|
+
authorization: authorization_from(kind, parsed),
|
|
231
|
+
test: test?,
|
|
232
|
+
:avs_result => { :code => AVS_RESPONSE_CODE[parsed[:fraudResult_avsResult]] },
|
|
233
|
+
:cvv_result => parsed[:fraudResult_cardValidationResult]
|
|
290
234
|
}
|
|
291
235
|
|
|
292
|
-
|
|
293
|
-
hash
|
|
236
|
+
Response.new(success_from(kind, parsed), parsed[:message], parsed, options)
|
|
294
237
|
end
|
|
295
238
|
|
|
296
|
-
def
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
hash['litleTxnId'] = authorization
|
|
300
|
-
hash
|
|
239
|
+
def success_from(kind, parsed)
|
|
240
|
+
return (parsed[:response] == '000') unless kind == :registerToken
|
|
241
|
+
%w(000 801 802).include?(parsed[:response])
|
|
301
242
|
end
|
|
302
243
|
|
|
303
|
-
def
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
if creditcard_or_paypage_registration_id.is_a?(String)
|
|
307
|
-
hash['paypageRegistrationId'] = creditcard_or_paypage_registration_id
|
|
308
|
-
else
|
|
309
|
-
hash['accountNumber'] = creditcard_or_paypage_registration_id.number
|
|
310
|
-
end
|
|
311
|
-
|
|
312
|
-
hash
|
|
244
|
+
def authorization_from(kind, parsed)
|
|
245
|
+
(kind == :registerToken) ? parsed[:litleToken] : "#{parsed[:litleTxnId]};#{kind}"
|
|
313
246
|
end
|
|
314
247
|
|
|
315
|
-
def
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
hash
|
|
248
|
+
def split_authorization(authorization)
|
|
249
|
+
transaction_id, kind = authorization.to_s.split(';')
|
|
250
|
+
[transaction_id, kind]
|
|
319
251
|
end
|
|
320
252
|
|
|
321
|
-
def
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
253
|
+
def transaction_attributes(options)
|
|
254
|
+
attributes = {}
|
|
255
|
+
attributes[:id] = truncated(options[:id] || options[:order_id])
|
|
256
|
+
attributes[:reportGroup] = options[:merchant] || 'Default Report Group'
|
|
257
|
+
attributes[:customerId] = options[:customer]
|
|
258
|
+
attributes.delete_if { |key, value| value == nil }
|
|
259
|
+
attributes
|
|
325
260
|
end
|
|
326
261
|
|
|
327
|
-
def
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
if options[:invoice]
|
|
335
|
-
enhanced_data['invoiceReferenceNumber'] = options[:invoice]
|
|
336
|
-
end
|
|
337
|
-
|
|
338
|
-
if options[:description]
|
|
339
|
-
enhanced_data['customerReference'] = options[:description][0..16]
|
|
340
|
-
end
|
|
262
|
+
def root_attributes
|
|
263
|
+
{
|
|
264
|
+
merchantId: @options[:merchant_id],
|
|
265
|
+
version: SCHEMA_VERSION,
|
|
266
|
+
xmlns: "http://www.litle.com/schema"
|
|
267
|
+
}
|
|
268
|
+
end
|
|
341
269
|
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
'addressLine1' => options[:billing_address][:address1],
|
|
347
|
-
'addressLine2' => options[:billing_address][:address2],
|
|
348
|
-
'city' => options[:billing_address][:city],
|
|
349
|
-
'state' => options[:billing_address][:state],
|
|
350
|
-
'zip' => options[:billing_address][:zip],
|
|
351
|
-
'country' => options[:billing_address][:country],
|
|
352
|
-
'email' => options[:email],
|
|
353
|
-
'phone' => options[:billing_address][:phone]
|
|
354
|
-
}
|
|
270
|
+
def build_xml_request
|
|
271
|
+
builder = Nokogiri::XML::Builder.new
|
|
272
|
+
builder.__send__('litleOnlineRequest', root_attributes) do |doc|
|
|
273
|
+
yield(doc)
|
|
355
274
|
end
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
'name' => options[:shipping_address][:name],
|
|
359
|
-
'companyName' => options[:shipping_address][:company],
|
|
360
|
-
'addressLine1' => options[:shipping_address][:address1],
|
|
361
|
-
'addressLine2' => options[:shipping_address][:address2],
|
|
362
|
-
'city' => options[:shipping_address][:city],
|
|
363
|
-
'state' => options[:shipping_address][:state],
|
|
364
|
-
'zip' => options[:shipping_address][:zip],
|
|
365
|
-
'country' => options[:shipping_address][:country],
|
|
366
|
-
'email' => options[:email],
|
|
367
|
-
'phone' => options[:shipping_address][:phone]
|
|
368
|
-
}
|
|
369
|
-
end
|
|
370
|
-
|
|
371
|
-
hash = {
|
|
372
|
-
'billToAddress' => bill_to_address,
|
|
373
|
-
'shipToAddress' => ship_to_address,
|
|
374
|
-
'orderId' => truncated_order_id(options),
|
|
375
|
-
'customerId' => options[:customer],
|
|
376
|
-
'reportGroup' => (options[:merchant] || @options[:merchant]),
|
|
377
|
-
'merchantId' => (options[:merchant_id] || @options[:merchant_id]),
|
|
378
|
-
'orderSource' => (options[:order_source] || 'ecommerce'),
|
|
379
|
-
'enhancedData' => enhanced_data,
|
|
380
|
-
'fraudCheckType' => fraud_check_type,
|
|
381
|
-
'user' => (options[:user] || @options[:user]),
|
|
382
|
-
'password' => (options[:password] || @options[:password]),
|
|
383
|
-
'version' => (options[:version] || @options[:version]),
|
|
384
|
-
'url' => (options[:url] || url),
|
|
385
|
-
'proxy_addr' => (options[:proxy_addr] || @options[:proxy_addr]),
|
|
386
|
-
'proxy_port' => (options[:proxy_port] || @options[:proxy_port]),
|
|
387
|
-
'id' => (options[:id] || options[:order_id] || @options[:order_id])
|
|
388
|
-
}
|
|
275
|
+
builder.doc.root.to_xml
|
|
276
|
+
end
|
|
389
277
|
|
|
390
|
-
|
|
278
|
+
def url
|
|
279
|
+
test? ? test_url : live_url
|
|
280
|
+
end
|
|
391
281
|
|
|
392
|
-
|
|
282
|
+
def truncated(value)
|
|
283
|
+
return unless value
|
|
284
|
+
value[0..24]
|
|
393
285
|
end
|
|
394
286
|
|
|
395
287
|
def truncated_order_id(options)
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
order_id[0..24]
|
|
288
|
+
return unless options[:order_id]
|
|
289
|
+
options[:order_id][0..24]
|
|
399
290
|
end
|
|
400
291
|
|
|
401
|
-
def
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
cvv_to_pass = result['cardValidationResult'].blank? ? "P" : result['cardValidationResult']
|
|
405
|
-
end
|
|
406
|
-
|
|
407
|
-
avs_to_pass = AVS_RESPONSE_CODE[result['avsResult']] unless result['avsResult'].blank?
|
|
408
|
-
end
|
|
409
|
-
{ 'cvv' => cvv_to_pass, 'avs' => avs_to_pass }
|
|
292
|
+
def truncated_id(options)
|
|
293
|
+
return unless options[:id]
|
|
294
|
+
options[:id][0..24]
|
|
410
295
|
end
|
|
411
296
|
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
# == Example Usage
|
|
416
|
-
# token = LitleCardToken.new(
|
|
417
|
-
# :token => '1234567890123456',
|
|
418
|
-
# :month => '9',
|
|
419
|
-
# :year => '2010',
|
|
420
|
-
# :brand => 'visa',
|
|
421
|
-
# :verification_value => '123'
|
|
422
|
-
# )
|
|
423
|
-
#
|
|
424
|
-
# token.valid? # => true
|
|
425
|
-
# cc.exp_date # => 0910
|
|
426
|
-
#
|
|
427
|
-
class LitleCardToken
|
|
428
|
-
include Validateable
|
|
429
|
-
|
|
430
|
-
# Returns or sets the token. (required)
|
|
431
|
-
#
|
|
432
|
-
# @return [String]
|
|
433
|
-
attr_accessor :token
|
|
434
|
-
|
|
435
|
-
# Returns or sets the expiry month for the card associated with token. (optional)
|
|
436
|
-
#
|
|
437
|
-
# @return [Integer]
|
|
438
|
-
attr_accessor :month
|
|
439
|
-
|
|
440
|
-
# Returns or sets the expiry year for the card associated with token. (optional)
|
|
441
|
-
#
|
|
442
|
-
# @return [Integer]
|
|
443
|
-
attr_accessor :year
|
|
444
|
-
|
|
445
|
-
# Returns or sets the card verification value. (optional)
|
|
446
|
-
#
|
|
447
|
-
# @return [String] the verification value
|
|
448
|
-
attr_accessor :verification_value
|
|
449
|
-
|
|
450
|
-
# Returns or sets the credit card brand. (optional)
|
|
451
|
-
#
|
|
452
|
-
# Valid card types are
|
|
453
|
-
#
|
|
454
|
-
# * +'visa'+
|
|
455
|
-
# * +'master'+
|
|
456
|
-
# * +'discover'+
|
|
457
|
-
# * +'american_express'+
|
|
458
|
-
# * +'diners_club'+
|
|
459
|
-
# * +'jcb'+
|
|
460
|
-
# * +'switch'+
|
|
461
|
-
# * +'solo'+
|
|
462
|
-
# * +'dankort'+
|
|
463
|
-
# * +'maestro'+
|
|
464
|
-
# * +'forbrugsforeningen'+
|
|
465
|
-
# * +'laser'+
|
|
466
|
-
#
|
|
467
|
-
# @return (String) the credit card brand
|
|
468
|
-
attr_accessor :brand
|
|
469
|
-
|
|
470
|
-
# Returns the Litle credit card type identifier.
|
|
471
|
-
#
|
|
472
|
-
# @return (String) the credit card type identifier
|
|
473
|
-
def type
|
|
474
|
-
CARD_TYPE[brand] unless brand.blank?
|
|
475
|
-
end
|
|
476
|
-
|
|
477
|
-
# Returns true if the expiration date is set.
|
|
478
|
-
#
|
|
479
|
-
# @return (Boolean)
|
|
480
|
-
def exp_date?
|
|
481
|
-
!month.to_i.zero? && !year.to_i.zero?
|
|
482
|
-
end
|
|
483
|
-
|
|
484
|
-
# Returns the card token expiration date in MMYY format.
|
|
485
|
-
#
|
|
486
|
-
# @return (String) the expiration date in MMYY format
|
|
487
|
-
def exp_date
|
|
488
|
-
result = ''
|
|
489
|
-
if exp_date?
|
|
490
|
-
exp_date_yr = year.to_s[2..3]
|
|
491
|
-
exp_date_mo = '%02d' % month.to_i
|
|
492
|
-
|
|
493
|
-
result = exp_date_mo + exp_date_yr
|
|
494
|
-
end
|
|
495
|
-
result
|
|
496
|
-
end
|
|
497
|
-
|
|
498
|
-
# Validates the card token details.
|
|
499
|
-
#
|
|
500
|
-
# Any validation errors are added to the {#errors} attribute.
|
|
501
|
-
def validate
|
|
502
|
-
validate_card_token
|
|
503
|
-
validate_expiration_date
|
|
504
|
-
validate_card_brand
|
|
505
|
-
end
|
|
506
|
-
|
|
507
|
-
def check?
|
|
508
|
-
false
|
|
509
|
-
end
|
|
510
|
-
|
|
511
|
-
private
|
|
512
|
-
|
|
513
|
-
CARD_TYPE = {
|
|
514
|
-
'visa' => 'VI',
|
|
515
|
-
'master' => 'MC',
|
|
516
|
-
'american_express' => 'AX',
|
|
517
|
-
'discover' => 'DI',
|
|
518
|
-
'jcb' => 'DI',
|
|
519
|
-
'diners_club' => 'DI'
|
|
297
|
+
def headers
|
|
298
|
+
{
|
|
299
|
+
'Content-Type' => 'text/xml'
|
|
520
300
|
}
|
|
521
|
-
|
|
522
|
-
def before_validate #:nodoc:
|
|
523
|
-
self.month = month.to_i
|
|
524
|
-
self.year = year.to_i
|
|
525
|
-
end
|
|
526
|
-
|
|
527
|
-
# Litle XML Reference Guide 1.8.2
|
|
528
|
-
#
|
|
529
|
-
# The length of the original card number is reflected in the token, so a
|
|
530
|
-
# submitted 16-digit number results in a 16-digit token. Also, all tokens
|
|
531
|
-
# use only numeric characters, so you do not have to change your
|
|
532
|
-
# systems to accept alpha-numeric characters.
|
|
533
|
-
#
|
|
534
|
-
# The credit card token numbers themselves have two parts.
|
|
535
|
-
# The last four digits match the last four digits of the card number.
|
|
536
|
-
# The remaining digits (length can vary based upon original card number
|
|
537
|
-
# length) are a randomly generated.
|
|
538
|
-
def validate_card_token #:nodoc:
|
|
539
|
-
if token.to_s.length < 12 || token.to_s.match(/\A\d+\Z/).nil?
|
|
540
|
-
errors.add :token, "is not a valid card token"
|
|
541
|
-
end
|
|
542
|
-
end
|
|
543
|
-
|
|
544
|
-
def validate_expiration_date #:nodoc:
|
|
545
|
-
if !month.to_i.zero? || !year.to_i.zero?
|
|
546
|
-
errors.add :month, "is not a valid month" unless valid_month?(month)
|
|
547
|
-
errors.add :year, "is not a valid year" unless valid_expiry_year?(year)
|
|
548
|
-
end
|
|
549
|
-
end
|
|
550
|
-
|
|
551
|
-
def validate_card_brand #:nodoc:
|
|
552
|
-
errors.add :brand, "is invalid" unless brand.blank? || CreditCard.card_companies.keys.include?(brand)
|
|
553
|
-
end
|
|
554
|
-
|
|
555
|
-
def valid_month?(month)
|
|
556
|
-
(1..12).include?(month.to_i)
|
|
557
|
-
end
|
|
558
|
-
|
|
559
|
-
def valid_expiry_year?(year)
|
|
560
|
-
year.to_s =~ /\A\d{4}\Z/ && year.to_i > 1987
|
|
561
|
-
end
|
|
562
301
|
end
|
|
302
|
+
|
|
563
303
|
end
|
|
564
304
|
end
|
|
565
305
|
end
|