paypal-ipn 0.0.1 → 0.0.2

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,3 @@
1
+ pkg/*
2
+ *.gem
3
+ .bundle
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source "http://rubygems.org"
2
+
3
+ # Specify your gem's dependencies in paypal.gemspec
4
+ gemspec
@@ -6,6 +6,8 @@ Currently paypal supports the following:
6
6
 
7
7
  * Verifying Paypal IPN's
8
8
  * MassPay Requests
9
+ * Permissions Service
10
+ * Authentication Service
9
11
 
10
12
  ## Configuration
11
13
  Paypal.setup do |config|
@@ -101,13 +103,56 @@ Note: Your class must respond to `payment_response` and return the payment respo
101
103
 
102
104
  Note: Currently Masspay payments only support a single recipient
103
105
 
104
- ## Rails
105
- `rails g paypal:initializer`
106
- Generates a stub initializer under config/initializers
106
+ ### Permissions Service
107
+ class Permissions
108
+ include Paypal::Permissions
109
+ end
110
+
111
+ #### Usage
112
+ 1. Make a call to `set_paypal_permissions_url` setting the *return_url* to your application's callback url and with your *required_permissions*
113
+
114
+ 2. Redirect the user to that url
115
+
116
+ 3. When Paypal redirects the user back to your application at *return_url* make a call to `get_paypal_permissions` with the token parameter
117
+
118
+ See below for further details:
119
+
120
+ ##### Private methods
121
+ `set_paypal_permissions_url(return_url, required_permissions = {})`
122
+ Returns a url where the user can sign in to Paypal and authorize the requested permissions. Paypal will then redirect the user to the *return_url*. Specify *required_permissions* by supplying a hash in the following format:
123
+ {
124
+ :mass_pay => true,
125
+ :refund_transaction => true,
126
+ :get_transaction_details => true
127
+ }
128
+ First name, Last name and email are always required permissions so you never have to specify these manually.
129
+
130
+ `get_paypal_permissions(token)`
131
+ Returns a hash of user information and permission details for the given *token* in the following format:
132
+ {
133
+ :email => "joe@example.com",
134
+ :first_name => "Joe",
135
+ :last_name => "Bloggs",
136
+ :payer_id => "VK7XZU4BDY79",
137
+ :permissions => {
138
+ :mass_pay => true,
139
+ :refund_transaction => true,
140
+ :get_transaction_details => true
141
+ }
142
+ }
107
143
 
108
144
  ## Installation
109
145
 
110
- gem install paypal
146
+ gem install paypal-ipn
147
+
148
+ ## Rails
149
+
150
+ Place the following in your Gemfile:
151
+ `gem 'paypal-ipn', :require => 'paypal'`
152
+
153
+ To generate a stub initializer under config/initializers run:
154
+ `rails g paypal:initializer`
155
+
111
156
 
112
157
  Copyright (c) 2010 David Wilkie, released under the MIT license
113
158
 
data/Rakefile CHANGED
@@ -1,39 +1,2 @@
1
- require 'rake'
2
- require 'rake/testtask'
3
- require 'rake/rdoctask'
4
-
5
- desc 'Default: run unit tests.'
6
- task :default => :test
7
-
8
- desc 'Test the Paypal plugin.'
9
- Rake::TestTask.new(:test) do |t|
10
- t.libs << 'lib'
11
- t.libs << 'spec'
12
- t.libs << 'features'
13
- t.pattern = 'spec/**/*_spec.rb'
14
- t.verbose = true
15
- end
16
-
17
- begin
18
- require 'jeweler'
19
- Jeweler::Tasks.new do |gemspec|
20
- gemspec.name = "paypal-ipn"
21
- gemspec.summary = "Another ruby wrapper for Paypal"
22
- gemspec.email = "dwilkie@gmail.com"
23
- gemspec.homepage = "http://github.com/dwilkie/paypal"
24
- gemspec.authors = ["David Wilkie"]
25
- gemspec.add_runtime_dependency "httparty", ">=0.6.1"
26
- end
27
- rescue LoadError
28
- puts "Jeweler not available. Install it with: gem install jeweler"
29
- end
30
-
31
- desc 'Generate documentation for the Paypal plugin.'
32
- Rake::RDocTask.new(:rdoc) do |rdoc|
33
- rdoc.rdoc_dir = 'rdoc'
34
- rdoc.title = 'Paypal'
35
- rdoc.options << '--line-numbers' << '--inline-source'
36
- rdoc.rdoc_files.include('README')
37
- rdoc.rdoc_files.include('lib/**/*.rb')
38
- end
39
-
1
+ require 'bundler'
2
+ Bundler::GemHelper.install_tasks
@@ -1,14 +1,20 @@
1
+ require 'httparty'
1
2
  require 'paypal/ipn/ipn'
