me_api 2.3.0 → 2.4.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: 3942e2db2028d21e0b113511557db26e3983b8a4da443f786210d4dfe52da15b
4
- data.tar.gz: 82ac71f265cad50574709106ddfe4ae2517b5c340e99f23dba14e21129b7f4a1
3
+ metadata.gz: eba26dc8650233f06f9e7a6fd2a7f0c39c4efad985fdef065900dba0ed1d520f
4
+ data.tar.gz: 2f3b45d5a3c8052d8c326fcab320e7fd92d40f87d55903e24c320e608bbecdc2
5
5
  SHA512:
6
- metadata.gz: 4ee347a27811c6a1d3cc34b40d87242c0e5a6583c621581b4333901288eff7ddb50eae697f28c447bfc27c7def09ff3e2b21f0da46689c17e4e9b1b63f0696c6
7
- data.tar.gz: 4deb41586578128a1fb7ed55ecda83428ed177352ac0daf82b9afc4d55e1ed7beb45bb10e6142f0931aa9a303d9ed110db2924b33dbfab8c181110385cb35186
6
+ metadata.gz: 83db71da4de61236728c80a9694949695dd29e98bf114aba171565e51dffb4be51b981754d2562a18fbb0cf8c51d930ca2a66d03909d63b6be33069960c3c760
7
+ data.tar.gz: 8ea06416c60b8759bb412adc62ff082aa40edae08832fdce9b8f40607f27bf7aa4120abcccd5061195b92603c32ba559672623de118631bc91b999256b58503d
@@ -0,0 +1,158 @@
1
+ module MeApi
2
+ class ClientProduction < Ac::Base
3
+ BASE_URL = "https://melhorenvio.com.br"
4
+ SAVE_RESPONSES = true
5
+
6
+ attr_reader :refresh_token, :client_id, :client_secret, :test_mode, :token_expires_at
7
+ def initialize(access_token: nil, refresh_token: nil, client_id: , client_secret:, token_expires_at:, test_mode: false)
8
+ @access_token = access_token
9
+ @refresh_token = refresh_token
10
+ @client_id = client_id
11
+ @client_secret = client_secret
12
+ @test_mode = test_mode
13
+ @token_expires_at = token_expires_at
14
+ end
15
+
16
+ def refresh_token(client_id:, client_secret:, refresh_token:)
17
+ body = {
18
+ grant_type: "refresh_token",
19
+ client_id: client_id,
20
+ client_secret: client_secret,
21
+ refresh_token: refresh_token
22
+ }
23
+ post("/oauth/token", body:, skip_authentication: true)
24
+ end
25
+
26
+ def authorize client_id:, client_secret:, code:, redirect_url:
27
+ body = {
28
+ grant_type: "authorization_code",
29
+ client_id: client_id,
30
+ client_secret: client_secret,
31
+ code: code,
32
+ redirect_uri: redirect_url
33
+ }
34
+ post("/oauth/token", body:, skip_authentication: true)
35
+ end
36
+
37
+ def default_options
38
+ {
39
+ headers: {
40
+ "Accept" => "application/json",
41
+ "Content-Type" => "application/json"
42
+ }
43
+ }
44
+ end
45
+
46
+ # @param volume [Object<MeApi::Volume>] Volume object containing width_cm, height_cm, length_cm, and weight_kg
47
+ def rates(from_postal_code:, to_postal_code:, volume:, contents_value_brl:)
48
+ body = {
49
+ from: {
50
+ postal_code: from_postal_code
51
+ },
52
+ to: {
53
+ postal_code: to_postal_code
54
+ },
55
+ package: volume.to_api_format,
56
+ options: {
57
+ insurance_value: contents_value_brl,
58
+ receipt: false,
59
+ own_hand: false
60
+ },
61
+ services: "1,2,3,4,17,33"
62
+ }
63
+ post("api/v2/me/shipment/calculate", body:) { _1.first.name }
64
+ end
65
+
66
+ # @param products [Array<MeApi::Product>] Array of product objects containing name, quantity, and unitary_value
67
+ # @param volumes [Array<MeApi::Volume>] Array of volume objects containing width_cm, height_cm, length_cm, and weight_kg
68
+ def add_label_to_cart(service_id:, from_name:, from_phone:, from_email:, from_address:, from_address_complement:, from_address_number:, from_address_district:, from_address_city:, from_postal_code:, from_address_state_abbr:, from_tax_id:, to_name:, to_phone:, to_email:, to_address:, to_address_complement:, to_address_number:, to_address_district:, to_address_city:, to_postal_code:, to_address_state_abbr:, to_tax_id:, products:, volumes:, insurance_value:)
69
+
70
+ from_tax_id_clean = cleaned_tax_id(from_tax_id)
71
+ to_tax_id_clean = cleaned_tax_id(to_tax_id)
72
+
73
+ body = {
74
+ service: service_id,
75
+ from: {
76
+ name: from_name,
77
+ phone: from_phone,
78
+ email: from_email,
79
+ address: from_address,
80
+ complement: from_address_complement,
81
+ number: from_address_number,
82
+ district: from_address_district,
83
+ city: from_address_city,
84
+ postal_code: from_postal_code,
85
+ state_abbr: from_address_state_abbr
86
+ },
87
+
88
+ to: {
89
+ name: to_name,
90
+ phone: to_phone,
91
+ email: to_email,
92
+ address: to_address,
93
+ complement: to_address_complement,
94
+ number: to_address_number,
95
+ district: to_address_district,
96
+ city: to_address_city,
97
+ postal_code: to_postal_code,
98
+ state_abbr: to_address_state_abbr
99
+ },
100
+ products: products.map do |product|
101
+ product.to_api_format
102
+ end,
103
+ volumes: volumes.map do |volume|
104
+ volume.to_api_format
105
+ end,
106
+ options: {
107
+ insurance_value: insurance_value,
108
+ }
109
+ }
110
+
111
+ add_tax_document_to_address(body[:from], from_tax_id_clean)
112
+ add_tax_document_to_address(body[:to], to_tax_id_clean)
113
+
114
+ post("/api/v2/me/cart", body:)
115
+ end
116
+
117
+ def pay_label(order_id)
118
+ body = {
119
+ orders: [order_id.to_s]
120
+ }
121
+ post("/api/v2/me/shipment/checkout", body:)
122
+ end
123
+
124
+ def generate_label(order_id)
125
+ body = {
126
+ orders: [order_id.to_s]
127
+ }
128
+ post("/api/v2/me/shipment/generate", body:)
129
+ end
130
+
131
+ def print_label(order_id)
132
+ get("/api/v2/me/imprimir/pdf/#{order_id}") { _1[0].include? order_id }
133
+ end
134
+
135
+ def get_label(order_id)
136
+ get("/api/v2/me/orders/#{order_id}")
137
+ end
138
+
139
+ def get_account_data
140
+ get("/api/v2/me")
141
+ end
142
+
143
+ def get_balance
144
+ get("/api/v2/me/balance")
145
+ end
146
+
147
+ private
148
+
149
+ def cleaned_tax_id(tax_id)
150
+ tax_id.gsub(/\D/, "")
151
+ end
152
+
153
+ def add_tax_document_to_address(address_hash, tax_id)
154
+ document_key = tax_id.length == 11 ? :document : :company_document
155
+ address_hash[document_key] = tax_id
156
+ end
157
+ end
158
+ end
@@ -0,0 +1,5 @@
1
+ module MeApi
2
+ class ClientSandbox < ClientProduction
3
+ BASE_URL = "https://sandbox.melhorenvio.com.br"
4
+ end
5
+ end
@@ -0,0 +1,19 @@
1
+ module MeApi
2
+ class Product
3
+ attr_accessor :name, :quantity, :unitary_value
4
+
5
+ def initialize(name:, quantity:, unitary_value:)
6
+ @name = name
7
+ @quantity = quantity
8
+ @unitary_value = unitary_value
9
+ end
10
+
11
+ def to_api_format
12
+ {
13
+ name: name,
14
+ quantity: quantity,
15
+ unitary_value: unitary_value
16
+ }
17
+ end
18
+ end
19
+ end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module MeApi
4
- VERSION = "2.3.0"
4
+ VERSION = "2.4.0"
5
5
  end
