paypal-rest-api 0.4.0 → 0.5.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: '08b9e0e25c50df502751486cfeceb957be78e1951aa919faec3caf9550eec304'
4
- data.tar.gz: 0d3894d681057c4721cf3e50a20308ad8e7a19ffb68d73ecab31ca9f112ed2c2
3
+ metadata.gz: dbd16b786c08d41262b404eb893480c37dbd1b4084dcb4f26a5d7f849d187970
4
+ data.tar.gz: 720a713a163ca01db1e414149673f416e484616d2e86442eb75ac0d17a29620a
5
5
  SHA512:
6
- metadata.gz: 49e4bbea2d23037f3af274dddf8fc9c0652b55b06247bf8513531bf41ca925bfc768f9bfa9a98022f3783cf64022906dec19932d8cf2380ef5c4464cff1ba66e
7
- data.tar.gz: b8e9d53bab01f8f31da162165191bbe8ecc00b06b9a342966a3400971811d6498c71b598e2f35e7269863d82abdcfa39b92dbcf7734eb6bb79545f52a11fbb48
6
+ metadata.gz: d7d63364e602fe0ae3840fefcf68efbd4432243fb337ef8c4a42ec45d8e3744565456696b8f06d04c426520d25c27dd21a0447df9e6ff7017d4c6556453ca568
7
+ data.tar.gz: 02ebf31571711bb7a0a347b38d8c0c6c116d6ec2bb135912a6ed1da7cc499a469f2cabb3ccd0c9317dbad520e101eabdc3006422fa3498e9df7bb518cc537e8b
data/README.md CHANGED
@@ -15,12 +15,13 @@ bundle add paypal-rest-api
15
15
 
16
16
  - Supported Ruby Versions - *(2.6 .. 3.3), head, jruby-9.4, truffleruby-24*
17
17
  - No dependencies;
18
- - Automatic authorization & reauthorization;
18
+ - Automatic authorization & re-authorization;
19
19
  - Auto-retries (configured);
20
20
  - Automatically added Paypal-Request-Id header for idempotent requests if not
21
21
  provided;
22
22
  - Webhooks Offline verification (needs to download certificate once)
23
23
  - Custom callbacks before/after request
24
+ - Automatic pagination methods
24
25
 
25
26
  ## Usage
26
27
 
@@ -44,7 +45,7 @@ PaypalAPI.live? # => false
44
45
  PaypalAPI.api_url # => "https://api-m.sandbox.paypal.com"
45
46
  PaypalAPI.web_url # => "https://sandbox.paypal.com"
46
47
 
47
- response = between redeploys::Orders.show(order_id)
48
+ response = PaypalAPI::Orders.show(order_id)
48
49
  response = PaypalAPI::Orders.create(body: body)
49
50
  ```
50
51
 
@@ -85,22 +86,42 @@ response = PaypalAPI.put(path, query: query, body: body, headers: headers)
85
86
  response = PaypalAPI.delete(path, query: query, body: body, headers: headers)
86
87
  ```
87
88
 
88
- ### Parsing response
89
+ ### Response
89
90
 
90
- `response.body` is a main method that returns parsed JSON respoonse as a Hash.
91
+ `Response` object is returned after each `API` request.
91
92
 
92
- There are also many others helpful methods:
93
+ #### Original HTTP response data
93
94
 
94
- ```ruby
95
- response.body # Parsed JSON. JSON is parsed lazyly, keys are symbolized.
96
- response[:foo] # Gets :foo attribute from parsed body
97
- response.fetch(:foo) # Fetches :foo attribute from parsed body
98
- response.http_response # original Net::HTTP::Response
99
- response.http_body # original response string
100
- response.http_status # Integer http status
101
- response.http_headers # Hash with response headers (keys are strings)
102
- response.request # Request that generates this response
103
- ```
95
+ - `response.http_status` - response HTTP status as Integer
96
+ - `response.http_body` - response body as String
97
+ - `response.http_headers` - response headers as Hash with String keys
98
+ - `response.http_response` - original Net::HTTP::Response object
99
+ - `response.request` - Request object that was used to get this response
100
+
101
+ #### Parsed JSON body methods
102
+
103
+ - `response.body` - parsed JSON body, keys are Symbols
104
+ - `response[:field]` - gets `:field` attribute from parsed body,
105
+ returns nil if response have no such key
106
+ - `response.fetch(:field)` - gets `:field` attribute from parsed body,
107
+ raises KeyError if response has no such key
108
+
109
+ #### Error check methods
110
+
111
+ - `response.success?` - checks HTTP status code is 2xx
112
+ - `response.failed?` - checks HTTP status code is not 2xx
113
+
114
+ #### Using HATEOAS links
115
+
116
+ - `response.follow_up_link('approve', query: nil, body: nil, headers: nil)` -
117
+ Finds HATEOAS link is response with `rel=approve` and requests it. Returns
118
+ `nil` if no such link were found.
119
+
120
+ #### Pagination (see [Automatic Pagination][automatic_pagination] for examples)
121
+
122
+ - `response.each_page { |response| ... }` - iterates over each page in response
123
+ - `response.each_page_item(items_field) { |item| ... }` - iterates over each
124
+ page item
104
125
 