2
3
  require 'paypal/ipn/types/masspay'
3
4
  require 'paypal/ipn/variables/buyer'
4
5
  require 'paypal/ipn/variables/item'
5
6
  require 'paypal/masspay'
7
+ require 'paypal/permissions'
8
+ require 'paypal/authentication'
6
9
 
7
10
  module Paypal
8
11
 
9
12
  LIVE_NVP_URI = "https://api-3t.paypal.com/nvp"
10
13
  SANDBOX_NVP_URI = "https://api-3t.sandbox.paypal.com/nvp"
11
14
 
15
+ LIVE_URI = "https://www.paypal.com"
16
+ SANDBOX_URI = "https://www.sandbox.paypal.com"
17
+
12
18
  mattr_accessor :environment,
13
19
  :api_username,
14
20
  :api_password,
@@ -20,10 +26,16 @@ module Paypal
20
26
  yield self
21
27
  end
22
28
 
23
- def self.nvp_uri
29
+ def self.nvp_uri(force_https = true)
24
30
  environment == "live" ?
25
31
  LIVE_NVP_URI :
26
32
  SANDBOX_NVP_URI
27
33
  end
34
+
35
+ def self.uri
36
+ environment == "live" ?
37
+ LIVE_URI :
38
+ SANDBOX_URI
39
+ end
28
40
  end
29
41
 
