sac_active_merchant_first_data 1.3.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -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: []