activemerchant 1.106.0 → 1.107.1

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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: f734d2204b43b893e645e5c47b9afe26506c0c383b355af486ac93cd6a8677ed
4
- data.tar.gz: 611450e08256619a1d8aea5bc5795c47ff9220f0abde707f0facc82dd76e1661
3
+ metadata.gz: 88249628bc56fb775fc6cc669fceea51b9040ced2f7c2dea503cd276a37202d1
4
+ data.tar.gz: f538ae45a677ec066b40dbb68742b1df9ccea5e7d45e0bd9e28d88968ae77334
5
5
  SHA512:
6
- metadata.gz: 98fa68d855a398089f9a088d8fa12edae2b34e8ed9fecab64511dc7e64b1ead409977adc00c3bc6aaf18f3f552f2b1fa3a38b8ceb5779d4a32a91e171a5556c8
7
- data.tar.gz: 78a05f047cb7de339104b39785394b75ca51be7d33368ba44549006e2429e3d2a2796a10d30a18a38fae4aff34e6f4a605f862ec3103ad101c9805c09af586f7
6
+ metadata.gz: 06c755605d7633a83cc1e2b9cfbf0cdf00d320e8bcd345cfdb6539ad814b9795ac4e33e075941f9b0761768ae9a6f3cb2bad90dd2ed35eca0fce7a8aa9642f55
7
+ data.tar.gz: e35ac5cfa97a22fdc416c0031e20f398b62189bb091e20b9c17fc815d2db2d481aa5463d047a5d718ec07574249c57acf1defec69c5ff7156f9be80220361b3d
data/CHANGELOG CHANGED
@@ -2,6 +2,25 @@
2
2
 
3
3
  == HEAD
4
4
 
5
+ == Version 1.107.1 (Apr 1, 2020)
6
+ * Add `allowed_push_host` to gemspec [mdeloupy]
7
+
8
+ == Version 1.107.0 (Apr 1, 2020)
9
+ * Stripe Payment Intents: Early return failed `payment_methods` response [chinhle23] #3570
10
+ * Borgun: Support `passengerItineraryData` [therufs] #3572
11
+ * Ingenico GlobalCollect: support optional `requires_approval` field [fatcatt316] #3571
12
+ * CenPOS: Update failing remote tests [britth] #3575
13
+ * Realex: Update remote tests [britth] #3576
14
+ * FirstData e4 v27: Properly tag stored credential initiation field in request [britth] #3578
15
+ * Orbital: Fix stored credentials [chinhle23] #3579
16
+ * Acapture(Opp): Update gateway credentials [molbrown] #3574
17
+ * Ingenico GlobalCollect: support `requires_approval` field [fatcatt316] #3577
18
+ * CyberSource: Fix `void` for `purchase` transactions [chinhle23] #3581
19
+ * Checkout V2: Begin to add support for using network tokens for transactions. [arbianchi] #3580
20
+ * Opp: Update remote test fixtures [ccarruitero] #3582
21
+ * Optimal Payment: Add support for store [britth] #3585
22
+ * SecurePay Australia : Update test URL (#3586)
23
+
5
24
  == Version 1.106.0 (Mar 10, 2020)
6
25
  * PayJunctionV2: Send billing address in `auth` and `purchase` transactions [naashton] #3538
7
26
  * Adyen: Fix some remote tests [curiousepic] #3541
@@ -34,7 +34,7 @@ module ActiveMerchant #:nodoc:
34
34
  post[:TransType] = '5'
35
35
  add_invoice(post, money, options)
36
36
  add_payment_method(post, payment)
37
- commit('authonly', post)
37
+ commit('authonly', post, options)
38
38
  end
39
39
 
40
40
  def capture(money, authorization, options={})
@@ -125,12 +125,12 @@ module ActiveMerchant #:nodoc:
125
125
  response
126
126
  end
127
127
 
128
- def commit(action, post)
128
+ def commit(action, post, options={})
129
129
  post[:Version] = '1000'
130
130
  post[:Processor] = @options[:processor]
131
131
  post[:MerchantID] = @options[:merchant_id]
132
132
 
133
- request = build_request(action, post)
133
+ request = build_request(action, post, options)
134
134
  raw = ssl_post(url(action), request, headers)
135
135
  pairs = parse(raw)
136
136
  success = success_from(pairs)
@@ -180,7 +180,7 @@ module ActiveMerchant #:nodoc:
180
180
  }
