activemerchant 1.29.3 → 1.30.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 (47) hide show
  1. data.tar.gz.sig +0 -0
  2. data/CHANGELOG +39 -0
  3. data/CONTRIBUTORS +19 -0
  4. data/README.md +43 -41
  5. data/lib/active_merchant/billing/check.rb +15 -11
  6. data/lib/active_merchant/billing/credit_card.rb +5 -1
  7. data/lib/active_merchant/billing/credit_card_formatting.rb +8 -8
  8. data/lib/active_merchant/billing/gateway.rb +1 -1
  9. data/lib/active_merchant/billing/gateways/authorize_net.rb +9 -1
  10. data/lib/active_merchant/billing/gateways/authorize_net_cim.rb +15 -4
  11. data/lib/active_merchant/billing/gateways/balanced.rb +9 -3
  12. data/lib/active_merchant/billing/gateways/banwire.rb +15 -1
  13. data/lib/active_merchant/billing/gateways/beanstream.rb +26 -24
  14. data/lib/active_merchant/billing/gateways/beanstream/beanstream_core.rb +6 -2
  15. data/lib/active_merchant/billing/gateways/braintree_blue.rb +5 -2
  16. data/lib/active_merchant/billing/gateways/cyber_source.rb +55 -22
  17. data/lib/active_merchant/billing/gateways/eway.rb +114 -171
  18. data/lib/active_merchant/billing/gateways/eway_managed.rb +52 -22
  19. data/lib/active_merchant/billing/gateways/firstdata_e4.rb +222 -0
  20. data/lib/active_merchant/billing/gateways/ideal_rabobank.rb +13 -2
  21. data/lib/active_merchant/billing/gateways/litle.rb +50 -19
  22. data/lib/active_merchant/billing/gateways/merchant_ware.rb +44 -9
  23. data/lib/active_merchant/billing/gateways/merchant_warrior.rb +190 -0
  24. data/lib/active_merchant/billing/gateways/moneris.rb +2 -4
  25. data/lib/active_merchant/billing/gateways/nab_transact.rb +20 -3
  26. data/lib/active_merchant/billing/gateways/netbilling.rb +1 -0
  27. data/lib/active_merchant/billing/gateways/netpay.rb +223 -0
  28. data/lib/active_merchant/billing/gateways/optimal_payment.rb +18 -3
  29. data/lib/active_merchant/billing/gateways/orbital.rb +9 -5
  30. data/lib/active_merchant/billing/gateways/payment_express.rb +62 -1
  31. data/lib/active_merchant/billing/gateways/paypal/paypal_common_api.rb +1 -1
  32. data/lib/active_merchant/billing/gateways/paypal_express.rb +2 -0
  33. data/lib/active_merchant/billing/gateways/pin.rb +157 -0
  34. data/lib/active_merchant/billing/gateways/qbms.rb +3 -2
  35. data/lib/active_merchant/billing/gateways/quickpay.rb +66 -28
  36. data/lib/active_merchant/billing/gateways/sage_pay.rb +6 -0
  37. data/lib/active_merchant/billing/gateways/smart_ps.rb +1 -1
  38. data/lib/active_merchant/billing/gateways/spreedly_core.rb +235 -0
  39. data/lib/active_merchant/billing/gateways/stripe.rb +1 -0
  40. data/lib/active_merchant/billing/gateways/wirecard.rb +15 -9
  41. data/lib/active_merchant/billing/integrations/payflow_link/helper.rb +4 -1
  42. data/lib/active_merchant/billing/integrations/paypal/notification.rb +39 -31
  43. data/lib/active_merchant/billing/integrations/quickpay/helper.rb +13 -10
  44. data/lib/active_merchant/billing/integrations/quickpay/notification.rb +14 -14
  45. data/lib/active_merchant/version.rb +1 -1
  46. metadata +109 -49
  47. metadata.gz.sig +0 -0
@@ -71,7 +71,13 @@ module ActiveMerchant #:nodoc:
71
71
  end
72
72
 
73
73
  def commit(money, parameters)
