dlocal_go 0.1.1 → 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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 742994b45e67cb4d844d69cd4570795367e3f51fa0f6aaaa57d620679b1bbd99
4
- data.tar.gz: 25fb5000d012caa135caa37c432ab3282d9e4a4eae875a5356aa209ce3a59836
3
+ metadata.gz: 23d32c3c1f09afe545b9d6337792969bf19a3b07068a60e77e3d1f41a8837061
4
+ data.tar.gz: 04acfaa27fc1ac98fa0222d7c9d3d427d3ab075378cd01983cbbb7242993b5b2
5
5
  SHA512:
6
- metadata.gz: bf2f018e82417debfb6f3108da4d0fbd4552509861ee16cb5cae9d1ffb5b068eb008d8fc2e43c994c811af188ceb042e72eff4e160e89b0bbe5a82d6882d772b
7
- data.tar.gz: 42e6313c58bfc8ee44bedb9144f67cad7d49e90976897f3c3eb988fa46b57b6e278ba9f46c820524d2bade6d0d9f3ec2e52e66caedd924f4e5ddade9d2880db8
6
+ metadata.gz: 0be8022f5d868dbec5a81808e9e7a2c1f9d38b247e31cb94ab485359a1ec7564f24b3e96681aaa93237fe053f3bcce8d0b994befcb51d718829765c97ff734b3
7
+ data.tar.gz: 33c6ec1f139e3f07b4ae407c5475fb946d01c73c43632efd4f0d824d9d7eefafc964b4318d096179b8728c141daa906f0e6715ed369a702cefdb53527b5c9e74
data/.rubocop.yml CHANGED
@@ -10,7 +10,10 @@ Style/StringLiteralsInInterpolation:
10
10
  EnforcedStyle: double_quotes
11
11
 
12
12
  Layout/LineLength:
13
- Max: 120
13
+ Max: 200
14
+
15
+ Metrics/MethodLength:
16
+ Max: 15
14
17
 
15
18
  Metrics/BlockLength:
16
19
  Enabled: true
data/Gemfile.lock CHANGED
@@ -1,43 +1,64 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- dlocal_go (0.1.1)
4
+ dlocal_go (1.0)
5
+ activesupport
5
6
  http
6
7
 
7
8
  GEM
8
9
  remote: https://rubygems.org/
9
10
  specs:
11
+ activesupport (7.1.3)
12
+ base64
13
+ bigdecimal
14
+ concurrent-ruby (~> 1.0, >= 1.0.2)
15
+ connection_pool (>= 2.2.5)
16
+ drb
17
+ i18n (>= 1.6, < 2)
18
+ minitest (>= 5.1)
19
+ mutex_m
20
+ tzinfo (~> 2.0)
10
21
  addressable (2.8.1)
11
22
  public_suffix (>= 2.0.2, < 6.0)
12
23
  ast (2.4.2)
24
+ base64 (0.2.0)
25
+ bigdecimal (3.1.6)
26
+ concurrent-ruby (1.2.3)
27
+ connection_pool (2.4.1)
13
28
  crack (0.4.5)
14
29
  rexml
15
30
  debug (1.6.2)
16
31
  irb (>= 1.3.6)
17
32
  reline (>= 0.3.1)
18
33
  diff-lcs (1.5.0)
19
- domain_name (0.5.20190701)
20
- unf (>= 0.0.5, < 1.0.0)
21
- ffi (1.15.5)
34
+ domain_name (0.6.20240107)
35
+ drb (2.2.0)
36
+ ruby2_keywords
37
+ ffi (1.16.3)
22
38
  ffi-compiler (1.0.1)
23
39
  ffi (>= 1.0.0)
24
40
  rake
25
41
  hashdiff (1.0.1)
26
- http (5.1.1)
42
+ http (5.2.0)
27
43
  addressable (~> 2.8)
44
+ base64 (~> 0.1)
28
45
  http-cookie (~> 1.0)
29
46
  http-form_data (~> 2.2)
30
- llhttp-ffi (~> 0.4.0)
47
+ llhttp-ffi (~> 0.5.0)
31
48
  http-cookie (1.0.5)
32
49
  domain_name (~> 0.5)
33
50
  http-form_data (2.3.0)
51
+ i18n (1.14.1)
52
+ concurrent-ruby (~> 1.0)
34
53
  io-console (0.5.11)
35
54
  irb (1.4.1)
36
55
  reline (>= 0.3.0)
37
56
  json (2.6.2)
38
- llhttp-ffi (0.4.0)
57
+ llhttp-ffi (0.5.0)
39
58
  ffi-compiler (~> 1.0)
40
59
  rake (~> 13.0)
60
+ minitest (5.22.2)
61
+ mutex_m (0.2.0)
41
62
  parallel (1.22.1)
42
63
  parser (3.1.2.1)
43
64
  ast (~> 2.4.1)
@@ -74,9 +95,9 @@ GEM
74
95
  rubocop-ast (1.21.0)
75
96
  parser (>= 3.1.1.0)
76
97
  ruby-progressbar (1.11.0)
