paypal-sdk-core 0.1.5 → 0.2.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.
checksums.yaml ADDED
@@ -0,0 +1,15 @@
1
+ ---
2
+ !binary "U0hBMQ==":
3
+ metadata.gz: !binary |-
4
+ ZWMwM2MzM2I5ZDkwMDY1ZWE1NDFkODJhMzQxMmEwZDM4NzhlMzk0YQ==
5
+ data.tar.gz: !binary |-
6
+ ZTA1MGNhNjE3MzdmZTBmNjY2M2IxNjU2YzNkM2FlMmVhYmMyNjBjNg==
7
+ !binary "U0hBNTEy":
8
+ metadata.gz: !binary |-
9
+ NDFmMzU2ZGNiM2JhOWM0ZDQ5NTI5MTUyNjY1MDU2MzA0ZTlmMDVmNWY2Yzc3
10
+ ZjE4ODBkMWViNjQ4Y2NhNGY4NjIzOThkOTBiMzI4ZDE3NmNkNmYzMzVjYzky
11
+ MjBiYTc0ZWFhZjBiZTliYWUxODM3NWFhZWExZGU2MWYyNDMzMjQ=
12
+ data.tar.gz: !binary |-
13
+ YWE5YjYwNjYzYWIxOGFhMDMzNGIwY2UyODcwZjg4OGIxZjliMzllNTJjOGFi
14
+ Y2MwMWFlZTNlOWEzNGYyZWY1YjA2ZTI5Njc2NjY2YTg2NmE2OTE1Y2ZlM2Qw
15
+ YzdkMzI5MjY0NTY0YjFiNDIwMTJiM2IzYWU4NzlkMWE2MWY5ZDQ=
File without changes
@@ -1,32 +1,29 @@
1
1
  test: &default
2
+
3
+ # Credentials for New APIs
4
+ client_id: EBWKjlELKMYqRNQ6sYvFo64FtaRLRR5BdHEESmha49TM
5
+ client_secret: EO422dn3gQLgDbuwqTjzrFgFtaRLRR5BdHEESmha49TM
6
+
7
+ # Mode can be 'live' or 'sandbox'
8
+ mode: sandbox
9
+
10
+ # Credentials for Classic APIs
2
11
  username: jb-us-seller_api1.paypal.com
3
12
  password: WX4WTU3S8MY44S7F
4
13
  signature: AFcWxV21C7fd0v3bYYYRCpSSRl31A7yDhhsPUU2XhtMoZXsWHFxu-RWy
5
14
  app_id: APP-80W284485P519543T
6
- http_timeout: 30
7
- mode: sandbox
15
+ # # With Certificate
16
+ # cert_path: "config/cert_key.pem"
8
17
  sandbox_email_address: Platform.sdk.seller@gmail.com
9
18
 
19
+ # # IP Address
20
+ # ip_address: 127.0.0.1
21
+ # # HTTP Proxy
22
+ # http_proxy: http://proxy-ipaddress:3129/
23
+
10
24
  development:
11
25
  <<: *default
12
26
 
13
27
  production:
14
28
  <<: *default
15
29
  mode: live
16
-
17
- # with_certificate:
18
- # <<: *default
19
- # username: platfo_1255170694_biz_api1.gmail.com
20
- # password: 2DPPKUPKB7DQLXNR
21
- # signature:
22
- # cert_path: "config/cert_key.pem"
23
- # app_id: APP-80W284485P519543T
24
- #
25
- # with_oauth_token:
26
- # <<: *default
27
- # token: ESTy2hio5WJQo1iixkH29I53RJxaS0Gvno1A6.YQXZgktxbY4I2Tdg
28
- # token_secret: ZKPhUYuwJwYsfWdzorozWO2U9pI
29
- #
30
- # with_proxy:
31
- # <<: *default
32
- # http_proxy: http://proxy-ipaddress:3129/
@@ -1,17 +1,19 @@
1
- require "paypal-sdk/core/version"
2
- require "paypal-sdk/core/config"
3
- require "paypal-sdk/core/logging"
4
-
5
1
  module PayPal
6
2
  module SDK
7
3
  module Core
8
4
 
5
+ autoload :VERSION, "paypal-sdk/core/version"
6
+ autoload :Config, "paypal-sdk/core/config"
7
+ autoload :Configuration, "paypal-sdk/core/config"
8
+ autoload :Logging, "paypal-sdk/core/logging"
9
9
  autoload :Authentication, "paypal-sdk/core/authentication"
