bborn-simplepay 0.2.2

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 (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
data/History.txt ADDED
@@ -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.
data/Manifest.txt ADDED
@@ -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
data/README.rdoc ADDED
@@ -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.
data/Rakefile ADDED
@@ -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]
data/lib/simplepay.rb ADDED
@@ -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)
48
+ result.read =~ /Success/ ? true : false
49
+ end
50
+
51
+ end
52
+
53
+ end
54
+ end