google4r-checkout 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (39) hide show
  1. data/CHANGES +40 -0
  2. data/LICENSE +22 -0
  3. data/README +76 -0
  4. data/lib/google4r/checkout.rb +33 -0
  5. data/lib/google4r/checkout/commands.rb +260 -0
  6. data/lib/google4r/checkout/frontend.rb +108 -0
  7. data/lib/google4r/checkout/notifications.rb +549 -0
  8. data/lib/google4r/checkout/shared.rb +541 -0
  9. data/lib/google4r/checkout/xml_generation.rb +313 -0
  10. data/test/integration/checkout_command_test.rb +103 -0
  11. data/test/unit/address_test.rb +131 -0
  12. data/test/unit/area_test.rb +44 -0
  13. data/test/unit/checkout_command_test.rb +116 -0
  14. data/test/unit/checkout_command_xml_generator_test.rb +203 -0
  15. data/test/unit/command_test.rb +115 -0
  16. data/test/unit/flat_rate_shipping_test.rb +114 -0
  17. data/test/unit/frontend_test.rb +63 -0
  18. data/test/unit/item_test.rb +159 -0
  19. data/test/unit/marketing_preferences_test.rb +65 -0
  20. data/test/unit/merchant_code_test.rb +122 -0
  21. data/test/unit/new_order_notification_test.rb +115 -0
  22. data/test/unit/notification_acknowledgement_test.rb +43 -0
  23. data/test/unit/notification_handler_test.rb +93 -0
  24. data/test/unit/order_adjustment_test.rb +119 -0
  25. data/test/unit/order_state_change_notification_test.rb +159 -0
  26. data/test/unit/pickup_shipping_test.rb +70 -0
  27. data/test/unit/postal_area_test.rb +71 -0
  28. data/test/unit/private_data_parser_test.rb +68 -0
  29. data/test/unit/shipping_adjustment_test.rb +100 -0
  30. data/test/unit/shipping_method_test.rb +41 -0
  31. data/test/unit/shopping_cart_test.rb +146 -0
  32. data/test/unit/tax_rule_test.rb +70 -0
  33. data/test/unit/tax_table_test.rb +82 -0
  34. data/test/unit/us_country_area_test.rb +76 -0
  35. data/test/unit/us_state_area_test.rb +70 -0
  36. data/test/unit/us_zip_area_test.rb +66 -0
  37. data/test/unit/world_area_test.rb +48 -0
  38. data/var/cacert.pem +7815 -0
  39. metadata +92 -0
