activemerchant 1.109.0 → 1.114.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (72) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG +47 -1
  3. data/README.md +2 -2
  4. data/lib/active_merchant/billing/credit_card.rb +1 -1
  5. data/lib/active_merchant/billing/credit_card_methods.rb +1 -1
  6. data/lib/active_merchant/billing/gateway.rb +1 -1
  7. data/lib/active_merchant/billing/gateways/adyen.rb +17 -6
  8. data/lib/active_merchant/billing/gateways/authorize_net.rb +6 -6
  9. data/lib/active_merchant/billing/gateways/authorize_net_cim.rb +1 -1
  10. data/lib/active_merchant/billing/gateways/balanced.rb +1 -1
  11. data/lib/active_merchant/billing/gateways/bambora_apac.rb +1 -1
  12. data/lib/active_merchant/billing/gateways/bank_frick.rb +1 -1
  13. data/lib/active_merchant/billing/gateways/blue_snap.rb +74 -16
  14. data/lib/active_merchant/billing/gateways/borgun.rb +1 -1
  15. data/lib/active_merchant/billing/gateways/braintree_blue.rb +7 -7
  16. data/lib/active_merchant/billing/gateways/cardknox.rb +1 -1
  17. data/lib/active_merchant/billing/gateways/cenpos.rb +1 -1
  18. data/lib/active_merchant/billing/gateways/checkout_v2.rb +1 -1
  19. data/lib/active_merchant/billing/gateways/credorax.rb +7 -1
  20. data/lib/active_merchant/billing/gateways/culqi.rb +1 -1
  21. data/lib/active_merchant/billing/gateways/cyber_source.rb +53 -16
  22. data/lib/active_merchant/billing/gateways/decidir.rb +1 -1
  23. data/lib/active_merchant/billing/gateways/digitzs.rb +1 -1
  24. data/lib/active_merchant/billing/gateways/efsnet.rb +1 -1
  25. data/lib/active_merchant/billing/gateways/element.rb +4 -0
  26. data/lib/active_merchant/billing/gateways/eway_rapid.rb +2 -2
  27. data/lib/active_merchant/billing/gateways/ezic.rb +1 -1
  28. data/lib/active_merchant/billing/gateways/fat_zebra.rb +5 -3
  29. data/lib/active_merchant/billing/gateways/firstdata_e4_v27.rb +8 -0
  30. data/lib/active_merchant/billing/gateways/flo2cash.rb +1 -1
  31. data/lib/active_merchant/billing/gateways/global_collect.rb +5 -0
  32. data/lib/active_merchant/billing/gateways/hdfc.rb +1 -1
  33. data/lib/active_merchant/billing/gateways/hps.rb +9 -6
  34. data/lib/active_merchant/billing/gateways/ipp.rb +2 -2
  35. data/lib/active_merchant/billing/gateways/iridium.rb +2 -2
  36. data/lib/active_merchant/billing/gateways/linkpoint.rb +1 -1
  37. data/lib/active_merchant/billing/gateways/litle.rb +1 -1
  38. data/lib/active_merchant/billing/gateways/mastercard.rb +2 -2
  39. data/lib/active_merchant/billing/gateways/mercado_pago.rb +1 -1
  40. data/lib/active_merchant/billing/gateways/netbanx.rb +8 -2
  41. data/lib/active_merchant/billing/gateways/openpay.rb +1 -1
  42. data/lib/active_merchant/billing/gateways/opp.rb +3 -3
  43. data/lib/active_merchant/billing/gateways/optimal_payment.rb +1 -1
  44. data/lib/active_merchant/billing/gateways/orbital.rb +8 -1
  45. data/lib/active_merchant/billing/gateways/pagarme.rb +1 -1
  46. data/lib/active_merchant/billing/gateways/pay_junction.rb +2 -2
  47. data/lib/active_merchant/billing/gateways/payeezy.rb +3 -3
  48. data/lib/active_merchant/billing/gateways/payex.rb +5 -5
  49. data/lib/active_merchant/billing/gateways/payflow.rb +3 -0
  50. data/lib/active_merchant/billing/gateways/payflow/payflow_common_api.rb +1 -1
  51. data/lib/active_merchant/billing/gateways/payflow/payflow_express_response.rb +1 -1
  52. data/lib/active_merchant/billing/gateways/paymill.rb +3 -3
  53. data/lib/active_merchant/billing/gateways/payu_latam.rb +4 -1
  54. data/lib/active_merchant/billing/gateways/plugnpay.rb +1 -1
  55. data/lib/active_merchant/billing/gateways/psigate.rb +1 -1
  56. data/lib/active_merchant/billing/gateways/qbms.rb +3 -3
  57. data/lib/active_merchant/billing/gateways/quickbooks.rb +3 -2
  58. data/lib/active_merchant/billing/gateways/qvalent.rb +1 -1
  59. data/lib/active_merchant/billing/gateways/realex.rb +1 -0
  60. data/lib/active_merchant/billing/gateways/redsys.rb +3 -3
  61. data/lib/active_merchant/billing/gateways/sage_pay.rb +4 -4
  62. data/lib/active_merchant/billing/gateways/skip_jack.rb +1 -1
  63. data/lib/active_merchant/billing/gateways/stripe.rb +2 -2
  64. data/lib/active_merchant/billing/gateways/telr.rb +1 -1
  65. data/lib/active_merchant/billing/gateways/trans_first.rb +1 -1
  66. data/lib/active_merchant/billing/gateways/trans_first_transaction_express.rb +2 -2
  67. data/lib/active_merchant/billing/gateways/trust_commerce.rb +7 -7
  68. data/lib/active_merchant/billing/gateways/usa_epay_advanced.rb +4 -4
  69. data/lib/active_merchant/billing/gateways/usa_epay_transaction.rb +1 -1
  70. data/lib/active_merchant/billing/gateways/worldpay_us.rb +2 -2
  71. data/lib/active_merchant/version.rb +1 -1
  72. metadata +16 -2
