paypal-rest-api 0.3.1 → 0.5.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (40) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +97 -16
  3. data/VERSION +1 -1
  4. data/lib/paypal-api/api_collections/authentication.rb +1 -1
  5. data/lib/paypal-api/api_collections/authorized_payments.rb +1 -1
  6. data/lib/paypal-api/api_collections/captured_payments.rb +1 -1
  7. data/lib/paypal-api/api_collections/catalog_products.rb +1 -1
  8. data/lib/paypal-api/api_collections/disputes.rb +1 -1
  9. data/lib/paypal-api/api_collections/invoice_templates.rb +1 -1
  10. data/lib/paypal-api/api_collections/invoices.rb +1 -1
  11. data/lib/paypal-api/api_collections/orders.rb +1 -1
  12. data/lib/paypal-api/api_collections/partner_referrals.rb +48 -0
  13. data/lib/paypal-api/api_collections/payment_experience_web_profiles.rb +94 -0
  14. data/lib/paypal-api/api_collections/payment_tokens.rb +70 -0
  15. data/lib/paypal-api/api_collections/payout_items.rb +1 -1
  16. data/lib/paypal-api/api_collections/payouts.rb +1 -1
  17. data/lib/paypal-api/api_collections/referenced_payout_items.rb +2 -2
  18. data/lib/paypal-api/api_collections/referenced_payouts.rb +1 -1
  19. data/lib/paypal-api/api_collections/refunds.rb +1 -1
  20. data/lib/paypal-api/api_collections/setup_tokens.rb +47 -0
  21. data/lib/paypal-api/api_collections/shipment_tracking.rb +1 -1
  22. data/lib/paypal-api/api_collections/subscription_plans.rb +1 -1
  23. data/lib/paypal-api/api_collections/subscriptions.rb +1 -1
  24. data/lib/paypal-api/api_collections/transaction_search.rb +46 -0
  25. data/lib/paypal-api/api_collections/user_info.rb +1 -1
  26. data/lib/paypal-api/api_collections/users.rb +2 -2
  27. data/lib/paypal-api/api_collections/webhook_events.rb +1 -1
  28. data/lib/paypal-api/api_collections/webhook_lookups.rb +1 -1
  29. data/lib/paypal-api/api_collections/webhooks.rb +1 -1
  30. data/lib/paypal-api/client/access_token_methods.rb +36 -0
  31. data/lib/paypal-api/client/api_methods.rb +140 -0
  32. data/lib/paypal-api/client/environment_methods.rb +34 -0
  33. data/lib/paypal-api/client/http_methods.rb +70 -0
  34. data/lib/paypal-api/client.rb +5 -215
  35. data/lib/paypal-api/error.rb +3 -1
  36. data/lib/paypal-api/request.rb +47 -22
  37. data/lib/paypal-api/request_executor.rb +32 -15
  38. data/lib/paypal-api/response.rb +68 -0
  39. data/lib/paypal-api.rb +27 -3
  40. metadata +12 -3
@@ -8,7 +8,7 @@ module PaypalAPI
8
8
  #
9
9
  class UserInfo < APICollection
10
10
  #
11
- # Common class and instance methods
11
+ # Common methods for PaypalAPI::UserInfo class and client.user_info instance
12
12
  #
13
13
  module APIs
14
14
  # @!macro [new] request
@@ -4,11 +4,11 @@ module PaypalAPI
4
4
  #
5
5
  # Managing users APIs
6
6
  #
7
- # https://developer.paypal.com/docs/api/identity/v2/
7
+ # @see https://developer.paypal.com/docs/api/identity/v2/
8
8
  #
9
9
  class Users < APICollection
10
10
  #
11
- # Common class and instance methods
11
+ # Common methods for PaypalAPI::Users class and client.users instance
12
12
  #
13
13
  module APIs
14
14
  # @!macro [new] request
@@ -6,7 +6,7 @@ module PaypalAPI
6
6
  #
7
7
  class WebhookEvents < APICollection
8
8
  #
9
- # Common class and instance methods
9
+ # Common methods for PaypalAPI::WebhookEvents class and client.webhook_events instance
10
10
  #
11
11
  module APIs
12
12
  # @!macro [new] request
@@ -6,7 +6,7 @@ module PaypalAPI
6
6
  #