10
+ autoload :Exceptions, "paypal-sdk/core/exceptions"
10
11
 
11
12
  module API
12
13
  autoload :Base, "paypal-sdk/core/api/base"
13
14
  autoload :Merchant, "paypal-sdk/core/api/merchant"
14
15
  autoload :Platform, "paypal-sdk/core/api/platform"
16
+ autoload :REST, "paypal-sdk/core/api/rest"
15
17
  autoload :IPN, "paypal-sdk/core/api/ipn"
16
18
 
17
19
  module DataTypes
@@ -25,6 +27,7 @@ module PayPal
25
27
  module Util
26
28
  autoload :OauthSignature, "paypal-sdk/core/util/oauth_signature"
27
29
  autoload :OrderedHash, "paypal-sdk/core/util/ordered_hash"
30
+ autoload :HTTPHelper, "paypal-sdk/core/util/http_helper"
28
31
  end
29
32
 
30
33
  module Credential
@@ -1,5 +1,3 @@
1
- require 'net/https'
2
-
3
1
  module PayPal::SDK::Core
4
2
 
5
3
  module API
@@ -9,35 +7,12 @@ module PayPal::SDK::Core
9
7
  # response = api.request("GetPaymentOptions", "")
10
8
  class Base
11
9
 
12
- include Configuration
13
- include Logging
14
- include Authentication
10
+ include Util::HTTPHelper
15
11
 
16
12
  attr_accessor :http, :uri, :service_name
17
13
 
18
- DEFAULT_END_POINTS = {
19
- :sandbox => {
20
- :platform => { # NVP EndPoint
21
- :three_token => "https://svcs.sandbox.paypal.com/",
22
- :certificate => "https://svcs.sandbox.paypal.com/"
23
- },
24
- :merchant => { # SOAP EndPoint
25
- :three_token => "https://api-3t.sandbox.paypal.com/2.0",
26
- :certificate => "https://api.sandbox.paypal.com/2.0"
27
- }
28
- },
29
- :live => {
30
- :platform => { # NVP EndPoint
31
- :three_token => "https://svcs.paypal.com/",
32
- :certificate => "https://svcs.paypal.com/"
33
- },
34
- :merchant => { # SOAP EndPoint
35
- :three_token => "https://api-3t.paypal.com/2.0",
36
- :certificate => "https://api.paypal.com/2.0"
37
- }
38
- }
39
- }
40
- DEFAULT_HTTP_HEADER = {}
14
+ DEFAULT_API_MODE = :sandbox
15
+ API_MODES = [ :live, :sandbox ]
41
16
 
42
17
  # Initialize API object
43
18
  # === Argument
@@ -56,89 +31,89 @@ module PayPal::SDK::Core
56
31
  set_config(environment, options)
57
32
  end
58
33
 
59
- # Override set_config method to create http connection on changing the configuration.
60
- def set_config(*args)
61
- super
62
- create_http_connection
34
+ def uri
35
+ @uri ||=
36
+ begin
37
+ uri = URI.parse("#{service_endpoint}/#{service_name}")
38
+ uri.path = uri.path.gsub(/\/+/, "/")
39
+ uri
40
+ end
63
41
  end
64
42
 
65
- # Create HTTP connection based on given service name or configured end point
66
- def create_http_connection
67
- service_path = "#{service_endpoint}/#{service_name}"
68
- @uri = URI.parse(service_path)
69
- if config.http_proxy
70
- proxy = URI.parse(config.http_proxy)
71
- @http = Net::HTTP.new(@uri.host, @uri.port, proxy.host, proxy.port, proxy.user, proxy.password)
72
- else
73
- @http = Net::HTTP.new(@uri.host, @uri.port)
74
- end
75
- @uri.path = @uri.path.gsub(/\/+/, "/")
76
- configure_http_connection
43
+ def http
44
+ @http ||= create_http_connection(uri)
77
45
  end
78
46
 
79
- # Configure HTTP connection based on configuration.
80
- def configure_http_connection
81
- if @uri.scheme == "https"
82
- http.use_ssl = true
83
- if config.ca_file
84
- http.verify_mode = OpenSSL::SSL::VERIFY_PEER
85
- http.ca_file = config.ca_file
86
- end
87
- end
88
- if config.http_timeout
89
- http.open_timeout = config.http_timeout
90
- http.read_timeout = config.http_timeout
91
- end
92
- add_certificate(http)
47
+ # Override set_config method to create http connection on changing the configuration.
48
+ def set_config(*args)
49
+ @http = @uri = nil
50
+ super
93
51
  end
