activemerchant 1.68.0 → 1.69.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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 3ed51178560acbebf43bedcb1e5ce966b279c04a
4
- data.tar.gz: fb02cd941337c8fb5a2e2ae2626a25d967e86750
3
+ metadata.gz: 18a666ef1305439841f07f349cea750f02d7f40f
4
+ data.tar.gz: eb8b0cd504e5f154d2834126601b626dd316df89
5
5
  SHA512:
6
- metadata.gz: d8fe0383adc62eb2a6af23bbe0ab0155d9121994fc7b9b0fe05f84ad7e521e3fe62db4814fb1efc02c8889e88fb561bba0807dc8133b3e39ad04d167d5b28c15
7
- data.tar.gz: 2159f015c245a4ebd0dc2ba57808884f08b2923271c951c8ffd4d0b581139d1426c0cadaa6f66bb6a26de4d63a12c2dcc26cd0adafc6ac51229c04668a05b640
6
+ metadata.gz: '09a7fded5ef8b8cfe0bd7744e0799a59064b550bc6f5ea7f2b5cc7208f49eec7b70e7cecd12e965c4053eaf7cab576facefd731dd1f0e9fad33d2df90042ad0b'
7
+ data.tar.gz: b6706229fd82c2be6f028f569987b724d284c6e32ed7b5ec79724035e628c9367233fb0576a13b8a3f37c1689d6e075090240c7724d2011e6ab0104f1e6050e1
data/CHANGELOG CHANGED
@@ -2,6 +2,24 @@
2
2
 
3
3
  == HEAD
4
4
 
5
+ == Version 1.69.0 (July 12, 2017)
6
+ * WePay: Add payer_rbits and transaction_rbits optional fields [davidsantoso]
7
+ * Adyen: Use Active Merchant standard order_id option for reference [jasonwebster] #2483
8
+ * Correct calculation for three-exponent currencies [curiousepic] #2486
9
+ * SagePay: Use VPSTxId from authorization for refunds [dtykocki] #2489
10
+ * Payflow: Move PAYPAL-NVP header option to a class attribute on the payment gateway [deuxpi] #2492
11
+ * Optimal Payments: Pass CVD indicator accurately [curiousepic] #2491
12
+ * SagePay: Make Repeat purchase if payment is a past authorization [curiousepic] #2495
13
+ * Netbanx: map response errorCodes onto standard error code [iirving] #2456
14
+ * Netbanx: Update supported countries and cardtypes [iirving] #2456
15
+ * Barclaycard Smartpay: Support 0- and 3-exponent currencies [curiousepic] #2498
16
+ * CyberSource: Fix XSD schema validation issues [jasonwebster] #2497
17
+ * WorldPay: Support three-decimal currencies [curiousepic] #2501
18
+ * NMI: Add first and lastname to echeck transactions [dtykocki] #2499
19
+ * PayFlow: Add optional email field [davidsantoso] #2505
20
+ * Worldpay: Support Credit on CFT-enabled merchant IDs [curiousepic] #2503
21
+ * FirstPay: Add processor_id field [davidsantoso] #2506
22
+
5
23
  == Version 1.68.0 (June 27, 2017)
6
24
  * Authorize.Net: Return failed response if forced refund settlement fails [bizla] #2476
7
25
  * Authorize.net: Concatenate address1 and address2 [dtykocki] #2479
@@ -280,9 +280,9 @@ module ActiveMerchant #:nodoc:
280
280
  end
281
281
  elsif three_decimal_currency?(currency)
282
282
  if self.money_format == :cents
283
- (amount.to_i * 10).to_s
283
+ amount.to_s
284
284
  else
285
- sprintf("%.3f", amount.to_f)
285
+ sprintf("%.3f", (amount.to_f / 10))
286
286
  end
287
287
  end
288
288
  end
@@ -40,7 +40,7 @@ module ActiveMerchant #:nodoc:
40
40
  end
41
41
 
42
42
  def authorize(money, payment, options={})
43
- requires!(options, :reference)
43
+ requires!(options, :order_id)
44
44
  post = init_post(options)
45
45
  add_invoice(post, money, options)
46
46
  add_payment(post, payment)