@@ -0,0 +1,67 @@
1
+ module Paypal
2
+ module Authentication
3
+ require 'rack'
4
+ include HTTParty
5
+ private
6
+ def authenticate_with_paypal_url(return_url)
7
+ body = {
8
+ "METHOD" => "SetAuthFlowParam",
9
+ "VERSION" => "2.3",
10
+ "USER" => Paypal.api_username,
11
+ "PWD" => Paypal.api_password,
12
+ "SIGNATURE" => Paypal.api_signature,
13
+ "SERVICENAME1" => "Name",
14
+ "SERVICEDEFREQ1" => "Required",
15
+ "SERVICENAME2" => "Email",
16
+ "SERVICEDEFREQ2" => "Required",
17
+ "RETURNURL" => return_url,
18
+ "CANCELURL" => return_url,
19
+ "LOGOUTURL"=> return_url
20
+ }
21
+ request_uri = URI.parse(Paypal.nvp_uri)
22
+ request_uri.scheme = "https" # force https
23
+ response = Paypal::Authentication.send_request(body)
24
+ url = Paypal::Authentication.build_uri_from_set_auth_flow_param_response(response)
25
+ url ? url : return_url
26
+ end
27
+
28
+ def get_auth_details(token)
29
+ body = {
30
+ "METHOD" => "GetAuthDetails",
31
+ "VERSION" => "2.3",
32
+ "USER" => Paypal.api_username,
33
+ "PWD" => Paypal.api_password,
34
+ "SIGNATURE" => Paypal.api_signature,
35
+ "TOKEN" => token
36
+ }
37
+ Paypal::Authentication.normalize_paypal_response(
38
+ Paypal::Authentication.send_request(body)
39
+ )
40
+ end
41
+
42
+ def self.normalize_paypal_response(raw_response)
43
+ raw_response_hash = Rack::Utils.parse_nested_query(raw_response)
44
+ {
45
+ :payer_id => raw_response_hash["PAYERID"],
46
+ :first_name => raw_response_hash["FIRSTNAME"],
47
+ :last_name => raw_response_hash["LASTNAME"],
48
+ :email => raw_response_hash["EMAIL"]
49
+ } if raw_response_hash["ACK"] == "Success"
50
+ end
51
+
52
+ def self.send_request(body)
53
+ self.post(Paypal.nvp_uri, :body => body).body
54
+ end
55
+
56
+ def self.build_uri_from_set_auth_flow_param_response(response)
57
+ if token = Rack::Utils.parse_nested_query(response)["TOKEN"]
58
+ uri = URI.parse(Paypal.uri)
59
+ uri.query = Rack::Utils.build_nested_query(
60
+ "token" => token, "cmd" => "_account-authenticate-login"
61
+ )
62
+ uri.to_s
63
+ end
64
+ end
65
+ end
66
+ end
67
+
@@ -0,0 +1,126 @@
1
+ module Paypal
2
+ module Permissions
3
+ require 'rack'
4
+ include HTTParty
5
+ private
6
+ def set_paypal_permissions_url(return_url, required_permissions = {})
7
+ required_permissions.merge!(:name => true, :email => true)
8
+ paypal_required_permissions = {}
9
+ index = 0
10
+ required_permissions.each do |k,v|
11
+ if v
12
+ paypal_required_permissions["L_REQUIREDACCESSPERMISSIONS#{index}"] = Paypal::Permissions.paypal_permission_name(k)
13
+ index += 1
14
+ end
15
+ end
16
+ body = {
17
+ "METHOD" => "SetAccessPermissions",
18
+ "VERSION" => "2.3",
19
+ "USER" => Paypal.api_username,
20
+ "PWD" => Paypal.api_password,
21
+ "SIGNATURE" => Paypal.api_signature,
22
+ "RETURNURL" => return_url,
23
+ "CANCELURL" => return_url,
24
+ "LOGOUTURL"=> return_url
25
+ }.merge(paypal_required_permissions)
26
+ response = Paypal::Permissions.send_request(body)
27
+ url = Paypal::Permissions.build_uri_from_set_access_permissions_response(response)
28
+ url ? url : return_url
29
+ end
30
+
31
+ def get_paypal_permissions(token)
32
+ body = {
33
+ "METHOD" => "GetAccessPermissionDetails",
34
+ "VERSION" => "2.3",
35
+ "USER" => Paypal.api_username,
36
+ "PWD" => Paypal.api_password,
37
+ "SIGNATURE" => Paypal.api_signature,
38
+ "TOKEN" => token
39
+ }
40
+ Paypal::Permissions.normalize_paypal_response(
41
+ Paypal::Permissions.send_request(body)
42
+ )
43
+ end
44
+
45
+ def self.send_request(body)
46
+ self.post(Paypal.nvp_uri, :body => body).body
47
+ end
48
+
49
+ def self.paypal_permission_name(key)
50
+ case key.to_s
51
+
52
+ when "express_checkout"
53
+ "Express_Checkout"
54
+
55
+ when "admin_api"
56
+ "Admin_API"
57
+
58
+ when "auth_settle"
59
+ "Auth_Settle"
60
+
61
+ when "transaction_history"
62
+ "Transaction_History"
63
+
64
+ when "do_uatp_authorization"
65
+ "DoUATPAuthorization"
66
+
67
+ when "do_uatp_express_checkout_payment"
68
+ "DoUATPExpressCheckoutPayment"
69
+
70
+ else
71
+ camelize(key)
72
+ end
73
+ end
74
+
75
+ def self.build_uri_from_set_access_permissions_response(response)
76
+ if token = Rack::Utils.parse_nested_query(response)["TOKEN"]
77
+ uri = URI.parse(Paypal.uri)
78
+ uri.query = Rack::Utils.build_nested_query(
79
+ "token" => token, "cmd" => "_access-permission-login"
80
+ )
81
+ uri.to_s
82
+ end
83
+ end
84
+
85
+ def self.normalize_paypal_response(raw_response)
86
+ raw_response_hash = Rack::Utils.parse_nested_query(raw_response)
87
+ if raw_response_hash["ACK"] == "Success"
88
+ normalized_response = {
89
+ :payer_id => raw_response_hash["PAYERID"],
90
+ :first_name => raw_response_hash["FIRSTNAME"],
91
+ :last_name => raw_response_hash["LASTNAME"],
92
+ :email => raw_response_hash["EMAIL"],
93
+ :permissions => normalize_permissions(raw_response_hash)
94
+ }
95
+ end
96
+ end
97
+
98
+ def self.normalize_permissions(raw_response_hash)
99
+ normalized_permissions = {}
100
+ permission_name_key = "L_ACCESSPERMISSIONNAME"
101
+ permission_status_key = "L_ACCESSPERMISSIONSTATUS"
102
+ i = 0
103
+ begin
104
+ permission = raw_response_hash[permission_name_key + i.to_s]
105
+ permission_status = raw_response_hash[permission_status_key + i.to_s]
106
+ normalized_permissions[underscore(permission).to_sym] = (permission_status == "Accepted") if permission && permission_status
107
+ i += 1
108
+ end until permission.nil? || permission_status.nil?
109
+ normalized_permissions
110
+ end
111
+
112
+ def self.camelize(lower_case_and_underscored_word)
113
+ lower_case_and_underscored_word.to_s.gsub(/(?:^|_)(.)/) { $1.upcase }
114
+ end
115
+
116
+ def self.underscore(camel_cased_word)
117
+ word = camel_cased_word.to_s.dup
118
+ word.gsub!(/([A-Z]+)([A-Z][a-z])/,'\1_\2')
119
+ word.gsub!(/([a-z\d])([A-Z])/,'\1_\2')
120
+ word.tr!("-", "_")
121
+ word.downcase!
122
+ word
123
+ end
124
+ end
125
+ end
126
+
@@ -0,0 +1,3 @@
1
+ module Paypal
2
+ VERSION = "0.0.2"
3
+ end
@@ -0,0 +1,23 @@
1
+ # -*- encoding: utf-8 -*-
2
+ $:.push File.expand_path("../lib", __FILE__)
3
+ require "paypal/version"
4
+
5
+ Gem::Specification.new do |s|
6
+ s.name = "paypal-ipn"
7
+ s.version = Paypal::VERSION
8
+ s.platform = Gem::Platform::RUBY
9
+ s.authors = ["David Wilkie"]
10
+ s.email = ["dwilkie@gmail.com"]
11
+ s.homepage = "https://github.com/dwilkie/paypal"
12
+ s.summary = %q{More than just IPNs}
13
+ s.description = %q{A ruby library for handling paypal api's including IPNs}
14
+ s.add_runtime_dependency("httparty")
15
+
16
+ s.rubyforge_project = "paypal"
17
+
18
+ s.files = `git ls-files`.split("\n")
19
+ s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
20
+ s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
21
+ s.require_paths = ["lib"]
22
+ end
23
+
metadata CHANGED
@@ -5,8 +5,8 @@ version: !ruby/object:Gem::Version
5
5
  segments:
6
6
  - 0
7
7
  - 0
8
- - 1
9
- version: 0.0.1
8
+ - 2
9
+ version: 0.0.2
10
10
  platform: ruby
11
11
  authors:
12
12
  - David Wilkie
@@ -14,7 +14,7 @@ autorequire:
14
14
  bindir: bin
15
15
  cert_chain: []
16
16
 
17
- date: 2010-09-24 00:00:00 +07:00
17
+ date: 2010-11-16 00:00:00 +07:00
18
18
  default_executable:
19
19
  dependencies:
20
20
  - !ruby/object:Gem::Dependency
@@ -27,41 +27,44 @@ dependencies:
27
27
  - !ruby/object:Gem::Version
28
28
  segments:
29
29
  - 0
30
- - 6
31
- - 1
32
- version: 0.6.1
30
+ version: "0"
33
31
  type: :runtime
34
32
  version_requirements: *id001
35
- description:
36
- email: dwilkie@gmail.com
33
+ description: A ruby library for handling paypal api's including IPNs
34
+ email:
35
+ - dwilkie@gmail.com
37
36
  executables: []
38
37
 
39
38
  extensions: []
40
39
 
41
- extra_rdoc_files:
42
- - README.markdown
40
+ extra_rdoc_files: []
41
+
43
42
  files:
43
+ - .gitignore
44
+ - Gemfile
44
45
  - MIT-LICENSE
45
46
  - README.markdown
46
47
  - Rakefile
47
- - VERSION
48
48
  - lib/generators/paypal/initializer/USAGE
49
49
  - lib/generators/paypal/initializer/initializer_generator.rb
50
50
  - lib/generators/paypal/initializer/templates/paypal.rb
51
51
  - lib/paypal.rb
52
+ - lib/paypal/authentication.rb
52
53
  - lib/paypal/ipn/ipn.rb
53
54
  - lib/paypal/ipn/types/masspay.rb
54
55
  - lib/paypal/ipn/variables/buyer.rb
55
56
  - lib/paypal/ipn/variables/item.rb
56
57
  - lib/paypal/masspay.rb
57
- - paypal.gemspec
58
+ - lib/paypal/permissions.rb
59
+ - lib/paypal/version.rb
60
+ - paypal-ipn.gemspec
58
61
  has_rdoc: true
59
- homepage: http://github.com/dwilkie/paypal
62
+ homepage: https://github.com/dwilkie/paypal
60
63
  licenses: []
61
64
 
62
65
  post_install_message:
63
- rdoc_options:
64
- - --charset=UTF-8
66
+ rdoc_options: []
67
+
65
68
  require_paths:
66
69
  - lib
67
70
  required_ruby_version: !ruby/object:Gem::Requirement
@@ -82,10 +85,10 @@ required_rubygems_version: !ruby/object:Gem::Requirement
82
85
  version: "0"
83
86
  requirements: []
84
87
 
85
- rubyforge_project:
88
+ rubyforge_project: paypal
86
89
  rubygems_version: 1.3.7
87
90
  signing_key:
88
91
  specification_version: 3
89
- summary: Another ruby wrapper for Paypal
92
+ summary: More than just IPNs
90
93
  test_files: []
91
94
 
data/VERSION DELETED
@@ -1 +0,0 @@
1
- 0.0.1
@@ -1,52 +0,0 @@
1
- # Generated by jeweler
2
- # DO NOT EDIT THIS FILE DIRECTLY
3
- # Instead, edit Jeweler::Tasks in Rakefile, and run the gemspec command
4
- # -*- encoding: utf-8 -*-
5
-
6
- Gem::Specification.new do |s|
7
- s.name = %q{paypal}
8
- s.version = "0.0.1"
9
-
10
- s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
11
- s.authors = ["David Wilkie"]
12
- s.date = %q{2010-09-24}
13
- s.email = %q{dwilkie@gmail.com}
14
- s.extra_rdoc_files = [
15
- "README.markdown"
16
- ]
17
- s.files = [
18
- "MIT-LICENSE",
19
- "README.markdown",
20
- "Rakefile",
21
- "VERSION",
22
- "lib/generators/paypal/initializer/USAGE",
23
- "lib/generators/paypal/initializer/initializer_generator.rb",
24
- "lib/generators/paypal/initializer/templates/paypal.rb",
25
- "lib/paypal.rb",
26
- "lib/paypal/ipn/ipn.rb",
27
- "lib/paypal/ipn/types/masspay.rb",
28
- "lib/paypal/ipn/variables/buyer.rb",
29
- "lib/paypal/ipn/variables/item.rb",
30
- "lib/paypal/masspay.rb",
31
- "paypal.gemspec"
32
- ]
33
- s.homepage = %q{http://github.com/dwilkie/paypal}
34
- s.rdoc_options = ["--charset=UTF-8"]
35
- s.require_paths = ["lib"]
36
- s.rubygems_version = %q{1.3.7}
37
- s.summary = %q{Another ruby wrapper for Paypal}
38
-
39
- if s.respond_to? :specification_version then
40
- current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION
41
- s.specification_version = 3
42
-
43
- if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.2.0') then
44
- s.add_runtime_dependency(%q<httparty>, [">= 0.6.1"])
45
- else
46
- s.add_dependency(%q<httparty>, [">= 0.6.1"])
47
- end
48
- else
49
- s.add_dependency(%q<httparty>, [">= 0.6.1"])
50
- end
51
- end
52
-