7
7
  class WebhookLookups < APICollection
8
8
  #
9
- # Common class and instance methods
9
+ # Common methods for PaypalAPI::WebhookLookups class and client.webhook_lookups instance
10
10
  #
11
11
  module APIs
12
12
  # @!macro [new] request
@@ -6,7 +6,7 @@ module PaypalAPI
6
6
  #
7
7
  class Webhooks < APICollection
8
8
  #
9
- # Common class and instance methods
9
+ # Common methods for PaypalAPI::Webhooks class and client.webhooks instance
10
10
  #
11
11
  module APIs
12
12
  # @!macro [new] request
@@ -0,0 +1,36 @@
1
+ # frozen_string_literal: true
2
+
3
+ module PaypalAPI
4
+ class Client
5
+ #
6
+ # Client methods to get access token
7
+ #
8
+ module AccessTokenMethods
9
+ #
10
+ # Checks cached access token is expired and returns it or generates new one
11
+ #
12
+ # @return [AccessToken] AccessToken object
13
+ #
14
+ def access_token
15
+ (@access_token.nil? || @access_token.expired?) ? refresh_access_token : @access_token
16
+ end
17
+
18
+ #
19
+ # Generates and caches new AccessToken
20
+ #
21
+ # @return [AccessToken] new AccessToken object
22
+ #
23
+ def refresh_access_token
24
+ requested_at = Time.now
25
+ response = authentication.generate_access_token
26
+
27
+ @access_token = AccessToken.new(
28
+ requested_at: requested_at,
29
+ expires_in: response.fetch(:expires_in),
30
+ access_token: response.fetch(:access_token),
31
+ token_type: response.fetch(:token_type)
32
+ )
33
+ end
34
+ end
35
+ end
36
+ end
@@ -0,0 +1,140 @@
1
+ # frozen_string_literal: true
2
+
3
+ module PaypalAPI
4
+ class Client
5
+ #
6
+ # Methods to access API collections
7
+ #
8
+ module APIMethods
9
+ # @return [AuthorizedPayments] AuthorizedPayments APIs collection
10
+ def authorized_payments
11
+ AuthorizedPayments.new(self)
12
+ end
13
+
14
+ # @return [CapturedPayments] CapturedPayments APIs collection
15
+ def captured_payments
16
+ CapturedPayments.new(self)
17
+ end
18
+
19
+ # @return [Authentication] Authentication APIs collection
20
+ def authentication
21
+ Authentication.new(self)
22
+ end
23
+
24
+ # @return [CatalogProducts] Catalog Products APIs collection
25
+ def catalog_products
26
+ CatalogProducts.new(self)
27
+ end
28
+
29
+ # @return [Disputes] Disputes APIs collection
30
+ def disputes
31
+ Disputes.new(self)
32
+ end
33
+
34
+ # @return [InvoiceTemplates] InvoiceTemplates APIs collection
35
+ def invoice_templates
36
+ InvoiceTemplates.new(self)
37
+ end
38
+
39
+ # @return [Invoices] Invoices APIs collection
40
+ def invoices
41
+ Invoices.new(self)
42
+ end
43
+
44
+ # @return [Orders] Orders APIs collection
45
+ def orders
46
+ Orders.new(self)
47
+ end
48
+
49
+ # @return [PartnerReferrals] PartnerReferrals APIs collection
50
+ def partner_referrals
51
+ PartnerReferrals.new(self)
52
+ end
53
+
54
+ # @return [PaymentExperienceWebProfiles] PaymentExperienceWebProfiles APIs collection
55
+ def payment_experience_web_profiles
56
+ PaymentExperienceWebProfiles.new(self)
57
+ end
58
+
59
+ # @return [PaymentTokens] PaymentTokens APIs collection
60
+ def payment_tokens
61
+ PaymentTokens.new(self)
62
+ end
63
+
64
+ # @return [PayoutItems] PayoutItems APIs collection
65
+ def payout_items
66
+ PayoutItems.new(self)
67
+ end
68
+
69
+ # @return [Payouts] Payouts APIs collection
70
+ def payouts
71
+ Payouts.new(self)
72
+ end
73
+
74
+ # @return [Refunds] Refunds APIs collection
75
+ def refunds
76
+ Refunds.new(self)
77
+ end
78
+
79
+ # @return [ReferencedPayoutItems] ReferencedPayoutItems APIs collection
80
+ def referenced_payout_items
81
+ ReferencedPayoutItems.new(self)
82
+ end
83
+
84
+ # @return [ReferencedPayouts] ReferencedPayouts APIs collection
85
+ def referenced_payouts
86
+ ReferencedPayouts.new(self)
87
+ end
88
+
89
+ # @return [SetupTokens] SetupTokens APIs collection
90
+ def setup_tokens
91
+ SetupTokens.new(self)
92
+ end
93
+
94
+ # @return [ShipmentTracking] Shipment Tracking APIs collection
95
+ def shipment_tracking
96
+ ShipmentTracking.new(self)
97
+ end
98
+
99
+ # @return [Subscriptions] Subscriptions APIs collection
100
+ def subscriptions
101
+ Subscriptions.new(self)
102
+ end
103
+
104
+ # @return [SubscriptionPlans] Subscription Plans APIs collection
105
+ def subscription_plans
106
+ SubscriptionPlans.new(self)
107
+ end
108
+
109
+ # @return [TransactionSearch] TransactionSearch APIs collection
110
+ def transaction_search
111
+ TransactionSearch.new(self)
112
+ end
113
+
114
+ # @return [UserInfo] User Info APIs collection
115
+ def user_info
116
+ UserInfo.new(self)
117
+ end
118
+
119
+ # @return [Users] Users Management APIs collection
120
+ def users
121
+ Users.new(self)
122
+ end
123
+
124
+ # @return [Webhooks] Webhooks APIs collection
125
+ def webhooks
126
+ Webhooks.new(self)
127
+ end
128
+
129
+ # @return [WebhookEvents] Webhook Events APIs collection
130
+ def webhook_lookups
131
+ WebhookLookups.new(self)
132
+ end
133
+
134
+ # @return [WebhookEvents] Webhook Lookups APIs collection
135
+ def webhook_events
136
+ WebhookEvents.new(self)
137
+ end
138
+ end
139
+ end
140
+ end
@@ -0,0 +1,34 @@
1
+ # frozen_string_literal: true
2
+
3
+ module PaypalAPI
4
+ class Client
5
+ #
6
+ # Client environment specific methods
7
+ #
8
+ module EnvironmentMethods
9
+ # Checks if PayPal LIVE environment enabled
10
+ # @return [Boolean] Checks if PayPal LIVE environment enabled
11
+ def live?
12
+ env.live?
13
+ end
14
+
15
+ # Checks if PayPal SANDBOX environment enabled
16
+ # @return [Boolean] Checks if PayPal SANDBOX environment enabled
17
+ def sandbox?
18
+ env.sandbox?
19
+ end
20
+
21
+ # Base API URL
22
+ # @return [String] Base API URL
23
+ def api_url
24
+ env.api_url
25
+ end
26
+
27
+ # Base WEB URL
28
+ # @return [String] Base WEB URL
29
+ def web_url
30
+ env.web_url
31
+ end
32
+ end
33
+ end
34
+ end
@@ -0,0 +1,70 @@
1
+ # frozen_string_literal: true
2
+
3
+ module PaypalAPI
4
+ class Client
5
+ #
6
+ # Client HTTP methods
7
+ #
8
+ module HTTPMethods
9
+ # @!macro [new] request
10
+ # @param path [String] Request path
11
+ # @param query [Hash, nil] Request query parameters
12
+ # @param body [Hash, nil] Request body parameters
13
+ # @param headers [Hash, nil] Request headers
14
+ #
15
+ # @return [Response] Response object
16
+
17
+ #
18
+ # Executes POST http request
19
+ #
20
+ # @macro request
21
+ #
22
+ def post(path, query: nil, body: nil, headers: nil)
23
+ execute_request(Net::HTTP::Post, path, query: query, body: body, headers: headers)
24
+ end
25
+
26
+ #
27
+ # Executes GET http request
28
+ #
29
+ # @macro request
30
+ #
31
+ def get(path, query: nil, body: nil, headers: nil)
32
+ execute_request(Net::HTTP::Get, path, query: query, body: body, headers: headers)
33
+ end
34
+
35
+ #
36
+ # Executes PATCH http request
37
+ #
38
+ # @macro request
39
+ #
40
+ def patch(path, query: nil, body: nil, headers: nil)
41
+ execute_request(Net::HTTP::Patch, path, query: query, body: body, headers: headers)
42
+ end
43
+
44
+ #
45
+ # Executes PUT http request
46
+ #
47
+ # @macro request
48
+ #
49
+ def put(path, query: nil, body: nil, headers: nil)
50
+ execute_request(Net::HTTP::Put, path, query: query, body: body, headers: headers)
51
+ end
52
+
53
+ #
54
+ # Executes DELETE http request
55
+ #
56
+ # @macro request
57
+ #
58
+ def delete(path, query: nil, body: nil, headers: nil)
59
+ execute_request(Net::HTTP::Delete, path, query: query, body: body, headers: headers)
60
+ end
61
+
62
+ private
63
+
64
+ def execute_request(http_method, path, query: nil, body: nil, headers: nil)
65
+ request = Request.new(self, http_method, path, query: query, body: body, headers: headers)
66
+ RequestExecutor.new(self, request).call
67
+ end
68
+ end
69
+ end
70
+ end
@@ -5,6 +5,11 @@ module PaypalAPI
5
5
  # PaypalAPI Client
