polar-ruby 0.1.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.
Files changed (42) hide show
  1. checksums.yaml +7 -0
  2. data/.rspec +3 -0
  3. data/CHANGELOG.md +50 -0
  4. data/DEVELOPMENT.md +329 -0
  5. data/EXAMPLES.md +385 -0
  6. data/Gemfile +12 -0
  7. data/Gemfile.lock +115 -0
  8. data/LICENSE +23 -0
  9. data/PROJECT_SUMMARY.md +256 -0
  10. data/README.md +635 -0
  11. data/Rakefile +24 -0
  12. data/examples/demo.rb +106 -0
  13. data/lib/polar/authentication.rb +83 -0
  14. data/lib/polar/client.rb +144 -0
  15. data/lib/polar/configuration.rb +46 -0
  16. data/lib/polar/customer_portal/benefit_grants.rb +41 -0
  17. data/lib/polar/customer_portal/customers.rb +69 -0
  18. data/lib/polar/customer_portal/license_keys.rb +70 -0
  19. data/lib/polar/customer_portal/orders.rb +82 -0
  20. data/lib/polar/customer_portal/subscriptions.rb +51 -0
  21. data/lib/polar/errors.rb +96 -0
  22. data/lib/polar/http_client.rb +150 -0
  23. data/lib/polar/pagination.rb +133 -0
  24. data/lib/polar/resources/base.rb +47 -0
  25. data/lib/polar/resources/benefits.rb +64 -0
  26. data/lib/polar/resources/checkouts.rb +75 -0
  27. data/lib/polar/resources/customers.rb +120 -0
  28. data/lib/polar/resources/events.rb +45 -0
  29. data/lib/polar/resources/files.rb +57 -0
  30. data/lib/polar/resources/license_keys.rb +81 -0
  31. data/lib/polar/resources/metrics.rb +30 -0
  32. data/lib/polar/resources/oauth2.rb +61 -0
  33. data/lib/polar/resources/orders.rb +54 -0
  34. data/lib/polar/resources/organizations.rb +41 -0
  35. data/lib/polar/resources/payments.rb +29 -0
  36. data/lib/polar/resources/products.rb +58 -0
  37. data/lib/polar/resources/subscriptions.rb +55 -0
  38. data/lib/polar/resources/webhooks.rb +81 -0
  39. data/lib/polar/version.rb +5 -0
  40. data/lib/polar/webhooks.rb +174 -0
  41. data/lib/polar.rb +65 -0
  42. metadata +239 -0
