codehog-google-checkout 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.
- data/History.txt +25 -0
- data/Isolate +13 -0
- data/MIT-LICENSE.txt +23 -0
- data/Manifest.txt +42 -0
- data/README.txt +148 -0
- data/Rakefile +35 -0
- data/examples/google_notifications_controller.rb +159 -0
- data/lib/duck_punches/hpricot.rb +24 -0
- data/lib/google-checkout.rb +61 -0
- data/lib/google-checkout/cart.rb +357 -0
- data/lib/google-checkout/command.rb +191 -0
- data/lib/google-checkout/notification.rb +226 -0
- data/spec/fixtures/google/checkout-shopping-cart.xml +22 -0
- data/spec/fixtures/google/commands/add-merchant-order-number.xml +5 -0
- data/spec/fixtures/google/commands/add-tracking-data.xml +8 -0
- data/spec/fixtures/google/commands/archive-order.xml +3 -0
- data/spec/fixtures/google/commands/authorize-order.xml +2 -0
- data/spec/fixtures/google/commands/cancel-order.xml +5 -0
- data/spec/fixtures/google/commands/charge-order.xml +4 -0
- data/spec/fixtures/google/commands/deliver-order.xml +9 -0
- data/spec/fixtures/google/commands/process-order.xml +2 -0
- data/spec/fixtures/google/commands/refund-order.xml +6 -0
- data/spec/fixtures/google/commands/send-buyer-message.xml +7 -0
- data/spec/fixtures/google/commands/unarchive-order.xml +2 -0
- data/spec/fixtures/google/notifications/authorization-amount-notification.xml +10 -0
- data/spec/fixtures/google/notifications/charge-amount-notification.xml +8 -0
- data/spec/fixtures/google/notifications/chargeback-amount-notification.xml +8 -0
- data/spec/fixtures/google/notifications/new-order-notification.xml +85 -0
- data/spec/fixtures/google/notifications/order-state-change-notification.xml +11 -0
- data/spec/fixtures/google/notifications/refund-amount-notification.xml +8 -0
- data/spec/fixtures/google/notifications/risk-information-notification.xml +23 -0
- data/spec/fixtures/google/responses/checkout-redirect.xml +5 -0
- data/spec/fixtures/google/responses/error.xml +5 -0
- data/spec/fixtures/google/responses/request-received.xml +3 -0
- data/spec/google-checkout/cart_spec.rb +165 -0
- data/spec/google-checkout/command_spec.rb +131 -0
- data/spec/google-checkout/notification_spec.rb +181 -0
- data/spec/google-checkout/response_spec.rb +49 -0
- data/spec/google-checkout_spec.rb +15 -0
- data/spec/spec_helper.rb +47 -0
- data/support/cacert.pem +7815 -0
- metadata +203 -0
@@ -0,0 +1,226 @@
|
|
1
|
+
|
2
|
+
module GoogleCheckout
|
3
|
+
|
4
|
+
##
|
5
|
+
# Base notification class. Parses incoming XML and returns a class
|
6
|
+
# matching the kind of notification being received.
|
7
|
+
#
|
8
|
+
# This makes it easy to handle events in your code.
|
9
|
+
#
|
10
|
+
# notification = GoogleCheckout::Notification.parse(request.raw_post)
|
11
|
+
# case notification
|
12
|
+
# when GoogleCheckout::NewOrderNotification
|
13
|
+
# do_something_with_new_order
|
14
|
+
# end
|
15
|
+
#
|
16
|
+
# TODO Document field access and Nokogiri object access.
|
17
|
+
#
|
18
|
+
# For the details, see http://code.google.com/apis/checkout/developer/index.html
|
19
|
+
|
20
|
+
class Notification
|
21
|
+
|
22
|
+
# The Nokogiri XML document received from Google.
|
23
|
+
attr_accessor :doc
|
24
|
+
|
25
|
+
##
|
26
|
+
# The entry point for notifications.
|
27
|
+
#
|
28
|
+
# Returns a corresponding notification object based on
|
29
|
+
# the XML received.
|
30
|
+
|
31
|
+
def self.parse(raw_xml)
|
32
|
+
doc = Nokogiri::XML(raw_xml)
|
33
|
+
|
34
|
+
# Convert +request-received+ to +request_received+,
|
35
|
+
# then to a +RequestReceived+ object of the proper class
|
36
|
+
# which will be created and returned.
|
37
|
+
inflector_klass = Inflector rescue nil
|
38
|
+
if inflector_klass.nil?
|
39
|
+
inflector_klass = ActiveSupport::Inflector
|
40
|
+
end
|
41
|
+
const_name = inflector_klass.camelize(doc.root.name.gsub('-', '_'))
|
42
|
+
if GoogleCheckout.const_get(const_name)
|
43
|
+
return GoogleCheckout.const_get(const_name).new(doc)
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
def initialize(doc) # :nodoc:
|
48
|
+
@doc = doc
|
49
|
+
end
|
50
|
+
|
51
|
+
##
|
52
|
+
# Returns the financial-order-state (or new-financial-order-state).
|
53
|
+
#
|
54
|
+
# This is a shortcut since this state will be accessed frequently.
|
55
|
+
#
|
56
|
+
# The fulfillment-order-state (and variations) can be accessed
|
57
|
+
# with the more explicit syntax:
|
58
|
+
#
|
59
|
+
# notification.fulfillment_order_state
|
60
|
+
#
|
61
|
+
# The following is from http://code.google.com/apis/checkout/developer/index.html
|
62
|
+
#
|
63
|
+
# The <financial-order-state> tag identifies the financial status of an order. Valid values for this tag are:
|
64
|
+
#
|
65
|
+
# REVIEWING - Google Checkout is reviewing the order.
|
66
|
+
# CHARGEABLE - The order is ready to be charged.
|
67
|
+
# CHARGING - The order is being charged; you may not refund or cancel an
|
68
|
+
# order until is the charge is completed.
|
69
|
+
# CHARGED - The order has been successfully charged; if the order was
|
70
|
+
# only partially charged, the buyer's account page will
|
71
|
+
# reflect the partial charge.
|
72
|
+
# PAYMENT_DECLINED - The charge attempt failed.
|
73
|
+
# CANCELLED - The seller canceled the order; an order's financial state
|
74
|
+
# cannot be changed after the order is canceled.
|
75
|
+
# CANCELLED_BY_GOOGLE - Google canceled the order. Google may cancel
|
76
|
+
# orders due to a failed charge without a replacement credit
|
77
|
+
# card being provided within a set period of time or due to a
|
78
|
+
# failed risk check. If Google cancels an order, you will be
|
79
|
+
# notified of the reason the order was canceled in the <reason>
|
80
|
+
# tag of an <order-state-change-notification>.
|
81
|
+
#
|
82
|
+
# Please see the Order States section for more information about these states.
|
83
|
+
|
84
|
+
def state
|
85
|
+
if (@doc.at 'financial-order-state')
|
86
|
+
return (@doc/'financial-order-state').inner_html
|
87
|
+
elsif (@doc.at 'new-financial-order-state')
|
88
|
+
return (@doc/'new-financial-order-state').inner_html
|
89
|
+
end
|
90
|
+
end
|
91
|
+
|
92
|
+
##
|
93
|
+
# Returns the serial number from the root element.
|
94
|
+
|
95
|
+
def serial_number
|
96
|
+
doc.root['serial-number']
|
97
|
+
end
|
98
|
+
|
99
|
+
##
|
100
|
+
# Returns an XML string that can be sent back to Google to
|
101
|
+
# communicate successful receipt of the notification.
|
102
|
+
|
103
|
+
def acknowledgment_xml
|
104
|
+
xml = Builder::XmlMarkup.new
|
105
|
+
xml.instruct!
|
106
|
+
@xml = xml.tag!('notification-acknowledgment', {
|
107
|
+
:xmlns => "http://checkout.google.com/schema/2"
|
108
|
+
})
|
109
|
+
@xml
|
110
|
+
end
|
111
|
+
|
112
|
+
##
|
113
|
+
# Returns true if this is a GoogleCheckout::Error object.
|
114
|
+
|
115
|
+
def error?
|
116
|
+
self.class == GoogleCheckout::Error
|
117
|
+
end
|
118
|
+
|
119
|
+
##
|
120
|
+
# Take requests for an XML element and returns its value.
|
121
|
+
#
|
122
|
+
# notification.google_order_number
|
123
|
+
# => Returns value of '<google-order-number>'
|
124
|
+
#
|
125
|
+
# Because of how Nokogiri#at works, it will even dig into subtags
|
126
|
+
# and return the value of the first matching tag. For example,
|
127
|
+
# there is an +email+ field in +buyer-shipping-address+ and also
|
128
|
+
# in +buyer-billing-address+, but only the first will be returned.
|
129
|
+
#
|
130
|
+
# If you want to get at a value explicitly, use +notification.doc+
|
131
|
+
# and search the Nokogiri document manually.
|
132
|
+
|
133
|
+
def method_missing(method_name, *args)
|
134
|
+
element_name = method_name.to_s.gsub(/_/, '-')
|
135
|
+
if element = (@doc.at element_name)
|
136
|
+
if element.respond_to?(:inner_html)
|
137
|
+
return element.inner_html
|
138
|
+
end
|
139
|
+
end
|
140
|
+
super
|
141
|
+
end
|
142
|
+
|
143
|
+
end
|
144
|
+
|
145
|
+
class AuthorizationAmountNotification < Notification; end
|
146
|
+
|
147
|
+
class ChargeAmountNotification < Notification
|
148
|
+
|
149
|
+
def latest_charge_amount
|
150
|
+
(@doc/"latest-charge-amount").to_money
|
151
|
+
end
|
152
|
+
|
153
|
+
def total_charge_amount
|
154
|
+
(@doc/"total-charge-amount").to_money
|
155
|
+
end
|
156
|
+
|
157
|
+
end
|
158
|
+
|
159
|
+
class ChargebackAmountNotification < Notification
|
160
|
+
|
161
|
+
def latest_chargeback_amount
|
162
|
+
(@doc/"latest-chargeback-amount").to_money
|
163
|
+
end
|
164
|
+
|
165
|
+
def total_chargeback_amount
|
166
|
+
(@doc/"total-chargeback-amount").to_money
|
167
|
+
end
|
168
|
+
|
169
|
+
end
|
170
|
+
|
171
|
+
class NewOrderNotification < Notification
|
172
|
+
|
173
|
+
##
|
174
|
+
# Returns a Money object representing the total price of the order.
|
175
|
+
|
176
|
+
def order_total
|
177
|
+
(@doc/"order-total").to_money
|
178
|
+
end
|
179
|
+
|
180
|
+
##
|
181
|
+
# Returns a Money object representing the total tax added.
|
182
|
+
|
183
|
+
def total_tax
|
184
|
+
(@doc/"total-tax").to_money
|
185
|
+
end
|
186
|
+
|
187
|
+
##
|
188
|
+
# Returns true if the buyer wants to received marketing emails.
|
189
|
+
|
190
|
+
def email_allowed
|
191
|
+
(@doc/"buyer-marketing-preferences"/"email-allowed").to_boolean
|
192
|
+
end
|
193
|
+
|
194
|
+
end
|
195
|
+
|
196
|
+
class OrderStateChangeNotification < Notification; end
|
197
|
+
|
198
|
+
class RefundAmountNotification < Notification; end
|
199
|
+
|
200
|
+
class RiskInformationNotification < Notification; end
|
201
|
+
|
202
|
+
class CheckoutRedirect < Notification
|
203
|
+
|
204
|
+
##
|
205
|
+
# Returns redirect-url with ampersands escaped, as specified by Google API docs.
|
206
|
+
|
207
|
+
def redirect_url
|
208
|
+
(@doc/"redirect-url").inner_html.gsub(/&/, '&')
|
209
|
+
end
|
210
|
+
|
211
|
+
end
|
212
|
+
|
213
|
+
class Error < Notification
|
214
|
+
|
215
|
+
##
|
216
|
+
# Alias for +error_message+
|
217
|
+
|
218
|
+
def message
|
219
|
+
(@doc/'error-message').inner_html
|
220
|
+
end
|
221
|
+
|
222
|
+
end
|
223
|
+
|
224
|
+
class RequestReceived < Notification; end
|
225
|
+
|
226
|
+
end
|
@@ -0,0 +1,22 @@
|
|
1
|
+
<?xml version="1.0" encoding="UTF-8"?>
|
2
|
+
<checkout-shopping-cart xmlns="http://checkout.google.com/schema/2">
|
3
|
+
<shopping-cart>
|
4
|
+
<items>
|
5
|
+
<item>
|
6
|
+
<item-name>HelloWorld 2GB MP3 Player</item-name>
|
7
|
+
<item-description>HelloWorld, the simple MP3 player</item-description>
|
8
|
+
<unit-price currency="USD">159.99</unit-price>
|
9
|
+
<quantity>1</quantity>
|
10
|
+
</item>
|
11
|
+
</items>
|
12
|
+
</shopping-cart>
|
13
|
+
<checkout-flow-support>
|
14
|
+
<merchant-checkout-flow-support>
|
15
|
+
<shipping-methods>
|
16
|
+
<flat-rate-shipping name="SuperShip Ground">
|
17
|
+
<price currency="USD">9.99</price>
|
18
|
+
</flat-rate-shipping>
|
19
|
+
</shipping-methods>
|
20
|
+
</merchant-checkout-flow-support>
|
21
|
+
</checkout-flow-support>
|
22
|
+
</checkout-shopping-cart>
|
@@ -0,0 +1,8 @@
|
|
1
|
+
<?xml version="1.0" encoding="UTF-8"?>
|
2
|
+
<add-tracking-data xmlns="http://checkout.google.com/schema/2"
|
3
|
+
google-order-number="841171949013218">
|
4
|
+
<tracking-data>
|
5
|
+
<carrier>UPS</carrier>
|
6
|
+
<tracking-number>Z9842W69871281267</tracking-number>
|
7
|
+
</tracking-data>
|
8
|
+
</add-tracking-data>
|
@@ -0,0 +1,9 @@
|
|
1
|
+
<?xml version="1.0" encoding="UTF-8"?>
|
2
|
+
<deliver-order xmlns="http://checkout.google.com/schema/2"
|
3
|
+
google-order-number="841171949013218">
|
4
|
+
<tracking-data>
|
5
|
+
<carrier>UPS</carrier>
|
6
|
+
<tracking-number>Z5498W45987123684</tracking-number>
|
7
|
+
</tracking-data>
|
8
|
+
<send-email>false</send-email>
|
9
|
+
</deliver-order>
|
@@ -0,0 +1,6 @@
|
|
1
|
+
<?xml version="1.0" encoding="UTF-8"?>
|
2
|
+
<refund-order xmlns="http://checkout.google.com/schema/2" google-order-number="6014423719">
|
3
|
+
<amount currency="USD">15.00</amount>
|
4
|
+
<comment>Discount for inconvenience; ship replacement item</comment>
|
5
|
+
<reason>Damaged Merchandise</reason>
|
6
|
+
</refund-order>
|
@@ -0,0 +1,7 @@
|
|
1
|
+
<?xml version="1.0" encoding="UTF-8"?>
|
2
|
+
<send-buyer-message xmlns="http://checkout.google.com/schema/2"
|
3
|
+
google-order-number="841171949013218">
|
4
|
+
<message>Due to high volume, your order will ship
|
5
|
+
next week. Thank you for your patience.</message>
|
6
|
+
<send-email>true</send-email>
|
7
|
+
</send-buyer-message>
|
@@ -0,0 +1,10 @@
|
|
1
|
+
<?xml version="1.0" encoding="UTF-8"?>
|
2
|
+
<authorization-amount-notification xmlns="http://checkout.google.com/schema/2"
|
3
|
+
serial-number="bea6bc1b-e1e2-44fe-80ff-0180e33a2614">
|
4
|
+
<google-order-number>841171949013218</google-order-number>
|
5
|
+
<authorization-amount currency="USD">226.06</authorization-amount>
|
6
|
+
<authorization-expiration-date>2006-03-18T20:25:31</authorization-expiration-date>
|
7
|
+
<avs-response>Y</avs-response>
|
8
|
+
<cvn-response>Y</cvn-response>
|
9
|
+
<timestamp>2006-03-18T20:25:31</timestamp>
|
10
|
+
</authorization-amount-notification>
|
@@ -0,0 +1,8 @@
|
|
1
|
+
<?xml version="1.0" encoding="UTF-8"?>
|
2
|
+
<charge-amount-notification xmlns="http://checkout.google.com/schema/2"
|
3
|
+
serial-number="bea6bc1b-e1e2-44fe-80ff-0180e33a2614">
|
4
|
+
<google-order-number>841171949013218</google-order-number>
|
5
|
+
<latest-charge-amount currency="USD">226.06</latest-charge-amount>
|
6
|
+
<total-charge-amount currency="USD">226.06</total-charge-amount>
|
7
|
+
<timestamp>2006-03-18T18:25:31</timestamp>
|
8
|
+
</charge-amount-notification>
|
@@ -0,0 +1,8 @@
|
|
1
|
+
<?xml version="1.0" encoding="UTF-8"?>
|
2
|
+
<chargeback-amount-notification xmlns="http://checkout.google.com/schema/2"
|
3
|
+
serial-number="bea6bc1b-e1e2-44fe-80ff-0180e33a2614">
|
4
|
+
<google-order-number>841171949013218</google-order-number>
|
5
|
+
<latest-chargeback-amount currency="USD">226.06</latest-chargeback-amount>
|
6
|
+
<total-chargeback-amount currency="USD">226.06</total-chargeback-amount>
|
7
|
+
<timestamp>2006-03-18T20:25:31</timestamp>
|
8
|
+
</chargeback-amount-notification>
|
@@ -0,0 +1,85 @@
|
|
1
|
+
<?xml version="1.0" encoding="UTF-8"?>
|
2
|
+
<new-order-notification xmlns="http://checkout.google.com/schema/2"
|
3
|
+
serial-number="bea6bc1b-e1e2-44fe-80ff-0180e33a2614">
|
4
|
+
<google-order-number>841171949013218</google-order-number>
|
5
|
+
<buyer-shipping-address>
|
6
|
+
|
7
|
+
<contact-name>John Smith</contact-name>
|
8
|
+
<email>johnsmith@example.com</email>
|
9
|
+
<address1>10 Example Road</address1>
|
10
|
+
<city>Sampleville</city>
|
11
|
+
<region>CA</region>
|
12
|
+
<postal-code>94141</postal-code>
|
13
|
+
<country-code>US</country-code>
|
14
|
+
</buyer-shipping-address>
|
15
|
+
<buyer-billing-address>
|
16
|
+
<contact-name>Bill Hu</contact-name>
|
17
|
+
<email>billhu@example.com</email>
|
18
|
+
<address1>99 Credit Lane</address1>
|
19
|
+
<city>Mountain View</city>
|
20
|
+
<region>CA</region>
|
21
|
+
<postal-code>94043</postal-code>
|
22
|
+
<country-code>US</country-code>
|
23
|
+
</buyer-billing-address>
|
24
|
+
<buyer-id>294873009217523</buyer-id>
|
25
|
+
<fulfillment-order-state>NEW</fulfillment-order-state>
|
26
|
+
<financial-order-state>REVIEWING</financial-order-state>
|
27
|
+
|
28
|
+
<shopping-cart>
|
29
|
+
<cart-expiration>
|
30
|
+
<good-until-date>2007-12-31T23:59:59-05:00</good-until-date>
|
31
|
+
</cart-expiration>
|
32
|
+
<items>
|
33
|
+
<item>
|
34
|
+
<merchant-item-id>GGLAA1453</merchant-item-id>
|
35
|
+
<item-name>Dry Food Pack</item-name>
|
36
|
+
<item-description>One pack of nutritious dried food for emergencies.</item-description>
|
37
|
+
<quantity>1</quantity>
|
38
|
+
<tax-table-selector>food</tax-table-selector>
|
39
|
+
<unit-price currency="USD">4.99</unit-price>
|
40
|
+
</item>
|
41
|
+
<item>
|
42
|
+
<merchant-item-id>MGS2GBMP3</merchant-item-id>
|
43
|
+
<item-name>Megasound 2GB MP3 Player</item-name>
|
44
|
+
<item-description>This portable MP3 player stores 500 songs.</item-description>
|
45
|
+
<quantity>1</quantity>
|
46
|
+
<unit-price currency="USD">179.99</unit-price>
|
47
|
+
<merchant-private-item-data>
|
48
|
+
<merchant-product-id>1234567890</merchant-product-id>
|
49
|
+
</merchant-private-item-data>
|
50
|
+
</item>
|
51
|
+
</items>
|
52
|
+
<merchant-private-data>
|
53
|
+
<peepcode-order-number>1234-5678-9012</peepcode-order-number>
|
54
|
+
</merchant-private-data>
|
55
|
+
</shopping-cart>
|
56
|
+
<order-adjustment>
|
57
|
+
<merchant-calculation-successful>true</merchant-calculation-successful>
|
58
|
+
<merchant-codes>
|
59
|
+
<coupon-adjustment>
|
60
|
+
<applied-amount currency="USD">5.00</applied-amount>
|
61
|
+
<code>FirstVisitCoupon</code>
|
62
|
+
<calculated-amount currency="USD">5.00</calculated-amount>
|
63
|
+
<message>You saved $5.00 for your first visit!</message>
|
64
|
+
</coupon-adjustment>
|
65
|
+
<gift-certificate-adjustment>
|
66
|
+
<applied-amount currency="USD">10.00</applied-amount>
|
67
|
+
<code>GiftCert12345</code>
|
68
|
+
<calculated-amount currency="USD">10.00</calculated-amount>
|
69
|
+
<message>You saved $10.00 with this gift certificate!</message>
|
70
|
+
</gift-certificate-adjustment>
|
71
|
+
</merchant-codes>
|
72
|
+
<total-tax currency="USD">0.0</total-tax>
|
73
|
+
<shipping>
|
74
|
+
<merchant-calculated-shipping-adjustment>
|
75
|
+
<shipping-name>SuperShip</shipping-name>
|
76
|
+
<shipping-cost currency="USD">9.95</shipping-cost>
|
77
|
+
</merchant-calculated-shipping-adjustment>
|
78
|
+
</shipping>
|
79
|
+
</order-adjustment>
|
80
|
+
<order-total currency="USD">190.98</order-total>
|
81
|
+
<buyer-marketing-preferences>
|
82
|
+
<email-allowed>false</email-allowed>
|
83
|
+
</buyer-marketing-preferences>
|
84
|
+
<timestamp>2006-05-03T17:32:11</timestamp>
|
85
|
+
</new-order-notification>
|
@@ -0,0 +1,11 @@
|
|
1
|
+
<?xml version="1.0" encoding="UTF-8"?>
|
2
|
+
<order-state-change-notification xmlns="http://checkout.google.com/schema/2"
|
3
|
+
serial-number="bea6bc1b-e1e2-44fe-80ff-0180e33a2614">
|
4
|
+
<google-order-number>841171949013218</google-order-number>
|
5
|
+
<new-financial-order-state>CHARGING</new-financial-order-state>
|
6
|
+
<new-fulfillment-order-state>NEW</new-fulfillment-order-state>
|
7
|
+
<previous-financial-order-state>CHARGEABLE</previous-financial-order-state>
|
8
|
+
<previous-fulfillment-order-state>NEW</previous-fulfillment-order-state>
|
9
|
+
<reason>The reason goes here, if there is one.</reason>
|
10
|
+
<timestamp>2006-05-03T17:32:11</timestamp>
|
11
|
+
</order-state-change-notification>
|