@@ -312,7 +312,7 @@ module ActiveMerchant #:nodoc:
312
312
  Version: '4.5.4',
313
313
  SoftwareName: 'Active Merchant',
314
314
  SoftwareVersion: ActiveMerchant::VERSION.to_s,
315
- Command: command,
315
+ Command: command
316
316
  }
317
317
 
318
318
  seed = SecureRandom.hex(32).upcase
@@ -250,7 +250,7 @@ module ActiveMerchant #:nodoc:
250
250
  '257' => STANDARD_ERROR_CODE[:invalid_cvc],
251
251
  '333' => STANDARD_ERROR_CODE[:expired_card],
252
252
  '1' => STANDARD_ERROR_CODE[:card_declined],
253
- '99' => STANDARD_ERROR_CODE[:processing_error],
253
+ '99' => STANDARD_ERROR_CODE[:processing_error]
254
254
  }
255
255
 
256
256
  def authorization_from(request, response)
@@ -194,7 +194,7 @@ module ActiveMerchant #:nodoc:
194
194
  def headers
195
195
  {
196
196
  'Authorization' => @options[:secret_key],
197
- 'Content-Type' => 'application/json;charset=UTF-8',
197
+ 'Content-Type' => 'application/json;charset=UTF-8'
198
198
  }
199
199
  end
200
200
 
@@ -193,6 +193,7 @@ module ActiveMerchant #:nodoc:
193
193
  add_email(post, options)
194
194
 
195
195
  if options[:referral_cft]
196
+ add_customer_name(post, options)
196
197
  commit(:referral_cft, post)
197
198
  else
198
199
  commit(:refund, post)
@@ -317,6 +318,11 @@ module ActiveMerchant #:nodoc:
317
318
  post[:c3] = options[:email] || 'unspecified@example.com'
