harleytt-simplepay 0.2.2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (51) hide show
  1. data/History.txt +25 -0
  2. data/Manifest.txt +50 -0
  3. data/README.rdoc +127 -0
  4. data/Rakefile +25 -0
  5. data/lib/simplepay.rb +27 -0
  6. data/lib/simplepay/authentication.rb +41 -0
  7. data/lib/simplepay/constants.rb +64 -0
  8. data/lib/simplepay/errors.rb +16 -0
  9. data/lib/simplepay/helpers/form_helper.rb +29 -0
  10. data/lib/simplepay/helpers/notification_helper.rb +54 -0
  11. data/lib/simplepay/helpers/rails_helper.rb +40 -0
  12. data/lib/simplepay/rails.rb +9 -0
  13. data/lib/simplepay/service.rb +133 -0
  14. data/lib/simplepay/services/donation.rb +91 -0
  15. data/lib/simplepay/services/marketplace.rb +89 -0
  16. data/lib/simplepay/services/marketplace_policy.rb +54 -0
  17. data/lib/simplepay/services/standard.rb +58 -0
  18. data/lib/simplepay/services/subscription.rb +96 -0
  19. data/lib/simplepay/support.rb +16 -0
  20. data/lib/simplepay/support/amount.rb +55 -0
  21. data/lib/simplepay/support/billing_frequency.rb +14 -0
  22. data/lib/simplepay/support/boolean.rb +28 -0
  23. data/lib/simplepay/support/currency.rb +21 -0
  24. data/lib/simplepay/support/epoch.rb +39 -0
  25. data/lib/simplepay/support/field.rb +147 -0
  26. data/lib/simplepay/support/interval.rb +143 -0
  27. data/lib/simplepay/support/simple_amount.rb +37 -0
  28. data/lib/simplepay/support/subscription_period.rb +25 -0
  29. data/script/console +10 -0
  30. data/script/destroy +14 -0
  31. data/script/generate +14 -0
  32. data/simplepay.gemspec +41 -0
  33. data/test/simplepay/helpers/test_notifier.rb +32 -0
  34. data/test/simplepay/services/test_donation.rb +85 -0
  35. data/test/simplepay/services/test_marketplace.rb +85 -0
  36. data/test/simplepay/services/test_marketplace_policy.rb +52 -0
  37. data/test/simplepay/services/test_standard.rb +71 -0
  38. data/test/simplepay/services/test_subscription.rb +109 -0
  39. data/test/simplepay/support/test_amount.rb +46 -0
  40. data/test/simplepay/support/test_billing_frequency.rb +43 -0
  41. data/test/simplepay/support/test_boolean.rb +17 -0
  42. data/test/simplepay/support/test_epoch.rb +34 -0
  43. data/test/simplepay/support/test_field.rb +99 -0
  44. data/test/simplepay/support/test_interval.rb +92 -0
  45. data/test/simplepay/support/test_simple_amount.rb +28 -0
  46. data/test/simplepay/support/test_subscription_period.rb +49 -0
  47. data/test/simplepay/test_authentication.rb +25 -0
  48. data/test/simplepay/test_service.rb +118 -0
  49. data/test/test_helper.rb +87 -0
  50. data/test/test_simplepay.rb +11 -0
  51. metadata +184 -0
