bitfluent-activemerchant 1.5.1.1 → 1.15.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (121) hide show
  1. data/CHANGELOG +168 -0
  2. data/CONTRIBUTORS +96 -1
  3. data/README.rdoc +33 -5
  4. data/lib/active_merchant.rb +12 -0
  5. data/lib/active_merchant/billing/credit_card.rb +59 -46
  6. data/lib/active_merchant/billing/credit_card_methods.rb +3 -3
  7. data/lib/active_merchant/billing/gateway.rb +16 -9
  8. data/lib/active_merchant/billing/gateways/authorize_net.rb +19 -9
  9. data/lib/active_merchant/billing/gateways/authorize_net_cim.rb +134 -12
  10. data/lib/active_merchant/billing/gateways/barclays_epdq.rb +309 -0
  11. data/lib/active_merchant/billing/gateways/beanstream.rb +39 -2
  12. data/lib/active_merchant/billing/gateways/beanstream/beanstream_core.rb +64 -26
  13. data/lib/active_merchant/billing/gateways/blue_pay.rb +11 -0
  14. data/lib/active_merchant/billing/gateways/bogus.rb +33 -3
  15. data/lib/active_merchant/billing/gateways/braintree.rb +11 -11
  16. data/lib/active_merchant/billing/gateways/braintree/braintree_common.rb +9 -0
  17. data/lib/active_merchant/billing/gateways/braintree_blue.rb +293 -0
  18. data/lib/active_merchant/billing/gateways/braintree_orange.rb +17 -0
  19. data/lib/active_merchant/billing/gateways/cyber_source.rb +5 -1
  20. data/lib/active_merchant/billing/gateways/data_cash.rb +6 -2
  21. data/lib/active_merchant/billing/gateways/efsnet.rb +8 -2
  22. data/lib/active_merchant/billing/gateways/epay.rb +268 -0
  23. data/lib/active_merchant/billing/gateways/eway_managed.rb +231 -0
  24. data/lib/active_merchant/billing/gateways/federated_canada.rb +168 -0
  25. data/lib/active_merchant/billing/gateways/first_pay.rb +8 -3
  26. data/lib/active_merchant/billing/gateways/garanti.rb +132 -92
  27. data/lib/active_merchant/billing/gateways/ideal/ideal_base.rb +250 -0
  28. data/lib/active_merchant/billing/gateways/ideal/ideal_rabobank.pem +13 -0
  29. data/lib/active_merchant/billing/gateways/ideal/ideal_response.rb +29 -0
  30. data/lib/active_merchant/billing/gateways/ideal_rabobank.rb +55 -0
  31. data/lib/active_merchant/billing/gateways/inspire.rb +221 -0
  32. data/lib/active_merchant/billing/gateways/iridium.rb +258 -0
  33. data/lib/active_merchant/billing/gateways/jetpay.rb +12 -6
  34. data/lib/active_merchant/billing/gateways/linkpoint.rb +6 -1
  35. data/lib/active_merchant/billing/gateways/merchant_e_solutions.rb +10 -8
  36. data/lib/active_merchant/billing/gateways/merchant_ware.rb +7 -1
  37. data/lib/active_merchant/billing/gateways/moneris.rb +6 -2
  38. data/lib/active_merchant/billing/gateways/netaxept.rb +239 -0
  39. data/lib/active_merchant/billing/gateways/nmi.rb +13 -0
  40. data/lib/active_merchant/billing/gateways/ogone.rb +16 -3
  41. data/lib/active_merchant/billing/gateways/orbital.rb +317 -0
  42. data/lib/active_merchant/billing/gateways/orbital/orbital_soft_descriptors.rb +46 -0
  43. data/lib/active_merchant/billing/gateways/pay_junction.rb +9 -9
  44. data/lib/active_merchant/billing/gateways/paybox_direct.rb +207 -0
  45. data/lib/active_merchant/billing/gateways/payflow.rb +26 -9
  46. data/lib/active_merchant/billing/gateways/payflow/payflow_common_api.rb +11 -11
  47. data/lib/active_merchant/billing/gateways/payflow_express.rb +122 -38
  48. data/lib/active_merchant/billing/gateways/payment_express.rb +7 -2
  49. data/lib/active_merchant/billing/gateways/paypal.rb +5 -5
  50. data/lib/active_merchant/billing/gateways/paypal/paypal_common_api.rb +33 -8
  51. data/lib/active_merchant/billing/gateways/paypal/paypal_express_response.rb +26 -15
  52. data/lib/active_merchant/billing/gateways/paypal_ca.rb +1 -1
  53. data/lib/active_merchant/billing/gateways/paypal_express.rb +55 -13
  54. data/lib/active_merchant/billing/gateways/paypal_express_common.rb +8 -3
  55. data/lib/active_merchant/billing/gateways/plugnpay.rb +9 -3
  56. data/lib/active_merchant/billing/gateways/psigate.rb +5 -0
  57. data/lib/active_merchant/billing/gateways/qbms.rb +295 -0
  58. data/lib/active_merchant/billing/gateways/quantum.rb +282 -0
  59. data/lib/active_merchant/billing/gateways/quickpay.rb +7 -2
  60. data/lib/active_merchant/billing/gateways/realex.rb +187 -76
  61. data/lib/active_merchant/billing/gateways/sage_pay.rb +16 -5
  62. data/lib/active_merchant/billing/gateways/secure_net.rb +330 -0
  63. data/lib/active_merchant/billing/gateways/secure_pay_au.rb +39 -3
  64. data/lib/active_merchant/billing/gateways/smart_ps.rb +9 -3
  65. data/lib/active_merchant/billing/gateways/trust_commerce.rb +7 -2
  66. data/lib/active_merchant/billing/gateways/usa_epay.rb +1 -1
  67. data/lib/active_merchant/billing/gateways/verifi.rb +6 -1
  68. data/lib/active_merchant/billing/gateways/viaklix.rb +1 -1
  69. data/lib/active_merchant/billing/gateways/worldpay.rb +280 -0
  70. data/lib/active_merchant/billing/integrations.rb +0 -12
  71. data/lib/active_merchant/billing/integrations/action_view_helper.rb +13 -24
  72. data/lib/active_merchant/billing/integrations/bogus.rb +2 -2
  73. data/lib/active_merchant/billing/integrations/chronopay.rb +2 -2
  74. data/lib/active_merchant/billing/integrations/direc_pay.rb +41 -0
  75. data/lib/active_merchant/billing/integrations/direc_pay/helper.rb +200 -0
  76. data/lib/active_merchant/billing/integrations/direc_pay/notification.rb +76 -0
  77. data/lib/active_merchant/billing/integrations/direc_pay/return.rb +32 -0
  78. data/lib/active_merchant/billing/integrations/direc_pay/status.rb +37 -0
  79. data/lib/active_merchant/billing/integrations/directebanking.rb +47 -0
  80. data/lib/active_merchant/billing/integrations/directebanking/helper.rb +90 -0
  81. data/lib/active_merchant/billing/integrations/directebanking/notification.rb +120 -0
  82. data/lib/active_merchant/billing/integrations/directebanking/return.rb +11 -0
  83. data/lib/active_merchant/billing/integrations/gestpay.rb +2 -2
  84. data/lib/active_merchant/billing/integrations/helper.rb +14 -11
  85. data/lib/active_merchant/billing/integrations/hi_trust.rb +2 -2
  86. data/lib/active_merchant/billing/integrations/ipay88.rb +4 -4
  87. data/lib/active_merchant/billing/integrations/moneybookers.rb +26 -0
  88. data/lib/active_merchant/billing/integrations/moneybookers/helper.rb +59 -0
  89. data/lib/active_merchant/billing/integrations/moneybookers/notification.rb +129 -0
  90. data/lib/active_merchant/billing/integrations/nochex.rb +2 -2
  91. data/lib/active_merchant/billing/integrations/notification.rb +1 -1
  92. data/lib/active_merchant/billing/integrations/paypal.rb +2 -2
  93. data/lib/active_merchant/billing/integrations/quickpay.rb +6 -2
  94. data/lib/active_merchant/billing/integrations/quickpay/helper.rb +1 -1
  95. data/lib/active_merchant/billing/integrations/quickpay/notification.rb +2 -2
  96. data/lib/active_merchant/billing/integrations/return.rb +10 -3
  97. data/lib/active_merchant/billing/integrations/sage_pay_form.rb +37 -0
  98. data/lib/active_merchant/billing/integrations/sage_pay_form/encryption.rb +33 -0
  99. data/lib/active_merchant/billing/integrations/sage_pay_form/helper.rb +111 -0
  100. data/lib/active_merchant/billing/integrations/sage_pay_form/notification.rb +210 -0
  101. data/lib/active_merchant/billing/integrations/sage_pay_form/return.rb +31 -0
  102. data/lib/active_merchant/billing/integrations/two_checkout.rb +2 -2
  103. data/lib/active_merchant/billing/integrations/two_checkout/notification.rb +5 -5
  104. data/lib/active_merchant/billing/integrations/valitor.rb +33 -0
  105. data/lib/active_merchant/billing/integrations/valitor/helper.rb +86 -0
  106. data/lib/active_merchant/billing/integrations/valitor/notification.rb +13 -0
  107. data/lib/active_merchant/billing/integrations/valitor/response_fields.rb +88 -0
  108. data/lib/active_merchant/billing/integrations/valitor/return.rb +13 -0
  109. data/lib/active_merchant/billing/integrations/world_pay.rb +27 -0
  110. data/lib/active_merchant/billing/integrations/world_pay/helper.rb +100 -0
  111. data/lib/active_merchant/billing/integrations/world_pay/notification.rb +160 -0
  112. data/lib/active_merchant/common.rb +1 -1
  113. data/lib/active_merchant/common/connection.rb +13 -8
  114. data/lib/active_merchant/common/country.rb +15 -6
  115. data/lib/active_merchant/common/post_data.rb +1 -1
  116. data/lib/active_merchant/common/posts_data.rb +21 -5
  117. data/lib/active_merchant/common/utils.rb +4 -0
  118. data/lib/active_merchant/common/validateable.rb +20 -15
  119. data/lib/active_merchant/version.rb +3 -0
  120. data/lib/support/gateway_support.rb +1 -1
  121. metadata +65 -27
