activemerchant 1.28.0 → 1.29.1

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 (117) hide show
  1. data/CHANGELOG +41 -0
  2. data/CONTRIBUTORS +12 -0
  3. data/README.md +6 -0
  4. data/lib/active_merchant/billing/gateway.rb +2 -1
  5. data/lib/active_merchant/billing/gateways/authorize_net.rb +3 -2
  6. data/lib/active_merchant/billing/gateways/authorize_net_cim.rb +77 -78
  7. data/lib/active_merchant/billing/gateways/balanced.rb +0 -1
  8. data/lib/active_merchant/billing/gateways/banwire.rb +1 -2
  9. data/lib/active_merchant/billing/gateways/barclays_epdq.rb +19 -20
  10. data/lib/active_merchant/billing/gateways/beanstream/beanstream_core.rb +35 -36
  11. data/lib/active_merchant/billing/gateways/blue_pay.rb +135 -140
  12. data/lib/active_merchant/billing/gateways/braintree_blue.rb +12 -4
  13. data/lib/active_merchant/billing/gateways/card_stream.rb +54 -59
  14. data/lib/active_merchant/billing/gateways/certo_direct.rb +0 -1
  15. data/lib/active_merchant/billing/gateways/cyber_source.rb +19 -14
  16. data/lib/active_merchant/billing/gateways/data_cash.rb +106 -112
  17. data/lib/active_merchant/billing/gateways/efsnet.rb +29 -34
  18. data/lib/active_merchant/billing/gateways/elavon.rb +7 -1
  19. data/lib/active_merchant/billing/gateways/epay.rb +0 -1
  20. data/lib/active_merchant/billing/gateways/eway.rb +88 -93
  21. data/lib/active_merchant/billing/gateways/eway_managed.rb +47 -51
  22. data/lib/active_merchant/billing/gateways/eway_rapid.rb +300 -0
  23. data/lib/active_merchant/billing/gateways/exact.rb +45 -54
  24. data/lib/active_merchant/billing/gateways/federated_canada.rb +3 -4
  25. data/lib/active_merchant/billing/gateways/first_pay.rb +37 -38
  26. data/lib/active_merchant/billing/gateways/garanti.rb +1 -2
  27. data/lib/active_merchant/billing/gateways/hdfc.rb +207 -0
  28. data/lib/active_merchant/billing/gateways/ideal/ideal_base.rb +5 -8
  29. data/lib/active_merchant/billing/gateways/inspire.rb +52 -52
  30. data/lib/active_merchant/billing/gateways/instapay.rb +10 -11
  31. data/lib/active_merchant/billing/gateways/iridium.rb +38 -39
  32. data/lib/active_merchant/billing/gateways/itransact.rb +7 -9
  33. data/lib/active_merchant/billing/gateways/jetpay.rb +45 -46
  34. data/lib/active_merchant/billing/gateways/linkpoint.rb +104 -108
  35. data/lib/active_merchant/billing/gateways/litle.rb +1 -5
  36. data/lib/active_merchant/billing/gateways/merchant_e_solutions.rb +153 -155
  37. data/lib/active_merchant/billing/gateways/merchant_ware.rb +49 -50
  38. data/lib/active_merchant/billing/gateways/mercury.rb +272 -0
  39. data/lib/active_merchant/billing/gateways/metrics_global.rb +9 -10
  40. data/lib/active_merchant/billing/gateways/migs.rb +5 -3
  41. data/lib/active_merchant/billing/gateways/modern_payments.rb +6 -7
  42. data/lib/active_merchant/billing/gateways/modern_payments_cim.rb +40 -41
  43. data/lib/active_merchant/billing/gateways/moneris.rb +46 -50
  44. data/lib/active_merchant/billing/gateways/moneris_us.rb +52 -55
  45. data/lib/active_merchant/billing/gateways/nab_transact.rb +0 -5
  46. data/lib/active_merchant/billing/gateways/net_registry.rb +20 -21
  47. data/lib/active_merchant/billing/gateways/netaxept.rb +30 -36
  48. data/lib/active_merchant/billing/gateways/netbilling.rb +2 -2
  49. data/lib/active_merchant/billing/gateways/ogone.rb +0 -5
  50. data/lib/active_merchant/billing/gateways/optimal_payment.rb +1 -6
  51. data/lib/active_merchant/billing/gateways/orbital/avs_result.rb +93 -0
  52. data/lib/active_merchant/billing/gateways/orbital.rb +25 -21
  53. data/lib/active_merchant/billing/gateways/pay_gate_xml.rb +1 -6
  54. data/lib/active_merchant/billing/gateways/pay_junction.rb +62 -63
  55. data/lib/active_merchant/billing/gateways/pay_secure.rb +29 -30
  56. data/lib/active_merchant/billing/gateways/paybox_direct.rb +0 -5
  57. data/lib/active_merchant/billing/gateways/payflow/payflow_common_api.rb +33 -38
  58. data/lib/active_merchant/billing/gateways/payment_express.rb +48 -51
  59. data/lib/active_merchant/billing/gateways/paypal/paypal_common_api.rb +7 -11
  60. data/lib/active_merchant/billing/gateways/paypal/paypal_express_response.rb +7 -0
  61. data/lib/active_merchant/billing/gateways/paypal/paypal_recurring_api.rb +3 -0
  62. data/lib/active_merchant/billing/gateways/paystation.rb +62 -64
  63. data/lib/active_merchant/billing/gateways/payway.rb +2 -9
  64. data/lib/active_merchant/billing/gateways/plugnpay.rb +0 -1
  65. data/lib/active_merchant/billing/gateways/psigate.rb +102 -94
  66. data/lib/active_merchant/billing/gateways/psl_card.rb +66 -67
  67. data/lib/active_merchant/billing/gateways/qbms.rb +0 -6
  68. data/lib/active_merchant/billing/gateways/quantum.rb +2 -8
  69. data/lib/active_merchant/billing/gateways/quickpay.rb +2 -3
  70. data/lib/active_merchant/billing/gateways/realex.rb +6 -16
  71. data/lib/active_merchant/billing/gateways/redsys.rb +394 -0
  72. data/lib/active_merchant/billing/gateways/sage/sage_core.rb +25 -26
  73. data/lib/active_merchant/billing/gateways/sage.rb +15 -16
  74. data/lib/active_merchant/billing/gateways/sage_pay.rb +51 -56
  75. data/lib/active_merchant/billing/gateways/sallie_mae.rb +1 -2
  76. data/lib/active_merchant/billing/gateways/samurai.rb +1 -4
  77. data/lib/active_merchant/billing/gateways/secure_net.rb +0 -1
  78. data/lib/active_merchant/billing/gateways/secure_pay.rb +5 -8
  79. data/lib/active_merchant/billing/gateways/secure_pay_au.rb +0 -5
  80. data/lib/active_merchant/billing/gateways/secure_pay_tech.rb +17 -18
  81. data/lib/active_merchant/billing/gateways/skip_jack.rb +29 -34
  82. data/lib/active_merchant/billing/gateways/smart_ps.rb +55 -56
  83. data/lib/active_merchant/billing/gateways/stripe.rb +8 -3
  84. data/lib/active_merchant/billing/gateways/trans_first.rb +28 -29
  85. data/lib/active_merchant/billing/gateways/trust_commerce.rb +85 -87
  86. data/lib/active_merchant/billing/gateways/usa_epay_advanced.rb +27 -28
  87. data/lib/active_merchant/billing/gateways/usa_epay_transaction.rb +0 -5
  88. data/lib/active_merchant/billing/gateways/verifi.rb +86 -87
  89. data/lib/active_merchant/billing/gateways/viaklix.rb +42 -47
  90. data/lib/active_merchant/billing/gateways/vindicia.rb +30 -28
  91. data/lib/active_merchant/billing/gateways/webpay.rb +45 -0
  92. data/lib/active_merchant/billing/gateways/wirecard.rb +0 -6
  93. data/lib/active_merchant/billing/gateways/worldpay.rb +4 -9
  94. data/lib/active_merchant/billing/gateways.rb +6 -7
  95. data/lib/active_merchant/billing/integrations/a1agregator/helper.rb +31 -0
  96. data/lib/active_merchant/billing/integrations/a1agregator/notification.rb +186 -0
  97. data/lib/active_merchant/billing/integrations/a1agregator/status.rb +38 -0
  98. data/lib/active_merchant/billing/integrations/a1agregator.rb +26 -0
  99. data/lib/active_merchant/billing/integrations/liqpay/helper.rb +43 -0
  100. data/lib/active_merchant/billing/integrations/liqpay/notification.rb +89 -0
  101. data/lib/active_merchant/billing/integrations/liqpay/return.rb +83 -0
  102. data/lib/active_merchant/billing/integrations/liqpay.rb +30 -0
  103. data/lib/active_merchant/billing/integrations/moneybookers/helper.rb +17 -1
  104. data/lib/active_merchant/billing/integrations/notification.rb +4 -0
  105. data/lib/active_merchant/billing/integrations/pay_fast/common.rb +42 -0
  106. data/lib/active_merchant/billing/integrations/pay_fast/helper.rb +50 -0
  107. data/lib/active_merchant/billing/integrations/pay_fast/notification.rb +134 -0
  108. data/lib/active_merchant/billing/integrations/pay_fast/return.rb +10 -0
  109. data/lib/active_merchant/billing/integrations/pay_fast.rb +70 -0
  110. data/lib/active_merchant/billing/integrations/paypal/notification.rb +64 -0
  111. data/lib/active_merchant/billing/integrations/sage_pay_form/helper.rb +10 -7
  112. data/lib/active_merchant/billing/integrations/webmoney/notification.rb +12 -0
  113. data/lib/active_merchant/billing/response.rb +17 -4
  114. data/lib/active_merchant/version.rb +1 -1
  115. data.tar.gz.sig +0 -0
  116. metadata +46 -27
  117. metadata.gz.sig +0 -0
