activemerchant 1.56.0 → 1.66.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (113) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG +331 -0
  3. data/README.md +9 -9
  4. data/lib/active_merchant/billing/check.rb +3 -0
  5. data/lib/active_merchant/billing/credit_card.rb +8 -3
  6. data/lib/active_merchant/billing/credit_card_methods.rb +41 -1
  7. data/lib/active_merchant/billing/gateway.rb +14 -6
  8. data/lib/active_merchant/billing/gateways/adyen.rb +228 -0
  9. data/lib/active_merchant/billing/gateways/authorize_net.rb +157 -44
  10. data/lib/active_merchant/billing/gateways/authorize_net_cim.rb +7 -4
  11. data/lib/active_merchant/billing/gateways/barclaycard_smartpay.rb +283 -0
  12. data/lib/active_merchant/billing/gateways/beanstream/beanstream_core.rb +68 -2
  13. data/lib/active_merchant/billing/gateways/blue_pay.rb +2 -2
  14. data/lib/active_merchant/billing/gateways/blue_snap.rb +348 -0
  15. data/lib/active_merchant/billing/gateways/bpoint.rb +1 -1
  16. data/lib/active_merchant/billing/gateways/braintree_blue.rb +58 -20
  17. data/lib/active_merchant/billing/gateways/bridge_pay.rb +37 -8
  18. data/lib/active_merchant/billing/gateways/card_stream.rb +161 -40
  19. data/lib/active_merchant/billing/gateways/cashnet.rb +1 -0
  20. data/lib/active_merchant/billing/gateways/checkout_v2.rb +5 -2
  21. data/lib/active_merchant/billing/gateways/citrus_pay.rb +24 -0
  22. data/lib/active_merchant/billing/gateways/clearhaus.rb +24 -40
  23. data/lib/active_merchant/billing/gateways/conekta.rb +6 -1
  24. data/lib/active_merchant/billing/gateways/creditcall.rb +1 -1
  25. data/lib/active_merchant/billing/gateways/credorax.rb +310 -0
  26. data/lib/active_merchant/billing/gateways/culqi.rb +279 -0
  27. data/lib/active_merchant/billing/gateways/cyber_source.rb +80 -64
  28. data/lib/active_merchant/billing/gateways/data_cash.rb +10 -304
  29. data/lib/active_merchant/billing/gateways/digitzs.rb +292 -0
  30. data/lib/active_merchant/billing/gateways/elavon.rb +40 -26
  31. data/lib/active_merchant/billing/gateways/element.rb +356 -0
  32. data/lib/active_merchant/billing/gateways/fat_zebra.rb +16 -2
  33. data/lib/active_merchant/billing/gateways/firstdata_e4.rb +6 -1
  34. data/lib/active_merchant/billing/gateways/forte.rb +10 -2
  35. data/lib/active_merchant/billing/gateways/global_collect.rb +311 -0
  36. data/lib/active_merchant/billing/gateways/global_transport.rb +1 -0
  37. data/lib/active_merchant/billing/gateways/iats_payments.rb +13 -0
  38. data/lib/active_merchant/billing/gateways/in_context_paypal_express.rb +15 -0
  39. data/lib/active_merchant/billing/gateways/iveri.rb +251 -0
  40. data/lib/active_merchant/billing/gateways/jetpay.rb +33 -19
  41. data/lib/active_merchant/billing/gateways/kushki.rb +217 -0
  42. data/lib/active_merchant/billing/gateways/latitude19.rb +416 -0
  43. data/lib/active_merchant/billing/gateways/linkpoint.rb +2 -0
  44. data/lib/active_merchant/billing/gateways/litle.rb +29 -13
  45. data/lib/active_merchant/billing/gateways/mastercard.rb +268 -0
  46. data/lib/active_merchant/billing/gateways/maxipago.rb +145 -122
  47. data/lib/active_merchant/billing/gateways/merchant_e_solutions.rb +15 -1
  48. data/lib/active_merchant/billing/gateways/merchant_warrior.rb +10 -7
  49. data/lib/active_merchant/billing/gateways/mercury.rb +13 -5
  50. data/lib/active_merchant/billing/gateways/metrics_global.rb +1 -1
  51. data/lib/active_merchant/billing/gateways/migs.rb +23 -1
  52. data/lib/active_merchant/billing/gateways/monei.rb +1 -1
  53. data/lib/active_merchant/billing/gateways/moneris.rb +21 -1
  54. data/lib/active_merchant/billing/gateways/nab_transact.rb +12 -0
  55. data/lib/active_merchant/billing/gateways/ncr_secure_pay.rb +165 -0
  56. data/lib/active_merchant/billing/gateways/netbanx.rb +245 -0
  57. data/lib/active_merchant/billing/gateways/nmi.rb +30 -9
  58. data/lib/active_merchant/billing/gateways/omise.rb +9 -5
  59. data/lib/active_merchant/billing/gateways/openpay.rb +10 -1
  60. data/lib/active_merchant/billing/gateways/opp.rb +362 -0
  61. data/lib/active_merchant/billing/gateways/orbital.rb +28 -7
  62. data/lib/active_merchant/billing/gateways/pagarme.rb +248 -0
  63. data/lib/active_merchant/billing/gateways/pay_junction_v2.rb +190 -0
  64. data/lib/active_merchant/billing/gateways/payeezy.rb +61 -12
  65. data/lib/active_merchant/billing/gateways/payflow/payflow_common_api.rb +1 -1
  66. data/lib/active_merchant/billing/gateways/payflow.rb +6 -0
  67. data/lib/active_merchant/billing/gateways/payment_express.rb +1 -1
  68. data/lib/active_merchant/billing/gateways/paymill.rb +29 -11
  69. data/lib/active_merchant/billing/gateways/paypal/paypal_common_api.rb +1 -1
  70. data/lib/active_merchant/billing/gateways/paypal_express.rb +1 -6
  71. data/lib/active_merchant/billing/gateways/payu_in.rb +3 -2
  72. data/lib/active_merchant/billing/gateways/payu_latam.rb +402 -0
  73. data/lib/active_merchant/billing/gateways/pin.rb +6 -3
  74. data/lib/active_merchant/billing/gateways/pro_pay.rb +326 -0
  75. data/lib/active_merchant/billing/gateways/psl_card.rb +3 -3
  76. data/lib/active_merchant/billing/gateways/quickpay/quickpay_common.rb +1 -1
  77. data/lib/active_merchant/billing/gateways/quickpay/quickpay_v10.rb +0 -2
  78. data/lib/active_merchant/billing/gateways/quickpay/quickpay_v4to7.rb +1 -1
  79. data/lib/active_merchant/billing/gateways/quickpay.rb +3 -3
  80. data/lib/active_merchant/billing/gateways/qvalent.rb +44 -1
  81. data/lib/active_merchant/billing/gateways/redsys.rb +3 -0
  82. data/lib/active_merchant/billing/gateways/s5.rb +8 -5
  83. data/lib/active_merchant/billing/gateways/safe_charge.rb +220 -0
  84. data/lib/active_merchant/billing/gateways/sage.rb +397 -128
  85. data/lib/active_merchant/billing/gateways/sage_pay.rb +45 -20
  86. data/lib/active_merchant/billing/gateways/secure_net.rb +0 -5
  87. data/lib/active_merchant/billing/gateways/secure_pay.rb +1 -1
  88. data/lib/active_merchant/billing/gateways/secure_pay_au.rb +12 -0
  89. data/lib/active_merchant/billing/gateways/securion_pay.rb +46 -17
  90. data/lib/active_merchant/billing/gateways/stripe.rb +125 -29
  91. data/lib/active_merchant/billing/gateways/telr.rb +275 -0
  92. data/lib/active_merchant/billing/gateways/tns.rb +13 -222
  93. data/lib/active_merchant/billing/gateways/trans_first.rb +40 -16
  94. data/lib/active_merchant/billing/gateways/trans_first_transaction_express.rb +606 -0
  95. data/lib/active_merchant/billing/gateways/usa_epay_advanced.rb +114 -9
  96. data/lib/active_merchant/billing/gateways/vanco.rb +14 -10
  97. data/lib/active_merchant/billing/gateways/visanet_peru.rb +209 -0
  98. data/lib/active_merchant/billing/gateways/wepay.rb +73 -38
  99. data/lib/active_merchant/billing/gateways/wirecard.rb +1 -0
  100. data/lib/active_merchant/billing/gateways/world_net.rb +344 -0
  101. data/lib/active_merchant/billing/gateways/worldpay.rb +48 -16
  102. data/lib/active_merchant/billing/network_tokenization_credit_card.rb +15 -0
  103. data/lib/active_merchant/country.rb +6 -4
  104. data/lib/active_merchant/posts_data.rb +1 -1
  105. data/lib/active_merchant/version.rb +1 -1
  106. metadata +32 -13
  107. data/lib/active_merchant/billing/gateways/app55.rb +0 -176
  108. data/lib/active_merchant/billing/gateways/barclays_epdq.rb +0 -314
  109. data/lib/active_merchant/billing/gateways/certo_direct.rb +0 -278
  110. data/lib/active_merchant/billing/gateways/sage/sage_bankcard.rb +0 -89
  111. data/lib/active_merchant/billing/gateways/sage/sage_core.rb +0 -115
  112. data/lib/active_merchant/billing/gateways/sage/sage_vault.rb +0 -149
  113. data/lib/active_merchant/billing/gateways/sage/sage_virtual_check.rb +0 -97