105
126
  ## Configuration options
106
127
 
@@ -173,6 +194,28 @@ client = PaypalAPI::Client.new(
173
194
  )
174
195
  ```
175
196
 
197
+ ## Automatic pagination
198
+
199
+ PayPal provides HATEOAS links in responses. This links can contain items with
200
+ `rel=next` attribute. We request next pages using this links.
201
+
202
+ We have two specific methods:
203
+
204
+ - `Response#each_page` - iterates over each page `Response` object
205
+ - `Response#each_page_item(items_field_name)` - iterates over items on each page
206
+
207
+ Example:
208
+
209
+ ```ruby
210
+ PaypalAPI::WebhookEvents.list(page_size: 25).each_page do |response|
211
+ # ...
212
+ end
213
+
214
+ PaypalAPI::WebhookEvents.list(page_size: 25).each_page_item(:events) do |hash|
215
+ # ...
216
+ end
217
+ ```
218
+
176
219
  ## Webhoooks verification
177
220
 
178
221
  Webhooks can be verified [offline](https://developer.paypal.com/api/rest/webhooks/rest/#link-selfverificationmethod)
@@ -514,6 +557,25 @@ All API endpoints accept this parameters:
514
557
  - `PaypalAPI::ReferencedPayoutItems.create`
515
558
  - `PaypalAPI::ReferencedPayoutItems.show`
516
559
 
560
+ ### PartnerReferrals
561
+
562
+ - `PaypalAPI::PartnerReferrals.create`
563
+ - `PaypalAPI::PartnerReferrals.show`
564
+
565
+ ### PaymentExperienceWebProfiles
566
+
567
+ - `PaypalAPI::PaymentExperienceWebProfiles.create`
568
+ - `PaypalAPI::PaymentExperienceWebProfiles.list`
569
+ - `PaypalAPI::PaymentExperienceWebProfiles.show`
570
+ - `PaypalAPI::PaymentExperienceWebProfiles.replace`
571
+ - `PaypalAPI::PaymentExperienceWebProfiles.update`
572
+ - `PaypalAPI::PaymentExperienceWebProfiles.delete`
573
+
574
+ ### TransactionSearch
575
+
576
+ - `PaypalAPI::TransactionSearch.list_transactions`
577
+ - `PaypalAPI::TransactionSearch.list_all_balances`
578
+
517
579
  ## Development
518
580
 
519
581
  ```bash
@@ -529,3 +591,5 @@ Bug reports and pull requests are welcome on GitHub at <https://github.com/aglus
529
591
  ## License
530
592
 
531
593
  The gem is available as open source under the terms of the [MIT License](https://opensource.org/licenses/MIT).
594
+
595
+ [automatic_pagination]: #automatic-pagination
data/VERSION CHANGED
@@ -1 +1 @@
1
- 0.4.0
1
+ 0.5.0
@@ -0,0 +1,48 @@
1
+ # frozen_string_literal: true
2
+
3
+ module PaypalAPI
4
+ #
5
+ # Use the Partner Referrals API to add PayPal seller accounts to PayPal
6
+ # Complete Payments Platform for Marketplaces and Platforms.
7
+ #
8
+ # @see https://developer.paypal.com/docs/api/partner-referrals/v2/
9
+ #
10
+ class PartnerReferrals < APICollection
11
+ #
12
+ # Common methods for PaypalAPI::PartnerReferrals class and client.partner_referrals instance
13
+ #
14
+ module APIs
15
+ # @!macro [new] request
16
+ # @param query [Hash, nil] Request query parameters
17
+ # @param body [Hash, nil] Request body parameters
18
+ # @param headers [Hash, nil] Request headers
19
+ # @return [Response] Response object
20
+
21
+ #
22
+ # Create partner referral
23
+ #
24
+ # @see https://developer.paypal.com/docs/api/partner-referrals/v2/#partner-referrals_create
25
+ #
26
+ # @macro request
27
+ #
28
+ def create(query: nil, body: nil, headers: nil)
29
+ client.post("/v2/customer/partner-referrals", query: query, body: body, headers: headers)
30
+ end
31
+
32
+ #
33
+ # Show referral data
34
+ #
35
+ # @see https://developer.paypal.com/docs/api/partner-referrals/v2/#partner-referrals_read
36
+ #
37
+ # @param id [String] The ID of the partner-referrals data for which to show details
38
+ # @macro request
39
+ #
40
+ def show(partner_referral_id, query: nil, body: nil, headers: nil)
41
+ client.get("/v2/customer/partner-referrals/#{encode(partner_referral_id)}", query: query, body: body, headers: headers)
42
+ end
43
+ end
44
+
45
+ include APIs
46
+ extend APIs
47
+ end
48
+ end
@@ -0,0 +1,94 @@
1
+ # frozen_string_literal: true
2
+
3
+ module PaypalAPI
4
+ #
5
+ # Use the Payment Experience API to create seamless payment experience profiles.
6
+ #
7
+ # @see https://developer.paypal.com/docs/api/orders/v2/
8
+ #
9
+ class PaymentExperienceWebProfiles < APICollection
10
+ #
11
+ # Common methods for PaypalAPI::PaymentExperienceWebProfiles class and client.orders instance
12
+ #
13
+ module APIs
14
+ # @!macro [new] request
15
+ # @param query [Hash, nil] Request query parameters
16
+ # @param body [Hash, nil] Request body parameters
17
+ # @param headers [Hash, nil] Request headers
18
+ # @return [Response] Response object
19
+
20
+ #
21
+ # Create web experience profile
22
+ #
23
+ # @see https://developer.paypal.com/docs/api/payment-experience/v1/#web-profile_create
24
+ #
25
+ # @macro request
26
+ #
27
+ def create(query: nil, body: nil, headers: nil)
28
+ client.post("/v1/payment-experience/web-profiles", query: query, body: body, headers: headers)
29
+ end
30
+
31
+ #
32
+ # List web experience profiles
33
+ #
34
+ # @see https://developer.paypal.com/docs/api/payment-experience/v1/#web-profile_get-list
35
+ #
36
+ # @macro request
37
+ #
38
+ def list(query: nil, body: nil, headers: nil)
39
+ client.get("/v1/payment-experience/web-profiles", query: query, body: body, headers: headers)
40
+ end
41
+
42
+ #
43
+ # Show web experience profile details by ID
44
+ #
45
+ # @see https://developer.paypal.com/docs/api/payment-experience/v1/#web-profile_get
46
+ #
47
+ # @param id [String] The ID of the profile for which to show details.
48
+ # @macro request
49
+ #
50
+ def show(id, query: nil, body: nil, headers: nil)
51
+ client.get("/v1/payment-experience/web-profiles/#{encode(id)}", query: query, body: body, headers: headers)
52
+ end
53
+
54
+ #
55
+ # Replace web experience profile
56
+ #
57
+ # @see https://developer.paypal.com/docs/api/payment-experience/v1/#web-profile_update
58
+ #
59
+ # @param id [String] The ID of the profile to replace.
60
+ # @macro request
61
+ #
62
+ def replace(id, query: nil, body: nil, headers: nil)
63
+ client.put("/v1/payment-experience/web-profiles/#{encode(id)}", query: query, body: body, headers: headers)
64
+ end
65
+
66
+ #
67
+ # Partially update web experience profile
68
+ #
69
+ # @see https://developer.paypal.com/docs/api/payment-experience/v1/#web-profile_partial-update
70
+ #
71
+ # @param id [String] The ID of the profile to update.
72
+ # @macro request
73
+ #
74
+ def update(id, query: nil, body: nil, headers: nil)
75
+ client.patch("/v1/payment-experience/web-profiles/#{encode(id)}", query: query, body: body, headers: headers)
76
+ end
77
+
78
+ #
79
+ # Delete web experience profile
80
+ #
81
+ # @see https://developer.paypal.com/docs/api/payment-experience/v1/#web-profile_delete
82
+ #
83
+ # @param id [String] The ID of the profile to delete.
84
+ # @macro request
85
+ #
86
+ def delete(id, query: nil, body: nil, headers: nil)
87
+ client.delete("/v1/payment-experience/web-profiles/#{encode(id)}", query: query, body: body, headers: headers)
88
+ end
89
+ end
90
+
91
+ include APIs
92
+ extend APIs
93
+ end
94
+ end
@@ -0,0 +1,46 @@
1
+ # frozen_string_literal: true
2
+
3
+ module PaypalAPI
4
+ #
5
+ # Use the Transaction Search API to get the history of transactions for a PayPal account.
6
+ #
7
+ # @see https://developer.paypal.com/docs/api/transaction-search/v1/
8
+ #
9
+ class TransactionSearch < APICollection
10
+ #
11
+ # Common methods for PaypalAPI::TransactionSearch class and client.transaction_search instance
12
+ #
13
+ module APIs
14
+ # @!macro [new] request
15
+ # @param query [Hash, nil] Request query parameters
16
+ # @param body [Hash, nil] Request body parameters
17
+ # @param headers [Hash, nil] Request headers
18
+ # @return [Response] Response object
19
+
20
+ #
21
+ # List transactions
22
+ #
23
+ # @see https://developer.paypal.com/docs/api/transaction-search/v1/#search_get
24
+ #
25
+ # @macro request
26
+ #
27
+ def list_transactions(query: nil, body: nil, headers: nil)
28
+ client.get("/v1/reporting/transactions", query: query, body: body, headers: headers)
29
+ end
30
+
31
+ #
32
+ # List all balances
33
+ #
34
+ # @see https://developer.paypal.com/docs/api/transaction-search/v1/#balances_get
35
+ #
36
+ # @macro request
37
+ #
38
+ def list_all_balances(query: nil, body: nil, headers: nil)
39
+ client.get("/v1/reporting/balances", query: query, body: body, headers: headers)
40
+ end
41
+ end
42
+
43
+ include APIs
44
+ extend APIs
45
+ end
46
+ end
@@ -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,180 +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 [PaymentTokens] PaymentTokens APIs collection
245
- def payment_tokens
246
- PaymentTokens.new(self)
247
- end
248
-
249
- # @return [PayoutItems] PayoutItems APIs collection
250
- def payout_items
251
- PayoutItems.new(self)
252
- end
253
-
254
- # @return [Payouts] Payouts APIs collection
255
- def payouts
256
- Payouts.new(self)
257
- end
258
-
259
- # @return [Refunds] Refunds APIs collection
260
- def refunds
261
- Refunds.new(self)
262
- end
263
-
264
- # @return [ReferencedPayoutItems] ReferencedPayoutItems APIs collection
265
- def referenced_payout_items
266
- ReferencedPayoutItems.new(self)
267
- end
268
-
269
- # @return [ReferencedPayouts] ReferencedPayouts APIs collection
270
- def referenced_payouts
271
- ReferencedPayouts.new(self)
272
- end
273
-
274
- # @return [SetupTokens] SetupTokens APIs collection
275
- def setup_tokens
276
- SetupTokens.new(self)
277
- end
278
-
279
- # @return [ShipmentTracking] Shipment Tracking APIs collection
280
- def shipment_tracking
281
- ShipmentTracking.new(self)
282
- end
283
-
284
- # @return [Subscriptions] Subscriptions APIs collection
285
- def subscriptions
286
- Subscriptions.new(self)
287
- end
288
-
289
- # @return [SubscriptionPlans] Subscription Plans APIs collection
290
- def subscription_plans
291
- SubscriptionPlans.new(self)
292
- end
293
-
294
- # @return [UserInfo] User Info APIs collection
295
- def user_info
296
- UserInfo.new(self)
297
- end
298
-
299
- # @return [Users] Users Management APIs collection
300
- def users
301
- Users.new(self)
302
- end
303
-
304
- # @return [Webhooks] Webhooks APIs collection
305
- def webhooks
306
- Webhooks.new(self)
307
- end
308
-
309
- # @return [WebhookEvents] Webhook Events APIs collection
310
- def webhook_lookups
311
- WebhookLookups.new(self)
312
- end
313
-
314
- # @return [WebhookEvents] Webhook Lookups APIs collection
315
- def webhook_events
316
- WebhookEvents.new(self)
317
- end
318
-
319
- private
320
-
321
- def execute_request(http_method, path, query: nil, body: nil, headers: nil)
322
- request = Request.new(self, http_method, path, query: query, body: body, headers: headers)
323
- RequestExecutor.new(self, request).call
324
- end
325
105
  end
326
106
  end
@@ -99,7 +99,8 @@ module PaypalAPI
99
99
 
100
100
  def build_http_uri(path, query)
101
101
  uri = URI.join(client.env.api_url, path)
102
- uri.query = URI.encode_www_form(query) if query && !query.empty?
102
+ add_query_params(uri, query)
103
+
103
104
  uri
104
105
  end
105
106
 
@@ -113,6 +114,20 @@ module PaypalAPI
113
114
  end
114
115
  end
115
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
+
116
131
  #
117
132
  # We should set json content type header to not get 415 UnsupportedMediaType
118
133
  # error in various APIs
@@ -30,31 +30,40 @@ module PaypalAPI
30
30
 
31
31
  private
32
32
 
33
- def execute_request(retry_number: 0)
33
+ def start_execution(retry_number)
34
34
  callbacks_context[:retry_number] = retry_number
35
-
36
35
  run_callbacks(:before)
37
- response = execute_net_http_request
38
- rescue => error
39
- raise error if NetworkErrorBuilder::ERRORS.none? { |network_error_class| error.is_a?(network_error_class) }
36
+ execute_net_http_request
37
+ end
40
38
 
39
+ def handle_network_error(error, retry_number)
41
40
  will_retry = retries[:enabled] && !retries_limit_reached?(retry_number)
42
41
  callbacks_context[:will_retry] = will_retry
43
42
  run_callbacks(:after_network_error, error)
44
43
  raise NetworkErrorBuilder.call(request: request, error: error) unless will_retry
45
44
 
46
45
  retry_request(retry_number)
46
+ end
47
+
48
+ def handle_success_response(response)
49
+ callbacks_context.delete(:will_retry)
50
+ run_callbacks(:after_success, response)
51
+ response
52
+ end
53
+
54
+ def handle_failed_response(response, retry_number)
55
+ will_retry = retries[:enabled] && retryable?(response, retry_number)
56
+ callbacks_context[:will_retry] = will_retry
57
+ run_callbacks(:after_fail, response)
58
+ will_retry ? retry_request(retry_number) : response
59
+ end
60
+
61
+ def execute_request(retry_number: 0)
62
+ response = start_execution(retry_number)
63
+ rescue => error
64
+ unknown_network_error?(error) ? handle_unknown_error(error) : handle_network_error(error, retry_number)
47
65
  else
48
- if response.success?
49
- callbacks_context.delete(:will_retry)
50
- run_callbacks(:after_success, response)
51
- response
52
- else
53
- will_retry = retries[:enabled] && retryable?(response, retry_number)
54
- callbacks_context[:will_retry] = will_retry
55
- run_callbacks(:after_fail, response)
56
- will_retry ? retry_request(retry_number) : response
57
- end
66
+ response.success? ? handle_success_response(response) : handle_failed_response(response, retry_number)
58
67
  end
59
68
 
60
69
  def execute_net_http_request
@@ -105,6 +114,14 @@ module PaypalAPI
105
114
  true
106
115
  end
107
116
 
117
+ def unknown_network_error?(error)
118
+ NetworkErrorBuilder::ERRORS.none? { |network_error_class| error.is_a?(network_error_class) }
119
+ end
120
+
121
+ def handle_unknown_error(error)
122
+ raise error
123
+ end
124
+
108
125
  def run_callbacks(callback_name, resp = nil)
109
126
  callbacks[callback_name].each { |callback| callback.call(request, callbacks_context, resp) }
110
127
  end
@@ -108,6 +108,72 @@ module PaypalAPI
108
108
  "#<#{self.class.name} (#{http_response.code})>"
109
109
  end
110
110
 
111
+ #
112
+ # Follow up HATEOAS link
113
+ #
114
+ # @see https://developer.paypal.com/api/rest/responses/#link-hateoaslinks
115
+ #
116
+ # @param rel [String] Target link "rel" attribute
117
+ # @param query [Hash] Request additional query parameters
118
+ # @param body [Hash] Request body parameters
119
+ # @param headers [Hash] Request headers
120
+ #
121
+ # @return [Response, nil] Follow-up link response, if link with provided "rel" exists
122
+ #
123
+ def follow_up_link(rel, query: nil, body: nil, headers: nil)
124
+ links = self[:links]
125
+ return unless links
126
+
127
+ link = links.find { |curr_link| curr_link[:rel] == rel.to_s }
128
+ return unless link
129
+
130
+ http_method = link[:method]&.downcase || :get
131
+ request.client.public_send(http_method, link[:href], query: query, body: body, headers: headers)
132
+ end
133
+
134
+ #
135
+ # Pagination methods
136
+ #
137
+ module PaginationHelpers
138
+ #
139
+ # Iterates through all response pages by requesting HATEOAS "next" links,
140
+ # making additional fetches to the API as necessary.
141
+ #
142
+ # @see #follow_up_link
143
+ #
144
+ # @yield [Response] Next page response
145
+ #
146
+ # @return [void]
147
+ #
148
+ def each_page(&block)
149
+ return enum_for(:each_page) unless block
150
+
151
+ page = self
152
+ yield(page)
153
+ yield(page) while (page = page.follow_up_link("next"))
154
+ end
155
+
156
+ #
157
+ # Iterates through all items in response +items_field_name+ field,
158
+ # making additional pages requests as necessary.
159
+ #
160
+ # @see #each_page
161
+ #
162
+ # @param items_field_name [Symbol] Name of field containing items
163
+ #
164
+ # @yield [Hash] Item
165
+ #
166
+ # @return [void]
167
+ #
168
+ def each_page_item(items_field_name, &block)
169
+ return enum_for(:each_page_item, items_field_name) unless block
170
+
171
+ each_page do |page|
172
+ page.fetch(items_field_name).each(&block)
173
+ end
174
+ end
175
+ end
176
+
111
177
  private
112
178
 
113
179
  def json_response?
@@ -120,5 +186,7 @@ module PaypalAPI
120
186
  rescue JSON::ParserError, TypeError
121
187
  json
122
188
  end
189
+
190
+ include PaginationHelpers
123
191
  end
124
192
  end
data/lib/paypal-api.rb CHANGED
@@ -100,10 +100,8 @@ module PaypalAPI
100
100
 
101
101
  #
102
102
  # @!macro [new] api_collection
103
- # $0 APIs collection
103
+ # $3 APIs collection
104
104
  # @api public
105
- # @example
106
- # PaypalAPI.$0
107
105
  #
108
106
 
109
107
  #
@@ -139,6 +137,14 @@ module PaypalAPI
139
137
  # @macro api_collection
140
138
  # @return [Orders]
141
139
  #
140
+ # @!method partner_referrals
141
+ # @macro api_collection
142
+ # @return [PartnerReferrals]
143
+ #
144
+ # @!method payment_experience_web_profiles
145
+ # @macro api_collection
146
+ # @return [PaymentExperienceWebProfile]
147
+ #
142
148
  # @!method payout_items
143
149
  # @macro api_collection
144
150
  # @return [PayoutItems]
@@ -171,6 +177,10 @@ module PaypalAPI
171
177
  # @macro api_collection
172
178
  # @return [SubscriptionPlans]
173
179
  #
180
+ # @!method transaction_search
181
+ # @macro api_collection
182
+ # @return [TransactionSearch]
183
+ #
174
184
  # @!method user_info
175
185
  # @macro api_collection
176
186
  # @return [UserInfo]
@@ -200,6 +210,8 @@ module PaypalAPI
200
210
  invoice_templates
201
211
  invoices
202
212
  orders
213
+ partner_referrals
214
+ payment_experience_web_profiles
203
215
  payment_tokens
204
216
  payout_items
205
217
  payouts
@@ -210,6 +222,7 @@ module PaypalAPI
210
222
  shipment_tracking
211
223
  subscriptions
212
224
  subscription_plans
225
+ transaction_search
213
226
  user_info
214
227
  users
215
228
  webhooks
@@ -237,6 +250,10 @@ end
237
250
  require_relative "paypal-api/access_token"
238
251
  require_relative "paypal-api/api_collection"
239
252
  require_relative "paypal-api/environment"
253
+ require_relative "paypal-api/client/access_token_methods"
254
+ require_relative "paypal-api/client/api_methods"
255
+ require_relative "paypal-api/client/environment_methods"
256
+ require_relative "paypal-api/client/http_methods"
240
257
  require_relative "paypal-api/client"
241
258
  require_relative "paypal-api/config"
242
259
  require_relative "paypal-api/error"
@@ -255,6 +272,8 @@ require_relative "paypal-api/api_collections/disputes"
255
272
  require_relative "paypal-api/api_collections/invoice_templates"
256
273
  require_relative "paypal-api/api_collections/invoices"
257
274
  require_relative "paypal-api/api_collections/orders"
275
+ require_relative "paypal-api/api_collections/partner_referrals"
276
+ require_relative "paypal-api/api_collections/payment_experience_web_profiles"
258
277
  require_relative "paypal-api/api_collections/payment_tokens"
259
278
  require_relative "paypal-api/api_collections/payout_items"
260
279
  require_relative "paypal-api/api_collections/payouts"
@@ -265,6 +284,7 @@ require_relative "paypal-api/api_collections/setup_tokens"
265
284
  require_relative "paypal-api/api_collections/shipment_tracking"
266
285
  require_relative "paypal-api/api_collections/subscriptions"
267
286
  require_relative "paypal-api/api_collections/subscription_plans"
287
+ require_relative "paypal-api/api_collections/transaction_search"
268
288
  require_relative "paypal-api/api_collections/user_info"
269
289
  require_relative "paypal-api/api_collections/users"
270
290
  require_relative "paypal-api/api_collections/webhooks"
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: paypal-rest-api
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.4.0
4
+ version: 0.5.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Andrey Glushkov
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2024-09-16 00:00:00.000000000 Z
11
+ date: 2024-09-30 00:00:00.000000000 Z
12
12
  dependencies: []
13
13
  description: PayPal REST API with no dependencies.
14
14
  email:
@@ -30,6 +30,8 @@ files:
30
30
  - lib/paypal-api/api_collections/invoice_templates.rb
31
31
  - lib/paypal-api/api_collections/invoices.rb
32
32
  - lib/paypal-api/api_collections/orders.rb
33
+ - lib/paypal-api/api_collections/partner_referrals.rb
34
+ - lib/paypal-api/api_collections/payment_experience_web_profiles.rb
33
35
  - lib/paypal-api/api_collections/payment_tokens.rb
34
36
  - lib/paypal-api/api_collections/payout_items.rb
35
37
  - lib/paypal-api/api_collections/payouts.rb
@@ -40,12 +42,17 @@ files:
40
42
  - lib/paypal-api/api_collections/shipment_tracking.rb
41
43
  - lib/paypal-api/api_collections/subscription_plans.rb
42
44
  - lib/paypal-api/api_collections/subscriptions.rb
45
+ - lib/paypal-api/api_collections/transaction_search.rb
43
46
  - lib/paypal-api/api_collections/user_info.rb
44
47
  - lib/paypal-api/api_collections/users.rb
45
48
  - lib/paypal-api/api_collections/webhook_events.rb
46
49
  - lib/paypal-api/api_collections/webhook_lookups.rb
47
50
  - lib/paypal-api/api_collections/webhooks.rb
48
51
  - lib/paypal-api/client.rb
52
+ - lib/paypal-api/client/access_token_methods.rb
53
+ - lib/paypal-api/client/api_methods.rb
54
+ - lib/paypal-api/client/environment_methods.rb
55
+ - lib/paypal-api/client/http_methods.rb
49
56
  - lib/paypal-api/config.rb
50
57
  - lib/paypal-api/environment.rb
51
58
  - lib/paypal-api/error.rb
@@ -80,7 +87,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
80
87
  - !ruby/object:Gem::Version
81
88
  version: '0'
82
89
  requirements: []
83
- rubygems_version: 3.5.18
90
+ rubygems_version: 3.5.20
84
91
  signing_key:
85
92
  specification_version: 4
86
93
  summary: PayPal REST API