@@ -118,7 +118,7 @@ module ActiveMerchant #:nodoc:
118
118
  value: amount(money),
119
119
  currency: options[:currency] || currency(money)
120
120
  }
121
- post[:reference] = options[:reference]
121
+ post[:reference] = options[:order_id]
122
122
  post[:amount] = amount
123
123
  end
124
124
 
@@ -145,7 +145,7 @@ module ActiveMerchant #:nodoc:
145
145
 
146
146
  def add_references(post, authorization, options = {})
147
147
  post[:originalReference] = authorization
148
- post[:reference] = options[:reference]
148
+ post[:reference] = options[:order_id]
149
149
  end
150
150
 
151
151
  def parse(body)
@@ -6,6 +6,7 @@ module ActiveMerchant #:nodoc:
6
6
 
7
7
  self.supported_countries = ['AL', 'AD', 'AM', 'AT', 'AZ', 'BY', 'BE', 'BA', 'BG', 'HR', 'CY', 'CZ', 'DK', 'EE', 'FI', 'FR', 'GE', 'DE', 'GR', 'HU', 'IS', 'IE', 'IT', 'KZ', 'LV', 'LI', 'LT', 'LU', 'MK', 'MT', 'MD', 'MC', 'ME', 'NL', 'NO', 'PL', 'PT', 'RO', 'RU', 'SM', 'RS', 'SK', 'SI', 'ES', 'SE', 'CH', 'TR', 'UA', 'GB', 'VA']
8
8
  self.default_currency = 'EUR'
9
+ self.currencies_with_three_decimal_places = %w(BHD KWD OMR RSD TND)
9
10
  self.money_format = :cents
10
11
  self.supported_cardtypes = [:visa, :master, :american_express, :discover, :diners_club, :jcb, :dankort, :maestro]
11
12
 
@@ -238,9 +239,10 @@ module ActiveMerchant #:nodoc:
238
239
  end
239
240
 
240
241
  def amount_hash(money, currency)
242
+ currency = currency || currency(money)
241
243
  hash = {}
242
- hash[:currency] = currency || currency(money)
243
- hash[:value] = amount(money) if money
244
+ hash[:currency] = currency
245
+ hash[:value] = localized_amount(money, currency) if money
244
246
  hash
245
247
  end
246
248
 
@@ -258,6 +258,7 @@ module ActiveMerchant #:nodoc:
258
258
  add_decision_manager_fields(xml, options)
259
259
  add_mdd_fields(xml, options)
260
260
  add_auth_service(xml, creditcard_or_reference, options)
261
+ add_payment_network_token(xml) if network_tokenization?(creditcard_or_reference)
261
262
  add_business_rules_data(xml, creditcard_or_reference, options)
262
263
  xml.target!
263
264
  end
@@ -293,6 +294,7 @@ module ActiveMerchant #:nodoc:
293
294
  add_check_service(xml)
294
295
  else
295
296
  add_purchase_service(xml, payment_method_or_reference, options)
297
+ add_payment_network_token(xml) if network_tokenization?(payment_method_or_reference)
296
298
  add_business_rules_data(xml, payment_method_or_reference, options) unless options[:pinless_debit_card]
297
299
  end
298
300
  xml.target!
@@ -355,6 +357,7 @@ module ActiveMerchant #:nodoc:
355
357
  add_check_service(xml, options)
356
358
  else
357
359
  add_purchase_service(xml, payment_method, options)
360
+ add_payment_network_token(xml) if network_tokenization?(payment_method)
358
361
  end
359
362
  end
360
363
  add_subscription_create_service(xml, options)
@@ -471,6 +474,8 @@ module ActiveMerchant #:nodoc:
471
474
  end
472
475
 
473
476
  def add_decision_manager_fields(xml, options)
477
+ return unless options[:decision_manager_enabled]
478
+
474
479
  xml.tag! 'decisionManager' do
475
480
  xml.tag! 'enabled', options[:decision_manager_enabled] if options[:decision_manager_enabled]
476
481
  xml.tag! 'profile', options[:decision_manager_profile] if options[:decision_manager_profile]
@@ -478,6 +483,8 @@ module ActiveMerchant #:nodoc:
478
483
  end
479
484
 
480
485
  def add_mdd_fields(xml, options)
