activemerchant 1.29.1 → 1.34.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 (92) hide show
  1. data/CHANGELOG +143 -0
  2. data/CONTRIBUTORS +43 -0
  3. data/README.md +59 -51
  4. data/lib/active_merchant/billing/check.rb +15 -14
  5. data/lib/active_merchant/billing/credit_card.rb +14 -5
  6. data/lib/active_merchant/billing/credit_card_formatting.rb +8 -8
  7. data/lib/active_merchant/billing/gateway.rb +2 -2
  8. data/lib/active_merchant/billing/gateways/authorize_net.rb +36 -8
  9. data/lib/active_merchant/billing/gateways/authorize_net_cim.rb +17 -5
  10. data/lib/active_merchant/billing/gateways/balanced.rb +9 -3
  11. data/lib/active_merchant/billing/gateways/banwire.rb +15 -1
  12. data/lib/active_merchant/billing/gateways/barclays_epdq.rb +8 -1
  13. data/lib/active_merchant/billing/gateways/beanstream/beanstream_core.rb +7 -2
  14. data/lib/active_merchant/billing/gateways/beanstream.rb +26 -24
  15. data/lib/active_merchant/billing/gateways/blue_pay.rb +201 -187
  16. data/lib/active_merchant/billing/gateways/bogus.rb +1 -1
  17. data/lib/active_merchant/billing/gateways/braintree_blue.rb +7 -3
  18. data/lib/active_merchant/billing/gateways/card_stream_modern.rb +155 -0
  19. data/lib/active_merchant/billing/gateways/cc5.rb +156 -0
  20. data/lib/active_merchant/billing/gateways/cyber_source.rb +55 -22
  21. data/lib/active_merchant/billing/gateways/data_cash.rb +3 -3
  22. data/lib/active_merchant/billing/gateways/evo_ca.rb +308 -0
  23. data/lib/active_merchant/billing/gateways/eway.rb +114 -171
  24. data/lib/active_merchant/billing/gateways/eway_managed.rb +52 -22
  25. data/lib/active_merchant/billing/gateways/finansbank.rb +22 -0
  26. data/lib/active_merchant/billing/gateways/firstdata_e4.rb +314 -0
  27. data/lib/active_merchant/billing/gateways/garanti.rb +0 -4
  28. data/lib/active_merchant/billing/gateways/ideal_rabobank.rb +13 -2
  29. data/lib/active_merchant/billing/gateways/iridium.rb +8 -2
  30. data/lib/active_merchant/billing/gateways/litle.rb +354 -105
  31. data/lib/active_merchant/billing/gateways/merchant_e_solutions.rb +28 -7
  32. data/lib/active_merchant/billing/gateways/merchant_ware.rb +44 -9
  33. data/lib/active_merchant/billing/gateways/merchant_warrior.rb +190 -0
  34. data/lib/active_merchant/billing/gateways/moneris.rb +4 -6
  35. data/lib/active_merchant/billing/gateways/moneris_us.rb +1 -1
  36. data/lib/active_merchant/billing/gateways/nab_transact.rb +20 -3
  37. data/lib/active_merchant/billing/gateways/net_registry.rb +8 -3
  38. data/lib/active_merchant/billing/gateways/netaxept.rb +65 -117
  39. data/lib/active_merchant/billing/gateways/netbilling.rb +1 -0
  40. data/lib/active_merchant/billing/gateways/netpay.rb +223 -0
  41. data/lib/active_merchant/billing/gateways/ogone.rb +7 -5
  42. data/lib/active_merchant/billing/gateways/optimal_payment.rb +43 -18
  43. data/lib/active_merchant/billing/gateways/orbital.rb +190 -53
  44. data/lib/active_merchant/billing/gateways/payflow/payflow_common_api.rb +12 -10
  45. data/lib/active_merchant/billing/gateways/payment_express.rb +62 -1
  46. data/lib/active_merchant/billing/gateways/paymill.rb +179 -0
  47. data/lib/active_merchant/billing/gateways/paypal/paypal_common_api.rb +12 -7
  48. data/lib/active_merchant/billing/gateways/paypal/paypal_express_response.rb +14 -9
  49. data/lib/active_merchant/billing/gateways/paypal_express.rb +59 -18
  50. data/lib/active_merchant/billing/gateways/pin.rb +165 -0
  51. data/lib/active_merchant/billing/gateways/qbms.rb +3 -2
  52. data/lib/active_merchant/billing/gateways/quickpay.rb +66 -28
  53. data/lib/active_merchant/billing/gateways/sage/sage_bankcard.rb +16 -11
  54. data/lib/active_merchant/billing/gateways/sage/sage_core.rb +1 -1
  55. data/lib/active_merchant/billing/gateways/sage/sage_virtual_check.rb +21 -16
  56. data/lib/active_merchant/billing/gateways/sage.rb +10 -5
  57. data/lib/active_merchant/billing/gateways/sage_pay.rb +7 -0
  58. data/lib/active_merchant/billing/gateways/smart_ps.rb +1 -1
  59. data/lib/active_merchant/billing/gateways/spreedly_core.rb +233 -0
  60. data/lib/active_merchant/billing/gateways/stripe.rb +49 -21
  61. data/lib/active_merchant/billing/gateways/transnational.rb +239 -0
  62. data/lib/active_merchant/billing/gateways/usa_epay_advanced.rb +9 -4
  63. data/lib/active_merchant/billing/gateways/webpay.rb +8 -0
  64. data/lib/active_merchant/billing/gateways/wirecard.rb +15 -9
  65. data/lib/active_merchant/billing/gateways/worldpay.rb +60 -24
  66. data/lib/active_merchant/billing/integrations/direc_pay/status.rb +1 -1
  67. data/lib/active_merchant/billing/integrations/direc_pay.rb +1 -1
  68. data/lib/active_merchant/billing/integrations/dwolla/common.rb +23 -0
  69. data/lib/active_merchant/billing/integrations/dwolla/helper.rb +18 -6
  70. data/lib/active_merchant/billing/integrations/dwolla/notification.rb +16 -7
  71. data/lib/active_merchant/billing/integrations/dwolla/return.rb +16 -5
  72. data/lib/active_merchant/billing/integrations/dwolla.rb +5 -12
  73. data/lib/active_merchant/billing/integrations/notification.rb +13 -8
  74. data/lib/active_merchant/billing/integrations/payflow_link/helper.rb +19 -3
  75. data/lib/active_merchant/billing/integrations/paypal/notification.rb +39 -31
  76. data/lib/active_merchant/billing/integrations/payu_in/helper.rb +74 -0
  77. data/lib/active_merchant/billing/integrations/payu_in/notification.rb +167 -0
  78. data/lib/active_merchant/billing/integrations/payu_in/return.rb +53 -0
  79. data/lib/active_merchant/billing/integrations/payu_in.rb +43 -0
  80. data/lib/active_merchant/billing/integrations/pxpay/helper.rb +1 -0
  81. data/lib/active_merchant/billing/integrations/quickpay/helper.rb +13 -10
  82. data/lib/active_merchant/billing/integrations/quickpay/notification.rb +78 -15
  83. data/lib/active_merchant/billing/integrations/rbkmoney/helper.rb +23 -0
  84. data/lib/active_merchant/billing/integrations/rbkmoney/notification.rb +91 -0
  85. data/lib/active_merchant/billing/integrations/rbkmoney.rb +17 -0
  86. data/lib/active_merchant/billing/integrations/robokassa/common.rb +1 -1
  87. data/lib/active_merchant/billing/integrations/sage_pay_form/helper.rb +7 -3
  88. data/lib/active_merchant/billing/integrations/world_pay.rb +15 -8
  89. data/lib/active_merchant/version.rb +1 -1
  90. data.tar.gz.sig +0 -0
  91. metadata +124 -50
  92. metadata.gz.sig +0 -0
