activemerchant 1.59.0 → 1.60.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 (29) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG +41 -0
  3. data/README.md +2 -2
  4. data/lib/active_merchant/billing/gateway.rb +3 -1
  5. data/lib/active_merchant/billing/gateways/authorize_net.rb +16 -5
  6. data/lib/active_merchant/billing/gateways/authorize_net_cim.rb +6 -4
  7. data/lib/active_merchant/billing/gateways/braintree_blue.rb +19 -3
  8. data/lib/active_merchant/billing/gateways/clearhaus.rb +6 -35
  9. data/lib/active_merchant/billing/gateways/cyber_source.rb +20 -8
  10. data/lib/active_merchant/billing/gateways/data_cash.rb +10 -304
  11. data/lib/active_merchant/billing/gateways/elavon.rb +40 -26
  12. data/lib/active_merchant/billing/gateways/global_transport.rb +1 -0
  13. data/lib/active_merchant/billing/gateways/maxipago.rb +144 -122
  14. data/lib/active_merchant/billing/gateways/openpay.rb +1 -0
  15. data/lib/active_merchant/billing/gateways/orbital.rb +3 -1
  16. data/lib/active_merchant/billing/gateways/pagarme.rb +248 -0
  17. data/lib/active_merchant/billing/gateways/psl_card.rb +3 -3
  18. data/lib/active_merchant/billing/gateways/quickpay/quickpay_common.rb +1 -1
  19. data/lib/active_merchant/billing/gateways/quickpay/quickpay_v10.rb +0 -2
  20. data/lib/active_merchant/billing/gateways/quickpay/quickpay_v4to7.rb +1 -1
  21. data/lib/active_merchant/billing/gateways/redsys.rb +1 -0
  22. data/lib/active_merchant/billing/gateways/sage_pay.rb +24 -7
  23. data/lib/active_merchant/billing/gateways/stripe.rb +21 -11
  24. data/lib/active_merchant/billing/gateways/tns.rb +11 -2
  25. data/lib/active_merchant/billing/gateways/trans_first_transaction_express.rb +1 -1
  26. data/lib/active_merchant/billing/gateways/visanet_peru.rb +19 -28
  27. data/lib/active_merchant/version.rb +1 -1
  28. metadata +3 -3
  29. data/lib/active_merchant/billing/gateways/certo_direct.rb +0 -278
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 1b699a9e799907880fbd2fb3c7cc68e8f1bdaead
4
- data.tar.gz: aba5081dee95a33710e5ac97bed5edd577cb1e33
3
+ metadata.gz: 7d43ab38ffa5badee3266ac1da82758f7f5a928d
4
+ data.tar.gz: 044674b27950c204a881c24ef8556e4d01841f22
5
5
  SHA512:
6
- metadata.gz: f1ca11be38d85bcea0dcca1cb3b036090d2f37535e0987159071e40345220c14b19f2b2c314e44c81bc1652c3195306bbed61badec33a17ccefca951a21b2182
7
- data.tar.gz: 68eddb6d812f974fe3ad0d8569bdab2374acffd012fac3bfa95c422958e61666c7994a482da845cb04f9eef9a54fc573ddebd291b08242757115ad5614bc0406
6
+ metadata.gz: 304da6ed75b96dbfa07fb1546f318a224a021c46d2d528b29db4d821858838c28ea4b3ecc9b7319d739281224a6e42c7a5880bd7f06483165f92d8b99f544d80
7
+ data.tar.gz: 889d972567c2b9cb383b29f8c472e27047b6e5b229e512b85478d9b60759014968c23963c1b48fe3b2aa1db7c36c9323e5fe5011cc00e4e3173db0c397e13f5f
data/CHANGELOG CHANGED
@@ -1,5 +1,46 @@
1
1
  = ActiveMerchant CHANGELOG
2
2
 
3
+ == Version 1.60.0 (July 4, 2016)
4
+ * Orbital: Fix CC num leak on profile calls [drewblas]
5
+ * VisaNetPeru: Add ability to refund [duff]
6
+ * AuthorizeNet: Fix store using new profile [duff]
7
+ * Clearhaus: Support private key for signature [curiousepic]
8
+ * Clearhaus: Copy private_key when stripping [curiousepic]
9
+ * CertoDirect: Remove gateway [shiroginne]
10
+ * Braintree: Extra error messaging [jordan-brough]
11
+ * AuthorizeNetCim: Set error code for AuthorizeNetCimGateway response [ka8725]
12
+ * Quickpay v10: Remove amount requirement for store [curiousepic]
13
+ * PSLCards: correct namespace in doc for Response object from ActiveRecord::Billing to ActiveMerchant::Billing [CJ Keeney]
14
+ * Pagar.me: Add pagar.me [chrisenytc]
15
+ * Stripe: Update Readme to show stripe support [rhlrjv]
16
+ * Orbital: Add support for the BRL currency [duff]
17
+ * GlobalTransport: Require TLSv1 [duff]
18
+ * Openpay: Allow currency to be specified [darkaz]
19
+ * DataCash: Use API version 2 [curiousepic]
20
+ * Stripe: Support verify_credentials [duff]
21
+ * AuthorizeNet: Support verify_credentials [duff]
22
+ * BraintreeBlue: Support verify_credentials [duff]
23
+ * Redsys: Added SAR currency [agseco]
24
+ * QuickPay: Adding customer_ip for authorize action in quickpay [dinesh]
25
+ * MaxiPago: add void and refund [shasum]
26
+ * MaxiPago: Allow processor_id override [duff]
27
+ * Stripe: Interpret string input to store method as token identifier [bizla]
28
+ * MaxiPago: Add verify and scrub [shasum]
29
+ * Stripe: Remove metadata restriction from EMV transactions [bizla]
30
+ * SagePay: Add optional fields to SagePay requests [cristianstanescu]
31
+ * CyberSource: Assign default with override for billing address and email [shasum]
32
+ * CyberSource: Assign default order_id [duff]
33
+ * TNS: Support asia_pacific endpoint [curiousepic]
34
+ * TransFirsTransactionExpress: Fix exception [duff]
35
+ * CyberSource: Add decision manager optional fields [shasum]
36
+ * CyberSource: Add decision manager optional fields [shasum]
37
+ * TNS: Add support for TLS v1.2 [curiousepic]
38
+ * QuickpayV7: Default description field for store operation [duff]
39
+ * Elavon: Support customer_number field [duff]
40
+ * Map test_mode_live_card code to new standard error code [berkcaputcu]
41
+ * Elavon: Pass customer_number correctly [duff]
42
+ * Stripe: add SG to supported_countries attribute [timbeiko]
43
+
3
44
  == Version 1.59.0 (May 18, 2016)