318
319
  end
319
320
 
321
+ def add_customer_name(post, options)
322
+ post[:j5] = options[:first_name] if options[:first_name]
323
+ post[:j13] = options[:last_name] if options[:last_name]
324
+ end
325
+
320
326
  def add_3d_secure(post, options)
321
327
  if options[:eci] && options[:xid]
322
328
  add_3d_secure_1_data(post, options)
@@ -333,7 +339,7 @@ module ActiveMerchant #:nodoc:
333
339
  post[:'3ds_browsertz'] = browser_info[:timezone]
334
340
  post[:'3ds_browserscreenwidth'] = browser_info[:width]
335
341
  post[:'3ds_browserscreenheight'] = browser_info[:height]
336
- post[:'3ds_browsercolordepth'] = browser_info[:depth]
342
+ post[:'3ds_browsercolordepth'] = browser_info[:depth].to_s == '30' ? '32' : browser_info[:depth]
337
343
  post[:d6] = browser_info[:language]
338
344
  post[:'3ds_browserjavaenabled'] = browser_info[:java]
339
345
  post[:'3ds_browseracceptheader'] = browser_info[:accept_header]
@@ -205,7 +205,7 @@ module ActiveMerchant #:nodoc:
205
205
  refund: 'SingleCallGenericReverse',
206
206
  tokenize: 'SingleCallTokenServlet',
207
207
  invalidate: 'SingleCallInvalidateToken',
208
- tokenpay: 'SingleCallTokenTransaction',
208
+ tokenpay: 'SingleCallTokenTransaction'
209
209
  }
210
210
 
211
211
  def commit(action, params)
@@ -30,9 +30,11 @@ module ActiveMerchant #:nodoc:
30
30
  ECI_BRAND_MAPPING = {
31
31
  visa: 'vbv',
32
32
  master: 'spa',
33
+ maestro: 'spa',
33
34
  american_express: 'aesk',
34
35
  jcb: 'js',
35
36
  discover: 'pb',
37
+ diners_club: 'pb'
36
38
  }.freeze
37
39
  DEFAULT_COLLECTION_INDICATOR = 2
38
40
 
@@ -264,7 +266,9 @@ module ActiveMerchant #:nodoc:
264
266
  zip: '00000',
265
267
  country: 'US'
266
268
  }
267
- options[:billing_address] = options[:billing_address] || options[:address] || default_address
269
+
270
+ submitted_address = options[:billing_address] || options[:address] || default_address
271
+ options[:billing_address] = default_address.merge(submitted_address.symbolize_keys) { |_k, default, submitted| submitted.blank? ? default : submitted }
268
272
  options[:shipping_address] = options[:shipping_address] || {}
269
273
  end
270
274
 
@@ -278,10 +282,11 @@ module ActiveMerchant #:nodoc:
278
282
  add_threeds_services(xml, options)
279
283
  add_payment_network_token(xml) if network_tokenization?(creditcard_or_reference)
280
284
  add_business_rules_data(xml, creditcard_or_reference, options)
281
- add_stored_credential_options(xml, options)
285
+ add_stored_credential_subsequent_auth(xml, options)
282
286
  add_issuer_additional_data(xml, options)
283
- add_merchant_description(xml, options)
284
287
  add_partner_solution_id(xml)
288
+ add_stored_credential_options(xml, options)
289
+ add_merchant_description(xml, options)
285
290
 
286
291
  xml.target!
287
292
  end
@@ -322,17 +327,20 @@ module ActiveMerchant #:nodoc:
322
327
  add_mdd_fields(xml, options)
323
328
  if !payment_method_or_reference.is_a?(String) && card_brand(payment_method_or_reference) == 'check'
324
329
  add_check_service(xml)
330
+ add_issuer_additional_data(xml, options)
331
+ add_partner_solution_id(xml)
325
332
  else