@@ -1,7 +1,10 @@
1
1
  module ActiveMerchant #:nodoc:
2
2
  module Billing #:nodoc:
3
3
  class MerchantWareGateway < Gateway
4
+ class_attribute :v4_live_url
5
+
4
6
  self.live_url = self.test_url = 'https://ps1.merchantware.net/MerchantWARE/ws/RetailTransaction/TXRetail.asmx'
7
+ self.v4_live_url = 'https://ps1.merchantware.net/Merchantware/ws/RetailTransaction/v4/Credit.asmx'
5
8
 
6
9
  self.supported_countries = ['US']
7
10
  self.supported_cardtypes = [:visa, :master, :american_express, :discover]
@@ -12,13 +15,19 @@ module ActiveMerchant #:nodoc:
12
15
  "xmlns:xsd" => "http://www.w3.org/2001/XMLSchema",
13
16
  "xmlns:env" => "http://schemas.xmlsoap.org/soap/envelope/"
14
17
  }
18
+ ENV_NAMESPACES_V4 = { "xmlns:xsi" => "http://www.w3.org/2001/XMLSchema-instance",
19
+ "xmlns:xsd" => "http://www.w3.org/2001/XMLSchema",
20
+ "xmlns:soap" => "http://schemas.xmlsoap.org/soap/envelope/"
21
+ }
22
+
15
23
  TX_NAMESPACE = "http://merchantwarehouse.com/MerchantWARE/Client/TransactionRetail"