77
- unf (0.1.4)
78
- unf_ext
79
- unf_ext (0.0.8.2)
98
+ ruby2_keywords (0.0.5)
99
+ tzinfo (2.0.6)
100
+ concurrent-ruby (~> 1.0)
80
101
  unicode-display_width (2.2.0)
81
102
  webmock (3.18.1)
82
103
  addressable (>= 2.8.0)
@@ -85,6 +106,7 @@ GEM
85
106
 
86
107
  PLATFORMS
87
108
  arm64-darwin-21
109
+ arm64-darwin-23
88
110
  x86_64-linux
89
111
 
90
112
  DEPENDENCIES
data/README.md CHANGED
@@ -13,14 +13,9 @@ If bundler is not being used to manage dependencies, install the gem by executin
13
13
 
14
14
  $ gem install dlocal_go
15
15
 
16
- ## Preview
17
-
18
- https://user-images.githubusercontent.com/57004457/222937723-c95ca31c-2871-4f0f-a61e-fd4c9738e75f.mp4
19
-
20
-
21
16
  ## Usage
22
17
 
23
- 1. Configure DlocalGo in a initializer
18
+ 1. Configure DlocalGo inside an initializer
24
19
 
25
20
  ```ruby
26
21
  DlocalGo.setup do |config|
@@ -31,46 +26,85 @@ https://user-images.githubusercontent.com/57004457/222937723-c95ca31c-2871-4f0f-
31
26
  end
32
27
  ```
33
28
 
29
+ 2. Use the client to interact with the API
34
30
 
35
- 2. Use the client to create a payment, get a payment, or create a refund.
31
+ - If you need to send body parameters just pass a hash:
32
+
33
+ ```ruby
34
+ client = DlocalGo::Client.new
35
+ response = client.create_payment({country: "UY", currency: "UYU", amount: 500, notification_url: "https://notification.url"})
36
+ # or
37
+ # response = client.create_payment(country: "UY", currency: "UYU", amount: 500, notification_url: "https://notification.url")
38
+ ```
36
39
 
37
- - Create Payment
40
+ - If you need to use path variables for specific endpoints you can also pass them as arguments
38
41
 
39
42
  ```ruby
40
- params = {
41
- country_code: "UY",
42
- currency: "USD", # Optional, if not supplied, it uses the default currency for the country
43
- amount: 100,
44
- success_url: "https://success.url", # Where the user will be redirected after the payment is approved
45
- back_url: "https://back.url", # Where the user is redirected if they go back from the checkout page
46
- notification_url: "https://notification.url" # Optional, where the notification will be sent when payment state changes, (It will send a POST request with a payment_id param in the body, which can be used to retrieve the payment)
47
- }
48
- response = DlocalGo::Client.create_payment(params)
49
- # If request is not successful, it will raise a DlocalGo::Error, otherwise the response will be a DlocalGo::Response::Payment object
50
-
51
- # You might want to save the payment from the response before redirecting, so you can update the state later via a webhook (notification_url)
52
- redirect_to response.redirect_url, allow_other_host: true
43
+ client = DlocalGo::Client.new
44
+
45
+ # This will replace the payment_id path variable in the uri: /v1/payments/:payment_id
46
+ response = client.get_payment(payment_id: "payment_id")
53
47
  ```
54
48
 
55
- - Get Payment
49
+ - If you need to send query parameters just pass as a hash under a query_params key
56
50
 
57
51
  ```ruby
58
- response = DlocalGo::Client.get_payment("payment_id")
59
- # If request is not successful, it will raise a DlocalGo::Error, otherwise the response will be a DlocalGo::Response::Payment object
52
+ client = DlocalGo::Client.new
53
+ response = client.get_all_subscription_plans(query_params: {page: 2})
54
+
55
+ # You can also use it with endpoints that require path variables. Eg:
56
+ response = client.get_subscriptions_by_plan(plan_id: 1234, query_params: {page: 2})
60
57
  ```
61
58
 