326
333
  add_purchase_service(xml, payment_method_or_reference, options)
327
334
  add_threeds_services(xml, options)
328
335
  add_payment_network_token(xml) if network_tokenization?(payment_method_or_reference)
329
336
  add_business_rules_data(xml, payment_method_or_reference, options) unless options[:pinless_debit_card]
337
+ add_stored_credential_subsequent_auth(xml, options)
338
+ add_issuer_additional_data(xml, options)
339
+ add_partner_solution_id(xml)
330
340
  add_stored_credential_options(xml, options)
331
341
  end
332
342
 
333
- add_issuer_additional_data(xml, options)
334
343
  add_merchant_description(xml, options)
335
- add_partner_solution_id(xml)
336
344
 
337
345
  xml.target!
338
346
  end
@@ -611,21 +619,34 @@ module ActiveMerchant #:nodoc:
611
619
 
612
620
  def add_normalized_threeds_2_data(xml, payment_method, options)
613
621
  threeds_2_options = options[:three_d_secure]
622
+ cc_brand = card_brand(payment_method).to_sym
623
+
624
+ return if threeds_2_options[:cavv].blank? && infer_commerce_indicator?(options, cc_brand)
625
+
626
+ xid = threeds_2_options[:xid]
614
627
 
615
- xml.tag!('cavv', threeds_2_options[:cavv]) if threeds_2_options[:cavv] && card_brand(payment_method).to_sym != :master
628
+ xml.tag!('cavv', threeds_2_options[:cavv]) if threeds_2_options[:cavv] && cc_brand != :master
616
629
  xml.tag!('cavvAlgorithm', threeds_2_options[:cavv_algorithm]) if threeds_2_options[:cavv_algorithm]
617
630
  xml.tag!('paSpecificationVersion', threeds_2_options[:version]) if threeds_2_options[:version]
618
631
  xml.tag!('directoryServerTransactionID', threeds_2_options[:ds_transaction_id]) if threeds_2_options[:ds_transaction_id]
619
- xml.tag!('commerceIndicator', options[:commerce_indicator] || ECI_BRAND_MAPPING[card_brand(payment_method).to_sym])
632
+ xml.tag!('commerceIndicator', options[:commerce_indicator] || ECI_BRAND_MAPPING[cc_brand])
620
633
  xml.tag!('eciRaw', threeds_2_options[:eci]) if threeds_2_options[:eci]
621
634
 
622
- xid = threeds_2_options[:xid] || threeds_2_options[:cavv]
623
- xml.tag!('xid', xid) if xid
635
+ if xid.present?
636
+ xml.tag!('xid', xid)
637
+ elsif threeds_2_options[:version]&.start_with?('2') && cc_brand != :master
638
+ cavv = threeds_2_options[:cavv]
639
+ xml.tag!('xid', cavv) if cavv.present?
640
+ end
624
641
 
625
642
  xml.tag!('veresEnrolled', threeds_2_options[:enrolled]) if threeds_2_options[:enrolled]
626
643
  xml.tag!('paresStatus', threeds_2_options[:authentication_response_status]) if threeds_2_options[:authentication_response_status]
627
644
  end
628
645
 
646
+ def infer_commerce_indicator?(options, cc_brand)
647
+ options[:commerce_indicator].blank? && ECI_BRAND_MAPPING[cc_brand].present?
648
+ end
649
+
629
650
  def add_threeds_2_ucaf_data(xml, payment_method, options)
630
651
  return unless options[:three_d_secure] && card_brand(payment_method).to_sym == :master
631
652
 
@@ -830,13 +851,30 @@ module ActiveMerchant #:nodoc:
830
851
  country_code&.code(:alpha2)
831
852
  end
832
853
 
