google4r 0.0.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 (39) hide show
  1. data/CHANGES +5 -0
  2. data/LICENSE +22 -0
  3. data/README +75 -0
  4. data/lib/google4r/checkout.rb +36 -0
  5. data/lib/google4r/checkout/commands.rb +267 -0
  6. data/lib/google4r/checkout/frontend.rb +100 -0
  7. data/lib/google4r/checkout/notifications.rb +533 -0
  8. data/lib/google4r/checkout/shared.rb +501 -0
  9. data/lib/google4r/checkout/xml_generation.rb +271 -0
  10. data/lib/google4r/maps.rb +174 -0
  11. data/test/checkout/integration/checkout_command_test.rb +103 -0
  12. data/test/checkout/unit/address_test.rb +131 -0
  13. data/test/checkout/unit/area_test.rb +41 -0
  14. data/test/checkout/unit/checkout_command_test.rb +112 -0
  15. data/test/checkout/unit/checkout_command_xml_generator_test.rb +187 -0
  16. data/test/checkout/unit/command_test.rb +126 -0
  17. data/test/checkout/unit/flat_rate_shipping_test.rb +114 -0
  18. data/test/checkout/unit/frontend_test.rb +63 -0
  19. data/test/checkout/unit/item_test.rb +159 -0
  20. data/test/checkout/unit/marketing_preferences_test.rb +65 -0
  21. data/test/checkout/unit/merchant_code_test.rb +122 -0
  22. data/test/checkout/unit/new_order_notification_test.rb +115 -0
  23. data/test/checkout/unit/notification_acknowledgement_test.rb +43 -0
  24. data/test/checkout/unit/notification_handler_test.rb +93 -0
  25. data/test/checkout/unit/order_adjustment_test.rb +95 -0
  26. data/test/checkout/unit/order_state_change_notification_test.rb +159 -0
  27. data/test/checkout/unit/pickup_shipping_test.rb +70 -0
  28. data/test/checkout/unit/private_data_parser_test.rb +68 -0
  29. data/test/checkout/unit/shipping_adjustment_test.rb +100 -0
  30. data/test/checkout/unit/shipping_method_test.rb +41 -0
  31. data/test/checkout/unit/shopping_cart_test.rb +146 -0
  32. data/test/checkout/unit/tax_rule_test.rb +65 -0
  33. data/test/checkout/unit/tax_table_test.rb +82 -0
  34. data/test/checkout/unit/us_country_area_test.rb +76 -0
  35. data/test/checkout/unit/us_state_area_test.rb +70 -0
  36. data/test/checkout/unit/us_zip_area_test.rb +66 -0
  37. data/test/maps/geocoder_test.rb +143 -0
  38. data/var/cacert.pem +7815 -0
  39. metadata +100 -0