@@ -0,0 +1,275 @@
1
+ require 'nokogiri'
2
+
3
+ module ActiveMerchant #:nodoc:
4
+ module Billing #:nodoc:
5
+ class TelrGateway < Gateway
6
+ self.display_name = "Telr"
7
+ self.homepage_url = "http://www.telr.com/"
8
+
9
+ self.live_url = "https://secure.telr.com/gateway/remote.xml"
10
+
11
+ self.supported_countries = ["AE", "IN", "SA"]
12
+ self.default_currency = "AED"
13
+ self.money_format = :dollars
14
+ self.supported_cardtypes = [:visa, :master, :american_express, :maestro, :solo, :jcb]
15
+
16
+ CVC_CODE_TRANSLATOR = {
17
+ 'Y' => 'M',
18
+ 'N' => 'N',
19
+ 'X' => 'P',
20
+ 'E' => 'U',
21
+ }
22
+
23
+ AVS_CODE_TRANSLATOR = {
24
+ 'Y' => 'M',
25
+ 'P' => 'A',
26
+ 'N' => 'N',
27
+ 'X' => 'I',
28
+ 'E' => 'R'
29
+ }
30
+
31
+ def initialize(options={})
32
+ requires!(options, :merchant_id, :api_key)
33
+ super
34
+ end
35
+
36
+ def purchase(amount, payment_method, options={})
37
+ commit(:purchase, amount, options[:currency]) do |doc|
38
+ add_invoice(doc, "sale", amount, payment_method, options)
39
+ add_payment_method(doc, payment_method, options)
40
+ add_customer_data(doc, payment_method, options)
41
+ end
42
+ end
43
+
44
+ def authorize(amount, payment_method, options={})
45
+ commit(:authorize, amount, options[:currency]) do |doc|
46
+ add_invoice(doc, "auth", amount, payment_method, options)
47
+ add_payment_method(doc, payment_method, options)
48
+ add_customer_data(doc, payment_method, options)
49
+ end
50
+ end
51
+
52
+ def capture(amount, authorization, options={})
53
+ commit(:capture) do |doc|
54
+ add_invoice(doc, "capture", amount, authorization, options)
55
+ end
56
+ end
57
+
58
+ def void(authorization, options={})
59
+ _, amount, currency = split_authorization(authorization)
60
+ commit(:void) do |doc|
61
+ add_invoice(doc, "void", amount.to_i, authorization, options.merge(currency: currency))
62
+ end
63
+ end
64
+
65
+ def refund(amount, authorization, options={})
66
+ commit(:refund) do |doc|
67
+ add_invoice(doc, "refund", amount, authorization, options)
68
+ end
69
+ end
70
+
71
+ def verify(credit_card, options={})
72
+ commit(:verify) do |doc|
73
+ add_invoice(doc, "verify", 100, credit_card, options)
74
+ add_payment_method(doc, credit_card, options)
75
+ add_customer_data(doc, credit_card, options)
76
+ end
77
+ end
78
+
79
+ def verify_credentials
80
+ response = void("0")
81
+ !["01", "04"].include?(response.error_code)
82
+ end
83
+
84
+ def supports_scrubbing?
85
+ true
86
+ end
87
+
88
+ def scrub(transcript)
89
+ transcript.
90
+ gsub(%r((<Number>)[^<]+(<))i, '\1[FILTERED]\2').
91
+ gsub(%r((<CVV>)[^<]+(<))i, '\1[FILTERED]\2').
92
+ gsub(%r((<Key>)[^<]+(<))i, '\1[FILTERED]\2')
93
+ end
94
+
95
+ private
96
+
97
+ def add_invoice(doc, action, money, payment_method, options)
98
+ doc.tran do
99
+ doc.type(action)
100
+ doc.amount(amount(money))
101
+ doc.currency(options[:currency] || currency(money))
102
+ doc.cartid(options[:order_id])
103
+ doc.class_(transaction_class(action, payment_method))
104
+ doc.description(options[:description] || "Description")
105
+ doc.test_(test_mode)
106
+ add_ref(doc, action, payment_method)
107
+ end
108
+ end
109
+
110
+ def add_payment_method(doc, payment_method, options)
111
+ return if payment_method.is_a?(String)
112
+ doc.card do
113
+ doc.number(payment_method.number)
114
+ doc.cvv(payment_method.verification_value)
115
+ doc.expiry do
116
+ doc.month(format(payment_method.month, :two_digits))
117
+ doc.year(format(payment_method.year, :four_digits))
118
+ end
119
+ end
120
+ end
121
+
122
+ def add_customer_data(doc, payment_method, options)
123
+ return if payment_method.is_a?(String)
124
+ doc.billing do
125
+ doc.name do
126
+ doc.first(payment_method.first_name)
127
+ doc.last(payment_method.last_name)
128
+ end
129
+ doc.email(options[:email] || "unspecified@email.com")
130
+ doc.ip(options[:ip]) if options[:ip]
131
+ doc.address do
132
+ add_address(doc, options)
133
+ end
134
+ end
135
+ end
136
+
137
+ def add_address(doc, options)
138
+ address = options[:billing_address] || {}
139
+ doc.country(address[:country] ? lookup_country_code(address[:country]) : "NA")
140
+ doc.city(address[:city] || "City")
141
+ doc.line1(address[:address1] || "Address")
142
+ return unless address
143
+ doc.line2(address[:address2]) if address[:address2]
144
+ doc.zip(address[:zip]) if address[:zip]
145
+ doc.region(address[:state]) if address[:state]
146
+ end
147
+
148
+ def add_ref(doc, action, payment_method)
149
+ if ["capture", "refund", "void"].include?(action) || payment_method.is_a?(String)
150
+ doc.ref(split_authorization(payment_method)[0])
151
+ end
152
+ end
153
+
154
+ def add_authentication(doc)
155
+ doc.store(@options[:merchant_id])
156
+ doc.key(@options[:api_key])
157
+ end
158
+
159
+ def lookup_country_code(code)
160
+ country = Country.find(code) rescue nil
161
+ country.code(:alpha2)
162
+ end
163
+
164
+ def commit(action, amount=nil, currency=nil)
165
+ currency = default_currency if currency == nil
166
+ request = build_xml_request { |doc| yield(doc) }
167
+ response = ssl_post(live_url, request, headers)
168
+ parsed = parse(response)
169
+
170
+ succeeded = success_from(parsed)
171
+ Response.new(
172
+ succeeded,
173
+ message_from(succeeded, parsed),
174
+ parsed,
175
+ authorization: authorization_from(action, parsed, amount, currency),
176
+ avs_result: avs_result(parsed),
177
+ cvv_result: cvv_result(parsed),
178
+ error_code: error_code_from(succeeded, parsed),
179
+ test: test?
180
+ )
181
+ end
182
+
183
+ def root_attributes
184
+ {
185
+ store: @options[:merchant_id],
186
+ key: @options[:api_key]
187
+ }
188
+ end
189
+
190
+ def build_xml_request
191
+ builder = Nokogiri::XML::Builder.new(encoding: 'UTF-8') do |xml|
192
+ xml.remote do |doc|
193
+
194
+ add_authentication(doc)
195
+ yield(doc)
196
+ end
197
+ end
198
+
199
+ builder.doc.to_xml
200
+ end
201
+
202
+ def test_mode
203
+ test? ? '1' : '0'
204
+ end
205
+
206
+ def transaction_class(action, payment_method)
207
+ if payment_method.is_a?(String) && action == "sale"
208
+ return "cont"
209
+ else
210
+ return "moto"
211
+ end
212
+ end
213
+
214
+ def parse(xml)
215
+ response = {}
216
+
217
+ doc = Nokogiri::XML(xml)
218
+ doc.root.xpath("*").each do |node|
219
+ if (node.elements.size == 0)
220
+ response[node.name.downcase.to_sym] = node.text
221
+ else
222
+ node.elements.each do |childnode|
223
+ name = "#{childnode.name.downcase}"
224
+ response[name.to_sym] = childnode.text
225
+ end
226
+ end
227
+ end unless doc.root.nil?
228
+
229
+ response
230
+ end
231
+
232
+ def authorization_from(action, response, amount, currency)
233
+ auth = response[:tranref]
234
+ auth = [auth, amount, currency].join('|')
235
+ auth
236
+ end
237
+
238
+ def split_authorization(authorization)
239
+ authorization.split('|')
240
+ end
241
+
242
+ def success_from(response)
243
+ response[:status] == "A"
244
+ end
245
+
246
+ def message_from(succeeded, response)
247
+ if succeeded
248
+ "Succeeded"
249
+ else
250
+ response[:message]
251
+ end
252
+ end
253
+
254
+ def error_code_from(succeeded, response)
255
+ unless succeeded
256
+ response[:code]
257
+ end
258
+ end
259
+
260
+ def cvv_result(parsed)
261
+ CVVResult.new(CVC_CODE_TRANSLATOR[parsed[:cvv]])
262
+ end
263
+
264
+ def avs_result(parsed)
265
+ AVSResult.new(code: AVS_CODE_TRANSLATOR[parsed[:avs]])
266
+ end
267
+
268
+ def headers
269
+ {
270
+ "Content-Type" => "text/xml"
271
+ }
272
+ end
273
+ end
274
+ end
275
+ end
@@ -1,232 +1,23 @@
1
- module ActiveMerchant #:nodoc:
2
- module Billing #:nodoc:
1
+ module ActiveMerchant
2
+ module Billing
3
3
  class TnsGateway < Gateway