@@ -0,0 +1,17 @@
1
+ require File.dirname(__FILE__) + '/smart_ps.rb'
2
+ require File.dirname(__FILE__) + '/braintree/braintree_common'
3
+
4
+ module ActiveMerchant #:nodoc:
5
+ module Billing #:nodoc:
6
+ class BraintreeOrangeGateway < SmartPs
7
+ include BraintreeCommon
8
+
9
+ self.display_name = 'Braintree (Orange Platform)'
10
+
11
+ def api_url
12
+ 'https://secure.braintreepaymentgateway.com/api/transact.php'
13
+ end
14
+ end
15
+ end
16
+ end
17
+
@@ -128,10 +128,14 @@ module ActiveMerchant #:nodoc:
128
128
  commit(build_void_request(identification, options), options)
129
129
  end
130
130
 
131
- def credit(money, identification, options = {})
131
+ def refund(money, identification, options = {})
132
132
  commit(build_credit_request(money, identification, options), options)
133
133
  end
134
134
 
135
+ def credit(money, identification, options = {})
136
+ deprecated CREDIT_DEPRECATION_MESSAGE
137
+ refund(money, identification, options)
138
+ end
135
139
 
136
140
  # CyberSource requires that you provide line item information for tax calculations
137
141
  # If you do not have prices for each item or want to simplify the situation then pass in one fake line item that costs the subtotal of the order
