sac_active_merchant_first_data 1.3.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.
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: dbf13ac2290b828176abe2950cde9f5ea56115d0
4
+ data.tar.gz: 4417471dfffbe2b91c87a84cc853040ae580d1e0
5
+ SHA512:
6
+ metadata.gz: ba10208e092fb8c1a6868bb118ba7c65f318eb0676c5e976a5d71829c1e9e4dd958af93a3701dcf309556e793d34bed2d7613520946d6284188ec44a7d848d65
7
+ data.tar.gz: c91211ec6c01187638ca7ed53a0c568f8d42e99ebed103c7608ed6479fe818d70f4b1b784275b6af1bf8c63375ff5ab50c700befac22fd65e5a0fe57badeb329
@@ -0,0 +1,15 @@
1
+ ## 1.3.0
2
+
3
+ * Response as an object instead of a hash (@Sacristan, #6)
4
+
5
+ ## 1.2.0
6
+
7
+ * Changed default currency from LVL to EUR
8
+
9
+ ## 1.1.0
10
+
11
+ * Recurring payments support (@rsim)
12
+
13
+ ## 1.0.0
14
+
15
+ * Initial version
data/LICENSE ADDED
@@ -0,0 +1,20 @@
1
+ Copyright (c) 2011 Edgars Beigarts
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining
4
+ a copy of this software and associated documentation files (the
5
+ "Software"), to deal in the Software without restriction, including
6
+ without limitation the rights to use, copy, modify, merge, publish,
7
+ distribute, sublicense, and/or sell copies of the Software, and to
8
+ permit persons to whom the Software is furnished to do so, subject to
9
+ the following conditions:
10
+
11
+ The above copyright notice and this permission notice shall be
12
+ included in all copies or substantial portions of the Software.
13
+
14
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
@@ -0,0 +1,65 @@
1
+ First Data Latvia gateway for Active Merchant
2
+ =============================================
3
+
4
+ [![Continuous Integration status](https://secure.travis-ci.org/ebeigarts/active_merchant_first_data.png)](http://travis-ci.org/ebeigarts/active_merchant_first_data)
5
+
6
+ ## Install
7
+
8
+ ```bash
9
+ $ gem install active_merchant_first_data
10
+ ```
11
+
12
+ ## Usage
13
+
14
+ ```ruby
15
+ require "active_merchant_first_data"
16
+
17
+ gateway = ActiveMerchant::Billing::FirstDataGateway.new(
18
+ pem: "1234567_keystore.pem"
19
+ pem_password: "5x64jq8n234c"
20
+ )
21
+
22
+ # Authorize for 10 euros (1000 euro cents)
23
+ response = gateway.authorize(1000, client_ip_addr: '127.0.0.1')
24
+
25
+ # Use this url to enter credit card data
26
+ gateway.redirect_url(response.authorization)
27
+
28
+ # Capture the money
29
+ gateway.capture(1000, response.authorization, client_ip_addr: '127.0.0.1')
30
+ ```
31
+
32
+ ## First Data test environment setup
33
+
34
+ 1. Generate a new certificate
35
+
36
+ ```bash
37
+ $ openssl req -newkey rsa:2048 -keyout spec/certs/1234567_key.pem -out spec/certs/1234567_req.pem -subj "/C=lv/O=example.com/CN=1234567" -outform PEM
38
+ Enter PEM pass phrase: 81f174259v45
39
+ ```
40
+
41
+ 2. [Request your certificate using `1234567_req.pem`](https://secureshop-test.firstdata.lv/report/keystore_.do)
42
+
43
+ 3. Copy the 3 files you received in e-mail to `spec/certs/`:
44
+
45
+ ```
46
+ 1234567.pem
47
+ 1234567_certificate_chain.p7.pem
48
+ ECOMM.pem
49
+ ```
50
+
51
+ 4. Convert the certificates and keys to `1234567_keystore.pem`
52
+
53
+ ```bash
54
+ $ openssl pkcs12 -export -in spec/certs/1234567.pem -out spec/certs/1234567_keystore.p12 -certfile spec/certs/ECOMM.pem -inkey spec/certs/1234567_key.pem
55
+ Enter pass phrase for 1234567_key.pem: 81f174259v45
56
+ Enter Export Password: <empty>
57
+ ```
58
+
59
+ ```bash
60
+ $ openssl pkcs12 -in spec/certs/1234567_keystore.p12 > spec/certs/1234567_keystore.pem
61
+ Enter Import Password: <empty>
62
+ Enter PEM pass phrase: 5x64jq8n234c
63
+ ```
64
+
65
+ 5. [Set your WAN IP address](https://secureshop-test.firstdata.lv/report/merchantlist.do)
@@ -0,0 +1,317 @@
1
+ module ActiveMerchant #:nodoc:
2
+ module Billing #:nodoc:
3
+ class FirstDataGateway < Gateway
4
+ # http://en.wikipedia.org/wiki/ISO_4217
5
+ CURRENCY_CODES = {
6
+ 'ADP' => '020', 'AED' => '784', 'AFA' => '004', 'ALL' => '008', 'AMD' => '051',
7
+ 'ANG' => '532', 'AOA' => '973', 'ARS' => '032', 'AUD' => '036', 'AWG' => '533',
8
+ 'AZM' => '031', 'BAM' => '977', 'BBD' => '052', 'BDT' => '050', 'BGL' => '100',
9
+ 'BGN' => '975', 'BHD' => '048', 'BIF' => '108', 'BMD' => '060', 'BND' => '096',
10
+ 'BOB' => '068', 'BOV' => '984', 'BRL' => '986', 'BSD' => '044', 'BTN' => '064',
11
+ 'BWP' => '072', 'BYR' => '974', 'BZD' => '084', 'CAD' => '124', 'CDF' => '976',
12
+ 'CHF' => '756', 'CLF' => '990', 'CLP' => '152', 'CNY' => '156', 'COP' => '170',
13
+ 'CRC' => '188', 'CUP' => '192', 'CVE' => '132', 'CYP' => '196', 'CZK' => '203',
14
+ 'DJF' => '262', 'DKK' => '208', 'DOP' => '214', 'DZD' => '012', 'ECS' => '218',
15
+ 'ECV' => '983', 'EEK' => '233', 'EGP' => '818', 'ERN' => '232', 'ETB' => '230',
16
+ 'EUR' => '978', 'FJD' => '242', 'FKP' => '238', 'GBP' => '826', 'GEL' => '981',
17
+ 'GHC' => '288', 'GIP' => '292', 'GMD' => '270', 'GNF' => '324', 'GTQ' => '320',
18
+ 'GWP' => '624', 'GYD' => '328', 'HKD' => '344', 'HNL' => '340', 'HRK' => '191',
19
+ 'HTG' => '332', 'HUF' => '348', 'IDR' => '360', 'ILS' => '376', 'INR' => '356',
20
+ 'IQD' => '368', 'IRR' => '364', 'ISK' => '352', 'JMD' => '388', 'JOD' => '400',
21
+ 'JPY' => '392', 'KES' => '404', 'KGS' => '417', 'KHR' => '116', 'KMF' => '174',
22
+ 'KPW' => '408', 'KRW' => '410', 'KWD' => '414', 'KYD' => '136', 'KZT' => '398',
23
+ 'LAK' => '418', 'LBP' => '422', 'LKR' => '144', 'LRD' => '430', 'LSL' => '426',
24
+ 'LTL' => '440', 'LVL' => '428', 'LYD' => '434', 'MAD' => '504', 'MDL' => '498',
25
+ 'MGF' => '450', 'MKD' => '807', 'MMK' => '104', 'MNT' => '496', 'MOP' => '446',
26
+ 'MRO' => '478', 'MTL' => '470', 'MUR' => '480', 'MVR' => '462', 'MWK' => '454',
27
+ 'MXN' => '484', 'MXV' => '979', 'MYR' => '458', 'MZM' => '508', 'NAD' => '516',
28
+ 'NGN' => '566', 'NIO' => '558', 'NOK' => '578', 'NPR' => '524', 'NZD' => '554',
29
+ 'OMR' => '512', 'PAB' => '590', 'PEN' => '604', 'PGK' => '598', 'PHP' => '608',
30
+ 'PKR' => '586', 'PLN' => '985', 'PYG' => '600', 'QAR' => '634', 'ROL' => '642',
31
+ 'RUB' => '643', 'RUR' => '810', 'RWF' => '646', 'SAR' => '682', 'SBD' => '090',
32
+ 'SCR' => '690', 'SDD' => '736', 'SEK' => '752', 'SGD' => '702', 'SHP' => '654',
33
+ 'SIT' => '705', 'SKK' => '703', 'SLL' => '694', 'SOS' => '706', 'SRG' => '740',
34
+ 'STD' => '678', 'SVC' => '222', 'SYP' => '760', 'SZL' => '748', 'THB' => '764',
35
+ 'TJS' => '972', 'TMM' => '795', 'TND' => '788', 'TOP' => '776', 'TPE' => '626',
36
+ 'TRL' => '792', 'TRY' => '949', 'TTD' => '780', 'TWD' => '901', 'TZS' => '834',
37
+ 'UAH' => '980', 'UGX' => '800', 'USD' => '840', 'UYU' => '858', 'UZS' => '860',
38
+ 'VEB' => '862', 'VND' => '704', 'VUV' => '548', 'XAF' => '950', 'XCD' => '951',
39
+ 'XOF' => '952', 'XPF' => '953', 'YER' => '886', 'YUM' => '891', 'ZAR' => '710',
40
+ 'ZMK' => '894', 'ZWD' => '716'
41
+ }
42
+
43
+ class_attribute :test_url, :live_url, :test_redirect_url, :live_redirect_url, :pem_file, :pem_password
44
+
45
+ self.test_redirect_url = 'https://secureshop-test.firstdata.lv/ecomm/ClientHandler'
46
+ self.live_redirect_url = 'https://secureshop.firstdata.lv/ecomm/ClientHandler'
47
+
48
+ self.test_url = 'https://secureshop-test.firstdata.lv:8443/ecomm/MerchantHandler'
49
+ self.live_url = 'https://secureshop.firstdata.lv:8443/ecomm/MerchantHandler'
50
+
51
+ self.homepage_url = 'http://www.firstdata.lv/'
52
+ self.display_name = 'First Data'
53
+
54
+ self.ssl_strict = false
55
+ self.default_currency = CURRENCY_CODES['EUR']
56
+ self.money_format = :cents
57
+
58
+ class Error < StandardError
59
+ attr_reader :response
60
+
61
+ def initialize(response, msg=nil)
62
+ @response = response
63
+ super(msg || response[:error])
64
+ end
65
+ end
66
+
67
+ # Creates a new FirstDataGateway
68
+ #
69
+ # The gateway requires that a valid pem and password be passed
70
+ # in the +options+ hash.
71
+ #
72
+ # @option options [String] :pem First Data cert/key (REQUIRED)
73
+ # @option options [String] :pem_password First Data cert password (REQUIRED)
74
+ #
75
+ def initialize(options = {})
76
+ requires!(options, :pem, :pem_password)
77
+ @options = options
78
+ super
79
+ end
80
+
81
+ # Perform a purchase, which is essentially an authorization and capture in a single operation.
82
+ #
83
+ # Registering of SMS transaction
84
+ #
85
+ # @param [Integer] amount transaction amount in minor units, mandatory
86
+ # @option params [Integer, String] :currency transaction currency code, mandatory
87
+ # @option params [String] :client_ip_addr client's IP address, mandatory
88
+ # @option params [String] :description description of transaction, optional
89
+ # @option params [String] :language authorization language identificator, optional
90
+ # @return [ActiveSupport::HashWithIndifferentAccess] TRANSACTION_ID
91
+ #
92
+ def purchase(amount, params = {})
93
+ params = params.reverse_merge(
94
+ :command => :v,
95
+ :amount => amount,
96
+ :currency => default_currency
97
+ )
98
+ lookup_currency(params)
99
+ requires!(params, :amount, :currency, :client_ip_addr)
100
+ commit(params)
101
+ end
102
+
103
+ # Performs an authorization, which reserves the funds on the customer's credit card, but does not
104
+ # charge the card.
105
+ #
106
+ # Registering of DMS authorisation
107
+ #
108
+ # @param [Integer] amount transaction amount in minor units, mandatory
109
+ # @option params [Integer, String] :currency transaction currency code, mandatory
110
+ # @option params [String] :client_ip_addr client's IP address, mandatory
111
+ # @option params [String] :description description of transaction, optional
112
+ # @option params [String] :language authorization language identificator, optional
113
+ # @return [ActiveSupport::HashWithIndifferentAccess] TRANSACTION_ID
114
+ #
115
+ def authorize(amount, params = {})
116
+ params = params.reverse_merge(
117
+ :command => :a,
118
+ :msg_type => 'DMS',
119
+ :amount => amount,
120
+ :currency => default_currency
121
+ )
122
+ lookup_currency(params)
123
+ requires!(params, :amount, :currency, :client_ip_addr, :msg_type)
124
+ commit(params)
125
+ end
126
+
127
+ # Captures the funds from an authorized transaction.
128
+ #
129
+ # Making of DMS transaction
130
+ #
131
+ # @param [Integer] amount transaction amount in minor units, mandatory
132
+ # @param [Integer] trans_id id of previously made successeful authorisation
133
+ # @option params [Integer, String] :currency transaction currency code, mandatory
134
+ # @option params [String] :client_ip_addr client's IP address, mandatory
135
+ # @option params [String] :description description of transaction, optional
136
+ # @return [ActiveSupport::HashWithIndifferentAccess] RESULT, RESULT_CODE, RRN, APPROVAL_CODE
137
+ #
138
+ def capture(amount, trans_id, params = {})
139
+ params = params.reverse_merge(
140
+ :command => :t,
141
+ :msg_type => 'DMS',
142
+ :trans_id => trans_id,
143
+ :amount => amount,
144
+ :currency => default_currency
145
+ )
146
+ lookup_currency(params)
147
+ requires!(params, :trans_id, :amount, :currency, :client_ip_addr)
148
+ commit(params)
149
+ end
150
+
151
+ # Transaction result
152
+ #
153
+ # @param [Integer] trans_id transaction identifier, mandatory
154
+ # @option params [String] :client_ip_addr client's IP address, mandatory
155
+ # @return [ActiveSupport::HashWithIndifferentAccess] RESULT, RESULT_CODE, 3DSECURE, AAV, RRN, APPROVAL_CODE
156
+ #
157
+ def result(trans_id, params = {})
158
+ params = params.reverse_merge(
159
+ :command => :c,
160
+ :trans_id => trans_id
161
+ )
162
+ requires!(params, :trans_id, :client_ip_addr)
163
+ commit(params)
164
+ end
165
+
166
+ # refund() allows you to return money to a card that was previously billed.
167
+ #
168
+ # Transaction reversal
169
+ #
170
+ # @param [Integer] amount transaction amount in minor units, mandatory
171
+ # @param [Integer] trans_id transaction identifier, mandatory
172
+ # @return [ActiveSupport::HashWithIndifferentAccess] RESULT, RESULT_CODE
173
+ #
174
+ def refund(amount, trans_id = nil)
175
+ params = {
176
+ :command => :r,
177
+ :trans_id => trans_id,
178
+ :amount => amount
179
+ }
180
+ requires!(params, :command, :trans_id, :amount)
181
+ commit(params)
182
+ end
183
+
184
+ def credit(amount, trans_id = nil)
185
+ deprecated CREDIT_DEPRECATION_MESSAGE
186
+ refund(amount, trans_id)
187
+ end
188
+
189
+ # Register new recurring payment along with the first payment
190
+ #
191
+ # @param [Integer] amount transaction amount in minor units, mandatory (up to 12 digits)
192
+ # @option params [Integer, String] :currency transaction currency code, mandatory
193
+ # @option params [String] :client_ip_addr client's IP address, mandatory
194
+ # @option params [String] :description transaction details, mandatory (up to 125 characters)
195
+ # @option params [String] :biller_client_id recurring payment identifier, mandatory (up to 30 characters)
196
+ # @option params [String] :perspayee_expiry preferred deadline for a Recurring payment, mandatory (MMYY)
197
+ # (system will compare two expiry dates - recurring payment expiry date provided by Merchant and
198
+ # card expiry date provided by Cardholder. In response Merchant will receive back the earliest expiry dates of both).
199
+ # For example, Recurring payment date is 1214 but card expiry date 1213 then Merchant will receive back 1213.
200
+ # First Data system will save the earliest expiry date as Recurring payment expiry date.
201
+ # @option params [Integer] :perspayee_overwrite set to 1 to overwrite existing recurring payment card data
202
+ # together with payment, optional
203
+ # @option params [String] :language authorization language identificator, optional
204
+ # @return [ActiveSupport::HashWithIndifferentAccess] TRANSACTION_ID
205
+ #
206
+ # Afterwards when transaction result is requested then result response includes also RECC_PMNT_ID and RECC_PMNT_EXPIRY
207
+ #
208
+ def recurring(amount, params = {})
209
+ params = params.reverse_merge(
210
+ :command => :z,
211
+ :amount => amount,
212
+ :currency => default_currency,
213
+ :msg_type => 'SMS',
214
+ :perspayee_gen => 1
215
+ )
216
+ lookup_currency(params)
217
+ requires!(params, :amount, :currency, :client_ip_addr, :description, :biller_client_id, :perspayee_expiry)
218
+ commit(params)
219
+ end
220
+
221
+ # Execute subsequent recurring payment
222
+ #
223
+ # @param [Integer] amount transaction amount in minor units, mandatory (up to 12 digits)
224
+ # @option params [Integer, String] :currency transaction currency code, mandatory
225
+ # @option params [String] :client_ip_addr client's IP address, mandatory
226
+ # (the same IP address which was provided when registered recurring payment)
227
+ # @option params [String] :description transaction details, mandatory (up to 125 characters)
228
+ # @option params [String] :biller_client_id recurring payment identifier, mandatory (up to 30 characters)
229
+ # @return [ActiveSupport::HashWithIndifferentAccess] TRANSACTION_ID, RESULT, RESULT_CODE, RRN, APPROVAL_CODE
230
+ #
231
+ def execute_recurring(amount, params = {})
232
+ params = params.reverse_merge(
233
+ :command => :e,
234
+ :amount => amount,
235
+ :currency => default_currency
236
+ )
237
+ lookup_currency(params)
238
+ requires!(params, :amount, :currency, :client_ip_addr, :description, :biller_client_id)
239
+ commit(params)
240
+ end
241
+
242
+ # Overwriting existing recurring payment card data without payment
243
+ #
244
+ # @option params [Integer, String] :currency transaction currency code, mandatory
245
+ # @option params [String] :client_ip_addr client's IP address, mandatory
246
+ # @option params [String] :description transaction details, mandatory (up to 125 characters)
247
+ # @option params [String] :biller_client_id existing recurring payment identifier, mandatory (up to 30 characters)
248
+ # @option params [String] :perspayee_expiry preferred deadline for a Recurring payment, mandatory (MMYY)
249
+ # (system will compare two expiry dates - recurring payment expiry date provided by Merchant and
250
+ # card expiry date provided by Cardholder. In response Merchant will receive back the earliest expiry dates of both).
251
+ # For example, Recurring payment date is 1214 but card expiry date 1213 then Merchant will receive back 1213.
252
+ # First Data system will save the earliest expiry date as Recurring payment expiry date.
253
+ # @option params [String] :language authorization language identificator, optional
254
+ # @return [ActiveSupport::HashWithIndifferentAccess] TRANSACTION_ID
255
+ #
256
+ # Afterwards when transaction result is requested then result response includes also RECC_PMNT_ID and RECC_PMNT_EXPIRY
257
+ #
258
+ def update_recurring(params = {})
259
+ params = params.reverse_merge(
260
+ :command => :p,
261
+ :amount => 0,
262
+ :currency => default_currency,
263
+ :msg_type => 'AUTH',
264
+ :perspayee_gen => 1,
265
+ :perspayee_overwrite => 1
266
+ )
267
+ lookup_currency(params)
268
+ requires!(params, :currency, :client_ip_addr, :description, :biller_client_id, :perspayee_expiry)
269
+ commit(params)
270
+ end
271
+
272
+ # Close business day.
273
+ def close_day
274
+ commit({ :command => :b })
275
+ end
276
+
277
+ def endpoint_url
278
+ test? ? test_url : live_url
279
+ end
280
+
281
+ def redirect_url(trans_id = nil)
282
+ url = test? ? test_redirect_url : live_redirect_url
283
+ url += "?trans_id=#{CGI.escape trans_id}" if trans_id
284
+ url
285
+ end
286
+
287
+ private
288
+ def lookup_currency(params)
289
+ params[:currency] = CURRENCY_CODES[params[:currency]] || params[:currency]
290
+ end
291
+
292
+ # Convert HTTP response body to a Ruby Hash.
293
+ def parse(body)
294
+ results = ActiveSupport::HashWithIndifferentAccess.new
295
+ body.split(/[\r\n]+/).each do |pair|
296
+ key, val = pair.split(": ")
297
+ results[key.downcase] = val
298
+ end
299
+ results
300
+ end
301
+
302
+ def commit(params = {})
303
+ response = parse(ssl_post(endpoint_url, post_data(params)))
304
+ # FIXME: test cases 17 and 19 return unnecessary error even when result and result_code are present
305
+ # should be removed when this issue is fixed on gataway side
306
+ raise Error.new(response) if !response[:error].blank? && response[:result_code].blank?
307
+ ActiveMerchant::Billing::FirstDataResponse.new response
308
+ end
309
+
310
+ def post_data(params)
311
+ post = PostData.new
312
+ params.each { |k, v| post[k] = v }
313
+ post.to_s
314
+ end
315
+ end
316
+ end
317
+ end
@@ -0,0 +1,150 @@
1
+ module ActiveMerchant #:nodoc:
2
+ module Billing #:nodoc:
3
+ class FirstDataResponse < Response
4
+ RESPONSE_CODES = {
5
+ "000" => "Approved",
6
+ "001" => "Approved, honour with identification",
7
+ "002" => "Approved for partial amount",
8
+ "003" => "Approved for VIP",
9
+ "004" => "Approved, update track 3",
10
+ "005" => "Approved, account type specified by card issuer",
11
+ "006" => "Approved for partial amount, account type specified by card issuer",
12
+ "007" => "Approved, update ICC",
13
+ "100" => "Decline (general, no comments)",
14
+ "101" => "Decline, expired card",
15
+ "102" => "Decline, suspected fraud",
16
+ "103" => "Decline, card acceptor contact acquirer",
17
+ "104" => "Decline, restricted card",
18
+ "105" => "Decline, card acceptor call acquirer's security department",
19
+ "106" => "Decline, allowable PIN tries exceeded",
20
+ "107" => "Decline, refer to card issuer",
21
+ "108" => "Decline, refer to card issuer's special conditions",
22
+ "109" => "Decline, invalid merchant",
23
+ "110" => "Decline, invalid amount",
24
+ "111" => "Decline, invalid card number",
25
+ "112" => "Decline, PIN data required",
26
+ "113" => "Decline, unacceptable fee",
27
+ "114" => "Decline, no account of type requested",
28
+ "115" => "Decline, requested function not supported",
29
+ "116" => "Decline, not sufficient funds",
30
+ "117" => "Decline, incorrect PIN",
31
+ "118" => "Decline, no card record",
32
+ "119" => "Decline, transaction not permitted to cardholder",
33
+ "120" => "Decline, transaction not permitted to terminal",
34
+ "121" => "Decline, exceeds withdrawal amount limit",
35
+ "122" => "Decline, security violation",
36
+ "123" => "Decline, exceeds withdrawal frequency limit",
37
+ "124" => "Decline, violation of law",
38
+ "125" => "Decline, card not effective",
39
+ "126" => "Decline, invalid PIN block",
40
+ "127" => "Decline, PIN length error",
41
+ "128" => "Decline, PIN kay synch error",
42
+ "129" => "Decline, suspected counterfeit card",
43
+ "197" => "Declined, call AmEx",
44
+ "198" => "Declined, call Card Processing Centre",
45
+ "200" => "Pick-up (general, no comments)",
46
+ "201" => "Pick-up, expired card",
47
+ "202" => "Pick-up, suspected fraud",
48
+ "203" => "Pick-up, card acceptor contact card acquirer",
49
+ "204" => "Pick-up, restricted card",
50
+ "205" => "Pick-up, card acceptor call acquirer's security department",
51
+ "206" => "Pick-up, allowable PIN tries exceeded",
52
+ "207" => "Pick-up, special conditions",
53
+ "208" => "Pick-up, lost card",
54
+ "209" => "Pick-up, stolen card",
55
+ "210" => "Pick-up, suspected counterfeit card",
56
+ "300" => "Status message: file action successful",
57
+ "301" => "Status message: file action not supported by receiver",
58
+ "302" => "Status message: unable to locate record on file",
59
+ "303" => "Status message: duplicate record, old record replaced",
60
+ "304" => "Status message: file record field edit error",
61
+ "305" => "Status message: file locked out",
62
+ "306" => "Status message: file action not successful",
63
+ "307" => "Status message: file data format error",
64
+ "308" => "Status message: duplicate record, new record rejected",
65
+ "309" => "Status message: unknown file",
66
+ "400" => "Accepted (for reversal)",
67
+ "500" => "Status message: reconciled, in balance",
68
+ "501" => "Status message: reconciled, out of balance",
69
+ "502" => "Status message: amount not reconciled, totals provided",
70
+ "503" => "Status message: totals for reconciliation not available",
71
+ "504" => "Status message: not reconciled, totals provided",
72
+ "600" => "Accepted (for administrative info)",
73
+ "601" => "Status message: impossible to trace back original transaction",
74
+ "602" => "Status message: invalid transaction reference number",
75
+ "603" => "Status message: reference number/PAN incompatible",
76
+ "604" => "Status message: POS photograph is not available",
77
+ "605" => "Status message: requested item supplied",
78
+ "606" => "Status message: request cannot be fulfilled - required documentation is not available",
79
+ "700" => "Accepted (for fee collection)",
80
+ "800" => "Accepted (for network management)",
81
+ "900" => "Advice acknowledged, no financial liability accepted",
82
+ "901" => "Advice acknowledged, finansial liability accepted",
83
+ "902" => "Decline reason message: invalid transaction",
84
+ "903" => "Status message: re-enter transaction",
85
+ "904" => "Decline reason message: format error",
86
+ "905" => "Decline reason message: acqiurer not supported by switch",
87
+ "906" => "Decline reason message: cutover in process",
88
+ "907" => "Decline reason message: card issuer or switch inoperative",
89
+ "908" => "Decline reason message: transaction destination cannot be found for routing",
90
+ "909" => "Decline reason message: system malfunction",
91
+ "910" => "Decline reason message: card issuer signed off",
92
+ "911" => "Decline reason message: card issuer timed out",
93
+ "912" => "Decline reason message: card issuer unavailable",
94
+ "913" => "Decline reason message: duplicate transmission",
95
+ "914" => "Decline reason message: not able to trace back to original transaction",
96
+ "915" => "Decline reason message: reconciliation cutover or checkpoint error",
97
+ "916" => "Decline reason message: MAC incorrect",
98
+ "917" => "Decline reason message: MAC key sync error",
99
+ "918" => "Decline reason message: no communication keys available for use",
100
+ "919" => "Decline reason message: encryption key sync error",
101
+ "920" => "Decline reason message: security software/hardware error - try again",
102
+ "921" => "Decline reason message: security software/hardware error - no action",
103
+ "922" => "Decline reason message: message number out of sequence",
104
+ "923" => "Status message: request in progress",
105
+ "940" => "Decline, blocked by fraud filter",
106
+ "950" => "Decline reason message: violation of business arrangement"
107
+ }
108
+
109
+ attr_accessor :authorization, :error_code, :error_message, :success, :message
110
+
111
+ def initialize params, options={}
112
+ @params = params.with_indifferent_access
113
+
114
+ success = @params[:result] == 'OK'
115
+ message = RESPONSE_CODES[@params[:result_code]]
116
+
117
+ unless success
118
+ error_code = @params[:result_code]
119
+ error_message = message
120
+ end
121
+
122
+ super success, message, @params, options.merge(
123
+ authorization: @params[:transaction_id]
124
+ )
125
+ end
126
+
127
+ def recurring?
128
+ recc_pmnt_id.present? && recc_pmnt_expiry.present?
129
+ end
130
+
131
+ [:recc_pmnt_expiry, :recc_pmnt_id, :result, :result_code, :transaction_id].each do |name|
132
+ define_method name do
133
+ @params[name]
134
+ end
135
+ end
136
+
137
+ def _3d_secure
138
+ @params[:'3dsecure']
139
+ end
140
+
141
+ def result_message
142
+ message
143
+ end
144
+
145
+ def [](value)
146
+ @params[value]
147
+ end
148
+ end
149
+ end
150
+ end
@@ -0,0 +1,3 @@
1
+ require "active_merchant"
2
+ require "active_merchant/billing/first_data_response"
3
+ require "active_merchant/billing/first_data_gateway"
metadata ADDED
@@ -0,0 +1,119 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: sac_active_merchant_first_data
3
+ version: !ruby/object:Gem::Version
4
+ version: 1.3.0
5
+ platform: ruby
6
+ authors:
7
+ - Girts Kesteris
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2016-04-01 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: activemerchant
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - ">="
18
+ - !ruby/object:Gem::Version
19
+ version: 1.15.0
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - ">="
25
+ - !ruby/object:Gem::Version
26
+ version: 1.15.0
27
+ - !ruby/object:Gem::Dependency
28
+ name: rake
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - ">="
32
+ - !ruby/object:Gem::Version
33
+ version: '0'
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - ">="
39
+ - !ruby/object:Gem::Version
40
+ version: '0'
41
+ - !ruby/object:Gem::Dependency
42
+ name: rspec
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - "~>"
46
+ - !ruby/object:Gem::Version
47
+ version: '3.2'
48
+ type: :development
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - "~>"
53
+ - !ruby/object:Gem::Version
54
+ version: '3.2'
55
+ - !ruby/object:Gem::Dependency
56
+ name: vcr
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - "~>"
60
+ - !ruby/object:Gem::Version
61
+ version: '1.11'
62
+ type: :development
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - "~>"
67
+ - !ruby/object:Gem::Version
68
+ version: '1.11'
69
+ - !ruby/object:Gem::Dependency
70
+ name: fakeweb
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - "~>"
74
+ - !ruby/object:Gem::Version
75
+ version: '1.3'
76
+ type: :development
77
+ prerelease: false
78
+ version_requirements: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - "~>"
81
+ - !ruby/object:Gem::Version
82
+ version: '1.3'
83
+ description: First Data Latvia gateway for Active Merchant
84
+ email:
85
+ - girts@creative.gs
86
+ executables: []
87
+ extensions: []
88
+ extra_rdoc_files: []
89
+ files:
90
+ - CHANGELOG.md
91
+ - LICENSE
92
+ - README.md
93
+ - lib/active_merchant/billing/first_data_gateway.rb
94
+ - lib/active_merchant/billing/first_data_response.rb
95
+ - lib/active_merchant_first_data.rb
96
+ homepage: https://github.com/Sacristan/sac_active_merchant_first_data
97
+ licenses: []
98
+ metadata: {}
99
+ post_install_message:
100
+ rdoc_options: []
101
+ require_paths:
102
+ - lib
103
+ required_ruby_version: !ruby/object:Gem::Requirement
104
+ requirements:
105
+ - - ">="
106
+ - !ruby/object:Gem::Version
107
+ version: '0'
108
+ required_rubygems_version: !ruby/object:Gem::Requirement
109
+ requirements:
110
+ - - ">="
111
+ - !ruby/object:Gem::Version
112
+ version: '0'
113
+ requirements: []
114
+ rubyforge_project:
115
+ rubygems_version: 2.4.8
116
+ signing_key:
117
+ specification_version: 4
118
+ summary: First Data Latvia gateway for Active Merchant
119
+ test_files: []