paddle 2.2.1 → 2.3.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: 6224fc2a3ec9423990985241a118780185a090617407f95e97bb542120eb9323
4
- data.tar.gz: 03403341d8dce73c881ed3fc2c722cf738b625803c6352dd2cca15e5d4cd65a7
3
+ metadata.gz: fd93d2c8220b972ffa99dc9134c9ae6a1dd4da4051d63d363f825f4130be5965
4
+ data.tar.gz: 4e6f0566db66650772cef15c976d229221cf3292b8a60f044ac22cfe91f81d70
5
5
  SHA512:
6
- metadata.gz: 6453da01350a80adf7f8723817b7d45edfac636d5ae72ebeb92b281ad93d85d59866631eb60a17c3a8225f5a8f51780b857e1aeab940c0264daaa53446a70637
7
- data.tar.gz: 716ef3061039df26a5cfc0dd0f8931cb1e9edcf964947047acf37ed8b95cc63a3cc36595288f6aaccc45ee2b1e3f8fe0b74ae39969123f2c99eeeeea9da41381
6
+ metadata.gz: 51904dcd27cdc1272ffffe94397ab53756a07cf0de48071d8e4b4830efd51533965296dd7f0b74667e6a0be0f9f6dd3ec2fbba6dda6f2b512983ab01be0e4096
7
+ data.tar.gz: aedd0b4538ed33115788157c00e18b06c83da69ac0491fa1f62f69ecf5c77cebc9e27c9f8e9aa51bfd23bf13a94f67a97f8657bd7a29d3b42bc4a2c9bb41d311
data/.rubocop.yml CHANGED
@@ -6,3 +6,6 @@ inherit_gem: { rubocop-rails-omakase: rubocop.yml }
6
6
  # # Use `[a, [b, c]]` not `[ a, [ b, c ] ]`
7
7
  # Layout/SpaceInsideArrayLiteralBrackets:
8
8
  # Enabled: false
9
+
10
+ Rails/RefuteMethods:
11
+ Enabled: false
data/Gemfile.lock CHANGED
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- paddle (2.2.1)
4
+ paddle (2.3.0)
5
5
  faraday (~> 2.0)
6
6
 
7
7
  GEM
@@ -40,9 +40,9 @@ GEM
40
40
  ast (~> 2.4.1)
41
41
  racc
42
42
  racc (1.8.0)
43
- rack (3.1.3)
43
+ rack (3.1.7)
44
44
  rainbow (3.1.1)
45
- rake (13.0.6)
45
+ rake (13.2.1)
46
46
  regexp_parser (2.9.2)
47
47
  rexml (3.3.0)
48
48
  strscan
data/README.md CHANGED
@@ -77,6 +77,14 @@ Paddle::Product.list(per_page: 10, after: "abc123")
77
77
  >
78
78
  > The Paddle API doesn't take `nil` values for optional parameters. If you want to remove a value, you'll need to pass `"null"` instead.
79
79
 
80
+ ### Updating records
81
+
82
+ For API endpoints that support it, you can use the `update` method to update a record, like so:
83
+
84
+ ```ruby
85
+ Paddle::Product.retrieve(id: "pro_abc123").update(name: "My New Name")
86
+ ```
87
+
80
88
  ### Products
81
89
 
