paypal-sdk-rest-pmrb 1.8.0

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 (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