4
- self.display_name = 'TNS'
5
- self.homepage_url = 'http://www.tnsi.com/'
4
+ include MastercardGateway
6
5
 
7
- # Testing is partitioned by account.
8
- self.live_url = 'https://secure.na.tnspayments.com/api/rest/version/22/'
6
+ class_attribute :live_na_url, :live_ap_url, :test_na_url, :test_ap_url
9
7
 
10
- self.supported_countries = %w(AR AU BR FR DE HK MX NZ SG GB US)
8
+ self.live_na_url = 'https://secure.na.tnspayments.com/api/rest/version/36/'
9
+ self.test_na_url = 'https://secure.na.tnspayments.com/api/rest/version/36/'
11
10
 
11
+ self.live_ap_url = 'https://secure.ap.tnspayments.com/api/rest/version/36/'
12
+ self.test_ap_url = 'https://secure.ap.tnspayments.com/api/rest/version/36/'
13
+
14
+ self.display_name = 'TNS'
15
+ self.homepage_url = 'http://www.tnsi.com/'
16
+ self.supported_countries = %w(AR AU BR FR DE HK MX NZ SG GB US)
12
17
  self.default_currency = 'USD'
13
18
  self.supported_cardtypes = [:visa, :master, :american_express, :discover, :diners_club, :jcb, :maestro, :laser]