854
+ def add_stored_credential_subsequent_auth(xml, options={})
855
+ return unless options[:stored_credential] || options[:stored_credential_overrides]
856
+
857
+ stored_credential_subsequent_auth = 'true' if options.dig(:stored_credential, :initiator) == 'merchant'
858
+
859
+ override_subsequent_auth = options.dig(:stored_credential_overrides, :subsequent_auth)
860
+
861
+ xml.subsequentAuth override_subsequent_auth.nil? ? stored_credential_subsequent_auth : override_subsequent_auth
862
+ end
863
+
833
864
  def add_stored_credential_options(xml, options={})
834
- return unless options[:stored_credential]
865
+ return unless options[:stored_credential] || options[:stored_credential_overrides]
866
+
867
+ stored_credential_subsequent_auth_first = 'true' if options.dig(:stored_credential, :initial_transaction)
868
+ stored_credential_transaction_id = options.dig(:stored_credential, :network_transaction_id) if options.dig(:stored_credential, :initiator) == 'merchant'
869
+ stored_credential_subsequent_auth_stored_cred = 'true' if options.dig(:stored_credential, :initiator) == 'cardholder' && !options.dig(:stored_credential, :initial_transaction) || options.dig(:stored_credential, :initiator) == 'merchant' && options.dig(:stored_credential, :reason_type) == 'unscheduled'
835
870
 
836
- xml.tag! 'subsequentAuth', 'true' if options[:stored_credential][:initiator] == 'merchant'
837
- xml.tag! 'subsequentAuthFirst', 'true' if options[:stored_credential][:initial_transaction]
838
- xml.tag! 'subsequentAuthTransactionID', options[:stored_credential][:network_transaction_id] if options[:stored_credential][:initiator] == 'merchant'
839
- xml.tag! 'subsequentAuthStoredCredential', 'true' if options[:stored_credential][:initiator] == 'cardholder' && !options[:stored_credential][:initial_transaction] || options[:stored_credential][:initiator] == 'merchant' && options[:stored_credential][:reason_type] == 'unscheduled'
871
+ override_subsequent_auth_first = options.dig(:stored_credential_overrides, :subsequent_auth_first)
872
+ override_subsequent_auth_transaction_id = options.dig(:stored_credential_overrides, :subsequent_auth_transaction_id)
873
+ override_subsequent_auth_stored_cred = options.dig(:stored_credential_overrides, :subsequent_auth_stored_credential)
874
+
875
+ xml.subsequentAuthFirst override_subsequent_auth_first.nil? ? stored_credential_subsequent_auth_first : override_subsequent_auth_first
876
+ xml.subsequentAuthTransactionID override_subsequent_auth_transaction_id.nil? ? stored_credential_transaction_id : override_subsequent_auth_transaction_id
877
+ xml.subsequentAuthStoredCredential override_subsequent_auth_stored_cred.nil? ? stored_credential_subsequent_auth_stored_cred : override_subsequent_auth_stored_cred
840
878
  end
841
879
 
842
880
  def add_partner_solution_id(xml)
@@ -887,8 +925,7 @@ module ActiveMerchant #:nodoc:
887
925
 
888
926
  success = success?(response)
889
927
  message = message_from(response)
890
-
891
- authorization = success ? authorization_from(response, action, amount, options) : nil
928
+ authorization = success || in_fraud_review?(response) ? authorization_from(response, action, amount, options) : nil
892
929
 
893
930
  Response.new(success, message, response,
894
931
  test: test?,
@@ -39,7 +39,7 @@ module ActiveMerchant #:nodoc:
39
39
  76 => STANDARD_ERROR_CODE[:call_issuer],
40
40
  91 => STANDARD_ERROR_CODE[:call_issuer],
41
41
  96 => STANDARD_ERROR_CODE[:processing_error],
42
- 97 => STANDARD_ERROR_CODE[:processing_error],
42
+ 97 => STANDARD_ERROR_CODE[:processing_error]
43
43
  }
44
44
 
45
45
  def initialize(options={})