6
6
  #
7
7
  class Client
8
+ include AccessTokenMethods
9
+ include APIMethods
10
+ include EnvironmentMethods
11
+ include HTTPMethods
12
+
8
13
  # Paypal environment
9
14
  attr_reader :env
10
15
 
@@ -43,30 +48,6 @@ module PaypalAPI
43
48
  @access_token = nil
44
49
  end
45
50
 
46
- # Checks if PayPal LIVE environment enabled
47
- # @return [Boolean] Checks if PayPal LIVE environment enabled
48
- def live?
49
- env.live?
50
- end
51
-
52
- # Checks if PayPal SANDBOX environment enabled
53
- # @return [Boolean] Checks if PayPal SANDBOX environment enabled
54
- def sandbox?
55
- env.sandbox?
56
- end
57
-
58
- # Base API URL
59
- # @return [String] Base API URL
60
- def api_url
61
- env.api_url
62
- end
63
-
64
- # Base WEB URL
65
- # @return [String] Base WEB URL
66
- def web_url
67
- env.web_url
68
- end
69
-
70
51
  # Registers callback
71
52
  #
72
53
  # @param callback_name [Symbol] Callback name.
@@ -90,32 +71,6 @@ module PaypalAPI
90
71
  callbacks.fetch(callback_name) << block