74
- response = parse(ssl_post(URL, post_data(parameters)))
74
+ raw_response = ssl_post(URL, post_data(parameters))
75
+ begin
76
+ response = parse(raw_response)
77
+ rescue JSON::ParserError
78
+ response = json_error(raw_response)
79
+ end
80
+
75
81
  Response.new(success?(response),
76
82
  response["message"],
77
83
  response,
@@ -86,6 +92,14 @@ module ActiveMerchant #:nodoc:
86
92
  def post_data(parameters = {})
87
93
  parameters.collect { |key, value| "#{key}=#{CGI.escape(value.to_s)}" }.join("&")
88
94
  end
95
+
96
+ def json_error(raw_response)
97
+ msg = 'Invalid response received from the Banwire API. Please contact Banwire support if you continue to receive this message.'
98
+ msg += " (The raw response returned by the API was #{raw_response.inspect})"
99
+ {
100
+ "message" => msg
101
+ }
102
+ end
89
103
  end
90
104
  end
91
105
  end
@@ -6,34 +6,34 @@ module ActiveMerchant #:nodoc:
6
6
  # It is also named TD Canada Trust Online Mart payment gateway.
7
7
  # To learn more about the specification of Beanstream gateway, please read the OM_Direct_Interface_API.pdf,
8
8
  # which you can get from your Beanstream account or get from me by email.
9
- #
9
+ #
10
10
  # == Supported transaction types by Beanstream:
11
11
  # * +P+ - Purchase
12
12
  # * +PA+ - Pre Authorization
13
13
  # * +PAC+ - Pre Authorization Completion
14
- #
14
+ #
15
15
  # == Secure Payment Profiles:
16
16
  # BeanStream supports payment profiles (vaults). This allows you to store cc information with BeanStream and process subsequent transactions with a customer id.
17
17
  # Secure Payment Profiles must be enabled on your account (must be done over the phone).
18
18
  # Your API Access Passcode must be set in Administration => account settings => order settings.
19
19
  # To learn more about storing credit cards with the Beanstream gateway, please read the BEAN_Payment_Profiles.pdf (I had to phone BeanStream to request it.)
20
- #
21
- # == Notes
20
+ #
21
+ # == Notes
22
22
  # * Adding of order products information is not implemented.
23
23
  # * Ensure that country and province data is provided as a code such as "CA", "US", "QC".
24
24
  # * login is the Beanstream merchant ID, username and password should be enabled in your Beanstream account and passed in using the <tt>:user</tt> and <tt>:password</tt> options.
25
25
  # * Test your app with your true merchant id and test credit card information provided in the api pdf document.
26
- # * Beanstream does not allow Payment Profiles to be deleted with their API. The accounts are 'closed', but have to be deleted manually.
27
- #
26
+ # * Beanstream does not allow Payment Profiles to be deleted with their API. The accounts are 'closed', but have to be deleted manually.
27
+ #
28
28
  # Example authorization (Beanstream PA transaction type):
29
- #
29
+ #
30
30
  # twenty = 2000
31
31
  # gateway = BeanstreamGateway.new(
32
32
  # :login => '100200000',
33
33
  # :user => 'xiaobozz',
34
34
  # :password => 'password'
35
35
  # )
36
- #
36
+ #
37
37
  # credit_card = CreditCard.new(
38
38
  # :number => '4030000010001234',
39
39
  # :month => 8,
@@ -63,37 +63,39 @@ module ActiveMerchant #:nodoc:
63
63
  # )
64
64
  class BeanstreamGateway < Gateway
65
65
  include BeanstreamCore
66
-
66
+
67
67
  def authorize(money, source, options = {})
68
68
  post = {}
69
69
  add_amount(post, money)
70
70
  add_invoice(post, options)
71
- add_source(post, source)
71
+ add_source(post, source)
72
72
  add_address(post, options)
73
73
  add_transaction_type(post, :authorization)
74
+ add_customer_ip(post, options)
74
75
  commit(post)
75
76
  end
76
-
77
+
77
78
  def purchase(money, source, options = {})
78
79
  post = {}
79
- add_amount(post, money)
80
+ add_amount(post, money)
80
81
  add_invoice(post, options)
81
82
  add_source(post, source)
82
83
  add_address(post, options)
83
84
  add_transaction_type(post, purchase_action(source))
85
+ add_customer_ip(post, options)
84
86
  commit(post)
85
- end
86
-
87
+ end
88
+
87
89
  def void(authorization, options = {})
88
90
  reference, amount, type = split_auth(authorization)
89
-
91
+
90
92
  post = {}
91
93
  add_reference(post, reference)
92
94
  add_original_amount(post, amount)
93
95
  add_transaction_type(post, void_action(type))
94
96
  commit(post)
95
97
  end
96
-
98
+
97
99
  def recurring(money, source, options = {})
98
100
  post = {}
99
101
  add_amount(post, money)
@@ -104,7 +106,7 @@ module ActiveMerchant #:nodoc:
104
106
  add_recurring_type(post, options)
105
107
  commit(post)
106
108
  end
107
-
109
+
108
110
  def update_recurring(amount, source, options = {})
109
111
  post = {}
110
112
  add_recurring_amount(post, amount)
@@ -115,7 +117,7 @@ module ActiveMerchant #:nodoc:
115
117
  add_recurring_service(post, options)
116
118
  recurring_commit(post)
117
119
  end
118
-
120
+
119
121
  def cancel_recurring(options = {})
120
122
  post = {}
121
123
  add_recurring_operation_type(post, :cancel)
@@ -126,25 +128,25 @@ module ActiveMerchant #:nodoc:
126
128
  def interac
127
129
  @interac ||= BeanstreamInteracGateway.new(@options)
128
130
  end
129
-
131
+
130
132
  # To match the other stored-value gateways, like TrustCommerce,
131
133
  # store and unstore need to be defined
132
134
  def store(credit_card, options = {})
133
- post = {}
135
+ post = {}
134
136
  add_address(post, options)
135
- add_credit_card(post, credit_card)
137
+ add_credit_card(post, credit_card)
136
138
  add_secure_profile_variables(post,options)
137
139
  commit(post, true)
138
140
  end
139
-
141
+
140
142
  #can't actually delete a secure profile with the supplicaed API. This function sets the status of the profile to closed (C).
141
143
  #Closed profiles will have to removed manually.
142
144
  def delete(vault_id)
143
145
  update(vault_id, false, {:status => "C"})
144
146
  end
145
-
147
+
146
148
  alias_method :unstore, :delete
147
-
149
+
148
150
  # Update the values (such as CC expiration) stored at
149
151
  # the gateway. The CC number must be supplied in the
150
152
  # CreditCard object.
@@ -66,7 +66,7 @@ module ActiveMerchant #:nodoc:
66
66
  base.supported_countries = ['CA']
67
67
 
68
68
  # The card types supported by the payment gateway
69
- base.supported_cardtypes = [:visa, :master, :american_express]
69
+ base.supported_cardtypes = [:visa, :master, :american_express, :discover, :diners_club, :jcb]
70
70
 
71
71
  # The homepage URL of the gateway
72
72
  base.homepage_url = 'http://www.beanstream.com/'
@@ -119,6 +119,10 @@ module ActiveMerchant #:nodoc:
119
119
  end
120
120
  end
121
121
 
122
+ def add_customer_ip(post, options)
123
+ post[:customerIP] = options[:ip] if options[:ip]
124
+ end
125
+
122
126
  def void_action(original_transaction_type)
123
127
  (original_transaction_type == TRANSACTIONS[:refund]) ? :void_refund : :void_purchase
124
128
  end
@@ -288,7 +292,7 @@ module ActiveMerchant #:nodoc:
288
292
  results = {}
289
293
  if !body.nil?
290
294
  body.split(/&/).each do |pair|
291
- key, val = pair.split(/=/)
295
+ key, val = pair.split(/\=/)
292
296
  results[key.to_sym] = val.nil? ? nil : CGI.unescape(val)
293
297
  end
294
298
  end
@@ -68,8 +68,10 @@ module ActiveMerchant #:nodoc:
68
68
  Braintree::Configuration.custom_user_agent = "ActiveMerchant #{ActiveMerchant::VERSION}"
69
69
 
70
70
  if wiredump_device
71
- Braintree::Configuration.logger = wiredump_device
71
+ Braintree::Configuration.logger = ((Logger === wiredump_device) ? wiredump_device : Logger.new(wiredump_device))
72
72
  Braintree::Configuration.logger.level = Logger::DEBUG
73
+ else
74
+ Braintree::Configuration.logger.level = Logger::WARN
73
75
  end
74
76
  end
75
77
 
@@ -135,7 +137,8 @@ module ActiveMerchant #:nodoc:
135
137
  {
136
138
  :braintree_customer => (customer_hash(result.customer) if result.success?),
137
139
  :customer_vault_id => (result.customer.id if result.success?)
138
- }
140
+ },
141
+ :authorization => (result.customer.id if result.success?)
139
142
  )