181
181
  end
182
182
 
183
- def build_request(action, post)
183
+ def build_request(action, post, options={})
184
184
  mode = action == 'void' ? 'cancel' : 'get'
185
185
  xml = Builder::XmlMarkup.new indent: 18
186
186
  xml.instruct!(:xml, version: '1.0', encoding: 'utf-8')
@@ -188,11 +188,22 @@ module ActiveMerchant #:nodoc:
188
188
  post.each do |field, value|
189
189
  xml.tag!(field, value)
190
190
  end
191
+ build_airline_xml(xml, options[:passenger_itinerary_data]) if options[:passenger_itinerary_data]
191
192
  end
192
193
  inner = CGI.escapeHTML(xml.target!)
193
194
  envelope(mode).sub(/{{ :body }}/, inner)
194
195
  end
195
196
 
197
+ def build_airline_xml(xml, airline_data)
198
+ xml.tag!('PassengerItineraryData') do
199
+ xml.tag!('A1') do
200
+ airline_data.each do |field, value|
201
+ xml.tag!(field, value)
202
+ end
203
+ end
204
+ end
205
+ end
206
+
196
207
  def envelope(mode)
197
208
  <<-EOS
198
209
  <soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:aut="http://Borgun/Heimir/pub/ws/Authorization">
@@ -102,13 +102,21 @@ module ActiveMerchant #:nodoc:
102
102
 
103
103
  def add_payment_method(post, payment_method, options)
104
104
  post[:source] = {}
105
- post[:source][:type] = 'card'
106
- post[:source][:name] = payment_method.name
107
- post[:source][:number] = payment_method.number
108
- post[:source][:cvv] = payment_method.verification_value
105
+ if payment_method.is_a?(NetworkTokenizationCreditCard) && payment_method.source == :network_token
106
+ post[:source][:type] = 'network_token'
107
+ post[:source][:token] = payment_method.number
108
+ post[:source][:token_type] = payment_method.brand == 'visa' ? 'vts' : 'mdes'
109
+ post[:source][:cryptogram] = payment_method.payment_cryptogram
110
+ post[:source][:eci] = options[:eci] || '05'
111
+ else
112
+ post[:source][:type] = 'card'
113
+ post[:source][:name] = payment_method.name
114
+ post[:source][:number] = payment_method.number
115
+ post[:source][:cvv] = payment_method.verification_value
116
+ post[:source][:stored] = 'true' if options[:card_on_file] == true
117
+ end
109
118
  post[:source][:expiry_year] = format(payment_method.year, :four_digits)
110
119
  post[:source][:expiry_month] = format(payment_method.month, :two_digits)
111
- post[:source][:stored] = 'true' if options[:card_on_file] == true
112
120
  end
113
121
 
114
122
  def add_customer_data(post, options)
@@ -325,7 +325,8 @@ module ActiveMerchant #:nodoc:
325
325
  options[:order_id] = order_id
326
326
 
327
327
  xml = Builder::XmlMarkup.new indent: 2
328
- if action == 'capture'
328
+ case action
329
+ when 'capture', 'purchase'
329
330
  add_mdd_fields(xml, options)
330
331
  add_void_service(xml, request_id, request_token)
331
332
  else
@@ -319,7 +319,7 @@ module ActiveMerchant #:nodoc:
319
319
  xml.tag! 'StoredCredentials' do
320
320
  xml.tag! 'Indicator', stored_credential_indicator(xml, card, options)
321
321
  if initiator = options.dig(:stored_credential, :initiator)
322
- xml.tag! initiator == 'merchant' ? 'M' : 'C'
322
+ xml.tag! 'Initiation', initiator == 'merchant' ? 'M' : 'C'
323
323
  end
324
324
  if reason_type = options.dig(:stored_credential, :reason_type)