94
52
 
95
53
  # Get configured API mode( sandbox or live)
96
54
  def api_mode
97
- api_modes = DEFAULT_END_POINTS.keys
98
- config_mode = ( config.mode || api_modes.first ).to_sym
99
- api_modes.include?(config_mode) ? config_mode : api_modes.first
100
- end
101
-
102
- # Get default endpoint for the given service name
103
- # === Argument
104
- # * <tt>name</tt> -- Service name ( platform or merchant)
105
- # === Returns
106
- # Return service end point based on the configured API mode.
107
- def default_end_point(name)
108
- default_end_point = DEFAULT_END_POINTS[api_mode][name]
109
- if default_end_point
110
- config.cert_path ? default_end_point[:certificate] : default_end_point[:three_token]
55
+ if config.mode and API_MODES.include? config.mode.to_sym
56
+ config.mode.to_sym
57
+ else
58
+ DEFAULT_API_MODE
111
59
  end
112
60
  end
113
61
 
114
62
  # Get service end point
115
63
  def service_endpoint
116
- config.end_point ? default_end_point(config.end_point.to_sym) : config.end_point
64
+ config.endpoint
117
65
  end
118
66
 
119
67
  # Default Http header
120
68
  def default_http_header
121
- DEFAULT_HTTP_HEADER
69
+ { "User-Agent" => self.class.user_agent }
122
70
  end
123
71
 
124
72
  # Generate HTTP request for given action and parameters
125
73
  # === Arguments
74
+ # * <tt>http_method</tt> -- HTTP method(get/put/post/delete/patch)
126
75
  # * <tt>action</tt> -- Action to perform
127
76
  # * <tt>params</tt> -- (Optional) Parameters for the action
128
77
  # * <tt>initheader</tt> -- (Optional) HTTP header
129
- def request(action, params = {}, initheader = {})
130
- uri, content, header = format_request(action, params)
131
- initheader = default_http_header.merge(header).merge(initheader)
132
- initheader.delete_if{|key, val| val.nil? }
133
- response =
134
- log_event("Request: #{action}") do
135
- @http.post(uri.path, content, initheader)
136
- end
137
- format_response(action, response)
78
+ def api_call(payload)
79
+ payload[:header] = default_http_header.merge(payload[:header])
80
+ payload[:uri] ||= uri.dup
81
+ payload[:http] ||= http.dup
82
+ payload[:uri].query = encode_www_form(payload[:query]) if payload[:query] and payload[:query].any?
83
+ format_request(payload)
84
+ payload[:response] = http_call(payload)
85
+ format_response(payload)
86
+ payload[:data]
138
87
  rescue Net::HTTPBadGateway, Errno::ECONNRESET, Errno::ECONNABORTED, SocketError => error
139
88
  format_error(error, error.message)
140
89
  end
141
90
 
91
+ # Generate HTTP request for given action and parameters
92
+ # === Arguments
93
+ # * <tt>action</tt> -- Action to perform
94
+ # * <tt>params</tt> -- (Optional) Parameters for the action
95
+ # * <tt>initheader</tt> -- (Optional) HTTP header
96
+ def post(action, params = {}, header = {})
97
+ api_call(:method => :post, :action => action, :params => params, :header => header)
98
+ end
99
+ alias_method :request, :post
100
+
101
+ def get(action, params = {}, header = {})
102
+ api_call(:method => :get, :action => action, :query => params, :params => nil, :header => header)
103
+ end
104
+
105
+ def patch(action, params = {}, header = {})
106
+ api_call(:method => :patch, :action => action, :params => params, :header => header)
107
+ end
108
+
109
+ def put(action, params = {}, header = {})
110
+ api_call(:method => :put, :action => action, :params => params, :header => header)
111
+ end
112
+
113
+ def delete(action, params = {}, header = {})
114
+ api_call(:method => :delete, :action => action, :params => params, :header => header)
115
+ end
116
+
142
117
  # Format Request data. It will be override by child class
143
118
  # == Arguments
144
119
  # * <tt>action</tt> -- Request action
@@ -147,16 +122,19 @@ module PayPal::SDK::Core
147
122
  # * <tt>path</tt> -- Formated request uri object
148
123
  # * <tt>params</tt> -- Formated request Parameters
149
124
  # * <tt>header</tt> -- HTTP Header
150
- def format_request(action, params)
151
- [ @uri, params, {} ]
125
+ def format_request(payload)
126
+ payload[:uri].path = url_join(payload[:uri].path, payload[:action])
127
+ payload[:body] = payload[:params].to_s
128
+ payload
152
129
  end