140
143
  end
141
144
  end
@@ -13,6 +13,7 @@ module ActiveMerchant #:nodoc:
13
13
  # names.
14
14
  #
15
15
  # Important Notes
16
+ # * For checks you can purchase and store.
16
17
  # * AVS and CVV only work against the production server. You will always
17
18
  # get back X for AVS and no response for CVV against the test server.
18
19
  # * Nexus is the list of states or provinces where you have a physical
@@ -131,10 +132,10 @@ module ActiveMerchant #:nodoc:
131
132
 
132
133
  # Purchase is an auth followed by a capture
133
134
  # You must supply an order_id in the options hash
134
- def purchase(money, creditcard_or_reference, options = {})
135
+ def purchase(money, payment_method_or_reference, options = {})
135
136
  requires!(options, :order_id)
136
137
  setup_address_hash(options)
137
- commit(build_purchase_request(money, creditcard_or_reference, options), options)
138
+ commit(build_purchase_request(money, payment_method_or_reference, options), options)
138
139
  end
139
140
 
140
141
  def void(identification, options = {})
@@ -154,10 +155,10 @@ module ActiveMerchant #:nodoc:
154
155
  # Stores a customer subscription/profile with type "on-demand".
155
156
  # To charge the card while creating a profile, pass
156
157
  # options[:setup_fee] => money