325
325
  xml.tag! 'Schedule', reason_type == 'unscheduled' ? 'U' : 'S'
@@ -7,10 +7,10 @@ module ActiveMerchant #:nodoc:
7
7
  self.test_url = 'https://eu.sandbox.api-ingenico.com'
8
8
  self.live_url = 'https://api.globalcollect.com'
9
9
 
10
- self.supported_countries = ['AD', 'AE', 'AG', 'AI', 'AL', 'AM', 'AO', 'AR', 'AS', 'AT', 'AU', 'AW', 'AX', 'AZ', 'BA', 'BB', 'BD', 'BE', 'BF', 'BG', 'BH', 'BI', 'BJ', 'BL', 'BM', 'BN', 'BO', 'BQ', 'BR', 'BS', 'BT', 'BW', 'BY', 'BZ', 'CA', 'CC', 'CD', 'CF', 'CH', 'CI', 'CK', 'CL', 'CM', 'CN', 'CO', 'CR', 'CU', 'CV', 'CW', 'CX', 'CY', 'CZ', 'DE', 'DJ', 'DK', 'DM', 'DO', 'DZ', 'EC', 'EE', 'EG', 'ER', 'ES', 'ET', 'FI', 'FJ', 'FK', 'FM', 'FO', 'FR', 'GA', 'GB', 'GD', 'GE', 'GF', 'GH', 'GI', 'GL', 'GM', 'GN', 'GP', 'GQ', 'GR', 'GS', 'GT', 'GU', 'GW', 'GY', 'HK', 'HN', 'HR', 'HT', 'HU', 'ID', 'IE', 'IL', 'IM', 'IN', 'IS', 'IT', 'JM', 'JO', 'JP', 'KE', 'KG', 'KH', 'KI', 'KM', 'KN', 'KR', 'KW', 'KY', 'KZ', 'LA', 'LB', 'LC', 'LI', 'LK', 'LR', 'LS', 'LT', 'LU', 'LV', 'MA', 'MC', 'MD', 'ME', 'MF', 'MG', 'MH', 'MK', 'MM', 'MN', 'MO', 'MP', 'MQ', 'MR', 'MS', 'MT', 'MU', 'MV', 'MW', 'MX', 'MY', 'MZ', 'NA', 'NC', 'NE', 'NG', 'NI', 'NL', 'NO', 'NP', 'NR', 'NU', 'NZ', 'OM', 'PA', 'PE', 'PF', 'PG', 'PH', 'PL', 'PN', 'PS', 'PT', 'PW', 'QA', 'RE', 'RO', 'RS', 'RU', 'RW', 'SA', 'SB', 'SC', 'SE', 'SG', 'SH', 'SI', 'SJ', 'SK', 'SL', 'SM', 'SN', 'SR', 'ST', 'SV', 'SZ', 'TC', 'TD', 'TG', 'TH', 'TJ', 'TL', 'TM', 'TN', 'TO', 'TR', 'TT', 'TV', 'TW', 'TZ', 'UA', 'UG', 'US', 'UY', 'UZ', 'VC', 'VE', 'VG', 'VI', 'VN', 'WF', 'WS', 'ZA', 'ZM', 'ZW']
10
+ self.supported_countries = %w[AD AE AG AI AL AM AO AR AS AT AU AW AX AZ BA BB BD BE BF BG BH BI BJ BL BM BN BO BQ BR BS BT BW BY BZ CA CC CD CF CH CI CK CL CM CN CO CR CU CV CW CX CY CZ DE DJ DK DM DO DZ EC EE EG ER ES ET FI FJ FK FM FO FR GA GB GD GE GF GH GI GL GM GN GP GQ GR GS GT GU GW GY HK HN HR HT HU ID IE IL IM IN IS IT JM JO JP KE KG KH KI KM KN KR KW KY KZ LA LB LC LI LK LR LS LT LU LV MA MC MD ME MF MG MH MK MM MN MO MP MQ MR MS MT MU MV MW MX MY MZ NA NC NE NG NI NL NO NP NR NU NZ OM PA PE PF PG PH PL PN PS PT PW QA RE RO RS RU RW SA SB SC SE SG SH SI SJ SK SL SM SN SR ST SV SZ TC TD TG TH TJ TL TM TN TO TR TT TV TW TZ UA UG US UY UZ VC VE VG VI VN WF WS ZA ZM ZW]
11
11
  self.default_currency = 'USD'
