activemerchant 1.0.3 → 1.1.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 (30) hide show
  1. data.tar.gz.sig +0 -0
  2. data/CHANGELOG +18 -0
  3. data/lib/active_merchant.rb +2 -0
  4. data/lib/active_merchant/billing/credit_card.rb +25 -113
  5. data/lib/active_merchant/billing/credit_card_formatting.rb +18 -0
  6. data/lib/active_merchant/billing/credit_card_methods.rb +83 -0
  7. data/lib/active_merchant/billing/gateway.rb +1 -0
  8. data/lib/active_merchant/billing/gateways.rb +2 -1
  9. data/lib/active_merchant/billing/gateways/data_cash.rb +475 -0
  10. data/lib/active_merchant/billing/gateways/linkpoint.rb +9 -24
  11. data/lib/active_merchant/billing/gateways/moneris.rb +1 -1
  12. data/lib/active_merchant/billing/gateways/payflow.rb +14 -0
  13. data/lib/active_merchant/billing/gateways/payflow/payflow_common_api.rb +1 -14
  14. data/lib/active_merchant/billing/gateways/paypal.rb +11 -3
  15. data/lib/active_merchant/billing/gateways/paypal/paypal_common_api.rb +47 -22
  16. data/lib/active_merchant/billing/gateways/paypal_express.rb +3 -3
  17. data/lib/active_merchant/billing/gateways/psigate.rb +4 -19
  18. data/lib/active_merchant/billing/gateways/usa_epay.rb +5 -6
  19. data/lib/active_merchant/billing/integrations.rb +1 -0
  20. data/lib/active_merchant/billing/integrations/helper.rb +13 -6
  21. data/lib/active_merchant/billing/integrations/notification.rb +2 -1
  22. data/lib/active_merchant/billing/integrations/paypal/helper.rb +2 -0
  23. data/lib/active_merchant/billing/integrations/two_checkout.rb +18 -0
  24. data/lib/active_merchant/billing/integrations/two_checkout/helper.rb +59 -0
  25. data/lib/active_merchant/billing/integrations/two_checkout/notification.rb +114 -0
  26. data/lib/active_merchant/lib/posts_data.rb +18 -9
  27. data/lib/active_merchant/lib/validateable.rb +2 -2
  28. data/lib/certs/cacert.pem +7815 -0
  29. metadata +11 -2
  30. metadata.gz.sig +0 -0
@@ -127,6 +127,9 @@ module ActiveMerchant #:nodoc:
127
127
 
128
128
  TEST_URL = 'https://staging.linkpt.net:1129/'
129
129
  LIVE_URL = 'https://secure.linkpt.net:1129/'
130
+
131
+ # We don't have the certificate to verify LinkPoint
132
+ self.ssl_strict = false
130
133
 
131
134
  # @options = {
132
135
  # :store_number => options[:login],
@@ -136,12 +139,11 @@ module ActiveMerchant #:nodoc:
136
139
  requires!(options, :login)
137
140
 
138
141
  @options = {
139
- :result => 'LIVE'
142
+ :result => 'LIVE',
143
+ :pem => LinkpointGateway.pem_file
140
144
  }.update(options)
141
145
 
142
- @pem = @options[:pem] || LinkpointGateway.pem_file
143
-
144
- raise ArgumentError, "You need to pass in your pem file using the :pem parameter or set it globally using ActiveMerchant::Billing::LinkpointGateway.pem_file = File.read( File.dirname(__FILE__) + '/../mycert.pem' ) or similar" if @pem.nil?
146
+ raise ArgumentError, "You need to pass in your pem file using the :pem parameter or set it globally using ActiveMerchant::Billing::LinkpointGateway.pem_file = File.read( File.dirname(__FILE__) + '/../mycert.pem' ) or similar" if @options[:pem].blank?
145
147
  end
146
148
 
147
149
  # Send a purchase request with periodic options
@@ -245,16 +247,16 @@ module ActiveMerchant #:nodoc:
245
247
  end
246
248
 
247
249
  private
248
-
249
250
  # Commit the transaction by posting the XML file to the LinkPoint server
250
251
  def commit(money, creditcard, options = {})
251
252
  parameters = parameters(money, creditcard, options)
253
+ url = test? ? TEST_URL : LIVE_URL
252
254
 