@@ -175,7 +175,7 @@ module ActiveMerchant #:nodoc:
175
175
  post[:data][:attributes] = {
176
176
  tokenType: 'card',
177
177
  customerId: options[:customer_id],
178
- label: 'Credit Card',
178
+ label: 'Credit Card'
179
179
  }
180
180
  add_payment(post, payment, options)
181
181
  add_address(post, options)
@@ -209,7 +209,7 @@ module ActiveMerchant #:nodoc:
209
209
  credit_card_refund: %w(ReferenceNumber TransactionAmount OriginalTransactionAmount OriginalTransactionID ClientIpAddress),
210
210
  void_transaction: %w(ReferenceNumber TransactionID),
211
211
  credit_card_settle: %w(ReferenceNumber TransactionAmount OriginalTransactionAmount OriginalTransactionID ClientIpAddress),
212
- system_check: %w(SystemCheck),
212
+ system_check: %w(SystemCheck)
213
213
  }
214
214
  end
215
215
  end
@@ -188,6 +188,10 @@ module ActiveMerchant #:nodoc:
188
188
  xml.TransactionAmount amount(money.to_i) if money
189
189
  xml.MarketCode 'Default' if money
190
190
  xml.ReferenceNumber options[:order_id] || SecureRandom.hex(20)
191
+
192
+ xml.PaymentType options[:payment_type] if options[:payment_type]
193
+ xml.SubmissionType options[:submission_type] if options[:submission_type]
194
+ xml.DuplicateCheckDisableFlag options[:duplicate_check_disable_flag].to_s == 'true' ? 'True' : 'False' unless options[:duplicate_check_disable_flag].nil?
191
195
  end
192
196
  end
193
197
 
@@ -204,7 +204,7 @@ module ActiveMerchant #:nodoc:
204
204
  'InvoiceReference' => truncate(options[:order_id], 50),
205
205
  'InvoiceNumber' => truncate(options[:invoice] || options[:order_id], 12),
206
206
  'InvoiceDescription' => truncate(options[:description], 64),
207
- 'CurrencyCode' => currency_code,
207
+ 'CurrencyCode' => currency_code
208
208
  }
209
209
  end
210
210
 
@@ -558,7 +558,7 @@ module ActiveMerchant #:nodoc:
558
558
  'V6150' => 'Invalid Refund Amount',
559
559
  'V6151' => 'Refund amount greater than original transaction',
560
560
  'V6152' => 'Original transaction already refunded for total amount',
561
- 'V6153' => 'Card type not support by merchant',
561
+ 'V6153' => 'Card type not support by merchant'
562
562
  }
563
563
  end
564
564
  end
@@ -187,7 +187,7 @@ module ActiveMerchant
187
187
 
188
188
  def headers
189
189
  {
190
- 'User-Agent' => "ActiveMerchantBindings/#{ActiveMerchant::VERSION}",
190
+ 'User-Agent' => "ActiveMerchantBindings/#{ActiveMerchant::VERSION}"
191
191
  }
192
192
  end
193
193
  end
@@ -125,11 +125,13 @@ module ActiveMerchant #:nodoc:
125
125
  def add_extra_options(post, options)
126
126
  extra = {}
127
127
  extra[:ecm] = '32' if options[:recurring]
128
- extra[:cavv] = options[:cavv] if options[:cavv]
129
- extra[:xid] = options[:xid] if options[:xid]
130
- extra[:sli] = options[:sli] if options[:sli]
128
+ extra[:cavv] = options[:cavv] || options.dig(:three_d_secure, :cavv) if options[:cavv] || options.dig(:three_d_secure, :cavv)
129
+ extra[:xid] = options[:xid] || options.dig(:three_d_secure, :xid) if options[:xid] || options.dig(:three_d_secure, :xid)
130
+ extra[:sli] = options[:sli] || options.dig(:three_d_secure, :eci) if options[:sli] || options.dig(:three_d_secure, :eci)
131
131
  extra[:name] = options[:merchant] if options[:merchant]