19
+ self.ssl_version = :TLSv1
14
20
 
15
- def initialize(options={})
16
- requires!(options, :userid, :password)
17
- super
18
- end
19
-
20
- def purchase(amount, payment_method, options={})
21
- MultiResponse.run do |r|
22
- r.process { authorize(amount, payment_method, options) }
23
- r.process { capture(amount, r.authorization, options) }
24
- end
25
- end
26
-
27
- def authorize(amount, payment_method, options={})
28
- post = new_post
29
- add_invoice(post, amount, options)
30
- add_reference(post, *new_authorization)
31
- add_payment_method(post, payment_method)
32
- add_customer_data(post, options)
33
-
34
- commit('authorize', post)
35
- end
36
-
37
- def capture(amount, authorization, options={})
38
- post = new_post
39
- add_invoice(post, amount, options, :transaction)
40
- add_reference(post, *next_authorization(authorization))
41
- add_customer_data(post, options)
42
-
43
- commit('capture', post)
44
- end
45
-
46
- def refund(amount, authorization, options={})
47
- post = new_post
48
- add_invoice(post, amount, options, :transaction)
49
- add_reference(post, *next_authorization(authorization))
50
- add_customer_data(post, options)
51
-
52
- commit('refund', post)
53
- end
54
-
55
- def void(authorization, options={})
56
- post = new_post
57
- add_reference(post, *next_authorization(authorization), :targetTransactionId)
58
-
59
- commit('void', post)
60
- end
61
-
62
- def verify(credit_card, options={})
63
- MultiResponse.run(:use_first_response) do |r|
64
- r.process { authorize(100, credit_card, options) }
65
- r.process(:ignore_result) { void(r.authorization, options) }
66
- end
67
- end
68
-
69
- private
70
-
71
- def new_post
72
- {
73
- order: {},
74
- sourceOfFunds: {
75
- provided: {
76
- card: {
77
- }
78
- }
79
- },
80
- customer: {},
81
- billing: {},
82
- shipping: {},
83
- transaction: {},
84
- }
85
- end
86
-
87
- def add_invoice(post, amount, options, node=:order)
88
- post[node][:amount] = amount(amount)
89
- post[node][:currency] = (options[:currency] || currency(amount))
90
- end
91
-
92
- def add_reference(post, orderid, transactionid, transaction_reference, reference_key=:reference)
93
- post[:orderid] = orderid
94
- post[:transactionid] = transactionid
95
- post[:transaction][reference_key] = transaction_reference if transaction_reference
96
- end
97
-
98
- def add_payment_method(post, payment_method)
99
- card = {}
100
- card[:expiry] = {}
101
- card[:number] = payment_method.number
102
- card[:securityCode] = payment_method.verification_value
103
- card[:expiry][:year] = format(payment_method.year, :two_digits)
104
- card[:expiry][:month] = format(payment_method.month, :two_digits)
105
-
106
- post[:sourceOfFunds][:type] = 'CARD'
107
- post[:sourceOfFunds][:provided][:card].merge!(card)
108
- end
109
-
110
- def add_customer_data(post, options)
111
- billing = {}
112
- shipping = {}
113
- customer = {}
114
- if(billing_address = (options[:billing_address] || options[:address]))
115
- billing[:address] = {}
116
- billing[:address][:street] = billing_address[:address1]
117
- billing[:address][:street2] = billing_address[:address2]
118
- billing[:address][:city] = billing_address[:city]
119
- billing[:address][:stateProvince] = billing_address[:state]
120
- billing[:address][:postcodeZip] = billing_address[:zip]
121
- billing[:address][:country] = country_code(billing_address[:country])
122
- billing[:phone] = billing_address[:phone]
123
-
124
- customer[:email] = options[:email] if options[:email]
125
- customer[:ipaddress] = options[:ip] if options[:ip]
126
- end
127
-
128
- if(shipping_address = options[:shipping_address])
129
- shipping[:address] = {}
130
- shipping[:address][:street] = shipping_address[:address1]
131
- shipping[:address][:street2] = shipping_address[:address2]
132
- shipping[:address][:city] = shipping_address[:city]
133
- shipping[:address][:stateProvince] = shipping_address[:state]
134
- shipping[:address][:postcodeZip] = shipping_address[:zip]
135
- shipping[:address][:shipcountry] = country_code(shipping_address[:country])
136
-
137
- first_name, last_name = split_names(shipping_address[:name])
138
- shipping[:firstName] = first_name if first_name
139
- shipping[:lastName] = last_name if last_name
140
- end
141
- post[:billing].merge!(billing)
142
- post[:shipping].merge!(shipping)
143
- post[:customer].merge!(customer)
144
- end
145
-
146
- def country_code(country)
147
- if country
148
- country = ActiveMerchant::Country.find(country)
149
- country.code(:alpha3).value
150
- end
151
- rescue InvalidCountryCodeError
152
- end
153
-
154
- def commit(action, post)
155
- url = build_url(post.delete(:orderid), post.delete(:transactionid))
156
- headers = {
157
- 'Authorization' => 'Basic ' + Base64.encode64("merchant.#{@options[:userid]}:#{@options[:password]}").strip.delete("\r\n"),
158
- 'Content-Type' => 'application/json',
159
- }
160
- post[:apiOperation] = action.upcase
161
- begin
162
- raw = parse(ssl_request(:put, url, build_request(post), headers))
163
- rescue ResponseError => e
164
- raw = parse(e.response.body)
165
- end
166
- succeeded = success_from(raw['result'])
167
- Response.new(
168
- succeeded,
169
- message_from(succeeded, raw),
170
- raw,
171
- :authorization => authorization_from(post, raw),
172
- :test => test?
173
- )
174
- end
175
-
176
- def build_url(orderid, transactionid)
177
- "#{live_url}merchant/#{@options[:userid]}/order/#{orderid}/transaction/#{transactionid}"
178
- end
179
-
180
- def build_request(post = {})
181
- post.to_json
182
- end
183
-
184
- def parse(body)
185
- JSON.parse(body)
186
- end
187
-
188
- def success_from(response)
189
- response == 'SUCCESS'
190
- end
191
-
192
- def message_from(succeeded, response)
193
- if succeeded
194
- 'Succeeded'
195
- else
196
- [
197
- response['result'],
198
- response['response'] && response['response']['gatewayCode'],
199
- response['error'] && response['error']['cause'],
200
- response['error'] && response['error']['explanation']
201
- ].compact.join(' - ')
202
- end
203
- end
204
-
205
- def authorization_from(request, response)
206
- [response['order']['id'], response['transaction']['id']].join('|') if response['order']
207
- end
208
-
209
- def split_authorization(authorization)
210
- authorization.split('|')
211
- end
212
-
213
- def new_authorization
214
- # Must be unique within a merchant id.
215
- orderid = SecureRandom.uuid
216
-
217
- # Must be unique within an order id.
218
- transactionid = '1'
219
-
220
- # New transactions have no previous reference.
221
- transaction_reference = nil
222
- [orderid, transactionid, transaction_reference]
223
- end
224
-
225
- def next_authorization(authorization)
226
- orderid, prev_transactionid = split_authorization(authorization)
227
- next_transactionid = SecureRandom.uuid
228
- [orderid, next_transactionid, prev_transactionid]
229
- end
230
21
  end