157
- def store(creditcard, options = {})
158
+ def store(payment_method, options = {})
158
159
  requires!(options, :order_id)
159
160
  setup_address_hash(options)
160
- commit(build_create_subscription_request(creditcard, options), options)
161
+ commit(build_create_subscription_request(payment_method, options), options)
161
162
  end
162
163
 
163
164
  # Updates a customer subscription/profile
@@ -222,7 +223,7 @@ module ActiveMerchant #:nodoc:
222
223
 
223
224
  def build_auth_request(money, creditcard_or_reference, options)
224
225
  xml = Builder::XmlMarkup.new :indent => 2
225
- add_creditcard_or_subscription(xml, money, creditcard_or_reference, options)
226
+ add_payment_method_or_subscription(xml, money, creditcard_or_reference, options)
226
227
  add_auth_service(xml)
227
228
  add_business_rules_data(xml)
228
229
  xml.target!
@@ -250,11 +251,15 @@ module ActiveMerchant #:nodoc:
250
251
  xml.target!
251
252
  end
252
253
 
253
- def build_purchase_request(money, creditcard_or_reference, options)
254
+ def build_purchase_request(money, payment_method_or_reference, options)
254
255
  xml = Builder::XmlMarkup.new :indent => 2
255
- add_creditcard_or_subscription(xml, money, creditcard_or_reference, options)
256
- add_purchase_service(xml, options)
257
- add_business_rules_data(xml)
256
+ add_payment_method_or_subscription(xml, money, payment_method_or_reference, options)
257
+ if(payment_method_or_reference.respond_to?(:check?) && payment_method_or_reference.check?)
258
+ add_check_service(xml)
259
+ else
260
+ add_purchase_service(xml, options)
261
+ add_business_rules_data(xml)
262
+ end
258
263
  xml.target!
259
264
  end
260
265
 
@@ -297,16 +302,22 @@ module ActiveMerchant #:nodoc:
297
302
  xml.target!
298
303
  end
299
304
 
300
- def build_create_subscription_request(creditcard, options)
305
+ def build_create_subscription_request(payment_method, options)
301
306
  options[:subscription] = (options[:subscription] || {}).merge(:frequency => "on-demand", :amount => 0, :automatic_renew => false)
302
307
 
303
308
  xml = Builder::XmlMarkup.new :indent => 2
304
- add_address(xml, creditcard, options[:billing_address], options)
309
+ add_address(xml, payment_method, options[:billing_address], options)
305
310
  add_purchase_data(xml, options[:setup_fee] || 0, true, options)
306
- add_creditcard(xml, creditcard)
307
- add_creditcard_payment_method(xml)
311
+ if payment_method.check?
312
+ add_check(xml, payment_method)
313
+ add_check_payment_method(xml)
314
+ add_check_service(xml, options) if options[:setup_fee]
315
+ else
316
+ add_creditcard(xml, payment_method)
317
+ add_creditcard_payment_method(xml)
318
+ add_purchase_service(xml, options) if options[:setup_fee]
319
+ end
308
320
  add_subscription(xml, options)
309
- add_purchase_service(xml, options) if options[:setup_fee]
310
321
  add_subscription_create_service(xml, options)
311
322
  add_business_rules_data(xml)
312
323
  xml.target!
@@ -372,12 +383,12 @@ module ActiveMerchant #:nodoc:
372
383
  end
373
384
  end
374
385
 
375
- def add_address(xml, creditcard, address, options, shipTo = false)
386
+ def add_address(xml, payment_method, address, options, shipTo = false)
376
387
  requires!(options, :email)
377
388
 
378
389
  xml.tag! shipTo ? 'shipTo' : 'billTo' do
379
- xml.tag! 'firstName', creditcard.first_name if creditcard
380
- xml.tag! 'lastName', creditcard.last_name if creditcard
390
+ xml.tag! 'firstName', payment_method.first_name if payment_method
391
+ xml.tag! 'lastName', payment_method.last_name if payment_method
381
392
  xml.tag! 'street1', address[:address1]
382
393
  xml.tag! 'street2', address[:address2] unless address[:address2].blank?