@@ -139,12 +139,16 @@ module ActiveMerchant
139
139
  # * <tt>:address</tt>:: billing address for card
140
140
  def credit(money, reference_or_credit_card, options = {})
141
141
  if reference_or_credit_card.is_a?(String)
142
- request = build_transaction_refund_request(money, reference_or_credit_card)
142
+ deprecated CREDIT_DEPRECATION_MESSAGE
143
+ refund(money, reference_or_credit_card)
143
144
  else
144
145
  request = build_refund_request(money, reference_or_credit_card, options)
146
+ commit(request)
145
147
  end
148
+ end
146
149
 
147
- commit(request)
150
+ def refund(money, reference, options = {})
151
+ commit(build_transaction_refund_request(money, reference))
148
152
  end
149
153
 
150
154
  # Is the gateway running in test mode?
@@ -41,9 +41,9 @@ module ActiveMerchant #:nodoc:
41
41
 
42
42
  def credit(money, identification_or_credit_card, options = {})
43
43
  if identification_or_credit_card.is_a?(String)
44
+ deprecated CREDIT_DEPRECATION_MESSAGE
44
45
  # Perform authorization reversal
45
- request = build_refund_or_settle_request(money, identification_or_credit_card, options)
46
- commit(:credit_card_refund, request)
46
+ refund(money, identification_or_credit_card, options)
47
47
  else
48
48
  # Perform credit
49
49
  request = build_credit_card_request(money, identification_or_credit_card, options)
@@ -51,6 +51,12 @@ module ActiveMerchant #:nodoc:
51
51
  end
52
52
  end
53
53
 
54
+ def refund(money, reference, options = {})
55
+ # Perform authorization reversal
56
+ request = build_refund_or_settle_request(money, reference, options)
57
+ commit(:credit_card_refund, request)
58
+ end
59
+
54
60
  def void(identification, options = {})