153
130
 
154
131
  # Format Response object. It will be override by child class
155
132
  # == Argument
156
133
  # * <tt>action</tt> -- Request action
157
134
  # * <tt>response</tt> -- HTTP response object
158
- def format_response(action, response)
159
- response
135
+ def format_response(payload)
136
+ payload[:data] = payload[:response].body
137
+ payload
160
138
  end
161
139
 
162
140
  # Format Error object. It will be override by child class.
@@ -166,6 +144,12 @@ module PayPal::SDK::Core
166
144
  def format_error(exception, message)
167
145
  raise exception
168
146
  end
147
+
148
+ class << self
149
+ def user_agent
150
+ @user_agent ||= "paypal-sdk-core/#{VERSION} #{RUBY_DESCRIPTION}"
151
+ end
152
+ end
169
153
  end
170
154
  end
171
155
  end
@@ -110,20 +110,32 @@ module PayPal::SDK::Core
110
110
 
111
111
  # Initialize options.
112
112
  def initialize(options = {}, &block)
113
+ merge!(options, &block)
114
+ end
115
+
116
+ # Merge values
117
+ def merge!(options, &block)
113
118
  if options.is_a? Hash
114
119
  options.each do |key, value|
115
- begin
116
- send("#{key}=", value)
117
- rescue TypeError, ArgumentError => error
118
- raise TypeError, "#{error.message}(#{value.inspect}) for #{self.class.name}.#{key} member"
119
- end
120
+ set(key, value)
120
121
  end
121
122
  elsif members[ContentKey]
122
- self.value = options
123
+ set(ContentKey, options)
123
124
  else
124
125
  raise ArgumentError, "invalid data(#{options.inspect}) for #{self.class.name} class"
125
126
  end
126
127
  self.instance_eval(&block) if block
128
+ self
129
+ end
130
+
131
+ # Set value for given member
132
+ # === Arguments
133
+ # * <tt>key</tt> -- member name
134
+ # * <tt>value</tt> -- value for member
135
+ def set(key, value)
136
+ send("#{key}=", value)
137
+ rescue TypeError, ArgumentError => error
138
+ raise TypeError, "#{error.message}(#{value.inspect}) for #{self.class.name}.#{key} member"
127
139
  end
128
140
 
129
141
  # Create array of objects.
@@ -1,5 +1,3 @@
1
- require 'net/https'
2
-
3
1
  module PayPal
4
2
  module SDK
5
3
  module Core
@@ -14,7 +12,7 @@ module PayPal
14
12
  INVALID = "INVALID"
15
13
 
16
14
  class Message
17
- include PayPal::SDK::Core::Configuration
15
+ include Util::HTTPHelper
18
16
 
19
17
  attr_accessor :message
20
18
 
@@ -24,31 +22,23 @@ module PayPal
24
22
  end
25
23
 
26
24
  # Fetch end point
27
- def ipn_end_point
28
- config.ipn_end_point || default_ipn_end_point
25
+ def ipn_endpoint
26
+ config.ipn_endpoint || default_ipn_endpoint
29
27
  end
30
28
 
31
29
  # Default IPN end point
32
- def default_ipn_end_point
33
- end_point = END_POINTS[(config.mode || :sandbox).to_sym] rescue nil
34
- end_point || END_POINTS[:sandbox]
30
+ def default_ipn_endpoint
31
+ endpoint = END_POINTS[(config.mode || :sandbox).to_sym] rescue nil
32
+ endpoint || END_POINTS[:sandbox]
35
33
  end
36
34
 
37
35
  # Request IPN service for validating the content
38
36
  # === Return
39
37
  # return http response object
40
38
  def request
41
- uri = URI(ipn_end_point)
42
- http = Net::HTTP.new(uri.host, uri.port)
43
- if uri.scheme == "https"
44
- http.use_ssl = true
45
- if config.ca_file
46
- http.verify_mode = OpenSSL::SSL::VERIFY_PEER
47
- http.ca_file = config.ca_file
48
- end
49
- end
39
+ uri = URI(ipn_endpoint)
50
40
  query_string = "cmd=_notify-validate&#{message}"
51
- http.post(uri.path, query_string)
41
+ http_call(:method => :post, :uri => uri, :body => query_string)
52
42
  end
53
43
 
54
44
  # Validate the given content
@@ -35,10 +35,20 @@ module PayPal::SDK::Core
35
35
  :signature => "ebl:Signature",
36
36
  :subject => "ebl:Subject"
