paypal-sdk-rest-pmrb 1.8.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (72) hide show
  1. checksums.yaml +7 -0
  2. data/Gemfile +15 -0
  3. data/README.md +265 -0
  4. data/Rakefile +15 -0
  5. data/data/DigiCertHighAssuranceEVRootCA.pem +23 -0
  6. data/data/DigiCertSHA2ExtendedValidationServerCA.pem +28 -0
  7. data/data/paypal.crt +193 -0
  8. data/lib/generators/paypal/sdk/USAGE +3 -0
  9. data/lib/generators/paypal/sdk/install_generator.rb +17 -0
  10. data/lib/generators/paypal/sdk/templates/paypal.rb +2 -0
  11. data/lib/generators/paypal/sdk/templates/paypal.yml +29 -0
  12. data/lib/paypal-sdk-core.rb +38 -0
  13. data/lib/paypal-sdk-rest.rb +2 -0
  14. data/lib/paypal-sdk/core/api.rb +20 -0
  15. data/lib/paypal-sdk/core/api/base.rb +169 -0
  16. data/lib/paypal-sdk/core/api/data_types/array_with_block.rb +44 -0
  17. data/lib/paypal-sdk/core/api/data_types/base.rb +225 -0
  18. data/lib/paypal-sdk/core/api/data_types/enum.rb +26 -0
  19. data/lib/paypal-sdk/core/api/data_types/simple_types.rb +52 -0
  20. data/lib/paypal-sdk/core/api/ipn.rb +66 -0
  21. data/lib/paypal-sdk/core/api/rest.rb +177 -0
  22. data/lib/paypal-sdk/core/authentication.rb +66 -0
  23. data/lib/paypal-sdk/core/config.rb +253 -0
  24. data/lib/paypal-sdk/core/credential.rb +16 -0
  25. data/lib/paypal-sdk/core/credential/base.rb +27 -0
  26. data/lib/paypal-sdk/core/credential/certificate.rb +32 -0
  27. data/lib/paypal-sdk/core/credential/signature.rb +22 -0
  28. data/lib/paypal-sdk/core/credential/third_party/subject.rb +25 -0
  29. data/lib/paypal-sdk/core/credential/third_party/token.rb +39 -0
  30. data/lib/paypal-sdk/core/exceptions.rb +112 -0
  31. data/lib/paypal-sdk/core/logging.rb +50 -0
  32. data/lib/paypal-sdk/core/openid_connect.rb +140 -0
  33. data/lib/paypal-sdk/core/openid_connect/api.rb +50 -0
  34. data/lib/paypal-sdk/core/openid_connect/data_types.rb +73 -0
  35. data/lib/paypal-sdk/core/openid_connect/get_api.rb +28 -0
  36. data/lib/paypal-sdk/core/openid_connect/request_data_type.rb +52 -0
  37. data/lib/paypal-sdk/core/openid_connect/set_api.rb +36 -0
  38. data/lib/paypal-sdk/core/util.rb +11 -0
  39. data/lib/paypal-sdk/core/util/http_helper.rb +171 -0
  40. data/lib/paypal-sdk/core/util/oauth_signature.rb +64 -0
  41. data/lib/paypal-sdk/core/util/ordered_hash.rb +165 -0
  42. data/lib/paypal-sdk/rest.rb +39 -0
  43. data/lib/paypal-sdk/rest/api.rb +23 -0
  44. data/lib/paypal-sdk/rest/data_types.rb +2597 -0
  45. data/lib/paypal-sdk/rest/error_hash.rb +39 -0
  46. data/lib/paypal-sdk/rest/get_api.rb +20 -0
  47. data/lib/paypal-sdk/rest/request_data_type.rb +53 -0
  48. data/lib/paypal-sdk/rest/set_api.rb +42 -0
  49. data/lib/paypal-sdk/rest/version.rb +7 -0
  50. data/spec/README.md +22 -0
  51. data/spec/config/cacert.pem +171 -0
  52. data/spec/config/cert_key.pem +33 -0
  53. data/spec/config/paypal.yml +35 -0
  54. data/spec/config/sample_data.yml +3 -0
  55. data/spec/core/api/data_type_spec.rb +289 -0
  56. data/spec/core/api/rest_spec.rb +211 -0
  57. data/spec/core/config_spec.rb +192 -0
  58. data/spec/core/logging_spec.rb +28 -0
  59. data/spec/core/openid_connect_spec.rb +153 -0
  60. data/spec/invoice_examples_spec.rb +38 -0
  61. data/spec/log/http.log +175 -0
  62. data/spec/log/rest_http.log +0 -0
  63. data/spec/payments_examples_spec.rb +437 -0
  64. data/spec/payouts_examples_spec.rb +74 -0
  65. data/spec/rest/data_types_spec.rb +62 -0
  66. data/spec/rest/error_hash_spec.rb +83 -0
  67. data/spec/spec_helper.rb +37 -0
  68. data/spec/subscription_examples_spec.rb +227 -0
  69. data/spec/support/sample_data.rb +5 -0
  70. data/spec/web_profile_examples_spec.rb +106 -0
  71. data/spec/webhooks_examples_spec.rb +93 -0
  72. metadata +177 -0