486
+ return unless options.keys.any? { |key| key.to_s.start_with?("mdd_field") }
487
+
481
488
  xml.tag! 'merchantDefinedData' do
482
489
  (1..100).each do |each|
483
490
  key = "mdd_field_#{each}".to_sym
@@ -503,7 +510,7 @@ module ActiveMerchant #:nodoc:
503
510
 
504
511
  def add_auth_service(xml, payment_method, options)
505
512
  if network_tokenization?(payment_method)
506
- add_network_tokenization(xml, payment_method, options)
513
+ add_auth_network_tokenization(xml, payment_method, options)
507
514
  else
508
515
  xml.tag! 'ccAuthService', {'run' => 'true'}
509
516
  end
@@ -513,7 +520,7 @@ module ActiveMerchant #:nodoc:
513
520
  payment_method.is_a?(NetworkTokenizationCreditCard)
514
521
  end
515
522
 
516
- def add_network_tokenization(xml, payment_method, options)
523
+ def add_auth_network_tokenization(xml, payment_method, options)
517
524
  return unless network_tokenization?(payment_method)
518
525
 
519
526
  case card_brand(payment_method).to_sym
@@ -539,9 +546,11 @@ module ActiveMerchant #:nodoc:
539
546
  xml.tag!("xid", Base64.encode64(cryptogram[20...40]))
540
547
  end
541
548
  end
549
+ end
542
550
 
551
+ def add_payment_network_token(xml)
543
552
  xml.tag! 'paymentNetworkToken' do
544
- xml.tag!('transactionType', "1")
553
+ xml.tag!('transactionType', '1')
545
554
  end
546
555
  end
547
556
 
@@ -67,6 +67,7 @@ module ActiveMerchant #:nodoc:
67
67
  def add_customer_data(post, options)
68
68
  post[:owner_email] = options[:email] if options[:email]
69
69
  post[:remote_ip_address] = options[:ip] if options[:ip]
70
+ post[:processor_id] = options[:processor_id] if options[:processor_id]
70
71
  end
71
72
 
72
73
  def add_address(post, creditcard, options)
@@ -5,16 +5,23 @@ module ActiveMerchant #:nodoc:
5
5
  self.test_url = 'https://api.test.netbanx.com/'
6
6
  self.live_url = 'https://api.netbanx.com/'
7
7
 
8
- self.supported_countries = ['CA', 'US', 'GB']
8
+ self.supported_countries = %w(AF AX AL DZ AS AD AO AI AQ AG AR AM AW AU AT AZ BS BH BD BB BY BE BZ BJ BM BT BO BQ BA BW BV BR IO BN BG BF BI KH CM CA CV KY CF TD CL CN CX CC CO KM CG CD CK CR CI HR CU CW CY CZ DK DJ DM DO EC EG SV GQ ER EE ET FK FO FJ FI FR GF PF TF GA GM GE DE GH GI GR GL GD GP GU GT GG GN GW GY HT HM HN HK HU IS IN ID IR IQ IE IM IL IT JM JP JE JO KZ KE KI KP KR KW KG LA LV LB LS LR LY LI LT LU MO MK MG MW MY MV ML MT MH MQ MR MU YT MX FM MD MC MN ME MS MA MZ MM NA NR NP NC NZ NI NE NG NU NF MP NO OM PK PW PS PA PG PY PE PH PN PL PT PR QA RE RO RU RW BL SH KN LC MF VC WS SM ST SA SN RS SC SL SG SX SK SI SB SO ZA GS SS ES LK PM SD SR SJ SZ SE CH SY TW TJ TZ TH NL TL TG TK TO TT TN TR TM TC TV UG UA AE GB US UM UY UZ VU VA VE VN VG VI WF EH YE ZM ZW)
9
9
  self.default_currency = 'CAD'
10
- self.supported_cardtypes = [:visa, :master, :american_express, :discover]
10
+ self.supported_cardtypes = [
11
+ :american_express,
12
+ :diners_club,
13
+ :discover,
14
+ :jcb,
15
+ :master,
16
+ :maestro,
17
+ :visa
18
+ ]
19
+
11
20
  self.money_format = :cents
12
21
 
13
22
  self.homepage_url = 'https://processing.paysafe.com/'