@@ -0,0 +1,21 @@
1
+ module MeApi
2
+ class Volume
3
+ attr_accessor :width_cm, :height_cm, :length_cm, :weight_kg
4
+
5
+ def initialize(width_cm:, height_cm:, length_cm:, weight_kg:)
6
+ @width_cm = width_cm
7
+ @height_cm = height_cm
8
+ @length_cm = length_cm
9
+ @weight_kg = weight_kg
10
+ end
11
+
12
+ def to_api_format
13
+ {
14
+ width: width_cm,
15
+ height: height_cm,
16
+ length: length_cm,
17
+ weight: weight_kg
18
+ }
19
+ end
20
+ end
21
+ end
data/lib/me_api.rb CHANGED
@@ -2,9 +2,21 @@
2
2
 
3
3
  require "ac"
4
4
  require_relative "me_api/version"
5
- require_relative "me_api/client"
5
+ require_relative "me_api/client_production"
6
+ require_relative "me_api/client_sandbox"
7
+ require_relative "me_api/product"
8
+ require_relative "me_api/volume"
6
9
 
7
10
  module MeApi
8
11
  class Error < StandardError; end
9
- # Your code goes here...
12
+
13
+ class Client
14
+ def self.new **args
15
+ if args[:test_mode]
16
+ ClientSandbox.new(**args)
17
+ else
18
+ ClientProduction.new(**args)
19
+ end
20
+ end
21
+ end
10
22
  end