24
+ TX_NAMESPACE_V4 = "http://schemas.merchantwarehouse.com/merchantware/40/Credit/"
16
25
 
17
26
  ACTIONS = {
18
27
  :purchase => "IssueKeyedSale",
19
28
  :authorize => "IssueKeyedPreAuth",
20
29
  :capture => "IssuePostAuth",
21
- :void => "IssueVoid",
30
+ :void => "VoidPreAuthorization",
22
31
  :credit => "IssueKeyedRefund",
23
32
  :reference_credit => "IssueRefundByReference"
24
33
  }
@@ -80,11 +89,10 @@ module ActiveMerchant #:nodoc:
80
89
  # * <tt>authorization</tt> - The authorization string returned from the initial authorization or purchase.
81
90
  def void(authorization, options = {})
82
91
  reference, options[:order_id] = split_reference(authorization)
83
-
84
- request = soap_request(:void) do |xml|
85
- add_reference(xml, reference)
92
+ request = v4_soap_request(:void) do |xml|
93
+ add_reference_token(xml, reference)
86
94
  end
87
- commit(:void, request)
95
+ commit(:void, request, true)
88
96
  end
89
97
 
90
98
  # Refund an amount back a cardholder
@@ -108,7 +116,6 @@ module ActiveMerchant #:nodoc:
108
116
  perform_reference_credit(money, reference, options)
109
117
  end
110
118
 
111
-
112
119
  private
113
120
 
114
121
  def soap_request(action)
@@ -125,6 +132,22 @@ module ActiveMerchant #:nodoc:
125
132
  xml.target!
126
133
  end
127
134
 
135
+ def v4_soap_request(action)
136
+ xml = Builder::XmlMarkup.new :indent => 2
137
+ xml.instruct!
138
+ xml.tag! "soap:Envelope", ENV_NAMESPACES_V4 do
139
+ xml.tag! "soap:Body" do
140
+ xml.tag! ACTIONS[:void], "xmlns" => TX_NAMESPACE_V4 do
141
+ xml.tag! "merchantName", @options[:name]
142
+ xml.tag! "merchantSiteId", @options[:login]
143
+ xml.tag! "merchantKey", @options[:password]
144
+ yield xml
145
+ end
146
+ end
147
+ end
148
+ xml.target!
149
+ end
150
+
128
151
  def build_purchase_request(action, money, credit_card, options)
129
152
  requires!(options, :order_id)
130
153
 
@@ -195,6 +218,10 @@ module ActiveMerchant #:nodoc:
195
218
  xml.tag! "strReferenceCode", reference
196
219
  end
197
220
 
221
+ def add_reference_token(xml, reference)
222
+ xml.tag! "token", reference
223
+ end
224
+
198
225
  def add_address(xml, options)
199
226
  if address = options[:billing_address] || options[:address]
200
227
  xml.tag! "strAVSStreetAddress", address[:address1]
@@ -258,11 +285,19 @@ module ActiveMerchant #:nodoc:
258
285
  response
259
286
  end
260
287
 
261
- def commit(action, request)
288
+ def soap_action(action, v4 = false)
289
+ v4 ? "#{TX_NAMESPACE_V4}#{ACTIONS[action]}" : "#{TX_NAMESPACE}/#{ACTIONS[action]}"
290
+ end
291
+
292
+ def url(v4 = false)
293
+ v4 ? v4_live_url : live_url
294
+ end
295
+
296
+ def commit(action, request, v4 = false)
262
297
  begin