4
45
  * Orbital: Allow AVS parts to be sent sans country [duff]
5
46
  * SecureNet: Return the right error message for declines [duff]
data/README.md CHANGED
@@ -105,7 +105,6 @@ The [ActiveMerchant Wiki](http://github.com/activemerchant/active_merchant/wikis
105
105
  * [Cecabank](http://www.ceca.es/es/) - ES
106
106
  * [Cenpos](https://www.cenpos.com/) - AD, AI, AG, AR, AU, AT, BS, BB, BE, BZ, BM, BR, BN, BG, CA, HR, CY, CZ, DK, DM, EE, FI, FR, DE, GR, GD, GY, HK, HU, IS, IN, IL, IT, JP, LV, LI, LT, LU, MY, MT, MX, MC, MS, NL, PA, PL, PT, KN, LC, MF, VC, SM, SG, SK, SI, ZA, ES, SR, SE, CH, TR, GB, US, UY
107
107
  * [CAMS: Central Account Management System](https://www.centralams.com/) - US
108
- * [CertoDirect](http://www.certodirect.com/) - BE, BG, CZ, DK, DE, EE, IE, EL, ES, FR, IT, CY, LV, LT, LU, HU, MT, NL, AT, PL, PT, RO, SI, SK, FI, SE, GB
109
108
  * [Checkout.com](https://www.checkout.com/) - AT, BE, BG, CY, CZ, DE, DK, EE, ES, FI, FR, GR, HR, HU, IE, IS, IT, LI, LT, LU, LV, MT, MU, NL, NO, PL, PT, RO, SE, SI, SK, US
110
109
  * [Clearhaus](https://www.clearhaus.com) - AD, AT, BE, BG, CH, CY, CZ, DE, DK, EE, ES, FI, FO, FR, GB, GL, GR, HR, HU, IE, IS, IT, LI, LT, LU, LV, MT, NL, NO, PL, PT, RO, SE, SI, SK
111
110
  * [Commercegate](http://www.commercegate.com/) - AD, AT, AX, BE, BG, CH, CY, CZ, DE, DK, ES, FI, FR, GB, GG, GI, GR, HR, HU, IE, IM, IS, IT, JE, LI, LT, LU, LV, MC, MT, NL, NO, PL, PT, RO, SE, SI, SK, VA
@@ -167,6 +166,7 @@ The [ActiveMerchant Wiki](http://github.com/activemerchant/active_merchant/wikis
167
166
  * [Openpay](Openpay) - MX
168
167
  * [Optimal Payments](http://www.optimalpayments.com/) - CA, US, GB
169
168
  * [Orbital Paymentech](http://chasepaymentech.com/) - US, CA
169
+ * [Pagar.me](https://pagar.me/) - BR
170
170
  * [PagoFacil](http://www.pagofacil.net/) - MX
171
171
  * [PayConex](http://www.bluefincommerce.com/) - US, CA
172
172
  * [PayGate PayXML](http://paygate.co.za/) - US, ZA
@@ -212,7 +212,7 @@ The [ActiveMerchant Wiki](http://github.com/activemerchant/active_merchant/wikis
212
212
  * [SkipJack](http://www.skipjack.com/) - US, CA
213
213
  * [SoEasyPay](http://www.soeasypay.com/) - US, CA, AT, BE, BG, HR, CY, CZ, DK, EE, FI, FR, DE, GR, HU, IE, IT, LV, LT, LU, MT, NL, PL, PT, RO, SK, SI, ES, SE, GB, IS, NO, CH
214
214
  * [Spreedly](https://spreedly.com) - AD, AE, AT, AU, BD, BE, BG, BN, CA, CH, CY, CZ, DE, DK, EE, EG, ES, FI, FR, GB, GI, GR, HK, HU, ID, IE, IL, IM, IN, IS, IT, JO, KW, LB, LI, LK, LT, LU, LV, MC, MT, MU, MV, MX, MY, NL, NO, NZ, OM, PH, PL, PT, QA, RO, SA, SE, SG, SI, SK, SM, TR, TT, UM, US, VA, VN, ZA
215
- * [Stripe](https://stripe.com/) - AT, AU, BE, CA, CH, DE, DK, ES, FI, FR, GB, IE, IT, LU, NL, NO, SE, US
215
+ * [Stripe](https://stripe.com/) - AT, AU, BE, CA, CH, DE, DK, ES, FI, FR, GB, IE, IT, LU, NL, NO, SE, SG, US
216
216
  * [Swipe](https://www.swipehq.com/checkout) - CA, NZ
217
217
  * [TNS](http://www.tnsi.com/) - AR, AU, BR, FR, DE, HK, MX, NZ, SG, GB, US
218
218
  * [Transact Pro](https://www.transactpro.lv/business/online-payments-acceptance) - US
@@ -76,6 +76,7 @@ module ActiveMerchant #:nodoc:
76
76
  # :processing_error - Processor error
77
77
  # :call_issuer - Transaction requires voice authentication, call issuer
78
78
  # :pickup_card - Issuer requests that you pickup the card from merchant
79
+ # :test_mode_live_card - Card was declined. Request was in test mode, but used a non test card.
79
80
 
80
81
  STANDARD_ERROR_CODE = {
81
82
  :incorrect_number => 'incorrect_number',
@@ -91,7 +92,8 @@ module ActiveMerchant #:nodoc:
91
92
  :processing_error => 'processing_error',
92
93
  :call_issuer => 'call_issuer',
93
94
  :pickup_card => 'pick_up_card',
94
- :config_error => 'config_error'
95
+ :config_error => 'config_error',
96
+ :test_mode_live_card => 'test_mode_live_card'
95
97
  }
96
98
 
97
99
  cattr_reader :implementations
@@ -1,7 +1,7 @@
1
1
  require 'nokogiri'
2
2
 
3
- module ActiveMerchant #:nodoc:
4
- module Billing #:nodoc:
3
+ module ActiveMerchant
4
+ module Billing
5
5
  class AuthorizeNetGateway < Gateway
6
6
  include Empty
7
7
 
@@ -161,6 +161,11 @@ module ActiveMerchant #:nodoc:
161
161
  end
162
162
  end
163
163
 
164
+ def verify_credentials
165
+ response = commit(:verify_credentials) { }
166
+ response.success?
167
+ end
168
+
164
169
  def supports_scrubbing?
165
170
  true
166
171
  end
@@ -580,7 +585,7 @@ module ActiveMerchant #:nodoc:
580
585
  end
581
586
 
582
587
  def parse(action, raw_response)
583
- if is_cim_action?(action)
588
+ if is_cim_action?(action) || action == :verify_credentials
584
589
  parse_cim(raw_response)
585
590
  else
586
591
  parse_normal(action, raw_response)
@@ -628,6 +633,8 @@ module ActiveMerchant #:nodoc:
628
633
  "createCustomerProfileRequest"
629
634
  elsif action == :cim_store_update
630
635
  "createCustomerPaymentProfileRequest"
636
+ elsif action == :verify_credentials
637
+ "authenticateTestRequest"
631
638
  elsif is_cim_action?(action)
632
639
  "createCustomerProfileTransactionRequest"
633
640
  else
@@ -738,7 +745,7 @@ module ActiveMerchant #:nodoc:
738
745
  end
739
746
 
740
747
  def success_from(action, response)
741
- if action == :cim_store
748
+ if cim?(action) || (action == :verify_credentials)
742
749
  response[:result_code] == "Ok"
743
750
  else
744
751
  response[:response_code] == APPROVED && TRANSACTION_ALREADY_ACTIONED.exclude?(response[:response_reason_code])
@@ -758,7 +765,7 @@ module ActiveMerchant #:nodoc:
758
765
  end
759
766
 
760
767
  def authorization_from(action, response)
761
- if action == :cim_store
768
+ if cim?(action)
762
769
  [response[:customer_profile_id], response[:customer_payment_profile_id], action].join("#")
763
770
  else
764
771
  [response[:transaction_id], response[:account_number], action].join("#")
@@ -769,6 +776,10 @@ module ActiveMerchant #:nodoc:
769
776
  authorization.split("#")
770
777
  end
771
778
 
779
+ def cim?(action)
780
+ (action == :cim_store) || (action == :cim_store_update)
781
+ end
782
+
772
783
  def transaction_id_from(authorization)
773
784
  transaction_id, _, _ = split_authorization(authorization)
774
785
  transaction_id
@@ -864,10 +864,12 @@ module ActiveMerchant #:nodoc:
864
864
  response_params['direct_response'] = parse_direct_response(response_params['direct_response']) if response_params['direct_response']
865
865
  transaction_id = response_params['direct_response']['transaction_id'] if response_params['direct_response']
866
866
 
867
- Response.new(success, message, response_params,
868
- :test => test_mode,
869
- :authorization => transaction_id || response_params['customer_profile_id'] || (response_params['profile'] ? response_params['profile']['customer_profile_id'] : nil)
870
- )
867
+ response_options = {}
868
+ response_options[:test] = test_mode
869
+ response_options[:authorization] = transaction_id || response_params['customer_profile_id'] || (response_params['profile'] ? response_params['profile']['customer_profile_id'] : nil)
870
+ response_options[:error_code] = response_params['messages']['message']['code'] unless success
871
+
872
+ Response.new(success, message, response_params, response_options)
871
873
  end
872
874
 
873
875
  def tag_unless_blank(xml, tag_name, data)
@@ -6,7 +6,9 @@ rescue LoadError
6
6
  raise "Could not load the braintree gem. Use `gem install braintree` to install it."
7
7
  end
8
8
 
9
- raise "Need braintree gem 2.x.y. Run `gem install braintree --version '~>2.0'` to get the correct version." unless Braintree::Version::Major == 2
9
+ unless Braintree::Version::Major == 2 && Braintree::Version::Minor >= 4
10
+ raise "Need braintree gem >= 2.4.0. Run `gem install braintree --version '~>2.4'` to get the correct version."
11
+ end
10
12
 
11
13
  module ActiveMerchant #:nodoc:
12
14
  module Billing #:nodoc:
@@ -173,6 +175,18 @@ module ActiveMerchant #:nodoc:
173
175
  true
174
176
  end
175
177
 
178
+ def verify_credentials
179
+ begin
180
+ @braintree_gateway.transaction.find("non_existent_token")
181
+ rescue Braintree::AuthenticationError
182
+ return false
183
+ rescue Braintree::NotFoundError
184
+ return true
185
+ end
186
+
187
+ true
188
+ end
189
+
176
190
  private
177
191
 
178
192
  def check_customer_exists(customer_vault_id)
@@ -311,10 +325,12 @@ module ActiveMerchant #:nodoc:
311
325
  def message_from_result(result)
312
326
  if result.success?
313
327
  "OK"
314
- elsif result.errors.size == 0 && result.credit_card_verification
328
+ elsif result.errors.any?
329
+ result.errors.map { |e| "#{e.message} (#{e.code})" }.join(" ")
330
+ elsif result.credit_card_verification
315
331
  "Processor declined: #{result.credit_card_verification.processor_response_text} (#{result.credit_card_verification.processor_response_code})"
316
332
  else
317
- result.errors.map { |e| "#{e.message} (#{e.code})" }.join(" ")
333
+ result.message.to_s
318
334
  end
319
335
  end
320
336
 
@@ -37,22 +37,12 @@ module ActiveMerchant #:nodoc:
37
37
  50000 => 'Clearhaus error'
38
38
  }
39
39
 
40
- # Create gateway
41
- #
42
- # options:
43
- # :api_key - merchant's Clearhaus API Key
44
- # :signing_key - merchant's private key for optionally signing request
45
40
  def initialize(options={})
46
41
  requires!(options, :api_key)
47
- options[:signing_key].strip! if options[:signing_key]
42
+ options[:private_key] = options[:private_key].strip if options[:private_key]
48
43
  super
49
44
  end
50
45
 
51
- # Make a purchase (authorize and capture)
52
- #
53
- # amount - The monetary amount of the transaction in cents.
54
- # payment - The CreditCard or the Clearhaus card token.
55
- # options - A standard ActiveMerchant options hash
56
46
  def purchase(amount, payment, options={})
57
47
  MultiResponse.run(:use_first_response) do |r|
58
48
  r.process { authorize(amount, payment, options) }
@@ -60,11 +50,6 @@ module ActiveMerchant #:nodoc:
60
50
  end
61
51
  end
62
52
 
63
- # Authorize a transaction.
64
- #
65
- # amount - The monetary amount of the transaction in cents.
66
- # payment - The CreditCard or the Clearhaus card token.
67
- # options - A standard ActiveMerchant options hash with optional pares
68
53
  def authorize(amount, payment, options={})
69
54
  post = {}
70
55
  add_invoice(post, amount, options)
@@ -84,11 +69,6 @@ module ActiveMerchant #:nodoc:
84
69
  commit(action, post)
85
70
  end
86
71
 
87
- # Capture a pre-authorized transaction.
88
- #
89
- # amount - The monetary amount of the transaction in cents.
90
- # authorization - The Clearhaus authorization id string.
91
- # options - A standard ActiveMerchant options hash
92
72
  def capture(amount, authorization, options={})
93
73
  post = {}
94
74
  add_invoice(post, amount, options)
@@ -96,11 +76,6 @@ module ActiveMerchant #:nodoc:
96
76
  commit("/authorizations/#{authorization}/captures", post)
97
77
  end
98
78
 
99
- # Refund a captured transaction (fully or partial).
100
- #
101
- # amount - The monetary amount of the transaction in cents.
102
- # authorization - The Clearhaus authorization id string.
103
- # options - A standard ActiveMerchant options hash
104
79
  def refund(amount, authorization, options={})
105
80
  post = {}
106
81
  add_amount(post, amount, options)
@@ -119,10 +94,6 @@ module ActiveMerchant #:nodoc:
119
94
  end
120
95
  end
121
96
 
122
- # Tokenize credit card with Clearhaus.
123
- #
124
- # credit_card - The CreditCard.
125
- # options - A standard ActiveMerchant options hash
126
97
  def store(credit_card, options={})
127
98
  post = {}
128
99
  add_payment(post, credit_card)
@@ -183,9 +154,9 @@ module ActiveMerchant #:nodoc:
183
154
  headers = headers(@options[:api_key])
184
155
  body = parameters.to_query
185
156
 
186
- if signing_key = @options[:signing_key]
157
+ if @options[:signing_key] && @options[:private_key]
187
158
  begin
188
- headers["Signature"] = generate_signature(@options[:api_key], signing_key, body)
159
+ headers["Signature"] = generate_signature(body)
189
160
  rescue OpenSSL::PKey::RSAError => e
190
161
  return Response.new(false, e.message)
191
162
  end
@@ -226,11 +197,11 @@ module ActiveMerchant #:nodoc:
226
197
  response['id']
227
198
  end
228
199
 
229
- def generate_signature(api_key, signing_key, body)
230
- key = OpenSSL::PKey::RSA.new(signing_key)
200
+ def generate_signature(body)
201
+ key = OpenSSL::PKey::RSA.new(@options[:private_key])
231
202
  hex = key.sign(OpenSSL::Digest.new('sha256'), body).unpack('H*').first
232
203
 
233
- "#{api_key} RS256-hex #{hex}"
204
+ "#{@options[:signing_key]} RS256-hex #{hex}"
234
205
  end
235
206
 
236
207
  def error_code_from(response)
@@ -120,7 +120,6 @@ module ActiveMerchant #:nodoc:
120
120
  #
121
121
  # You must supply an :order_id in the options hash
122
122
  def authorize(money, creditcard_or_reference, options = {})
123
- requires!(options, :order_id)
124
123
  setup_address_hash(options)
125
124
  commit(build_auth_request(money, creditcard_or_reference, options), options )
126
125
  end
@@ -139,7 +138,6 @@ module ActiveMerchant #:nodoc:
139
138
  # You must supply an order_id in the options hash
140
139
  # options[:pinless_debit_card] => true # attempts to process as pinless debit card
141
140
  def purchase(money, payment_method_or_reference, options = {})
142
- requires!(options, :order_id)
143
141
  setup_address_hash(options)
144
142
  commit(build_purchase_request(money, payment_method_or_reference, options), options)
145
143
  end
@@ -161,7 +159,6 @@ module ActiveMerchant #:nodoc:
161
159
 
162
160
  # Adds credit to a subscription (stand alone credit).
163
161
  def credit(money, reference, options = {})
164
- requires!(options, :order_id)
165
162
  commit(build_credit_request(money, reference, options), options)
166
163
  end
167
164
 
@@ -169,7 +166,6 @@ module ActiveMerchant #:nodoc:
169
166
  # To charge the card while creating a profile, pass
170
167
  # options[:setup_fee] => money
171
168
  def store(payment_method, options = {})
172
- requires!(options, :order_id)
173
169
  setup_address_hash(options)
174
170
  commit(build_create_subscription_request(payment_method, options), options)
175
171
  end
@@ -252,15 +248,23 @@ module ActiveMerchant #:nodoc:
252
248
  private
253
249
 
254
250
  # Create all address hash key value pairs so that we still function if we
255
- # were only provided with one or two of them
251
+ # were only provided with one or two of them or even none
256
252
  def setup_address_hash(options)
257
- options[:billing_address] = options[:billing_address] || options[:address] || {}
253
+ default_address = {
254
+ :address1 => 'Unspecified',
255
+ :city => 'Unspecified',
256
+ :state => 'NC',
257
+ :zip => '00000',
258
+ :country => 'US'
259
+ }
260
+ options[:billing_address] = options[:billing_address] || options[:address] || default_address
258
261
  options[:shipping_address] = options[:shipping_address] || {}
259
262
  end
260
263
 
261
264
  def build_auth_request(money, creditcard_or_reference, options)
262
265
  xml = Builder::XmlMarkup.new :indent => 2
263
266
  add_payment_method_or_subscription(xml, money, creditcard_or_reference, options)
267
+ add_decision_manager_fields(xml, options)
264
268
  add_mdd_fields(xml, options)
265
269
  add_auth_service(xml, creditcard_or_reference, options)
266
270
  add_business_rules_data(xml, creditcard_or_reference, options)
@@ -292,6 +296,7 @@ module ActiveMerchant #:nodoc:
292
296
  def build_purchase_request(money, payment_method_or_reference, options)
293
297
  xml = Builder::XmlMarkup.new :indent => 2
294
298
  add_payment_method_or_subscription(xml, money, payment_method_or_reference, options)
299
+ add_decision_manager_fields(xml, options)
295
300
  add_mdd_fields(xml, options)
296
301
  if !payment_method_or_reference.is_a?(String) && card_brand(payment_method_or_reference) == 'check'
297
302
  add_check_service(xml)
@@ -435,7 +440,7 @@ module ActiveMerchant #:nodoc:
435
440
 
436
441
  def add_merchant_data(xml, options)
437
442
  xml.tag! 'merchantID', @options[:login]
438
- xml.tag! 'merchantReferenceCode', options[:order_id]
443
+ xml.tag! 'merchantReferenceCode', options[:order_id] || generate_unique_id
439
444
  xml.tag! 'clientLibrary' ,'Ruby Active Merchant'
440
445
  xml.tag! 'clientLibraryVersion', VERSION
441
446
  xml.tag! 'clientEnvironment' , RUBY_PLATFORM
@@ -461,7 +466,7 @@ module ActiveMerchant #:nodoc:
461
466
  xml.tag! 'company', address[:company] unless address[:company].blank?
462
467
  xml.tag! 'companyTaxID', address[:companyTaxID] unless address[:company_tax_id].blank?
463
468
  xml.tag! 'phoneNumber', address[:phone] unless address[:phone].blank?
464
- xml.tag! 'email', options[:email]
469
+ xml.tag! 'email', options[:email] || 'null@cybersource.com'
465
470
  xml.tag! 'ipAddress', options[:ip] unless options[:ip].blank? || shipTo
466
471
  xml.tag! 'driversLicenseNumber', options[:drivers_license_number] unless options[:drivers_license_number].blank?
467
472
  xml.tag! 'driversLicenseState', options[:drivers_license_state] unless options[:drivers_license_state].blank?
@@ -478,6 +483,13 @@ module ActiveMerchant #:nodoc:
478
483
  end
479
484
  end
480
485
 
486
+ def add_decision_manager_fields(xml, options)
487
+ xml.tag! 'decisionManager' do
488
+ xml.tag! 'enabled', options[:decision_manager_enabled] if options[:decision_manager_enabled]
489
+ xml.tag! 'profile', options[:decision_manager_profile] if options[:decision_manager_profile]
490
+ end
491
+ end
492
+
481
493
  def add_mdd_fields(xml, options)
482
494
  xml.tag! 'merchantDefinedData' do
483
495
  (1..20).each do |each|
@@ -6,23 +6,14 @@ module ActiveMerchant
6
6
  self.default_currency = 'GBP'
7
7
  self.supported_countries = ['GB']
8
8
 
9
- # From the DataCash docs; Page 13, the following cards are
10
- # usable:
11
- # American Express, ATM, Carte Blanche, Diners Club, Discover,
12
- # EnRoute, GE Capital, JCB, Laser, Maestro, Mastercard, Solo,
13
- # Switch, Visa, Visa Delta, VISA Electron, Visa Purchasing
14
- #
15
- # Note continuous authority is only supported for :visa, :master and :american_express card types
16
9
  self.supported_cardtypes = [ :visa, :master, :american_express, :discover, :diners_club, :jcb, :maestro, :switch, :solo, :laser ]
17
10
 
18
11
  self.homepage_url = 'http://www.datacash.com/'
19
12
  self.display_name = 'DataCash'
20
13
 
21
- # Datacash server URLs
22
14
  self.test_url = 'https://testserver.datacash.com/Transaction'
23
15
  self.live_url = 'https://mars.transaction.datacash.com/Transaction'
24
16
 
25
- # Different Card Transaction Types
26
17
  AUTH_TYPE = 'auth'
27
18
  CANCEL_TYPE = 'cancel'
28
19
  FULFILL_TYPE = 'fulfill'
@@ -30,44 +21,14 @@ module ActiveMerchant
30
21
  REFUND_TYPE = 'refund'
31
22
  TRANSACTION_REFUND_TYPE = 'txn_refund'
32
23
 
33
- # Constant strings for use in the ExtendedPolicy complex element for
34
- # CV2 checks
35
24
  POLICY_ACCEPT = 'accept'
36
25
  POLICY_REJECT = 'reject'
37
26
 
38
- # Datacash success code
39
- DATACASH_SUCCESS = '1'
40
-
41
- # Creates a new DataCashGateway
42
- #
43
- # The gateway requires that a valid login and password be passed
44
- # in the +options+ hash.
45
- #
46
- # ==== Options
47
- #
48
- # * <tt>:login</tt> -- The Datacash account login.
49
- # * <tt>:password</tt> -- The Datacash account password.
50
- # * <tt>:test => +true+ or +false+</tt> -- Use the test or live Datacash url.
51
- #
52
27
  def initialize(options = {})
53
28
  requires!(options, :login, :password)
54
29
  super
55
30
  end
56
31
 
57
- # Perform a purchase, which is essentially an authorization and capture in a single operation.
58
- #
59
- # ==== Parameters
60
- # * <tt>money</tt> The amount to be authorized as an Integer value in cents.
61
- # * <tt>authorization_or_credit_card</tt>:: The continuous authority reference or CreditCard details for the transaction.
62
- # * <tt>options</tt> A hash of optional parameters.
63
- # * <tt>:order_id</tt> A unique reference for this order (corresponds to merchantreference in datacash documentation)
64
- # * <tt>:set_up_continuous_authority</tt>
65
- # Set to true to set up a recurring historic transaction account be set up.
66
- # Only supported for :visa, :master and :american_express card types
67
- # See http://www.datacash.com/services/recurring/historic.php for more details of historic transactions.
68
- # * <tt>:address</tt>:: billing address for card
69
- #
70
- # The continuous authority reference will be available in response#params['ca_reference'] if you have requested one
71
32
  def purchase(money, authorization_or_credit_card, options = {})
72
33
  requires!(options, :order_id)
73
34
 
@@ -80,22 +41,6 @@ module ActiveMerchant
80
41
  commit(request)
81
42
  end
82
43
 
83
- # Performs an authorization, which reserves the funds on the customer's credit card, but does not
84
- # charge the card.
85
- #
86
- # ==== Parameters
87
- #
88
- # * <tt>money</tt> The amount to be authorized as an Integer value in cents.
89
- # * <tt>authorization_or_credit_card</tt>:: The continuous authority reference or CreditCard details for the transaction.
90
- # * <tt>options</tt> A hash of optional parameters.
91
- # * <tt>:order_id</tt> A unique reference for this order (corresponds to merchantreference in datacash documentation)
92
- # * <tt>:set_up_continuous_authority</tt>::
93
- # Set to true to set up a recurring historic transaction account be set up.
94
- # Only supported for :visa, :master and :american_express card types
95
- # See http://www.datacash.com/services/recurring/historic.php for more details of historic transactions.
96
- # * <tt>:address</tt>:: billing address for card
97
- #
98
- # The continuous authority reference will be available in response#params['ca_reference'] if you have requested one
99
44
  def authorize(money, authorization_or_credit_card, options = {})
100
45
  requires!(options, :order_id)
101
46
 
@@ -108,42 +53,22 @@ module ActiveMerchant
108
53
  commit(request)
109
54
  end
110
55
 
111
- # Captures the funds from an authorized transaction.
112
- #
113
- # ==== Parameters
114
- #
115
- # * <tt>money</tt> -- The amount to be captured as anInteger value in cents.
116
- # * <tt>authorization</tt> -- The authorization returned from the previous authorize request.
117
56
  def capture(money, authorization, options = {})
118
57
  commit(build_void_or_capture_request(FULFILL_TYPE, money, authorization, options))
119
58
  end
120
59
 
121
- # Void a previous transaction
122
- #
123
- # ==== Parameters
124
- #
125
- # * <tt>authorization</tt> - The authorization returned from the previous authorize request.
126
60
  def void(authorization, options = {})
127
61
  request = build_void_or_capture_request(CANCEL_TYPE, nil, authorization, options)
128
62
 
129
63
  commit(request)
130
64
  end
131
65
 
132
- # Refund to a card
133
- #
134
- # ==== Parameters
135
- #
136
- # * <tt>money</tt> The amount to be refunded as an Integer value in cents. Set to nil for a full refund on existing transaction.
137
- # * <tt>reference_or_credit_card</tt> The credit card you want to refund OR the datacash_reference for the existing transaction you are refunding
138
- # * <tt>options</tt> Are ignored when refunding via reference to an existing transaction, otherwise
139
- # * <tt>:order_id</tt> A unique reference for this order (corresponds to merchantreference in datacash documentation)
140
- # * <tt>:address</tt>:: billing address for card
141
66
  def credit(money, reference_or_credit_card, options = {})
142
67
  if reference_or_credit_card.is_a?(String)
143
68
  ActiveMerchant.deprecated CREDIT_DEPRECATION_MESSAGE
144
69
  refund(money, reference_or_credit_card)
145
70
  else
146
- request = build_refund_request(money, reference_or_credit_card, options)
71
+ request = build_credit_request(money, reference_or_credit_card, options)
147
72
  commit(request)
148
73
  end
149
74
  end
@@ -152,42 +77,14 @@ module ActiveMerchant
152
77
  commit(build_transaction_refund_request(money, reference))
153
78
  end
154
79
 
80
+
155
81
  private
156
- # Create the xml document for a 'cancel' or 'fulfill' transaction.
157
- #
158
- # Final XML should look like:
159
- # <Request>
160
- # <Authentication>
161
- # <client>99000001</client>
162
- # <password>******</password>
163
- # </Authentication>
164
- # <Transaction>
165
- # <TxnDetails>
166
- # <amount>25.00</amount>
167
- # </TxnDetails>
168
- # <HistoricTxn>
169
- # <reference>4900200000000001</reference>
170
- # <authcode>A6</authcode>
171
- # <method>fulfill</method>
172
- # </HistoricTxn>
173
- # </Transaction>
174
- # </Request>
175
- #
176
- # Parameters:
177
- # * <tt>type</tt> must be FULFILL_TYPE or CANCEL_TYPE
178
- # * <tt>money</tt> - optional - Integer value in cents
179
- # * <tt>authorization</tt> - the Datacash authorization from a previous succesful authorize transaction
180
- # * <tt>options</tt>
181
- # * <tt>order_id</tt> - A unique reference for the transaction
182
- #
183
- # Returns:
184
- # -Builder xml document
185
- #
82
+
186
83
  def build_void_or_capture_request(type, money, authorization, options)
187
84
  parsed_authorization = parse_authorization_string(authorization)
188
85
  xml = Builder::XmlMarkup.new :indent => 2
189
86
  xml.instruct!
190
- xml.tag! :Request do
87
+ xml.tag! :Request, :version => '2' do
191
88
  add_authentication(xml)
192
89
 
193
90
  xml.tag! :Transaction do
@@ -209,71 +106,10 @@ module ActiveMerchant
209
106
  xml.target!
210
107
  end
211
108
 
212
- # Create the xml document for an 'auth' or 'pre' transaction with a credit card
213
- #
214
- # Final XML should look like:
215
- #
216
- # <Request>
217
- # <Authentication>
218
- # <client>99000000</client>
219
- # <password>*******</password>
220
- # </Authentication>
221
- # <Transaction>
222
- # <TxnDetails>
223
- # <merchantreference>123456</merchantreference>
224
- # <amount currency="EUR">10.00</amount>
225
- # </TxnDetails>
226
- # <CardTxn>
227
- # <Card>
228
- # <pan>4444********1111</pan>
229
- # <expirydate>03/04</expirydate>
230
- # <Cv2Avs>
231
- # <street_address1>Flat 7</street_address1>
232
- # <street_address2>89 Jumble
233
- # Street</street_address2>
234
- # <street_address3>Mytown</street_address3>
235
- # <postcode>AV12FR</postcode>
236
- # <cv2>123</cv2>
237
- # <ExtendedPolicy>
238
- # <cv2_policy notprovided="reject"
239
- # notchecked="accept"
240
- # matched="accept"
241
- # notmatched="reject"
242
- # partialmatch="reject"/>
243
- # <postcode_policy notprovided="reject"
244
- # notchecked="accept"
245
- # matched="accept"
246
- # notmatched="reject"
247
- # partialmatch="accept"/>
248
- # <address_policy notprovided="reject"
249
- # notchecked="accept"
250
- # matched="accept"
251
- # notmatched="reject"
252
- # partialmatch="accept"/>
253
- # </ExtendedPolicy>
254
- # </Cv2Avs>
255
- # </Card>
256
- # <method>auth</method>
257
- # </CardTxn>
258
- # </Transaction>
259
- # </Request>
260
- #
261
- # Parameters:
262
- # -type must be 'auth' or 'pre'
263
- # -money - A money object with the price and currency
264
- # -credit_card - The credit_card details to use
265
- # -options:
266
- # :order_id is the merchant reference number
267
- # :billing_address is the billing address for the cc
268
- # :address is the delivery address
269
- #
270
- # Returns:
271
- # -xml: Builder document containing the markup
272
- #
273
109
  def build_purchase_or_authorization_request_with_credit_card_request(type, money, credit_card, options)
274
110
  xml = Builder::XmlMarkup.new :indent => 2
275
111
  xml.instruct!
276
- xml.tag! :Request do
112
+ xml.tag! :Request, :version => '2' do
277
113
  add_authentication(xml)
278
114
 
279
115
  xml.tag! :Transaction do
@@ -294,47 +130,13 @@ module ActiveMerchant
294
130
  xml.target!
295
131
  end
296
132
 
297
- # Create the xml document for an 'auth' or 'pre' transaction with
298
- # continuous authorization
299
- #
300
- # Final XML should look like:
301
- #
302
- # <Request>
303
- # <Transaction>
304
- # <ContAuthTxn type="historic" />
305
- # <TxnDetails>
306
- # <merchantreference>3851231</merchantreference>
307
- # <capturemethod>cont_auth</capturemethod>
308
- # <amount currency="GBP">18.50</amount>
309
- # </TxnDetails>
310
- # <HistoricTxn>
311
- # <reference>4500200040925092</reference>
312
- # <method>auth</method>
313
- # </HistoricTxn>
314
- # </Transaction>
315
- # <Authentication>
316
- # <client>99000001</client>
317
- # <password>mypasswd</password>
318
- # </Authentication>
319
- # </Request>
320
- #
321
- # Parameters:
322
- # -type must be 'auth' or 'pre'
323
- # -money - A money object with the price and currency
324
- # -authorization - The authorization containing a continuous authority reference previously set up on a credit card
325
- # -options:
326
- # :order_id is the merchant reference number
327
- #
328
- # Returns:
329
- # -xml: Builder document containing the markup
330
- #
331
133
  def build_purchase_or_authorization_request_with_continuous_authority_reference_request(type, money, authorization, options)
332
134
  parsed_authorization = parse_authorization_string(authorization)
333
135
  raise ArgumentError, "The continuous authority reference is required for continuous authority transactions" if parsed_authorization[:ca_reference].blank?
334
136
 
335
137
  xml = Builder::XmlMarkup.new :indent => 2
336
138
  xml.instruct!
337
- xml.tag! :Request do
139
+ xml.tag! :Request, :version => '2' do
338
140
  add_authentication(xml)
339
141
  xml.tag! :Transaction do
340
142
  xml.tag! :ContAuthTxn, :type => 'historic'
@@ -352,31 +154,11 @@ module ActiveMerchant
352
154
  xml.target!
353
155
  end
354
156
 
355
- # Create the xml document for a full or partial refund transaction with
356
- #
357
- # Final XML should look like:
358
- #
359
- # <Request>
360
- # <Authentication>
361
- # <client>99000001</client>
362
- # <password>*******</password>
363
- # </Authentication>
364
- # <Transaction>
365
- # <HistoricTxn>
366
- # <method>txn_refund</method>
367
- # <reference>12345678</reference>
368
- # </HistoricTxn>
369
- # <TxnDetails>
370
- # <amount>10.00</amount>
371
- # </TxnDetails>
372
- # </Transaction>
373
- # </Request>
374
- #
375
157
  def build_transaction_refund_request(money, authorization)
376
158
  parsed_authorization = parse_authorization_string(authorization)
377
159
  xml = Builder::XmlMarkup.new :indent => 2
378
160
  xml.instruct!
379
- xml.tag! :Request do
161
+ xml.tag! :Request, :version => '2' do
380
162
  add_authentication(xml)
381
163
  xml.tag! :Transaction do
382
164
  xml.tag! :HistoricTxn do
@@ -393,34 +175,10 @@ module ActiveMerchant
393
175
  xml.target!
394
176
  end
395
177
 
396
- # Create the xml document for a full or partial refund with
397
- #
398
- # Final XML should look like:
399
- #
400
- # <Request>
401
- # <Authentication>
402
- # <client>99000001</client>
403
- # <password>*****</password>
404
- # </Authentication>
405
- # <Transaction>
406
- # <CardTxn>
407
- # <Card>
408
- # <pan>633300*********1</pan>
409
- # <expirydate>04/06</expirydate>
410
- # <startdate>01/04</startdate>
411
- # </Card>
412
- # <method>refund</method>
413
- # </CardTxn>
414
- # <TxnDetails>
415
- # <merchantreference>1000001</merchantreference>
416
- # <amount currency="GBP">95.99</amount>
417
- # </TxnDetails>
418
- # </Transaction>
419
- # </Request>
420
- def build_refund_request(money, credit_card, options)
178
+ def build_credit_request(money, credit_card, options)
421
179
  xml = Builder::XmlMarkup.new :indent => 2
422
180
  xml.instruct!
423
- xml.tag! :Request do
181
+ xml.tag! :Request, :version => '2' do
424
182
  add_authentication(xml)
425
183
  xml.tag! :Transaction do
426
184
  xml.tag! :CardTxn do
@@ -436,15 +194,6 @@ module ActiveMerchant
436
194
  xml.target!
437
195
  end
438
196
 
439
-
440
- # Adds the authentication element to the passed builder xml doc
441
- #
442
- # Parameters:
443
- # -xml: Builder document that is being built up
444
- #
445
- # Returns:
446
- # -none: The results is stored in the passed xml document
447
- #
448
197
  def add_authentication(xml)
449
198
  xml.tag! :Authentication do
450
199
  xml.tag! :client, @options[:login]
@@ -452,16 +201,6 @@ module ActiveMerchant
452
201
  end
453
202
  end
454
203
 
455
- # Add credit_card details to the passed XML Builder doc
456
- #
457
- # Parameters:
458
- # -xml: Builder document that is being built up
459
- # -credit_card: ActiveMerchant::Billing::CreditCard object
460
- # -billing_address: Hash containing all of the billing address details
461
- #
462
- # Returns:
463
- # -none: The results is stored in the passed xml document
464
- #
465
204
  def add_credit_card(xml, credit_card, address)
466
205
 
467
206
  xml.tag! :Card do
@@ -520,44 +259,19 @@ module ActiveMerchant
520
259
  end
521
260
  end
522
261
 
523
- # Send the passed data to DataCash for processing
524
- #
525
- # Parameters:
526
- # -request: The XML data that is to be sent to Datacash
527
- #
528
- # Returns:
529
- # - ActiveMerchant::Billing::Response object
530
- #
531
262
  def commit(request)
532
263
  response = parse(ssl_post(test? ? self.test_url : self.live_url, request))
533
264
 
534
- Response.new(response[:status] == DATACASH_SUCCESS, response[:reason], response,
265
+ Response.new(response[:status] == '1', response[:reason], response,
535
266
  :test => test?,
536
267
  :authorization => "#{response[:datacash_reference]};#{response[:authcode]};#{response[:ca_reference]}"
537
268
  )
538
269
  end
539
270
 
540
- # Returns a date string in the format Datacash expects
541
- #
542
- # Parameters:
543
- # -month: integer, the month
544
- # -year: integer, the year
545
- #
546
- # Returns:
547
- # -String: date in MM/YY format
548
- #
549
271
  def format_date(month, year)
550
272
  "#{format(month,:two_digits)}/#{format(year, :two_digits)}"
551
273
  end
552
274
 
553
- # Parse the datacash response and create a Response object
554
- #
555
- # Parameters:
556
- # -body: The XML returned from Datacash
557
- #
558
- # Returns:
559
- # -a hash with all of the values returned in the Datacash XML response
560
- #
561
275
  def parse(body)
562
276
 
563
277
  response = {}
@@ -571,14 +285,6 @@ module ActiveMerchant
571
285
  response
572
286
  end
573
287
 
574
- # Parse an xml element
575
- #
576
- # Parameters:
577
- # -response: The hash that the values are being returned in
578
- # -node: The node that is currently being read
579
- #
580
- # Returns:
581
- # - none (results are stored in the passed hash)
582
288
  def parse_element(response, node)
583
289
  if node.has_elements?
584
290
  node.elements.each{|e| parse_element(response, e) }