253
255
  if creditcard and result = test_result_from_cc_number(parameters[:creditcard][:cardnumber])
254
256
  return result
255
257
  end
256
258
 
257
- data = ssl_post post_data(parameters)
259
+ data = ssl_post(url, post_data(parameters))
258
260
 
259
261
  @response = parse(data)
260
262
 
@@ -288,7 +290,7 @@ module ActiveMerchant #:nodoc:
288
290
 
289
291
  return xml.to_s
290
292
  end
291
-
293
+
292
294
  # Set up the parameters hash just once so we don't have to do it
293
295
  # for every action.
294
296
  def parameters(money, creditcard, options = {})
@@ -408,23 +410,6 @@ module ActiveMerchant #:nodoc:
408
410
 
409
411
  response
410
412
  end
411
-
412
- # Redefine ssl_post to use our PEM file
413
- def ssl_post(data)
414
-
415
- raise "PEM file invalid or missing!" unless @pem =~ %r{RSA.*CERTIFICATE}m
416
-
417
- uri = URI.parse(test? ? TEST_URL : LIVE_URL)
418
-
419
- http = Net::HTTP.new(uri.host, uri.port)
420
-
421
- http.verify_mode = OpenSSL::SSL::VERIFY_NONE unless @ssl_strict
422
- http.use_ssl = true
423
- http.cert = OpenSSL::X509::Certificate.new(@pem)
424
- http.key = OpenSSL::PKey::RSA.new(@pem)
425
-
426
- http.post(uri.path, data).body
427
- end
428
413
 
429
414
  # Make a ruby type out of the response string
430
415
  def normalize(field)
@@ -59,7 +59,7 @@ module ActiveMerchant #:nodoc:
59
59
 
60
60
  # Moneris requires both the order_id and the transaction number of
61
61
  # the original authorization. To maintain the same interface as the other
62
- # gateways the two numbers are concatenated together with an _ separator as
62
+ # gateways the two numbers are concatenated together with a ; separator as
63
63
  # the authorization number returned by authorization
64
64
  def capture(money, authorization, options = {})
65
65
  txn_number, order_id = authorization.split(';')
@@ -48,6 +48,8 @@ module ActiveMerchant #:nodoc:
48
48
  add_address(xml, 'ShipTo', shipping_address, options)
49
49
 
50
50
  xml.tag! 'TotalAmt', amount(money), 'Currency' => currency(money)
51
+
52
+
51
53
  end
52
54
 
53
55
  xml.tag! 'Tender' do
@@ -65,6 +67,11 @@ module ActiveMerchant #:nodoc:
65
67
  xml.tag! 'ExpDate', expdate(credit_card)
66
68
  xml.tag! 'NameOnCard', credit_card.name
67
69
  xml.tag! 'CVNum', credit_card.verification_value if credit_card.verification_value?
70
+
71
+ if [ 'switch', 'solo' ].include?(credit_card.type.to_s)
72
+ xml.tag!('ExtData', 'Name' => 'CardStart', 'Value' => startdate(credit_card)) unless credit_card.start_month.blank? || credit_card.start_year.blank?
73
+ xml.tag!('ExtData', 'Name' => 'CardIssue', 'Value' => credit_card.issue_number) unless credit_card.issue_number.blank?
74
+ end
68
75
  end
69
76
  end
70
77
 
@@ -75,6 +82,13 @@ module ActiveMerchant #:nodoc:
75
82
  "#{year}#{month}"
76
83
  end
77
84
 
85
+ def startdate(creditcard)
86
+ year = format(creditcard.start_year, :two_digits)
87
+ month = format(creditcard.start_month, :two_digits)
88
+
89
+ "#{month}#{year}"
90
+ end
91
+
78
92
  def build_response(success, message, response, options = {})
79
93
  Response.new(success, message, response, options)
80
94
  end
@@ -111,20 +111,7 @@ module ActiveMerchant #:nodoc:
111
111
  end
112
112
  end
113
113
  end
114
-
115
- def ssl_post(url, data, headers)
116
- uri = URI.parse(url)
117
-
118
- http = Net::HTTP.new(uri.host, uri.port)
119
-
120
- http.verify_mode = OpenSSL::SSL::VERIFY_PEER
121
- http.verify_depth = 5
122
- http.use_ssl = true
123
- http.ca_file = File.dirname(__FILE__) + '/f73e89fd.0'
124
-
125
- http.post(uri.path, data, headers).body
126
- end
127
-
114
+
128
115
  def parse(data)