132
132
  extra[:location] = options[:merchant_location] if options[:merchant_location]
133
+ extra[:card_on_file] = options.dig(:extra, :card_on_file) if options.dig(:extra, :card_on_file)
134
+ extra[:auth_reason] = options.dig(:extra, :auth_reason) if options.dig(:extra, :auth_reason)
133
135
  post[:extra] = extra if extra.any?
134
136
  end
135
137
 
@@ -287,6 +287,8 @@ module ActiveMerchant #:nodoc:
287
287
 
288
288
  def add_address(xml, options)
289
289
  if (address = options[:billing_address] || options[:address])
290
+ address = strip_line_breaks(address)
291
+
290
292
  xml.tag! 'Address' do
291
293
  xml.tag! 'Address1', address[:address1]
292
294
  xml.tag! 'Address2', address[:address2] if address[:address2]
@@ -299,6 +301,12 @@ module ActiveMerchant #:nodoc:
299
301
  end
300
302
  end
301
303
 
304
+ def strip_line_breaks(address)
305
+ return unless address.is_a?(Hash)
306
+
307
+ Hash[address.map { |k, s| [k, s&.tr("\r\n", ' ')&.strip] }]
308
+ end
309
+
302
310
  def add_invoice(xml, options)
303
311
  xml.tag! 'Reference_No', options[:order_id]
304
312
  xml.tag! 'Reference_3', options[:description] if options[:description]
@@ -204,7 +204,7 @@ module ActiveMerchant #:nodoc:
204
204
  'Bank Declined Transaction' => STANDARD_ERROR_CODE[:card_declined],
205
205
  'Insufficient Funds' => STANDARD_ERROR_CODE[:card_declined],
206
206
  'Transaction Declined - Bank Error' => STANDARD_ERROR_CODE[:processing_error],
207
- 'No Reply from Bank' => STANDARD_ERROR_CODE[:processing_error],
207
+ 'No Reply from Bank' => STANDARD_ERROR_CODE[:processing_error]
208
208
  }
209
209
 
210
210
  def error_code_from(succeeded, response)
@@ -100,6 +100,7 @@ module ActiveMerchant #:nodoc:
100
100
  'invoiceNumber' => options[:invoice]
101
101
  }
102
102
  add_airline_data(post, options) if options[:airline_data]
103
+ add_number_of_installments(post, options) if options[:number_of_installments]
103
104
  end
104
105
 
105
106
  def add_airline_data(post, options)
@@ -231,6 +232,10 @@ module ActiveMerchant #:nodoc:
231
232
  post['fraudFields'] = fraud_fields unless fraud_fields.empty?
232
233
  end
233
234
 
235
+ def add_number_of_installments(post, options)
236
+ post['order']['additionalInput']['numberOfInstallments'] = options[:number_of_installments] if options[:number_of_installments]
237
+ end
238
+
234
239
  def parse(body)
235
240
  JSON.parse(body)
236
241
  end
@@ -134,7 +134,7 @@ module ActiveMerchant #:nodoc:
134
134
  'purchase' => '1',
135
135
  'refund' => '2',
136
136
  'authorize' => '4',
137
- 'capture' => '5',
137
+ 'capture' => '5'
138
138
  }
139
139
 
140
140
  def commit(action, post)
@@ -43,7 +43,7 @@ module ActiveMerchant #:nodoc:
43
43
  end
44
44
 
45
45
  def capture(money, transaction_id, options={})
46
- commit('CreditAddToBatch') do |xml|
46
+ commit('CreditAddToBatch', transaction_id) do |xml|
47
47
  add_amount(xml, money)
48
48
  add_reference(xml, transaction_id)
49
49
  end
@@ -126,7 +126,8 @@ module ActiveMerchant #:nodoc:
126
126
  end
127
127
 
128
128
  def add_reference(xml, transaction_id)