12
12
  self.money_format = :cents
13
- self.supported_cardtypes = [:visa, :master, :american_express, :discover, :naranja, :cabal]
13
+ self.supported_cardtypes = %i[visa master american_express discover naranja cabal]
14
14
 
15
15
  def initialize(options={})
16
16
  requires!(options, :merchant_id, :api_key_id, :secret_api_key)
@@ -20,7 +20,7 @@ module ActiveMerchant #:nodoc:
20
20
  def purchase(money, payment, options={})
21
21
  MultiResponse.run do |r|
22
22
  r.process { authorize(money, payment, options) }
23
- r.process { capture(money, r.authorization, options) } unless capture_requested?(r)
23
+ r.process { capture(money, r.authorization, options) } if should_request_capture?(r, options[:requires_approval])
24
24
  end
25
25
  end
26
26
 
@@ -32,7 +32,6 @@ module ActiveMerchant #:nodoc:
32
32
  add_address(post, payment, options)
33
33
  add_creator_info(post, options)
34
34
  add_fraud_fields(post, options)
35
-
36
35
  commit(:authorize, post)
37
36
  end
38
37
 
@@ -161,6 +160,8 @@ module ActiveMerchant #:nodoc:
161
160
  'skipFraudService' => 'true',
162
161
  'authorizationMode' => pre_authorization
163
162
  }