37
37
  }
38
+ DEFAULT_END_POINTS = {
39
+ :sandbox => {
40
+ :three_token => "https://api-3t.sandbox.paypal.com/2.0/",
41
+ :certificate => "https://api.sandbox.paypal.com/2.0/"
42
+ },
43
+ :live => {
44
+ :three_token => "https://api-3t.paypal.com/2.0/",
45
+ :certificate => "https://api.paypal.com/2.0/"
46
+ }
47
+ }
38
48
 
39
- # Get SOAP or default end point
49
+ # Get services end point
40
50
  def service_endpoint
41
- config.merchant_end_point || super || default_end_point(:merchant)
51
+ config.merchant_endpoint || config.endpoint || DEFAULT_END_POINTS[api_mode][base_credential_type]
42
52
  end
43
53
 
44
54
  # Format the HTTP request content
@@ -48,22 +58,24 @@ module PayPal::SDK::Core
48
58
  # === Return
49
59
  # * <tt>request_path</tt> -- Soap request path. DEFAULT("/")
50
60
  # * <tt>request_content</tt> -- Request content in SOAP format.
51
- def format_request(action, params)
61
+ def format_request(payload)
52
62
  credential_properties = credential(uri.to_s).properties
53
63
  user_auth_header = map_header_value(SOAP_AUTH_HEADER, credential_properties)
54
- content_key = params.keys.first.is_a?(Symbol) ? ContentKey.to_sym : ContentKey.to_s
64
+ content_key = payload[:params].keys.first.is_a?(Symbol) ? ContentKey.to_sym : ContentKey.to_s
55
65
  xml_out_options = XML_OUT_OPTIONS.merge( 'ContentKey' => content_key )
56
66
  request_content = XmlSimple.xml_out({
57
67
  "soapenv:Envelope" => {
58
68
  content_key => (
59
- XmlSimple.xml_out({"soapenv:Header" => { "ns:RequesterCredentials" => {
69
+ XmlSimple.xml_out({"soapenv:Header" => { "ns:RequesterCredentials" => {
60
70
  "ebl:Credentials" => user_auth_header
61
71
  }}}, xml_out_options) +
62
- XmlSimple.xml_out({"soapenv:Body" => body(action, params)}, xml_out_options))
72
+ XmlSimple.xml_out({"soapenv:Body" => request_body(payload[:action], payload[:params])}, xml_out_options))
63
73
  }.merge(Namespaces)
64
74
  }, xml_out_options.merge('noescape' => true))
65
75
  header = map_header_value(SOAP_HTTP_AUTH_HEADER, credential_properties)
66
- [ @uri, request_content, header ]
76
+ payload[:header] = header.merge(header)
77
+ payload[:body] = request_content
78
+ payload
67
79
  end
68
80
 
69
81
  # Format Response object
@@ -72,14 +84,22 @@ module PayPal::SDK::Core
72
84
  # * <tt>response</tt> -- Response object
73
85
  # === Return
74
86
  # Parse the SOAP response content and return Hash object
75
- def format_response(action, response)
76
- if response.code == "200"
77
- hash = XmlSimple.xml_in(response.body, XML_IN_OPTIONS)
78
- hash = skip_attributes(hash)
79
- hash["Body"].find{|key_val| key_val[0] =~ /^[^@]/ }[1] || {}
80
- else
81
- format_error(response, response.message)
82
- end
87
+ def format_response(payload)
88
+ payload[:data] =
89
+ if payload[:response].code == "200"
90
+ hash = XmlSimple.xml_in(payload[:response].body, XML_IN_OPTIONS)
91
+ hash = skip_attributes(hash)
92
+ hash["Body"].find{|key_val| key_val[0] =~ /^[^@]/ }[1] || {}
93
+ else
94
+ format_error(payload[:response], payload[:response].message)
95
+ end
96
+ payload
97
+ end
98
+
99
+ # Log additional information
100
+ def log_http_call(payload)
101
+ logger.info "Action: #{payload[:action]}" if payload[:action]
102
+ super
83
103
  end
84
104
 
85
105
  private
@@ -88,7 +108,7 @@ module PayPal::SDK::Core
88
108
  # == Arguments
89
109
  # * <tt>action</tt> -- Request Action name
90
110
  # * <tt>params</tt> -- Parameters for the action.
91
- def body(action, params = {})
111
+ def request_body(action, params = {})
92
112
  { "ns:#{action}Req" => { "ns:#{action}Request" => DEFAULT_PARAMS.merge(params) } }
93
113
  end
94
114