231
22
  end
232
23
  end
@@ -9,7 +9,7 @@ module ActiveMerchant #:nodoc:
9
9
  self.homepage_url = 'http://www.transfirst.com/'
10
10
  self.display_name = 'TransFirst'
11
11
 
12
- UNUSED_FIELDS = %w(ECIValue UserId CAVVData TrackData POSInd EComInd MerchZIP MerchCustPNum MCC InstallmentNum InstallmentOf POSEntryMode POSConditionCode AuthCharInd CardCertData)
12
+ UNUSED_CREDIT_CARD_FIELDS = %w(UserId TrackData MerchZIP MerchCustPNum MCC InstallmentNum InstallmentOf POSInd POSEntryMode POSConditionCode EComInd AuthCharInd CardCertData CAVVData)
13
13
 
14
14
  DECLINED = 'The transaction was declined'
15
15
 
@@ -38,30 +38,46 @@ module ActiveMerchant #:nodoc:
38
38
  post = {}
39
39
 
40
40
  add_amount(post, money)
41
- add_invoice(post, options)
42
41
  add_payment(post, payment)
43
42
  add_address(post, options)
43
+ add_invoice(post, options) if payment.credit_card?
44
+ add_pair(post, :RefID, options[:order_id], required: true)
44
45
 
45
46
  commit((payment.is_a?(Check) ? :purchase_echeck : :purchase), post)