@@ -0,0 +1,25 @@
1
+ == 0.2.2 2009-06-07
2
+
3
+ * Added Donation service support.
4
+
5
+ == 0.2.1 2009-01-06
6
+
7
+ * Maintenance release for missing files.
8
+
9
+ == 0.2.0 2009-01-03
10
+
11
+ * Added Marketplace Service support [Nick Plante (zapnap)]
12
+ * Added Standard and Subscription documentation.
13
+ * Added a submit tag override to simplepay_form_for helper.
14
+ * Added a Simplepay::ResponseStatusCode::All shortcut.
15
+
16
+ == 0.1.1 2008-12-11
17
+
18
+ * Added a NotificationHelper to aid with Amazon IPN validation.
19
+ * Updated the Rails helper and added more detailed documentation.
20
+
21
+ == 0.1.0 2008-12-05
22
+
23
+ * Initial release
24
+ * Supports Amazon Simple Pay Standard and the-soon-to-be-released Subscriptions
25
+ * Generates your dynamic service HTML forms automatically.
@@ -0,0 +1,50 @@
1
+ History.txt
2
+ Manifest.txt
3
+ README.rdoc
4
+ Rakefile
5
+ lib/simplepay.rb
6
+ lib/simplepay/authentication.rb
7
+ lib/simplepay/constants.rb
8
+ lib/simplepay/errors.rb
9
+ lib/simplepay/helpers/form_helper.rb
10
+ lib/simplepay/helpers/notification_helper.rb
11
+ lib/simplepay/helpers/rails_helper.rb
12
+ lib/simplepay/rails.rb
13
+ lib/simplepay/service.rb
14
+ lib/simplepay/services/donation.rb
15
+ lib/simplepay/services/marketplace.rb
16
+ lib/simplepay/services/marketplace_policy.rb
17
+ lib/simplepay/services/standard.rb
18
+ lib/simplepay/services/subscription.rb
19
+ lib/simplepay/support.rb
20
+ lib/simplepay/support/amount.rb
21
+ lib/simplepay/support/billing_frequency.rb
22
+ lib/simplepay/support/boolean.rb
23
+ lib/simplepay/support/currency.rb
24
+ lib/simplepay/support/epoch.rb
25
+ lib/simplepay/support/field.rb
26
+ lib/simplepay/support/interval.rb
27
+ lib/simplepay/support/simple_amount.rb
28
+ lib/simplepay/support/subscription_period.rb
29
+ script/console
30
+ script/destroy
31
+ script/generate
32
+ simplepay.gemspec
33
+ test/simplepay/helpers/test_notifier.rb
34
+ test/simplepay/services/test_donation.rb
35
+ test/simplepay/services/test_marketplace.rb
36
+ test/simplepay/services/test_marketplace_policy.rb
37
+ test/simplepay/services/test_standard.rb
38
+ test/simplepay/services/test_subscription.rb
39
+ test/simplepay/support/test_amount.rb
40
+ test/simplepay/support/test_billing_frequency.rb
41
+ test/simplepay/support/test_boolean.rb
42
+ test/simplepay/support/test_epoch.rb
43
+ test/simplepay/support/test_field.rb
44
+ test/simplepay/support/test_interval.rb
45
+ test/simplepay/support/test_simple_amount.rb
46
+ test/simplepay/support/test_subscription_period.rb
47
+ test/simplepay/test_authentication.rb
48
+ test/simplepay/test_service.rb
49
+ test/test_helper.rb
50
+ test/test_simplepay.rb
@@ -0,0 +1,127 @@
1
+ = simplepay (Rails Amazon Simple Pay Interface)
2
+
3
+ http://simplepay.rubyforge.org
4
+
5
+ == DESCRIPTION:
6
+
7
+ This gem provides a Rails interface to the Amazon Simple Pay payment service.
8
+
9
+ == FEATURES/PROBLEMS:
10
+
11
+ Supports the following Amazon Simple Pay services:
12
+
13
+ * Standard
14
+ * Subscription
15
+ * Marketplace
16
+ * Donation
17
+
18
+ == SYNOPSIS:
19
+
20
+ Set up the gem requirement in your environment:
21
+
22
+ (in config/environment.rb)
23
+
24
+ config.gem "simplepay"
25
+
26
+ Configure the gem with your Amazon credentials:
27
+
28
+ (in config/initializers/simplepay.rb)
29
+
30
+ Simplepay.aws_access_key_id = 'MYAMAZONACCESSKEYID'
31
+ Simplepay.aws_secret_access_key = 'MYAMAZONSECRETACCESSKEY'
32
+ Simplepay.account_id = 'ACCOUNTIDFORAMAZONPAYMENTS'
33
+
34
+ Then, let Rails know about the Simplepay::Helpers:
35
+
36
+ (potentially in app/controllers/application[_controller].rb or really anywhere else)
37
+
38
+ require 'simplepay/rails'
39
+
40
+
41
+ === Generating your Simple Pay forms
42
+
43
+ Generally, this library will then be used directly from one (or more) of your
44
+ views. Depending on the type of Simple Pay service you're using (see
45
+ Simplepay::Services), some form values will be required, while others may be
46
+ optional. This is done like so:
47
+
48
+ <%= simplepay_form_for(:standard, {
49
+ :amount => 10.95,
50
+ :description => "Profit!"
51
+ }) %>
52
+
53
+ <%= simplepay_form_for(:subscription, {
54
+ :amount => 10.95,
55
+ :description => "MORE Profit!",
56
+ :recurring_frequency => "1 month"
57
+ }) %>
58
+
59
+
60
+ === Marketplace forms
61
+
62
+ Amazon Simple Pay Marketplace makes it easy to facilitate payments between
63
+ buyers and sellers, and to charge a fee for the transaction. If you're building
64
+ a marketplace application, your sellers must first agree to the policy that you
65
+ set. You can do this by specifying the Simplepay::Services::MarketplacePolicy
66
+ service:
67
+
68
+ <%= simplepay_form_for(:marketplace_policy, {
69
+ :max_fixed_fee => 5.00,
70
+ :max_variable_fee => 5,
71
+ :return_url => 'http://yourservice.com',
72
+ :reference_id => '1234567890'
73
+ }) %>
74
+
75
+ The user will be prompted to login to their Amazon account and accept the policy
76
+ you propose. After they complete the process, they'll be returned to the return_url
77
+ specified. Amazon will also provide a recipientEmail parameter that will contain
78
+ the seller email here (you may want to craft your return url so that it contains the
79
+ reference_id value and use this to 'acknowledge' a sellers consent and record their
80
+ Amazon recipient email address).
81
+
82
+ Only once this is done will you be able to offer marketplace checkout options for
83
+ that sellers items:
84
+
85
+ <%= simplepay_form_for(:marketplace, {
86
+ :amount => 34.95,
87
+ :description => "Mutual profit!",
88
+ :recipient_email => 'seller@gmail.com',
89
+ :fixed_marketplace_fee => 10.00,
90
+ :variable_marketplace_fee => 5
91
+ }) %>
92
+
93
+
94
+ == REQUIREMENTS:
95
+
96
+ 1. You must have an Amazon Payments <b>business account</b>.
97
+ 2. You must know your Amazon Payments <b>account identifier</b> [instructions to come]
98
+ 3. You must know your Amazon Web Services <b>access key</b> and <b>secret access key</b>.
99
+
100
+ == INSTALL:
101
+
102
+ sudo gem install simplepay
103
+
104
+ == LICENSE:
105
+
106
+ (The MIT License)
107
+
108
+ Copyright (c) 2008 Nathaniel E. Bibler
109
+
110
+ Permission is hereby granted, free of charge, to any person obtaining
111
+ a copy of this software and associated documentation files (the
112
+ 'Software'), to deal in the Software without restriction, including
113
+ without limitation the rights to use, copy, modify, merge, publish,
114
+ distribute, sublicense, and/or sell copies of the Software, and to
115
+ permit persons to whom the Software is furnished to do so, subject to
116
+ the following conditions:
117
+
118
+ The above copyright notice and this permission notice shall be
119
+ included in all copies or substantial portions of the Software.
120
+
121
+ THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,
122
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
123
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
124
+ IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
125
+ CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
126
+ TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
127
+ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
@@ -0,0 +1,25 @@
1
+ %w[rubygems rake rake/clean fileutils hoe newgem rubigen].each { |f| require f }
2
+ require File.dirname(__FILE__) + '/lib/simplepay'
3
+
4
+ $hoe = Hoe.new('simplepay', Simplepay::VERSION) do |p|
5
+ p.developer('Nathaniel E. Bibler', 'gem@nathanielbibler.com')
6
+ p.changes = p.paragraphs_of("History.txt", 0..1).join("\n\n")
7
+ p.rubyforge_name = p.name
8
+ p.extra_deps = [
9
+ ['activesupport','~> 2.3.9']
10
+ ]
11
+ p.extra_dev_deps = [
12
+ ['newgem', ">= #{::Newgem::VERSION}"]
13
+ ]
14
+
15
+ p.clean_globs |= %w[**/.DS_Store tmp *.log]
16
+ path = (p.rubyforge_name == p.name) ? p.rubyforge_name : "\#{p.rubyforge_name}/\#{p.name}"
17
+ p.remote_rdoc_dir = ''
18
+ p.rsync_args = '-av --delete --ignore-errors'
19
+ end
20
+
21
+ require 'newgem/tasks' # load /tasks/*.rake
22
+ Dir['tasks/**/*.rake'].each { |t| load t }
23
+
24
+ task :default => [:test]
25
+ task :release_and_update => [:gemspec, :release, :website, :post_news]
@@ -0,0 +1,27 @@
1
+ $:.unshift(File.dirname(__FILE__)) unless
2
+ $:.include?(File.dirname(__FILE__)) || $:.include?(File.expand_path(File.dirname(__FILE__)))
3
+
4
+ require 'active_support'
5
+
6
+ module Simplepay
7
+
8
+ VERSION = '0.2.2' unless const_defined?(:VERSION)
9
+
10
+ mattr_accessor :aws_access_key_id
11
+ mattr_accessor :aws_secret_access_key
12
+ mattr_accessor :account_id
13
+
14
+ mattr_accessor :use_sandbox
15
+ @@use_sandbox = true
16
+
17
+ def self.use_sandbox?
18
+ @@use_sandbox
19
+ end
20
+
21
+ end
22
+
23
+ require 'simplepay/constants'
24
+ require 'simplepay/support'
25
+ require 'simplepay/authentication'
26
+ require 'simplepay/service'
27
+ require 'simplepay/helpers/form_helper'
@@ -0,0 +1,41 @@
1
+ require 'openssl'
2
+ require 'base64'
3
+ require 'uri'
4
+ require 'cgi'
5
+
6
+ module Simplepay
7
+
8
+ class Signature
9
+
10
+ def initialize(uri, params, secret_key = Simplepay.aws_secret_access_key)
11
+ @uri = uri
12
+ @params = params
13
+ @secret_key = secret_key
14
+ end
15
+
16
+ def sign
17
+ make_canonical_string
18
+ compute_signature
19
+ end
20
+
21
+ private
22
+
23
+ def compute_signature
24
+ digest = OpenSSL::Digest::Digest.new('sha256')
25
+ Base64.encode64(OpenSSL::HMAC.digest(digest, @secret_key, @canonical)).chomp
26
+ end
27
+
28
+ def make_canonical_string
29
+ @canonical = "POST\n#{@uri.host}\n#{@uri.path}\n"
30
+ params = @params.reject{|k,v| v.blank? }.inject({}) { |a, (k,v)| a[k.to_s] = v; a }
31
+ params = params.sort.inject([]) { |a, v| a << urlencode(v[0]) + '=' + urlencode(v[1]) }.join('&')
32
+ @canonical += params
33
+ end
34
+
35
+ def urlencode(plaintext)
36
+ CGI.escape(plaintext.to_s).gsub('+', '%20').gsub('%7E', '~')
37
+ end
38
+
39
+ end
40
+
41
+ end
@@ -0,0 +1,64 @@
1
+ require 'simplepay/errors'
2
+ require 'simplepay/support/currency'
3
+
4
+ module Simplepay
5
+
6
+ module Boolean
7
+ True = '1'
8
+ False = '0'
9
+ end
10
+
11
+ module Interval
12
+ Day = 'day'
13
+ Week = 'week'
14
+ Month = 'month'
15
+ Year = 'year'
16
+ end
17
+
18
+ Intervals = [Interval::Day, Interval::Week, Interval::Month, Interval::Year]
19
+
20
+ ##
21
+ # Amazon Status Codes (FPS Basic)
22
+ # SA Success status for the ABT payment method.
23
+ # SB Success status for the ACH (bank account) payment method.
24
+ # SC Success status for the credit card payment method.
25
+ # SE System error.
26
+ # A Buyer abandoned the pipeline.
27
+ # CE Specifies a caller exception.
28
+ # PE Payment Method Mismatch Error: Specifies that the buyer does not have the payment method you requested.
29
+ # NP This account type does not support the specified payment method.
30
+ # NM You are not registered as a third-party caller to make this transaction. Contact Amazon Payments for more information.
31
+ #
32
+ module ResponseStatusCode
33
+ SuccessfulABT = 'SA'
34
+ SuccessfulACH = 'SB'
35
+ SuccessfulCC = 'SC'
36
+ Abandoned = 'A'
37
+ CallerException = 'CE'
38
+ PaymentMismatch = 'PE'
39
+ NotSupported = 'NP'
40
+ NotRegistered = 'NM'
41
+
42
+ # These haven't been verified so I'll leave them in for the time being
43
+ HtmlError = 'ME'
44
+ PaymentFailed = 'PF'
45
+ PaymentInitiated = 'PI'
46
+ PaymentReserved = 'PR'
47
+ PaymentSuccessful = 'PS'
48
+ SystemError = 'SE'
49
+ SubscriptionFailed = 'SF'
50
+ SubscriptionSuccessful = 'SS'
51
+
52
+ Successful = [SuccessfulABT, SuccessfulACH, SuccessfulCC, PaymentSuccessful, SubscriptionSuccessful]
53
+ Failure = [Abandoned, CallerException, PaymentMismatch, NotSupported, NotRegistered, HtmlError, PaymentFailed, SystemError, SubscriptionFailed]
54
+ Pending = [PaymentInitiated, PaymentReserved]
55
+ All = [Successful, Failure, Pending].flatten
56
+ end
57
+
58
+ module Currency
59
+ USD = Support::Currency.new('United States Dollar', 'USD', "%0.2f")
60
+ end
61
+
62
+ Currencies = [Currency::USD]
63
+
64
+ end
@@ -0,0 +1,16 @@
1
+ module Simplepay
2
+
3
+ ##
4
+ # All SimplePay errors will inherit from the base Simplepay::Error.
5
+ #
6
+ class Error < RuntimeError; end
7
+
8
+ #:stopdoc:
9
+
10
+ class RequiredFieldMissing < Error; end
11
+ class InvalidOptions < Error; end
12
+ class ParseError < Error; end
13
+
14
+ #:startdoc:
15
+
16
+ end
@@ -0,0 +1,29 @@
1
+ module Simplepay
2
+ module Helpers
3
+
4
+ module FormHelper
5
+
6
+ def self.tag(name, options = nil, open = false)
7
+ "<#{name}#{tag_options(options) if options}" + (open ? ">" : " />")
8
+ end
9
+
10
+ def self.content_tag(name, content, options = nil)
11
+ "<#{name}#{tag_options(options)}>#{content}</#{name}>"
12
+ end
13
+
14
+
15
+ private
16
+
17
+
18
+ def self.tag_options(options)
19
+ unless options.blank?
20
+ attrs = []
21
+ attrs = options.map { |key, value| %(#{key}="#{value}") }
22
+ " #{attrs.sort * ' '}" unless attrs.empty?
23
+ end
24
+ end
25
+
26
+ end
27
+
28
+ end
29
+ end
@@ -0,0 +1,54 @@
1
+ require 'cgi'
2
+ require 'open-uri'
3
+
4
+ module Simplepay
5
+ module Helpers
6
+
7
+ ##
8
+ # Adds a +valid_simplepay_request?+ method to your ActionControllers.
9
+ #
10
+ # In order to use this, you should just directly hand your +params+ into
11
+ # the method:
12
+ #
13
+ # class FooController < ApplicationController
14
+ #
15
+ # def receive_ipn
16
+ # if valid_simplepay_request?(params)
17
+ # ... record something useful ...
18
+ # else
19
+ # ... maybe log a bad request? ...
20
+ # end
21
+ # end
22
+ #
23
+ # end
24
+ #
25
+ module NotificationHelper
26
+
27
+ protected
28
+
29
+
30
+ ##
31
+ # Authenticates the incoming request by validating the +signature+
32
+ # provided.
33
+ #
34
+ # (from within your controller)
35
+ # def receive_ipn
36
+ # if valid_simplepay_request?(params)
37
+ # ...
38
+ # end
39
+ # end
40
+ #
41
+ def valid_simplepay_request?(endpoint, query)
42
+ url = Simplepay.use_sandbox ? 'https://fps.sandbox.amazonaws.com' : 'https://fps.amazonaws.com'
43
+ endpoint = CGI.escape(endpoint)
44
+ query = CGI.escape(query)
45
+
46
+ url_and_query = url + "/?Action=VerifySignature&Version=2008-09-17&UrlEndPoint=#{endpoint}&HttpParameters=#{query}"
47
+ result = open(url_and_query) rescue false
48
+ result.read =~ /Success/ ? true : false
49
+ end
50
+
51
+ end
52
+
53
+ end
54
+ end