62
- - Create Refund
59
+ 3. Handle the response
60
+
61
+ - We return DlocalGo::Responses objects (eg: DlocalGo::Responses::Payment) which have the same schema as the documentation responses.
62
+ - All attributes inside responses use the snake_case syntax
63
+
64
+ - NOTE: If the request fails we raise a DlocalGo::Error with an error code and message, so you might want to rescue it. (We'll make it optional in the future, for now we always raise an error when the request fails)
63
65
 
64
66
  ```ruby
65
- params = {
66
- payment_id: "payment_id_sample",
67
- amount: 100,
68
- reason: "reason_sample"
69
- }
70
- response = DlocalGo::Client.create_refund(params)
71
- # If request is not successful, it will raise a DlocalGo::Error, otherwise the response will be a DlocalGo::Response::Refund object
67
+ def create
68
+ # Example:
69
+ response = client.create_payment({country: "UY", currency: "UYU", amount: 500, notification_url: "https://notification.url"})
70
+ redirect_to response.redirect_url, allow_other_host: true
71
+
72
+ rescue DlocalGo::Error => e
73
+ # Do sth else
74
+ end
72
75
  ```
73
76
 
77
+ ## Supported Endpoints
78
+
79
+ We support all endpoints from the [DlocalGo API](https://docs.dlocalgo.com/integration-api)
80
+
81
+ ### Payments
82
+ - [x] Create Payment: `client.create_payment(params)`
83
+ - [x] Get Payment: `client.get_payment(payment_id: "the_id")`
84
+ - [x] Create Refund: `client.create_refund(params)`
85
+ - [x] Get Refund: `client.get_refund(refund_id: "the_id")`
86
+
87
+ ## Recurring Payments
88
+ - [x] Create Recurring Payment: `client.create_recurring_payment(params)`
89
+ - [x] Get Recurring Payment: `client.get_recurring_payment(recurring_link_token: "the_token")`
90
+ - [x] Get All Recurring Payments: `client.get_all_recurring_payments`
91
+
92
+ ## Subscriptions
93
+ - [x] Create Subscription Plan: `client.create_subscription_plan(params)`
94
+ - [x] Update Subscription Plan: `client.update_subscription_plan(plan_id: "the_id", params)`
95
+ - [x] Get All Subscription Plans: `client.get_all_subscription_plans`
96
+ - [x] Get Subscription Plan: `client.get_subscription_plan(plan_id: "the_id")`
97
+ - [x] Get Subscriptions by Plan: `client.get_subscriptions_by_plan(plan_id: "the_id")`
98
+ - [x] Get All Executions by Subscription: `client.get_all_executions_by_subscription(plan_id: "the_id", subscription_id: "the_id")`
99
+ - [x] Get Subscription Execution: `client.get_subscription_execution(subscription_id: "the_id", order_id: "the_id")`
100
+ - [x] Cancel Plan: `client.cancel_plan(plan_id: "the_id")`
101
+ - [x] Cancel Subscription: `client.cancel_subscription(plan_id: "the_id", subscription_id: "the_id")`
102
+
103
+
104
+ # Endpoints request and response schema details
105
+
106
+ - See the [DlocalGo API](https://docs.dlocalgo.com/integration-api) docs for more details on the request and response schema for each endpoint
107
+
74
108
  ## Contributing
75
109
 
76
110
  Bug reports and pull requests are welcome on GitHub at https://github.com/MetaLabs-inc/dlocal_go.
@@ -2,78 +2,58 @@
2
2
 
3
3
  require_relative "responses/payment"
4
4
  require_relative "responses/refund"
5
+ require_relative "responses/recurring_payment"
6
+ require_relative "responses/subscription_plan"
7
+ require_relative "responses/subscription"
8
+ require_relative "responses/subscription_execution"
9
+ require_relative "endpoint_generator"
5
10
 
6
11
  module DlocalGo
7
12
  # Client for Dlocal Go API
8
13
  class Client
9
- SANDBOX_URL = "https://api-sbx.dlocalgo.com"
10
- PRODUCTION_URL = "https://api.dlocalgo.com"
11
- DEFAULT_SUPPORTED_COUNTRIES = %w[UY AR CL BO BR CO CR EC GT ID MX MY PE PY].freeze
12
- CURRENCY_FOR_COUNTRY = { UY: "UYU", AR: "ARS", CL: "CLP", BO: "BOB", BR: "BRL",
13
- CO: "COP", CR: "CRC", EC: "USD", GT: "GTQ", ID: "IDR", MX: "MXN",
14
- MY: "MYR", PE: "PEN", PY: "PYG" }.freeze
14
+ include DlocalGo::EndpointGenerator
15
15
 
16
16
  def initialize
17
- @api_key = DlocalGo.api_key
18
- @api_secret = DlocalGo.api_secret
19
- @base_url = DlocalGo.environment == "production" ? PRODUCTION_URL : SANDBOX_URL
20
-
21
- raise DlocalGo::Error, "Dlocal Go api key is not set" if @api_key.nil?
22
- raise DlocalGo::Error, "Dlocal Go api secret is not set" if @api_secret.nil?
17
+ raise DlocalGo::Error, "Dlocal Go api key is not set" if api_key.nil?
18
+ raise DlocalGo::Error, "Dlocal Go api secret is not set" if api_secret.nil?
23
19
  end
24
20
 
25
- def create_payment(params = {})
26
- raise DlocalGo::Error, "Unsupported country" unless supported_countries.include?(params[:country_code])
27
-
28
- uri = "/v1/payments"
29
- body = { amount: params[:amount], country: params[:country_code], notification_url: params[:notification_url],
30
- currency: params[:currency] || CURRENCY_FOR_COUNTRY[params[:country_code].to_sym],
31
- success_url: params[:success_url], back_url: params[:back_url] }
32
-
33
- response = HTTP.auth(auth_header).headers(json_content_type).post(endpoint_url(uri), json: body)
34
-
35
- raise DlocalGo::Error, "Error creating checkout #{response.parse}" unless response.status.success?
21
+ # Request body requirements for each endpoint: https://docs.dlocalgo.com/integration-api/welcome-to-dlocal-go-api/
36
22
 
37
- DlocalGo::Responses::Payment.new(OpenStruct.new(response.parse))
38
- end
39
-
40
- def get_payment(payment_id)
41
- uri = "/v1/payments/#{payment_id}"
42
- response = HTTP.auth(auth_header).get(endpoint_url(uri))
23
+ # ===== USAGE =====
24
+ #
43
25
 
44
- raise DlocalGo::Error, "Error getting payment: #{response.parse}" unless response.status.success?
26
+ # For get and delete requests, send the path variables as a hash, for example: client.get_payment(payment_id: "123") and it will get replaced automatically inside the uri
27
+ # Also for get and delete requests, query params are taken from the query_params hash key, for example: client.get_all_subscription_plans(query_params: { page: 2 })
28
+ # This is an example that uses query and path params: client.get_all_executions_by_subscription(subscription_id: "123", plan_id: "456", query_params: { page: 2 })
45
29
 
46
- DlocalGo::Responses::Payment.new(OpenStruct.new(response.parse))
47
- end
30
+ # For post and put/patch requests, the hash variables will be included in the body instead
48
31
 
49
- def create_refund(params = {})
50
- uri = "/v1/refunds"
51
- body = { payment_id: params[:payment_id], currency: params[:currency], amount: params[:amount],
52
- notification_url: params[:notification_url] }
32
+ #
33
+ # ===== USAGE =====
53
34
 
54
- response = HTTP.auth(auth_header).headers(json_content_type).post(endpoint_url(uri), json: body)
35
+ # PAYMENTS
36
+ endpoint :create_payment, uri: "/v1/payments", verb: :post, dto_class: DlocalGo::Responses::Payment
37
+ endpoint :get_payment, uri: "/v1/payments/:payment_id", verb: :get, dto_class: DlocalGo::Responses::Payment
38
+ endpoint :create_refund, uri: "/v1/refunds", verb: :post, dto_class: DlocalGo::Responses::Refund
39
+ endpoint :get_refund, uri: "/v1/refunds/:refund_id", verb: :get, dto_class: DlocalGo::Responses::Refund
55
40
 
56
- raise DlocalGo::Error, "Error creating refund: #{response.parse}" unless response.status.success?
41
+ # RECURRING PAYMENTS
42
+ endpoint :create_recurring_payment, uri: "/v1/recurring-payments", verb: :post, dto_class: DlocalGo::Responses::RecurringPayment
43
+ endpoint :get_recurring_payment, uri: "/v1/recurring-payments/:recurring_link_token", verb: :get, dto_class: DlocalGo::Responses::RecurringPayment
44
+ endpoint :get_all_recurring_payments, uri: "/v1/recurring-payments", verb: :get, dto_class: DlocalGo::Responses::RecurringPayment
57
45
 
58
- DlocalGo::Responses::Refund.new(OpenStruct.new(response.parse))
59
- end
46
+ # SUBSCRIPTIONS
47
+ endpoint :create_subscription_plan, uri: "/v1/subscription/plan", verb: :post, dto_class: DlocalGo::Responses::SubscriptionPlan
48
+ endpoint :update_subscription_plan, uri: "/v1/subscription/plan/:plan_id", verb: :patch, dto_class: DlocalGo::Responses::SubscriptionPlan
49
+ endpoint :get_all_subscription_plans, uri: "/v1/subscription/plan/all", verb: :get, dto_class: DlocalGo::Responses::SubscriptionPlan
50
+ endpoint :get_subscription_plan, uri: "/v1/subscription/plan/:plan_id", verb: :get, dto_class: DlocalGo::Responses::SubscriptionPlan
60
51
 
61
- private
52
+ endpoint :get_subscriptions_by_plan, uri: "/v1/subscription/plan/:plan_id/subscription/all", verb: :get, dto_class: DlocalGo::Responses::Subscription
53
+ endpoint :get_all_executions_by_subscription, uri: "/v1/subscription/plan/:plan_id/subscription/:subscription_id/execution/all", verb: :get, dto_class: DlocalGo::Responses::SubscriptionExecution
54
+ endpoint :get_subscription_execution, uri: "/v1/subscription/:subscription_id/execution/:order_id", verb: :get, dto_class: DlocalGo::Responses::SubscriptionExecution
62
55
 
63
- def auth_header
64
- "Bearer #{@api_key}:#{@api_secret}"
65
- end
66
-
67
- def json_content_type
68
- { 'content-type': "application/json" }
69
- end
70
-
71
- def endpoint_url(endpoint_url)
72
- "#{@base_url}#{endpoint_url}"
73
- end
74
-
75
- def supported_countries
76
- DlocalGo.supported_countries || DEFAULT_SUPPORTED_COUNTRIES
77
- end
56
+ endpoint :cancel_plan, uri: "/v1/subscription/plan/:plan_id/deactivate", verb: :patch, dto_class: DlocalGo::Responses::SubscriptionPlan
57
+ endpoint :cancel_subscription, uri: "/v1/subscription/plan/:plan_id/subscription/:subscription_id/deactivate", verb: :patch, dto_class: DlocalGo::Responses::Subscription
78
58
  end
79
59
  end
@@ -0,0 +1,43 @@
1
+ # frozen_string_literal: true
2
+
3
+ module DlocalGo
4
+ # Constants we'll use throughout the gem
5
+ module Constants
6
+ SANDBOX_URL = "https://api-sbx.dlocalgo.com"
7
+ PRODUCTION_URL = "https://api.dlocalgo.com"
8
+
9
+ SUBSCRIPTION_BASE_SANDBOX_URL = "https://checkout-sbx.dlocalgo.com/validate/subscription"
10
+ SUBSCRIPTION_BASE_PRODUCTION_URL = "https://checkout.dlocalgo.com/validate/subscription"
11
+
12
+ DEFAULT_SUPPORTED_COUNTRIES = %w[UY AR CL BO BR CO CR EC GT ID MX MY PE PY].freeze
13
+ CURRENCY_FOR_COUNTRY = { UY: "UYU", AR: "ARS", CL: "CLP", BO: "BOB", BR: "BRL",
14
+ CO: "COP", CR: "CRC", EC: "USD", GT: "GTQ", ID: "IDR", MX: "MXN",
15
+ MY: "MYR", PE: "PEN", PY: "PYG" }.freeze
16
+
17
+ def currency_for_country(country)
18
+ CURRENCY_FOR_COUNTRY[country.to_sym]
19
+ end
20
+
21
+ private
22
+
23
+ def api_key
24
+ @api_key ||= DlocalGo.api_key
25
+ end
26
+
27
+ def api_secret
28
+ @api_secret ||= DlocalGo.api_secret
29
+ end
30
+
31
+ def base_url
32
+ @base_url ||= DlocalGo.environment == "production" ? PRODUCTION_URL : SANDBOX_URL
33
+ end
34
+
35
+ def subscription_base_url
36
+ @subscription_base_url ||= DlocalGo.environment == "production" ? SUBSCRIPTION_BASE_PRODUCTION_URL : SUBSCRIPTION_BASE_SANDBOX_URL
37
+ end
38
+
39
+ def supported_countries
40
+ @supported_countries ||= DlocalGo.supported_countries || DEFAULT_SUPPORTED_COUNTRIES
41
+ end
42
+ end
43
+ end
@@ -0,0 +1,93 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "http"
4
+
5
+ require_relative "constants"
6
+ require_relative "responses/array"
7
+
8
+ module DlocalGo
9
+ # Module that allows us to define endpoints in the DlocalGo::Client class just by calling the endpoint method
10
+ module EndpointGenerator
11
+ include Constants
12
+
13
+ def self.included(base)
14
+ base.extend(ClassMethods)
15
+ end
16
+
17
+ # "Define the DSL"
18
+ module ClassMethods
19
+ def endpoint(method, uri:, verb:, dto_class:)
20
+ define_method(method) do |params = {}|
21
+ if params[:country].present? && supported_countries.exclude?(params[:country])
22
+ raise DlocalGo::Error,
23
+ "Unsupported country"
24
+ end
25
+
26
+ response = call_api(verb, uri, params)
27
+ parse_response(response, dto_class)
28
+ end
29
+ end
30
+ end
31
+
32
+ private
33
+
34
+ def call_api(http_method, uri, params)
35
+ parsed_uri, keys_to_remove = parse_uri(uri, params)
36
+ url = endpoint_url(parsed_uri)
37
+ args = [http_method, url]
38
+ needs_body = %i[post put patch].include?(http_method)
39
+
40
+ request_body = params.except(*keys_to_remove)
41
+ args << { json: request_body } if needs_body
42
+
43
+ HTTP.auth(auth_header).headers(json_content_type).send(*args)
44
+ end
45
+
46
+ # We grab the query_params from the params hash
47
+ # We also grab the path variables from the params hash and replace them in the uri
48
+ # We return the uri and the keys from the params hash that we used so we can remove them later and not include them in the json body
49
+ def parse_uri(uri, params)
50
+ parsed_uri = uri
51
+ keys_to_remove = %i[query_params]
52
+ query_params = params[:query_params] || {}
53
+
54
+ params.each do |key, value|
55
+ next unless uri.include?(":#{key}")
56
+
57
+ parsed_uri = parsed_uri.gsub(":#{key}", value.to_s)
58
+ keys_to_remove << key
59
+ end
60
+
61
+ ["#{parsed_uri}?#{query_params.to_query}", keys_to_remove]
62
+ end
63
+
64
+ def parse_response(response, dto_class)
65
+ response_body = response.parse
66
+ unless response.status.success?
67
+ raise DlocalGo::Error.new(response_body["message"],
68
+ error_code: response_body["code"])
69
+ end
70
+
71
+ parse_successful_response(response_body, dto_class)
72
+ end
73
+
74
+ def parse_successful_response(response_body, dto_class)
75
+ struct = OpenStruct.new(response_body)
76
+ array_response = response_body["data"].is_a?(Array)
77
+
78
+ array_response ? DlocalGo::Responses::Array.new(struct, { data_class: dto_class }) : dto_class.new(struct)
79
+ end
80
+
81
+ def auth_header
82
+ "Bearer #{api_key}:#{api_secret}"
83
+ end
84
+
85
+ def json_content_type
86
+ { 'content-type': "application/json" }
87
+ end
88
+
89
+ def endpoint_url(endpoint_url)
90
+ "#{base_url}#{endpoint_url}"
91
+ end
92
+ end
93
+ end
@@ -1,5 +1,13 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module DlocalGo
4
- class Error < StandardError; end
4
+ # Generic error class for all errors that occur in the gem
5
+ class Error < StandardError
6
+ attr_reader :error_code
7
+
8
+ def initialize(message, error_code: nil)
9
+ @error_code = error_code
10
+ super(message)
11
+ end
12
+ end
5
13
  end
@@ -0,0 +1,20 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative "base"
4
+
5
+ module DlocalGo
6
+ module Responses
7
+ # Wrapper for Dlocal Go array responses
8
+ class Array < DlocalGo::Responses::Base
9
+ has_array_data_attribute :data
10
+
11
+ has_attributes %i[
12
+ total_elements
13
+ total_pages
14
+ page
15
+ number_of_elements
16
+ size
17
+ ]
18
+ end
19
+ end
20
+ end
@@ -0,0 +1,11 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative "response_parser"
4
+
5
+ module DlocalGo
6
+ module Responses
7
+ class Base
8
+ include DlocalGo::Responses::ResponseParser
9
+ end
10
+ end
11
+ end
@@ -1,19 +1,28 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ require_relative "base"
4
+
3
5
  module DlocalGo
4
6
  module Responses
5
7
  # Class that represents Dlocal Go payment schema
6
- class Payment
7
- RESPONSE_ATTRIBUTES = %i[id amount currency country created_date status order_id success_url back_url
8
- redirect_url merchant_checkout_token direct].freeze
9
-
10
- attr_reader(*RESPONSE_ATTRIBUTES)
11
-
12
- def initialize(response)
13
- RESPONSE_ATTRIBUTES.each do |attribute|
14
- instance_variable_set("@#{attribute}", response.send(attribute))
15
- end
16
- end
8
+ class Payment < DlocalGo::Responses::Base
9
+ has_attributes %i[
10
+ id
11
+ amount
12
+ currency
13
+ country
14
+ created_date
15
+ status
16
+ order_id
17
+ success_url
18
+ back_url
19
+ redirect_url
20
+ notification_url
21
+ merchant_checkout_token
22
+ approved_date
23
+ description
24
+ direct
25
+ ]
17
26
  end
18
27
  end
19
28
  end
@@ -0,0 +1,17 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative "base"
4
+
5
+ module DlocalGo
6
+ module Responses
7
+ # Class that represents Dlocal Go recurring payment schema
8
+ class RecurringPayment < DlocalGo::Responses::Base
9
+ has_attributes %i[
10
+ currency
11
+ amount
12
+ recurring_link_token
13
+ enabled
14
+ ]
15
+ end
16
+ end
17
+ end
@@ -1,18 +1,16 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ require_relative "base"
4
+
3
5
  module DlocalGo
4
6
  module Responses
5
7
  # Class that represents Dlocal Go refund schema
6
- class Refund
7
- RESPONSE_ATTRIBUTES = %i[id amount status].freeze
8
-
9
- attr_reader(*RESPONSE_ATTRIBUTES)
10
-
11
- def initialize(response)
12
- RESPONSE_ATTRIBUTES.each do |attribute|
13
- instance_variable_set("@#{attribute}", response.send(attribute))
14
- end
15
- end
8
+ class Refund < DlocalGo::Responses::Base
9
+ has_attributes %i[
10
+ id
11
+ amount
12
+ status
13
+ ]
16
14
  end
17
15
  end
18
16
  end
@@ -0,0 +1,84 @@
1
+ # frozen_string_literal: true
2
+
3
+ module DlocalGo
4
+ module Responses
5
+ # Module that makes it easier for DTOs to define their schema
6
+ module ResponseParser
7
+ def self.included(base)
8
+ base.class_eval { class_attribute :response_attributes, :response_associations, :array_data_attribute }
9
+
10
+ base.extend(ClassMethods)
11
+
12
+ base.class_eval <<-CODE, __FILE__, __LINE__ + 1
13
+ def initialize(response, options = {})
14
+ extract_options(options)
15
+
16
+ assign_attributes(response)
17
+ assign_associations(response)
18
+ end
19
+ CODE
20
+ end
21
+
22
+ # "Define the DSL" for all the DTOs
23
+ module ClassMethods
24
+ # rubocop:disable Naming/PredicateName
25
+ def has_attributes(attributes)
26
+ self.response_attributes = attributes
27
+
28
+ class_eval { attr_reader(*attributes) }
29
+ end
30
+
31
+ def has_association(attribute, klass)
32
+ self.response_associations ||= {}
33
+ self.response_associations[attribute] = klass
34
+
35
+ class_eval { attr_reader attribute }
36
+ end
37
+
38
+ def has_array_data_attribute(attribute)
39
+ self.array_data_attribute = attribute
40
+ end
41
+ # rubocop:enable Naming/PredicateName
42
+ end
43
+
44
+ private
45
+
46
+ def extract_options(options)
47
+ return unless options[:data_class].present?
48
+
49
+ raise ArgumentError, "array_data_attribute is required" if array_data_attribute.blank?
50
+
51
+ class_eval { has_association(array_data_attribute, options[:data_class]) }
52
+ end
53
+
54
+ def assign_attributes(response)
55
+ return if response_attributes.nil?
56
+
57
+ response_attributes.each do |attribute|
58
+ instance_variable_set("@#{attribute}",
59
+ response.send(attribute) || response.send(attribute.to_s.camelize(:lower)))
60
+ end
61
+ end
62
+
63
+ def assign_associations(response)
64
+ return if self.response_associations.nil?
65
+
66
+ self.response_associations.each do |attribute, klass|
67
+ response_data = response.send(attribute) || response.send(attribute.to_s.camelize(:lower))
68
+
69
+ if response_data.instance_of?(::Array)
70
+ mapped_data = response_data.map do |data|
71
+ struct = OpenStruct.new(data)
72
+ klass.new(struct)
73
+ end
74
+
75
+ instance_variable_set("@#{attribute}", mapped_data)
76
+ else
77
+ struct = OpenStruct.new(response_data)
78
+ instance_variable_set("@#{attribute}", klass.new(struct))
79
+ end
80
+ end
81
+ end
82
+ end
83
+ end
84
+ end
@@ -0,0 +1,33 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative "base"
4
+
5
+ require_relative "subscription_plan"
6
+
7
+ module DlocalGo
8
+ module Responses
9
+ # Class that represents Dlocal Go subscription schema
10
+ class Subscription < DlocalGo::Responses::Base
11
+ has_attributes %i[
12
+ id
13
+ country
14
+ subscription_token
15
+ status
16
+ language
17
+ scheduled_date
18
+ active
19
+ client_id
20
+ client_first_name
21
+ client_last_name
22
+ client_document_type
23
+ client_document
24
+ client_email
25
+ card_token
26
+ created_at
27
+ updated_at
28
+ ]
29
+
30
+ has_association :plan, DlocalGo::Responses::SubscriptionPlan
31
+ end
32
+ end
33
+ end
@@ -0,0 +1,27 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative "base"
4
+ require_relative "subscription"
5
+
6
+ module DlocalGo
7
+ module Responses
8
+ # Class that represents Dlocal Go subscription plan execution schema
9
+ class SubscriptionExecution < DlocalGo::Responses::Base
10
+ has_attributes %i[
11
+ id
12
+ status
13
+ order_id
14
+ merchant_checkout_id
15
+ currency
16
+ amount_paid
17
+ amount_received
18
+ checkout_currency
19
+ balance_currency
20
+ created_at
21
+ updated_at
22
+ ]
23
+
24
+ has_association :subscription, DlocalGo::Responses::Subscription
25
+ end
26
+ end
27
+ end
@@ -0,0 +1,31 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative "base"
4
+
5
+ module DlocalGo
6
+ module Responses
7
+ # Class that represents Dlocal Go subscription plan schema
8
+ class SubscriptionPlan < DlocalGo::Responses::Base
9
+ has_attributes %i[
10
+ id
11
+ merchant_id
12
+ name
13
+ description
14
+ country
15
+ currency
16
+ amount
17
+ frequency_type
18
+ frequency_value
19
+ active
20
+ free_trial_days
21
+ plan_token
22
+ back_url
23
+ notification_url
24
+ success_url
25
+ error_url
26
+ created_at
27
+ updated_at
28
+ ]
29
+ end
30
+ end
31
+ end
@@ -0,0 +1,20 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative "constants"
4
+
5
+ module DlocalGo
6
+ # Utilities for using the Dlocal Go API
7
+ class Utilities
8
+ include Constants
9
+
10
+ class << self
11
+ def subscription_url(token:, email: nil)
12
+ new.subscription_url(token: token, email: email)
13
+ end
14
+ end
15
+
16
+ def subscription_url(token:, email: nil)
17
+ email.present? ? "#{subscription_base_url}/#{token}?email=#{email}" : "#{base_url}#{token}"
18
+ end
19
+ end
20
+ end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module DlocalGo
4
- VERSION = "0.1.1"
4
+ VERSION = "1.0"
5
5
  end
data/lib/dlocal_go.rb CHANGED
@@ -1,8 +1,11 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ require "active_support/all"
4
+
3
5
  require_relative "dlocal_go/version"
4
6
  require_relative "dlocal_go/errors"
5
7
  require_relative "dlocal_go/client"
8
+ require_relative "dlocal_go/utilities"
6
9
 
7
10
  # Main module for Dlocal Go, it provides a way to configure the gem and imports the client
8
11
  module DlocalGo
metadata CHANGED
@@ -1,15 +1,29 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: dlocal_go
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.1
4
+ version: '1.0'
5
5
  platform: ruby
6
6
  authors:
7
7
  - matiassalles99
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2023-03-05 00:00:00.000000000 Z
11
+ date: 2024-04-24 00:00:00.000000000 Z
12
12
  dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: activesupport
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - ">="
18
+ - !ruby/object:Gem::Version
19
+ version: '0'
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - ">="
25
+ - !ruby/object:Gem::Version
26
+ version: '0'
13
27
  - !ruby/object:Gem::Dependency
14
28
  name: http
15
29
  requirement: !ruby/object:Gem::Requirement
@@ -39,17 +53,23 @@ files:
39
53
  - LICENSE.txt
40
54
  - README.md
41
55
  - Rakefile
42
- - dlocal_go.gemspec
43
56
  - lib/dlocal_go.rb
44
57
  - lib/dlocal_go/client.rb
58
+ - lib/dlocal_go/constants.rb
59
+ - lib/dlocal_go/endpoint_generator.rb
45
60
  - lib/dlocal_go/errors.rb
61
+ - lib/dlocal_go/responses/array.rb
62
+ - lib/dlocal_go/responses/base.rb
46
63
  - lib/dlocal_go/responses/payment.rb
64
+ - lib/dlocal_go/responses/recurring_payment.rb
47
65
  - lib/dlocal_go/responses/refund.rb
66
+ - lib/dlocal_go/responses/response_parser.rb
67
+ - lib/dlocal_go/responses/subscription.rb
68
+ - lib/dlocal_go/responses/subscription_execution.rb
69
+ - lib/dlocal_go/responses/subscription_plan.rb
70
+ - lib/dlocal_go/utilities.rb
48
71
  - lib/dlocal_go/version.rb
49
72
  - sig/dlocal_go.rbs
50
- - sig/dlocal_go/client.rbs
51
- - sig/dlocal_go/responses/payment.rbs
52
- - sig/dlocal_go/responses/refund.rbs
53
73
  homepage: https://github.com/MetaLabs-inc/dlocal_go
54
74
  licenses:
55
75
  - MIT
@@ -72,7 +92,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
72
92
  - !ruby/object:Gem::Version
73
93
  version: '0'
74
94
  requirements: []
75
- rubygems_version: 3.3.7
95
+ rubygems_version: 3.4.10
76
96
  signing_key:
77
97
  specification_version: 4
78
98
  summary: Dlocal Go client for ruby
data/dlocal_go.gemspec DELETED
@@ -1,36 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require_relative "lib/dlocal_go/version"
4
-
5
- Gem::Specification.new do |spec|
6
- spec.name = "dlocal_go"
7
- spec.version = DlocalGo::VERSION
8
- spec.authors = ["matiassalles99"]
9
- spec.email = ["matiassalles99@gmail.com"]
10
-
11
- spec.summary = "Dlocal Go client for ruby"
12
- spec.description = "Dlocal Go client written in ruby to interact with Dlocal Go's API"
13
- spec.homepage = "https://github.com/MetaLabs-inc/dlocal_go"
14
- spec.license = "MIT"
15
- spec.required_ruby_version = ">= 2.6.0"
16
-
17
- spec.metadata["homepage_uri"] = spec.homepage
18
- spec.metadata["source_code_uri"] = "https://github.com/MetaLabs-inc/dlocal_go"
19
- spec.metadata["changelog_uri"] = "https://github.com/MetaLabs-inc/dlocal_go/blob/main/CHANGELOG.md"
20
-
21
- # Specify which files should be added to the gem when it is released.
22
- # The `git ls-files -z` loads the files in the RubyGem that have been added into git.
23
- spec.files = Dir.chdir(__dir__) do
24
- `git ls-files -z`.split("\x0").reject do |f|
25
- (f == __FILE__) || f.match(%r{\A(?:(?:bin|test|spec|features)/|\.(?:git|travis|circleci)|appveyor)})
26
- end
27
- end
28
- spec.bindir = "exe"
29
- spec.executables = spec.files.grep(%r{\Aexe/}) { |f| File.basename(f) }
30
- spec.require_paths = ["lib"]
31
-
32
- spec.add_dependency "http"
33
-
34
- # For more information and examples about making a new gem, check out our
35
- # guide at: https://bundler.io/guides/creating_gem.html
36
- end
@@ -1,26 +0,0 @@
1
- module DlocalGo
2
- class Client
3
- CURRENCY_FOR_COUNTRY: Hash[Symbol, String]
4
- DEFAULT_SUPPORTED_COUNTRIES: Array[String]
5
- SANDBOX_URL: String
6
- PRODUCTION_URL: String
7
-
8
- @api_key: String
9
- @api_secret: String
10
- @base_url: String
11
-
12
- def create_payment: -> Responses::Payment
13
- def get_payment: -> Responses::Payment
14
- def create_refund: -> Responses::Refund
15
-
16
- private
17
-
18
- def auth_header: -> untyped
19
-
20
- def endpoint_url: -> untyped
21
-
22
- def json_content_type: -> untyped
23
-
24
- def supported_countries: -> untyped
25
- end
26
- end
@@ -1,7 +0,0 @@
1
- module DlocalGo
2
- module Responses
3
- class Payment
4
- RESPONSE_ATTRIBUTES: Array[Symbol]
5
- end
6
- end
7
- end
@@ -1,7 +0,0 @@
1
- module DlocalGo
2
- module Responses
3
- class Refund
4
- RESPONSE_ATTRIBUTES: Array[Symbol]
5
- end
6
- end
7
- end