metadata CHANGED
@@ -1,13 +1,13 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: me_api
3
3
  version: !ruby/object:Gem::Version
4
- version: 2.3.0
4
+ version: 2.4.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Todas Essas Coisas
8
8
  bindir: exe
9
9
  cert_chain: []
10
- date: 2025-07-31 00:00:00.000000000 Z
10
+ date: 2025-08-04 00:00:00.000000000 Z
11
11
  dependencies:
12
12
  - !ruby/object:Gem::Dependency
13
13
  name: ac
@@ -36,8 +36,11 @@ files:
36
36
  - README.md
37
37
  - Rakefile
38
38
  - lib/me_api.rb
39
- - lib/me_api/client.rb
39
+ - lib/me_api/client_production.rb
40
+ - lib/me_api/client_sandbox.rb
41
+ - lib/me_api/product.rb
40
42
  - lib/me_api/version.rb
43
+ - lib/me_api/volume.rb
41
44
  homepage: https://github.com/todasessascoisas/me_api
42
45
  licenses:
43
46
  - MIT
data/lib/me_api/client.rb DELETED
@@ -1,117 +0,0 @@
1
- module MeApi
2
- class Client < Ac::Base
3
- BASE_URL = "https://melhorenvio.com.br"
4
- SAVE_RESPONSES = true
5
- Rate = Data.define(:id, :from, :to, :price, :min_delivery_time, :max_delivery_time, :service_name, :carrier_name, :carrier_logo_url)
6
-
7
- def rates(from:, to:, weight_kg:, contents_value_brl:, height_cm:, width_cm:, length_cm:)
8
- body = {
9
- "from" => {
10
- "postal_code" => from
11
- },
12
- "to" => {
13
- "postal_code" => to
14
- },
15
- "package" => {
16
- "weight" => weight_kg,
17
- "height" => height_cm,
18
- "width" => width_cm,
19
- "length" => length_cm
20
- },
21
- "options" => {
22
- "insurance_value" => contents_value_brl,
23
- "receipt" => false,
24
- "own_hand" => false
25
- },
26
- "services" => "1,2,3,4,17,33"
27
- }
28
- response = post("api/v2/me/shipment/calculate", body:) { _1.first.name }
29
- response.map do |rate|
30
- next unless rate["error"].blank? && rate["price"]
31
- Rate.new(
32
- id: rate.id,
33
- from: from,
34
- to: to,
35
- price: rate.price.to_f,
36
- min_delivery_time: rate.delivery_range.min,
37
- max_delivery_time: rate.delivery_range.max,
38
- service_name: rate.name,
39
- carrier_name: rate.company.name,
40
- carrier_logo_url: rate.company.picture
41
- )
42
- end.compact
43
- end
44
-
45
- def refresh_token(client_id:, client_secret:, refresh_token:)
46
- body = {
47
- grant_type: "refresh_token",
48
- client_id: client_id,
49
- client_secret: client_secret,
50
- refresh_token: refresh_token
51
- }
52
- post("/oauth/token", body:)
53
- end
54
-
55
- def authorize client_id:, client_secret:, code:, redirect_url:
56
- body = {
57
- grant_type: "authorization_code",
58
- client_id: client_id,
59
- client_secret: client_secret,
60
- code: code,
61
- redirect_uri: redirect_url
62
- }
63
- post("/oauth/token", body:, skip_authentication: true)
64
- end
65
-
66
- def default_options
67
- {
68
- headers: {
69
- "Accept" => "application/json",
70
- "Content-Type" => "application/json"
71
- }
72
- }
73
- end
74
-
75
- def insert_package_into_cart(service_id:, from:, to:, products:, volumes:, options:)
76
- body = {
77
- service: service_id,
78
- from: from,
79
- to: to,
80
- products: products,
81
- volumes: volumes,
82
- options: options
83
- }
84
- post("/api/v2/me/cart", body:)
85
- end
86
-
87
- def payment_ticket(order_id)
88
- body = {
89
- orders: [order_id.to_s]
90
- }
91
- post("/api/v2/me/shipment/checkout", body:)
92
- end
93
-
94
- def generate_ticket(order_id)
95
- body = {
96
- orders: [order_id.to_s]
97
- }
98
- post("/api/v2/me/shipment/generate", body:)
99
- end
100
-
101
- def print_ticket(order_id)
102
- get("/api/v2/me/imprimir/pdf/#{order_id}") { _1[0].include? order_id }
103
- end
104
-
105
- def get_ticket(order_id)
106
- get("/api/v2/me/orders/#{order_id}")
107
- end
108
-
109
- def get_account_data
110
- get("/api/v2/me")
111
- end
112
-
113
- def get_balance
114
- get("/api/v2/me/balance")
115
- end
116
- end
117
- end