46
47
  end
47
48
 
48
49
  def refund(money, authorization, options={})
49
50
  post = {}
51
+
50
52
  transaction_id, payment_type = split_authorization(authorization)
51
53
  add_amount(post, money)
52
- add_invoice(post, options)
53
54
  add_pair(post, :TransID, transaction_id)
55
+
54
56
  commit((payment_type == "check" ? :refund_echeck : :refund), post)
55
57
  end
56
58
 
57
59
  def void(authorization, options={})
58
60
  post = {}
61
+
59
62
  transaction_id, _ = split_authorization(authorization)
60
63
  add_pair(post, :TransID, transaction_id)
61
64
 
62
65
  commit(:void, post)
63
66
  end
64
67
 
68
+ def supports_scrubbing?
69
+ true
70
+ end
71
+
72
+ def scrub(transcript)
73
+ transcript.
74
+ gsub(%r((&?RegKey=)\w*(&?)), '\1[FILTERED]\2').
75
+ gsub(%r((&?CardNumber=)\d*(&?)), '\1[FILTERED]\2').
76
+ gsub(%r((&?CVV2=)\d*(&?)), '\1[FILTERED]\2').
77
+ gsub(%r((&?TransRoute=)\d*(&?)), '\1[FILTERED]\2').
78
+ gsub(%r((&?BankAccountNo=)\d*(&?)), '\1[FILTERED]\2')
79
+ end
80
+
65
81
  private