383
394
  xml.tag! 'city', address[:city]
@@ -403,6 +414,14 @@ module ActiveMerchant #:nodoc:
403
414
  end
404
415
  end
405
416
 
417
+ def add_check(xml, check)
418
+ xml.tag! 'check' do
419
+ xml.tag! 'accountNumber', check.account_number
420
+ xml.tag! 'accountType', check.account_type[0]
421
+ xml.tag! 'bankTransitNumber', check.routing_number
422
+ end
423
+ end
424
+
406
425
  def add_tax_service(xml)
407
426
  xml.tag! 'taxService', {'run' => 'true'} do
408
427
  xml.tag!('nexus', @options[:nexus]) unless @options[:nexus].blank?
@@ -447,6 +466,10 @@ module ActiveMerchant #:nodoc:
447
466
  end
448
467
  end
449
468
 
469
+ def add_check_service(xml)
470
+ xml.tag! 'ecDebitService', {'run' => 'true'}
471
+ end
472
+
450
473
  def add_subscription_create_service(xml, options)
451
474
  xml.tag! 'paySubscriptionCreateService', {'run' => 'true'}
452
475
  end
@@ -491,14 +514,24 @@ module ActiveMerchant #:nodoc:
491
514
  end
492
515
  end
493
516
 
494
- def add_creditcard_or_subscription(xml, money, creditcard_or_reference, options)
495
- if creditcard_or_reference.is_a?(String)
517
+ def add_check_payment_method(xml)
518
+ xml.tag! 'subscription' do
519
+ xml.tag! 'paymentMethod', "check"
520
+ end
521
+ end
522
+
523
+ def add_payment_method_or_subscription(xml, money, payment_method_or_reference, options)
524
+ if payment_method_or_reference.is_a?(String)
525
+ add_purchase_data(xml, money, true, options)
526
+ add_subscription(xml, options, payment_method_or_reference)
527
+ elsif payment_method_or_reference.check?
528
+ add_address(xml, payment_method_or_reference, options[:billing_address], options)
496
529
  add_purchase_data(xml, money, true, options)
497
- add_subscription(xml, options, creditcard_or_reference)
530
+ add_check(xml, payment_method_or_reference)
498
531
  else
499
- add_address(xml, creditcard_or_reference, options[:billing_address], options)
532
+ add_address(xml, payment_method_or_reference, options[:billing_address], options)
500
533
  add_purchase_data(xml, money, true, options)
501
- add_creditcard(xml, creditcard_or_reference)
534
+ add_creditcard(xml, payment_method_or_reference)
502
535
  end
503
536
  end
504
537
 
@@ -2,137 +2,10 @@ require 'rexml/document'
2
2
 
3
3
  module ActiveMerchant #:nodoc:
4
4
  module Billing #:nodoc:
5
- # First, make sure you have everything setup correctly and all of your dependencies in place with:
6
- #
7
- # require 'rubygems'
8
- # require 'active_merchant'
9
- #
10
- # ActiveMerchant expects the amounts to be given as an Integer in cents. In this case, $10 US becomes 1000.
11
- #
12
- # tendollar = 1000
13
- #
14
- # The transaction result is based on the cent value of the transaction. $10.15 will return a failed transaction
15
- # with a response code of "15 – No Issuer", while $10.00 will return "00 – Transaction Approved."
16
- #
17
- # Next, create a credit card object using a eWay approved test card number (4444333322221111).
18
- #
19
- # creditcard = ActiveMerchant::Billing::CreditCard.new(
20
- # :number => '4444333322221111',
21
- # :month => 8,
22
- # :year => 2006,
23
- # :first_name => 'Longbob',
24
- # :last_name => 'Longsen',
25
- # :verification_value => '123'
26
- # )
27
- # options = {
28
- # :order_id => '1230123',
29
- # :email => 'bob@testbob.com',
30
- # :address => { :address1 => '47 Bobway',
31
- # :city => 'Bobville',
32
- # :state => 'WA',
33
- # :country => 'Australia',
34
- # :zip => '2000'
35
- # },
36
- # :description => 'purchased items'
37
- # }
38
- #
39
- # To finish setting up, create the active_merchant object you will be using, with the eWay gateway. If you have a
40
- # functional eWay account, replace :login with your Customer ID.
41
- #
42
- # gateway = ActiveMerchant::Billing::Base.gateway(:eway).new(:login => '87654321')
43
- #
44
- # Now we are ready to process our transaction
45
- #
46
- # response = gateway.purchase(tendollar, creditcard, options)
47
- #
48
- # Sending a transaction to eWay with active_merchant returns a Response object, which consistently allows you to:
49
- #
50
- # 1) Check whether the transaction was successful
51
- #
52
- # response.success?
53
- #
54
- # 2) Retrieve any message returned by eWay, either a "transaction was successful" note or an explanation of why the
55
- # transaction was rejected.
56
- #
57
- # response.message
58
- #
59
- # 3) Retrieve and store the unique transaction ID returned by eWway, for use in referencing the transaction in the future.
60
- #
61
- # response.authorization
62
- #
63
- # This should be enough to get you started with eWay and active_merchant. For further information, review the methods
64
- # below and the rest of active_merchant's documentation.
65
-
5
+ # Public: For more information on the Eway Gateway please visit their
6
+ # {Developers Area}[http://www.eway.com.au/developers/api/direct-payments]
66
7
  class EwayGateway < Gateway