14
23
  self.display_name = 'Netbanx by PaySafe'
15
24
 
16
- STANDARD_ERROR_CODE_MAPPING = {}
17
-
18
25
  def initialize(options={})
19
26
  requires!(options, :account_number, :api_key)
20
27
  super
@@ -110,9 +117,6 @@ module ActiveMerchant #:nodoc:
110
117
  def add_customer_data(post, options)
111
118
  post[:merchantCustomerId] = (options[:merchant_customer_id] || SecureRandom.uuid)
112
119
  post[:locale] = options[:locale]
113
- # if options[:billing_address]
114
- # post[:address] = map_address(options[:billing_address])
115
- # end
116
120
  end
117
121
 
118
122
  def add_credit_card(post, credit_card, options = {})
@@ -192,6 +196,7 @@ module ActiveMerchant #:nodoc:
192
196
  message_from(success, response),
193
197
  response,
194
198
  :test => test?,
199
+ :error_code => error_code_from(response),
195
200
  :authorization => authorization_from(success, get_url(uri), method, response)
196
201
  )
197
202
  end
@@ -240,6 +245,48 @@ module ActiveMerchant #:nodoc:
240
245
  'User-Agent' => "Netbanx-Paysafe v1.0/ActiveMerchant #{ActiveMerchant::VERSION}"
241
246
  }
242
247
  end
248
+
249
+ def error_code_from(response)
250
+ unless success_from(response)
251
+ case response['errorCode']
252
+ when '3002' then STANDARD_ERROR_CODE[:invalid_number] # You submitted an invalid card number or brand or combination of card number and brand with your request.
253
+ when '3004' then STANDARD_ERROR_CODE[:incorrect_zip] # The zip/postal code must be provided for an AVS check request.
254
+ when '3005' then STANDARD_ERROR_CODE[:incorrect_cvc] # You submitted an incorrect CVC value with your request.
255
+ when '3006' then STANDARD_ERROR_CODE[:expired_card] # You submitted an expired credit card number with your request.
256
+ when '3009' then STANDARD_ERROR_CODE[:card_declined] # Your request has been declined by the issuing bank.
257
+ when '3011' then STANDARD_ERROR_CODE[:card_declined] # Your request has been declined by the issuing bank because the card used is a restricted card. Contact the cardholder's credit card company for further investigation.
258
+ when '3012' then STANDARD_ERROR_CODE[:card_declined] # Your request has been declined by the issuing bank because the credit card expiry date submitted is invalid.
259
+ when '3013' then STANDARD_ERROR_CODE[:card_declined] # Your request has been declined by the issuing bank due to problems with the credit card account.
260
+ when '3014' then STANDARD_ERROR_CODE[:card_declined] # Your request has been declined - the issuing bank has returned an unknown response. Contact the card holder's credit card company for further investigation.
261
+ when '3015' then STANDARD_ERROR_CODE[:card_declined] # The bank has requested that you process the transaction manually by calling the cardholder's credit card company.
262
+ when '3016' then STANDARD_ERROR_CODE[:card_declined] # The bank has requested that you retrieve the card from the cardholder – it may be a lost or stolen card.
263
+ when '3017' then STANDARD_ERROR_CODE[:invalid_number] # You submitted an invalid credit card number with your request.
264
+ when '3022' then STANDARD_ERROR_CODE[:card_declined] # The card has been declined due to insufficient funds.
265
+ when '3023' then STANDARD_ERROR_CODE[:card_declined] # Your request has been declined by the issuing bank due to its proprietary card activity regulations.
266
+ when '3024' then STANDARD_ERROR_CODE[:card_declined] # Your request has been declined because the issuing bank does not permit the transaction for this card.
267
+ when '3032' then STANDARD_ERROR_CODE[:card_declined] # Your request has been declined by the issuing bank or external gateway because the card is probably in one of their negative databases.
268
+ when '3035' then STANDARD_ERROR_CODE[:card_declined] # Your request has been declined due to exceeded PIN attempts.
269
+ when '3036' then STANDARD_ERROR_CODE[:card_declined] # Your request has been declined due to an invalid issuer.
270
+ when '3037' then STANDARD_ERROR_CODE[:card_declined] # Your request has been declined because it is invalid.
271
+ when '3038' then STANDARD_ERROR_CODE[:card_declined] # Your request has been declined due to customer cancellation.
272
+ when '3039' then STANDARD_ERROR_CODE[:card_declined] # Your request has been declined due to an invalid authentication value.
273
+ when '3040' then STANDARD_ERROR_CODE[:card_declined] # Your request has been declined because the request type is not permitted on the card.
274
+ when '3041' then STANDARD_ERROR_CODE[:card_declined] # Your request has been declined due to a timeout.
275
+ when '3042' then STANDARD_ERROR_CODE[:card_declined] # Your request has been declined due to a cryptographic error.
276
+ when '3045' then STANDARD_ERROR_CODE[:invalid_expiry_date] # You submitted an invalid date format for this request.
277
+ when '3046' then STANDARD_ERROR_CODE[:card_declined] # The transaction was declined because the amount was set to zero.
278
+ when '3047' then STANDARD_ERROR_CODE[:card_declined] # The transaction was declined because the amount exceeds the floor limit.
279
+ when '3048' then STANDARD_ERROR_CODE[:card_declined] # The transaction was declined because the amount is less than the floor limit.
280
+ when '3049' then STANDARD_ERROR_CODE[:card_declined] # The bank has requested that you retrieve the card from the cardholder – the credit card has expired.
281
+ when '3050' then STANDARD_ERROR_CODE[:card_declined] # The bank has requested that you retrieve the card from the cardholder – fraudulent activity is suspected.
282
+ when '3051' then STANDARD_ERROR_CODE[:card_declined] # The bank has requested that you retrieve the card from the cardholder – contact the acquirer for more information.
283
+ when '3052' then STANDARD_ERROR_CODE[:card_declined] # The bank has requested that you retrieve the card from the cardholder – the credit card is restricted.
284
+ when '3053' then STANDARD_ERROR_CODE[:card_declined] # The bank has requested that you retrieve the card from the cardholder – please call the acquirer.
285
+ when '3054' then STANDARD_ERROR_CODE[:card_declined] # The transaction was declined due to suspected fraud.
286
+ else STANDARD_ERROR_CODE[:processing_error]
287
+ end
288
+ end
289
+ end
243
290
  end
