activemerchant 1.59.0 → 1.60.0

Sign up to get free protection for your applications and to get access to all the features.
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) }