129
116
  response = {}
130
117
  xml = REXML::Document.new(data)
@@ -40,7 +40,7 @@ module ActiveMerchant #:nodoc:
40
40
  xml = Builder::XmlMarkup.new :indent => 2
41
41
  xml.tag! 'DoDirectPaymentReq', 'xmlns' => PAYPAL_NAMESPACE do
42
42
  xml.tag! 'DoDirectPaymentRequest', 'xmlns:n2' => EBAY_NAMESPACE do
43
- xml.tag! 'n2:Version', '2.0'
43
+ xml.tag! 'n2:Version', API_VERSION
44
44
  xml.tag! 'n2:DoDirectPaymentRequestDetails' do
45
45
  xml.tag! 'n2:PaymentAction', action
46
46
  xml.tag! 'n2:PaymentDetails' do
@@ -64,10 +64,16 @@ module ActiveMerchant #:nodoc:
64
64
  xml.tag! 'n2:CreditCard' do
65
65
  xml.tag! 'n2:CreditCardType', credit_card_type(credit_card.type)
66
66
  xml.tag! 'n2:CreditCardNumber', credit_card.number
67
- xml.tag! 'n2:ExpMonth', sprintf("%.2i", credit_card.month)
68
- xml.tag! 'n2:ExpYear', sprintf("%.4i", credit_card.year)
67
+ xml.tag! 'n2:ExpMonth', format(credit_card.month, :two_digits)
68
+ xml.tag! 'n2:ExpYear', format(credit_card.year, :four_digits)
69
69
  xml.tag! 'n2:CVV2', credit_card.verification_value
70
70
 
71
+ if [ 'switch', 'solo' ].include?(credit_card.type.to_s)
72
+ xml.tag! 'n2:StartMonth', format(credit_card.start_month, :two_digits) unless credit_card.start_month.blank?
73
+ xml.tag! 'n2:StartYear', format(credit_card.start_year, :four_digits) unless credit_card.start_year.blank?
74
+ xml.tag! 'n2:IssueNumber', format(credit_card.issue_number, :two_digits) unless credit_card.issue_number.blank?
75
+ end
76
+
71
77
  xml.tag! 'n2:CardOwner' do
72
78
  xml.tag! 'n2:PayerName' do
73
79
  xml.tag! 'n2:FirstName', credit_card.first_name
@@ -86,6 +92,8 @@ module ActiveMerchant #:nodoc:
86
92
  when 'master' then 'MasterCard'
87
93
  when 'discover' then 'Discover'
88
94
  when 'american_express' then 'Amex'
95
+ when 'switch' then 'Switch'
96
+ when 'solo' then 'Solo'
89
97
  end
90
98
  end
91
99
 
@@ -7,6 +7,7 @@ module ActiveMerchant #:nodoc:
7
7
  base.cattr_accessor :pem_file
8
8
  end
9
9
 
10
+ API_VERSION = '2.0'
10
11
  TEST_URL = 'https://api.sandbox.paypal.com/2.0/'
11
12
  LIVE_URL = 'https://api-aa.paypal.com/2.0/'
12
13
 
@@ -21,6 +22,17 @@ module ActiveMerchant #:nodoc:
21
22
  'xmlns:n1' => EBAY_NAMESPACE,
22
23
  'env:mustUnderstand' => '0'
23
24
  }
25
+
26
+ AUSTRALIAN_STATES = {
27
+ 'ACT' => 'Australian Capital Territory',
28
+ 'NSW' => 'New South Wales',
29
+ 'NT' => 'Northern Territory',
30
+ 'QLD' => 'Queensland',
31
+ 'SA' => 'South Australia',
32
+ 'TAS' => 'Tasmania',
33
+ 'VIC' => 'Victoria',
34
+ 'WA' => 'Western Australia'
35
+ }
24
36
 
25
37
  # <tt>:pem</tt> The text of your PayPal PEM file. Note
26
38
  # this is not the path to file, but its
@@ -42,6 +54,10 @@ module ActiveMerchant #:nodoc:
42
54
  @options[:test] || Base.gateway_mode == :test