244
291
  end
245
292
  end
@@ -146,6 +146,8 @@ module ActiveMerchant #:nodoc:
146
146
  post[:token_cryptogram] = payment_method.payment_cryptogram
147
147
  elsif(card_brand(payment_method) == 'check')
148
148
  post[:payment] = 'check'
149
+ post[:firstname] = payment_method.first_name
150
+ post[:lastname] = payment_method.last_name
149
151
  post[:checkname] = payment_method.name
150
152
  post[:checkaba] = payment_method.routing_number
151
153
  post[:checkaccount] = payment_method.account_number
@@ -259,9 +259,11 @@ module ActiveMerchant #:nodoc:
259
259
  if brand = card_type(@credit_card.brand)
260
260
  xml.tag! 'cardType' , brand
261
261
  end
262
- if @credit_card.verification_value
262
+ if @credit_card.verification_value?
263
263
  xml.tag! 'cvdIndicator' , '1' # Value Provided
264
264
  xml.tag! 'cvd' , @credit_card.verification_value
265
+ else
266
+ xml.tag! 'cvdIndicator' , '0'
265
267
  end
266
268
  end
267
269
  end
@@ -152,6 +152,7 @@ module ActiveMerchant #:nodoc:
152
152
  xml.tag! 'FreightAmt', options[:freightamt] unless options[:freightamt].blank?
153
153
  xml.tag! 'DutyAmt', options[:dutyamt] unless options[:dutyamt].blank?
154
154
  xml.tag! 'DiscountAmt', options[:discountamt] unless options[:discountamt].blank?
155
+ xml.tag! 'EMail', options[:email] unless options[:email].nil?
155
156
 
156
157
  billing_address = options[:billing_address] || options[:address]
157
158
  add_address(xml, 'BillTo', billing_address, options) if billing_address
@@ -25,6 +25,13 @@ module ActiveMerchant #:nodoc:
25
25
  # subsequent Responses will have a :duplicate parameter set in the params
26
26
  # hash.
