activemerchant 1.123.0 → 1.125.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.
Files changed (48) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG +131 -0
  3. data/lib/active_merchant/billing/check.rb +5 -8
  4. data/lib/active_merchant/billing/credit_card.rb +10 -0
  5. data/lib/active_merchant/billing/credit_card_methods.rb +6 -3
  6. data/lib/active_merchant/billing/gateway.rb +1 -1
  7. data/lib/active_merchant/billing/gateways/adyen.rb +61 -9
  8. data/lib/active_merchant/billing/gateways/card_stream.rb +17 -13
  9. data/lib/active_merchant/billing/gateways/cashnet.rb +15 -5
  10. data/lib/active_merchant/billing/gateways/checkout_v2.rb +33 -4
  11. data/lib/active_merchant/billing/gateways/cyber_source.rb +11 -3
  12. data/lib/active_merchant/billing/gateways/d_local.rb +12 -6
  13. data/lib/active_merchant/billing/gateways/decidir_plus.rb +173 -0
  14. data/lib/active_merchant/billing/gateways/ebanx.rb +16 -1
  15. data/lib/active_merchant/billing/gateways/elavon.rb +6 -3
  16. data/lib/active_merchant/billing/gateways/element.rb +20 -2
  17. data/lib/active_merchant/billing/gateways/global_collect.rb +111 -16
  18. data/lib/active_merchant/billing/gateways/ipg.rb +416 -0
  19. data/lib/active_merchant/billing/gateways/kushki.rb +7 -0
  20. data/lib/active_merchant/billing/gateways/mercado_pago.rb +3 -1
  21. data/lib/active_merchant/billing/gateways/mit.rb +260 -0
  22. data/lib/active_merchant/billing/gateways/moka.rb +24 -11
  23. data/lib/active_merchant/billing/gateways/mundipagg.rb +8 -6
  24. data/lib/active_merchant/billing/gateways/nmi.rb +15 -1
  25. data/lib/active_merchant/billing/gateways/orbital.rb +19 -3
  26. data/lib/active_merchant/billing/gateways/pay_arc.rb +9 -7
  27. data/lib/active_merchant/billing/gateways/pay_conex.rb +3 -1
  28. data/lib/active_merchant/billing/gateways/pay_trace.rb +1 -1
  29. data/lib/active_merchant/billing/gateways/payflow.rb +14 -6
  30. data/lib/active_merchant/billing/gateways/paymentez.rb +9 -2
  31. data/lib/active_merchant/billing/gateways/paysafe.rb +144 -23
  32. data/lib/active_merchant/billing/gateways/payu_latam.rb +6 -1
  33. data/lib/active_merchant/billing/gateways/payway_dot_com.rb +3 -3
  34. data/lib/active_merchant/billing/gateways/pin.rb +31 -4
  35. data/lib/active_merchant/billing/gateways/priority.rb +347 -0
  36. data/lib/active_merchant/billing/gateways/realex.rb +18 -0
  37. data/lib/active_merchant/billing/gateways/safe_charge.rb +6 -2
  38. data/lib/active_merchant/billing/gateways/stripe.rb +27 -7
  39. data/lib/active_merchant/billing/gateways/stripe_payment_intents.rb +96 -38
  40. data/lib/active_merchant/billing/gateways/trans_first_transaction_express.rb +2 -1
  41. data/lib/active_merchant/billing/gateways/trust_commerce.rb +2 -1
  42. data/lib/active_merchant/billing/gateways/usa_epay_transaction.rb +20 -6
  43. data/lib/active_merchant/billing/gateways/wompi.rb +193 -0
  44. data/lib/active_merchant/billing/gateways/worldpay.rb +196 -64
  45. data/lib/active_merchant/billing/network_tokenization_credit_card.rb +1 -1
  46. data/lib/active_merchant/billing/response.rb +4 -0
  47. data/lib/active_merchant/version.rb +1 -1
  48. metadata +7 -2