263
- data = ssl_post(self.live_url, request,
298
+ data = ssl_post(url(v4), request,
264
299
  "Content-Type" => 'text/xml; charset=utf-8',
265
- "SOAPAction" => "http://merchantwarehouse.com/MerchantWARE/Client/TransactionRetail/#{ACTIONS[action]}"
300
+ "SOAPAction" => soap_action(action, v4)
266
301
  )
267
302
  response = parse(action, data)
268
303
  rescue ActiveMerchant::ResponseError => e
@@ -0,0 +1,190 @@
1
+ require 'digest/md5'
2
+ require 'rexml/document'
3
+
4
+ module ActiveMerchant #:nodoc:
5
+ module Billing #:nodoc:
6
+ class MerchantWarriorGateway < Gateway
7
+ TOKEN_TEST_URL = 'https://base.merchantwarrior.com/token/'
8
+ TOKEN_LIVE_URL = 'https://api.merchantwarrior.com/token/'
9
+
10
+ POST_TEST_URL = 'https://base.merchantwarrior.com/post/'
11
+ POST_LIVE_URL = 'https://api.merchantwarrior.com/post/'
12
+
13
+ self.supported_countries = ['AU']
14
+ self.supported_cardtypes = [:visa, :master, :american_express,
15
+ :diners_club, :discover]
16
+ self.homepage_url = 'http://www.merchantwarrior.com/'
17
+ self.display_name = 'MerchantWarrior'
18
+
19
+ self.money_format = :dollars
20
+ self.default_currency = 'AUD'
21
+
22
+ def initialize(options = {})
23
+ requires!(options, :merchant_uuid, :api_key, :api_passphrase)
24
+ super
25
+ end
26
+
27
+ def authorize(money, payment_method, options = {})
28
+ post = {}
29
+ add_amount(post, money, options)
30
+ add_product(post, options)
31
+ add_address(post, options)
32
+ add_payment_method(post, payment_method)
33
+ commit('processAuth', post)
34
+ end
35
+
36
+ def purchase(money, payment_method, options = {})
37
+ post = {}
38
+ add_amount(post, money, options)
39
+ add_product(post, options)
40
+ add_address(post, options)
41
+ add_payment_method(post, payment_method)
42
+ commit('processCard', post)
43
+ end
44
+
45
+ def capture(money, identification)
46
+ post = {}
47
+ add_amount(post, money, options)
48
+ add_transaction(post, identification)
49
+ post.merge!('captureAmount' => money.to_s)
50
+ commit('processCapture', post)
51
+ end
52
+
53
+ def refund(money, identification)
54
+ post = {}
55
+ add_amount(post, money, options)
56
+ add_transaction(post, identification)
57
+ post['refundAmount'] = money
58
+ commit('refundCard', post)
59
+ end
60
+
61
+ def store(creditcard, options = {})
62
+ post = {
63
+ 'cardName' => creditcard.name,
64
+ 'cardNumber' => creditcard.number,
65
+ 'cardExpiryMonth' => format(creditcard.month, :two_digits),
66
+ 'cardExpiryYear' => format(creditcard.year, :two_digits)
67
+ }
68
+ commit('addCard', post)
69
+ end
70
+
71
+ private
72
+
73
+ def add_transaction(post, identification)
74
+ post['transactionID'] = identification
75
+ end
76
+
77
+ def add_address(post, options)
78
+ return unless(address = options[:address])
79
+
80
+ post['customerName'] = address[:name]
81
+ post['customerCountry'] = address[:country]
82
+ post['customerState'] = address[:state]
83
+ post['customerCity'] = address[:city]
84
+ post['customerAddress'] = address[:address1]
85
+ post['customerPostCode'] = address[:zip]
86
+ end
87
+
88
+ def add_product(post, options)
89
+ post['transactionProduct'] = options[:transaction_product]
90
+ end
91
+
92
+ def add_payment_method(post, payment_method)
93
+ if payment_method.respond_to?(:number)
94
+ add_creditcard(post, payment_method)
95
+ else
96
+ add_token(post, payment_method)
97
+ end
98
+ end
99
+
100
+ def add_token(post, token)
101
+ post['cardID'] = token
102
+ end
103
+
104
+ def add_creditcard(post, creditcard)
105
+ post['paymentCardNumber'] = creditcard.number
106
+ post['paymentCardName'] = creditcard.name
107
+ post['paymentCardExpiry'] = creditcard.expiry_date.expiration.strftime("%m%y")
108
+ end
109
+
110
+ def add_amount(post, money, options)
111
+ currency = (options[:currency] || currency(money))
112
+
113
+ post['transactionAmount'] = money.to_s
114
+ post['transactionCurrency'] = currency
115
+ post['hash'] = verification_hash(money, currency)
116
+ end
117
+
118
+ def verification_hash(money, currency)
119
+ Digest::MD5.hexdigest(
120
+ (
121
+ @options[:api_passphrase].to_s +
122
+ @options[:merchant_uuid].to_s +
123
+ money.to_s +
124
+ currency
125
+ ).downcase
126
+ )
127
+ end
128
+
129
+ def parse(body)
130
+ xml = REXML::Document.new(body)
131
+
132
+ response = {}
133
+ xml.root.elements.to_a.each do |node|
134
+ parse_element(response, node)
135
+ end
136
+ response
137
+ end
138
+
139
+ def parse_element(response, node)
140
+ if node.has_elements?
141
+ node.elements.each{|element| parse_element(response, element)}
142
+ else
143
+ response[node.name.underscore.to_sym] = node.text
144
+ end
145
+ end
146
+
147
+ def commit(action, post)
148
+ add_auth(action, post)
149
+
150
+ response = parse(ssl_post(url_for(action, post), post_data(post)))
151
+
152
+ Response.new(
153
+ success?(response),
154
+ response[:response_message],
155
+ response,
156
+ :test => test?,
157
+ :authorization => (response[:card_id] || response[:transaction_id])
158
+ )
159
+ end
160
+
161
+ def add_auth(action, post)
162
+ post['merchantUUID'] = @options[:merchant_uuid]
163
+ post['apiKey'] = @options[:api_key]
164
+ unless token?(post)
165
+ post['method'] = action
166
+ end
167
+ end
168
+
169
+ def url_for(action, post)
170
+ if token?(post)
171
+ [(test? ? TOKEN_TEST_URL : TOKEN_LIVE_URL), action].join("/")
172
+ else
173
+ (test? ? POST_TEST_URL : POST_LIVE_URL)
174
+ end
175
+ end
176
+
177
+ def token?(post)
178
+ (post["cardID"] || post["cardName"])
179
+ end
180
+
181
+ def success?(response)
182
+ (response[:response_code] == '0')
183
+ end
184
+
185
+ def post_data(post)
186
+ post.collect{|k,v| "#{k}=#{CGI.escape(v.to_s)}" }.join("&")
187
+ end
188
+ end
189
+ end
190
+ end
@@ -22,7 +22,7 @@ module ActiveMerchant #:nodoc:
22
22
  # password is your API Token
23
23
  def initialize(options = {})
24
24
  requires!(options, :login, :password)
25
- @options = { :crypt_type => 7 }.update(options)
25
+ options = { :crypt_type => 7 }.merge(options)
26
26
  super
27
27
  end
28
28
 
@@ -70,15 +70,13 @@ module ActiveMerchant #:nodoc:
70
70
  commit 'completion', crediting_params(authorization, :comp_amount => amount(money))
71
71
  end
72
72
 
73
- # Voiding requires the original transaction ID and order ID of some open
74
- # transaction. Closed transactions must be refunded. Note that the only
75
- # methods which may be voided are +capture+ and +purchase+.
73
+ # Voiding cancels an open authorization.
76
74
  #
77
75
  # Concatenate your transaction number and order_id by using a semicolon
78
76
  # (';'). This is to keep the Moneris interface consistent with other
79
77
  # gateways. (See +capture+ for details.)
80
78
  def void(authorization, options = {})
81
- commit 'purchasecorrection', crediting_params(authorization)
79
+ capture(0, authorization, options)
82
80
  end
83
81
 
84
82
  # Performs a refund. This method requires that the original transaction
@@ -103,7 +101,7 @@ module ActiveMerchant #:nodoc:
103
101
  commit('res_add_cc', post)
104
102
  end
105
103
 
106
- def unstore(data_key)
104
+ def unstore(data_key, options = {})
107
105
  post = {}
108
106
  post[:data_key] = data_key
109
107
  commit('res_delete', post)
@@ -22,7 +22,7 @@ module ActiveMerchant #:nodoc:
22
22
  # password is your API Token
23
23
  def initialize(options = {})
24
24
  requires!(options, :login, :password)
25
- @options = { :crypt_type => 7 }.update(options)
25
+ options = { :crypt_type => 7 }.merge(options)
26
26
  super
27
27
  end
28
28
 
@@ -34,7 +34,7 @@ module ActiveMerchant #:nodoc:
34
34
  #Transactions currently accepted by NAB Transact XML API
35
35
  TRANSACTIONS = {
36
36
  :purchase => 0, #Standard Payment
37
- :credit => 4, #Refund
37
+ :refund => 4, #Refund
38
38
  :void => 6, #Client Reversal (Void)
39
39
  :authorization => 10, #Preauthorise
40
40
  :capture => 11 #Preauthorise Complete (Advice)
@@ -66,6 +66,10 @@ module ActiveMerchant #:nodoc:
66
66
  end
67
67
  end
68
68
 
69
+ def refund(money, authorization, options = {})
70
+ commit :refund, build_reference_request(money, authorization)
71
+ end
72
+
69
73
  def store(creditcard, options = {})
70
74
  requires!(options, :billing_id, :amount)
71
75
  commit_periodic(build_periodic_item(:addcrn, options[:amount], creditcard, options))
@@ -104,10 +108,23 @@ module ActiveMerchant #:nodoc:
104
108
  xml.target!
105
109
  end
106
110
 
111
+ def build_reference_request(money, reference)
112
+ xml = Builder::XmlMarkup.new
113
+
114
+ transaction_id, order_id, preauth_id, original_amount = reference.split('*')
115
+
116
+ xml.tag! 'amount', (money ? amount(money) : original_amount)
117
+ xml.tag! 'currency', options[:currency] || currency(money)
118
+ xml.tag! 'txnID', transaction_id
119
+ xml.tag! 'purchaseOrderNo', order_id
120
+ xml.tag! 'preauthID', preauth_id
121
+
122
+ xml.target!
123
+ end
124
+
107
125
  #Generate payment request XML
108
126
  # - API is set to allow multiple Txn's but currentlu only allows one
109
127
  # - txnSource = 23 - (XML)
110
-
111
128
  def build_request(action, body)
112
129
  xml = Builder::XmlMarkup.new
113
130
  xml.instruct!
@@ -210,7 +227,7 @@ module ActiveMerchant #:nodoc:
210
227
  end
211
228
 
212
229
  def authorization_from(response)
213
- response[:txn_id]
230
+ [response[:txn_id], response[:purchase_order_no], response[:preauth_id], response[:amount]].join('*')
214
231
  end
215
232
 
216
233
  def message_from(response)
@@ -41,7 +41,7 @@ module ActiveMerchant
41
41
  :purchase => 'purchase',
42
42
  :capture => 'completion',
43
43
  :status => 'status',
44
- :credit => 'refund'
44
+ :refund => 'refund'
45
45
  }
46
46
 
47
47
  # Create a new NetRegistry gateway.
@@ -94,13 +94,18 @@ module ActiveMerchant
94
94
  commit(:purchase, params)
95
95
  end
96
96
 
97
- def credit(money, identification, options = {})
97
+ def refund(money, identification, options = {})
98
98
  params = {
99
99
  'AMOUNT' => amount(money),
100
100
  'TXNREF' => identification
101
101
  }
102
102
  add_request_details(params, options)
103
- commit(:credit, params)
103
+ commit(:refund, params)
104
+ end
105
+
106
+ def credit(money, identification, options = {})
107
+ deprecated CREDIT_DEPRECATION_MESSAGE
108
+ refund(money, identification, options)
104
109
  end
105
110
 
106
111
  # Specific to NetRegistry.
@@ -30,56 +30,73 @@ module ActiveMerchant #:nodoc:
30
30
  def purchase(money, creditcard, options = {})
31
31
  requires!(options, :order_id)
32
32
 
33
- post = {}
34
- add_credentials(post, options)
35
- add_transaction(post, options)
36
- add_order(post, money, options)
37
- add_creditcard(post, creditcard)
38
- commit('Sale', post)
33
+ MultiResponse.run do |r|
34
+ r.process{authorize(money, creditcard, options)}
35
+ r.process{capture(money, r.authorization, options)}
36
+ end
39
37
  end
40
38
 
41
39
  def authorize(money, creditcard, options = {})
42
40
  requires!(options, :order_id)
43
41
 
44
- post = {}
45
- add_credentials(post, options)
46
- add_transaction(post, options)
47
- add_order(post, money, options)
48
- add_creditcard(post, creditcard)
49
- commit('Auth', post)
42
+ MultiResponse.run do |r|
43
+ r.process{setup_transaction(money, options)}
44
+ r.process{add_and_auth_credit_card(r.authorization, creditcard, options)}
45
+ r.process{query_transaction(r.authorization, options)}
46
+ end
50
47
  end
51
48
 
52
49
  def capture(money, authorization, options = {})
53
50
  post = {}
54
51
  add_credentials(post, options)
55
52
  add_authorization(post, authorization, money)
56
- commit('Capture', post, false)
53
+ post[:operation] = "Capture"
54
+ commit("Netaxept/process.aspx", post)
57
55
  end
58
56
 
59
57
  def refund(money, authorization, options = {})
60
58
  post = {}
61
59
  add_credentials(post, options)
62
60
  add_authorization(post, authorization, money)
63
- commit('Credit', post, false)
64
- end
65
-
66
- def credit(money, authorization, options = {})
67
- deprecated CREDIT_DEPRECATION_MESSAGE
68
- refund(money, authorization, options)
61
+ post[:operation] = "Credit"
62
+ commit("Netaxept/process.aspx", post)
69
63
  end
70
64
 
71
65
  def void(authorization, options = {})
72
66
  post = {}
73
67
  add_credentials(post, options)
74
68
  add_authorization(post, authorization)
75
- commit('Annul', post, false)
69
+ post[:operation] = "Annul"
70
+ commit("Netaxept/process.aspx", post)
76
71
  end
77
72
 
78
73
  private
79
74
 
80
- def add_credentials(post, options)
75
+ def setup_transaction(money, options)
76
+ post = {}
77
+ add_credentials(post, options)
78
+ add_order(post, money, options)
79
+ commit("Netaxept/Register.aspx", post)
80
+ end
81
+
82
+ def add_and_auth_credit_card(authorization, creditcard, options)
83
+ post = {}
84
+ add_credentials(post, options, false)
85
+ add_authorization(post, authorization)
86
+ add_creditcard(post, creditcard)
87
+ commit("terminal/default.aspx", post, false)
88
+ end
89
+
90
+ def query_transaction(authorization, options)
91
+ post = {}
92
+ add_credentials(post, options)
93
+ add_authorization(post, authorization)
94
+ commit("Netaxept/query.aspx", post)
95
+ end
96
+
97
+ def add_credentials(post, options, secure=true)
81
98
  post[:merchantId] = @options[:login]
82
- post[:token] = @options[:password]
99
+ post[:token] = @options[:password] if secure
83
100
  end
84
101
 
85
102
  def add_authorization(post, authorization, money=nil)
@@ -87,92 +104,45 @@ module ActiveMerchant #:nodoc:
87
104
  post[:transactionAmount] = amount(money) if money
88
105
  end
89
106
 
90
- def add_transaction(post, options)
91
- post[:transactionId] = generate_transaction_id(options)
92
- post[:serviceType] = 'M'
93
- post[:redirectUrl] = 'http://example.com'
94
- end
95
-
96
107
  def add_order(post, money, options)
108
+ post[:serviceType] = 'M'
97
109
  post[:orderNumber] = options[:order_id]
98
110
  post[:amount] = amount(money)
99
111
  post[:currencyCode] = (options[:currency] || currency(money))
112
+ post[:autoAuth] = "true"
100
113
  end
101
114
 
102
- CARD_TYPE_PREFIXES = {
103
- 'visa' => 'v',
104
- 'master' => 'm',
105
- 'american_express' => 'a',
106
- }
107
- def add_creditcard(post, creditcard)
108
- brand = Gateway.card_brand(creditcard)
109
- prefix = CARD_TYPE_PREFIXES[brand]
110
- unless prefix
111
- raise ArgumentError.new("Card type #{brand} not supported.")
112
- end
113
-
114
- post[:creditcard] = {}
115
- post[:creditcard][:"#{prefix}a"] = creditcard.number
116
- post[:creditcard][:"#{prefix}m"] = format(creditcard.month, :two_digits)
117
- post[:creditcard][:"#{prefix}y"] = format(creditcard.year, :two_digits)
118
- post[:creditcard][:"#{prefix}c"] = creditcard.verification_value
115
+ def add_creditcard(post, options)
116
+ post[:pan] = options.number
117
+ post[:expiryDate] = format(options.month, :two_digits) + format(options.year, :two_digits)
118
+ post[:securityCode] = options.verification_value
119
119
  end
120
120
 
121
- def commit(action, parameters, setup=true)
122
- parameters[:action] = action
123
-
124
- response = {:success => false}
125
-
126
- catch(:exception) do
127
- if setup
128
- commit_transaction_setup(response, parameters)
129
- commit_payment_details(response, parameters)
130
- commit_process_setup(response, parameters)
131
- end
132
- commit_transaction(response, parameters)
133
- response[:success] = true
134
- end
135
-
136
- Response.new(response[:success], response[:message], response, :test => test?, :authorization => response[:authorization])
137
- end
138
-
139
- def commit_transaction_setup(response, parameters)
140
- response[:setup] = parse(ssl_get(build_url("REST/Setup.aspx", pick(parameters, :merchantId, :token, :serviceType, :amount, :currencyCode, :redirectUrl, :orderNumber, :transactionId))))
141
- process(response, :setup)
142
- end
143
-
144
- def commit_payment_details(response, parameters)
145
- data = encode(parameters[:creditcard].merge(:BBSePay_transaction => response[:setup]['SetupString']))
146
- response[:paymentDetails] = parse(ssl_post(build_url("terminal/default.aspx"), data), false)
147
- process(response, :paymentDetails)
148
- end
149
-
150
- def commit_process_setup(response, parameters)
151
- result = ssl_get(build_url("REST/ProcessSetup.aspx", pick(parameters, :merchantId, :token, :transactionId).merge(:transactionString => response[:paymentDetails][:result])))
152
- response[:processSetup] = parse(result)
153
- process(response, :processSetup)
154
- end
121
+ def commit(path, parameters, xml=true)
122
+ raw = parse(ssl_get(build_url(path, parameters)), xml)
155
123
 
156
- def commit_transaction(response, parameters)
157
- result = ssl_get(build_url("REST/#{parameters[:action]}.aspx", pick(parameters, :merchantId, :token, :transactionId, :transactionAmount)))
158
- response[:action] = parse(result)
159
- process(response, :action)
160
- end
161
-
162
- def process(response, step)
163
- if response[step][:container] =~ /Exception|Error/
164
- response[:message] = response[step]['Message']
165
- throw :exception
124
+ success = false
125
+ authorization = (raw["TransactionId"] || parameters[:transactionId])
126
+ if raw[:container] =~ /Exception|Error/
127
+ message = (raw["Message"] || raw["Error"]["Message"])
128
+ elsif raw["Error"] && !raw["Error"].empty?
129
+ message = (raw["Error"]["ResponseText"] || raw["Error"]["ResponseCode"])
166
130
  else
167
- message = (response[step]['ResponseText'] || response[step]['ResponseCode'])
168
- response[:message] = (message || response[:message])
169
-
170
- response[:authorization] = response[step]['TransactionId']
131
+ message = (raw["ResponseText"] || raw["ResponseCode"] || "OK")
132
+ success = true
171
133
  end
134
+
135
+ Response.new(
136
+ success,
137
+ message,
138
+ raw,
139
+ :test => test?,
140
+ :authorization => authorization
141
+ )
172
142
  end
173
143
 
174
144
  def parse(result, expects_xml=true)
175
- if expects_xml || /^</ =~ result
145
+ if expects_xml
176
146
  doc = REXML::Document.new(result)
177
147
  extract_xml(doc.root).merge(:container => doc.root.name)
178
148
  else
@@ -192,20 +162,8 @@ module ActiveMerchant #:nodoc:
192
162
  end
193
163
  end
194
164
 
195
- def url
196
- (test? ? self.test_url : self.live_url)
197
- end
198
-
199
- def generate_transaction_id(options)
200
- Digest::MD5.hexdigest("#{options.inspect}+#{Time.now}+#{rand}")
201
- end
202
-
203
- def pick(hash, *keys)
204
- keys.inject({}){|h,key| h[key] = hash[key] if hash[key]; h}
205
- end
206
-
207
165
  def build_url(base, parameters=nil)
208
- url = "#{test? ? self.test_url : self.live_url}"
166
+ url = (test? ? self.test_url : self.live_url).dup
209
167
  url << base
210
168
  if parameters
211
169
  url << '?'
@@ -217,16 +175,6 @@ module ActiveMerchant #:nodoc:
217
175
  def encode(hash)
218
176
  hash.collect{|(k,v)| "#{CGI.escape(k.to_s)}=#{CGI.escape(v.to_s)}"}.join('&')
219
177
  end
220
-
221
- class Response < Billing::Response
222
- attr_reader :error_detail
223
- def initialize(success, message, raw, options)
224
- super
225
- unless success
226
- @error_detail = raw[:processSetup]['Result']['ResponseText'] if raw[:processSetup] && raw[:processSetup]['Result']
227
- end
228
- end
229
- end
230
178
  end
231
179
  end
232
180
  end