27
27
  base.retry_safe = true
28
+
29
+ # Send Payflow requests to PayPal directly by activating the NVP protocol.
30
+ # Valid XMLPay documents may have issues being parsed correctly by
31
+ # Payflow but will be accepted by PayPal if a PAYPAL-NVP request header
32
+ # is declared.
33
+ base.class_attribute :use_paypal_nvp
34
+ base.use_paypal_nvp = false
28
35
  end
29
36
 
30
37
  XMLNS = 'http://www.paypal.com/XMLPay'
@@ -180,7 +187,7 @@ module ActiveMerchant #:nodoc:
180
187
  end
181
188
  end
182
189
 
183
- def build_headers(content_length, options = {})
190
+ def build_headers(content_length)
184
191
  headers = {
185
192
  "Content-Type" => "text/xml",
186
193
  "Content-Length" => content_length.to_s,
@@ -190,13 +197,13 @@ module ActiveMerchant #:nodoc:
190
197
  "X-VPS-Request-ID" => SecureRandom.hex(16)
191
198
  }
192
199
 
193
- headers.merge!("PAYPAL-NVP" => options[:paypal_nvp]) if options[:paypal_nvp]
200
+ headers.merge!("PAYPAL-NVP" => "Y") if self.use_paypal_nvp
194
201
  headers
195
202
  end
196
203
 
197
204
  def commit(request_body, options = {})
198
205
  request = build_request(request_body, options)
199
- headers = build_headers(request.size, options)
206
+ headers = build_headers(request.size)
200
207
 
201
208
  response = parse(ssl_post(test? ? self.test_url : self.live_url, request, headers))
202
209
 
@@ -88,7 +88,7 @@ module ActiveMerchant #:nodoc:
88
88
  add_customer_data(post, options)
89
89
  add_optional_data(post, options)
90
90
 
91
- commit((options[:repeat] ? :repeat : :purchase), post)
91
+ commit((past_purchase_reference?(payment_method) ? :repeat : :purchase), post)
92
92
  end
93
93
 
94
94
  def authorize(money, payment_method, options = {})
@@ -268,12 +268,14 @@ module ActiveMerchant #:nodoc:
268
268
  end
269
269
 
270
270
  def add_payment_method(post, payment_method, options)
271
- if options[:repeat]
272
- add_related_reference(post, payment_method)
273
- elsif payment_method.respond_to?(:number)
274
- add_credit_card(post, payment_method)
271
+ if payment_method.is_a?(String)
272
+ if past_purchase_reference?(payment_method)
273
+ add_related_reference(post, payment_method)
274
+ else
275
+ add_token_details(post, payment_method, options)
276
+ end
275
277
  else
276
- add_token_details(post, payment_method, options)
278
+ add_credit_card(post, payment_method)
277
279
  end
278
280
  end
279
281
 
@@ -359,9 +361,9 @@ module ActiveMerchant #:nodoc:
359
361
  response['Token']
360
362
  else
361
363
  [ params[:VendorTxCode],
362
- response["VPSTxId"],
364
+ response["VPSTxId"] || params[:VPSTxId],
363
365
  response["TxAuthNo"],
364
- response["SecurityKey"],
366
+ response["SecurityKey"] || params[:SecurityKey],
365
367
  action ].join(";")
366
368
  end
367
369
  end
@@ -422,6 +424,10 @@ module ActiveMerchant #:nodoc:
422
424
  post[key] = value if !value.blank? || options[:required]
423
425
  end
424
426
 
427
+ def past_purchase_reference?(payment_method)
428
+ return false unless payment_method.is_a?(String)
429
+ payment_method.split(';').last == 'purchase'
430
+ end
425
431
  end
426
432
 
427
433
  end
@@ -148,6 +148,8 @@ module ActiveMerchant #:nodoc:
148
148
  post[:preapproval_id] = options[:preapproval_id] if options[:preapproval_id]
149
149
  post[:prefill_info] = options[:prefill_info] if options[:prefill_info]
150
150
  post[:funding_sources] = options[:funding_sources] if options[:funding_sources]
151
+ post[:payer_rbits] = options[:payer_rbits] if options[:payer_rbits]
152
+ post[:transaction_rbits] = options[:transaction_rbits] if options[:transaction_rbits]
151
153
  add_fee(post, options)
