paypal-brazil 3.0.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.
@@ -0,0 +1,5 @@
1
+ README.rdoc
2
+ lib/**/*.rb
3
+ bin/*
4
+ features/**/*.feature
5
+ LICENSE
@@ -0,0 +1,11 @@
1
+ *.sw?
2
+ .DS_Store
3
+ coverage
4
+ rdoc
5
+ pkg
6
+ ._*
7
+ *.orig
8
+ Thumbs.db
9
+ doc
10
+ .yardoc
11
+ .bundle
@@ -0,0 +1,75 @@
1
+ = 3.0.0 (git)
2
+
3
+ Update spec task to use the new RSpec module name
4
+ Remove constant/class variable usage and use Thread specific configurations
5
+ Start spec on Paypal::Helpers::Common.paypal_setup
6
+ Fix specs for Paypal::Config
7
+ Upgrade dev dependencies to use Rspec >= 2.0.0.a
8
+ Introduce a Paypal::Config module to handle ipn/certificates (Jonathan Tron)
9
+ Allow access to params as method (via method_missing) (Jonathan Tron)
10
+ Rework Paypal::Notification :
11
+ Remove methods to get params informations (CAUTION !!! THIS BREAK OLD API) (Jonathan Tron)
12
+ Add methods for all possible statuses and rename #complete? as completed? to follow Paypal naming (Jonathan Tron)
13
+ Use Rack::Utils#parse_query in Paypal::Notification for query parsing (Jonathan Tron)
14
+ Add Spec for notification (Jonathan Tron)
15
+ Add paypal/rails.rb to trigger helper inclusion in view (Jonathan Tron)
16
+ Separate actual helpers in two files (paypal/helpers/common.rb and paypal/helpers/rails.rb) (Jonathan Tron)
17
+ Move files around (Jonathan Tron)
18
+ Update the README and switch to MarkDown (Jonathan Tron)
19
+ Add a CHANGELOG file and switch to new format (Jonathan Tron)
20
+ Remove init.rb (Jonathan Tron)
21
+ Configure gem generation with jelewer (Jonathan Tron)
22
+
23
+ = 2008-10-16 -- 2.0.2
24
+
25
+ NEW: Added block style support for paypal_form_tag (paypal_form_tag do blah.. blah... end)
26
+ DEL: Removed patch for 2.0.0, no longer seems suitable.
27
+ NEW: Added testing for the paypal_form_tag block style.
28
+ NEW: Added a sample (actual from paypal sandbox) PayPal server response for IPN, to aid in testing.
29
+
30
+ = 2008-10-15 -- 2.0.1
31
+
32
+ CHG: Modified README.
33
+ FIX: Moved patch to own directory, was being caught by git-hub as gem's README
34
+ NEW: Added patch for currently installed paypal-2.0.0 gem to apply directly on gems directory.
35
+ NEW: Added relevant test statements.
36
+ FIX: removed duplicate 'invoice' method in lib/notification.rb
37
+ NEW: added correct 'custom' method to lib/notification.rb
38
+ NEW: added pending_reason, reason_code, memo, payment_type, exchange_rate methods to lib/notification.rb
39
+
40
+ = 2006-04-20 -- 2.0.0
41
+
42
+ Uses paypal extended syntax. The plugin can now submit shipping and billing addresses using the paypal_address helper.
43
+
44
+ = 2006-04-20 -- 1.7.0
45
+
46
+ Now a rails plugin
47
+
48
+ = 2006-02-10 -- 1.5.1
49
+
50
+ added complete list of valid paypal options (Paul Hart)
51
+
52
+ = 2006-02-02 -- 1.5.0
53
+
54
+ Now report an error when invalid option is passed to paypal_setup
55
+ Had to rename parameters cancel_url to cancel_return and return_url to return, please update your app
56
+ Improved the test coverage strategy for helper tests
57
+ Added support for encrypted form data (Paul Hart)
58
+
59
+ = 2005-09-16 -- 0.9.6
60
+
61
+ Added readme note about the openssl requirement
62
+
63
+ = 2005-07-26 -- 0.9.5
64
+
65
+ Added tax to the helper parameters
66
+ fixed bug when money class was used to pass in amount. Cents were always 00 (doh!)
67
+ Added invoice and custom optional parameters
68
+ Added charset = utf-8 to all paypal posts
69
+ Wrongly used undefined_quanitity parameter in 0.9.1, this caused users to be prompted for the quanitity on the paypal checkout page... fixed
70
+
71
+ = 2005-07-22 -- 0.9.1
72
+
73
+ support for cancel_url as well as notify_url. This means you can now set the IPN callback address from the paypal_setup method and
74
+ you don't have to do that in the paypal admin interface!
75
+ Removed the actual form tag from the paypal_setup generated code to conform better with docs
data/Gemfile ADDED
@@ -0,0 +1,3 @@
1
+ source "http://rubygems.org"
2
+
3
+ gemspec
@@ -0,0 +1,36 @@
1
+ PATH
2
+ remote: .
3
+ specs:
4
+ jonathantron-paypal (3.0.0pre4)
5
+ rack (>= 1.0.0)
6
+
7
+ GEM
8
+ remote: http://rubygems.org/
9
+ specs:
10
+ bluecloth (2.1.0)
11
+ diff-lcs (1.1.2)
12
+ fakeweb (1.3.0)
13
+ nokogiri (1.5.0)
14
+ rack (1.3.1)
15
+ rcov (0.9.9)
16
+ rspec (2.6.0)
17
+ rspec-core (~> 2.6.0)
18
+ rspec-expectations (~> 2.6.0)
19
+ rspec-mocks (~> 2.6.0)
20
+ rspec-core (2.6.4)
21
+ rspec-expectations (2.6.0)
22
+ diff-lcs (~> 1.1.2)
23
+ rspec-mocks (2.6.0)
24
+ yard (0.7.2)
25
+
26
+ PLATFORMS
27
+ ruby
28
+
29
+ DEPENDENCIES
30
+ bluecloth
31
+ fakeweb
32
+ jonathantron-paypal!
33
+ nokogiri
34
+ rcov (>= 0.9.8)
35
+ rspec (~> 2.6.0)
36
+ yard
data/LICENSE ADDED
@@ -0,0 +1,23 @@
1
+ #--
2
+ # Copyright (c) 2005 Tobias Luetke
3
+ # Copyright (c) 2009 Tron Jonathan
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
19
+ # NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20
+ # LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21
+ # OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22
+ # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
23
+ #++
@@ -0,0 +1,117 @@
1
+ # Welcome to Paypal ruby library
2
+
3
+ This library is here to aid with integrating Paypal payments into ruby on rails
4
+ applications or similar. To set this up you will need to log into your paypal
5
+ business account and tell paypal where to send the IPN ( Instant payment notifications ).
6
+
7
+ # Download
8
+
9
+ * Preferred method of installation is using rubygems. gem install JonathanTron-paypal
10
+ * Alternatively you can get the source code at http://github.com/JonathanTron/paypal
11
+
12
+ # Requirements
13
+
14
+ * Ruby 1.8.2 (may work with previous versions) With OpenSSL support compiled in.
15
+ * Valid paypal business account.
16
+ * (optional) The money library from http://dist.leetsoft.com/api/money
17
+
18
+ # Installation
19
+
20
+ 1. sudo gem install JonathanTron-paypal --source=http://gems.github.com
21
+
22
+ 2. Require the library
23
+
24
+ require "paypal"
25
+
26
+ 2.1. If you're using Rails add :
27
+
28
+ require "paypal/rails"
29
+
30
+ 3. Create a paypal_ipn ( or similar ) action like the one in the "Example action" appendix.
31
+
32
+
33
+ ## -- - TODO : REWRITE BELOW THIS POINT - --
34
+
35
+ Within the new payment controller you can now create pages from which users can be sent to paypal. You always have to sent users to paypal using a HTTP Post so a standard link won't work (well OK but you need some javascript for that). The +Paypal::Helper+ namespace has some examples of how such a forward page may look.
36
+
37
+ # Testing the integration
38
+
39
+ Under https://developer.paypal.com/ you can signup for a paypal developer account.
40
+ This allows you to set up "sandboxed" accounts which work and act like real accounts
41
+ with the difference that no money is exchanged. Its a good idea to sign up for a
42
+ sandbox account to use while the application is running in development mode.
43
+
44
+
45
+ # Example rails controller
46
+
47
+ class BackendController < ApplicationController
48
+
49
+ # Simplification, please write better code then this...
50
+ def paypal_ipn
51
+ notify # Paypal::Notification.new(request.raw_post)
52
+
53
+ if notify.acknowledge
54
+ order # Order.find(notify.item_id)
55
+ order.success # (notify.complete? and order.total # notify.amount) ? 'success' : 'failure'
56
+ order.save
57
+ end
58
+
59
+ render :nothing #> true
60
+ end
61
+ end
62
+
63
+ # Example paypal forward page
64
+
65
+ <%# paypal_form_tag %>
66
+ <%# paypal_setup "Item 500", Money.us_dollar(50000), "bob@bigbusiness.com", :notify_url #> url_for(:only_path #> false, :action #> 'paypal_ipn') %>
67
+
68
+ Please press here to pay $500US using paypal. <br/>
69
+ <%# submit_tag "Go to paypal >>" %>
70
+
71
+ </form>
72
+
73
+ or, with the same results, the block version:
74
+
75
+ <% paypal_form_tag do %>
76
+ <%# paypal_setup "Item 500", Money.us_dollar(50000), "bob@bigbusiness.com", :notify_url #> url_for(:only_path #> false, :action #> 'paypal_ipn') %>
77
+
78
+ Please press here to pay $500US using paypal. <br/>
79
+ <%# submit_tag "Go to paypal >>" %>
80
+
81
+ <% end %>
82
+
83
+ # Using encrypted form data
84
+
85
+ Paypal supports encrypted form data to prevent tampering by third parties.
86
+ You must have a verified paypal account to use this functionality.
87
+
88
+ 1) Create a private key for yourself
89
+
90
+ openssl genrsa -out business_key.pem 1024
91
+
92
+ 2) Create a public certificate to share with Paypal
93
+
94
+ openssl req -new -key business_key.pem -x509 -days 3650 -out business_cert.pem
95
+
96
+ 3) Upload the public certificate to Paypal (under Profile -> Encrypted Payment Settings -> Your Public Certificates -> Add),
97
+ and note the "Cert ID" that Paypal shows for the certificate.
98
+
99
+ 4) Update your controller to include the details for your key and certificate.
100
+
101
+ @business_key # File::read("business_key.pem")
102
+ @business_cert # File::read("business_cert.pem")
103
+ @business_certid # "certid from paypal"
104
+
105
+ 5) Update your views to populate the :business_key, :business_cert and :business_certid options in 'paypal_setup' - the rest of the signature is the same.
106
+
107
+ 6) When you're ready to go live, download the production Paypal certificate and override the default certificate.
108
+
109
+ Paypal::Notification.paypal_cert # File::read("paypal_cert.pem")
110
+
111
+ 7) Finally, add the following line to your environment.rb or inside an initializer:
112
+
113
+ Paypal::Notification.ipn_url # "https://www.paypal.com/cgi-bin/webscr"
114
+
115
+ # Troubleshooting
116
+
117
+ uninitalized constant Paypal - Make sure your ruby has openssl support
@@ -0,0 +1,21 @@
1
+ require "rubygems"
2
+
3
+ $:.unshift "./lib"
4
+ require "paypal"
5
+
6
+ require "rspec/core/rake_task"
7
+ ::RSpec::Core::RakeTask.new(:spec)
8
+ ::RSpec::Core::RakeTask.new(:rcov) do |spec|
9
+ spec.rcov = true
10
+ spec.rcov_opts = "--exclude spec/"
11
+ end
12
+ task :default => :spec
13
+
14
+ begin
15
+ require "yard"
16
+ YARD::Rake::YardocTask.new
17
+ rescue LoadError
18
+ task :yardoc do
19
+ abort "YARD is not available. In order to run yardoc, you must: sudo gem install yard"
20
+ end
21
+ end
@@ -0,0 +1,8 @@
1
+ require 'cgi'
2
+ require 'net/http'
3
+ require 'net/https'
4
+
5
+ require "paypal/version"
6
+ require "paypal/config"
7
+ require "paypal/notification"
8
+ require "paypal/helpers/common"
@@ -0,0 +1,22 @@
1
+ -----BEGIN CERTIFICATE-----
2
+ MIIDoTCCAwqgAwIBAgIBADANBgkqhkiG9w0BAQUFADCBmDELMAkGA1UEBhMCVVMx
3
+ EzARBgNVBAgTCkNhbGlmb3JuaWExETAPBgNVBAcTCFNhbiBKb3NlMRUwEwYDVQQK
4
+ EwxQYXlQYWwsIEluYy4xFjAUBgNVBAsUDXNhbmRib3hfY2VydHMxFDASBgNVBAMU
5
+ C3NhbmRib3hfYXBpMRwwGgYJKoZIhvcNAQkBFg1yZUBwYXlwYWwuY29tMB4XDTA0
6
+ MDQxOTA3MDI1NFoXDTM1MDQxOTA3MDI1NFowgZgxCzAJBgNVBAYTAlVTMRMwEQYD
7
+ VQQIEwpDYWxpZm9ybmlhMREwDwYDVQQHEwhTYW4gSm9zZTEVMBMGA1UEChMMUGF5
8
+ UGFsLCBJbmMuMRYwFAYDVQQLFA1zYW5kYm94X2NlcnRzMRQwEgYDVQQDFAtzYW5k
9
+ Ym94X2FwaTEcMBoGCSqGSIb3DQEJARYNcmVAcGF5cGFsLmNvbTCBnzANBgkqhkiG
10
+ 9w0BAQEFAAOBjQAwgYkCgYEAt5bjv/0N0qN3TiBL+1+L/EjpO1jeqPaJC1fDi+cC
11
+ 6t6tTbQ55Od4poT8xjSzNH5S48iHdZh0C7EqfE1MPCc2coJqCSpDqxmOrO+9QXsj
12
+ HWAnx6sb6foHHpsPm7WgQyUmDsNwTWT3OGR398ERmBzzcoL5owf3zBSpRP0NlTWo
13
+ nPMCAwEAAaOB+DCB9TAdBgNVHQ4EFgQUgy4i2asqiC1rp5Ms81Dx8nfVqdIwgcUG
14
+ A1UdIwSBvTCBuoAUgy4i2asqiC1rp5Ms81Dx8nfVqdKhgZ6kgZswgZgxCzAJBgNV
15
+ BAYTAlVTMRMwEQYDVQQIEwpDYWxpZm9ybmlhMREwDwYDVQQHEwhTYW4gSm9zZTEV
16
+ MBMGA1UEChMMUGF5UGFsLCBJbmMuMRYwFAYDVQQLFA1zYW5kYm94X2NlcnRzMRQw
17
+ EgYDVQQDFAtzYW5kYm94X2FwaTEcMBoGCSqGSIb3DQEJARYNcmVAcGF5cGFsLmNv
18
+ bYIBADAMBgNVHRMEBTADAQH/MA0GCSqGSIb3DQEBBQUAA4GBAFc288DYGX+GX2+W
19
+ P/dwdXwficf+rlG+0V9GBPJZYKZJQ069W/ZRkUuWFQ+Opd2yhPpneGezmw3aU222
20
+ CGrdKhOrBJRRcpoO3FjHHmXWkqgbQqDWdG7S+/l8n1QfDPp+jpULOrcnGEUY41Im
21
+ jZJTylbJQ1b5PBBjGiP0PpK48cdF
22
+ -----END CERTIFICATE-----
@@ -0,0 +1,49 @@
1
+ module Paypal
2
+ module Config
3
+
4
+ class << self
5
+ attr_accessor :ipn_urls, :mode, :paypal_sandbox_cert, :paypal_production_cert, :business_cert, :business_key, :business_cert_id
6
+
7
+ def ipn_urls
8
+ @ipn_urls ||= {
9
+ :sandbox => "https://www.sandbox.paypal.com/br/cgi-bin/webscr",
10
+ :production => "https://www.paypal.com/br/cgi-bin/webscr"
11
+ }
12
+ end
13
+
14
+ def mode=(new_mode)
15
+ raise ArgumentError.new("Paypal::Config.mode should be either :sandbox or :production (you tried to set it as : #{new_mode})") unless [:sandbox, :production].include?(new_mode.to_sym)
16
+ @mode = new_mode.to_sym
17
+ end
18
+ def mode
19
+ @mode ||= :sandbox
20
+ end
21
+
22
+ def ipn_url
23
+ ipn_urls[mode]
24
+ end
25
+
26
+ def ipn_validation_path
27
+ URI.parse(ipn_url).path + "?cmd=_notify-validate"
28
+ end
29
+
30
+ def ipn_validation_url
31
+ "#{ipn_url}?cmd=_notify-validate"
32
+ end
33
+
34
+ def paypal_sandbox_cert
35
+ @paypal_sandbox_cert ||= File.read(File.join(File.dirname(__FILE__), 'certs', 'paypal_sandbox.pem'))
36
+ end
37
+
38
+ def paypal_cert
39
+ case mode
40
+ when :sandbox
41
+ paypal_sandbox_cert
42
+ when :production
43
+ raise StandardError.new("You should set Paypal::Config.paypal_production_cert with your paypal production certificate") unless paypal_production_cert
44
+ paypal_production_cert
45
+ end
46
+ end
47
+ end
48
+ end
49
+ end
@@ -0,0 +1,304 @@
1
+ module Paypal
2
+ # This is a collection of helpers which aid in the creation of paypal buttons
3
+ #
4
+ # Example:
5
+ #
6
+ # <%= form_tag Paypal::Config.ipn_url %>
7
+ #
8
+ # <%= paypal_setup "Item 500", Money.us_dollar(50000), "bob@bigbusiness.com" %>
9
+ # Please press here to pay $500US using paypal. <%= submit_tag %>
10
+ #
11
+ # <% end_form_tag %>
12
+ #
13
+ # For this to work you have to include these methods as helpers in your rails application.
14
+ # One way is to add "include Paypal::Helpers" in your application_helper.rb
15
+ # See Paypal::Notification for information on how to catch payment events.
16
+ module Helpers
17
+ module Common
18
+ # This helper creates the hidden form data which is needed for a paypal purchase.
19
+ #
20
+ # * <tt>item_number</tt> -- The first parameter is the item number. This is for your personal organization and can
21
+ # be arbitrary. Paypal will sent the item number back with the IPN so its a great place to
22
+ # store a user ID or a order ID or something like this.
23
+ #
24
+ # * <tt>amount</tt> -- should be a parameter of type Money ( see http://leetsoft.com/api/money ) but can also
25
+ # be a string of type "50.00" for 50$. If you use the string syntax make sure you set the current
26
+ # currency as part of the options hash. The default is USD
27
+ #
28
+ # * <tt>business</tt> -- This is your paypal account name ( an email ). This needs to be a valid paypal business account.
29
+ #
30
+ # The last parameter is a options hash. You can set or override any Paypal-recognized parameter, including:
31
+ #
32
+ # * <tt>:cmd</tt> -- default is '_xclick' or '_xclick-subscriptions' when you use :subscription.
33
+ # * <tt>:quantity</tt> -- default is '1'.
34
+ # * <tt>:no_note</tt> -- default is '1'.
35
+ # * <tt>:item_name</tt> -- default is 'Store purchase'. This is the name of the purchase which will be displayed
36
+ # on the paypal page.
37
+ # * <tt>:no_shipping</tt> -- default is '1'. By default we tell paypal that no shipping is required. Usually
38
+ # the shipping address should be collected in our application, not by paypal.
39
+ # * <tt>:currency</tt> -- default is 'USD'. If you provide a Money object, that will automatically override
40
+ # the value.
41
+ # * <tt>:charset</tt> -- default is 'utf-8'.
42
+ # * <tt>:notify_url</tt> -- If provided paypal will send its IPN notification once a
43
+ # purchase is made, canceled or any other status changes occur.
44
+ # * <tt>:return</tt> -- If provided paypal will redirect a user back to this url after a
45
+ # successful purchase. Useful for a kind of thankyou page.
46
+ # * <tt>:cancel_return</tt> -- If provided paypal will redirect a user back to this url when
47
+ # the user cancels the purchase.
48
+ # * <tt>:tax</tt> -- the tax for the store purchase. Same format as the amount parameter but optional
49
+ # * <tt>:invoice</tt> -- Unique invoice number. User will never see this. optional
50
+ # * <tt>:custom</tt> -- Custom field. User will never see this. optional
51
+ #
52
+ # Dealing with subscriptions
53
+ #
54
+ # * <tt>:subscription</tt> -- Hash containing the subscription options. optional
55
+ # * <tt>:period</tt> -- One of :monthly, :yearly, :weekly or :daily
56
+ # * <tt>:length</tt> -- How often, based on :period. E.g. 6 :monthly?
57
+ # * <tt>:retry</tt> -- Default is false. Boolean for if paypal should retry failed payments.
58
+ # * <tt>:recurring</tt> -- Default is false. Boolean for if paypal should recur payment and end of period.
59
+ #
60
+ # Generating encrypted form data
61
+ #
62
+ # The helper also supports the generation of encrypted button data. Please see the README for more information
63
+ # on the setup and prerequisite steps for using encrypted forms.
64
+ #
65
+ # The following options must all be provided (as strings) to encrypt the data:
66
+ #
67
+ # * <tt>:business_key</tt> -- The private key you have generated
68
+ # * <tt>:business_cert</tt> -- The public certificate you have also uploaded to Paypal
69
+ # * <tt>:business_certid</tt> -- The certificate ID that Paypal has assigned to your certificate.
70
+ #
71
+ # Examples:
72
+ #
73
+ # <%= paypal_setup @order.id, Money.us_dollar(50000), "bob@bigbusiness.com" %>
74
+ # <%= paypal_setup @order.id, '50.00', "bob@bigbusiness.com", :currency => 'USD' %>
75
+ # <%= paypal_setup @order.id, '50.00', "bob@bigbusiness.com", :currency => 'USD', :notify_url => url_for(:only_path => false, :action => 'paypal_ipn') %>
76
+ # <%= paypal_setup @order.id, Money.ca_dollar(50000), "bob@bigbusiness.com", :item_name => 'Snowdevil shop purchase', :return_url => paypal_return_url, :cancel_url => paypal_cancel_url, :notify_url => paypal_ipn_url %>
77
+ # <%= paypal_setup @order.id, Money.ca_dollar(50000), "bob@bigbusiness.com", :item_name => 'Snowdevil shop purchase', :return_url => paypal_return_url, :cancel_url => paypal_cancel_url, :business_key => @business_key, :business_cert => @business_cert, :business_certid => @business_certid %>
78
+ #
79
+ def paypal_setup(item_number, amount, business, options = {})
80
+
81
+ subscription = options.delete(:subscription)
82
+
83
+ misses = (options.keys - valid_setup_options)
84
+ raise ArgumentError, "Unknown option #{misses.inspect}" unless misses.empty?
85
+
86
+ params = {
87
+ :cmd => subscription ? '_ext-enter' : '_xclick',
88
+ :redirect_cmd => subscription ? '_xclick-subscriptions' : nil,
89
+ :quantity => 1,
90
+ :business => business,
91
+ :item_number => item_number,
92
+ :item_name => 'Store purchase',
93
+ :no_shipping => '1',
94
+ :no_note => '1',
95
+ :charset => 'utf-8',
96
+ :page_style => 'PayPal'
97
+ }.reject{|k,v| v.nil?}.merge(options)
98
+
99
+ params[:currency_code] = amount.currency if amount.respond_to?(:currency)
100
+ params[:currency_code] = params.delete(:currency) if params[:currency]
101
+ params[:currency_code] ||= 'USD'
102
+
103
+ # We accept both strings and money objects as amount
104
+ amount = amount.cents.to_f / 100.0 if amount.respond_to?(:cents)
105
+ amount = sprintf('%.2f', amount)
106
+
107
+ if subscription.nil?
108
+ params[:amount] = amount
109
+ else
110
+ params[:a3] = amount
111
+ params[:p3] = subscription[:length]
112
+ params[:sra] = subscription[:retry] == true ? 1 : 0
113
+ params[:src] = subscription[:recurring] == true ? 1 : 0
114
+ params[:t3] = case subscription[:period]
115
+ when :monthly; 'M'
116
+ when :yearly; 'Y'
117
+ when :weekly; 'W'
118
+ when :daily; 'D'
119
+ end
120
+ end
121
+
122
+ # same for tax
123
+ tax = params[:tax]
124
+ unless tax.nil?
125
+ tax = tax.cents.to_f / 100.0 if tax.respond_to?(:cents)
126
+ params[:tax] = sprintf("%.2f", tax)
127
+ end
128
+
129
+ # look for encryption parameters, save them outsite the parameter hash.
130
+ if params.delete(:enable_encryption)
131
+ business_key = Paypal::Config.business_key
132
+ business_cert = Paypal::Config.business_cert
133
+ business_certid = Paypal::Config.business_cert_id
134
+ unless business_key && business_cert && business_certid
135
+ raise ArgumentError, "Paypal::Config.business_key, Paypal::Config.business_cert and Paypal::Config.business_cert_id should be set if you use :enable_encryption"
136
+ end
137
+ end
138
+
139
+ # Build the form
140
+ buttons = []
141
+ # Only attempt an encrypted form if we have all the required fields.
142
+ if business_key and business_cert and business_certid
143
+ require 'openssl'
144
+
145
+ # Convert the key and certificates into OpenSSL-friendly objects.
146
+ paypal_cert = OpenSSL::X509::Certificate.new(Paypal::Config.paypal_cert)
147
+ business_key = OpenSSL::PKey::RSA.new(business_key)
148
+ business_cert = OpenSSL::X509::Certificate.new(business_cert)
149
+ # Put the certificate ID back into the parameter hash the way Paypal wants it.
150
+ params[:cert_id] = business_certid
151
+
152
+ # Prepare a string of data for encryption
153
+ data = ""
154
+ params.each_pair {|k,v| data << "#{k}=#{v}\n"}
155
+
156
+ # Sign the data with our key/certificate pair
157
+ signed = OpenSSL::PKCS7::sign(business_cert, business_key, data, [], OpenSSL::PKCS7::BINARY)
158
+ # Encrypt the signed data with Paypal's public certificate.
159
+ encrypted = OpenSSL::PKCS7::encrypt([paypal_cert], signed.to_der, OpenSSL::Cipher::Cipher::new("DES3"), OpenSSL::PKCS7::BINARY).to_s.gsub("\n", "")
160
+
161
+ # The command for encrypted forms is always '_s-xclick'; the real command is in the encrypted data.
162
+ buttons << %Q{<input type="hidden" name="cmd" value="_s-xclick" />}
163
+ buttons << %Q{<input type="hidden" name="encrypted" value="#{encrypted}" />}
164
+ else
165
+ # Just emit all the parameters that we have as hidden fields.
166
+ # Note that the sorting isn't really needed, but it makes testing a lot easier for now.
167
+ params.each do |key, value|
168
+ buttons << %Q{<input type="hidden" name="#{key}" value="#{value}" />} unless value.nil?
169
+ end
170
+ end
171
+ buttons.join("\n")
172
+ end
173
+
174
+ # Pass an address to paypal so that all signup forms can be prefilled
175
+ #
176
+ # * <tt>email</tt> -- Customer's email address
177
+ # * <tt>first_name</tt> -- Customer's first name. Must be alpha-numeric, with a 32 character limit
178
+ # * <tt>last_name</tt> -- Customer's last name. Must be alpha-numeric, with a 64 character limit
179
+ # * <tt>address1</tt> -- First line of customer's address. Must be alpha-numeric, with a 100 character limit
180
+ # * <tt>address2</tt> -- Second line of customer's address. Must be alpha-numeric, with a 100 character limit
181
+ # * <tt>city</tt> -- City of customer's address. Must be alpha-numeric, with a 100 character limit
182
+ # * <tt>state</tt> -- State of customer's address. Must be official 2 letter abbreviation
183
+ # * <tt>zip</tt> -- Zip code of customer's address
184
+ # * <tt>night_phone_a</tt> -- Area code of customer's night telephone number
185
+ # * <tt>night_phone_b</tt> -- First three digits of customer's night telephone number
186
+ # * <tt>day_phone_a</tt> -- Area code of customer's daytime telephone number
187
+ # * <tt>day_phone_b</tt> -- First three digits of customer's daytime telephon
188
+ def paypal_address(options = {})
189
+ options.collect do |key, value|
190
+ %Q{<input type="hidden" name="#{key}" value="#{value}" />}
191
+ end.join("\n")
192
+ end
193
+
194
+ private
195
+
196
+ # See https://www.paypal.com/IntegrationCenter/ic_std-variable-reference.html for details on the following options.
197
+ def valid_setup_options
198
+ [
199
+ # Generic Options
200
+ :cmd,
201
+ # IPN Support
202
+ :notify_url,
203
+ # Item Information
204
+ :item_name,
205
+ :quantity,
206
+ :undefined_quantity,
207
+ :on0,
208
+ :os0,
209
+ :on1,
210
+ :os1,
211
+ # Display Information
212
+ :add,
213
+ :cancel_return,
214
+ :cbt,
215
+ :cn,
216
+ :cpp_header_image,
217
+ :cpp_headerback_color,
218
+ :cpp_headerborder_color,
219
+ :cpp_payflow_color,
220
+ :cs,
221
+ :display,
222
+ :image_url,
223
+ :no_note,
224
+ :no_shipping,
225
+ :page_style,
226
+ :return,
227
+ :rm,
228
+ # Transaction Information
229
+ :address_override,
230
+ :currency,
231
+ :currency_code,
232
+ :custom,
233
+ :handling,
234
+ :invoice,
235
+ :redirect_cmd,
236
+ :shipping,
237
+ :tax,
238
+ :tax_cart,
239
+ # Shopping Cart Options
240
+ :amount,
241
+ :business,
242
+ :handling_cart,
243
+ :paymentaction,
244
+ :rupload,
245
+ :charset,
246
+ :upload,
247
+ # Prepopulating PayPal FORMs or Address Overriding
248
+ :address1,
249
+ :address2,
250
+ :city,
251
+ :country,
252
+ :email,
253
+ :first_name,
254
+ :last_name,
255
+ :lc,
256
+ :night_phone_a,
257
+ :night_phone_b,
258
+ :night_phone_c,
259
+ :state,
260
+ :zip,
261
+ # Prepopulating Business Account Sign-up
262
+ :business_address1,
263
+ :business_address2,
264
+ :business_city,
265
+ :business_state,
266
+ :business_country,
267
+ :business_cs_email,
268
+ :business_cs_phone_a,
269
+ :business_cs_phone_b,
270
+ :business_cs_phone_c,
271
+ :business_url,
272
+ :business_night_phone_a,
273
+ :business_night_phone_b,
274
+ :business_night_phone_c,
275
+ # End of list from https://www.paypal.com/IntegrationCenter/ic_std-variable-reference.html
276
+ # The following items are known to exist but are not yet on the above page.
277
+ :business_zip,
278
+ :day_phone_a,
279
+ :day_phone_b,
280
+ :day_phone_c,
281
+ # Subscription Options
282
+ :a1, # Trial Amount 1
283
+ :p1, # Trial Period 1
284
+ :t1, # Trial Period 1 Units (D=days, W=weeks, M=months, Y=years)
285
+ :a2, # Trial Amount 2
286
+ :p2, # Trial Period 2
287
+ :t2, # Trial Period 2 Units
288
+ :a3, # Regular Subscription Amount
289
+ :p3, # Regular Subscription Period
290
+ :t3, # Regular Subscription Period Units
291
+ :src, # Recurring Payments? (1=yes, default=0)
292
+ :sra, # Reattempt Transaction on Failure? (1=yes, default=0)
293
+ :srt, # Recurring Times (number of renewals before auto-cancel, default=forever)
294
+ :usr_manage, # Username and Password Generator? (1=yes, default=0)
295
+ :modify, # Modification Behaviour (0=new subs only, 1=new or modify, 2=modify existing only, default=0)
296
+ # Encryption Options - used internally only.
297
+ :enable_encryption, # Use business_cert, business_key and business_cert_id from Paypal::Config
298
+ # Other
299
+ :bn
300
+ ]
301
+ end
302
+ end
303
+ end
304
+ end