@@ -0,0 +1,16 @@
1
+ module PayPal
2
+ module SDK
3
+ module Core
4
+ module Credential
5
+ autoload :Base, "paypal-sdk/core/credential/base"
6
+ autoload :Certificate, "paypal-sdk/core/credential/certificate"
7
+ autoload :Signature, "paypal-sdk/core/credential/signature"
8
+
9
+ module ThirdParty
10
+ autoload :Token, "paypal-sdk/core/credential/third_party/token"
11
+ autoload :Subject, "paypal-sdk/core/credential/third_party/subject"
12
+ end
13
+ end
14
+ end
15
+ end
16
+ end
@@ -0,0 +1,27 @@
1
+ module PayPal::SDK::Core
2
+ module Credential
3
+
4
+ # Base credential Class for authentication
5
+ class Base
6
+ attr_accessor :username, :password, :app_id, :device_ipaddress, :sandbox_email_address
7
+
8
+ # Initialize authentication configurations
9
+ # === Arguments
10
+ # * <tt>config</tt> -- Configuration object
11
+ def initialize(config)
12
+ self.username = config.username
13
+ self.password = config.password
14
+ self.app_id = config.app_id
15
+ self.device_ipaddress = config.device_ipaddress
16
+ self.sandbox_email_address = config.sandbox_email_address
17
+ end
18
+
19
+ # Return credential properties
20
+ def properties
21
+ { :username => username, :password => password, :app_id => app_id,
22
+ :device_ipaddress => device_ipaddress, :sandbox_email_address => sandbox_email_address }
23
+ end
24
+
25
+ end
26
+ end
27
+ end
@@ -0,0 +1,32 @@
1
+ module PayPal::SDK::Core
2
+ module Credential
3
+
4
+ # Certificate class for SSL Certificate authentication
5
+ class Certificate < Base
6
+
7
+ attr_reader :cert_path
8
+
9
+ def initialize(config)
10
+ super
11
+ @cert_path = config.cert_path
12
+ end
13
+
14
+ # Return SSL certificate
15
+ def cert
16
+ @cert ||= OpenSSL::X509::Certificate.new(cert_content)
17
+ end
18
+
19
+ # Return SSL certificate key
20
+ def key
21
+ @key = OpenSSL::PKey::RSA.new(cert_content)
22
+ end
23
+
24
+ private
25
+ # Return certificate content from the configured file.
26
+ def cert_content
27
+ @cert_content ||= File.read(cert_path)
28
+ end
29
+
30
+ end
31
+ end
32
+ end
@@ -0,0 +1,22 @@
1
+ module PayPal::SDK::Core
2
+ module Credential
3
+ class Signature < Base
4
+
5
+ attr_accessor :signature
6
+
7
+ # Initialize configuration
8
+ # === Argument
9
+ # * <tt>config</tt> -- Configuration object
10
+ def initialize(config)
11
+ super
12
+ self.signature = config.signature
13
+ end
14
+
15
+ # Return properties for authentication
16
+ def properties
17
+ super.merge({ :signature => signature })
18
+ end
19
+
20
+ end
21
+ end
22
+ end
@@ -0,0 +1,25 @@
1
+ module PayPal::SDK::Core
2
+ module Credential
3
+ module ThirdParty
4
+ class Subject
5
+
6
+ attr_accessor :subject, :credential
7
+
8
+ # Initialize configuration
9
+ # === Arguments
10
+ # * <tt>credential</tt> -- Credential object
11
+ # * <tt>config</tt> -- Configuration object
12
+ def initialize(credential, config)
13
+ @credential = credential
14
+ @subject = config.subject
15
+ end
16
+
17
+ # Return properties for authentication.
18
+ def properties
19
+ credential.properties.merge( :subject => subject )
20
+ end
21
+
22
+ end
23
+ end
24
+ end
25
+ end
@@ -0,0 +1,39 @@
1
+ module PayPal::SDK::Core
2
+ module Credential
3
+ module ThirdParty
4
+ class Token
5
+
6
+ attr_accessor :token, :token_secret, :credential, :url
7
+
8
+ # Initialize Token credentials
9
+ # === Arguments
10
+ # * <tt>credential</tt> -- Credential Object
11
+ # * <tt>config</tt> -- Configuration object
12
+ # * <tt>url</tt> -- Request url
13
+ def initialize(credential, config, url)
14
+ @credential = credential
15
+ @token = config.token
16
+ @token_secret = config.token_secret
17
+ @url = url
18
+ end
19
+
20
+ RemoveProperties = [ :username, :password, :signature ]
21
+
22
+ # Return credential properties for authentication.
23
+ def properties
24
+ credential_properties = credential.properties
25
+ credential_properties.delete_if{|k,v| RemoveProperties.include? k }
26
+ credential_properties.merge( :authorization => oauth_authentication )
27
+ end
28
+
29
+ private
30
+ # Return OAuth authentication string.
31
+ def oauth_authentication
32
+ Util::OauthSignature.new(credential.username, credential.password, token, token_secret, url).
33
+ authorization_string
34
+ end
35
+
36
+ end
37
+ end
38
+ end
39
+ end
@@ -0,0 +1,112 @@
1
+ require 'json'
2
+ require 'pp'
3
+
4
+ module PayPal::SDK::Core
5
+ module Exceptions
6
+ class ConnectionError < StandardError # :nodoc:
7
+ attr_reader :response
8
+
9
+ def initialize(response, message = nil)
10
+ @response = response
11
+ @message = message
12
+ end
13
+
14
+ def to_s
15
+ begin
16
+ response_body = JSON.parse(response.body)
17
+ debug_id = response["paypal-debug-id"]
18
+ debug_id = response["correlation-id"] if debug_id.to_s == ''
19
+ debug_id = response_body["debug_id"] if debug_id.to_s == ''
20
+ rescue
21
+ end
22
+ message = "Failed."
23
+ message << " Response code = #{response.code}." if response.respond_to?(:code)
24
+ message << " Response message = #{response.message}." if response.respond_to?(:message)
25
+ message << " Response debug ID = #{debug_id}." if debug_id
26
+ message
27
+ end
28
+ end
29
+
30
+ # Raised when a Timeout::Error occurs.
31
+ class TimeoutError < ConnectionError
32
+ def initialize(message)
33
+ @message = message
34
+ end
35
+ def to_s; @message ;end
36
+ end
37
+
38
+ # Raised when a OpenSSL::SSL::SSLError occurs.
39
+ class SSLError < ConnectionError
40
+ def initialize(message)
41
+ @message = message
42
+ end
43
+ def to_s; @message ;end
44
+ end
45
+
46
+ # 3xx Redirection
47
+ class Redirection < ConnectionError # :nodoc:
48
+ def to_s
49
+ response['Location'] ? "#{super} => #{response['Location']}" : super
50
+ end
51
+ end
52
+
53
+ class MissingParam < ArgumentError # :nodoc:
54
+ end
55
+
56
+ class MissingConfig < StandardError # :nodoc:
57
+ end
58
+
59
+ # 4xx Client Error
60
+ class ClientError < ConnectionError # :nodoc:
61
+ end
62
+
63
+ # 400 Bad Request
64
+ class BadRequest < ClientError # :nodoc:
65
+ end
66
+
67
+ # 401 Unauthorized
68
+ class UnauthorizedAccess < ClientError # :nodoc:
69
+ end
70
+
71
+ # 403 Forbidden
72
+ class ForbiddenAccess < ClientError # :nodoc:
73
+ end
74
+
75
+ # 404 Not Found
76
+ class ResourceNotFound < ClientError # :nodoc:
77
+ end
78
+
79
+ # 409 Conflict
80
+ class ResourceConflict < ClientError # :nodoc:
81
+ end
82
+
83
+ # 410 Gone
84
+ class ResourceGone < ClientError # :nodoc:
85
+ end
86
+
87
+ # 422 Unprocessable Entity
88
+ class ResourceInvalid < ClientError # :nodoc:
89
+ end
90
+
91
+ # 5xx Server Error
92
+ class ServerError < ConnectionError # :nodoc:
93
+ end
94
+
95
+ # 405 Method Not Allowed
96
+ class MethodNotAllowed < ClientError # :nodoc:
97
+ def allowed_methods
98
+ @response['Allow'].split(',').map { |verb| verb.strip.downcase.to_sym }
99
+ end
100
+ end
101
+
102
+ # API error: returned as 200 + "error" key in response.
103
+ class UnsuccessfulApiCall < RuntimeError
104
+ attr_reader :api_error
105
+
106
+ def initialize(api_error)
107
+ super(api_error['message'])
108
+ @api_error = api_error
109
+ end
110
+ end
111
+ end
112
+ end
@@ -0,0 +1,50 @@
1
+ require 'logger'
2
+
3
+ module PayPal::SDK::Core
4
+
5
+ # Include Logging module to provide logger functionality.
6
+ # == Configure logger
7
+ # Logging.logger = Logger.new(STDERR)
8
+ #
9
+ # == Example
10
+ # include Logger
11
+ # logger.info "Debug message"
12
+ module Logging
13
+
14
+ # Get logger object
15
+ def logger
16
+ @logger ||= Logging.logger
17
+ end
18
+
19
+ def log_event(message, &block)
20
+ start_time = Time.now
21
+ block.call
22
+ ensure
23
+ logger.info sprintf("[%.3fs] %s", Time.now - start_time, message)
24
+ end
25
+
26
+ class << self
27
+
28
+ # Get or Create configured logger based on the default environment configuration
29
+ def logger
30
+ @logger ||= Logger.new(STDERR)
31
+ end
32
+
33
+ # Set logger directly and clear the loggers cache.
34
+ # === Attributes
35
+ # * <tt>logger</tt> -- Logger object
36
+ # === Example
37
+ # Logging.logger = Logger.new(STDERR)
38
+ def logger=(logger)
39
+ @logger = logger
40
+ if Config.config.mode.eql? 'live' and @logger.level == Logger::DEBUG
41
+ @logger.warn "DEBUG log level not allowed in sandbox mode for security of confidential information. Changing log level to INFO..."
42
+ @logger.level = Logger::INFO
43
+ end
44
+ end
45
+
46
+ end
47
+ end
48
+
49
+ end
50
+
@@ -0,0 +1,140 @@
1
+
2
+ module PayPal::SDK
3
+ module Core
4
+ module OpenIDConnect
5
+ autoload :API, "paypal-sdk/core/openid_connect/api"
6
+ autoload :SetAPI, "paypal-sdk/core/openid_connect/set_api"
7
+ autoload :GetAPI, "paypal-sdk/core/openid_connect/get_api"
8
+ autoload :RequestDataType, "paypal-sdk/core/openid_connect/request_data_type"
9
+ autoload :DataTypes, "paypal-sdk/core/openid_connect/data_types"
10
+
11
+ include DataTypes
12
+
13
+ class << self
14
+ def api
15
+ RequestDataType.api
16
+ end
17
+
18
+ def set_config(*args)
19
+ RequestDataType.set_config(*args)
20
+ end
21
+ alias_method :config=, :set_config
22
+
23
+ AUTHORIZATION_URL = "paypal.com/signin/authorize"
24
+ ENDSESSION_URL = "paypal.com/webapps/auth/protocol/openidconnect/v1/endsession"
25
+ DEFAULT_SCOPE = "openid"
26
+
27
+ def authorize_url(params = {})
28
+ uri = URI(url_for_mode(AUTHORIZATION_URL))
29
+ uri.query = api.encode_www_form({
30
+ :response_type => "code",
31
+ :scope => DEFAULT_SCOPE,
32
+ :client_id => RequestDataType.client_id,
33
+ :redirect_uri => api.config.openid_redirect_uri
34
+ }.merge(params))
35
+ uri.to_s
36
+ end
37
+
38
+ def logout_url(params = {})
39
+ uri = URI(url_for_mode(ENDSESSION_URL))
40
+ uri.query = api.encode_www_form({
41
+ :logout => "true",
42
+ :redirect_uri => api.config.openid_redirect_uri
43
+ }.merge(params))
44
+ uri.to_s
45
+ end
46
+
47
+ private
48
+
49
+ def url_for_mode(url)
50
+ "https://www.#{"sandbox." if api.api_mode == :sandbox}#{url}"
51
+ end
52
+ end
53
+
54
+ module DataTypes
55
+ class Tokeninfo < Base
56
+ include RequestDataType
57
+ PATH = "v1/identity/openidconnect/tokenservice"
58
+ FP_PATH = "v1/oauth2/token"
59
+
60
+ class << self
61
+
62
+ def basic_auth_header(options)
63
+ credentials = options[:client_id].to_s + ":" + options[:client_secret].to_s
64
+ encoded = Base64.encode64(credentials.force_encoding('UTF-8')).gsub!(/\n/, "")
65
+ "Basic #{encoded}"
66
+ end
67
+
68
+ def create_from_authorization_code(options, http_header = {})
69
+ options = { :code => options } if options.is_a? String
70
+ options = options.merge( :grant_type => "authorization_code" )
71
+ Tokeninfo.new(api.post(PATH, with_credentials(options), http_header))
72
+ end
73
+ alias_method :create, :create_from_authorization_code
74
+
75
+ def create_from_refresh_token(options, http_header = {})
76
+ options = { :refresh_token => options } if options.is_a? String
77
+ options = options.merge( :grant_type => "refresh_token" )
78
+ http_header = http_header.merge( { "Content-Type" => "application/x-www-form-urlencoded", "Authorization" => basic_auth_header(with_credentials(options)) } )
79
+ Tokeninfo.new(api.post(PATH, options, http_header))
80
+ end
81
+ alias_method :refresh, :create_from_refresh_token
82
+
83
+ def create_from_future_payment_auth_code(options, http_header = {})
84
+ options = { :code => options } if options.is_a? String
85
+ options = options.merge( { :grant_type => "authorization_code", :response_type => "token", :redirect_uri => "urn:ietf:wg:oauth:2.0:oob" } )
86
+ http_header = http_header.merge( { "Content-Type" => "application/x-www-form-urlencoded", "Authorization" => basic_auth_header(with_credentials(options)) } )
87
+ Tokeninfo.new(api.post(FP_PATH, options, http_header))
88
+ end
89
+ alias_method :token_hash, :create_from_future_payment_auth_code
90
+ alias_method :create_fp, :create_from_future_payment_auth_code
91
+
92
+ def with_credentials(options = {})
93
+ options = options.dup
94
+ [ :client_id, :client_secret ].each do |key|
95
+ options[key] = self.send(key) unless options[key] or options[key.to_s]
96
+ end
97
+ options
98
+ end
99
+
100
+ def authorize_url(options = {})
101
+ OpenIDConnect.authorize_url(options)
102
+ end
103
+ end
104
+
105
+ def refresh(options = {})
106
+ tokeninfo = self.class.refresh({
107
+ :refresh_token => self.refresh_token}.merge(options))
108
+ self.merge!(tokeninfo.to_hash)
109
+ end
110
+
111
+ def userinfo(options = {})
112
+ Userinfo.get({ :access_token => self.access_token }.merge(options))
113
+ end
114
+
115
+ def logout_url(options = {})
116
+ OpenIDConnect.logout_url({ :id_token => self.id_token }.merge(options))
117
+ end
118
+
119
+ end
120
+
121
+ class Userinfo < Base
122
+ include RequestDataType
123
+ PATH = "v1/identity/openidconnect/userinfo"
124
+
125
+ class << self
126
+ def get_userinfo(options = {}, http_header = {})
127
+ options = { :access_token => options } if options.is_a? String
128
+ options = options.merge( :schema => "openid" ) unless options[:schema] or options["schema"]
129
+ Userinfo.new(api.post(PATH, options, http_header))
130
+ end
131
+ alias_method :get, :get_userinfo
132
+ end
133
+ end
134
+ end
135
+ end
136
+ end
137
+
138
+ # Alias for the Core::OpenIDConnect constant
139
+ OpenIDConnect = Core::OpenIDConnect
140
+ end