data/CHANGES ADDED
@@ -0,0 +1,5 @@
1
+ = google4r Changelog
2
+
3
+ == 0.0.1 (2007-02-17)
4
+
5
+ * initial release, be prepared for some API changes that move the API closer to the XML API
data/LICENSE ADDED
@@ -0,0 +1,22 @@
1
+ Unless noted otherwise, the files of this projects are licensed under a MIT
2
+ style license:
3
+
4
+ Copyright (c) 2006 Manuel Holtgrewe
5
+
6
+ Permission is hereby granted, free of charge, to any person obtaining a copy
7
+ of this software and associated documentation files (the "Software"), to
8
+ deal in the Software without restriction, including without limitation the
9
+ rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
10
+ sell copies of the Software, and to permit persons to whom the Software is
11
+ furnished to do so, subject to the following conditions:
12
+
13
+ The above copyright notice and this permission notice shall be included in
14
+ all copies or substantial portions of the Software.
15
+
16
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
21
+ FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
22
+ IN THE SOFTWARE.
data/README ADDED
@@ -0,0 +1,75 @@
1
+ = google4r
2
+
3
+ google4r is a collection of libraries that allow you to access some of Google's web services using Ruby. At the moment, there are wrappers for
4
+
5
+ * Google Maps
6
+ * Google Checkout.
7
+
8
+ You have to 'require' each library independently:
9
+
10
+ require 'google4r/maps'
11
+ require 'google4r/checkout'
12
+
13
+ === License
14
+
15
+ google4r itself is distributed under an MIT style license.
16
+
17
+ However, the library includes the cacert.pem:http://curl.haxx.se/ca/cacert.pem file from the Mozilla project. This file is distributed under the MPL:http://www.mozilla.org/MPL/.
18
+
19
+ == Google Checkout
20
+
21
+ You can find more information on the Google Checkout API here:http://code.google.com/apis/checkout/developer/index.html. Note that the API documentation assumes an understanding of the Google Checkout XML API.
22
+
23
+ Google4R also contains a partial implementation of the level 2 of the Google Checkout API:
24
+
25
+ * The <checkout-cart-command> tag and all of its subtags that are not related to the merchant calculation API can be generated.
26
+ * The <new-order-notification> tag and all of its subtags which are not related to the merchant calculation API can be parsed.
27
+ * The <order-state-change-notification> tag can be parsed.
28
+
29
+ === Google Checkout Tests
30
+
31
+ You have to place a file called 'checkout_command_test.rb' in 'test/checkout' with the configuration for the Google4R::Checkout::Frontend class to use for running the tests.
32
+
33
+ The file should contain content similar to:
34
+
35
+ # The test configuration for the Google4R::Checkout::Frontend class.
36
+ FRONTEND_CONFIGURATION =
37
+ {
38
+ :merchant_id => '<your merchant id>',
39
+ :merchant_key => '<your merchant key>',
40
+ :use_sandbox => true
41
+ }
42
+
43
+ === TODO
44
+
45
+ Notifications:
46
+
47
+ * <risk-information-notification>
48
+ * <charge-amount-notification>
49
+ * <refund-amount-notification>
50
+ * <chargeback-amount-notification>
51
+ * <authorization-amount-notification>
52
+
53
+ All of the Order Processing API.
54
+
55
+ == Google Maps
56
+
57
+ The only part of the Google Maps API that can be standalone with sense is the Geocoder. The Google4R::Maps::Geocoder class allows to geocode address strings, i.e. finds a number of known locations that match the query to a certain degree. The information about the "known locations" includes the latitude and longitude of the location.
58
+
59
+ === Queries To Try Out
60
+
61
+ <b>Querying for this string</b>:: <b>will yield n results</b>
62
+ Helena:: 0
63
+ 1600 Amphitheatre Pkwy, Mountain View, CA 94043, USA:: 1
64
+ Janitell Rd, Colorado Springs, CO:: 2
65
+
66
+ === Maps Tests
67
+
68
+ Note that you wil have to place a file called 'key.rb' in the directory 'test/maps' to be able to run unit tests. It should have the following contents:
69
+
70
+ GOOGLE_MAPS_KEY = '<your google maps key>'
71
+
72
+ == Dependencies
73
+
74
+ The unit tests use Mocha so you have to install the gem "mocha" to run the tests.
75
+
@@ -0,0 +1,36 @@
1
+ #--
2
+ # Project: google4r
3
+ # File: lib/google4r/checkout.rb
4
+ # Author: Manuel Holtgrewe <purestorm at ggnore dot net>
5
+ # Copyright: (c) 2007 by Manuel Holtgrewe
6
+ # License: MIT License as follows:
7
+ #
8
+ # Permission is hereby granted, free of charge, to any person obtaining
9
+ # a copy of this software and associated documentation files (the
10
+ # "Software"), to deal in the Software without restriction, including
11
+ # without limitation the rights to use, copy, modify, merge, publish,
12
+ # distribute, sublicense, and/or sell copies of the Software, and to permit
13
+ # persons to whom the Software is furnished to do so, subject to the
14
+ # following conditions:
15
+ #
16
+ # The above copyright notice and this permission notice shall be included
17
+ # in all copies or substantial portions of the Software.
18
+ #
19
+ # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
20
+ # OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
21
+ # MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
22
+ # IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
23
+ # CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
24
+ # TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE
25
+ # OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
26
+ #++
27
+ # Require all the files that provide the code for the Google Checkout wrapper.
28
+
29
+ # Tweak the paths so hmac works without modifications.
30
+ $LOAD_PATH << File.expand_path(File.dirname(__FILE__) + '/checkout/vendor/hmac')
31
+
32
+ require 'google4r/checkout/shared'
33
+ require 'google4r/checkout/commands'
34
+ require 'google4r/checkout/notifications'
35
+ require 'google4r/checkout/xml_generation'
36
+ require 'google4r/checkout/frontend'
@@ -0,0 +1,267 @@
1
+ #--
2
+ # Project: google4r
3
+ # File: lib/google4r/checkout/commands.rb
4
+ # Author: Manuel Holtgrewe <purestorm at ggnore dot net>
5
+ # Copyright: (c) 2007 by Manuel Holtgrewe
6
+ # License: MIT License as follows:
7
+ #
8
+ # Permission is hereby granted, free of charge, to any person obtaining
9
+ # a copy of this software and associated documentation files (the
10
+ # "Software"), to deal in the Software without restriction, including
11
+ # without limitation the rights to use, copy, modify, merge, publish,
12
+ # distribute, sublicense, and/or sell copies of the Software, and to permit
13
+ # persons to whom the Software is furnished to do so, subject to the
14
+ # following conditions:
15
+ #
16
+ # The above copyright notice and this permission notice shall be included
17
+ # in all copies or substantial portions of the Software.
18
+ #
19
+ # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
20
+ # OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
21
+ # MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
22
+ # IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
23
+ # CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
24
+ # TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE
25
+ # OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
26
+ #++
27
+ # This file contains the classes and modules that are used by the command
28
+ # generating code.
29
+
30
+ require 'openssl'
31
+ require 'money'
32
+ require 'base64'
33
+ require 'net/http'
34
+ require 'net/https'
35
+ require 'uri'
36
+
37
+ module Google4R #:nodoc:
38
+ module Checkout #:nodoc:
39
+ # Abstract super class for all commands that are to be sent to Google. Provides the base
40
+ # functionality for signing and encoding the cart.
41
+ class Command
42
+ # The URL to use for requests to the sandboxed API. The merchant id is to be
43
+ # put in via String#%.
44
+ SANDBOX_URL = "https://sandbox.google.com/checkout/cws/v2/Merchant/%s/request"
45
+
46
+ # The URL to use for real requests to the Google Checkout API. The merchant id
47
+ # is to be put in via String#%.
48
+ PRODUCTION_URL = "https://checkout.google.com/cws/v2/Merchant/%s/request"
49
+
50
+ # The Frontent class that was used to create this CheckoutCommand and whose
51
+ # configuration will be used.
52
+ attr_reader :frontend
53
+
54
+ # Initialize the frontend attribute with the value of the frontend parameter.
55
+ def initialize(frontend)
56
+ @frontend = frontend
57
+ end
58
+
59
+ # Returns a hash with xml representation of this command and the signature for
60
+ # this representation. Both values are Base64 encoded.
61
+ #
62
+ # This can be used for generating the CheckoutButton when directly posted to
63
+ # Google.
64
+ #
65
+ # command.sign_and_encode
66
+ # # => { :cart => 'asdf', :signature => 'asdfasdf' }
67
+ def sign_and_encode
68
+ xml = self.to_xml
69
+
70
+ # Create a signature of the XML using OpenSSL::HMAC. Note that we do not want a
71
+ # hexadecimal result from the hash function but a binary result.
72
+ signature = OpenSSL::HMAC.digest(OpenSSL::Digest::Digest.new('sha1'),
73
+ frontend.configuration[:merchant_key], xml)
74
+
75
+ # Create Base64 encoded versions of the XML and the signature.
76
+ encoded_xml = Base64.encode64(xml)
77
+ encoded_signature = Base64.encode64(signature)
78
+
79
+ return { :cart => encoded_xml, :signature => encoded_signature }
80
+ end
81
+
82
+ # Sends the cart's XML to GoogleCheckout via HTTPs with Basic Auth.
83
+ #
84
+ # Raises an OpenSSL::SSL::SSLError when the SSL certificate verification failed.
85
+ #
86
+ # Raises a GoogleCheckoutError when Google returns an error.
87
+ #
88
+ # Raises a RuntimeException on unknown responses.
89
+ def send_to_google_checkout
90
+ # Create HTTP(S) POST command and set up Basic Authentication.
91
+ url_str =
92
+ if frontend.configuration[:use_sandbox] then
93
+ SANDBOX_URL % frontend.configuration[:merchant_id]
94
+ else
95
+ PRODUCTION_URL % frontend.configuration[:merchant_id]
96
+ end
97
+ url = URI.parse(url_str)
98
+
99
+ request = Net::HTTP::Post.new(url.path)
100
+ request.basic_auth(frontend.configuration[:merchant_id], frontend.configuration[:merchant_key])
101
+
102
+ # Set up the HTTP connection object and the SSL layer.
103
+ https = Net::HTTP.new(url.host, url.port)
104
+ https.use_ssl = true
105
+ https.cert_store = self.class.x509_store
106
+ https.verify_mode = OpenSSL::SSL::VERIFY_PEER
107
+ https.verify_depth = 5
108
+
109
+ # Send the request to Google.
110
+ result = https.request(request, self.to_xml)
111
+
112
+ case result
113
+ when Net::HTTPSuccess then
114
+ xml_doc = REXML::Document.new(result.body)
115
+
116
+ case xml_doc.root.name
117
+ when 'checkout-redirect'
118
+ serial_number = xml_doc.elements['/checkout-redirect/@serial-number'].value
119
+ redirect_url = xml_doc.elements['/checkout-redirect/redirect-url/text()'].value
120
+ return CheckoutRedirectResponse.new(serial_number, redirect_url)
121
+ else
122
+ raise "Unknown response:\n--\n#{xml_doc.to_s}\n--"
123
+ end
124
+ when Net::HTTPClientError then
125
+ xml_doc = REXML::Document.new(result.body)
126
+
127
+ if xml_doc.elements['/error/@serial-number'].nil? or xml_doc.elements['/error/error-message/text()'].nil? then
128
+ raise "Invalid response from Google:\n---\n#{result.body}\n---"
129
+ end
130
+
131
+ hash =
132
+ {
133
+ :serial_number => xml_doc.elements['/error/@serial-number'].value,
134
+ :message => xml_doc.elements['/error/error-message/text()'].value
135
+ }
136
+
137
+ raise GoogleCheckoutError.new(hash)
138
+ when Net::HTTPRedirection, Net::HTTPServerError, Net::HTTPInformation then
139
+ raise "Unexpected reponse code (#{result.class}): #{result.code} - #{result.message}"
140
+ else
141
+ raise "Unknown reponse code: #{result.code} - #{result.message}"
142
+ end
143
+ end
144
+
145
+ # Abstract method that is to contain the command's XML representation.
146
+ def to_xml
147
+ raise "Command#to_xml is abstract and must be overridden in a subclass."
148
+ end
149
+
150
+ protected
151
+
152
+ # Class method to return the OpenSSL::X509::Store instance for the
153
+ # CA certificates.
154
+ def self.x509_store
155
+ return @@x509_store if defined?(@@x509_store)
156
+
157
+ cacert_path = File.expand_path(File.dirname(__FILE__) + '/../../../var/cacert.pem')
158
+
159
+ @@x509_store = OpenSSL::X509::Store.new
160
+ @@x509_store.add_file(cacert_path)
161
+
162
+ return @@x509_store
163
+ end
164
+ end
165
+
166
+ # The CheckoutCommand represents a <checkout-shopping-cart> command sent
167
+ # to the server.
168
+ #
169
+ # A CheckoutCommand instance can have an arbitrary number of TaxTable
170
+ # and ShippingMethod instances. You must create these instances using the
171
+ # create_* methods which CheckoutCommand supplies.
172
+ #
173
+ # CheckoutCommand#send_to_google_checkout returns CheckoutRedirectResponse
174
+ # instances.
175
+ #
176
+ # Use the Frontend class to create new CheckoutCommand instances and do not
177
+ # instanciate the class directly.
178
+ #
179
+ # Note that you have to create/set the tax tables for CheckoutCommands before you
180
+ # can add any items to the cart that define a tax table.
181
+ #
182
+ # === Example
183
+ #
184
+ # frontend = Google4R::Checkout::Frontend.new(configuration)
185
+ # frontend.tax_table_factory = TaxTableFactory.new
186
+ # command = frontend.create_checkout_command
187
+ class CheckoutCommand < Command
188
+ # The ShoppingCart of this CheckoutCommand.
189
+ attr_reader :cart
190
+
191
+ # An array of the TaxTable objects of this CheckoutCommand. They have been
192
+ # created with the tax table factory of the frontend which created this
193
+ # command.
194
+ attr_reader :tax_tables
195
+
196
+ # An array of ShippingMethod objects of this CheckoutCommand. Use
197
+ # #create_shipping_method to create new shipping methods.
198
+ attr_reader :shipping_methods
199
+
200
+ # The URL at where the cart can be edited (String, optional).
201
+ attr_accessor :edit_cart_url
202
+
203
+ # The URL to continue shopping after completing the checkout (String, optional).
204
+ attr_accessor :continue_shopping_url
205
+
206
+ # A boolean flag; true iff the customer HAS to provide his phone number (optional).
207
+ attr_accessor :request_buyer_phone_number
208
+
209
+ # Generates the XML for this CheckoutCommand.
210
+ def to_xml
211
+ CheckoutCommandXmlGenerator.new(self).generate
212
+ end
213
+
214
+ # Initialize a new CheckoutCommand with a fresh CheckoutCart and an empty
215
+ # Array of tax tables and an empty array of ShippingMethod instances.
216
+ # Do not use this method directly but use Frontent#create_checkout_command
217
+ # to create CheckoutCommand objects.
218
+ def initialize(frontend)
219
+ super(frontend)
220
+
221
+ @cart = ShoppingCart.new(self)
222
+ @tax_tables = frontend.tax_table_factory.effective_tax_tables_at(Time.new)
223
+ @shipping_methods = Array.new
224
+ end
225
+
226
+ # Use this method to create a new shipping method. You have to pass in one of
227
+ # { PickupShipping, FlatRateShipping } for clazz. The method will create a
228
+ # new instance of the class you passedin object and add it to the internal list
229
+ # of shipping methods.
230
+ #
231
+ # If you pass a block to this method (preferred) then the newly created
232
+ # ShippingMethod object will be passed into this block for setting its attributes.
233
+ # The newly created shipping method will be returned in all cases.
234
+ #
235
+ # The first shipping method will be used as the default.
236
+ #
237
+ # Raises a RuntimeError if the parameter clazz is invalid.
238
+ def create_shipping_method(clazz, &block)
239
+ if not [ PickupShipping, FlatRateShipping ].include?(clazz) then
240
+ raise "Unknown shipping method: #{type.inspect}."
241
+ end
242
+
243
+ shipping_method = clazz.new
244
+ @shipping_methods << shipping_method
245
+
246
+ yield(shipping_method) if block_given?
247
+
248
+ return shipping_method
249
+ end
250
+ end
251
+
252
+ # CheckoutRedirectResponse instances are returned when a CheckoutCommand is successfully
253
+ # processed by Google Checkout.
254
+ class CheckoutRedirectResponse
255
+ # The serial number of the <checkout-redirect> response.
256
+ attr_reader :serial_number
257
+
258
+ # The URL to redirect to.
259
+ attr_reader :redirect_url
260
+
261
+ def initialize(serial_number, redirect_url)
262
+ @serial_number = serial_number
263
+ @redirect_url = redirect_url
264
+ end
265
+ end
266
+ end
267
+ end
@@ -0,0 +1,100 @@
1
+ #--
2
+ # Project: google4r
3
+ # File: lib/google4r/checkout/frontend.rb
4
+ # Author: Manuel Holtgrewe <purestorm at ggnore dot net>
5
+ # Copyright: (c) 2007 by Manuel Holtgrewe
6
+ # License: MIT License as follows:
7
+ #
8
+ # Permission is hereby granted, free of charge, to any person obtaining
9
+ # a copy of this software and associated documentation files (the
10
+ # "Software"), to deal in the Software without restriction, including
11
+ # without limitation the rights to use, copy, modify, merge, publish,
12
+ # distribute, sublicense, and/or sell copies of the Software, and to permit
13
+ # persons to whom the Software is furnished to do so, subject to the
14
+ # following conditions:
15
+ #
16
+ # The above copyright notice and this permission notice shall be included
17
+ # in all copies or substantial portions of the Software.
18
+ #
19
+ # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
20
+ # OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
21
+ # MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
22
+ # IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
23
+ # CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
24
+ # TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE
25
+ # OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
26
+ #++
27
+ # This file provides the Google4R::Checkout::Frontend class that is a factory for the commands
28
+ # to be sent to Google Checkout.
29
+
30
+ module Google4R #:nodoc:
31
+ module Checkout #:nodoc:
32
+ # The Frontend class is the factory that is to be used to create the Command (and later
33
+ # NotificationHandler) objects.
34
+ #
35
+ # === Example
36
+ #
37
+ # configuration = { :merchant_id => '123456789', :merchant_key => '12345abcd' }
38
+ #
39
+ # frontend = Google4R::Checkout::Frontend.new(configuration)
40
+ # command = frontend.create_checkout_command
41
+ #
42
+ # == Tax Table Factory
43
+ #
44
+ # You have to set the tax_table_factory attribute of every Frontend object before you
45
+ # can call #create_checkout_command or #create_notification_handler because those
46
+ # objects require tax tables.
47
+ #
48
+ # The Tax Table Factory must provide the method "effective_tax_tables_at" accept a Time
49
+ # object and provide a method that returns an Array of TaxTable object that describe the
50
+ # effective tax rules at the given point of time.
51
+ #
52
+ # class TaxTableFactory
53
+ # def effective_tax_tables_at(time)
54
+ # if time < Time.parse("Wed Apr 09 08:56:03 CDT 2003") then
55
+ # table1, table2 = TaxTable.new, TaxTable.new
56
+ # # ... set rules
57
+ # [ table1, table 2]
58
+ # else
59
+ # table3, table4 = TaxTable.new, TaxTable.new
60
+ # # ... set rules
61
+ # [ table3, table 4]
62
+ # end
63
+ # end
64
+ # end
65
+ #
66
+ # frontend = Frontend.new
67
+ # frontend.tax_table_factory = TaxTableFactory.new
68
+ class Frontend
69
+ # The configuration for this Frontend class. It will be used by all classes created
70
+ # by this Frontend instance.
71
+ attr_reader :configuration
72
+
73
+ # An object with a factory method that can create the effective TaxTable objects
74
+ # that were valid at a given point of time.
75
+ attr_accessor :tax_table_factory
76
+
77
+ # Creates a new Frontend instance and sets the configuration attribute to the parameter
78
+ # configuration.
79
+ def initialize(configuration)
80
+ raise "Missing configuration setting: merchant_id" if configuration[:merchant_id].nil?
81
+ raise "Missing configuration setting: merchant_key" if configuration[:merchant_key].nil?
82
+ raise "Missing configuration setting: use_sandbox" if configuration[:use_sandbox].nil?
83
+
84
+ @configuration = configuration.dup.freeze
85
+ end
86
+
87
+ # Factory method that creates a new CheckoutCommand object. Use this method to create
88
+ # your CheckoutCommand instances.
89
+ def create_checkout_command
90
+ return CheckoutCommand.new(self)
91
+ end
92
+
93
+ # Factory method that creates a new NotificationHandler object. Use this method to
94
+ # create your NotificationHandler instances.
95
+ def create_notification_handler
96
+ return NotificationHandler.new(self)
97
+ end
98
+ end
99
+ end
100
+ end