152
154
  end
153
155
 
@@ -9,6 +9,7 @@ module ActiveMerchant #:nodoc:
9
9
  self.supported_countries = %w(HK GB AU AD BE CH CY CZ DE DK ES FI FR GI GR HU IE IL IT LI LU MC MT NL NO NZ PL PT SE SG SI SM TR UM VA)
10
10
  self.supported_cardtypes = [:visa, :master, :american_express, :discover, :jcb, :maestro, :laser, :switch]
11
11
  self.currencies_without_fractions = %w(HUF IDR ISK JPY KRW)
12
+ self.currencies_with_three_decimal_places = %w(BHD KWD OMR RSD TND)
12
13
  self.homepage_url = 'http://www.worldpay.com/'
13
14
  self.display_name = 'Worldpay Global'
14
15
 
@@ -71,6 +72,14 @@ module ActiveMerchant #:nodoc:
71
72
  void(authorization, options ) if response.params["last_event"] == "AUTHORISED"
72
73
  end
73
74
 
75
+ # Credits only function on a Merchant ID/login/profile flagged for Payouts
76
+ # aka Credit Fund Transfers (CFT), whereas normal purchases, refunds,
77
+ # and other transactions should be performed on a normal eCom-flagged
78
+ # merchant ID.
79
+ def credit(money, payment_method, options = {})
80
+ credit_request(money, payment_method, options.merge(:credit => true))
81
+ end
82
+
74
83
  def verify(credit_card, options={})
75
84
  MultiResponse.run(:use_first_response) do |r|
76
85
  r.process { authorize(100, credit_card, options) }
@@ -111,6 +120,10 @@ module ActiveMerchant #:nodoc:
111
120
  commit('refund', build_refund_request(money, authorization, options), :ok)
112
121
  end
113
122
 
123
+ def credit_request(money, payment_method, options)
124
+ commit('credit', build_authorization_request(money, payment_method, options), :ok)
125
+ end
126
+
114
127
  def build_request
115
128
  xml = Builder::XmlMarkup.new :indent => 2
116
129
  xml.instruct! :xml, :encoding => 'UTF-8'
@@ -194,7 +207,7 @@ module ActiveMerchant #:nodoc:
194
207
  amount_hash = {
195
208
  :value => localized_amount(money, currency),
196
209
  'currencyCode' => currency,
197
- 'exponent' => non_fractional_currency?(currency) ? 0 : 2
210
+ 'exponent' => currency_exponent(currency)
198
211
  }
199
212
 
200
213
  if options[:debit_credit_indicator]
@@ -216,7 +229,7 @@ module ActiveMerchant #:nodoc:
216
229
  end
217
230
  end
218
231
  else
219
- xml.tag! 'paymentDetails' do
232
+ xml.tag! 'paymentDetails', credit_fund_transfer_attribute(options) do
220
233
  xml.tag! CARD_CODES[card_brand(payment_method)] do
221
234
  xml.tag! 'cardNumber', payment_method.number
222
235
  xml.tag! 'expiryDate' do
@@ -365,10 +378,21 @@ module ActiveMerchant #:nodoc:
365
378
  (pair ? pair.last : nil)
366
379
  end
367
380
 
381
+ def credit_fund_transfer_attribute(options)
382
+ return unless options[:credit]
383
+ {'action' => "REFUND"}
384
+ end
385
+
368
386
  def encoded_credentials
369
387
  credentials = "#{@options[:login]}:#{@options[:password]}"
370
388
  "Basic #{[credentials].pack('m').strip}"
371
389
  end
390
+
391
+ def currency_exponent(currency)
392
+ return 0 if non_fractional_currency?(currency)
393
+ return 3 if three_decimal_currency?(currency)
394
+ return 2
395
+ end
372
396
  end
373
397
  end
374
398
  end
@@ -1,3 +1,3 @@
1
1
  module ActiveMerchant
2
- VERSION = "1.68.0"
2
+ VERSION = "1.69.0"
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.68.0
4
+ version: 1.69.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Tobias Luetke
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2017-06-28 00:00:00.000000000 Z
11
+ date: 2017-07-14 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: activesupport