91
72
  end
92
73
 
93
- #
94
- # Checks cached access token is expired and returns it or generates new one
95
- #
96
- # @return [AccessToken] AccessToken object
97
- #
98
- def access_token
99
- (@access_token.nil? || @access_token.expired?) ? refresh_access_token : @access_token
100
- end
101
-
102
- #
103
- # Generates and caches new AccessToken
104
- #
105
- # @return [AccessToken] new AccessToken object
106
- #
107
- def refresh_access_token
108
- requested_at = Time.now
109
- response = authentication.generate_access_token
110
-
111
- @access_token = AccessToken.new(
112
- requested_at: requested_at,
113
- expires_in: response.fetch(:expires_in),
114
- access_token: response.fetch(:access_token),
115
- token_type: response.fetch(:token_type)
116
- )
117
- end
118
-
119
74
  #
120
75
  # Verifies Webhook
121
76
  #
@@ -147,170 +102,5 @@ module PaypalAPI
147
102
  def verify_webhook(webhook_id:, headers:, raw_body:)
148
103
  WebhookVerifier.new(self).call(webhook_id: webhook_id, headers: headers, raw_body: raw_body)
149
104
  end
150
-
151
- # @!macro [new] request
152
- # @param path [String] Request path
153
- # @param query [Hash, nil] Request query parameters
154
- # @param body [Hash, nil] Request body parameters
155
- # @param headers [Hash, nil] Request headers
156
- #
157
- # @return [Response] Response object
158
-
159
- #
160
- # Executes POST http request
161
- #
162
- # @macro request
163
- #
164
- def post(path, query: nil, body: nil, headers: nil)
165
- execute_request(Net::HTTP::Post, path, query: query, body: body, headers: headers)
166
- end
167
-
168
- #
169
- # Executes GET http request
170
- #
171
- # @macro request
172
- #
173
- def get(path, query: nil, body: nil, headers: nil)
174
- execute_request(Net::HTTP::Get, path, query: query, body: body, headers: headers)
175
- end
176
-
177
- #
178
- # Executes PATCH http request
179
- #
180
- # @macro request
181
- #
182
- def patch(path, query: nil, body: nil, headers: nil)
183
- execute_request(Net::HTTP::Patch, path, query: query, body: body, headers: headers)
184
- end
185
-
186
- #
187
- # Executes PUT http request
188
- #
189
- # @macro request
190
- #
191
- def put(path, query: nil, body: nil, headers: nil)
192
- execute_request(Net::HTTP::Put, path, query: query, body: body, headers: headers)
193
- end
194
-
195
- #
196
- # Executes DELETE http request
197
- #
198
- # @macro request
199
- #
200
- def delete(path, query: nil, body: nil, headers: nil)
201
- execute_request(Net::HTTP::Delete, path, query: query, body: body, headers: headers)
202
- end
203
-
204
- # @return [AuthorizedPayments] AuthorizedPayments APIs collection
205
- def authorized_payments
206
- AuthorizedPayments.new(self)
207
- end
208
-
209
- # @return [CapturedPayments] CapturedPayments APIs collection
210
- def captured_payments
211
- CapturedPayments.new(self)
212
- end
213
-
214
- # @return [Authentication] Authentication APIs collection
215
- def authentication
216
- Authentication.new(self)
217
- end
218
-
219
- # @return [CatalogProducts] Catalog Products APIs collection
220
- def catalog_products
221
- CatalogProducts.new(self)
222
- end
223
-
224
- # @return [Disputes] Disputes APIs collection
225
- def disputes
226
- Disputes.new(self)
227
- end
228
-
229
- # @return [InvoiceTemplates] InvoiceTemplates APIs collection
230
- def invoice_templates
231
- InvoiceTemplates.new(self)
232
- end
233
-
234
- # @return [Invoices] Invoices APIs collection
235
- def invoices
236
- Invoices.new(self)
237
- end
238
-
239
- # @return [Orders] Orders APIs collection
240
- def orders
241
- Orders.new(self)
242
- end
243
-
244
- # @return [PayoutItems] PayoutItems APIs collection
245
- def payout_items
246
- PayoutItems.new(self)
247
- end
248
-
249
- # @return [Payouts] Payouts APIs collection
250
- def payouts
251
- Payouts.new(self)
252
- end
253
-
254
- # @return [Redunds] Refunds APIs collection
255
- def refunds
256
- Refunds.new(self)
257
- end
258
-
259
- # @return [ReferencedPayoutItems] ReferencedPayoutItems APIs collection
260
- def referenced_payout_items
261
- ReferencedPayoutItems.new(self)
262
- end
263
-
264
- # @return [ReferencedPayouts] ReferencedPayouts APIs collection
265
- def referenced_payouts
266
- ReferencedPayouts.new(self)
267
- end
268
-
269
- # @return [ShipmentTracking] Shipment Tracking APIs collection
270
- def shipment_tracking
271
- ShipmentTracking.new(self)
272
- end
273
-
274
- # @return [Subscriptions] Subscriptions APIs collection
275
- def subscriptions
276
- Subscriptions.new(self)
277
- end
278
-
279
- # @return [SubscriptionPlans] Subscription Plans APIs collection
280
- def subscription_plans
281
- SubscriptionPlans.new(self)
282
- end
283
-
284
- # @return [UserInfo] User Info APIs collection
285
- def user_info
286
- UserInfo.new(self)
287
- end
288
-
289
- # @return [Users] Users Management APIs collection
290
- def users
291
- Users.new(self)
292
- end
293
-
294
- # @return [Webhooks] Webhooks APIs collection
295
- def webhooks
296
- Webhooks.new(self)
297
- end
298
-
299
- # @return [WebhookEvents] Webhook Events APIs collection
300
- def webhook_lookups
301
- WebhookLookups.new(self)
302
- end
303
-
304
- # @return [WebhookEvents] Webhook Lookups APIs collection
305
- def webhook_events
306
- WebhookEvents.new(self)
307
- end
308
-
309
- private
310
-
311
- def execute_request(http_method, path, query: nil, body: nil, headers: nil)
312
- request = Request.new(self, http_method, path, query: query, body: body, headers: headers)
313
- RequestExecutor.new(self, request).call
314
- end
315
105
  end