82
90
  ```ruby
@@ -167,6 +175,7 @@ Paddle::Customer.list(email: "me@mydomain.com")
167
175
 
168
176
  # Create a customer
169
177
  # https://developer.paddle.com/api-reference/customers/create-customer
178
+ # Returns a Paddle::ConflictError if the email is already used on Paddle
170
179
  Paddle::Customer.create(email: "myemail@mydomain.com", name: "Customer Name")
171
180
 
172
181
  # Retrieve a customer
data/lib/paddle/client.rb CHANGED
@@ -1,66 +1,61 @@
1
+ require "faraday"
2
+
1
3
  module Paddle
2
4
  class Client
3
5
  class << self
4
6
  def connection
5
- @connection ||= Faraday.new(Paddle.config.url) do |conn|
6
- conn.request :authorization, :Bearer, Paddle.config.api_key
7
-
8
- conn.headers = {
9
- "User-Agent" => "paddle/v#{VERSION} (github.com/deanpcmad/paddle)",
10
- "Paddle-Version" => Paddle.config.version.to_s
11
- }
12
-
13
- conn.request :json
14
- conn.response :json
15
- end
7
+ @connection ||= create_connection
16
8
  end
17
9
 
18
-
19
10
  def get_request(url, params: {}, headers: {})
20
- handle_response connection.get(url, params, headers)
11
+ handle_response(connection.get(url, params, headers))
21
12
  end
22
13
 
23
14
  def post_request(url, body: {}, headers: {})
24
- handle_response connection.post(url, body, headers)
15
+ handle_response(connection.post(url, body, headers))
25
16
  end
26
17
 
27
18
  def patch_request(url, body:, headers: {})
28
- handle_response connection.patch(url, body, headers)
19
+ handle_response(connection.patch(url, body, headers))
29
20
  end
30
21
 
31
22
  def delete_request(url, headers: {})
32
- handle_response connection.delete(url, headers)
23
+ handle_response(connection.delete(url, headers))
33
24
  end
34
25
 
35
- def handle_response(response)
36
- case response.status
37
- when 400
38
- raise Error, "Error 400: Your request was malformed. '#{response.body["error"]["code"]}'"
39
- when 401
40
- raise Error, "Error 401: You did not supply valid authentication credentials. '#{response.body["error"]}'"
41
- when 403
42
- raise Error, "Error 403: You are not allowed to perform that action. '#{response.body["error"]["code"]}'"
43
- when 404
44
- raise Error, "Error 404: No results were found for your request. '#{response.body["error"]["code"]}'"
45
- when 409
46
- raise Error, "Error 409: Your request was a conflict. '#{response.body["error"]["code"]}'"
47
- when 429
48
- raise Error, "Error 429: Your request exceeded the API rate limit. '#{response.body["error"]["code"]}'"
49
- when 500
50
- raise Error, "Error 500: We were unable to perform the request due to server-side problems. '#{response.body["error"]["code"]}'"
51
- when 503
52
- raise Error, "Error 503: You have been rate limited for sending more than 20 requests per second. '#{response.body["error"]["code"]}'"
53
- when 501
54
- raise Error, "Error 501: This resource has not been implemented. '#{response.body["error"]["code"]}'"
55
- when 204
56
- return true
57
- end
26
+ private
58
27
 
59
- if response.body && response.body["error"]
60
- raise Error, "Error #{response.body["error"]["code"]} - #{response.body["errors"]["message"]}"
28
+ def create_connection
29
+ Faraday.new(Paddle.config.url) do |conn|
30
+ conn.request :authorization, :Bearer, Paddle.config.api_key
31
+ conn.headers = default_headers
32
+ conn.request :json
33
+ conn.response :json
61
34
  end
35
+ end
36
+
37
+ def default_headers
38
+ {
39
+ "User-Agent" => "paddle/v#{VERSION} (github.com/deanpcmad/paddle)",
40
+ "Paddle-Version" => Paddle.config.version.to_s
41
+ }
42
+ end
43
+
44
+ def handle_response(response)
45
+ return true if response.status == 204
46
+ return response unless error?(response)
47
+
48
+ raise_error(response)
49
+ end
50
+
51
+ def error?(response)
52
+ [ 400, 401, 403, 404, 409, 429, 500, 501, 503 ].include?(response.status) ||
53
+ response.body&.key?("error")
54
+ end
62
55
 
63
- response
56
+ def raise_error(response)
57
+ error = Paddle::ErrorFactory.create(response.body, response.status)
58
+ raise error if error
64
59
  end
65
60
  end
66
61
  end
data/lib/paddle/error.rb CHANGED
@@ -1,4 +1,127 @@
1
1
  module Paddle
2
2
  class Error < StandardError
3
+ attr_reader :http_status_code
4
+ attr_reader :paddle_error_code
5
+ attr_reader :paddle_error_message
6
+
7
+ def initialize(response_body, http_status_code)
8
+ @response_body = response_body
9
+ @http_status_code = http_status_code
10
+ set_paddle_error_values
11
+ super(build_message)
12
+ end
13
+
14
+ private
15
+
16
+ def set_paddle_error_values
17
+ @paddle_error_code = @response_body.dig("error", "code")
18
+ @paddle_error_message = @response_body.dig("error", "detail")
19
+ end
20
+
21
+ def error_message
22
+ @paddle_error_message || @response_body.dig("error", "code")
23
+ rescue NoMethodError
24
+ "An unknown error occurred."
25
+ end
26
+
27
+ def build_message
28
+ if paddle_error_code.nil?
29
+ return "Error #{@http_status_code}: #{error_message}"
30
+ end
31
+ "Error #{@http_status_code}: #{error_message} '#{paddle_error_code}'"
32
+ end
33
+ end
34
+
35
+ class BadRequestError < Error
36
+ private
37
+
38
+ def error_message
39
+ "Your request was malformed."
40
+ end
41
+ end
42
+
43
+ class AuthenticationMissingError < Error
44
+ private
45
+
46
+ def error_message
47
+ "You did not supply valid authentication credentials."
48
+ end
49
+ end
50
+
51
+ class ForbiddenError < Error
52
+ private
53
+
54
+ def error_message
55
+ "You are not allowed to perform that action."
56
+ end
57
+ end
58
+
59
+ class EntityNotFoundError < Error
60
+ private
61
+
62
+ def error_message
63
+ "No results were found for your request."
64
+ end
65
+ end
66
+
67
+ class ConflictError < Error
68
+ private
69
+
70
+ def error_message
71
+ "Your request was a conflict."
72
+ end
73
+ end
74
+
75
+ class TooManyRequestsError < Error
76
+ private
77
+
78
+ def error_message
79
+ "Your request exceeded the API rate limit."
80
+ end
81
+ end
82
+
83
+ class InternalError < Error
84
+ private
85
+
86
+ def error_message
87
+ "We were unable to perform the request due to server-side problems."
88
+ end
89
+ end
90
+
91
+ class ServiceUnavailableError < Error
92
+ private
93
+
94
+ def error_message
95
+ "You have been rate limited for sending more than 20 requests per second."
96
+ end
97
+ end
98
+
99
+ class NotImplementedError < Error
100
+ private
101
+
102
+ def error_message
103
+ "This resource has not been implemented."
104
+ end
105
+ end
106
+
107
+
108
+ class ErrorFactory
109
+ HTTP_ERROR_MAP = {
110
+ 400 => BadRequestError,
111
+ 401 => AuthenticationMissingError,
112
+ 403 => ForbiddenError,
113
+ 404 => EntityNotFoundError,
114
+ 409 => ConflictError,
115
+ 429 => TooManyRequestsError,
116
+ 500 => InternalError,
117
+ 503 => ServiceUnavailableError,
118
+ 501 => NotImplementedError
119
+ }.freeze
120
+
121
+ def self.create(response_body, http_status_code)
122
+ status = http_status_code
123
+ error_class = HTTP_ERROR_MAP[status] || Error
124
+ error_class.new(response_body, http_status_code) if error_class
125
+ end
3
126
  end
4
127
  end
data/lib/paddle/object.rb CHANGED
@@ -15,5 +15,26 @@ module Paddle
15
15
  obj
16
16
  end
17
17
  end
18
+
19
+ def update(**params)
20
+ method_missing :update unless klass.respond_to? :update
21
+
22
+ primary_attributes = klass.method(:update).parameters.select { |(type, name)| type == :keyreq }.map(&:last) # Identified by whatever is a required named parameter.
23
+
24
+ primary_attributes.each do |attrib|
25
+ # ? Should we need to handle blank strings here?
26
+ params[attrib] = self[attrib] || self["#{attrib}_id"] # Handling for customer (customer_id) and id.
27
+ end
28
+
29
+ klass.public_send(:update, **params).each_pair { |key, val| self[key] = val } # Updating self
30
+
31
+ self
32
+ end
33
+
34
+ private
35
+
36
+ def klass
37
+ self.class
38
+ end
18
39
  end
19
40
  end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Paddle
4
- VERSION = "2.2.1"
4
+ VERSION = "2.3.0"
5
5
  end
data/lib/paddle.rb CHANGED
@@ -9,6 +9,8 @@ module Paddle
9
9
  autoload :Client, "paddle/client"
10
10
  autoload :Collection, "paddle/collection"
11
11
  autoload :Error, "paddle/error"
12
+ autoload :ErrorFactory, "paddle/error"
13
+
12
14
  autoload :Object, "paddle/object"
13
15
 
14
16
  class << self
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: paddle
3
3
  version: !ruby/object:Gem::Version
4
- version: 2.2.1
4
+ version: 2.3.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Dean Perry
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2024-06-28 00:00:00.000000000 Z
11
+ date: 2024-07-16 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: faraday
@@ -110,7 +110,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
110
110
  - !ruby/object:Gem::Version
111
111
  version: '0'
112
112
  requirements: []
113
- rubygems_version: 3.5.9
113
+ rubygems_version: 3.5.15
114
114
  signing_key:
115
115
  specification_version: 4
116
116
  summary: Ruby library for the Paddle Billing & Classic APIs