paypal-rest-api 0.4.0 → 0.5.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 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