55
61
  requires!(options, :order_id)
56
62
  original_transaction_id, original_transaction_amount = identification.split(";")
@@ -0,0 +1,268 @@
1
+ module ActiveMerchant #:nodoc:
2
+ module Billing #:nodoc:
3
+ class EpayGateway < Gateway
4
+ API_HOST = 'ssl.ditonlinebetalingssystem.dk'
5
+ SOAP_URL = 'https://' + API_HOST + '/remote/payment'
6
+
7
+ self.default_currency = 'DKK'
8
+ self.money_format = :cents
9
+ self.supported_cardtypes = [:dankort, :forbrugsforeningen, :visa, :master,
10
+ :american_express, :diners_club, :jcb, :maestro]
11
+ self.supported_countries = ['DK']
12
+ self.homepage_url = 'http://epay.dk/'
13
+ self.display_name = 'ePay'
14
+
15
+ CURRENCY_CODES = {
16
+ :ADP => '020', :AED => '784', :AFA => '004', :ALL => '008', :AMD => '051',
17
+ :ANG => '532', :AOA => '973', :ARS => '032', :AUD => '036', :AWG => '533',
18
+ :AZM => '031', :BAM => '977', :BBD => '052', :BDT => '050', :BGL => '100',
19
+ :BGN => '975', :BHD => '048', :BIF => '108', :BMD => '060', :BND => '096',
20
+ :BOB => '068', :BOV => '984', :BRL => '986', :BSD => '044', :BTN => '064',
21
+ :BWP => '072', :BYR => '974', :BZD => '084', :CAD => '124', :CDF => '976',
22
+ :CHF => '756', :CLF => '990', :CLP => '152', :CNY => '156', :COP => '170',
23
+ :CRC => '188', :CUP => '192', :CVE => '132', :CYP => '196', :CZK => '203',
24
+ :DJF => '262', :DKK => '208', :DOP => '214', :DZD => '012', :ECS => '218',
25
+ :ECV => '983', :EEK => '233', :EGP => '818', :ERN => '232', :ETB => '230',
26
+ :EUR => '978', :FJD => '242', :FKP => '238', :GBP => '826', :GEL => '981',
27
+ :GHC => '288', :GIP => '292', :GMD => '270', :GNF => '324', :GTQ => '320',
28
+ :GWP => '624', :GYD => '328', :HKD => '344', :HNL => '340', :HRK => '191',
29
+ :HTG => '332', :HUF => '348', :IDR => '360', :ILS => '376', :INR => '356',
30
+ :IQD => '368', :IRR => '364', :ISK => '352', :JMD => '388', :JOD => '400',
31
+ :JPY => '392', :KES => '404', :KGS => '417', :KHR => '116', :KMF => '174',
32
+ :KPW => '408', :KRW => '410', :KWD => '414', :KYD => '136', :KZT => '398',
33
+ :LAK => '418', :LBP => '422', :LKR => '144', :LRD => '430', :LSL => '426',
34
+ :LTL => '440', :LVL => '428', :LYD => '434', :MAD => '504', :MDL => '498',
35
+ :MGF => '450', :MKD => '807', :MMK => '104', :MNT => '496', :MOP => '446',
36
+ :MRO => '478', :MTL => '470', :MUR => '480', :MVR => '462', :MWK => '454',
37
+ :MXN => '484', :MXV => '979', :MYR => '458', :MZM => '508', :NAD => '516',
38
+ :NGN => '566', :NIO => '558', :NOK => '578', :NPR => '524', :NZD => '554',
39
+ :OMR => '512', :PAB => '590', :PEN => '604', :PGK => '598', :PHP => '608',
40
+ :PKR => '586', :PLN => '985', :PYG => '600', :QAR => '634', :ROL => '642',
41
+ :RUB => '643', :RUR => '810', :RWF => '646', :SAR => '682', :SBD => '090',
42
+ :SCR => '690', :SDD => '736', :SEK => '752', :SGD => '702', :SHP => '654',
43
+ :SIT => '705', :SKK => '703', :SLL => '694', :SOS => '706', :SRG => '740',
44
+ :STD => '678', :SVC => '222', :SYP => '760', :SZL => '748', :THB => '764',
45
+ :TJS => '972', :TMM => '795', :TND => '788', :TOP => '776', :TPE => '626',
46
+ :TRL => '792', :TRY => '949', :TTD => '780', :TWD => '901', :TZS => '834',
47
+ :UAH => '980', :UGX => '800', :USD => '840', :UYU => '858', :UZS => '860',
48
+ :VEB => '862', :VND => '704', :VUV => '548', :XAF => '950', :XCD => '951',
49
+ :XOF => '952', :XPF => '953', :YER => '886', :YUM => '891', :ZAR => '710',
50
+ :ZMK => '894', :ZWD => '716'
51
+ }
52
+
53
+ # login: merchant number
54
+ # password: referrer url (for authorize authentication)
55
+ def initialize(options = {})
56
+ requires!(options, :login, :password)
57
+ @options = options
58
+ super
59
+ end
60
+
61
+ def authorize(money, credit_card_or_reference, options = {})
62
+ post = {}
63
+
64
+ add_amount(post, money, options)
65
+ add_invoice(post, options)
66
+ add_creditcard_or_reference(post, credit_card_or_reference)
67
+ add_instant_capture(post, false)
68
+
69
+ commit(:authorize, post)
70
+ end
71
+
72
+ def purchase(money, credit_card_or_reference, options = {})
73
+ post = {}
74
+
75
+ add_amount(post, money, options)
76
+ add_creditcard_or_reference(post, credit_card_or_reference)
77
+ add_invoice(post, options)
78
+ add_instant_capture(post, true)
79
+
80
+ commit(:authorize, post)
81
+ end
82
+
83
+ def capture(money, authorization, options = {})
84
+ post = {}
85
+
86
+ add_reference(post, authorization)
87
+ add_amount_without_currency(post, money)
88
+
89
+ commit(:capture, post)
90
+ end
91
+
92
+ def void(identification, options = {})
93
+ post = {}
94
+
95
+ add_reference(post, identification)
96
+
97
+ commit(:void, post)
98
+ end
99
+
100
+ def refund(money, identification, options = {})
101
+ post = {}
102
+
103
+ add_amount_without_currency(post, money)
104
+ add_reference(post, identification)
105
+
106
+ commit(:credit, post)
107
+ end
108
+
109
+ def credit(money, identification, options = {})
110
+ deprecated CREDIT_DEPRECATION_MESSAGE
111
+ refund(money, identification, options)
112
+ end
113
+
114
+ private
115
+
116
+ def add_amount(post, money, options)
117
+ post[:amount] = amount(money)
118
+ post[:currency] = CURRENCY_CODES[(options[:currency] || currency(money)).to_sym]
119
+ end
120
+
121
+ def add_amount_without_currency(post, money)
122
+ post[:amount] = amount(money)
123
+ end
124
+
125
+ def add_reference(post, identification)
126
+ post[:transaction] = identification
127
+ end
128
+
129
+ def add_invoice(post, options)
130
+ post[:orderid] = format_order_number(options[:order_id])
131
+ end
132
+
133
+ def add_creditcard(post, credit_card)
134
+ post[:cardno] = credit_card.number
135
+ post[:cvc] = credit_card.verification_value
136
+ post[:expmonth] = credit_card.month
137
+ post[:expyear] = credit_card.year
138
+ end
139
+
140
+ def add_creditcard_or_reference(post, credit_card_or_reference)
141
+ if credit_card_or_reference.respond_to?(:number)
142
+ add_creditcard(post, credit_card_or_reference)
143
+ else
144
+ add_reference(post, credit_card_or_reference.to_s)
145
+ end
146
+ end
147
+
148
+ def add_instant_capture(post, option)
149
+ post[:instantcapture] = option ? 1 : 0
150
+ end
151
+
152
+ def commit(action, params)
153
+ response = send("do_#{action}", params)
154
+
155
+ if action == :authorize
156
+ Response.new response['accept'].to_i == 1,
157
+ response['errortext'],
158
+ response,
159
+ :test => test?,
160
+ :authorization => response['tid']
161
+ else
162
+ Response.new response['result'] == 'true',
163
+ messages(response['epay'], response['pbs']),
164
+ response,
165
+ :test => test?,
166
+ :authorization => params[:transaction]
167
+ end
168
+ end
169
+
170
+ def messages(epay, pbs = nil)
171
+ response = "ePay: #{epay}"
172
+ response << " PBS: #{pbs}" if pbs
173
+ return response
174
+ end
175
+
176
+ def soap_post(method, params)
177
+ data = xml_builder(params, method)
178
+ headers = make_headers(data, method)
179
+ REXML::Document.new(ssl_post('https://' + API_HOST + '/remote/payment.asmx', data, headers))
180
+ end
181
+
182
+ def do_authorize(params)
183
+ headers = {
184
+ 'Referer' => options[:password]
185
+ }
186
+
187
+ response = raw_ssl_request(:post, 'https://' + API_HOST + '/auth/default.aspx', authorize_post_data(params), headers)
188
+
189
+ # Authorize gives the response back by redirecting with the values in
190
+ # the URL query
191
+ query = CGI::parse(URI.parse(response['Location'].gsub(' ', '%20')).query)
192
+
193
+ result = {}
194
+ query.each_pair do |k,v|
195
+ result[k] = v.is_a?(Array) && v.size == 1 ? v[0] : v # make values like ['v'] into 'v'
196
+ end
197
+ result
198
+ end
199
+
200
+ def do_capture(params)
201
+ response = soap_post('capture', params)
202
+ {
203
+ 'result' => response.elements['//captureResponse/captureResult'].text,
204
+ 'pbs' => response.elements['//captureResponse/pbsResponse'].text,
205
+ 'epay' => response.elements['//captureResponse/epayresponse'].text
206
+ }
207
+ end
208
+
209
+ def do_credit(params)
210
+ response = soap_post('credit', params)
211
+ {
212
+ 'result' => response.elements['//creditResponse/creditResult'].text,
213
+ 'pbs' => response.elements['//creditResponse/pbsresponse'].text,
214
+ 'epay' => response.elements['//creditResponse/epayresponse'].text
215
+ }
216
+ end
217
+
218
+ def do_void(params)
219
+ response = soap_post('delete', params)
220
+ {
221
+ 'result' => response.elements['//deleteResponse/deleteResult'].text,
222
+ 'epay' => response.elements['//deleteResponse/epayresponse'].text
223
+ }
224
+ end
225
+
226
+ def make_headers(data, soap_call)
227
+ {
228
+ 'Content-Type' => 'text/xml; charset=utf-8',
229
+ 'Host' => API_HOST,
230
+ 'Content-Length' => data.size.to_s,
231
+ 'SOAPAction' => SOAP_URL + '/' + soap_call
232
+ }
233
+ end
234
+
235
+ def xml_builder(params, soap_call)
236
+ xml = Builder::XmlMarkup.new(:indent => 2)
237
+ xml.instruct!
238
+ xml.tag! 'soap:Envelope', { 'xmlns:xsi' => 'http://schemas.xmlsoap.org/soap/envelope/',
239
+ 'xmlns:xsd' => 'http://www.w3.org/2001/XMLSchema',
240
+ 'xmlns:soap' => 'http://schemas.xmlsoap.org/soap/envelope/' } do
241
+ xml.tag! 'soap:Body' do
242
+ xml.tag! soap_call, { 'xmlns' => SOAP_URL } do
243
+ xml.tag! 'merchantnumber', @options[:login]
244
+ xml.tag! 'transactionid', params[:transaction]
245
+ xml.tag! 'amount', params[:amount].to_s if soap_call != 'delete'
246
+ end
247
+ end
248
+ end
249
+ xml.target!
250
+ end
251
+
252
+ def authorize_post_data(params = {})
253
+ params[:language] = '2'
254
+ params[:cms] = 'activemerchant'
255
+ params[:accepturl] = 'https://ssl.ditonlinebetalingssystem.dk/auth/default.aspx?accept=1'
256
+ params[:declineurl] = 'https://ssl.ditonlinebetalingssystem.dk/auth/default.aspx?decline=1'
257
+ params[:merchantnumber] = @options[:login]
258
+
259
+ params.collect { |key, value| "#{key}=#{CGI.escape(value.to_s)}" }.join("&")
260
+ end
261
+
262
+ # Limited to 20 digits max
263
+ def format_order_number(number)
264
+ number.to_s.gsub(/[^\w_]/, '').rjust(4, "0")[0...20]
265
+ end
266
+ end
267
+ end
268
+ end
@@ -0,0 +1,231 @@
1
+ module ActiveMerchant #:nodoc:
2
+ module Billing #:nodoc:
3
+ class EwayManagedGateway < Gateway
4
+ TEST_URL = 'https://www.eway.com.au/gateway/ManagedPaymentService/test/managedCreditCardPayment.asmx'
5
+ LIVE_URL = 'https://www.eway.com.au/gateway/ManagedPaymentService/managedCreditCardPayment.asmx'
6
+
7
+ # The countries the gateway supports merchants from as 2 digit ISO country codes
8
+ self.supported_countries = ['AU']
9
+
10
+ # The card types supported by the payment gateway
11
+ self.supported_cardtypes = [:visa, :master]
12
+
13
+ self.default_currency = 'AUD'
14
+
15
+ #accepted money format
16
+ self.money_format = :cents
17
+
18
+ # The homepage URL of the gateway
19
+ self.homepage_url = 'http://www.eway.com.au/'
20
+
21
+ # The name of the gateway
22
+ self.display_name = 'eWay Managed Payments'
23
+
24
+ def initialize(options = {})
25
+ requires!(options, :login, :username, :password)
26
+ @options = options
27
+
28
+ # eWay returns 500 code for faults, which AM snaffles.
29
+ # So, we tell it to allow them.
30
+ @options[:ignore_http_status]=true
31
+ super
32
+ end
33
+
34
+ # add a new customer CC to your eway account and return unique ManagedCustomerID
35
+ # supports storing details required by eway see "add_creditcard" and "add_address"
36
+ def store(creditcard, options = {})
37
+ post = {}
38
+
39
+ # Handle our required fields
40
+ requires!(options, :billing_address)
41
+
42
+ # Handle eWay specific required fields.
43
+ billing_address = options[:billing_address]
44
+ eway_requires!(billing_address)
45
+
46
+ add_creditcard(post, creditcard)
47
+ add_address(post, billing_address)
48
+ add_misc_fields(post, billing_address)
49
+
50
+ commit("CreateCustomer", post)
51
+ end
52
+
53
+ def update(billing_id, creditcard, options={})
54
+ post = {}
55
+
56
+ # Handle our required fields
57
+ requires!(options, :billing_address)
58
+
59
+ # Handle eWay specific required fields.
60
+ billing_address = options[:billing_address]
61
+ eway_requires!(billing_address)
62
+
63
+ post[:managedCustomerID]=billing_id
64
+ add_creditcard(post, creditcard)
65
+ add_address(post, billing_address)
66
+ add_misc_fields(post, billing_address)
67
+
68
+ commit("UpdateCustomer", post)
69
+ end
70
+
71
+ #process payment for given amount from stored CC "ManagedCustomerID = billing_id"
72
+ def purchase(money, billing_id, options={})
73
+ post = {}
74
+ post[:managedCustomerID] = billing_id.to_s
75
+ post[:amount]=money
76
+
77
+ commit("ProcessPayment", post)
78
+ end
79
+
80
+ # TODO: eWay API also provides QueryCustomer
81
+ # TODO: eWay API also provides QueryPayment
82
+
83
+ def test?
84
+ @options[:test] || Base.gateway_mode == :test
85
+ end
86
+ private
87
+
88
+ def eway_requires!(hash)
89
+ raise ArgumentError.new("Missing eWay required parameter in `billing_address`: title") unless hash.has_key?(:title)
90
+ raise ArgumentError.new("Missing eWay required parameter in `billing_address`: country") unless hash.has_key?(:country)
91
+ end
92
+
93
+ def add_address(post, address)
94
+ post[:Address] = address[:address1].to_s
95
+ post[:Phone] = address[:phone].to_s
96
+ post[:PostCode] = address[:zip].to_s
97
+ post[:Suburb] = address[:city].to_s
98
+ post[:Country] = address[:country].to_s.downcase
99
+ post[:State] = address[:state].to_s
100
+ post[:Mobile] = address[:mobile].to_s
101
+ post[:Fax] = address[:fax].to_s
102
+ end
103
+
104
+ def add_misc_fields(post, options)
105
+ post[:CustomerRef]=options[:customer_ref].to_s
106
+ post[:Title]=options[:title]
107
+ post[:Company]=options[:company]
108
+ post[:JobDesc]=options[:job_desc]
109
+ post[:Email]=options[:email]
110
+ post[:URL]=options[:url]
111
+ end
112
+
113
+ # add credit card details to be stored by eway. NOTE eway requires "title" field
114
+ def add_creditcard(post, creditcard)
115
+ post[:CCNumber] = creditcard.number
116
+ post[:CCExpiryMonth] = sprintf("%.2i", creditcard.month)
117
+ post[:CCExpiryYear] = sprintf("%.4i", creditcard.year)[-2..-1]
118
+ post[:CCNameOnCard] = creditcard.name
119
+ post[:FirstName] = creditcard.first_name
120
+ post[:LastName] = creditcard.last_name
121
+ end
122
+
123
+ def parse(body)
124
+ reply = {}
125
+ xml = REXML::Document.new(body)
126
+ if root = REXML::XPath.first(xml, "//soap:Fault") then
127
+ reply=parse_fault(root)
128
+ else
129
+ if root = REXML::XPath.first(xml, '//ProcessPaymentResponse/ewayResponse') then
130
+ # Successful payment
131
+ reply=parse_purchase(root)
132
+ else
133
+ if root = REXML::XPath.first(xml, '//CreateCustomerResult') then
134
+ reply[:message]='OK'
135
+ reply[:CreateCustomerResult]=root.text
136
+ reply[:success]=true
137
+ else
138
+ if root = REXML::XPath.first(xml, '//UpdateCustomerResult') then
139
+ if root.text.downcase == 'true' then
140
+ reply[:message]='OK'
141
+ reply[:success]=true
142
+ else
143
+ # ERROR: This state should never occur. If there is a problem,
144
+ # a soap:Fault will be returned. The presence of this
145
+ # element always means a success.
146
+ raise StandardError, "Unexpected \"false\" in UpdateCustomerResult"
147
+ end
148
+ else
149
+ # ERROR: This state should never occur currently. We have handled
150
+ # responses for all the methods which we support.
151
+ raise StandardError, "Unexpected response"
152
+ end
153
+ end
154
+ end
155
+ end
156
+ return reply
157
+ end
158
+
159
+ def parse_fault(node)
160
+ reply={}
161
+ reply[:message]=REXML::XPath.first(node, '//soap:Reason/soap:Text').text
162
+ reply[:success]=false
163
+ reply
164
+ end
165
+
166
+ def parse_purchase(node)
167
+ reply={}
168
+ reply[:message]=REXML::XPath.first(node, '//ewayTrxnError').text
169
+ reply[:success]=(REXML::XPath.first(node, '//ewayTrxnStatus').text == 'True')
170
+ reply[:auth_code]=REXML::XPath.first(node, '//ewayAuthCode').text
171
+ reply
172
+ end
173
+
174
+ def commit(action, post)
175
+ raw = begin
176
+ ssl_post(test? ? TEST_URL : LIVE_URL, soap_request(post, action), 'Content-Type' => 'application/soap+xml; charset=utf-8')
177
+ rescue ResponseError => e
178
+ e.response.body
179
+ end
180
+ response = parse(raw)
181
+
182
+ EwayResponse.new(response[:success], response[:message], response,
183
+ :test => test?,
184
+ :authorization => response[:auth_code]
185
+ )
186
+ end
187
+
188
+ # Where we build the full SOAP 1.2 request using builder
189
+ def soap_request(arguments, action)
190
+ # eWay demands all fields be sent, but contain an empty string if blank
191
+ post=default_fields.merge(arguments)
192
+
193
+ xml = Builder::XmlMarkup.new :indent => 2
194
+ xml.instruct!
195
+ xml.tag! 'soap12:Envelope', {'xmlns:xsi' => 'http://www.w3.org/2001/XMLSchema-instance', 'xmlns:xsd' => 'http://www.w3.org/2001/XMLSchema', 'xmlns:soap12' => 'http://www.w3.org/2003/05/soap-envelope'} do
196
+ xml.tag! 'soap12:Header' do
197
+ xml.tag! 'eWAYHeader', {'xmlns' => 'https://www.eway.com.au/gateway/managedpayment'} do
198
+ xml.tag! 'eWAYCustomerID', @options[:login]
199
+ xml.tag! 'Username', @options[:username]
200
+ xml.tag! 'Password', @options[:password]
201
+ end
202
+ end
203
+ xml.tag! 'soap12:Body' do |x|
204
+ x.tag! "#{action}", {'xmlns' => 'https://www.eway.com.au/gateway/managedpayment'} do |y|
205
+ post.each do |key, value|
206
+ y.tag! "#{key}", "#{value}"
207
+ end
208
+ end
209
+ end
210
+ end
211
+ xml.target!
212
+ end
213
+
214
+ def default_fields
215
+ hash={}
216
+ %w( CustomerRef Title FirstName LastName Company JobDesc Email Address Suburb State PostCode Country Phone Mobile Fax URL Comments CCNumber CCNameOnCard CCExpiryMonth CCExpiryYear ).each do |field|
217
+ hash[field.to_sym]=''
218
+ end
219
+ return hash
220
+ end
221
+
222
+ class EwayResponse < Response
223
+ # add a method to response so we can easily get the eway token "ManagedCustomerID"
224
+ def token
225
+ @params['CreateCustomerResult']
226
+ end
227
+ end
228
+
229
+ end
230
+ end
231
+ end