@@ -0,0 +1,272 @@
1
+ module ActiveMerchant #:nodoc:
2
+ module Billing #:nodoc:
3
+ class MercuryGateway < Gateway
4
+ URLS = {
5
+ :test => 'https://w1.mercurydev.net/ws/ws.asmx',
6
+ :live => 'https://w1.mercurypay.com/ws/ws.asmx'
7
+ }
8
+
9
+ self.homepage_url = 'http://www.mercurypay.com'
10
+ self.display_name = 'Mercury'
11
+ self.supported_countries = ['US']
12
+ self.supported_cardtypes = [:visa, :master, :american_express, :discover, :diners_club, :jcb]
13
+ self.default_currency = 'USD'
14
+
15
+ def initialize(options = {})
16
+ requires!(options, :login, :password)
17
+ super
18
+ end
19
+
20
+ def purchase(money, credit_card, options = {})
21
+ requires!(options, :order_id)
22
+
23
+ request = build_non_authorized_request('Sale', money, credit_card, options)
24
+ commit('Sale', request)
25
+ end
26
+
27
+ def credit(money, credit_card, options = {})
28
+ requires!(options, :order_id)
29
+
30
+ request = build_non_authorized_request('Return', money, credit_card, options)
31
+ commit('Return', request)
32
+ end
33
+
34
+ def authorize(money, credit_card, options = {})
35
+ requires!(options, :order_id)
36
+
37
+ options[:authorized] ||= money
38
+ request = build_non_authorized_request('PreAuth', money, credit_card, options)
39
+ commit('PreAuth', request)
40
+ end
41
+
42
+ def capture(money, authorization, options = {})
43
+ requires!(options, :credit_card)
44
+ options[:authorized] ||= money
45
+ request = build_authorized_request('PreAuthCapture', money, authorization, options[:credit_card], options)
46
+ commit('PreAuthCapture', request)
47
+ end
48
+
49
+ def refund(money, authorization, options = {})
50
+ requires!(options, :credit_card)
51
+
52
+ request = build_authorized_request('VoidSale', money, authorization, options[:credit_card], options)
53
+ commit(options[:void], request)
54
+ end
55
+
56
+ private
57
+
58
+ def build_non_authorized_request(action, money, credit_card, options)
59
+ xml = Builder::XmlMarkup.new
60
+
61
+ xml.tag! "TStream" do
62
+ xml.tag! "Transaction" do
63
+ xml.tag! 'TranType', 'Credit'
64
+ xml.tag! 'TranCode', action
65
+ if action == 'PreAuth' || action == 'Sale'
66
+ xml.tag! "PartialAuth", "Allow"
67
+ end
68
+ add_invoice(xml, options[:order_id], nil, options)
69
+ add_customer_data(xml, options)
70
+ add_amount(xml, money, options)
71
+ add_credit_card(xml, credit_card, action)
72
+ add_address(xml, options)
73
+ end
74
+ end
75
+ xml = xml.target!
76
+ end
77
+
78
+ def build_authorized_request(action, money, authorization, credit_card, options)
79
+ xml = Builder::XmlMarkup.new
80
+
81
+ invoice_no, ref_no, auth_code, acq_ref_data, process_data = split_authorization(authorization)
82
+
83
+ xml.tag! "TStream" do
84
+ xml.tag! "Transaction" do
85
+ xml.tag! 'TranType', 'Credit'
86
+ xml.tag! 'TranCode', action
87
+ if action == 'PreAuthCapture'
88
+ xml.tag! "PartialAuth", "Allow"
89
+ end
90
+ add_invoice(xml, invoice_no, ref_no, options)
91
+ add_customer_data(xml, options)
92
+ add_amount(xml, money, options)
93
+ add_credit_card(xml, credit_card, action)
94
+ add_address(xml, options)
95
+ xml.tag! 'TranInfo' do
96
+ xml.tag! "AuthCode", auth_code
97
+ xml.tag! "AcqRefData", acq_ref_data
98
+ xml.tag! "ProcessData", process_data
99
+ end
100
+ end
101
+ end
102
+ xml = xml.target!
103
+ end
104
+
105
+ def add_invoice(xml, invoice_no, ref_no, options)
106
+ if /^\d+$/ !~ invoice_no.to_s
107
+ raise ArgumentError.new("#{invoice_no} is not numeric as required by Mercury")
108
+ end
109
+
110
+ xml.tag! 'InvoiceNo', invoice_no
111
+ xml.tag! 'RefNo', ref_no || invoice_no
112
+ xml.tag! 'OperatorID', options[:merchant] if options[:merchant]
113
+ xml.tag! 'Memo', options[:description] if options[:description]
114
+ end
115
+
116
+ def add_customer_data(xml, options)
117
+ xml.tag! 'IpAddress', options[:ip] if options[:ip]
118
+ if options[:customer]
119
+ xml.tag! "TranInfo" do
120
+ xml.tag! 'CustomerCode', options[:customer]
121
+ end
122
+ end
123
+ xml.tag! 'MerchantID', @options[:login]
124
+ end
125
+
126
+ def add_amount(xml, money, options = {})
127
+ xml.tag! 'Amount' do
128
+ xml.tag! 'Purchase', amount(money)
129
+ xml.tag! 'Tax', options[:tax] if options[:tax]
130
+ xml.tag! 'Authorize', amount(options[:authorized]) if options[:authorized]
131
+ xml.tag! 'Gratuity', amount(options[:tip]) if options[:tip]
132
+ end
133
+ end
134
+
135
+ CARD_CODES = {
136
+ 'visa' => 'VISA',
137
+ 'master' => 'M/C',
138
+ 'american_express' => 'AMEX',
139
+ 'discover' => 'DCVR',
140
+ 'diners_club' => 'DCLB',
141
+ 'jcb' => 'JCB'
142
+ }
143
+
144
+ def add_credit_card(xml, credit_card, action)
145
+ xml.tag! 'Account' do
146
+ xml.tag! 'AcctNo', credit_card.number
147
+ xml.tag! 'ExpDate', expdate(credit_card)
148
+ end
149
+ xml.tag! 'CardType', CARD_CODES[credit_card.brand] if credit_card.brand
150
+
151
+ include_cvv = !%w(Return PreAuthCapture).include?(action)
152
+ xml.tag! 'CVVData', credit_card.verification_value if(include_cvv && credit_card.verification_value)
153
+ end
154
+
155
+ def expdate(credit_card)
156
+ year = sprintf("%.4i", credit_card.year)
157
+ month = sprintf("%.2i", credit_card.month)
158
+
159
+ "#{month}#{year[-2..-1]}"
160
+ end
161
+
162
+ def add_address(xml, options)
163
+ if billing_address = options[:billing_address] || options[:address]
164
+ xml.tag! 'AVS' do
165
+ xml.tag! 'Address', billing_address[:address1]
166
+ xml.tag! 'Zip', billing_address[:zip]
167
+ end
168
+ end
169
+ end
170
+
171
+ def parse(action, body)
172
+ response = {}
173
+ hashify_xml!(unescape_xml(body), response)
174
+ response
175
+ end
176
+
177
+ def hashify_xml!(xml, response)
178
+ xml = REXML::Document.new(xml)
179
+
180
+ xml.elements.each("//CmdResponse/*") do |node|
181
+ response[node.name.underscore.to_sym] = node.text
182
+ end
183
+
184
+ xml.elements.each("//TranResponse/*") do |node|
185
+ if node.name.to_s == "Amount"
186
+ node.elements.each do |amt|
187
+ response[amt.name.underscore.to_sym] = amt.text
188
+ end
189
+ else
190
+ response[node.name.underscore.to_sym] = node.text
191
+ end
192
+ end
193
+ end
194
+
195
+ def endpoint_url
196
+ URLS[test? ? :test : :live]
197
+ end
198
+
199
+ def build_soap_request(body)
200
+ xml = Builder::XmlMarkup.new
201
+
202
+ xml.instruct!
203
+ xml.tag! 'soap:Envelope', ENVELOPE_NAMESPACES do
204
+ xml.tag! 'soap:Body' do
205
+ xml.tag! 'CreditTransaction', 'xmlns' => homepage_url do
206
+ xml.tag! 'tran' do
207
+ xml << escape_xml(body)
208
+ end
209
+ xml.tag! 'pw', @options[:password]
210
+ end
211
+ end
212
+ end
213
+ xml.target!
214
+ end
215
+
216
+ def build_header
217
+ {
218
+ "SOAPAction" => "http://www.mercurypay.com/CreditTransaction",
219
+ "Content-Type" => "text/xml; charset=utf-8"
220
+ }
221
+ end
222
+
223
+ SUCCESS_CODES = [ 'Approved', 'Success' ]
224
+
225
+ def commit(action, request)
226
+ response = parse(action, ssl_post(endpoint_url, build_soap_request(request), build_header))
227
+
228
+ success = SUCCESS_CODES.include?(response[:cmd_status])
229
+ message = success ? 'Success' : message_from(response)
230
+
231
+ Response.new(success, message, response,
232
+ :test => test?,
233
+ :authorization => authorization_from(response),
234
+ :avs_result => { :code => response[:avs_result] },
235
+ :cvv_result => response[:cvv_result])
236
+ end
237
+
238
+ def message_from(response)
239
+ response[:text_response]
240
+ end
241
+
242
+ def authorization_from(response)
243
+ [
244
+ response[:invoice_no],
245
+ response[:ref_no],
246
+ response[:auth_code],
247
+ response[:acq_ref_data],
248
+ response[:process_data]
249
+ ].join(";")
250
+ end
251
+
252
+ def split_authorization(authorization)
253
+ invoice_no, ref_no, auth_code, acq_ref_data, process_data = authorization.split(";")
254
+ [invoice_no, ref_no, auth_code, acq_ref_data, process_data]
255
+ end
256
+
257
+ ENVELOPE_NAMESPACES = {
258
+ 'xmlns:xsd' => 'http://www.w3.org/2001/XMLSchema',
259
+ 'xmlns:soap' => "http://schemas.xmlsoap.org/soap/envelope/",
260
+ 'xmlns:xsi' => 'http://www.w3.org/2001/XMLSchema-instance'
261
+ }
262
+
263
+ def escape_xml(xml)
264
+ "\n<![CDATA[\n#{xml}\n]]>\n"
265
+ end
266
+
267
+ def unescape_xml(escaped_xml)
268
+ escaped_xml.gsub(/\&gt;/,'>').gsub(/\&lt;/,'<')
269
+ end
270
+ end
271
+ end
272
+ end
@@ -48,11 +48,10 @@ module ActiveMerchant #:nodoc:
48
48
  #