@@ -0,0 +1,416 @@
1
+ module ActiveMerchant #:nodoc:
2
+ module Billing #:nodoc:
3
+ class IpgGateway < Gateway
4
+ self.test_url = 'https://test.ipg-online.com/ipgapi/services'
5
+ self.live_url = 'https://www5.ipg-online.com'
6
+
7
+ self.supported_countries = %w(UY AR)
8
+ self.default_currency = 'ARS'
9
+ self.supported_cardtypes = %i[visa master american_express discover]
10
+
11
+ self.homepage_url = 'https://www.ipg-online.com'
12
+ self.display_name = 'IPG'
13
+
14
+ CURRENCY_CODES = {
15
+ 'UYU' => '858',
16
+ 'ARS' => '032'
17
+ }
18
+
19
+ ACTION_REQUEST_ITEMS = %w(vault unstore)
20
+
21
+ def initialize(options = {})
22
+ requires!(options, :store_id, :user_id, :password, :pem, :pem_password)
23
+ @credentials = options
24
+ @hosted_data_id = nil
25
+ super
26
+ end
27
+
28
+ def purchase(money, payment, options = {})
29
+ xml = build_purchase_and_authorize_request(money, payment, options)
30
+
31
+ commit('sale', xml)
32
+ end
33
+
34
+ def authorize(money, payment, options = {})
35
+ xml = build_purchase_and_authorize_request(money, payment, options)
36
+
37
+ commit('preAuth', xml)
38
+ end
39
+
40
+ def capture(money, authorization, options = {})
41
+ xml = build_capture_and_refund_request(money, authorization, options)
42
+
43
+ commit('postAuth', xml)
44
+ end
45
+
46
+ def refund(money, authorization, options = {})
47
+ xml = build_capture_and_refund_request(money, authorization, options)
48
+
49
+ commit('return', xml)
50
+ end
51
+
52
+ def void(authorization, options = {})
53
+ xml = Builder::XmlMarkup.new(indent: 2)
54
+ add_transaction_details(xml, options.merge!({ order_id: authorization }))
55
+
56
+ commit('void', xml)
57
+ end
58
+
59
+ def store(credit_card, options = {})
60
+ @hosted_data_id = options[:hosted_data_id] || generate_unique_id
61
+ xml = Builder::XmlMarkup.new(indent: 2)
62
+ add_storage_item(xml, credit_card, options)
63
+
64
+ commit('vault', xml)
65
+ end
66
+
67
+ def unstore(hosted_data_id)
68
+ xml = Builder::XmlMarkup.new(indent: 2)
69
+ add_unstore_item(xml, hosted_data_id)
70
+
71
+ commit('unstore', xml)
72
+ end
73
+
74
+ def verify(credit_card, options = {})
75
+ options[:currency] = self.default_currency unless options[:currency] && !options[:currency].empty?
76
+ MultiResponse.run(:use_first_response) do |r|
77
+ r.process { authorize(100, credit_card, options) }
78
+ r.process(:ignore_result) { void(r.authorization, options) }
79
+ end
80
+ end
81
+
82
+ def supports_scrubbing?
83
+ true
84
+ end
85
+
86
+ def scrub(transcript)
87
+ transcript.
88
+ gsub(%r((Authorization: Basic )\w+), '\1[FILTERED]').
89
+ gsub(%r((<v1:CardNumber>).+(</v1:CardNumber>)), '\1[FILTERED]\2').
90
+ gsub(%r((<v1:CardCodeValue>).+(</v1:CardCodeValue>)), '\1[FILTERED]\2').
91
+ gsub(%r((<v1:StoreId>).+(</v1:StoreId>)), '\1[FILTERED]\2')
92
+ end
93
+
94
+ private
95
+
96
+ NAMESPACE_BASE_URL = 'http://ipg-online.com'
97
+
98
+ def build_purchase_and_authorize_request(money, payment, options)
99
+ xml = Builder::XmlMarkup.new(indent: 2)
100
+
101
+ add_credit_card(xml, payment, options)
102
+ add_sub_merchant(xml, options[:submerchant]) if options[:submerchant]
103
+ add_three_d_secure(xml, options[:three_d_secure]) if options[:three_d_secure]
104
+ add_stored_credentials(xml, options) if options[:stored_credential] || options[:recurring_type]
105
+ add_payment(xml, money, payment, options)
106
+ add_transaction_details(xml, options)
107
+ add_billing(xml, options[:billing]) if options[:billing]
108
+ add_shipping(xml, options[:shipping]) if options[:shipping]
109
+ xml
110
+ end
111
+
112
+ def build_capture_and_refund_request(money, authorization, options)
113
+ xml = Builder::XmlMarkup.new(indent: 2)
114
+ add_payment(xml, money, nil, options)
115
+ add_transaction_details(xml, options.merge!({ order_id: authorization }), true)
116
+ xml
117
+ end
118
+
119
+ def build_order_request(xml, action, body)
120
+ xml.tag!('ipg:IPGApiOrderRequest') do
121
+ xml.tag!('v1:Transaction') do
122
+ add_transaction_type(xml, action)
123
+ xml << body.target!
124
+ end
125
+ end
126
+ end
127
+
128
+ def build_action_request(xml, action, body)
129
+ xml.tag!('ns4:IPGApiActionRequest', ipg_action_namespaces) do
130
+ xml.tag!('ns2:Action') do
131
+ xml << body.target!
132
+ end
133
+ end
134
+ end
135
+
136
+ def build_soap_request(action, body)
137
+ xml = Builder::XmlMarkup.new(indent: 2)
138
+ xml.tag!('soapenv:Envelope', envelope_namespaces) do
139
+ xml.tag!('soapenv:Header')
140
+ xml.tag!('soapenv:Body') do
141
+ build_order_request(xml, action, body) unless ACTION_REQUEST_ITEMS.include?(action)
142
+ build_action_request(xml, action, body) if ACTION_REQUEST_ITEMS.include?(action)
143
+ end
144
+ end
145
+ xml.target!
146
+ end
147
+
148
+ def add_stored_credentials(xml, params)
149
+ recurring_type = params[:stored_credential][:initial_transaction] ? 'FIRST' : 'REPEAT' if params[:stored_credential]
150
+ recurring_type = params[:recurring_type] if params[:recurring_type]
151
+ xml.tag!('v1:recurringType', recurring_type)
152
+ end
153
+
154
+ def add_storage_item(xml, credit_card, options)
155
+ requires!(options.merge!({ credit_card: credit_card, hosted_data_id: @hosted_data_id }), :credit_card, :hosted_data_id)
156
+ xml.tag!('ns2:StoreHostedData') do
157
+ xml.tag!('ns2:DataStorageItem') do
158
+ add_credit_card(xml, credit_card, {}, 'ns2')
159
+ add_three_d_secure(xml, options[:three_d_secure]) if options[:three_d_secure]
160
+ xml.tag!('ns2:HostedDataID', @hosted_data_id) if @hosted_data_id
161
+ end
162
+ end
163
+ end
164
+
165
+ def add_unstore_item(xml, hosted_data_id)
166
+ requires!({}.merge!({ hosted_data_id: hosted_data_id }), :hosted_data_id)
167
+ xml.tag!('ns2:StoreHostedData') do
168
+ xml.tag!('ns2:DataStorageItem') do
169
+ xml.tag!('ns2:Function', 'delete')
170
+ xml.tag!('ns2:HostedDataID', hosted_data_id)
171
+ end
172
+ end
173
+ end
174
+
175
+ def add_transaction_type(xml, type)
176
+ xml.tag!('v1:CreditCardTxType') do
177
+ xml.tag!('v1:StoreId', @credentials[:store_id])
178
+ xml.tag!('v1:Type', type)
179
+ end
180
+ end
181
+
182
+ def add_credit_card(xml, payment, options = {}, credit_envelope = 'v1')
183
+ if payment&.is_a?(CreditCard)
184
+ requires!(options.merge!({ card_number: payment.number, month: payment.month, year: payment.year }), :card_number, :month, :year)
185
+
186
+ xml.tag!("#{credit_envelope}:CreditCardData") do
187
+ xml.tag!('v1:CardNumber', payment.number) if payment.number
188
+ xml.tag!('v1:ExpMonth', format(payment.month, :two_digits)) if payment.month
189
+ xml.tag!('v1:ExpYear', format(payment.year, :two_digits)) if payment.year
190
+ xml.tag!('v1:CardCodeValue', payment.verification_value) if payment.verification_value
191
+ xml.tag!('v1:Brand', options[:brand]) if options[:brand]
192
+ end
193
+ end
194
+
195
+ if options[:card_function_type]
196
+ xml.tag!('v1:cardFunction') do
197
+ xml.tag!('v1:Type', options[:card_function_type])
198
+ end
199
+ end
200
+
201
+ if options[:track_data]
202
+ xml.tag!("#{credit_envelope}:CreditCardData") do
203
+ xml.tag!('v1:TrackData', options[:track_data])
204
+ end
205
+ end
206
+ end
207
+
208
+ def add_sub_merchant(xml, submerchant)
209
+ xml.tag!('v1:SubMerchant') do
210
+ xml.tag!('v1:Mcc', submerchant[:mcc]) if submerchant[:mcc]
211
+ xml.tag!('v1:LegalName', submerchant[:legal_name]) if submerchant[:legal_name]
212
+ add_address(xml, submerchant[:address]) if submerchant[:address]
213
+ add_document(xml, submerchant[:document]) if submerchant[:document]
214
+ xml.tag!('v1:MerchantID', submerchant[:merchant_id]) if submerchant[:merchant_id]
215
+ end
216
+ end
217
+
218
+ def add_address(xml, address)
219
+ xml.tag!('v1:Address') do
220
+ xml.tag!('v1:Address1', address[:address1]) if address[:address1]
221
+ xml.tag!('v1:Address2', address[:address2]) if address[:address2]
222
+ xml.tag!('v1:Zip', address[:zip]) if address[:zip]
223
+ xml.tag!('v1:City', address[:city]) if address[:city]
224
+ xml.tag!('v1:State', address[:state]) if address[:state]
225
+ xml.tag!('v1:Country', address[:country]) if address[:country]
226
+ end
227
+ end
228
+
229
+ def add_document(xml, document)
230
+ xml.tag!('v1:Document') do
231
+ xml.tag!('v1:Type', document[:type]) if document[:type]
232
+ xml.tag!('v1:Number', document[:number]) if document[:number]
233
+ end
234
+ end
235
+
236
+ def add_three_d_secure(xml, three_d_secure)
237
+ xml.tag!('v1:CreditCard3DSecure') do
238
+ xml.tag!('v1:AuthenticationValue', three_d_secure[:cavv]) if three_d_secure[:cavv]
239
+ xml.tag!('v1:XID', three_d_secure[:xid]) if three_d_secure[:xid]
240
+ xml.tag!('v1:Secure3D2TransactionStatus', three_d_secure[:directory_response_status]) if three_d_secure[:directory_response_status]
241
+ xml.tag!('v1:Secure3D2AuthenticationResponse', three_d_secure[:authentication_response_status]) if three_d_secure[:authentication_response_status]
242
+ xml.tag!('v1:Secure3DProtocolVersion', three_d_secure[:version]) if three_d_secure[:version]
243
+ xml.tag!('v1:DirectoryServerTransactionId', three_d_secure[:ds_transaction_id]) if three_d_secure[:ds_transaction_id]
244
+ end
245
+ end
246
+
247
+ def add_transaction_details(xml, options, pre_order = false)
248
+ requires!(options, :order_id) if pre_order
249
+ xml.tag!('v1:TransactionDetails') do
250
+ xml.tag!('v1:OrderId', options[:order_id]) if options[:order_id]
251
+ xml.tag!('v1:MerchantTransactionId', options[:merchant_transaction_id]) if options[:merchant_transaction_id]
252
+ xml.tag!('v1:Ip', options[:ip]) if options[:ip]
253
+ xml.tag!('v1:Tdate', options[:t_date]) if options[:t_date]
254
+ xml.tag!('v1:IpgTransactionId', options[:ipg_transaction_id]) if options[:ipg_transaction_id]
255
+ xml.tag!('v1:ReferencedMerchantTransactionId', options[:referenced_merchant_transaction_id]) if options[:referenced_merchant_transaction_id]
256
+ xml.tag!('v1:TransactionOrigin', options[:transaction_origin]) if options[:transaction_origin]
257
+ xml.tag!('v1:InvoiceNumber', options[:invoice_number]) if options[:invoice_number]
258
+ xml.tag!('v1:DynamicMerchantName', options[:dynamic_merchant_name]) if options[:dynamic_merchant_name]
259
+ xml.tag!('v1:Comments', options[:comments]) if options[:comments]
260
+ if options[:terminal_id]
261
+ xml.tag!('v1:Terminal') do
262
+ xml.tag!('v1:TerminalID', options[:terminal_id]) if options[:terminal_id]
263
+ end
264
+ end
265
+ end
266
+ end
267
+
268
+ def add_payment(xml, money, payment, options)
269
+ requires!(options.merge!({ money: money }), :currency, :money)
270
+ xml.tag!('v1:Payment') do
271
+ xml.tag!('v1:HostedDataID', payment) if payment&.is_a?(String)
272
+ xml.tag!('v1:HostedDataStoreID', options[:hosted_data_store_id]) if options[:hosted_data_store_id]
273
+ xml.tag!('v1:DeclineHostedDataDuplicates', options[:decline_hosted_data_duplicates]) if options[:decline_hosted_data_duplicates]
274
+ xml.tag!('v1:SubTotal', options[:sub_total]) if options[:sub_total]
275
+ xml.tag!('v1:ValueAddedTax', options[:value_added_tax]) if options[:value_added_tax]
276
+ xml.tag!('v1:DeliveryAmount', options[:delivery_amount]) if options[:delivery_amount]
277
+ xml.tag!('v1:ChargeTotal', money)
278
+ xml.tag!('v1:Currency', CURRENCY_CODES[options[:currency]])
279
+ xml.tag!('v1:numberOfInstallments', options[:number_of_installments]) if options[:number_of_installments]
280
+ end
281
+ end
282
+
283
+ def add_billing(xml, billing)
284
+ xml.tag!('v1:Billing') do
285
+ xml.tag!('v1:CustomerID', billing[:customer_id]) if billing[:customer_id]
286
+ xml.tag!('v1:Name', billing[:name]) if billing[:name]
287
+ xml.tag!('v1:Company', billing[:company]) if billing[:company]
288
+ xml.tag!('v1:Address1', billing[:address_1]) if billing[:address_1]
289
+ xml.tag!('v1:Address2', billing[:address_2]) if billing[:address_2]
290
+ xml.tag!('v1:City', billing[:city]) if billing[:city]
291
+ xml.tag!('v1:State', billing[:state]) if billing[:state]
292
+ xml.tag!('v1:Zip', billing[:zip]) if billing[:zip]
293
+ xml.tag!('v1:Country', billing[:country]) if billing[:country]
294
+ xml.tag!('v1:Phone', billing[:phone]) if billing[:phone]
295
+ xml.tag!('v1:Fax', billing[:fax]) if billing[:fax]
296
+ xml.tag!('v1:Email', billing[:email]) if billing[:email]
297
+ end
298
+ end
299
+
300
+ def add_shipping(xml, shipping)
301
+ xml.tag!('v1:Shipping') do
302
+ xml.tag!('v1:Type', shipping[:type]) if shipping[:type]
303
+ xml.tag!('v1:Name', shipping[:name]) if shipping[:name]
304
+ xml.tag!('v1:Address1', shipping[:address_1]) if shipping[:address_1]
305
+ xml.tag!('v1:Address2', shipping[:address_2]) if shipping[:address_2]
306
+ xml.tag!('v1:City', shipping[:city]) if shipping[:city]
307
+ xml.tag!('v1:State', shipping[:state]) if shipping[:state]
308
+ xml.tag!('v1:Zip', shipping[:zip]) if shipping[:zip]
309
+ xml.tag!('v1:Country', shipping[:country]) if shipping[:country]
310
+ end
311
+ end
312
+
313
+ def build_header
314
+ {
315
+ 'Content-Type' => 'text/xml; charset=utf-8',
316
+ 'Authorization' => "Basic #{encoded_credentials}"
317
+ }
318
+ end
319
+
320
+ def encoded_credentials
321
+ Base64.encode64("WS#{@credentials[:store_id]}._.#{@credentials[:user_id]}:#{@credentials[:password]}").delete("\n")
322
+ end
323
+
324
+ def envelope_namespaces
325
+ {
326
+ 'xmlns:soapenv' => 'http://schemas.xmlsoap.org/soap/envelope/',
327
+ 'xmlns:ipg' => "#{NAMESPACE_BASE_URL}/ipgapi/schemas/ipgapi",
328
+ 'xmlns:v1' => "#{NAMESPACE_BASE_URL}/ipgapi/schemas/v1"
329
+ }
330
+ end
331
+
332
+ def ipg_order_namespaces
333
+ {
334
+ 'xmlns:v1' => "#{NAMESPACE_BASE_URL}/ipgapi/schemas/v1",
335
+ 'xmlns:ipgapi' => "#{NAMESPACE_BASE_URL}/ipgapi/schemas/ipgapi"
336
+ }
337
+ end
338
+
339
+ def ipg_action_namespaces
340
+ {
341
+ 'xmlns:ns4' => "#{NAMESPACE_BASE_URL}/ipgapi/schemas/ipgapi",
342
+ 'xmlns:ns2' => "#{NAMESPACE_BASE_URL}/ipgapi/schemas/a1",
343
+ 'xmlns:ns3' => "#{NAMESPACE_BASE_URL}/ipgapi/schemas/v1"
344
+ }
345
+ end
346
+
347
+ def commit(action, request)
348
+ url = (test? ? test_url : live_url)
349
+ soap_request = build_soap_request(action, request)
350
+ response = parse(ssl_post(url, soap_request, build_header))
351
+ Response.new(
352
+ response[:success],
353
+ message_from(response),
354
+ response,
355
+ authorization: authorization_from(action, response),
356
+ avs_result: AVSResult.new(code: response[:AVSResponse]),
357
+ cvv_result: CVVResult.new(response[:ProcessorCCVResponse]),
358
+ test: test?,
359
+ error_code: error_code_from(response)
360
+ )
361
+ end
362
+
363
+ def parse(xml)
364
+ reply = {}
365
+ xml = REXML::Document.new(xml)
366
+ root = REXML::XPath.first(xml, '//ipgapi:IPGApiOrderResponse') || REXML::XPath.first(xml, '//ipgapi:IPGApiActionResponse') || REXML::XPath.first(xml, '//SOAP-ENV:Fault') || REXML::XPath.first(xml, '//ns4:IPGApiActionResponse')
367
+ reply[:success] = REXML::XPath.first(xml, '//faultcode') ? false : true
368
+ if REXML::XPath.first(xml, '//ns4:IPGApiActionResponse')
369
+ reply[:tpv_error_code] = REXML::XPath.first(root, '//ns2:Error').attributes['Code']
370
+ reply[:tpv_error_msg] = REXML::XPath.first(root, '//ns2:ErrorMessage').text
371
+ reply[:success] = false
372
+ end
373
+ root.elements.to_a.each do |node|
374
+ parse_element(reply, node)
375
+ end
376
+ reply[:hosted_data_id] = @hosted_data_id if @hosted_data_id
377
+ return reply
378
+ end
379
+
380
+ def parse_element(reply, node)
381
+ if node.has_elements?
382
+ node.elements.each { |e| parse_element(reply, e) }
383
+ else
384
+ if /item/.match?(node.parent.name)
385
+ parent = node.parent.name
386
+ parent += '_' + node.parent.attributes['id'] if node.parent.attributes['id']
387
+ parent += '_'
388
+ end
389
+ reply["#{parent}#{node.name}".to_sym] ||= node.text
390
+ end
391
+ return reply
392
+ end
393
+
394
+ def message_from(response)
395
+ response[:TransactionResult]
396
+ end
397
+
398
+ def authorization_from(action, response)
399
+ return (action == 'vault' ? response[:hosted_data_id] : response[:OrderId])
400
+ end
401
+
402
+ def error_code_from(response)
403
+ response[:ErrorMessage]&.split(':')&.first unless response[:success]
404
+ end
405
+
406
+ def handle_response(response)
407
+ case response.code.to_i
408
+ when 200...300, 500
409
+ response.body
410
+ else
411
+ raise ResponseError.new(response)
412
+ end
413
+ end
414
+ end
415
+ end
416
+ end
@@ -82,6 +82,7 @@ module ActiveMerchant #:nodoc:
82
82
  add_invoice(action, post, amount, options)