163
+ post['cardPaymentMethodSpecificInput']['requiresApproval'] = options[:requires_approval] unless options[:requires_approval].nil?
164
+
164
165
  post['cardPaymentMethodSpecificInput']['card'] = {
165
166
  'cvv' => payment.verification_value,
166
167
  'cardNumber' => payment.number,
@@ -283,7 +284,7 @@ module ActiveMerchant #:nodoc:
283
284
 
284
285
  def headers(action, post, authorization = nil)
285
286
  {
286
- 'Content-Type' => content_type,
287
+ 'Content-Type' => content_type,
287
288
  'Authorization' => auth_digest(action, post, authorization),
288
289
  'Date' => date
289
290
  }
@@ -314,18 +315,16 @@ POST
314
315
  end
315
316
 
316
317
  def message_from(succeeded, response)
317
- if succeeded
318
- 'Succeeded'
318
+ return 'Succeeded' if succeeded
319
+
320
+ if errors = response['errors']
321
+ errors.first.try(:[], 'message')
322
+ elsif response['error_message']
323
+ response['error_message']
324
+ elsif response['status']
325
+ 'Status: ' + response['status']
319
326
  else
320
- if errors = response['errors']
321
- errors.first.try(:[], 'message')
322
- elsif response['error_message']
323
- response['error_message']
324
- elsif response['status']
325
- 'Status: ' + response['status']
326
- else
327
- 'No message available'
328
- end
327
+ 'No message available'
329
328
  end
330
329
  end
331
330
 
@@ -340,14 +339,14 @@ POST
340
339
  end
341
340
 
342
341
  def error_code_from(succeeded, response)
343
- unless succeeded
344
- if errors = response['errors']
345
- errors.first.try(:[], 'code')
346
- elsif status = response.try(:[], 'statusOutput').try(:[], 'statusCode')
347
- status.to_s
348
- else
349
- 'No error code available'
350
- end
342
+ return if succeeded
343
+
344
+ if errors = response['errors']
345
+ errors.first.try(:[], 'code')
346
+ elsif status = response.try(:[], 'statusOutput').try(:[], 'statusCode')
347
+ status.to_s
348
+ else
349
+ 'No error code available'
351
350
  end
352
351
  end
353
352
 
@@ -355,6 +354,13 @@ POST
355
354
  Hash.new { |h, k| h[k] = Hash.new(&h.default_proc) }
356
355
  end
357
356
 
357
+ # Capture hasn't already been requested,
358
+ # and
359
+ # `requires_approval` is not false
360
+ def should_request_capture?(response, requires_approval)
361
+ !capture_requested?(response) && requires_approval != false
362
+ end
363
+
358
364
  def capture_requested?(response)
359
365
  response.params.try(:[], 'payment').try(:[], 'status') == 'CAPTURE_REQUESTED'
360
366
  end
@@ -13,8 +13,7 @@ module ActiveMerchant #:nodoc:
13
13
  # == Usage
14
14
  #
15
15
  # gateway = ActiveMerchant::Billing::OppGateway.new(
16
- # user_id: 'merchant user id',
17
- # password: 'password',
16
+ # access_token: 'access_token',
18
17
  # entity_id: 'entity id',
19
18
  # )
20
19
  #
@@ -119,7 +118,7 @@ module ActiveMerchant #:nodoc:
119
118
  self.display_name = 'Open Payment Platform'
120
119
 
121
120
  def initialize(options={})
122
- requires!(options, :user_id, :password, :entity_id)
121
+ requires!(options, :access_token, :entity_id)
123
122
  super
124
123
  end
125
124
 
@@ -167,7 +166,7 @@ module ActiveMerchant #:nodoc:
167
166
 
168
167
  def scrub(transcript)
169
168
  transcript.
170
- gsub(%r((authentication\.password=)\w+), '\1[FILTERED]').
169
+ gsub(%r((Authorization: Bearer )\w+)i, '\1[FILTERED]').
171
170
  gsub(%r((card\.number=)\d+), '\1[FILTERED]').
172
171
  gsub(%r((card\.cvv=)\d+), '\1[FILTERED]')
173
172
  end
@@ -203,7 +202,7 @@ module ActiveMerchant #:nodoc:
203
202
  end
204
203
 
205
204
  def add_authentication(post)
206
- post[:authentication] = { entityId: @options[:entity_id], password: @options[:password], userId: @options[:user_id]}
205
+ post[:authentication] = { entityId: @options[:entity_id] }
207
206
  end
208
207
 
209
208
  def add_customer_data(post, payment, options)
@@ -316,7 +315,7 @@ module ActiveMerchant #:nodoc:
316
315
  ssl_post(
317
316
  url,
318
317
  post.collect { |key, value| "#{key}=#{CGI.escape(value.to_s)}" }.join('&'),
319
- 'Content-Type' => 'application/x-www-form-urlencoded;charset=UTF-8'
318
+ headers
320
319
  )
321
320
  )
322
321
  rescue ResponseError => e
@@ -335,6 +334,13 @@ module ActiveMerchant #:nodoc:
335
334
  )
336
335
  end
337
336
 
337
+ def headers
338
+ {
339
+ 'Content-Type' => 'application/x-www-form-urlencoded;charset=UTF-8',
340
+ 'Authorization' => "Bearer #{@options[:access_token]}"
341
+ }
342
+ end
343
+
338
344
  def parse(body)
339
345
  JSON.parse(body)
340
346
  rescue JSON::ParserError
@@ -65,6 +65,10 @@ module ActiveMerchant #:nodoc:
65
65
  commit('ccVerification', 0, options)
66
66
  end
67
67
 
68
+ def store(credit_card, options = {})
69
+ verify(credit_card, options)
70
+ end
71
+
68
72
  def supports_scrubbing?
69
73
  true
70
74
  end
@@ -569,7 +569,7 @@ module ActiveMerchant #:nodoc:
569
569
 
570
570
  initiator =
571
571
  case parameters[:stored_credential][:initiator]
572
- when 'customer' then 'C'
572
+ when 'cardholder', 'customer' then 'C'
573
573
  when 'merchant' then 'M'
574
574
  end
575
575
  reason =
@@ -8,7 +8,7 @@ module ActiveMerchant #:nodoc:
8
8
 
9
9
  class_attribute :test_periodic_url, :live_periodic_url
10
10
 
11
- self.test_url = 'https://api.securepay.com.au/test/payment'
11
+ self.test_url = 'https://test.api.securepay.com.au/xmlapi/payment'
12
12
  self.live_url = 'https://api.securepay.com.au/xmlapi/payment'