data/CHANGES ADDED
@@ -0,0 +1,40 @@
1
+ = google4r-checkout Changelog
2
+
3
+ == HEAD
4
+
5
+ == 0.1.0 (2007-05-12)
6
+
7
+ * Added property "shipping_taxed" to TaxRule (contributed by Dan Dukeson).
8
+ * Added XML generation for the tax tables in the shopping cart (contributed by Dan Dukeson).
9
+ * Added Area subclasses WorldArea and PostalArea (contributed by Dan Dukeson).
10
+ * Changed time zones in tests to UTC.
11
+ * Added Test::Unit::TestCase#assert_strings_equal to test_helper.rb.
12
+ * Added "rake test" (alias of "rake test:all")
13
+ * Added GoogleCheckoutError#to_s to return verbose representation.
14
+ * Split google4r into google4r-checkout and google4r-maps.
15
+ * MerchantCode#create_from_element raises an ArgumentError instead of a RuntimeError on invalid elements now.
16
+ * Changed the #create_from_element code to set the properties directly into the objects instead of building Hashes to collect the values first.
17
+ * "Resolved" the problem of converting currency amounts which are fractional numbers into the amount of the minor currency to be passed into the Money class: Instead of converting the fractional number into a float and multiplying by 100, all nonnumeric characters are stripped from the string, the resulting number is converted into an integer and this integer is then passed to Money.new.
18
+ * Added example to NotificationHandler of how to use the class.
19
+ * Added link to simple_http_auth plugin in NotificationHandler which allows for easy HTTP Auth Basic protection of Rails controllers.
20
+ * Renamed CheckoutCommand#cart to CheckoutCommand#shopping_cart
21
+ * CheckoutCommand raises ArgumentError instead of RuntimeError on invalid clazz parameter.
22
+ * Added "Howto freeze google4r in a Rails project" to README
23
+ * Google4R::Checkout::Command#to_xml raises an NotImplementedError instead of a RuntimeError now.
24
+ * Geocoder returns nil on 603 (G_UNAVAILABLE_ADDRESS) results now.
25
+ * Added support for registering GUnload() to be called on window's unload event.
26
+ * The generated Javascript that creates the GMap2() instance (and thus modifies the map div) has been put into a function <var name>_loader that is called in an onload handler. This should remove a problem with MSIE.
27
+ * Using Syck as the YAML parser now. However, a workaround is needed because of http://code.whytheluckystiff.net/syck/ticket/27.
28
+ * Only require the json gem if objects have no "to_json" method already added to them. This solves a problem with converting arbitrary objects to json because the json gem seemingly only converts simple types.
29
+ * Added GMarker#info_window_html.
30
+ * Added support for onclick handlers in markers.
31
+ * Added support for the value :auto of GMap2#zoom and GMap2#center.
32
+ * Fixed buggy generation of GMarker Javascript.
33
+ * Adding website folder to contain a webgen based website.
34
+ * Fixed a problem with generating XML from Hashes in the "private" data of shopping carts and items.
35
+ * The parse for the <order-adjustment> tag does not expect to see a <shipping> tag in every case any more.
36
+ * Extending Google4R::Maps by the classes GMap2, GIcon and GMarker to allow for easy Google Maps HTML generation.
37
+
38
+ == 0.0.1 (2007-02-17)
39
+
40
+ * 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) 2007 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,76 @@
1
+ = google4r/checkout
2
+
3
+ google4r/checkout is a library to access the Google Checkout API.
4
+
5
+ === License
6
+
7
+ google4r itself is distributed under an MIT style license.
8
+
9
+ 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/.
10
+
11
+ == Status
12
+
13
+ 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.
14
+
15
+ Google4R also contains a partial implementation of the level 2 of the Google Checkout API:
16
+
17
+ * The <checkout-cart-command> tag and all of its subtags that are not related to the merchant calculation API can be generated.
18
+ * The <new-order-notification> tag and all of its subtags which are not related to the merchant calculation API can be parsed.
19
+ * The <order-state-change-notification> tag can be parsed.
20
+
21
+ == Google Checkout Tests
22
+
23
+ You have to place a file called 'frontend_configuration.rb' in the directory'test' with the configuration for the Google4R::Checkout::Frontend class to use for running the tests.
24
+
25
+ The file should contain content similar to:
26
+
27
+ # Uncomment the following line if you are using Google Checkout in Great Britain
28
+ # and adjust it if you want to test google4r-checkout against any other (future)
29
+ # Google Checkout service.
30
+
31
+ # Money.default_currency = 'GBP'
32
+
33
+ # The test configuration for the Google4R::Checkout::Frontend class.
34
+ FRONTEND_CONFIGURATION =
35
+ {
36
+ :merchant_id => '<your merchant id>',
37
+ :merchant_key => '<your merchant key>',
38
+ :use_sandbox => true
39
+ }
40
+
41
+ == TODO
42
+
43
+ Notifications:
44
+
45
+ * <risk-information-notification>
46
+ * <charge-amount-notification>
47
+ * <refund-amount-notification>
48
+ * <chargeback-amount-notification>
49
+ * <authorization-amount-notification>
50
+
51
+ All of the Order Processing API.
52
+
53
+ == Dependencies
54
+
55
+ The unit tests use Mocha so you have to install the gem "mocha" to run the tests. You will also need the money gem library.
56
+
57
+ == How To: Freeze a google4r version in a Rails project
58
+
59
+ <code>rake rails:freeze:gems</code> only works for the Rails gems. So, how do you freeze your own gems like google4r? It turns out to be pretty straightforward:
60
+
61
+ cd RAILS_ROOT
62
+ cd vendor
63
+ gem unpack google4r-checkout
64
+ ls
65
+ # ... google4r-checkout-0.1.1 ...
66
+
67
+ Then, open RAILS_ROOT/config/environment.rb in your favourite text editor and add the following lines at the top of the file just below <code>require File.join(File.dirname(__FILE__), 'boot')</code>:
68
+
69
+ # Freeze non-Rails gem.
70
+ Dir.glob(File.join(RAILS_ROOT, 'vendor', '*', 'lib')) do |path|
71
+ $LOAD_PATH << path
72
+ end
73
+
74
+ Now you can use the following in your own code:
75
+
76
+ require 'google4r/checkout'
@@ -0,0 +1,33 @@
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
+ require 'google4r/checkout/shared'
30
+ require 'google4r/checkout/commands'
31
+ require 'google4r/checkout/notifications'
32
+ require 'google4r/checkout/xml_generation'
33
+ require 'google4r/checkout/frontend'
@@ -0,0 +1,260 @@
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 'net/http'
33
+ require 'net/https'
34
+ require 'uri'
35
+
36
+ module Google4R #:nodoc:
37
+ module Checkout #:nodoc:
38
+ # Abstract super class for all commands that are to be sent to Google. Provides the base
39
+ # functionality for signing and encoding the cart.
40
+ class Command
41
+ # The URL to use for requests to the sandboxed API. The merchant id is to be
42
+ # put in via String#%.
43
+ #--
44
+ # TODO: Move this into a class variable (e.g. via cattr) so it is adaptable.
45
+ #++
46
+ SANDBOX_URL = "https://sandbox.google.com/checkout/cws/v2/Merchant/%s/request"
47
+
48
+ # The URL to use for real requests to the Google Checkout API. The merchant id
49
+ # is to be put in via String#%.
50
+ #--
51
+ # TODO: Move this into a class variable (e.g. via cattr) so it is adaptable.
52
+ #++
53
+ PRODUCTION_URL = "https://checkout.google.com/cws/v2/Merchant/%s/request"
54
+
55
+ # The Frontent class that was used to create this CheckoutCommand and whose
56
+ # configuration will be used.
57
+ attr_reader :frontend
58
+
59
+ # Initialize the frontend attribute with the value of the frontend parameter.
60
+ def initialize(frontend)
61
+ @frontend = frontend
62
+ end
63
+
64
+ # Sends the cart's XML to GoogleCheckout via HTTPs with Basic Auth.
65
+ #
66
+ # Raises an OpenSSL::SSL::SSLError when the SSL certificate verification failed.
67
+ #
68
+ # Raises a GoogleCheckoutError when Google returns an error.
69
+ #
70
+ # Raises a RuntimeException on unknown responses.
71
+ #--
72
+ # TODO: The send-and-expect-response part should be adaptable to other commands and responses.
73
+ #++
74
+ def send_to_google_checkout
75
+ # Create HTTP(S) POST command and set up Basic Authentication.
76
+ url_str =
77
+ if frontend.configuration[:use_sandbox] then
78
+ SANDBOX_URL % frontend.configuration[:merchant_id]
79
+ else
80
+ PRODUCTION_URL % frontend.configuration[:merchant_id]
81
+ end
82
+ url = URI.parse(url_str)
83
+
84
+ request = Net::HTTP::Post.new(url.path)
85
+ request.basic_auth(frontend.configuration[:merchant_id], frontend.configuration[:merchant_key])
86
+
87
+ # Set up the HTTP connection object and the SSL layer.
88
+ https = Net::HTTP.new(url.host, url.port)
89
+ https.use_ssl = true
90
+ https.cert_store = self.class.x509_store
91
+ https.verify_mode = OpenSSL::SSL::VERIFY_PEER
92
+ https.verify_depth = 5
93
+
94
+ # Send the request to Google.
95
+ result = https.request(request, self.to_xml)
96
+
97
+ case result
98
+ when Net::HTTPSuccess then
99
+ xml_doc = REXML::Document.new(result.body)
100
+
101
+ case xml_doc.root.name
102
+ when 'checkout-redirect'
103
+ serial_number = xml_doc.elements['/checkout-redirect/@serial-number'].value
104
+ redirect_url = xml_doc.elements['/checkout-redirect/redirect-url/text()'].value
105
+ return CheckoutRedirectResponse.new(serial_number, redirect_url)
106
+ else
107
+ raise "Unknown response:\n--\n#{xml_doc.to_s}\n--"
108
+ end
109
+ when Net::HTTPClientError then
110
+ xml_doc = REXML::Document.new(result.body)
111
+
112
+ if xml_doc.elements['/error/@serial-number'].nil? or xml_doc.elements['/error/error-message/text()'].nil? then
113
+ raise "Invalid response from Google:\n---\n#{result.body}\n---"
114
+ end
115
+
116
+ hash =
117
+ {
118
+ :serial_number => xml_doc.elements['/error/@serial-number'].value,
119
+ :message => xml_doc.elements['/error/error-message/text()'].value
120
+ }
121
+
122
+ raise GoogleCheckoutError.new(hash)
123
+ when Net::HTTPRedirection, Net::HTTPServerError, Net::HTTPInformation then
124
+ raise "Unexpected reponse code (#{result.class}): #{result.code} - #{result.message}"
125
+ else
126
+ raise "Unknown reponse code: #{result.code} - #{result.message}"
127
+ end
128
+ end
129
+
130
+ # Abstract method that is to contain the command's XML representation.
131
+ #
132
+ # Raises a NotImplementedError by default, override to remove this.
133
+ def to_xml
134
+ raise NotImplementedError, "Command#to_xml is abstract and must be overridden in a subclass."
135
+ end
136
+
137
+ protected
138
+
139
+ # Class method to return the OpenSSL::X509::Store instance for the
140
+ # CA certificates.
141
+ #--
142
+ # TODO: Is OpenSSL::X509::Store thread safe when reading only? This method most certainly is *not*. It must become so.
143
+ #++
144
+ def self.x509_store
145
+ return @@x509_store if defined?(@@x509_store)
146
+
147
+ cacert_path = File.expand_path(File.dirname(__FILE__) + '/../../../var/cacert.pem')
148
+
149
+ @@x509_store = OpenSSL::X509::Store.new
150
+ @@x509_store.add_file(cacert_path)
151
+
152
+ return @@x509_store
153
+ end
154
+ end
155
+
156
+ # The CheckoutCommand represents a <checkout-shopping-cart> command sent
157
+ # to the server.
158
+ #
159
+ # A CheckoutCommand instance can have an arbitrary number of TaxTable
160
+ # and ShippingMethod instances. You must create these instances using the
161
+ # create_* methods which CheckoutCommand supplies.
162
+ #
163
+ # CheckoutCommand#send_to_google_checkout returns CheckoutRedirectResponse
164
+ # instances.
165
+ #
166
+ # Use the Frontend class to create new CheckoutCommand instances and do not
167
+ # instanciate the class directly.
168
+ #
169
+ # Note that you have to create/set the tax tables for CheckoutCommands before you
170
+ # can add any items to the cart that define a tax table.
171
+ #
172
+ # === Example
173
+ #
174
+ # frontend = Google4R::Checkout::Frontend.new(configuration)
175
+ # frontend.tax_table_factory = TaxTableFactory.new
176
+ # command = frontend.create_checkout_command
177
+ class CheckoutCommand < Command
178
+ # The ShoppingCart of this CheckoutCommand.
179
+ attr_reader :shopping_cart
180
+
181
+ # An array of the TaxTable objects of this CheckoutCommand. They have been
182
+ # created with the tax table factory of the frontend which created this
183
+ # command.
184
+ attr_reader :tax_tables
185
+
186
+ # An array of ShippingMethod objects of this CheckoutCommand. Use
187
+ # #create_shipping_method to create new shipping methods.
188
+ attr_reader :shipping_methods
189
+
190
+ # The URL at where the cart can be edited (String, optional).
191
+ attr_accessor :edit_cart_url
192
+
193
+ # The URL to continue shopping after completing the checkout (String, optional).
194
+ attr_accessor :continue_shopping_url
195
+
196
+ # A boolean flag; true iff the customer HAS to provide his phone number (optional).
197
+ attr_accessor :request_buyer_phone_number
198
+
199
+ # Generates the XML for this CheckoutCommand.
200
+ def to_xml
201
+ CheckoutCommandXmlGenerator.new(self).generate
202
+ end
203
+
204
+ # Initialize a new CheckoutCommand with a fresh CheckoutCart and an empty
205
+ # Array of tax tables and an empty array of ShippingMethod instances.
206
+ # Do not use this method directly but use Frontent#create_checkout_command
207
+ # to create CheckoutCommand objects.
208
+ def initialize(frontend)
209
+ super(frontend)
210
+
211
+ @shopping_cart = ShoppingCart.new(self)
212
+ @tax_tables = frontend.tax_table_factory.effective_tax_tables_at(Time.new)
213
+ @shipping_methods = Array.new
214
+ end
215
+
216
+ # Use this method to create a new shipping method. You have to pass in one of
217
+ # { PickupShipping, FlatRateShipping } for clazz. The method will create a
218
+ # new instance of the class you passedin object and add it to the internal list
219
+ # of shipping methods.
220
+ #
221
+ # If you pass a block to this method (preferred) then the newly created
222
+ # ShippingMethod object will be passed into this block for setting its attributes.
223
+ # The newly created shipping method will be returned in all cases.
224
+ #
225
+ # The first created shipping method will be used as the default.
226
+ #
227
+ # Raises a ArgumentError if the parameter clazz is invalid.
228
+ def create_shipping_method(clazz, &block)
229
+ if not [ PickupShipping, FlatRateShipping ].include?(clazz) then
230
+ raise ArgumentError, "Unknown shipping method: #{clazz.inspect}."
231
+ end
232
+
233
+ shipping_method = clazz.new
234
+ @shipping_methods << shipping_method
235
+
236
+ yield(shipping_method) if block_given?
237
+
238
+ return shipping_method
239
+ end
240
+ end
241
+
242
+ # CheckoutRedirectResponse instances are returned when a CheckoutCommand is successfully
243
+ # processed by Google Checkout.
244
+ class CheckoutRedirectResponse
245
+ # The serial number of the <checkout-redirect> response.
246
+ attr_reader :serial_number
247
+
248
+ # The URL to redirect to.
249
+ attr_reader :redirect_url
250
+
251
+ # Create a new CheckoutRedirectResponse with the given serial number and redirection URL.
252
+ # Do not create CheckoutRedirectResponse instances in your own code. Google4R creates them
253
+ # for you.
254
+ def initialize(serial_number, redirect_url)
255
+ @serial_number = serial_number
256
+ @redirect_url = redirect_url
257
+ end
258
+ end
259
+ end
260
+ end
@@ -0,0 +1,108 @@
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
+ #
41
+ # == Tax Table Factory
42
+ #
43
+ # You have to set the tax_table_factory attribute of every Frontend object before you
44
+ # can call #create_checkout_command or #create_notification_handler because the
45
+ # objects created by those methods require tax tables.
46
+ #
47
+ # The Tax Table Factory must provide the method "effective_tax_tables_at" accept a Time
48
+ # object and provide a method that returns an Array of TaxTable object that describe the
49
+ # effective tax rules at the given point of time.
50
+ #
51
+ # Effectively, this means you have to implement the Temporal Property pattern as described
52
+ # here: http://www.martinfowler.com/ap2/temporalProperty.html.
53
+ #
54
+ # == Example
55
+ #
56
+ # class TaxTableFactory
57
+ # def effective_tax_tables_at(time)
58
+ # if time < Time.parse("Wed Apr 09 08:56:03 CDT 2003") then
59
+ # table1, table2 = TaxTable.new, TaxTable.new
60
+ # # ... set rules
61
+ # [ table1, table 2]
62
+ # else
63
+ # table3, table4 = TaxTable.new, TaxTable.new
64
+ # # ... set rules
65
+ # [ table3, table 4]
66
+ # end
67
+ # end
68
+ # end
69
+ #
70
+ # frontend = Google4R::Checkout::Frontend.new(configuration)
71
+ # frontend.tax_table_factory = TaxTableFactory.new
72
+ #
73
+ # checkout_command = frontent.create_checkout_command
74
+ # # ...
75
+ # handler = frontend.create_notification_handler
76
+ class Frontend
77
+ # The configuration for this Frontend class. It will be used by all classes created
78
+ # by this Frontend instance (Hash).
79
+ attr_reader :configuration
80
+
81
+ # An object with a factory method that can create the effective TaxTable objects
82
+ # that were valid at a given point of time.
83
+ attr_accessor :tax_table_factory
84
+
85
+ # Creates a new Frontend instance and sets the configuration attribute to the parameter
86
+ # configuration.
87
+ def initialize(configuration)
88
+ raise "Missing configuration setting: merchant_id" if configuration[:merchant_id].nil?
89
+ raise "Missing configuration setting: merchant_key" if configuration[:merchant_key].nil?
90
+ raise "Missing configuration setting: use_sandbox" if configuration[:use_sandbox].nil?
91
+
92
+ @configuration = configuration.dup.freeze
93
+ end
94
+
95
+ # Factory method that creates a new CheckoutCommand object. Use this method to create
96
+ # your CheckoutCommand instances.
97
+ def create_checkout_command
98
+ return CheckoutCommand.new(self)
99
+ end
100
+
101
+ # Factory method that creates a new NotificationHandler object. Use this method to
102
+ # create your NotificationHandler instances.
103
+ def create_notification_handler
104
+ return NotificationHandler.new(self)
105
+ end
106
+ end
107
+ end
108
+ end