66
82
 
67
83
  def add_amount(post, money)
@@ -72,18 +88,20 @@ module ActiveMerchant #:nodoc:
72
88
  address = options[:billing_address] || options[:address]
73
89
 
74
90
  if address
75
- add_pair(post, :Address, address[:address1])
76
- add_pair(post, :ZipCode, address[:zip])
91
+ add_pair(post, :Address, address[:address1], required: true)
92
+ add_pair(post, :ZipCode, address[:zip], required: true)
93
+ else
94
+ add_pair(post, :Address, "", required: true)
95
+ add_pair(post, :ZipCode, "", required: true)
77
96
  end
78
97
  end
79
98
 
80
99
  def add_invoice(post, options)
81
- add_pair(post, :RefID, options[:order_id], required: true)
82
100
  add_pair(post, :SECCCode, options[:invoice], required: true)
83
101
  add_pair(post, :PONumber, options[:invoice], required: true)
84
102
  add_pair(post, :SaleTaxAmount, amount(options[:tax] || 0))
85
- add_pair(post, :PaymentDesc, options[:description], required: true)
86
103
  add_pair(post, :TaxIndicator, 0)
104
+ add_pair(post, :PaymentDesc, options[:description] || "", required: true)
87
105
  add_pair(post, :CompanyName, options[:company_name] || "", required: true)