43
55
  end
44
56
 
57
+ def reauthorize(money, authorization, options = {})
58
+ commit 'DoReauthorization', build_reauthorize_request(money, authorization, options)
59
+ end
60
+
45
61
  def capture(money, authorization, options = {})
46
62
  commit 'DoCapture', build_capture_request(money, authorization, options)
47
63
  end
@@ -69,13 +85,26 @@ module ActiveMerchant #:nodoc:
69
85
  end
70
86
 
71
87
  private
88
+ def build_reauthorize_request(money, authorization, options)
89
+ xml = Builder::XmlMarkup.new :indent => 2
90
+
91
+ xml.tag! 'DoReauthorizationReq', 'xmlns' => PAYPAL_NAMESPACE do
92
+ xml.tag! 'DoReauthorizationRequest', 'xmlns:n2' => EBAY_NAMESPACE do
93
+ xml.tag! 'n2:Version', API_VERSION
94
+ xml.tag! 'AuthorizationID', authorization
95
+ xml.tag! 'Amount', amount(money), 'currencyID' => currency(money)
96
+ end
97
+ end
98
+
99
+ xml.target!
100
+ end
72
101
 
73
102
  def build_capture_request(money, authorization, options)
74
103
  xml = Builder::XmlMarkup.new :indent => 2
75
104
 
76
105
  xml.tag! 'DoCaptureReq', 'xmlns' => PAYPAL_NAMESPACE do
77
106
  xml.tag! 'DoCaptureRequest', 'xmlns:n2' => EBAY_NAMESPACE do
78
- xml.tag! 'n2:Version', '2.0'
107
+ xml.tag! 'n2:Version', API_VERSION
79
108
  xml.tag! 'AuthorizationID', authorization
80
109
  xml.tag! 'Amount', amount(money), 'currencyID' => currency(money)
81
110
  xml.tag! 'CompleteType', 'Complete'
@@ -91,7 +120,7 @@ module ActiveMerchant #:nodoc:
91
120
 
92
121
  xml.tag! 'RefundTransactionReq', 'xmlns' => PAYPAL_NAMESPACE do
93
122
  xml.tag! 'RefundTransactionRequest', 'xmlns:n2' => EBAY_NAMESPACE do
94
- xml.tag! 'n2:Version', '2.0'
123
+ xml.tag! 'n2:Version', API_VERSION
95
124
  xml.tag! 'TransactionID', identification
96
125
  xml.tag! 'Amount', amount(money), 'currencyID' => currency(money)
97
126
  xml.tag! 'RefundType', 'Partial'
@@ -107,7 +136,7 @@ module ActiveMerchant #:nodoc:
107
136
 
108
137
  xml.tag! 'DoVoidReq', 'xmlns' => PAYPAL_NAMESPACE do
109
138
  xml.tag! 'DoVoidRequest', 'xmlns:n2' => EBAY_NAMESPACE do
110
- xml.tag! 'n2:Version', '2.0'
139
+ xml.tag! 'n2:Version', API_VERSION
111
140
  xml.tag! 'AuthorizationID', authorization
112
141
  xml.tag! 'Note', options[:description]
113
142
  end
@@ -124,7 +153,7 @@ module ActiveMerchant #:nodoc:
124
153
 
125
154
  xml.tag! 'MassPayReq', 'xmlns' => PAYPAL_NAMESPACE do
126
155
  xml.tag! 'MassPayRequest', 'xmlns:n2' => EBAY_NAMESPACE do
127
- xml.tag! 'n2:Version', '2.0'
156
+ xml.tag! 'n2:Version', API_VERSION
128
157
  xml.tag! 'EmailSubject', default_options[:subject] if default_options[:subject]
129
158
  recipients.each do |money, recipient, options|
130
159
  options ||= default_options
@@ -132,6 +161,7 @@ module ActiveMerchant #:nodoc:
132
161
  xml.tag! 'ReceiverEmail', recipient
133
162
  xml.tag! 'Amount', amount(money), 'currencyID' => currency(money)
134
163
  xml.tag! 'Note', options[:note] if options[:note]
164
+ xml.tag! 'UniqueId', options[:unique_id] if options[:unique_id]
135
165
  end
136
166
  end
137
167
  end
@@ -139,21 +169,7 @@ module ActiveMerchant #:nodoc:
139
169
 
