google4r-checkout 1.0.1 → 1.0.2
Sign up to get free protection for your applications and to get access to all the features.
- data/CHANGES +9 -0
- data/lib/google4r/checkout.rb +1 -0
- data/lib/google4r/checkout/commands.rb +13 -1
- data/lib/google4r/checkout/frontend.rb +14 -8
- data/lib/google4r/checkout/merchant_calculation.rb +317 -0
- data/lib/google4r/checkout/notifications.rb +0 -56
- data/lib/google4r/checkout/shared.rb +172 -32
- data/lib/google4r/checkout/xml_generation.rb +140 -24
- data/test/unit/anonymous_address_test.rb +75 -0
- data/test/unit/callback_handler_test.rb +83 -0
- data/test/unit/checkout_command_test.rb +7 -3
- data/test/unit/checkout_command_xml_generator_test.rb +7 -1
- data/test/unit/{shipping_method_test.rb → delivery_method_test.rb} +4 -3
- data/test/unit/flat_rate_shipping_test.rb +28 -10
- data/test/unit/merchant_calculated_shipping_test.rb +136 -0
- data/test/unit/merchant_calculation_callback_test.rb +137 -0
- data/test/unit/merchant_calculation_result_test.rb +78 -0
- data/test/unit/merchant_calculation_results_test.rb +178 -0
- data/test/unit/merchant_code_result_test.rb +51 -0
- metadata +11 -3
data/CHANGES
CHANGED
@@ -1,5 +1,14 @@
|
|
1
1
|
=google4r-checkout Changelog
|
2
2
|
|
3
|
+
== 1.0.2 (2007-08-18)
|
4
|
+
|
5
|
+
* Moved Address from notifications.rb to shared.rb
|
6
|
+
* Added AnonymousAddress class, now Address is extended from it
|
7
|
+
* Added merchant calcuations callback and result support
|
8
|
+
* Added unit tests for merchant calculation callback and result
|
9
|
+
* Added merchant calculations tag support in Shopping Cart XML
|
10
|
+
* Updated checkout_command_test.rb and checkout_command_xml_generator_test.rb after for testing merchant calculations tag support
|
11
|
+
|
3
12
|
== 1.0.1 (2007-08-16)
|
4
13
|
|
5
14
|
* Fixed text.to_s.gsub(/[^0-9]/, '') to (...text.to_f*100).to_i so dollar amount is now handled correctly
|
data/lib/google4r/checkout.rb
CHANGED
@@ -208,6 +208,18 @@ module Google4R #:nodoc:
|
|
208
208
|
# A boolean flag; true iff the customer HAS to provide his phone number (optional).
|
209
209
|
attr_accessor :request_buyer_phone_number
|
210
210
|
|
211
|
+
# The URL of the merchant calculation callback (optional).
|
212
|
+
attr_accessor :merchant_calculations_url
|
213
|
+
|
214
|
+
# A boolean flag to indicate whether merchant coupon is supported or not (optional).
|
215
|
+
attr_accessor :accept_merchant_coupons
|
216
|
+
|
217
|
+
# A boolean flag to indicate whether gift certificate is supported or not (optional).
|
218
|
+
attr_accessor :accept_gift_certificates
|
219
|
+
|
220
|
+
# A Google Checkout merchant ID that identifies the eCommerce provider.
|
221
|
+
attr_accessor :platform_id
|
222
|
+
|
211
223
|
# Generates the XML for this CheckoutCommand.
|
212
224
|
def to_xml
|
213
225
|
CheckoutCommandXmlGenerator.new(self).generate
|
@@ -237,7 +249,7 @@ module Google4R #:nodoc:
|
|
237
249
|
#
|
238
250
|
# Raises a ArgumentError if the parameter clazz is invalid.
|
239
251
|
def create_shipping_method(clazz, &block)
|
240
|
-
if not [ PickupShipping, FlatRateShipping ].include?(clazz) then
|
252
|
+
if not [ PickupShipping, FlatRateShipping, MerchantCalculatedShipping ].include?(clazz) then
|
241
253
|
raise ArgumentError, "Unknown shipping method: #{clazz.inspect}."
|
242
254
|
end
|
243
255
|
|
@@ -29,8 +29,8 @@
|
|
29
29
|
|
30
30
|
module Google4R #:nodoc:
|
31
31
|
module Checkout #:nodoc:
|
32
|
-
# The Frontend class is the factory that is to be used to create the Command
|
33
|
-
# NotificationHandler
|
32
|
+
# The Frontend class is the factory that is to be used to create the Command,
|
33
|
+
# NotificationHandler and CallbackHandler objects.
|
34
34
|
#
|
35
35
|
# === Example
|
36
36
|
#
|
@@ -91,6 +91,18 @@ module Google4R #:nodoc:
|
|
91
91
|
|
92
92
|
@configuration = configuration.dup.freeze
|
93
93
|
end
|
94
|
+
|
95
|
+
# Factory method that creates a new NotificationHandler object. Use this method to
|
96
|
+
# create your NotificationHandler instances.
|
97
|
+
def create_notification_handler
|
98
|
+
return NotificationHandler.new(self)
|
99
|
+
end
|
100
|
+
|
101
|
+
# Factory method that creates a new CallbackHandler object. Use this method to
|
102
|
+
# create your CallbackHandler instances.
|
103
|
+
def create_callback_handler
|
104
|
+
return CallbackHandler.new(self)
|
105
|
+
end
|
94
106
|
|
95
107
|
# Factory method to create a new DeliverOrderCommand object. Use this method to create
|
96
108
|
# your DeliverOrderCommand instances.
|
@@ -109,12 +121,6 @@ module Google4R #:nodoc:
|
|
109
121
|
def create_checkout_command
|
110
122
|
return CheckoutCommand.new(self)
|
111
123
|
end
|
112
|
-
|
113
|
-
# Factory method that creates a new NotificationHandler object. Use this method to
|
114
|
-
# create your NotificationHandler instances.
|
115
|
-
def create_notification_handler
|
116
|
-
return NotificationHandler.new(self)
|
117
|
-
end
|
118
124
|
|
119
125
|
# Factory method to create a new CancelOrderCommand object. Use this method to create
|
120
126
|
# your CancelOrderCommand instances.
|
@@ -0,0 +1,317 @@
|
|
1
|
+
#--
|
2
|
+
# Project: google4r
|
3
|
+
# File: lib/google4r/checkout/merchant_calculation.rb
|
4
|
+
# Author: Tony Chan <api dot htchan at gmail dot com>
|
5
|
+
# Copyright: (c) 2007 by Tony Chan
|
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 in the callback
|
28
|
+
# handling code.
|
29
|
+
|
30
|
+
require 'rexml/document'
|
31
|
+
|
32
|
+
module Google4R #:nodoc:
|
33
|
+
module Checkout #:nodoc:
|
34
|
+
# Thrown by Callback on unimplemented and unknown callbacks from Google.
|
35
|
+
class UnknownCallbackType < Exception
|
36
|
+
end
|
37
|
+
|
38
|
+
# This class expects the message sent by Google. It parses the XMl document and returns
|
39
|
+
# the appropriate callback. If the callback sent by Google is invalid then a
|
40
|
+
# UnknownCallbackType is raised that you should catch and then send a 404 to Google
|
41
|
+
# to indicate that the callback handler has not been implemented yet.
|
42
|
+
#
|
43
|
+
# See http://code.google.com/apis/checkout/developer/index.html#merchant_calculations_api for
|
44
|
+
# details.
|
45
|
+
#
|
46
|
+
# Note that you must protect the HTTPS request to the piece of code using a
|
47
|
+
# CallbackHandler by HTTP Auth Basic. If you are using Ruby On Rails then you can
|
48
|
+
# use the great "simple_http_auth" plugin you can find here:
|
49
|
+
# http://blog.codahale.com/2006/05/11/basic-http-authentication-with-rails-simple_http_auth/
|
50
|
+
#
|
51
|
+
# === Usage Example
|
52
|
+
#
|
53
|
+
# When you use a Rails controller to handle the calbacks by Google then your action to handle
|
54
|
+
# the callbacks could use a CallbackHandler as follows:
|
55
|
+
#
|
56
|
+
# def google_checkout_api
|
57
|
+
# frontend = Google4R::Checkout::Frontend.new(FRONTEND_CONFIGURATION)
|
58
|
+
# frontend.tax_table_factory = TaxTableFactory.new
|
59
|
+
# handler = frontend.create_callback_handler
|
60
|
+
#
|
61
|
+
# begin
|
62
|
+
# callback = handler.handle(request.raw_post) # raw_post contains the XML
|
63
|
+
# rescue Google4R::Checkout::UnknownCallbackType => e
|
64
|
+
# # This can happen if Google adds new commands and Google4R has not been
|
65
|
+
# # upgraded yet. It is not fatal.
|
66
|
+
# render :text => 'ignoring unknown callback type', :status => 200
|
67
|
+
# return
|
68
|
+
# end
|
69
|
+
#
|
70
|
+
# # ...
|
71
|
+
# end
|
72
|
+
class CallbackHandler
|
73
|
+
# The Frontend object that created this CallbackHandler
|
74
|
+
attr_accessor :frontend
|
75
|
+
|
76
|
+
# Create a new CallbackHandler and assign value of the parameter frontend to
|
77
|
+
# the frontend attribute.
|
78
|
+
def initialize(frontend)
|
79
|
+
@frontend = frontend
|
80
|
+
end
|
81
|
+
|
82
|
+
# Parses the given xml_str and returns the appropriate *Callback class. At the
|
83
|
+
# moment, only MerchantCalculationCallback objects can be returned.
|
84
|
+
def handle(xml_str)
|
85
|
+
root = REXML::Document.new(xml_str).root
|
86
|
+
|
87
|
+
case root.name
|
88
|
+
when 'merchant-calculation-callback' then
|
89
|
+
MerchantCalculationCallback.create_from_element(root, frontend)
|
90
|
+
else
|
91
|
+
raise UnknownCallbackType, "Unknown callback type: #{root.name}"
|
92
|
+
end
|
93
|
+
end
|
94
|
+
end
|
95
|
+
|
96
|
+
# Google Checkout send a <merchant-calculation-callback> message to you when any of the
|
97
|
+
# events occur:
|
98
|
+
# The customer signs in to Google Checkout.
|
99
|
+
# The customer enters a new shipping address on the Place Order page.
|
100
|
+
# The customer enters a coupon or gift certificate code.
|
101
|
+
#
|
102
|
+
# The message will be parsed into a MerchantCalculationCallback instance.
|
103
|
+
#
|
104
|
+
class MerchantCalculationCallback
|
105
|
+
# The frontend this callback belongs to.
|
106
|
+
attr_accessor :frontend
|
107
|
+
|
108
|
+
# The order's shopping cart (ShoppingCart)
|
109
|
+
attr_accessor :shopping_cart
|
110
|
+
|
111
|
+
# The buyer's language
|
112
|
+
attr_accessor :buyer_language
|
113
|
+
|
114
|
+
# An array of AnonymousAddress objects of this callback.
|
115
|
+
attr_reader :anonymous_addresses
|
116
|
+
|
117
|
+
# This indicates whether the merchant needs to calculate taxes for the order.
|
118
|
+
attr_accessor :tax
|
119
|
+
|
120
|
+
# An array of shipping method names
|
121
|
+
attr_reader :shipping_methods
|
122
|
+
|
123
|
+
# An array of merchant codes
|
124
|
+
attr_reader :merchant_code_strings
|
125
|
+
|
126
|
+
# Sets the frontend attribute to the value of the frontend parameter.
|
127
|
+
def initialize(frontend)
|
128
|
+
@frontend = frontend
|
129
|
+
@anonymous_addresses = Array.new
|
130
|
+
@shipping_methods = Array.new
|
131
|
+
@merchant_code_strings = Array.new
|
132
|
+
end
|
133
|
+
|
134
|
+
# Factory method to create a new MerchantCalculationCallback object from
|
135
|
+
# the REXML:Element object
|
136
|
+
#
|
137
|
+
# Raises NoMethodError and RuntimeError exceptions if the given element misses required
|
138
|
+
# elements.
|
139
|
+
#
|
140
|
+
# You have to pass in the Frontend class this callback belongs to.
|
141
|
+
def self.create_from_element(element, frontend)
|
142
|
+
result = MerchantCalculationCallback.new(frontend)
|
143
|
+
|
144
|
+
result.shopping_cart = ShoppingCart.create_from_element(element.elements['shopping-cart'], result)
|
145
|
+
result.buyer_language = element.elements['buyer-language'].text
|
146
|
+
element.elements.each('calculate/addresses/anonymous-address') do |address_element|
|
147
|
+
result.anonymous_addresses << AnonymousAddress.create_from_element(address_element)
|
148
|
+
end
|
149
|
+
result.tax = element.elements['calculate/tax'].text
|
150
|
+
element.elements.each('calculate/shipping/method') do |shipping_method_element|
|
151
|
+
result.shipping_methods << shipping_method_element.attributes['name']
|
152
|
+
end
|
153
|
+
element.elements.each('calculate/merchant-code-strings/merchant-code-string') do |merchant_code_string_element|
|
154
|
+
result.merchant_code_strings << merchant_code_string_element.attributes['code']
|
155
|
+
end
|
156
|
+
|
157
|
+
return result
|
158
|
+
end
|
159
|
+
end
|
160
|
+
|
161
|
+
# This class represents a merchant-calculation-results XML
|
162
|
+
#
|
163
|
+
# === Usage Sample
|
164
|
+
#
|
165
|
+
# results = MerchantCalculationResults.new
|
166
|
+
# coupon_result = CouponResult.new(true, 'FirstVisitCoupon', Money.new(500, 'USD'), 'Congratulations! You saved $5.00 on your first visit!')
|
167
|
+
# gift_certificate_result = GiftCertificateResult.new(true, 'GiftCert012345', Money.new(1000, 'USD'), 'You used your Gift Certificate!')
|
168
|
+
#
|
169
|
+
# results.create_merchant_calculation_result do |result|
|
170
|
+
# result.shipping_name = 'SuperShip'
|
171
|
+
# result.address_id = '739030698069958'
|
172
|
+
# result.shipping_rate = Money.new(703, 'USD')
|
173
|
+
# result.shippable = true
|
174
|
+
# result.total_tax = Money.new(1467, 'USD')
|
175
|
+
# result.create_merchant_code_result(@coupon_result)
|
176
|
+
# result.create_merchant_code_result(@gift_certificate_result)
|
177
|
+
# end
|
178
|
+
#
|
179
|
+
# results.create_merchant_calculation_result do |result|
|
180
|
+
# result.shipping_name = 'UPS Ground'
|
181
|
+
# result.address_id = '739030698069958'
|
182
|
+
# result.shipping_rate = Money.new(556, 'USD')
|
183
|
+
# result.shippable = true
|
184
|
+
# result.total_tax = Money.new(1467, 'USD')
|
185
|
+
# result.create_merchant_code_result(@coupon_result)
|
186
|
+
# result.create_merchant_code_result(@gift_certificate_result)
|
187
|
+
# end
|
188
|
+
#
|
189
|
+
# results.to_xml # To create the XML to return to Google
|
190
|
+
#
|
191
|
+
class MerchantCalculationResults
|
192
|
+
# An array of merchant calcuation results
|
193
|
+
attr_reader :merchant_calculation_results
|
194
|
+
|
195
|
+
def initialize()
|
196
|
+
@merchant_calculation_results = Array.new
|
197
|
+
end
|
198
|
+
|
199
|
+
# This method takes a MerchantCalculationResult object and add it to the
|
200
|
+
# merchant_calculation_results array. If the object is not provided, it will
|
201
|
+
# instantiate one and add it to the array. An optional code block can be
|
202
|
+
# supplied to set the attributes of the new MerchantCalculationResult object.
|
203
|
+
#
|
204
|
+
# Raises RuntimeError exceptions if the given object is not of type
|
205
|
+
# MerchantCalculationResult.
|
206
|
+
def create_merchant_calculation_result(result=nil, &block)
|
207
|
+
if result.nil?
|
208
|
+
result = MerchantCalculationResult.new
|
209
|
+
# Pass the newly generated item to the given block to set its attributes.
|
210
|
+
yield(result) if block_given?
|
211
|
+
else
|
212
|
+
raise "Not a MerchantCalculationResult!" unless result.kind_of?(MerchantCalculationResult)
|
213
|
+
end
|
214
|
+
@merchant_calculation_results << result
|
215
|
+
end
|
216
|
+
|
217
|
+
def to_xml()
|
218
|
+
return MerchantCalculationResultsXmlGenerator.new(self).generate()
|
219
|
+
end
|
220
|
+
end
|
221
|
+
|
222
|
+
# The class represnts a merchant-calculation-result in the merchant-calculation-results XML
|
223
|
+
class MerchantCalculationResult
|
224
|
+
# The shipping name (string)
|
225
|
+
attr_accessor :shipping_name
|
226
|
+
|
227
|
+
# The address id (string)
|
228
|
+
attr_accessor :address_id
|
229
|
+
|
230
|
+
# The shipping rate (Money)
|
231
|
+
attr_accessor :shipping_rate
|
232
|
+
|
233
|
+
# Is it this applicable to this order (boolean)
|
234
|
+
attr_accessor :shippable
|
235
|
+
|
236
|
+
# The total tax (Money)
|
237
|
+
attr_accessor :total_tax
|
238
|
+
|
239
|
+
# An array of merchant code results
|
240
|
+
attr_reader :merchant_code_results
|
241
|
+
|
242
|
+
def initialize(shipping_name='', address_id='', shipping_rate=nil, shippable=false, total_tax=nil)
|
243
|
+
@shipping_name = shipping_name
|
244
|
+
@address_id = address_id
|
245
|
+
@shipping_rate = shipping_rate
|
246
|
+
@shippable = shippable
|
247
|
+
@total_tax = total_tax
|
248
|
+
@merchant_code_results = Array.new
|
249
|
+
end
|
250
|
+
|
251
|
+
# This method takes either a CouponResult or GiftCertificateResult object and
|
252
|
+
# add it to the merchant_code_results array. If the Class object of either
|
253
|
+
# the two types is provided, it will create an instance from the Class object.
|
254
|
+
# An optional code block can be supplied to set the attributes of the new
|
255
|
+
# object.
|
256
|
+
#
|
257
|
+
# Raises RuntimeError exceptions if there is no argument or a wrong class
|
258
|
+
# type is provided.
|
259
|
+
def create_merchant_code_result(result=nil, &block)
|
260
|
+
if !result.nil?
|
261
|
+
if [ CouponResult, GiftCertificateResult ].include?(result) # is a Class object
|
262
|
+
result = result.new
|
263
|
+
else
|
264
|
+
raise "Invalid Merchant Code Result class type: #{result.class}!" unless
|
265
|
+
(result.kind_of?(CouponResult) || result.kind_of?(GiftCertificateResult))
|
266
|
+
end
|
267
|
+
else
|
268
|
+
raise "You must either provide a MerchantCodeResult Class type or a CoupleResult or GiftCertificateResult instance."
|
269
|
+
end
|
270
|
+
@merchant_code_results << result
|
271
|
+
|
272
|
+
# Pass the newly generated item to the given block to set its attributes.
|
273
|
+
yield(result) if block_given?
|
274
|
+
|
275
|
+
end
|
276
|
+
end
|
277
|
+
|
278
|
+
# Base class for merchant code (coupon and gift certificate)
|
279
|
+
class CodeResult
|
280
|
+
# Is this valid (boolean)
|
281
|
+
attr_accessor :valid
|
282
|
+
|
283
|
+
# The code (string)
|
284
|
+
attr_accessor :code
|
285
|
+
|
286
|
+
# The calculated amount (Money)
|
287
|
+
attr_accessor :calculated_amount
|
288
|
+
|
289
|
+
# The message (string)
|
290
|
+
attr_accessor :message
|
291
|
+
|
292
|
+
def initialize()
|
293
|
+
raise "Do not use the abstract class Google::Checkout::CodeReslt"
|
294
|
+
end
|
295
|
+
end
|
296
|
+
|
297
|
+
# This class represents a coupon-result in the merchant-calculation-results XML
|
298
|
+
class CouponResult < CodeResult
|
299
|
+
def initialize(valid=false, code='', calculated_amount=nil, message='')
|
300
|
+
@valid = valid
|
301
|
+
@code = code
|
302
|
+
@calculated_amount = calculated_amount
|
303
|
+
@message = message
|
304
|
+
end
|
305
|
+
end
|
306
|
+
|
307
|
+
# This class represents a gift-certificate-result in the merchant-calculation-results XML
|
308
|
+
class GiftCertificateResult < CodeResult
|
309
|
+
def initialize(valid=false, code='', calculated_amount=nil, message='')
|
310
|
+
@valid = valid
|
311
|
+
@code = code
|
312
|
+
@calculated_amount = calculated_amount
|
313
|
+
@message = message
|
314
|
+
end
|
315
|
+
end
|
316
|
+
end
|
317
|
+
end
|
@@ -583,62 +583,6 @@ module Google4R #:nodoc:
|
|
583
583
|
DELIVERED = "DELIVERED".freeze
|
584
584
|
WILL_NOT_DELIVER = "WILL_NOT_DELIVER".freeze
|
585
585
|
end
|
586
|
-
|
587
|
-
# Address instances are used in NewOrderNotification objects for the buyer's billing
|
588
|
-
# and buyer's shipping address.
|
589
|
-
class Address
|
590
|
-
# Contact name (String, optional).
|
591
|
-
attr_accessor :contact_name
|
592
|
-
|
593
|
-
# Second Address line (String).
|
594
|
-
attr_accessor :address1
|
595
|
-
|
596
|
-
# Second Address line (String optional).
|
597
|
-
attr_accessor :address2
|
598
|
-
|
599
|
-
# The buyer's city name (String).
|
600
|
-
attr_accessor :city
|
601
|
-
|
602
|
-
# The buyer's company name (String; optional).
|
603
|
-
attr_accessor :company_name
|
604
|
-
|
605
|
-
# The buyer's country code (String, 2 chars, ISO 3166).
|
606
|
-
attr_accessor :country_code
|
607
|
-
|
608
|
-
# The buyer's email address (String; optional).
|
609
|
-
attr_accessor :email
|
610
|
-
|
611
|
-
# The buyer's phone number (String; optional).
|
612
|
-
attr_accessor :fax
|
613
|
-
|
614
|
-
# The buyer's phone number (String; Optional, can be enforced in CheckoutCommand).)
|
615
|
-
attr_accessor :phone
|
616
|
-
|
617
|
-
# The buyers postal/zip code (String).
|
618
|
-
attr_accessor :postal_code
|
619
|
-
|
620
|
-
# The buyer's geographical region (String).
|
621
|
-
attr_accessor :region
|
622
|
-
|
623
|
-
# Creates a new Address from the given REXML::Element instance.
|
624
|
-
def self.create_from_element(element)
|
625
|
-
result = Address.new
|
626
|
-
|
627
|
-
result.address1 = element.elements['address1'].text
|
628
|
-
result.address2 = element.elements['address2'].text rescue nil
|
629
|
-
result.city = element.elements['city'].text
|
630
|
-
result.company_name = element.elements['company-name'].text rescue nil
|
631
|
-
result.contact_name = element.elements['contact-name'].text rescue nil
|
632
|
-
result.country_code = element.elements['country-code'].text
|
633
|
-
result.email = element.elements['email'].text rescue nil
|
634
|
-
result.fax = element.elements['fax'].text rescue nil
|
635
|
-
result.phone = element.elements['phone'].text rescue nil
|
636
|
-
result.postal_code = element.elements['postal-code'].text
|
637
|
-
result.region = element.elements['region'].text
|
638
|
-
|
639
|
-
return result
|
640
|
-
end
|
641
|
-
end
|
642
586
|
|
643
587
|
# The marketing preferences of a customer.
|
644
588
|
class MarketingPreferences
|