vizjerai-google-checkout 0.0.5

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 (67) hide show
  1. data/History.txt +14 -0
  2. data/MIT-LICENSE.txt +23 -0
  3. data/README.txt +143 -0
  4. data/Rakefile +34 -0
  5. data/VERSION.yml +4 -0
  6. data/examples/google_notifications_controller.rb +159 -0
  7. data/lib/duck_punches/hpricot.rb +24 -0
  8. data/lib/google-checkout/cart.rb +304 -0
  9. data/lib/google-checkout/command.rb +255 -0
  10. data/lib/google-checkout/geography/area.rb +11 -0
  11. data/lib/google-checkout/geography/postal.rb +26 -0
  12. data/lib/google-checkout/geography/us_country.rb +24 -0
  13. data/lib/google-checkout/geography/us_state.rb +22 -0
  14. data/lib/google-checkout/geography/us_zip.rb +22 -0
  15. data/lib/google-checkout/geography/world.rb +12 -0
  16. data/lib/google-checkout/geography.rb +7 -0
  17. data/lib/google-checkout/merchant_calculation.rb +30 -0
  18. data/lib/google-checkout/notification.rb +352 -0
  19. data/lib/google-checkout/shipping/filters.rb +32 -0
  20. data/lib/google-checkout/shipping/flat_rate.rb +26 -0
  21. data/lib/google-checkout/shipping/merchant_calculated.rb +29 -0
  22. data/lib/google-checkout/shipping/method.rb +11 -0
  23. data/lib/google-checkout/shipping/pickup.rb +22 -0
  24. data/lib/google-checkout/shipping/restrictions.rb +32 -0
  25. data/lib/google-checkout/shipping.rb +8 -0
  26. data/lib/google-checkout.rb +65 -0
  27. data/spec/fixtures/google/checkout-shopping-cart.xml +22 -0
  28. data/spec/fixtures/google/commands/add-merchant-order-number.xml +5 -0
  29. data/spec/fixtures/google/commands/add-tracking-data.xml +8 -0
  30. data/spec/fixtures/google/commands/archive-order.xml +3 -0
  31. data/spec/fixtures/google/commands/authorize-order.xml +2 -0
  32. data/spec/fixtures/google/commands/cancel-order.xml +5 -0
  33. data/spec/fixtures/google/commands/charge-order.xml +4 -0
  34. data/spec/fixtures/google/commands/deliver-order.xml +9 -0
  35. data/spec/fixtures/google/commands/process-order.xml +2 -0
  36. data/spec/fixtures/google/commands/refund-order.xml +6 -0
  37. data/spec/fixtures/google/commands/send-buyer-message.xml +7 -0
  38. data/spec/fixtures/google/commands/unarchive-order.xml +2 -0
  39. data/spec/fixtures/google/merchant_calculations/shipping.xml +40 -0
  40. data/spec/fixtures/google/notifications/authorization-amount-notification.xml +10 -0
  41. data/spec/fixtures/google/notifications/charge-amount-notification.xml +8 -0
  42. data/spec/fixtures/google/notifications/chargeback-amount-notification.xml +8 -0
  43. data/spec/fixtures/google/notifications/new-order-notification.xml +94 -0
  44. data/spec/fixtures/google/notifications/order-state-change-notification.xml +11 -0
  45. data/spec/fixtures/google/notifications/refund-amount-notification.xml +8 -0
  46. data/spec/fixtures/google/notifications/risk-information-notification.xml +23 -0
  47. data/spec/fixtures/google/responses/checkout-redirect.xml +5 -0
  48. data/spec/fixtures/google/responses/error-charged.xml +5 -0
  49. data/spec/fixtures/google/responses/error.xml +5 -0
  50. data/spec/fixtures/google/responses/request-received.xml +3 -0
  51. data/spec/google-checkout/cart_spec.rb +110 -0
  52. data/spec/google-checkout/command_spec.rb +216 -0
  53. data/spec/google-checkout/geography/postal_spec.rb +26 -0
  54. data/spec/google-checkout/geography/us_country_spec.rb +26 -0
  55. data/spec/google-checkout/geography/us_state_spec.rb +11 -0
  56. data/spec/google-checkout/geography/us_zip_spec.rb +11 -0
  57. data/spec/google-checkout/geography/world_spec.rb +12 -0
  58. data/spec/google-checkout/merchant_calculation_spec.rb +17 -0
  59. data/spec/google-checkout/notification_spec.rb +253 -0
  60. data/spec/google-checkout/response_spec.rb +49 -0
  61. data/spec/google-checkout/shipping/flat_rate_spec.rb +46 -0
  62. data/spec/google-checkout/shipping/merchant_calculated_spec.rb +70 -0
  63. data/spec/google-checkout/shipping/pickup_spec.rb +22 -0
  64. data/spec/google-checkout_spec.rb +15 -0
  65. data/spec/spec_helper.rb +47 -0
  66. data/support/cacert.pem +7815 -0
  67. metadata +145 -0