140
170
  xml.target!
141
171
  end
142
-
143
- def ssl_post(data)
144
- uri = URI.parse(test? ? TEST_URL : LIVE_URL)
145
-
146
- http = Net::HTTP.new(uri.host, uri.port)
147
-
148
- http.verify_mode = OpenSSL::SSL::VERIFY_PEER
149
- http.use_ssl = true
150
- http.cert = OpenSSL::X509::Certificate.new(@options[:pem])
151
- http.key = OpenSSL::PKey::RSA.new(@options[:pem])
152
- http.ca_file = File.dirname(__FILE__) + '/api_cert_chain.crt'
153
-
154
- http.post(uri.path, data).body
155
- end
156
-
172
+
157
173
  def parse(action, xml)
158
174
  response = {}
159
175
  xml = REXML::Document.new(xml)
@@ -229,19 +245,28 @@ module ActiveMerchant #:nodoc:
229
245
  xml.tag! 'n2:Street1', address[:address1]
230
246
  xml.tag! 'n2:Street2', address[:address2]
231
247
  xml.tag! 'n2:CityName', address[:city]
232
- xml.tag! 'n2:StateOrProvince', address[:state]
248
+ xml.tag! 'n2:StateOrProvince', lookup_state(address)
233
249
  xml.tag! 'n2:Country', address[:country]
234
250
  xml.tag! 'n2:PostalCode', address[:zip]
235
251
  xml.tag! 'n2:Phone', address[:phone]
236
252
  end
237
253
  end
254
+
255
+ def lookup_state(address)
256
+ state = if address[:country].to_s.upcase == 'AU' || address[:country] == 'Australia'
257
+ AUSTRALIAN_STATES[address[:state]] || address[:state]
258
+ else
259
+ address[:state]
260
+ end
261
+ end
238
262
 
239
263
  def currency(money)
240
264
  money.respond_to?(:currency) ? money.currency : 'USD'
241
265
  end
242
266
 
243
267
  def commit(action, request)
244
- data = ssl_post build_request(request)
268
+ url = test? ? TEST_URL : LIVE_URL
269
+ data = ssl_post(url, build_request(request))
245
270
 
246
271
  @response = parse(action, data)
247
272
 
@@ -250,7 +275,7 @@ module ActiveMerchant #:nodoc:
250
275
 
251
276
  build_response(success, message, @response,
252
277
  :test => test?,
253
- :authorization => @response[:transaction_id]
278
+ :authorization => @response[:transaction_id] || @response[:authorization_id] # latter one is from reauthorization
254
279
  )
255
280
  end
256
281
  end
@@ -50,7 +50,7 @@ module ActiveMerchant #:nodoc:
50
50
  xml = Builder::XmlMarkup.new :indent => 2
51
51
  xml.tag! 'GetExpressCheckoutDetailsReq', 'xmlns' => PAYPAL_NAMESPACE do
52
52
  xml.tag! 'GetExpressCheckoutDetailsRequest', 'xmlns:n2' => EBAY_NAMESPACE do
53
- xml.tag! 'n2:Version', '2.0'
53
+ xml.tag! 'n2:Version', API_VERSION
54
54
  xml.tag! 'Token', token
55
55
  end
56
56
  end
@@ -62,7 +62,7 @@ module ActiveMerchant #:nodoc:
62
62
  xml = Builder::XmlMarkup.new :indent => 2
63
63
  xml.tag! 'DoExpressCheckoutPaymentReq', 'xmlns' => PAYPAL_NAMESPACE do
64
64
  xml.tag! 'DoExpressCheckoutPaymentRequest', 'xmlns:n2' => EBAY_NAMESPACE do
65
- xml.tag! 'n2:Version', '2.0'
65
+ xml.tag! 'n2:Version', API_VERSION
66
66
  xml.tag! 'n2:DoExpressCheckoutPaymentRequestDetails' do
67
67
  xml.tag! 'n2:PaymentAction', action
68
68
  xml.tag! 'n2:Token', options[:token]
@@ -82,7 +82,7 @@ module ActiveMerchant #:nodoc:
82
82
  xml = Builder::XmlMarkup.new :indent => 2
83
83
  xml.tag! 'SetExpressCheckoutReq', 'xmlns' => PAYPAL_NAMESPACE do