67
- self.test_url = 'https://www.eway.com.au/gateway/xmltest/testpage.asp'
68
- self.live_url = 'https://www.eway.com.au/gateway/xmlpayment.asp'
69
-
70
- class_attribute :test_cvn_url, :live_cvn_url
71
- self.test_cvn_url = 'https://www.eway.com.au/gateway_cvn/xmltest/testpage.asp'
72
- self.live_cvn_url = 'https://www.eway.com.au/gateway_cvn/xmlpayment.asp'
73
-
74
- MESSAGES = {
75
- "00" => "Transaction Approved",
76
- "01" => "Refer to Issuer",
77
- "02" => "Refer to Issuer, special",
78
- "03" => "No Merchant",
79
- "04" => "Pick Up Card",
80
- "05" => "Do Not Honour",
81
- "06" => "Error",
82
- "07" => "Pick Up Card, Special",
83
- "08" => "Honour With Identification",
84
- "09" => "Request In Progress",
85
- "10" => "Approved For Partial Amount",
86
- "11" => "Approved, VIP",
87
- "12" => "Invalid Transaction",
88
- "13" => "Invalid Amount",
89
- "14" => "Invalid Card Number",
90
- "15" => "No Issuer",
91
- "16" => "Approved, Update Track 3",
92
- "19" => "Re-enter Last Transaction",
93
- "21" => "No Action Taken",
94
- "22" => "Suspected Malfunction",
95
- "23" => "Unacceptable Transaction Fee",
96
- "25" => "Unable to Locate Record On File",
97
- "30" => "Format Error",
98
- "31" => "Bank Not Supported By Switch",
99
- "33" => "Expired Card, Capture",
100
- "34" => "Suspected Fraud, Retain Card",
101
- "35" => "Card Acceptor, Contact Acquirer, Retain Card",
102
- "36" => "Restricted Card, Retain Card",
103
- "37" => "Contact Acquirer Security Department, Retain Card",
104
- "38" => "PIN Tries Exceeded, Capture",
105
- "39" => "No Credit Account",
106
- "40" => "Function Not Supported",
107
- "41" => "Lost Card",
108
- "42" => "No Universal Account",
109
- "43" => "Stolen Card",
110
- "44" => "No Investment Account",
111
- "51" => "Insufficient Funds",
112
- "52" => "No Cheque Account",
113
- "53" => "No Savings Account",
114
- "54" => "Expired Card",
115
- "55" => "Incorrect PIN",
116
- "56" => "No Card Record",
117
- "57" => "Function Not Permitted to Cardholder",
118
- "58" => "Function Not Permitted to Terminal",
119
- "59" => "Suspected Fraud",
120
- "60" => "Acceptor Contact Acquirer",
121
- "61" => "Exceeds Withdrawal Limit",
122
- "62" => "Restricted Card",
123
- "63" => "Security Violation",
124
- "64" => "Original Amount Incorrect",
125
- "66" => "Acceptor Contact Acquirer, Security",
126
- "67" => "Capture Card",
127
- "75" => "PIN Tries Exceeded",
128
- "82" => "CVV Validation Error",
129
- "90" => "Cutoff In Progress",
130
- "91" => "Card Issuer Unavailable",
131
- "92" => "Unable To Route Transaction",
132
- "93" => "Cannot Complete, Violation Of The Law",
133
- "94" => "Duplicate Transaction",
134
- "96" => "System Error"
135
- }
8
+ self.live_url = 'https://www.eway.com.au'
136
9
 
137
10
  self.money_format = :cents
138
11
  self.supported_countries = ['AU']
@@ -140,28 +13,46 @@ module ActiveMerchant #:nodoc:
140
13
  self.homepage_url = 'http://www.eway.com.au/'
141
14
  self.display_name = 'eWAY'
142
15
 