129
- xml.hps :GatewayTxnId, transaction_id
129
+ reference = transaction_id.to_s.include?('|') ? transaction_id.split('|').first : transaction_id
130
+ xml.hps :GatewayTxnId, reference
130
131
  end
131
132
 
132
133
  def add_amount(xml, money)
@@ -232,7 +233,7 @@ module ActiveMerchant #:nodoc:
232
233
  source: card_or_token.source,
233
234
  cavv: card_or_token.payment_cryptogram,
234
235
  eci: card_or_token.eci,
235
- xid: card_or_token.transaction_id,
236
+ xid: card_or_token.transaction_id
236
237
  })
237
238
  elsif options[:three_d_secure]
238
239
  options[:three_d_secure][:source] ||= card_brand(card_or_token)
@@ -323,7 +324,7 @@ module ActiveMerchant #:nodoc:
323
324
  response
324
325
  end
325
326
 
326
- def commit(action, &request)
327
+ def commit(action, reference = nil, &request)
327
328
  data = build_request(action, &request)
328
329
 
329
330
  response =
@@ -338,7 +339,7 @@ module ActiveMerchant #:nodoc:
338
339
  message_from(response),
339
340
  response,
340
341
  test: test?,
341
- authorization: authorization_from(response),
342
+ authorization: authorization_from(response, reference),
342
343
  avs_result: {
343
344
  code: response['AVSRsltCode'],
344
345
  message: response['AVSRsltText']
@@ -369,7 +370,9 @@ module ActiveMerchant #:nodoc:
369
370
  end
370
371
  end
371
372
 
372
- def authorization_from(response)
373
+ def authorization_from(response, reference)
374
+ return [reference, response['GatewayTxnId']].join('|') if reference
375
+
373
376
  response['GatewayTxnId']
374
377
  end
375
378
 
@@ -18,7 +18,7 @@ module ActiveMerchant #:nodoc:
18
18
  '05' => STANDARD_ERROR_CODE[:card_declined],
19
19
  '06' => STANDARD_ERROR_CODE[:processing_error],
20
20
  '14' => STANDARD_ERROR_CODE[:invalid_number],
21
- '54' => STANDARD_ERROR_CODE[:expired_card],
21
+ '54' => STANDARD_ERROR_CODE[:expired_card]
22
22
  }
23
23
 
24
24
  def initialize(options={})
@@ -121,7 +121,7 @@ module ActiveMerchant #:nodoc:
121
121
  def commit(action, &block)
122
122
  headers = {
123
123
  'Content-Type' => 'text/xml; charset=utf-8',
124
- 'SOAPAction' => "http://www.ippayments.com.au/interface/api/dts/#{action}",
124
+ 'SOAPAction' => "http://www.ippayments.com.au/interface/api/dts/#{action}"
125
125
  }
126
126
  response = parse(ssl_post(commit_url, new_submit_xml(action, &block), headers))
127
127
 
@@ -203,7 +203,7 @@ module ActiveMerchant #:nodoc:
203
203
  'YER' => '886',
204
204
  'ZAR' => '710',
205
205
  'ZMK' => '894',
206
- 'ZWD' => '716',
206
+ 'ZWD' => '716'
207
207
  }
208
208
 
209
209
  AVS_CODE = {
@@ -389,7 +389,7 @@ module ActiveMerchant #:nodoc:
389
389
  authorization: authorization,
390
390
  avs_result: {
391
391
  street_match: AVS_CODE[ response[:transaction_output_data][:address_numeric_check_result] ],
392
- postal_match: AVS_CODE[ response[:transaction_output_data][:post_code_check_result] ],
392
+ postal_match: AVS_CODE[ response[:transaction_output_data][:post_code_check_result] ]
393
393
  },
394
394
  cvv_result: CVV_CODE[ response[:transaction_output_data][:cv2_check_result] ]
395
395
  )