316
106
  end
@@ -37,7 +37,6 @@ module PaypalAPI
37
37
  #
38
38
  class FailedRequest < Error
39
39
  def initialize(message = nil, request:, response:)
40
- super(message)
41
40
  @request = request
42
41
  @response = response
43
42
 
@@ -48,6 +47,9 @@ module PaypalAPI
48
47
  @error_debug_id = data[:debug_id]
49
48
  @error_details = data[:details]
50
49
  @paypal_request_id = request.http_request["paypal-request-id"]
50
+
51
+ message += "\n #{response.http_body}" unless data.empty?
52
+ super(message)
51
53
  end
52
54
  end
53
55
 
@@ -83,27 +83,9 @@ module PaypalAPI
83
83
  def build_http_headers(http_request, body, headers)
84
84
  headers = normalize_headers(headers)
85
85
 
86
- unless headers.key?("authorization")
87
- http_request["authorization"] = client.access_token.authorization_string
88
- end
89
-
90
- #
91
- # We should set json content type header to not get 415 UnsupportedMediaType
92
- # error in various APIs
93
- #
94
- # PayPal requires "application/json" content type even for GET requests
95
- # and for POST requests without body.
96
- #
97
- # Net::HTTP sets default content-type "application/x-www-form-urlencoded"
98
- # if not provided
99
- #
100
- unless headers.key?("content-type")
101
- http_request["content-type"] = "application/json"
102
- end
103
-
104
- unless headers.key?("paypal-request-id")
105
- http_request["paypal-request-id"] = SecureRandom.uuid unless http_request.is_a?(Net::HTTP::Get)
106
- end
86
+ add_authorization_header(http_request, headers)
87
+ add_content_type_header(http_request, headers)
88
+ add_paypal_request_id_header(http_request, headers)
107
89
 