data/examples/demo.rb ADDED
@@ -0,0 +1,106 @@
1
+ #!/usr/bin/env ruby
2
+ # Demo script showing the Polar Ruby SDK in action
3
+
4
+ require_relative '../lib/polar'
5
+
6
+ puts 'šŸ»ā€ā„ļø Polar Ruby SDK Demo'
7
+ puts '=' * 50
8
+
9
+ # Configuration example
10
+ puts "\nšŸ“‹ Configuration Examples:"
11
+ puts "- Production client: Polar.new(access_token: 'polar_oat_...') "
12
+ puts "- Sandbox client: Polar.new(access_token: 'polar_oat_...', server: :sandbox)"
13
+ puts "- With customer session: Polar.new(customer_session: 'customer_session_...')"
14
+
15
+ # Create a demo client (without real credentials)
16
+ puts "\nšŸ”§ Creating client instance..."
17
+ client = Polar.new
18
+
19
+ puts 'āœ… Client created successfully!'
20
+ puts 'Available resources:'
21
+
22
+ # List all available resources
23
+ resources = %w[
24
+ organizations products customers orders payments subscriptions
25
+ checkouts benefits license_keys files metrics events webhooks oauth2
26
+ ]
27
+
28
+ resources.each do |resource|
29
+ puts " • #{resource}: #{client.send(resource).class.name}"
30
+ end
31
+
32
+ puts "\nšŸ‘„ Customer Portal resources:"
33
+ customer_portal_resources = %w[customers orders subscriptions benefit_grants license_keys]
34
+ customer_portal_resources.each do |resource|
35
+ puts " • #{resource}: #{client.customer_portal.send(resource).class.name}"
36
+ end
37
+
38
+ # Configuration demonstration
39
+ puts "\nāš™ļø Configuration examples:"
40
+ Polar.configure do |config|
41
+ config.server = :sandbox
42
+ config.timeout = 60
43
+ config.retries = 5
44
+ config.debug = false
45
+ end
46
+
47
+ puts 'Global configuration set:'
48
+ puts " • Server: #{Polar.configuration.server}"
49
+ puts " • Timeout: #{Polar.configuration.timeout}s"
50
+ puts " • Retries: #{Polar.configuration.retries}"
51
+ puts " • Debug: #{Polar.configuration.debug}"
52
+
53
+ # Error handling demonstration
54
+ puts "\n🚨 Error handling capabilities:"
55
+ error_classes = [
56
+ Polar::HTTPError, Polar::NotFoundError, Polar::UnauthorizedError,
57
+ Polar::ValidationError, Polar::WebhookVerificationError, Polar::TimeoutError
58
+ ]
59
+
60
+ error_classes.each do |error_class|
61
+ puts " • #{error_class.name}"
62
+ end
63
+
64
+ # Webhook verification demo
65
+ puts "\nšŸ” Webhook verification example:"
66
+ payload = '{"type":"order.created","id":"evt_123","data":{"id":"order_123"}}'
67
+ timestamp = Time.now.to_i.to_s
68
+ secret = 'demo_webhook_secret'
69
+
70
+ signature = Polar::Webhooks.compute_signature(payload, timestamp, secret)
71
+ puts " • Computed signature: #{signature[0..20]}..."
72
+
73
+ # Event parsing
74
+ event = Polar::Webhooks::Event.new(payload)
75
+ puts " • Event type: #{event.type}"
76
+ puts " • Event ID: #{event.id}"
77
+ puts " • Is order event: #{event.order_event?}"
78
+
79
+ puts "\nšŸŽÆ Usage patterns:"
80
+ puts ' • List with pagination: client.customers.list.each { |customer| ... }'
81
+ puts ' • Auto-paginate: client.orders.list.auto_paginate'
82
+ puts " • Single resource: client.products.get('prod_123')"
83
+ puts " • Create resource: client.customers.create(email: '...', name: '...')"
84
+
85
+ puts "\n✨ Key features:"
86
+ puts ' āœ… Complete API coverage'
87
+ puts ' āœ… Type-safe error handling'
88
+ puts ' āœ… Automatic pagination'
89
+ puts ' āœ… Retry logic with backoff'
90
+ puts ' āœ… Webhook verification'
91
+ puts ' āœ… Customer portal support'
92
+ puts ' āœ… Environment switching (prod/sandbox)'
93
+ puts ' āœ… Ruby 2.7+ compatibility'
94
+
95
+ puts "\nšŸ“š For detailed usage examples, see:"
96
+ puts ' • README.md - Main documentation'
97
+ puts ' • EXAMPLES.md - Comprehensive usage examples'
98
+ puts ' • DEVELOPMENT.md - Development guide'
99
+
100
+ puts "\nšŸ”— Resources:"
101
+ puts ' • Polar.sh Documentation: https://polar.sh/docs'
102
+ puts ' • API Reference: https://polar.sh/docs/api-reference'
103
+ puts ' • Discord Community: https://discord.gg/polar'
104
+
105
+ puts "\nšŸŽ‰ SDK loaded and validated successfully!"
106
+ puts 'Ready to integrate with Polar.sh payment infrastructure.'
@@ -0,0 +1,83 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Polar
4
+ module Authentication
5
+ # Organization Access Token authentication
6
+ class OATAuth
7
+ attr_reader :access_token
8
+
9
+ def initialize(access_token)
10
+ @access_token = access_token
11
+ validate_token!
12
+ end
13
+
14
+ def headers
15
+ {
16
+ 'Authorization' => "Bearer #{access_token}",
17
+ 'Content-Type' => 'application/json',
18
+ 'Accept' => 'application/json'
19
+ }
20
+ end
21
+
22
+ def valid?
23
+ !access_token.nil? && !access_token.empty? && access_token.start_with?('polar_oat_')
24
+ end
25
+
26
+ private
27
+
28
+ def validate_token!
29
+ return if valid?
30
+
31
+ raise AuthenticationError, 'Access token is required' if access_token.nil? || access_token.empty?
32
+
33
+ return if access_token.start_with?('polar_oat_')
34
+
35
+ raise AuthenticationError,
36
+ "Invalid Organization Access Token format. Expected token to start with 'polar_oat_'"
37
+ end
38
+ end
39
+
40
+ # Customer Access Token authentication
41
+ class CustomerAuth
42
+ attr_reader :customer_session
43
+
44
+ def initialize(customer_session)
45
+ @customer_session = customer_session
46
+ validate_token!
47
+ end
48
+
49
+ def headers
50
+ {
51
+ 'Authorization' => "Bearer #{customer_session}",
52
+ 'Content-Type' => 'application/json',
53
+ 'Accept' => 'application/json'
54
+ }
55
+ end
56
+
57
+ def valid?
58
+ !customer_session.nil? && !customer_session.empty?
59
+ end
60
+
61
+ private
62
+
63
+ def validate_token!
64
+ return if valid?
65
+
66
+ raise AuthenticationError, 'Customer session token is required'
67
+ end
68
+ end
69
+
70
+ # Factory for creating appropriate authentication based on token type
71
+ class AuthFactory
72
+ def self.create(token)
73
+ return nil if token.nil? || token.empty?
74
+
75
+ if token.start_with?('polar_oat_')
76
+ OATAuth.new(token)
77
+ else
78
+ CustomerAuth.new(token)
79
+ end
80
+ end
81
+ end
82
+ end
83
+ end
@@ -0,0 +1,144 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Polar
4
+ class Client
5
+ include Pagination
6
+
7
+ attr_reader :configuration, :auth, :http_client
8
+
9
+ def initialize(options = {})
10
+ @configuration = build_configuration(options)
11
+ @auth = build_authentication(options)
12
+ @http_client = HTTPClient.new(@configuration, @auth)
13
+ end
14
+
15
+ # Core API Resources
16
+ def organizations
17
+ @organizations ||= Resources::Organizations.new(self)
18
+ end
19
+
20
+ def products
21
+ @products ||= Resources::Products.new(self)
22
+ end
23
+
24
+ def customers
25
+ @customers ||= Resources::Customers.new(self)
26
+ end
27
+
28
+ def orders
29
+ @orders ||= Resources::Orders.new(self)
30
+ end
31
+
32
+ def payments
33
+ @payments ||= Resources::Payments.new(self)
34
+ end
35
+
36
+ def subscriptions
37
+ @subscriptions ||= Resources::Subscriptions.new(self)
38
+ end
39
+
40
+ def checkouts
41
+ @checkouts ||= Resources::Checkouts.new(self)
42
+ end
43
+
44
+ def benefits
45
+ @benefits ||= Resources::Benefits.new(self)
46
+ end
47
+
48
+ def license_keys
49
+ @license_keys ||= Resources::LicenseKeys.new(self)
50
+ end
51
+
52
+ def files
53
+ @files ||= Resources::Files.new(self)
54
+ end
55
+
56
+ def metrics
57
+ @metrics ||= Resources::Metrics.new(self)
58
+ end
59
+
60
+ def events
61
+ @events ||= Resources::Events.new(self)
62
+ end
63
+
64
+ def webhooks
65
+ @webhooks ||= Resources::Webhooks.new(self)
66
+ end
67
+
68
+ def oauth2
69
+ @oauth2 ||= Resources::OAuth2.new(self)
70
+ end
71
+
72
+ # Customer Portal API
73
+ def customer_portal
74
+ @customer_portal ||= CustomerPortalClient.new(self)
75
+ end
76
+
77
+ private
78
+
79
+ def build_configuration(options)
80
+ config = Configuration.new
81
+
82
+ # Set from options
83
+ config.access_token = options[:access_token] || ENV['POLAR_ACCESS_TOKEN']
84
+ config.server = options[:server] || :production
85
+ config.base_url = options[:base_url] if options[:base_url]
86
+ config.timeout = options[:timeout] if options[:timeout]
87
+ config.retries = options[:retries] if options[:retries]
88
+ config.logger = options[:logger] if options[:logger]
89
+ config.debug = options[:debug] || ENV['POLAR_DEBUG'] == 'true'
90
+
91
+ # Apply global configuration
92
+ global_config = Polar.configuration
93
+ config.access_token ||= global_config.access_token
94
+ config.server = global_config.server if global_config.server && !options.key?(:server)
95
+ config.base_url ||= global_config.base_url
96
+ config.timeout = global_config.timeout if global_config.timeout && !options.key?(:timeout)
97
+ config.retries = global_config.retries if global_config.retries && !options.key?(:retries)
98
+ config.logger ||= global_config.logger
99
+ config.debug = global_config.debug if global_config.debug && !options.key?(:debug)
100
+
101
+ config
102
+ end
103
+
104
+ def build_authentication(options)
105
+ token = options[:access_token] || @configuration.access_token
106
+ customer_session = options[:customer_session]
107
+
108
+ if customer_session
109
+ Authentication::CustomerAuth.new(customer_session)
110
+ elsif token
111
+ Authentication::AuthFactory.create(token)
112
+ end
113
+ end
114
+ end
115
+
116
+ # Customer Portal specific client wrapper
117
+ class CustomerPortalClient
118
+ attr_reader :client
119
+
120
+ def initialize(client)
121
+ @client = client
122
+ end
123
+
124
+ def customers
125
+ @customers ||= CustomerPortal::Customers.new(@client)
126
+ end
127
+
128
+ def orders
129
+ @orders ||= CustomerPortal::Orders.new(@client)
130
+ end
131
+
132
+ def subscriptions
133
+ @subscriptions ||= CustomerPortal::Subscriptions.new(@client)
134
+ end
135
+
136
+ def benefit_grants
137
+ @benefit_grants ||= CustomerPortal::BenefitGrants.new(@client)
138
+ end
139
+
140
+ def license_keys
141
+ @license_keys ||= CustomerPortal::LicenseKeys.new(@client)
142
+ end
143
+ end
144
+ end
@@ -0,0 +1,46 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Polar
4
+ class Configuration
5
+ attr_accessor :access_token, :server, :base_url, :timeout, :retries, :logger, :debug
6
+
7
+ # Server environments
8
+ PRODUCTION_SERVER = 'https://api.polar.sh/v1'
9
+ SANDBOX_SERVER = 'https://sandbox-api.polar.sh/v1'
10
+
11
+ def initialize
12
+ @server = :production
13
+ @timeout = 30
14
+ @retries = 3
15
+ @debug = false
16
+ @logger = nil
17
+ end
18
+
19
+ def base_url
20
+ @base_url || server_url
21
+ end
22
+
23
+ attr_writer :base_url
24
+
25
+ def server=(environment)
26
+ unless %i[production sandbox].include?(environment.to_sym)
27
+ raise ArgumentError, 'Invalid server environment. Must be :production or :sandbox'
28
+ end
29
+
30
+ @server = environment.to_sym
31
+ end
32
+
33
+ private
34
+
35
+ def server_url
36
+ case @server
37
+ when :production
38
+ PRODUCTION_SERVER
39
+ when :sandbox
40
+ SANDBOX_SERVER
41
+ else
42
+ raise ArgumentError, "Unknown server environment: #{@server}"
43
+ end
44
+ end
45
+ end
46
+ end
@@ -0,0 +1,41 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative '../resources/base'
4
+
5
+ module Polar
6
+ module CustomerPortal
7
+ class BenefitGrants < Resources::Base
8
+ # List customer benefit grants
9
+ # @param params [Hash] Query parameters
10
+ # @param customer_session [String] Customer session token
11
+ # @option params [Integer] :page Page number
12
+ # @option params [Integer] :limit Items per page
13
+ # @return [PaginatedResponse] Paginated list of benefit grants
14
+ def list(params = {}, customer_session:)
15
+ headers = { 'Authorization' => "Bearer #{customer_session}" }
16
+ paginate('/customer-portal/benefit-grants', params, headers)
17
+ end
18
+
19
+ # Get customer benefit grant
20
+ # @param id [String] Benefit grant ID
21
+ # @param customer_session [String] Customer session token
22
+ # @return [Hash] Benefit grant data
23
+ def get(id, customer_session:)
24
+ headers = { 'Authorization' => "Bearer #{customer_session}" }
25
+ response = get("/customer-portal/benefit-grants/#{id}", {}, headers)
26
+ response.body
27
+ end
28
+
29
+ # Update customer benefit grant
30
+ # @param id [String] Benefit grant ID
31
+ # @param attributes [Hash] Updated attributes
32
+ # @param customer_session [String] Customer session token
33
+ # @return [Hash] Updated benefit grant
34
+ def update(id, attributes, customer_session:)
35
+ headers = { 'Authorization' => "Bearer #{customer_session}" }
36
+ response = patch("/customer-portal/benefit-grants/#{id}", attributes, headers)
37
+ response.body
38
+ end
39
+ end
40
+ end
41
+ end
@@ -0,0 +1,69 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative '../resources/base'
4
+
5
+ module Polar
6
+ module CustomerPortal
7
+ class Customers < Resources::Base
8
+ # Get authenticated customer information
9
+ # @param customer_session [String] Customer session token
10
+ # @return [Hash] Customer data
11
+ def get(customer_session:)
12
+ headers = { 'Authorization' => "Bearer #{customer_session}" }
13
+ response = get('/customer-portal/customers/me', {}, headers)
14
+ response.body
15
+ end
16
+
17
+ # Update authenticated customer
18
+ # @param attributes [Hash] Updated customer attributes
19
+ # @param customer_session [String] Customer session token
20
+ # @return [Hash] Updated customer
21
+ def update(attributes, customer_session:)
22
+ headers = { 'Authorization' => "Bearer #{customer_session}" }
23
+ response = patch('/customer-portal/customers/me', attributes, headers)
24
+ response.body
25
+ end
26
+
27
+ # List customer payment methods
28
+ # @param customer_session [String] Customer session token
29
+ # @return [Array] List of payment methods
30
+ def list_payment_methods(customer_session:)
31
+ headers = { 'Authorization' => "Bearer #{customer_session}" }
32
+ response = get('/customer-portal/customers/me/payment-methods', {}, headers)
33
+ response.body
34
+ end
35
+
36
+ # Add customer payment method
37
+ # @param payment_method_data [Hash] Payment method data
38
+ # @param customer_session [String] Customer session token
39
+ # @return [Hash] Payment method creation response
40
+ def add_payment_method(payment_method_data, customer_session:)
41
+ headers = { 'Authorization' => "Bearer #{customer_session}" }
42
+ response = post('/customer-portal/customers/me/payment-methods', payment_method_data, headers)
43
+ response.body
44
+ end
45
+
46
+ # Confirm customer payment method
47
+ # @param payment_method_id [String] Payment method ID
48
+ # @param confirmation_data [Hash] Confirmation data
49
+ # @param customer_session [String] Customer session token
50
+ # @return [Hash] Confirmation response
51
+ def confirm_payment_method(payment_method_id, confirmation_data, customer_session:)
52
+ headers = { 'Authorization' => "Bearer #{customer_session}" }
53
+ path = "/customer-portal/customers/me/payment-methods/#{payment_method_id}/confirm"
54
+ response = post(path, confirmation_data, headers)
55
+ response.body
56
+ end
57
+
58
+ # Delete customer payment method
59
+ # @param payment_method_id [String] Payment method ID
60
+ # @param customer_session [String] Customer session token
61
+ # @return [Boolean] Success status
62
+ def delete_payment_method(payment_method_id, customer_session:)
63
+ headers = { 'Authorization' => "Bearer #{customer_session}" }
64
+ delete("/customer-portal/customers/me/payment-methods/#{payment_method_id}", headers)
65
+ true
66
+ end
67
+ end
68
+ end
69
+ end
@@ -0,0 +1,70 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative '../resources/base'
4
+
5
+ module Polar
6
+ module CustomerPortal
7
+ class LicenseKeys < Resources::Base
8
+ # List customer license keys
9
+ # @param params [Hash] Query parameters
10
+ # @param customer_session [String] Customer session token
11
+ # @option params [Integer] :page Page number
12
+ # @option params [Integer] :limit Items per page
13
+ # @return [PaginatedResponse] Paginated list of license keys
14
+ def list(params = {}, customer_session:)
15
+ headers = { 'Authorization' => "Bearer #{customer_session}" }
16
+ paginate('/customer-portal/license-keys', params, headers)
17
+ end
18
+
19
+ # Get customer license key
20
+ # @param id [String] License key ID
21
+ # @param customer_session [String] Customer session token
22
+ # @return [Hash] License key data
23
+ def get(id, customer_session:)
24
+ headers = { 'Authorization' => "Bearer #{customer_session}" }
25
+ response = get("/customer-portal/license-keys/#{id}", {}, headers)
26
+ response.body
27
+ end
28
+
29
+ # Validate a license key (no authentication required)
30
+ # @param key [String] License key
31
+ # @param activation_id [String, nil] Optional activation ID
32
+ # @return [Hash] Validation result
33
+ def validate(key, activation_id: nil)
34
+ body = { key: key }
35
+ body[:activation_id] = activation_id if activation_id
36
+
37
+ response = post('/customer-portal/license-keys/validate', body)
38
+ response.body
39
+ end
40
+
41
+ # Activate a license key (no authentication required)
42
+ # @param key [String] License key
43
+ # @param activation_data [Hash] Activation data
44
+ # @param customer_session [String, nil] Optional customer session token
45
+ # @option activation_data [String] :label Activation label
46
+ # @option activation_data [Hash] :metadata Activation metadata
47
+ # @return [Hash] Activation result
48
+ def activate(key, activation_data = {}, customer_session: nil)
49
+ body = { key: key }.merge(activation_data)
50
+ headers = customer_session ? { 'Authorization' => "Bearer #{customer_session}" } : {}
51
+
52
+ response = post('/customer-portal/license-keys/activate', body, headers)
53
+ response.body
54
+ end
55
+
56
+ # Deactivate a license key (no authentication required)
57
+ # @param key [String] License key
58
+ # @param activation_id [String] Activation ID
59
+ # @param customer_session [String, nil] Optional customer session token
60
+ # @return [Boolean] Success status
61
+ def deactivate(key, activation_id, customer_session: nil)
62
+ body = { key: key, activation_id: activation_id }
63
+ headers = customer_session ? { 'Authorization' => "Bearer #{customer_session}" } : {}
64
+
65
+ post('/customer-portal/license-keys/deactivate', body, headers)
66
+ true
67
+ end
68
+ end
69
+ end
70
+ end
@@ -0,0 +1,82 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative '../resources/base'
4
+
5
+ module Polar
6
+ module CustomerPortal
7
+ class Orders < Resources::Base
8
+ # List customer orders
9
+ # @param params [Hash] Query parameters
10
+ # @param customer_session [String] Customer session token
11
+ # @option params [Integer] :page Page number
12
+ # @option params [Integer] :limit Items per page
13
+ # @return [PaginatedResponse] Paginated list of orders
14
+ def list(params = {}, customer_session:)
15
+ headers = { 'Authorization' => "Bearer #{customer_session}" }
16
+ paginate('/customer-portal/orders', params, headers)
17
+ end
18
+
19
+ # Get customer order
20
+ # @param id [String] Order ID
21
+ # @param customer_session [String] Customer session token
22
+ # @return [Hash] Order data
23
+ def get(id, customer_session:)
24
+ headers = { 'Authorization' => "Bearer #{customer_session}" }
25
+ response = get("/customer-portal/orders/#{id}", {}, headers)
26
+ response.body
27
+ end
28
+
29
+ # Update customer order
30
+ # @param id [String] Order ID
31
+ # @param attributes [Hash] Updated attributes
32
+ # @param customer_session [String] Customer session token
33
+ # @return [Hash] Updated order
34
+ def update(id, attributes, customer_session:)
35
+ headers = { 'Authorization' => "Bearer #{customer_session}" }
36
+ response = patch("/customer-portal/orders/#{id}", attributes, headers)
37
+ response.body
38
+ end
39
+
40
+ # Generate invoice for customer order
41
+ # @param id [String] Order ID
42
+ # @param customer_session [String] Customer session token
43
+ # @return [Hash] Invoice generation result
44
+ def generate_invoice(id, customer_session:)
45
+ headers = { 'Authorization' => "Bearer #{customer_session}" }
46
+ response = post("/customer-portal/orders/#{id}/invoice", {}, headers)
47
+ response.body
48
+ end
49
+
50
+ # Get customer order invoice
51
+ # @param id [String] Order ID
52
+ # @param customer_session [String] Customer session token
53
+ # @return [Hash] Invoice data
54
+ def invoice(id, customer_session:)
55
+ headers = { 'Authorization' => "Bearer #{customer_session}" }
56
+ response = get("/customer-portal/orders/#{id}/invoice", {}, headers)
57
+ response.body
58
+ end
59
+
60
+ # Get order payment status
61
+ # @param id [String] Order ID
62
+ # @param customer_session [String] Customer session token
63
+ # @return [Hash] Payment status
64
+ def get_payment_status(id, customer_session:)
65
+ headers = { 'Authorization' => "Bearer #{customer_session}" }
66
+ response = get("/customer-portal/orders/#{id}/payment-status", {}, headers)
67
+ response.body
68
+ end
69
+
70
+ # Confirm retry payment for order
71
+ # @param id [String] Order ID
72
+ # @param payment_data [Hash] Payment confirmation data
73
+ # @param customer_session [String] Customer session token
74
+ # @return [Hash] Payment confirmation result
75
+ def confirm_retry_payment(id, payment_data, customer_session:)
76
+ headers = { 'Authorization' => "Bearer #{customer_session}" }
77
+ response = post("/customer-portal/orders/#{id}/confirm-retry-payment", payment_data, headers)
78
+ response.body
79
+ end
80
+ end
81
+ end
82
+ end
@@ -0,0 +1,51 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative '../resources/base'
4
+
5
+ module Polar
6
+ module CustomerPortal
7
+ class Subscriptions < Resources::Base
8
+ # List customer subscriptions
9
+ # @param params [Hash] Query parameters
10
+ # @param customer_session [String] Customer session token
11
+ # @option params [Integer] :page Page number
12
+ # @option params [Integer] :limit Items per page
13
+ # @return [PaginatedResponse] Paginated list of subscriptions
14
+ def list(params = {}, customer_session:)
15
+ headers = { 'Authorization' => "Bearer #{customer_session}" }
16
+ paginate('/customer-portal/subscriptions', params, headers)
17
+ end
18
+
19
+ # Get customer subscription
20
+ # @param id [String] Subscription ID
21
+ # @param customer_session [String] Customer session token
22
+ # @return [Hash] Subscription data
23
+ def get(id, customer_session:)
24
+ headers = { 'Authorization' => "Bearer #{customer_session}" }
25
+ response = get("/customer-portal/subscriptions/#{id}", {}, headers)
26
+ response.body
27
+ end
28
+
29
+ # Update customer subscription
30
+ # @param id [String] Subscription ID
31
+ # @param attributes [Hash] Updated attributes
32
+ # @param customer_session [String] Customer session token
33
+ # @return [Hash] Updated subscription
34
+ def update(id, attributes, customer_session:)
35
+ headers = { 'Authorization' => "Bearer #{customer_session}" }
36
+ response = patch("/customer-portal/subscriptions/#{id}", attributes, headers)
37
+ response.body
38
+ end
39
+
40
+ # Cancel customer subscription
41
+ # @param id [String] Subscription ID
42
+ # @param customer_session [String] Customer session token
43
+ # @return [Hash] Cancelled subscription
44
+ def cancel(id, customer_session:)
45
+ headers = { 'Authorization' => "Bearer #{customer_session}" }
46
+ response = post("/customer-portal/subscriptions/#{id}/cancel", {}, headers)
47
+ response.body
48
+ end
49
+ end
50
+ end
51
+ end