49
49
  # * <tt>:login</tt> -- The username required to access the Metrics Global control panel. (REQUIRED)
50
50
  # * <tt>:password</tt> -- The password required to access the Metrics Global control panel. (REQUIRED)
51
- # * <tt>:test</tt> -- +true+ or +false+. If true, perform transactions against the test server.
51
+ # * <tt>:test</tt> -- +true+ or +false+. If true, perform transactions against the test server.
52
52
  # Otherwise, perform transactions against the production server.
53
53
  def initialize(options = {})
54
54
  requires!(options, :login, :password)
55
- @options = options
56
55
  super
57
56
  end
58
57
 
@@ -156,7 +155,7 @@ module ActiveMerchant #:nodoc:
156
155
  end
157
156
 
158
157
  private
159
-
158
+
160
159
  def commit(action, money, parameters)
161
160
  parameters[:amount] = amount(money) unless action == 'VOID'
162
161
 
@@ -177,8 +176,8 @@ module ActiveMerchant #:nodoc:
177
176
  # (TESTMODE) Successful Sale
178
177
  test_mode = test? || message =~ /TESTMODE/
179
178
 
180
- Response.new(success?(response), message, response,
181
- :test => test_mode,
179
+ Response.new(success?(response), message, response,
180
+ :test => test_mode,
182
181
  :authorization => response[:transaction_id],
183
182
  :fraud_review => fraud_review?(response),
184
183
  :avs_result => { :code => response[:avs_result_code] },
@@ -199,7 +198,7 @@ module ActiveMerchant #:nodoc:
199
198
 
200
199
  results = {
201
200
  :response_code => fields[RESPONSE_CODE].to_i,
202
- :response_reason_code => fields[RESPONSE_REASON_CODE],
201
+ :response_reason_code => fields[RESPONSE_REASON_CODE],
203
202
  :response_reason_text => fields[RESPONSE_REASON_TEXT],
204
203
  :avs_result_code => fields[AVS_RESULT_CODE],
205
204
  :transaction_id => fields[TRANSACTION_ID],
@@ -252,7 +251,7 @@ module ActiveMerchant #:nodoc:
252
251
  post[:customer_ip] = options[:ip]
253
252
  end
254
253
  end
255
-
254
+
256
255
  # x_duplicate_window won't be sent by default, because sending it changes the response.
257
256
  # "If this field is present in the request with or without a value, an enhanced duplicate transaction response will be sent."
258
257
  def add_duplicate_window(post)
@@ -271,7 +270,7 @@ module ActiveMerchant #:nodoc:
271
270
  post[:country] = address[:country].to_s
272
271
  post[:state] = address[:state].blank? ? 'n/a' : address[:state]
273
272
  end
274
-
273
+
275
274
  if address = options[:shipping_address]
276
275
  post[:ship_to_first_name] = address[:first_name].to_s
277
276
  post[:ship_to_last_name] = address[:last_name].to_s
@@ -296,11 +295,11 @@ module ActiveMerchant #:nodoc:
296
295
  end
297
296
  end
298
297
 
299
- def message_from(results)
298
+ def message_from(results)
300
299
  if results[:response_code] == DECLINED
301
300
  return CVVResult.messages[ results[:card_code] ] if CARD_CODE_ERRORS.include?(results[:card_code])
302
301
  if AVS_REASON_CODES.include?(results[:response_reason_code]) && AVS_ERRORS.include?(results[:avs_result_code])
303
- return AVSResult.messages[ results[:avs_result_code] ]
302
+ return AVSResult.messages[ results[:avs_result_code] ]
304
303
  end
305
304
  end
306
305
 
@@ -46,8 +46,6 @@ module ActiveMerchant #:nodoc:
46
46
  # * <tt>:advanced_password</tt> -- The MiGS AMA User's password
47
47
  def initialize(options = {})
48
48
  requires!(options, :login, :password)
49
- @test = options[:login].start_with?('TEST')
50
- @options = options
51
49
  super
52
50
  end
53
51
 
@@ -180,6 +178,10 @@ module ActiveMerchant #:nodoc:
180
178
  response_object(response_hash)
181
179
  end
182
180
 
181
+ def test?
182
+ @options[:login].start_with?('TEST')
183
+ end
184
+
183
185
  private
184
186
 
185
187
  def add_advanced_user(post)
@@ -219,7 +221,7 @@ module ActiveMerchant #:nodoc:
219
221
 
220
222
  def response_object(response)
221
223
  Response.new(success?(response), response[:Message], response,
222
- :test => @test,
224
+ :test => test?,
223
225
  :authorization => response[:TransactionNo],
224
226
  :fraud_review => fraud_review?(response),
225
227
  :avs_result => { :code => response[:AVSResultCode] },
@@ -7,27 +7,26 @@ module ActiveMerchant #:nodoc:
7
7
  self.supported_cardtypes = ModernPaymentsCimGateway.supported_cardtypes
8
8
  self.homepage_url = ModernPaymentsCimGateway.homepage_url
9
9
  self.display_name = ModernPaymentsCimGateway.display_name
10
-
10
+
11
11
  self.abstract_class = true
12
12
 
13
13
  def initialize(options = {})
14
14
  requires!(options, :login, :password)
15
- @options = options
16
15
  super
17
16
  end
18
-
17
+
19
18
  def purchase(money, credit_card, options = {})
20
19
  customer_response = cim.create_customer(options)
21
20
  return customer_response unless customer_response.success?
22
-
21
+
23
22
  customer_id = customer_response.params["create_customer_result"]
24
-
23
+
25
24
  card_response = cim.modify_customer_credit_card(customer_id, credit_card)
26
25
  return card_response unless card_response.success?
27
-
26
+
28
27
  cim.authorize_credit_card_payment(customer_id, money)
29
28
  end
30
-
29
+
31
30
  private
32
31
  def cim
33
32
  @cim ||= ModernPaymentsCimGateway.new(@options)
@@ -3,66 +3,65 @@ module ActiveMerchant #:nodoc:
3
3
  class ModernPaymentsCimGateway < Gateway #:nodoc:
4
4
  self.test_url = "https://secure.modpay.com/netservices/test/ModpayTest.asmx"
5
5
  self.live_url = 'https://secure.modpay.com/ws/modpay.asmx'
6
-
6
+
7
7
  LIVE_XMLNS = "https://secure.modpay.com/ws/"
8
8
  TEST_XMLNS = "https://secure.modpay.com/netservices/test/"
9
-
9
+
10
10
  self.supported_countries = ['US']
11
11
  self.supported_cardtypes = [:visa, :master, :american_express, :discover]
12
12
  self.homepage_url = 'http://www.modpay.com'
13
13
  self.display_name = 'Modern Payments'
14
-
14
+
15
15
  SUCCESS_MESSAGE = "Transaction accepted"
16
16
  FAILURE_MESSAGE = "Transaction failed"
17
17
  ERROR_MESSAGE = "Transaction error"
18
-
18
+
19
19
  PAYMENT_METHOD = {
20
20
  :check => 1,
21
21
  :credit_card => 2
22
22
  }
23
-
23
+
24
24
  def initialize(options = {})
25
25
  requires!(options, :login, :password)
26
- @options = options
27
26
  super
28
- end
29
-
27
+ end
28
+
30
29
  def create_customer(options = {})
31
30
  post = {}
32
31
  add_customer_data(post, options)
33
32
  add_address(post, options)
34
-
33
+
35
34
  commit('CreateCustomer', post)
36
35
  end
37
-
36
+
38
37
  def modify_customer_credit_card(customer_id, credit_card)
39
38
  raise ArgumentError, "The customer_id cannot be blank" if customer_id.blank?
40
-
39
+
41
40
  post = {}
42
41
  add_customer_id(post, customer_id)
43
42
  add_credit_card(post, credit_card)
44
-
43
+
45
44
  commit('ModifyCustomerCreditCard', post)
46
45
  end
47
-
46
+
48
47
  def authorize_credit_card_payment(customer_id, amount)
49
48
  raise ArgumentError, "The customer_id cannot be blank" if customer_id.blank?
50
-
49
+
51
50
  post = {}
52
51
  add_customer_id(post, customer_id)
53
52
  add_amount(post, amount)
54
-
53
+
55
54
  commit('AuthorizeCreditCardPayment', post)
56
55
  end
57
-
56
+
58
57
  def create_payment(customer_id, amount, options = {})
59
58
  raise ArgumentError, "The customer_id cannot be blank" if customer_id.blank?
60
-
59
+
61
60
  post = {}
62
61
  add_customer_id(post, customer_id)
63
62
  add_amount(post, amount)
64
63
  add_payment_details(post, options)
65
-
64
+
66
65
  commit('CreatePayment', post)
67
66
  end
68
67
 
@@ -71,22 +70,22 @@ module ActiveMerchant #:nodoc:
71
70
  post[:pmtDate] = (options[:payment_date] || Time.now.utc).strftime("%Y-%m-%dT%H:%M:%SZ")
72
71
  post[:pmtType] = PAYMENT_METHOD[options[:payment_method] || :credit_card]
73
72
  end
74
-
73
+
75
74
  def add_amount(post, money)
76
75
  post[:pmtAmount] = amount(money)
77
76
  end
78
-
77
+
79
78
  def add_customer_id(post, customer_id)
80
79
  post[:custId] = customer_id
81
80
  end
82
-
81
+
83
82
  def add_customer_data(post, options)
84
83
  post[:acctNum] = options[:customer]
85
84
  end
86
-
85
+
87
86
  def add_address(post, options)
88
87
  address = options[:billing_address] || options[:address] || {}
89
-
88
+
90
89
  if name = address[:name]
91
90
  segments = name.split(' ')
92
91
  post[:lastName] = segments.pop
@@ -95,7 +94,7 @@ module ActiveMerchant #:nodoc:
95
94
  post[:firstName] = address[:first_name]
96
95
  post[:lastName] = address[:last_name]
97
96
  end
98
-
97
+
99
98
  post[:address] = address[:address1]
100
99
  post[:city] = address[:city]
101
100
  post[:state] = address[:state]
@@ -104,14 +103,14 @@ module ActiveMerchant #:nodoc:
104
103
  post[:fax] = address[:fax]
105
104
  post[:email] = options[:email]
106
105
  end
107
-
106
+
108
107
  def add_credit_card(post, credit_card)
109
108
  post[:ccName] = credit_card.name
110
109
  post[:ccNum] = credit_card.number
111
110
  post[:expMonth] = credit_card.month
112
111
  post[:expYear] = credit_card.year
113
112
  end
114
-
113
+
115
114
  def build_request(action, params)
116
115
  xml = Builder::XmlMarkup.new :indent => 2
117
116
  xml.instruct!
@@ -130,7 +129,7 @@ module ActiveMerchant #:nodoc:
130
129
  end
131
130
  xml.target!
132
131
  end
133
-
132
+
134
133
  def xmlns(action)
135
134
  if test? && action == 'AuthorizeCreditCardPayment'
136
135
  TEST_XMLNS
@@ -138,7 +137,7 @@ module ActiveMerchant #:nodoc:
138
137
  LIVE_XMLNS
139
138
  end
140
139
  end
141
-
140
+
142
141
  def url(action)
143
142
  if test? && action == 'AuthorizeCreditCardPayment'
144
143
  self.test_url
@@ -146,39 +145,39 @@ module ActiveMerchant #:nodoc:
146
145
  self.live_url
147
146
  end
148
147
  end
149
-
148
+
150
149
  def commit(action, params)
151
- data = ssl_post(url(action), build_request(action, params),
152
- { 'Content-Type' =>'text/xml; charset=utf-8',
150
+ data = ssl_post(url(action), build_request(action, params),
151
+ { 'Content-Type' =>'text/xml; charset=utf-8',
153
152
  'SOAPAction' => "#{xmlns(action)}#{action}" }
154
153
  )
155
154
 
156
155
  response = parse(action, data)
157
- Response.new(successful?(action, response), message_from(action, response), response,
158
- :test => test?,
156
+ Response.new(successful?(action, response), message_from(action, response), response,
157
+ :test => test?,
159
158
  :authorization => authorization_from(action, response),
160
159
  :avs_result => { :code => response[:avs_code] }
161
160
  )
162
161
  end
163
-
162
+
164
163
  def authorization_from(action, response)
165
164
  response[authorization_key(action)]
166
165
  end
167
-
166
+
168
167
  def authorization_key(action)
169
168
  action == "AuthorizeCreditCardPayment" ? :trans_id : "#{action.underscore}_result".to_sym
170
169
  end
171
-
170
+
172
171
  def successful?(action, response)
173
172
  key = authorization_key(action)
174
-
173
+
175
174
  if key == :trans_id
176
175
  response[:approved] == "true"
177
176
  else
178
177
  response[key].to_i > 0
179
178
  end
180
179
  end
181
-
180
+
182
181
  def message_from(action, response)
183
182
  if response[:faultcode]
184
183
  ERROR_MESSAGE
@@ -188,11 +187,11 @@ module ActiveMerchant #:nodoc:
188
187
  FAILURE_MESSAGE
189
188
  end
190
189
  end
191
-
190
+
192
191
  def parse(action, xml)
193
192
  response = {}
194
193
  response[:action] = action
195
-
194
+
196
195
  xml = REXML::Document.new(xml)
197
196
  if root = REXML::XPath.first(xml, "//#{action}Response")
198
197
  root.elements.to_a.each do |node|
@@ -206,7 +205,7 @@ module ActiveMerchant #:nodoc:
206
205
 
207
206
  response
208
207
  end
209
-
208
+
210
209
  def parse_element(response, node)
211
210
  if node.has_elements?
212
211
  node.elements.each{|e| parse_element(response, e) }