108
90
  headers.each { |key, value| http_request[key] = value }
109
91
  end
@@ -117,12 +99,55 @@ module PaypalAPI
117
99
 
118
100
  def build_http_uri(path, query)
119
101
  uri = URI.join(client.env.api_url, path)
120
- uri.query = URI.encode_www_form(query) if query && !query.empty?
102
+ add_query_params(uri, query)
103
+
121
104
  uri
122
105
  end
123
106
 
124
107
  def normalize_headers(headers)
125
108
  headers.empty? ? headers : headers.transform_keys { |key| key.to_s.downcase }
126
109
  end
110
+
111
+ def add_authorization_header(http_request, headers)
112
+ unless headers.key?("authorization")
113
+ http_request["authorization"] = client.access_token.authorization_string
114
+ end
115
+ end
116
+
117
+ def add_query_params(uri, query)
118
+ return if !query || query.empty?
119
+
120
+ # We should merge query params with uri query params to not temove them
121
+ uri_query_string = uri.query
122
+
123
+ if uri_query_string && !uri_query_string.empty?
124
+ old_query = URI.decode_www_form(uri_query_string).to_h
125
+ query = old_query.transform_keys!(&:to_sym).merge!(query.transform_keys(&:to_sym))
126
+ end
127
+
128
+ uri.query = URI.encode_www_form(query)
129
+ end
130
+
131
+ #
132
+ # We should set json content type header to not get 415 UnsupportedMediaType
133
+ # error in various APIs
134
+ #
135
+ # PayPal requires "application/json" content type even for GET requests
136
+ # and for POST requests without body.
137
+ #
138
+ # Net::HTTP sets default content-type "application/x-www-form-urlencoded"
139
+ # if not provided
140
+ #
141
+ def add_content_type_header(http_request, headers)
142
+ unless headers.key?("content-type")
143
+ http_request["content-type"] = "application/json"
144
+ end
145
+ end
146
+
147
+ def add_paypal_request_id_header(http_request, headers)
148
+ unless headers.key?("paypal-request-id")
149
+ http_request["paypal-request-id"] = SecureRandom.uuid unless http_request.is_a?(Net::HTTP::Get)
150
+ end
151
+ end
127
152
  end
128
153
  end