data/History.txt ADDED
@@ -0,0 +1,14 @@
1
+ == 0.2.0 / 2007-08-14
2
+
3
+ * Significant rewrite!
4
+ * Added rSpec specifications.
5
+ * Added level 2 integration for sending and
6
+ and parsing notifications from Google.
7
+ * Shipping temporarily hard-coded to
8
+ "Digital Download"
9
+ * Added merchant-private-data for sending
10
+ one's own tracking number to Google.
11
+ * Defaults to live system but you can call
12
+ GoogleCheckout.use_sandbox to use the
13
+ sandbox instead.
14
+ * Fixtures for Google commands and notifications.
data/MIT-LICENSE.txt ADDED
@@ -0,0 +1,23 @@
1
+ (The MIT License)
2
+
3
+ Copyright (c) 2006-2008 Peter Elmore (pete.elmore at gmail.com) and Topfunky Corporation
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining
6
+ a copy of this software and associated documentation files (the
7
+ 'Software'), to deal in the Software without restriction, including
8
+ without limitation the rights to use, copy, modify, merge, publish,
9
+ distribute, sublicense, and/or sell copies of the Software, and to
10
+ permit persons to whom the Software is furnished to do so, subject to
11
+ the following conditions:
12
+
13
+ The above copyright notice and this permission notice shall be
14
+ included in all copies or substantial portions of the Software.
15
+
16
+ THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,
17
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
19
+ IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
20
+ CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
21
+ TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
22
+ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
23
+
data/README.txt ADDED
@@ -0,0 +1,143 @@
1
+ google-checkout
2
+ by Peter Elmore and Geoffrey Grosenbach
3
+ http://rubyforge.org/projects/google-checkout
4
+
5
+ == DESCRIPTION:
6
+
7
+ Experimental library for working with GoogleCheckout. Currently in use for
8
+ payment at http://peepcode.com.
9
+
10
+ == Installation
11
+
12
+ sudo gem install google-checkout
13
+
14
+ Or straight from the source at
15
+
16
+ sudo gem install topfunky-google-checkout --source http://gems.github.com
17
+
18
+ == What is Google Checkout?
19
+
20
+ Well, according to Google, "Google Checkout helps you increase sales. And
21
+ process them for free when you advertise with Google." What it really amounts
22
+ to is that Google will process your orders for a 10% fee and you get a little
23
+ shopping cart icon in your ad if you advertise through AdWords. The fee can
24
+ be paid by running AdWords ads on your site. You can read about it and get an
25
+ account at http://checkout.google.com/sell.
26
+
27
+ == What is google-checkout?
28
+
29
+ google-checkout is a module for working with the Google Checkout API
30
+ (http://code.google.com/apis/checkout/index.html). Specifically, if you have
31
+ a Google Checkout account, you can use this module to do things like add
32
+ "Checkout" and "Buy Now" buttons to your site.
33
+
34
+ == Brief Example
35
+
36
+ require 'rubygems'
37
+ require 'google-checkout'
38
+
39
+ merchant_id = 'Your merchant id.'
40
+ merchant_key = 'Your merchant key. Keep this a secret!'
41
+
42
+ cart = GoogleCheckout::Cart.new(merchant_id, merchant_key)
43
+ cart.add_item(:name => 'Chair', :description => 'A sturdy, wooden chair',
44
+ :price => 44.99)
45
+ puts cart.checkout_button
46
+
47
+ == Usage
48
+
49
+ First, you'll need a merchant ID and a merchant key, which you can get from
50
+ the Google Checkout site once you have an account. After you have that, you
51
+ can start writing code.
52
+
53
+ The class you'll be working with is GoogleCheckout::Cart. Of course, it
54
+ represents a cart, and you can fill it with items.
55
+
56
+ cart = GoogleCheckout::Cart.new(merchant_id, merchant_key, item1, item2)
57
+ cart.add_item item3
58
+
59
+ The items you put into the cart should be one of two types:
60
+ * A Hash containing the following
61
+ ** :name
62
+ ** :description
63
+ ** :price
64
+ ** :quantity (default 1)
65
+ ** :currency (default 'USD')
66
+ ** :regular_shipping, the shipping cost (default $0)
67
+ * Or any Object that has a method called to_google_product that returns a hash
68
+ like the one described.
69
+
70
+ Once you have a cart full of items, you can generate the XML for the API call
71
+ by calling Cart#checkout_xml, although you'll probably just want to add a
72
+ checkout button to your page with Cart#checkout_button. This method generates
73
+ HTML for a form containing a button and the hidden inputs necessary to call
74
+ Google Checkout. Cart#checkout_button has plenty of options for controlling
75
+ the look of the button. Once again, the arguments are passed as a hash,
76
+ although the defaults are usually reasonable so you might not need to pass
77
+ anything.
78
+
79
+ * :size is the size of the button, one of :small, :medium, or :large. Google
80
+ is picky about the sizes of these buttons. See GoogleCheckout::ButtonSizes
81
+ for more information. The default is :medium.
82
+ * :variant is one of 'disabled' or 'text'. 'disabled' means that the button
83
+ should be greyed-out; it is used in cases that the item you are selling
84
+ cannot be bought via Google Checkout. (There's a long list of items that
85
+ are not allowed at https://checkout.google.com/seller/content_policies.html
86
+ * :buy_or_checkout must be one of :buy_now or :checkout . This determines the
87
+ look of the button that will be displayed. The default is to use :checkout
88
+ if there are two or more items in the cart.
89
+ * :style must be one of 'white' or 'trans'. 'white' gets you a white button,
90
+ while 'trans' gets you a transparent button suitable for use on non-white
91
+ backgrounds. The default is 'white'.
92
+
93
+ cart.checkout_button :size => :small, :style => 'trans'
94
+
95
+ When users click the button, they will be taken to the Google Checkout page
96
+ with a cart full of the products you specified, and your work is done.
97
+
98
+ == Missing Features
99
+
100
+ * Level 1 integration is complete except for tax tables
101
+ * Level 2 integration has been partly implemented and is in use at http://peepcode.com.
102
+
103
+ See
104
+ http://checkout.google.com/support/sell/bin/answer.py?answer=42917&topic=8671
105
+ for more information about the two integration levels.
106
+
107
+ If there are missing features I haven't thought of, let me know.
108
+
109
+ == Bugs
110
+
111
+ No 'hard' bugs, I hope. Pete's contact information is at the bottom of the page if you find one. There may be more subjective bugs (e.g., design issues); feel free to tell me about these, too.
112
+
113
+ == Contact Information
114
+
115
+ The home page is at http://debu.gs/google-checkout . You can email me at pete
116
+ dot elmore at gmail dot com. Try to mention Google Checkout in the subject
117
+ line.
118
+
119
+ == LICENSE:
120
+
121
+ (The MIT License)
122
+
123
+ Copyright (c) 2006-2007 Peter Elmore (pete.elmore at gmail.com) and Topfunky Corporation
124
+
125
+ Permission is hereby granted, free of charge, to any person obtaining
126
+ a copy of this software and associated documentation files (the
127
+ 'Software'), to deal in the Software without restriction, including
128
+ without limitation the rights to use, copy, modify, merge, publish,
129
+ distribute, sublicense, and/or sell copies of the Software, and to
130
+ permit persons to whom the Software is furnished to do so, subject to
131
+ the following conditions:
132
+
133
+ The above copyright notice and this permission notice shall be
134
+ included in all copies or substantial portions of the Software.
135
+
136
+ THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,
137
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
138
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
139
+ IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
140
+ CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
141
+ TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
142
+ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
143
+
data/Rakefile ADDED
@@ -0,0 +1,34 @@
1
+ require 'rake'
2
+ require 'rake/rdoctask'
3
+ require 'spec/rake/spectask'
4
+
5
+ desc 'Run the specs'
6
+ Spec::Rake::SpecTask.new(:spec) do |t|
7
+ t.spec_opts = ['--colour --format progress --loadby mtime --reverse']
8
+ t.spec_files = FileList['spec/**/*_spec.rb']
9
+ end
10
+
11
+ Rake::RDocTask.new do |t|
12
+ t.rdoc_dir = 'doc'
13
+ t.rdoc_files.include('README')
14
+ t.rdoc_files.include('lib/**/*.rb')
15
+ t.options << '--inline-source'
16
+ t.options << '--all'
17
+ t.options << '--line-numbers'
18
+ end
19
+
20
+ begin
21
+ require 'jeweler'
22
+ Jeweler::Tasks.new do |s|
23
+ s.name = "google-checkout"
24
+ s.summary = "An experimental library for sending payment requests to Google Checkout."
25
+ s.email = "mattlins@gmail.com"
26
+ s.homepage = "http://github.com/mlins/google-checkout/"
27
+ s.description = "An experimental library for sending payment requests to Google Checkout."
28
+ s.authors = ["Peter Elmore", "Geoffrey Grosenbach", "Matt Lins"]
29
+ s.files = FileList["[A-Z]*", "{lib,spec,support,examples}/**/*"]
30
+ s.add_dependency 'ruby-hmac'
31
+ end
32
+ rescue LoadError
33
+ puts "Jeweler not available. Install it with: sudo gem install technicalpickles-jeweler -s http://gems.github.com"
34
+ end
data/VERSION.yml ADDED
@@ -0,0 +1,4 @@
1
+ ---
2
+ :major: 0
3
+ :minor: 0
4
+ :patch: 5
@@ -0,0 +1,159 @@
1
+ ##
2
+ # Skeleton for handing Level 2 notifications from GoogleCheckout with Rails.
3
+ #
4
+ # You'll need to write the individual handlers. SSL is required.
5
+ #
6
+ # SAMPLE ONLY! Modify for your own use. Extra error handling may be needed.
7
+
8
+ class GoogleNotificationsController < ApplicationController
9
+
10
+ before_filter :verify_access
11
+ after_filter :log_google_notification
12
+
13
+ ##
14
+ # Google calls this with notifications.
15
+
16
+ def create
17
+ @notification = GoogleCheckout::Notification.parse(request.raw_post)
18
+
19
+ case @notification
20
+ when GoogleCheckout::NewOrderNotification
21
+ handle_new_order_notification(@notification)
22
+
23
+ when GoogleCheckout::OrderStateChangeNotification
24
+ handle_order_state_change_notification(@notification)
25
+
26
+ when GoogleCheckout::RiskInformationNotification
27
+ handle_risk_information_notification(@notification)
28
+
29
+ when GoogleCheckout::ChargeAmountNotification
30
+ handle_charge_amount_notification(@notification)
31
+
32
+ when GoogleCheckout::AuthorizationAmountNotification
33
+ handle_authorization_amount_notification(@notification)
34
+
35
+ when GoogleCheckout::ChargebackAmountNotification
36
+ handle_chargeback_amount_notification(@notification)
37
+
38
+ when GoogleCheckout::RefundAmountNotification
39
+ handle_refund_amount_notification(@notification)
40
+ end
41
+
42
+ render :xml => @notification.acknowledgment_xml
43
+ end
44
+
45
+ private
46
+
47
+ ##
48
+ # Use basic authentication in my realm to get a user object.
49
+ # Since this is a security filter - return false if the user is not authenticated.
50
+
51
+ def verify_access
52
+ return false unless (request.ssl? || (RAILS_ENV == 'development') || (RAILS_ENV == 'test'))
53
+ authenticate_or_request_with_http_basic("PeepCode") do |merchant_id, merchant_key|
54
+ (merchant_id == GOOGLE_ID) && (merchant_key == GOOGLE_KEY)
55
+ end
56
+ end
57
+
58
+ ##
59
+ #
60
+
61
+ def log_google_notification
62
+ # TODO Write to your log or to a DB table
63
+ end
64
+
65
+ ##
66
+ #
67
+
68
+ def handle_new_order_notification(notification)
69
+ logger.info "Got NewOrderNotification"
70
+
71
+ # NOTE You should have passed your own order number to Google when
72
+ # making the initial order. Subsequent notifications will use
73
+ # Google's order number instead.
74
+ @order = Order.find_by_order_number(notification.my_order_number)
75
+ if @order
76
+ # NOTE You may want to check the amount being charged vs. the amount
77
+ # you expected the user to pay.
78
+
79
+ @order.google_order_number = notification.google_order_number
80
+ @order.email = notification.email
81
+
82
+ # Fee is 20 cents plus 2% of total.
83
+ @order.fee_cents = (20 + (notification.order_total.cents * 0.02)).round
84
+ @order.gross_cents = notification.order_total.cents
85
+ @order.net_cents = @order.gross_cents - @order.fee_cents
86
+
87
+ # NOTE Also of interest is notification.email_allowed, a boolean
88
+ @order.save
89
+ @order.new_order!
90
+ end
91
+ end
92
+
93
+ ##
94
+ #
95
+
96
+ def handle_order_state_change_notification(notification)
97
+ @order = Order.find_for_notification(notification)
98
+ @order.update_attribute(:google_state, notification.state)
99
+
100
+ case notification.state
101
+ when "REVIEWING" # Initial state of orders. Rarely seen by client.
102
+
103
+ when "CHARGEABLE" # You can now charge the customer for the order.
104
+ @order.chargeable!
105
+ when "CHARGING" # Google is charging the customer.
106
+ @order.charging!
107
+ when "CHARGED" # You have charged the customer.
108
+ @order.charged!
109
+ when "PAYMENT_DECLINED" # Google was unable to charge the client
110
+ @order.denied!
111
+ when "CANCELLED" # Order was cancelled by the merchant
112
+ @order.denied!
113
+ @order.update_attribute(:payment_note, notification.reason) rescue nil
114
+ when "CANCELLED_BY_GOOGLE" # Order was cancelled by Google
115
+ @order.denied!
116
+ # notification.reason
117
+ end
118
+ end
119
+
120
+ ##
121
+ #
122
+
123
+ def handle_risk_information_notification(notification)
124
+ logger.info "Got RiskInformationNotification"
125
+
126
+ @order = Order.find_for_notification(notification)
127
+ @order.risk!
128
+
129
+ # TODO You need to ping Google after this to trigger the next state.
130
+ # Do this in the model, but for reference, here's the basic code.
131
+ if @order.google_state == "CHARGEABLE"
132
+ charge_order_command = GoogleCheckout::ChargeOrder.new(GOOGLE_ID, GOOGLE_KEY, @order.google_order_number)
133
+ # To string, to float in order to get a float representation of the money
134
+ charge_order_command.amount = total_price.to_s.to_f
135
+ # Will throw error on failure
136
+ notification = charge_order_command.post
137
+ else
138
+ logger.error("Order was not in CHARGEABLE state")
139
+ end
140
+ end
141
+
142
+ ##
143
+ #
144
+
145
+ def handle_charge_amount_notification(notification)
146
+ @order = Order.find_for_notification(notification)
147
+ @order.charge!
148
+ end
149
+
150
+ ##
151
+ #
152
+
153
+ def handle_refund_amount_notification(notification)
154
+ # NOTE Notification includes amount refunded.
155
+ @order = Order.find_for_notification(notification)
156
+ @order.refund!
157
+ end
158
+
159
+ end
@@ -0,0 +1,24 @@
1
+
2
+ class Hpricot::Elements
3
+
4
+ ##
5
+ # Assume a Google standard money node with a currency attribute.
6
+ #
7
+ # Returns a Ruby Money object.
8
+
9
+ def to_money
10
+ dollar_amount = inner_html
11
+ cents = (dollar_amount.to_f * 100).round
12
+ currency = first[:currency]
13
+ Money.new(cents, currency)
14
+ end
15
+
16
+ ##
17
+ # Return boolean true if the value of an element is the
18
+ # string 'true'.
19
+
20
+ def to_boolean
21
+ inner_html == 'true'
22
+ end
23
+
24
+ end