16
+ # Public: Create a new Eway Gateway.
17
+ # options - A hash of options:
18
+ # :login - Your Customer ID.
19
+ # :password - Your XML Refund Password that you
20
+ # specified on the Eway site. (optional)
143
21
  def initialize(options = {})
144
22
  requires!(options, :login)
145
23
  super
146
24
  end
147
25
 
148
- # ewayCustomerEmail, ewayCustomerAddress, ewayCustomerPostcode
149
26
  def purchase(money, creditcard, options = {})
150
27
  requires_address!(options)
151
28
 
152
29
  post = {}
153
30
  add_creditcard(post, creditcard)
154
31
  add_address(post, options)
155
- add_customer_data(post, options)
32
+ add_customer_id(post)
156
33
  add_invoice_data(post, options)
157
- # The request fails if all of the fields aren't present
158
- add_optional_data(post)
34
+ add_non_optional_data(post)
35
+ add_amount(post, money)
36
+ post[:CustomerEmail] = options[:email]
159
37
 
160
- commit(money, post)
38
+ commit(purchase_url(post[:CVN]), money, post)
161
39
  end
162
40
 
163
- private
41
+ def refund(money, authorization, options={})
42
+ post = {}
164
43
 
44
+ add_customer_id(post)
45
+ add_amount(post, money)
46
+ add_non_optional_data(post)
47
+ post[:OriginalTrxnNumber] = authorization
48
+ post[:RefundPassword] = @options[:password]
49
+ post[:CardExpiryMonth] = nil
50
+ post[:CardExpiryYear] = nil
51
+
52
+ commit(refund_url, money, post)
53
+ end
54
+
55
+ private
165
56
  def requires_address!(options)
166
57
  raise ArgumentError.new("Missing eWay required parameters: address or billing_address") unless (options.has_key?(:address) or options.has_key?(:billing_address))
167
58
  end
@@ -184,8 +75,8 @@ module ActiveMerchant #:nodoc:
184
75
  end
185
76
  end
186
77
 
187
- def add_customer_data(post, options)
188
- post[:CustomerEmail] = options[:email]
78
+ def add_customer_id(post)
79
+ post[:CustomerID] = @options[:login]
189
80
  end
190
81
 
191
82
  def add_invoice_data(post, options)
@@ -193,21 +84,26 @@ module ActiveMerchant #:nodoc:
193
84
  post[:CustomerInvoiceDescription] = options[:description]
194
85
  end
195
86
 
196
- def add_optional_data(post)
197
- post[:TrxnNumber] = nil
87
+ def add_amount(post, money)
88
+ post[:TotalAmount] = amount(money)
89
+ end
90
+
91
+ def add_non_optional_data(post)
198
92
  post[:Option1] = nil
199
93
  post[:Option2] = nil
200
94
  post[:Option3] = nil
95
+ post[:TrxnNumber] = nil
201
96
  end
202
97
 
203
- def commit(money, parameters)
204
- parameters[:TotalAmount] = amount(money)
98
+ def commit(url, money, parameters)
99
+ raw_response = ssl_post(url, post_data(parameters))
100
+ response = parse(raw_response)
205
101
 