83
83
  add_payment_method(post, payment_method, options)
84
84
  add_full_response(post, options)
85
+ add_metadata(post, options)
85
86
 
86
87
  commit(action, post)
87
88
  end
@@ -94,6 +95,7 @@ module ActiveMerchant #:nodoc:
94
95
  add_invoice(action, post, amount, options)
95
96
  add_contact_details(post, options[:contact_details]) if options[:contact_details]
96
97
  add_full_response(post, options)
98
+ add_metadata(post, options)
97
99
 
98
100
  commit(action, post)
99
101
  end
@@ -105,6 +107,7 @@ module ActiveMerchant #:nodoc:
105
107
  add_reference(post, authorization, options)
106
108
  add_invoice(action, post, amount, options)
107
109
  add_full_response(post, options)
110
+ add_metadata(post, options)
108
111
 
109
112
  commit(action, post)
110
113
  end
@@ -177,6 +180,10 @@ module ActiveMerchant #:nodoc:
177
180
  post[:fullResponse] = options[:full_response].to_s.casecmp('true').zero? if options[:full_response]
178
181
  end
179
182
 
183
+ def add_metadata(post, options)
184
+ post[:metadata] = options[:metadata] if options[:metadata]
185
+ end
186
+
180
187
  ENDPOINT = {
181
188
  'tokenize' => 'tokens',
182
189
  'charge' => 'charges',
@@ -53,8 +53,10 @@ module ActiveMerchant #:nodoc:
53
53
  end
54
54
 
55
55
  def verify(credit_card, options = {})
56
+ verify_amount = 100
57
+ verify_amount = options[:amount].to_i if options[:amount]
56
58
  MultiResponse.run(:use_first_response) do |r|
57
- r.process { authorize(100, credit_card, options) }
59
+ r.process { authorize(verify_amount, credit_card, options) }
58
60
  r.process(:ignore_result) { void(r.authorization, options) }
59
61
  end
60
62
  end