88
106
  end
89
107
 
@@ -99,21 +117,28 @@ module ActiveMerchant #:nodoc:
99
117
  add_pair(post, :CardHolderName, payment.name, required: true)
100
118
  add_pair(post, :CardNumber, payment.number, required: true)
101
119
  add_pair(post, :Expiration, expdate(payment), required: true)
102
- add_pair(post, :CVV2, payment.verification_value)
120
+ add_pair(post, :CVV2, payment.verification_value, required: true)
103
121
  end
104
122
 
105
123
  def add_echeck(post, payment)
106
124
  add_pair(post, :TransRoute, payment.routing_number, required: true)
107
125
  add_pair(post, :BankAccountNo, payment.account_number, required: true)
108
- add_pair(post, :BankAccountType, payment.account_type.capitalize, required: true)
109
- add_pair(post, :CheckType, payment.account_holder_type.capitalize, required: true)
126
+ add_pair(post, :BankAccountType, add_or_use_default(payment.account_type, "Checking"), required: true)
127
+ add_pair(post, :CheckType, add_or_use_default(payment.account_holder_type, "Personal"), required: true)
110
128
  add_pair(post, :Name, payment.name, required: true)
111
129
  add_pair(post, :ProcessDate, Time.now.strftime("%m%d%y"), required: true)
112
130
  add_pair(post, :Description, "", required: true)
113
131
  end
114
132
 
115
- def add_unused_fields(post)
116
- UNUSED_FIELDS.each do |f|
133
+ def add_or_use_default(payment_data, default_value)
134
+ return payment_data.capitalize if payment_data
135
+ return default_value
136
+ end
137
+
138
+ def add_unused_fields(action, post)
139
+ return unless action == :purchase
140
+
141
+ UNUSED_CREDIT_CARD_FIELDS.each do |f|
117
142
  post[f] = ""
118
143
  end
119
144
  end
@@ -143,7 +168,7 @@ module ActiveMerchant #:nodoc:
143
168
  end
144
169
 
145
170
  def commit(action, params)
146
- response = parse(ssl_post(url(action), post_data(params)))
171
+ response = parse(ssl_post(url(action), post_data(action, params)))
147
172
 
148
173
  Response.new(
149
174
  success_from(response),
@@ -188,8 +213,8 @@ module ActiveMerchant #:nodoc:
188
213
  end
189
214
  end
190
215
 
191
- def post_data(params = {})
192
- add_unused_fields(params)
216
+ def post_data(action, params = {})
217
+ add_unused_fields(action, params)
193
218
  params[:MerchantID] = @options[:login]
194
219
  params[:RegKey] = @options[:password]
195
220
 
@@ -212,4 +237,3 @@ module ActiveMerchant #:nodoc:
212
237
  end
213
238
  end
214
239
  end
215
-