206
- response = parse( ssl_post(gateway_url(parameters[:CVN], test?), post_data(parameters)) )
207
-
208
- Response.new(success?(response), message_from(response[:ewaytrxnerror]), response,
209
- :authorization => response[:ewayauthcode],
210
- :test => /\(Test( CVN)? Gateway\)/ === response[:ewaytrxnerror]
102
+ Response.new(success?(response),
103
+ message_from(response[:ewaytrxnerror]),
104
+ response,
105
+ :authorization => response[:ewaytrxnnumber],
106
+ :test => test?
211
107
  )
212
108
  end
213
109
 
@@ -215,35 +111,17 @@ module ActiveMerchant #:nodoc:
215
111
  response[:ewaytrxnstatus] == "True"
216
112
  end
217
113
 
218
- # Parse eway response xml into a convinient hash
219
114
  def parse(xml)
220
- # "<?xml version=\"1.0\"?>".
221
- # <ewayResponse>
222
- # <ewayTrxnError></ewayTrxnError>
223
- # <ewayTrxnStatus>True</ewayTrxnStatus>
224
- # <ewayTrxnNumber>10002</ewayTrxnNumber>
225
- # <ewayTrxnOption1></ewayTrxnOption1>
226
- # <ewayTrxnOption2></ewayTrxnOption2>
227
- # <ewayTrxnOption3></ewayTrxnOption3>
228
- # <ewayReturnAmount>10</ewayReturnAmount>
229
- # <ewayAuthCode>123456</ewayAuthCode>
230
- # <ewayTrxnReference>987654321</ewayTrxnReference>
231
- # </ewayResponse>
232
-
233
115
  response = {}
234
116
  xml = REXML::Document.new(xml)
235
117
  xml.elements.each('//ewayResponse/*') do |node|
236
-
237
118
  response[node.name.downcase.to_sym] = normalize(node.text)
238
-
239
119
  end unless xml.root.nil?
240
120
 
241
121
  response
242
122
  end
243
123
 
244
124
  def post_data(parameters = {})
245
- parameters[:CustomerID] = @options[:login]
246
-
247
125
  xml = REXML::Document.new
248
126
  root = xml.add_element("ewaygateway")
249
127
 
@@ -269,14 +147,79 @@ module ActiveMerchant #:nodoc:
269
147
  end
270
148
  end
271
149
 
272
- def gateway_url(cvn, test)
273
- if cvn
274
- test ? self.test_cvn_url : self.live_cvn_url
275
- else
276
- test ? self.test_url : self.live_url
277
- end
150
+ def purchase_url(cvn)
151
+ suffix = test? ? 'xmltest/testpage.asp' : 'xmlpayment.asp'
152
+ gateway_part = cvn ? 'gateway_cvn' : 'gateway'
153
+ "#{live_url}/#{gateway_part}/#{suffix}"
278
154
  end
279
155
 
156
+ def refund_url
157
+ suffix = test? ? 'xmltest/refund_test.asp' : 'xmlpaymentrefund.asp'
158
+ "#{live_url}/gateway/#{suffix}"
159
+ end
160
+
161
+ MESSAGES = {
162
+ "00" => "Transaction Approved",
163
+ "01" => "Refer to Issuer",
164
+ "02" => "Refer to Issuer, special",
165
+ "03" => "No Merchant",
166
+ "04" => "Pick Up Card",
167
+ "05" => "Do Not Honour",
168
+ "06" => "Error",
169
+ "07" => "Pick Up Card, Special",
170
+ "08" => "Honour With Identification",
171
+ "09" => "Request In Progress",
172
+ "10" => "Approved For Partial Amount",
173
+ "11" => "Approved, VIP",
174
+ "12" => "Invalid Transaction",
175
+ "13" => "Invalid Amount",
176
+ "14" => "Invalid Card Number",
177
+ "15" => "No Issuer",
178
+ "16" => "Approved, Update Track 3",
179
+ "19" => "Re-enter Last Transaction",
180
+ "21" => "No Action Taken",
181
+ "22" => "Suspected Malfunction",
182
+ "23" => "Unacceptable Transaction Fee",
183
+ "25" => "Unable to Locate Record On File",
184
+ "30" => "Format Error",
185
+ "31" => "Bank Not Supported By Switch",
186
+ "33" => "Expired Card, Capture",
187
+ "34" => "Suspected Fraud, Retain Card",
188
+ "35" => "Card Acceptor, Contact Acquirer, Retain Card",
189
+ "36" => "Restricted Card, Retain Card",
190
+ "37" => "Contact Acquirer Security Department, Retain Card",
191
+ "38" => "PIN Tries Exceeded, Capture",
192
+ "39" => "No Credit Account",
193
+ "40" => "Function Not Supported",
194
+ "41" => "Lost Card",
195
+ "42" => "No Universal Account",
196
+ "43" => "Stolen Card",
197
+ "44" => "No Investment Account",
198
+ "51" => "Insufficient Funds",
199
+ "52" => "No Cheque Account",
200
+ "53" => "No Savings Account",
201
+ "54" => "Expired Card",
202
+ "55" => "Incorrect PIN",
203
+ "56" => "No Card Record",
204
+ "57" => "Function Not Permitted to Cardholder",
205
+ "58" => "Function Not Permitted to Terminal",
206
+ "59" => "Suspected Fraud",
207
+ "60" => "Acceptor Contact Acquirer",
208
+ "61" => "Exceeds Withdrawal Limit",
209
+ "62" => "Restricted Card",
210
+ "63" => "Security Violation",
211
+ "64" => "Original Amount Incorrect",
212
+ "66" => "Acceptor Contact Acquirer, Security",
213
+ "67" => "Capture Card",
214
+ "75" => "PIN Tries Exceeded",
215
+ "82" => "CVV Validation Error",
216
+ "90" => "Cutoff In Progress",
217
+ "91" => "Card Issuer Unavailable",
218
+ "92" => "Unable To Route Transaction",
219
+ "93" => "Cannot Complete, Violation Of The Law",
220
+ "94" => "Duplicate Transaction",
221
+ "96" => "System Error"
222
+ }
280
223
  end
281
224
  end
282
225
  end