84
84
  xml.tag! 'SetExpressCheckoutRequest', 'xmlns:n2' => EBAY_NAMESPACE do
85
- xml.tag! 'n2:Version', '2.0'
85
+ xml.tag! 'n2:Version', API_VERSION
86
86
  xml.tag! 'n2:SetExpressCheckoutRequestDetails' do
87
87
  xml.tag! 'n2:PaymentAction', action
88
88
  xml.tag! 'n2:OrderTotal', amount(money), 'currencyID' => currency(money)
@@ -100,7 +100,9 @@ module ActiveMerchant #:nodoc:
100
100
  return result
101
101
  end
102
102
 
103
- data = ssl_post post_data(parameters)
103
+ url = test? ? TEST_URL : LIVE_URL
104
+
105
+ data = ssl_post(url, post_data(parameters))
104
106
  @response = parse(data)
105
107
  success = (@response[:approved] == "APPROVED")
106
108
  message = message_form(@response)
@@ -159,12 +161,9 @@ module ActiveMerchant #:nodoc:
159
161
  xml.to_s
160
162
  end
161
163
 
162
-
163
164
  # Set up the parameters hash just once so we don't have to do it
164
165
  # for every action.
165
- def parameters(money, creditcard, options = {})
166
-
167
-
166
+ def parameters(money, creditcard, options = {})
168
167
  params = {
169
168
  # General order paramters
170
169
  :StoreID => @options[:store_id],
@@ -227,20 +226,6 @@ module ActiveMerchant #:nodoc:
227
226
  return params
228
227
  end
229
228
 
230
- # Redefine ssl_post to use correct url depending on test mode
231
- def ssl_post(data)
232
- # In my case I only want the LIVE_URL to be used when in prodcution mode
233
- # because Psigate charges for all transactions
234
- uri = URI.parse(test? ? TEST_URL : LIVE_URL )
235
- http = Net::HTTP.new(uri.host, uri.port)
236
-
237
- http.verify_mode = OpenSSL::SSL::VERIFY_NONE unless @ssl_strict
238
- http.use_ssl = true
239
-
240
- http.post(uri.path, data).body
241
- end
242
-
243
-
244
229
  def message_form(response)
245
230
  if response[:approved] == "APPROVED"
246
231
  return 'Success'
@@ -3,6 +3,7 @@ module ActiveMerchant #:nodoc:
3
3
 
4
4
  class UsaEpayGateway < Gateway
5
5
  GATEWAY_URL = 'https://www.usaepay.com/gate.php'
6
+ POST_HEADERS = { 'Content-Type' => 'application/x-www-form-urlencoded' }
6
7
 
7
8
  attr_reader :url
8
9
  attr_reader :response
@@ -46,10 +47,10 @@ module ActiveMerchant #:nodoc:
46
47
  private
47
48
 
48
49
  def expdate(creditcard)
49
- year = sprintf("%.4i", creditcard.year)
50
- month = sprintf("%.2i", creditcard.month)
50
+ year = format(creditcard.year, :two_digits)
51
+ month = format(creditcard.month, :two_digits)
51
52
 
52
- "#{year[-2..-1]}#{month}"
53
+ "#{month}#{year}"
53
54
  end
54
55
 
55
56
  def add_customer_data(post, options)
@@ -151,9 +152,7 @@ module ActiveMerchant #:nodoc:
151
152
  return result
152
153
  end
153
154
 
154
- data = ssl_post GATEWAY_URL,
155
- post_data(action, parameters),
156
- { 'Content-Type' => 'application/x-www-form-urlencoded' }
155
+ data = ssl_post(GATEWAY_URL, post_data(action, parameters), POST_HEADERS)
157
156
 
158
157
  @response = parse(data)
159
158
  success = @response[:status] == 'Approved'
@@ -5,6 +5,7 @@ require 'active_merchant/billing/integrations/chronopay'
5
5
  require 'active_merchant/billing/integrations/paypal'
6
6
  require 'active_merchant/billing/integrations/nochex'
7
7
  require 'active_merchant/billing/integrations/gestpay'
8
+ require 'active_merchant/billing/integrations/two_checkout'
8
9
 
9
10
  # make the bogus gateway be classified correctly by the inflector
10
11
  Inflector.inflections do |inflect|