13
13
 
14
14
  self.test_periodic_url = 'https://test.securepay.com.au/xmlapi/periodic'
@@ -20,7 +20,9 @@ module ActiveMerchant #:nodoc:
20
20
  add_capture_method(post, options)
21
21
  add_confirmation_method(post, options)
22
22
  add_customer(post, options)
23
- add_payment_method_token(post, payment_method, options)
23
+ payment_method = add_payment_method_token(post, payment_method, options)
24
+ return payment_method if payment_method.is_a?(ActiveMerchant::Billing::Response)
25
+
24
26
  add_metadata(post, options)
25
27
  add_return_url(post, options)
26
28
  add_connected_account(post, options)
@@ -41,7 +43,9 @@ module ActiveMerchant #:nodoc:
41
43
 
42
44
  def confirm_intent(intent_id, payment_method, options = {})
43
45
  post = {}
44
- add_payment_method_token(post, payment_method, options)
46
+ payment_method = add_payment_method_token(post, payment_method, options)
47
+ return payment_method if payment_method.is_a?(ActiveMerchant::Billing::Response)
48
+
45
49
  CONFIRM_INTENT_ATTRIBUTES.each do |attribute|
46
50
  add_whitelisted_attribute(post, options, attribute)
47
51
  end
@@ -65,7 +69,9 @@ module ActiveMerchant #:nodoc:
65
69
  post = {}
66
70
  add_amount(post, money, options)
67
71
 
68
- add_payment_method_token(post, payment_method, options)
72
+ payment_method = add_payment_method_token(post, payment_method, options)
73
+ return payment_method if payment_method.is_a?(ActiveMerchant::Billing::Response)
74
+
69
75
  add_payment_method_types(post, options)
70
76
  add_customer(post, options)
71
77
  add_metadata(post, options)
@@ -121,7 +127,9 @@ module ActiveMerchant #:nodoc:
121
127
  # If customer option is provided, create a payment method and attach to customer id
122
128
  # Otherwise, create a customer, then attach
123
129
  if payment_method.is_a?(StripePaymentToken) || payment_method.is_a?(ActiveMerchant::Billing::CreditCard)
124
- add_payment_method_token(params, payment_method, options)
130
+ payment_method = add_payment_method_token(params, payment_method, options)
131
+ return payment_method if payment_method.is_a?(ActiveMerchant::Billing::Response)
132
+
125
133
  if options[:customer]
126
134
  customer_id = options[:customer]
127
135
  else
@@ -191,6 +199,8 @@ module ActiveMerchant #:nodoc:
191
199
 
192
200
  if payment_method.is_a?(ActiveMerchant::Billing::CreditCard)
193
201
  p = create_payment_method(payment_method, options)
202
+ return p unless p.success?
203
+
194
204
  payment_method = p.params['id']
195
205
  end
196
206
 
@@ -17,7 +17,7 @@ module ActiveMerchant #:nodoc:
17
17
  attr_accessor :payment_cryptogram, :eci, :transaction_id
18
18
  attr_writer :source
19
19
 
20
- SOURCES = %i(apple_pay android_pay google_pay)
20
+ SOURCES = %i(apple_pay android_pay google_pay network_token)
21
21
 
22
22
  def source
23
23
  if defined?(@source) && SOURCES.include?(@source)
@@ -1,3 +1,3 @@
1
1
  module ActiveMerchant
2
- VERSION = '1.106.0'
2
+ VERSION = '1.107.1'
3
3
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: activemerchant
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.106.0
4
+ version: 1.107.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Tobias Luetke
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2020-03-10 00:00:00.000000000 Z
11
+ date: 2020-04-01 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: activesupport
@@ -412,7 +412,8 @@ files:
412
412
  homepage: http://activemerchant.org/
413
413
  licenses:
414
414
  - MIT
415
- metadata: {}
415
+ metadata:
416
+ allowed_push_host: https://rubygems.org
416
417
  post_install_message:
417
418
  rdoc_options: []
418
419
  require_paths: