cdek_api_client 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.
- checksums.yaml +7 -0
- data/README.md +306 -0
- data/lib/cdek_api_client/client.rb +114 -0
- data/lib/cdek_api_client/entities/currency_mapper.rb +34 -0
- data/lib/cdek_api_client/entities/item.rb +44 -0
- data/lib/cdek_api_client/entities/location.rb +30 -0
- data/lib/cdek_api_client/entities/order_data.rb +61 -0
- data/lib/cdek_api_client/entities/package.rb +44 -0
- data/lib/cdek_api_client/entities/payment.rb +30 -0
- data/lib/cdek_api_client/entities/recipient.rb +33 -0
- data/lib/cdek_api_client/entities/sender.rb +33 -0
- data/lib/cdek_api_client/entities/service.rb +33 -0
- data/lib/cdek_api_client/entities/tariff_data.rb +42 -0
- data/lib/cdek_api_client/entities/validatable.rb +90 -0
- data/lib/cdek_api_client/entities/webhook.rb +32 -0
- data/lib/cdek_api_client/location.rb +32 -0
- data/lib/cdek_api_client/order.rb +43 -0
- data/lib/cdek_api_client/recipient.rb +37 -0
- data/lib/cdek_api_client/tariff.rb +32 -0
- data/lib/cdek_api_client/track_order.rb +29 -0
- data/lib/cdek_api_client/version.rb +5 -0
- data/lib/cdek_api_client/webhook.rb +54 -0
- data/lib/cdek_api_client.rb +37 -0
- metadata +112 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: 389563fd9ba0f235cdc75afdc77906d9e2fb7d3f6da3d4392105758c8ad8756a
|
4
|
+
data.tar.gz: dfa1b6d50ea42547dfdf8c5846a47c9882e8b2ab5f56557b014d122a026c5eb2
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 364b5510d3f833a43ff3ab1d0581844821e1cbce1211a61b81802c3fb1f228d901621552c57e4052aaa88ae6609861ee5a2e1ff6ad759eaa970d51b70de1b3a5
|
7
|
+
data.tar.gz: b982eef2e9d6bb5f268204af574605f7f96a077331cfeb38d58db02a2ef9be601e5cac83439b4aa879b245ac41262c97a3dcb6cc83eca2bf977e5359af989089
|
data/README.md
ADDED
@@ -0,0 +1,306 @@
|
|
1
|
+
# CDEK API Client
|
2
|
+
|
3
|
+
[](https://badge.fury.io/rb/cdek_api_client)
|
4
|
+
|
5
|
+
A Ruby client for interacting with the CDEK API, providing functionalities for order creation, tracking, tariff calculation, location data retrieval, and webhook management. This gem ensures clean, robust, and maintainable code with proper validations.
|
6
|
+
|
7
|
+
This Readme is also available in:
|
8
|
+
|
9
|
+
- [Russian](README_RUS.md)
|
10
|
+
- [Tatar](README_TAT.md)
|
11
|
+
|
12
|
+
## Table of Contents
|
13
|
+
|
14
|
+
- [Installation](#installation)
|
15
|
+
- [Usage](#usage)
|
16
|
+
- [Initialization](#initialization)
|
17
|
+
- [Creating an Order](#creating-an-order)
|
18
|
+
- [Tracking an Order](#tracking-an-order)
|
19
|
+
- [Calculating Tariff](#calculating-tariff)
|
20
|
+
- [Getting Location Data](#getting-location-data)
|
21
|
+
- [Setting Up Webhooks](#setting-up-webhooks)
|
22
|
+
- [Entities](#entities)
|
23
|
+
- [OrderData](#orderdata)
|
24
|
+
- [Recipient](#recipient)
|
25
|
+
- [Sender](#sender)
|
26
|
+
- [Package](#package)
|
27
|
+
- [Item](#item)
|
28
|
+
- [Contributing](#contributing)
|
29
|
+
- [License](#license)
|
30
|
+
|
31
|
+
## Installation
|
32
|
+
|
33
|
+
Add this line to your application's Gemfile:
|
34
|
+
|
35
|
+
```ruby
|
36
|
+
gem 'cdek_api_client'
|
37
|
+
```
|
38
|
+
|
39
|
+
````
|
40
|
+
|
41
|
+
And then execute:
|
42
|
+
|
43
|
+
```sh
|
44
|
+
bundle install
|
45
|
+
```
|
46
|
+
|
47
|
+
Or install it yourself as:
|
48
|
+
|
49
|
+
```sh
|
50
|
+
gem install cdek_api_client
|
51
|
+
```
|
52
|
+
|
53
|
+
## Usage
|
54
|
+
|
55
|
+
### Initialization
|
56
|
+
|
57
|
+
To use the CDEK API Client, you need to initialize it with your CDEK API credentials (client ID and client secret):
|
58
|
+
|
59
|
+
```ruby
|
60
|
+
require 'cdek_api_client'
|
61
|
+
|
62
|
+
client_id = 'your_client_id'
|
63
|
+
client_secret = 'your_client_secret'
|
64
|
+
|
65
|
+
client = CDEKApiClient::Client.new(client_id, client_secret)
|
66
|
+
```
|
67
|
+
|
68
|
+
### Creating an Order
|
69
|
+
|
70
|
+
To create an order, you need to create the necessary entities (`OrderData`, `Recipient`, `Sender`, `Package`, and `Item`) and then pass them to the `create_order` method of the `Order` class:
|
71
|
+
|
72
|
+
```ruby
|
73
|
+
recipient = CDEKApiClient::Entities::Recipient.new(
|
74
|
+
name: 'John Doe',
|
75
|
+
phones: [{ number: '+79000000000' }],
|
76
|
+
email: 'johndoe@example.com'
|
77
|
+
)
|
78
|
+
|
79
|
+
sender = CDEKApiClient::Entities::Sender.new(
|
80
|
+
name: 'Sender Name',
|
81
|
+
phones: [{ number: '+79000000001' }],
|
82
|
+
email: 'sender@example.com'
|
83
|
+
)
|
84
|
+
|
85
|
+
item = CDEKApiClient::Entities::Item.new(
|
86
|
+
name: 'Item 1',
|
87
|
+
ware_key: '00055',
|
88
|
+
payment: 1000,
|
89
|
+
cost: 1000,
|
90
|
+
weight: 500,
|
91
|
+
amount: 1
|
92
|
+
)
|
93
|
+
|
94
|
+
package = CDEKApiClient::Entities::Package.new(
|
95
|
+
number: '1',
|
96
|
+
weight: 500,
|
97
|
+
length: 10,
|
98
|
+
width: 10,
|
99
|
+
height: 10,
|
100
|
+
comment: 'Package 1',
|
101
|
+
items: [item]
|
102
|
+
)
|
103
|
+
|
104
|
+
order_data = CDEKApiClient::Entities::OrderData.new(
|
105
|
+
type: 1,
|
106
|
+
number: 'TEST123',
|
107
|
+
tariff_code: 1,
|
108
|
+
comment: 'Test order',
|
109
|
+
recipient: recipient,
|
110
|
+
sender: sender,
|
111
|
+
from_location: { code: 44 },
|
112
|
+
to_location: { code: 270 },
|
113
|
+
packages: [package]
|
114
|
+
)
|
115
|
+
|
116
|
+
order_client = CDEKApiClient::Order.new(client)
|
117
|
+
|
118
|
+
begin
|
119
|
+
order_response = order_client.create(order_data)
|
120
|
+
puts "Order created successfully: #{order_response}"
|
121
|
+
rescue => e
|
122
|
+
puts "Error creating order: #{e.message}"
|
123
|
+
end
|
124
|
+
```
|
125
|
+
|
126
|
+
### Tracking an Order
|
127
|
+
|
128
|
+
To track an order, use the `track` method of the `Order` class with the order UUID:
|
129
|
+
|
130
|
+
```ruby
|
131
|
+
order_uuid = 'order_uuid_from_created_order_response'
|
132
|
+
|
133
|
+
begin
|
134
|
+
tracking_info = order_client.track(order_uuid)
|
135
|
+
puts "Tracking info: #{tracking_info}"
|
136
|
+
rescue => e
|
137
|
+
puts "Error tracking order: #{e.message}"
|
138
|
+
end
|
139
|
+
```
|
140
|
+
|
141
|
+
### Calculating Tariff
|
142
|
+
|
143
|
+
To calculate the tariff, use the `calculate` method of the `Tariff` class with the necessary tariff data:
|
144
|
+
|
145
|
+
```ruby
|
146
|
+
tariff_data = CDEKApiClient::Entities::TariffData.new(
|
147
|
+
type: 1,
|
148
|
+
currency: 'RUB',
|
149
|
+
from_location: { code: 44 },
|
150
|
+
to_location: { code: 137 },
|
151
|
+
packages: [{ weight: 500, length: 10, width: 10, height: 10 }]
|
152
|
+
)
|
153
|
+
|
154
|
+
tariff_client = CDEKApiClient::Tariff.new(client)
|
155
|
+
|
156
|
+
begin
|
157
|
+
tariff_response = tariff_client.calculate(tariff_data)
|
158
|
+
puts "Tariff calculated: #{tariff_response}"
|
159
|
+
rescue => e
|
160
|
+
puts "Error calculating tariff: #{e.message}"
|
161
|
+
end
|
162
|
+
```
|
163
|
+
|
164
|
+
### Getting Location Data
|
165
|
+
|
166
|
+
To retrieve location data such as cities and regions supported by CDEK, use the `cities` and `regions` methods of the `Location` class:
|
167
|
+
|
168
|
+
```ruby
|
169
|
+
location_client = CDEKApiClient::Location.new(client)
|
170
|
+
|
171
|
+
# Fetching cities
|
172
|
+
begin
|
173
|
+
cities = location_client.cities
|
174
|
+
puts "Cities: #{cities}"
|
175
|
+
rescue => e
|
176
|
+
puts "Error fetching cities: #{e.message}"
|
177
|
+
end
|
178
|
+
|
179
|
+
# Fetching regions
|
180
|
+
begin
|
181
|
+
regions = location_client.regions
|
182
|
+
puts "Regions: #{regions}"
|
183
|
+
rescue => e
|
184
|
+
puts "Error fetching regions: #{e.message}"
|
185
|
+
end
|
186
|
+
```
|
187
|
+
|
188
|
+
### Setting Up Webhooks
|
189
|
+
|
190
|
+
Webhooks allow your application to receive real-time notifications about various events related to your shipments. To set up a webhook, register a URL where CDEK will send HTTP POST requests with event data:
|
191
|
+
|
192
|
+
```ruby
|
193
|
+
webhook_client = CDEKApiClient::Webhook.new(client)
|
194
|
+
|
195
|
+
webhook_url = 'https://yourapp.com/webhooks/cdek'
|
196
|
+
begin
|
197
|
+
response = webhook_client.register(webhook_url, event_types: ['ORDER_STATUS', 'DELIVERY_STATUS'])
|
198
|
+
puts "Webhook registered: #{response}"
|
199
|
+
rescue => e
|
200
|
+
puts "Error registering webhook: #{e.message}"
|
201
|
+
end
|
202
|
+
```
|
203
|
+
|
204
|
+
To retrieve and delete registered webhooks:
|
205
|
+
|
206
|
+
```ruby
|
207
|
+
# Fetching webhooks
|
208
|
+
begin
|
209
|
+
webhooks = webhook_client.get_webhooks
|
210
|
+
puts "Webhooks: #{webhooks}"
|
211
|
+
rescue => e
|
212
|
+
puts "Error fetching webhooks: #{e.message}"
|
213
|
+
end
|
214
|
+
|
215
|
+
# Deleting a webhook
|
216
|
+
webhook_id = 'webhook_id_to_delete'
|
217
|
+
begin
|
218
|
+
response = webhook_client.delete(webhook_id)
|
219
|
+
puts "Webhook deleted: #{response}"
|
220
|
+
rescue => e
|
221
|
+
puts "Error deleting webhook: #{e.message}"
|
222
|
+
end
|
223
|
+
```
|
224
|
+
|
225
|
+
## Entities
|
226
|
+
|
227
|
+
### OrderData
|
228
|
+
|
229
|
+
Represents the order data.
|
230
|
+
|
231
|
+
Attributes:
|
232
|
+
|
233
|
+
- `type` (Integer, required): The type of the order.
|
234
|
+
- `number` (String, required): The order number.
|
235
|
+
- `tariff_code` (Integer, required): The tariff code.
|
236
|
+
- `comment` (String): The comment for the order.
|
237
|
+
- `recipient` (Recipient, required): The recipient details.
|
238
|
+
- `sender` (Sender, required): The sender details.
|
239
|
+
- `from_location` (Hash, required): The location details from where the order is shipped.
|
240
|
+
- `to_location` (Hash, required): The location details to where the order is shipped.
|
241
|
+
- `services` (Array): Additional services.
|
242
|
+
- `packages` (Array, required): List of packages.
|
243
|
+
|
244
|
+
### Recipient
|
245
|
+
|
246
|
+
Represents the recipient details.
|
247
|
+
|
248
|
+
Attributes:
|
249
|
+
|
250
|
+
- `name` (String, required): The recipient's name.
|
251
|
+
- `phones` (Array, required): List of phone numbers.
|
252
|
+
- `email` (String, required): The recipient's email address.
|
253
|
+
|
254
|
+
### Sender
|
255
|
+
|
256
|
+
Represents the sender details.
|
257
|
+
|
258
|
+
Attributes:
|
259
|
+
|
260
|
+
- `name` (String, required): The sender's name.
|
261
|
+
- `phones` (Array, required): List of phone numbers.
|
262
|
+
- `email` (String, required): The sender's email address.
|
263
|
+
|
264
|
+
### Package
|
265
|
+
|
266
|
+
Represents the package details.
|
267
|
+
|
268
|
+
Attributes:
|
269
|
+
|
270
|
+
- `number` (String, required): The package number.
|
271
|
+
- `weight` (Integer, required): The weight of the package.
|
272
|
+
- `length` (Integer, required): The length of the package.
|
273
|
+
- `width` (Integer, required): The width of the package.
|
274
|
+
- `height` (Integer, required): The height of the package.
|
275
|
+
- `comment` (String): The comment for the package.
|
276
|
+
- `items` (Array, required): List of items in the package.
|
277
|
+
|
278
|
+
### Item
|
279
|
+
|
280
|
+
Represents the item details.
|
281
|
+
|
282
|
+
Attributes:
|
283
|
+
|
284
|
+
- `name` (String, required): The name of the item.
|
285
|
+
- `ware_key` (String, required): The ware key of the item.
|
286
|
+
- `payment` (Integer, required): The payment value of the item.
|
287
|
+
- `cost` (Integer, required): The cost of the item.
|
288
|
+
- `weight` (Integer, required): The weight of the item.
|
289
|
+
- `amount` (Integer, required): The amount of the item.
|
290
|
+
|
291
|
+
## TODO List
|
292
|
+
|
293
|
+
- [ ] Restructure the codebase for better organization.
|
294
|
+
- [ ] Add mappings for CDEK internal codes.
|
295
|
+
- [ ] Add more API endpoints and data entities.
|
296
|
+
- [ ] Check all attributes for required and optional fields.
|
297
|
+
- [ ] Add documentation for all classes and methods.
|
298
|
+
|
299
|
+
## Contributing
|
300
|
+
|
301
|
+
Bug reports and pull requests are welcome on GitHub at [https://github.com/your-username/cdek_api_client](https://github.com/your-username/cdek_api_client).
|
302
|
+
|
303
|
+
## License
|
304
|
+
|
305
|
+
The gem is available as open-source under the terms of the [MIT License](https://opensource.org/licenses/MIT).
|
306
|
+
````
|
@@ -0,0 +1,114 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'faraday'
|
4
|
+
require 'faraday_middleware'
|
5
|
+
require 'json'
|
6
|
+
require 'logger'
|
7
|
+
|
8
|
+
module CDEKApiClient
|
9
|
+
##
|
10
|
+
# Client class for interacting with the CDEK API.
|
11
|
+
#
|
12
|
+
# This class provides methods for authentication and initializing the API resources
|
13
|
+
# for orders, locations, tariffs, and webhooks.
|
14
|
+
#
|
15
|
+
# @attr_reader [String] token The access token used for authentication.
|
16
|
+
# @attr_reader [Logger] logger The logger used for logging HTTP requests and responses.
|
17
|
+
# @attr_reader [Order] order The Order resource for interacting with order-related API endpoints.
|
18
|
+
# @attr_reader [Location] location The Location resource for interacting with location-related API endpoints.
|
19
|
+
# @attr_reader [Tariff] tariff The Tariff resource for interacting with tariff-related API endpoints.
|
20
|
+
# @attr_reader [Webhook] webhook The Webhook resource for interacting with webhook-related API endpoints.
|
21
|
+
class Client
|
22
|
+
BASE_URL = ENV.fetch('CDEK_API_URL', 'https://api.edu.cdek.ru/v2')
|
23
|
+
TOKEN_URL = "#{BASE_URL}/oauth/token".freeze
|
24
|
+
|
25
|
+
attr_reader :token, :logger, :order, :location, :tariff, :webhook
|
26
|
+
|
27
|
+
##
|
28
|
+
# Initializes a new Client object.
|
29
|
+
#
|
30
|
+
# @param [String] client_id The client ID for authentication.
|
31
|
+
# @param [String] client_secret The client secret for authentication.
|
32
|
+
# @param [Logger] logger The logger for logging HTTP requests and responses.
|
33
|
+
def initialize(client_id, client_secret, logger: Logger.new($stdout))
|
34
|
+
@client_id = client_id
|
35
|
+
@client_secret = client_secret
|
36
|
+
@logger = logger
|
37
|
+
@token = authenticate
|
38
|
+
|
39
|
+
@order = CDEKApiClient::Order.new(self)
|
40
|
+
@location = CDEKApiClient::Location.new(self)
|
41
|
+
@tariff = CDEKApiClient::Tariff.new(self)
|
42
|
+
@webhook = CDEKApiClient::Webhook.new(self)
|
43
|
+
end
|
44
|
+
|
45
|
+
##
|
46
|
+
# Authenticates with the CDEK API and retrieves an access token.
|
47
|
+
#
|
48
|
+
# @return [String] The access token.
|
49
|
+
# @raise [Error] if there is an error getting the token.
|
50
|
+
def authenticate
|
51
|
+
response = connection.post(TOKEN_URL) do |req|
|
52
|
+
req.body = {
|
53
|
+
grant_type: 'client_credentials',
|
54
|
+
client_id: @client_id,
|
55
|
+
client_secret: @client_secret
|
56
|
+
}
|
57
|
+
end
|
58
|
+
|
59
|
+
raise Error, "Error getting token: #{response.body}" unless response.success?
|
60
|
+
|
61
|
+
response.body['access_token']
|
62
|
+
end
|
63
|
+
|
64
|
+
##
|
65
|
+
# Creates a Faraday connection object.
|
66
|
+
#
|
67
|
+
# @return [Faraday::Connection] The Faraday connection object.
|
68
|
+
def connection
|
69
|
+
Faraday.new(url: BASE_URL) do |conn|
|
70
|
+
conn.request :url_encoded
|
71
|
+
conn.response :json, content_type: /\bjson$/
|
72
|
+
conn.adapter Faraday.default_adapter
|
73
|
+
conn.response :logger, @logger, bodies: true
|
74
|
+
end
|
75
|
+
end
|
76
|
+
|
77
|
+
##
|
78
|
+
# Creates a Faraday connection object with authorization.
|
79
|
+
#
|
80
|
+
# @return [Faraday::Connection] The Faraday connection object with authorization.
|
81
|
+
def auth_connection
|
82
|
+
Faraday.new(url: BASE_URL) do |conn|
|
83
|
+
conn.request :url_encoded
|
84
|
+
conn.response :json, content_type: /\bjson$/
|
85
|
+
conn.authorization :Bearer, @token
|
86
|
+
conn.adapter Faraday.default_adapter
|
87
|
+
conn.response :logger, @logger, bodies: true
|
88
|
+
end
|
89
|
+
end
|
90
|
+
|
91
|
+
##
|
92
|
+
# Handles the response from the API.
|
93
|
+
#
|
94
|
+
# @param [Faraday::Response] response The response object.
|
95
|
+
# @return [Hash] The parsed response body.
|
96
|
+
# @raise [Error] if the response is not successful.
|
97
|
+
def handle_response(response)
|
98
|
+
raise Error, "Error: #{response.body}" unless response.success?
|
99
|
+
|
100
|
+
response.body
|
101
|
+
end
|
102
|
+
|
103
|
+
##
|
104
|
+
# Validates the format of a UUID.
|
105
|
+
#
|
106
|
+
# @param [String] uuid The UUID to validate.
|
107
|
+
# @raise [RuntimeError] if the UUID format is invalid.
|
108
|
+
def validate_uuid(uuid)
|
109
|
+
return if uuid.match?(/\A[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-4[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}\z/)
|
110
|
+
|
111
|
+
raise 'Invalid UUID format'
|
112
|
+
end
|
113
|
+
end
|
114
|
+
end
|
@@ -0,0 +1,34 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module CDEKApiClient
|
4
|
+
module Entities
|
5
|
+
module CurrencyMapper
|
6
|
+
CURRENCY_CODES = {
|
7
|
+
'RUB' => 1,
|
8
|
+
'KZT' => 2,
|
9
|
+
'USD' => 3,
|
10
|
+
'EUR' => 4,
|
11
|
+
'GBP' => 5,
|
12
|
+
'CNY' => 6,
|
13
|
+
'BYR' => 7,
|
14
|
+
'UAH' => 8,
|
15
|
+
'KGS' => 9,
|
16
|
+
'AMD' => 10,
|
17
|
+
'TRY' => 11,
|
18
|
+
'THB' => 12,
|
19
|
+
'KRW' => 13,
|
20
|
+
'AED' => 14,
|
21
|
+
'UZS' => 15,
|
22
|
+
'MNT' => 16,
|
23
|
+
'PLN' => 17,
|
24
|
+
'AZN' => 18,
|
25
|
+
'GEL' => 19,
|
26
|
+
'JPY' => 55
|
27
|
+
}.freeze
|
28
|
+
|
29
|
+
def self.to_code(currency)
|
30
|
+
CURRENCY_CODES[currency] || (raise ArgumentError, "Invalid currency code: #{currency}")
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
@@ -0,0 +1,44 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_relative 'validatable'
|
4
|
+
require_relative 'payment'
|
5
|
+
|
6
|
+
module CDEKApiClient
|
7
|
+
module Entities
|
8
|
+
class Item
|
9
|
+
include Validatable
|
10
|
+
|
11
|
+
attr_accessor :ware_key, :payment, :name, :cost, :amount, :weight, :url
|
12
|
+
|
13
|
+
validates :ware_key, type: :string, presence: true
|
14
|
+
validates :payment, type: :object, presence: true
|
15
|
+
validates :name, type: :string, presence: true
|
16
|
+
validates :cost, type: :integer, presence: true
|
17
|
+
validates :amount, type: :integer, presence: true
|
18
|
+
validates :weight, type: :integer, presence: true
|
19
|
+
|
20
|
+
def initialize(ware_key:, payment:, name:, cost:, amount:, weight:, url: nil)
|
21
|
+
@ware_key = ware_key
|
22
|
+
@payment = payment
|
23
|
+
@name = name
|
24
|
+
@cost = cost
|
25
|
+
@amount = amount
|
26
|
+
@weight = weight
|
27
|
+
@url = url
|
28
|
+
validate!
|
29
|
+
end
|
30
|
+
|
31
|
+
def to_json(*_args)
|
32
|
+
{
|
33
|
+
ware_key: @ware_key,
|
34
|
+
payment: @payment,
|
35
|
+
name: @name,
|
36
|
+
cost: @cost,
|
37
|
+
amount: @amount,
|
38
|
+
weight: @weight,
|
39
|
+
url: @url
|
40
|
+
}.to_json
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
@@ -0,0 +1,30 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module CDEKApiClient
|
4
|
+
module Entities
|
5
|
+
class Location
|
6
|
+
include Validatable
|
7
|
+
|
8
|
+
attr_accessor :code, :city, :address
|
9
|
+
|
10
|
+
validates :code, type: :integer, presence: true
|
11
|
+
validates :city, type: :string
|
12
|
+
validates :address, type: :string
|
13
|
+
|
14
|
+
def initialize(code:, city: nil, address: nil)
|
15
|
+
@code = code
|
16
|
+
@city = city
|
17
|
+
@address = address
|
18
|
+
validate!
|
19
|
+
end
|
20
|
+
|
21
|
+
def to_json(*_args)
|
22
|
+
{
|
23
|
+
code: @code,
|
24
|
+
city: @city,
|
25
|
+
address: @address
|
26
|
+
}.to_json
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
@@ -0,0 +1,61 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_relative 'validatable'
|
4
|
+
require_relative 'package'
|
5
|
+
require_relative 'recipient'
|
6
|
+
require_relative 'sender'
|
7
|
+
|
8
|
+
module CDEKApiClient
|
9
|
+
module Entities
|
10
|
+
class OrderData
|
11
|
+
include Validatable
|
12
|
+
|
13
|
+
attr_accessor :type, :number, :tariff_code, :comment, :shipment_point, :delivery_point,
|
14
|
+
:from_location, :to_location, :recipient, :sender, :services, :packages
|
15
|
+
|
16
|
+
validates :type, type: :integer, presence: true
|
17
|
+
validates :number, type: :string, presence: true
|
18
|
+
validates :tariff_code, type: :integer, presence: true
|
19
|
+
validates :from_location, type: :object, presence: true
|
20
|
+
validates :to_location, type: :object, presence: true
|
21
|
+
validates :recipient, type: :object, presence: true
|
22
|
+
validates :sender, type: :object, presence: true
|
23
|
+
validates :packages, type: :array, presence: true, items: [Package]
|
24
|
+
validates :comment, type: :string
|
25
|
+
|
26
|
+
def initialize(type:, number:, tariff_code:, from_location:, to_location:, recipient:, sender:, packages:,
|
27
|
+
comment: nil, shipment_point: nil, delivery_point: nil, services: [])
|
28
|
+
@type = type
|
29
|
+
@number = number
|
30
|
+
@tariff_code = tariff_code
|
31
|
+
@comment = comment
|
32
|
+
@shipment_point = shipment_point
|
33
|
+
@delivery_point = delivery_point
|
34
|
+
@from_location = from_location
|
35
|
+
@to_location = to_location
|
36
|
+
@recipient = recipient
|
37
|
+
@sender = sender
|
38
|
+
@services = services
|
39
|
+
@packages = packages
|
40
|
+
validate!
|
41
|
+
end
|
42
|
+
|
43
|
+
def to_json(*_args)
|
44
|
+
{
|
45
|
+
type: @type,
|
46
|
+
number: @number,
|
47
|
+
tariff_code: @tariff_code,
|
48
|
+
comment: @comment,
|
49
|
+
shipment_point: @shipment_point,
|
50
|
+
delivery_point: @delivery_point,
|
51
|
+
from_location: @from_location,
|
52
|
+
to_location: @to_location,
|
53
|
+
recipient: @recipient,
|
54
|
+
sender: @sender,
|
55
|
+
services: @services,
|
56
|
+
packages: @packages
|
57
|
+
}.to_json
|
58
|
+
end
|
59
|
+
end
|
60
|
+
end
|
61
|
+
end
|
@@ -0,0 +1,44 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_relative 'validatable'
|
4
|
+
require_relative 'item'
|
5
|
+
|
6
|
+
module CDEKApiClient
|
7
|
+
module Entities
|
8
|
+
class Package
|
9
|
+
include Validatable
|
10
|
+
|
11
|
+
attr_accessor :number, :comment, :height, :length, :weight, :width, :items
|
12
|
+
|
13
|
+
validates :number, type: :string, presence: true
|
14
|
+
validates :height, type: :integer, presence: true
|
15
|
+
validates :length, type: :integer, presence: true
|
16
|
+
validates :weight, type: :integer, presence: true
|
17
|
+
validates :width, type: :integer, presence: true
|
18
|
+
validates :items, type: :array, presence: true, items: [Item]
|
19
|
+
|
20
|
+
def initialize(number:, comment:, height:, length:, weight:, width:, items:)
|
21
|
+
@number = number
|
22
|
+
@comment = comment
|
23
|
+
@height = height
|
24
|
+
@length = length
|
25
|
+
@weight = weight
|
26
|
+
@width = width
|
27
|
+
@items = items
|
28
|
+
validate!
|
29
|
+
end
|
30
|
+
|
31
|
+
def to_json(*_args)
|
32
|
+
{
|
33
|
+
number: @number,
|
34
|
+
comment: @comment,
|
35
|
+
height: @height,
|
36
|
+
length: @length,
|
37
|
+
weight: @weight,
|
38
|
+
width: @width,
|
39
|
+
items: @items
|
40
|
+
}.to_json
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
@@ -0,0 +1,30 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_relative 'validatable'
|
4
|
+
require_relative 'currency_mapper'
|
5
|
+
|
6
|
+
module CDEKApiClient
|
7
|
+
module Entities
|
8
|
+
class Payment
|
9
|
+
include Validatable
|
10
|
+
|
11
|
+
attr_accessor :value, :currency
|
12
|
+
|
13
|
+
validates :value, type: :integer, presence: true, positive: true
|
14
|
+
validates :currency, type: :integer, presence: true
|
15
|
+
|
16
|
+
def initialize(value:, currency:)
|
17
|
+
@value = value
|
18
|
+
@currency = CDEKApiClient::Entities::CurrencyMapper.to_code(currency)
|
19
|
+
validate!
|
20
|
+
end
|
21
|
+
|
22
|
+
def to_json(*_args)
|
23
|
+
{
|
24
|
+
value: @value,
|
25
|
+
currency: @currency
|
26
|
+
}.to_json
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
@@ -0,0 +1,33 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_relative 'validatable'
|
4
|
+
|
5
|
+
module CDEKApiClient
|
6
|
+
module Entities
|
7
|
+
class Recipient
|
8
|
+
include Validatable
|
9
|
+
|
10
|
+
attr_accessor :name, :phones, :email
|
11
|
+
|
12
|
+
validates :name, type: :string, presence: true
|
13
|
+
validates :phones, type: :array, items: [{ type: :hash, schema: { number: { type: :string, presence: true } } }],
|
14
|
+
presence: true
|
15
|
+
validates :email, type: :string, presence: true
|
16
|
+
|
17
|
+
def initialize(name:, phones:, email:)
|
18
|
+
@name = name
|
19
|
+
@phones = phones
|
20
|
+
@email = email
|
21
|
+
validate!
|
22
|
+
end
|
23
|
+
|
24
|
+
def to_json(*_args)
|
25
|
+
{
|
26
|
+
name: @name,
|
27
|
+
phones: @phones,
|
28
|
+
email: @email
|
29
|
+
}.to_json
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
@@ -0,0 +1,33 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_relative 'validatable'
|
4
|
+
|
5
|
+
module CDEKApiClient
|
6
|
+
module Entities
|
7
|
+
class Sender
|
8
|
+
include Validatable
|
9
|
+
|
10
|
+
attr_accessor :name, :phones, :email
|
11
|
+
|
12
|
+
validates :name, type: :string, presence: true
|
13
|
+
validates :phones, type: :array, items: [{ type: :hash, schema: { number: { type: :string, presence: true } } }],
|
14
|
+
presence: true
|
15
|
+
validates :email, type: :string, presence: true
|
16
|
+
|
17
|
+
def initialize(name:, phones:, email:)
|
18
|
+
@name = name
|
19
|
+
@phones = phones
|
20
|
+
@email = email
|
21
|
+
validate!
|
22
|
+
end
|
23
|
+
|
24
|
+
def to_json(*_args)
|
25
|
+
{
|
26
|
+
name: @name,
|
27
|
+
phones: @phones,
|
28
|
+
email: @email
|
29
|
+
}.to_json
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
@@ -0,0 +1,33 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_relative 'validatable'
|
4
|
+
require_relative 'payment'
|
5
|
+
|
6
|
+
module CDEKApiClient
|
7
|
+
module Entities
|
8
|
+
class Service
|
9
|
+
include Validatable
|
10
|
+
|
11
|
+
attr_accessor :code, :price, :name
|
12
|
+
|
13
|
+
validates :code, type: :string, presence: true
|
14
|
+
validates :price, type: :integer, presence: true
|
15
|
+
validates :name, type: :string, presence: true
|
16
|
+
|
17
|
+
def initialize(code:, price:, name:)
|
18
|
+
@code = code
|
19
|
+
@price = price
|
20
|
+
@name = name
|
21
|
+
validate!
|
22
|
+
end
|
23
|
+
|
24
|
+
def to_json(*_args)
|
25
|
+
{
|
26
|
+
code: @code,
|
27
|
+
price: @price,
|
28
|
+
name: @name
|
29
|
+
}.to_json
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
@@ -0,0 +1,42 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_relative 'validatable'
|
4
|
+
require_relative 'currency_mapper'
|
5
|
+
|
6
|
+
module CDEKApiClient
|
7
|
+
module Entities
|
8
|
+
class TariffData
|
9
|
+
include Validatable
|
10
|
+
|
11
|
+
attr_accessor :type, :currency, :from_location, :to_location, :packages, :tariff_code
|
12
|
+
|
13
|
+
validates :type, type: :integer, presence: true
|
14
|
+
validates :currency, type: :integer, presence: true
|
15
|
+
validates :tariff_code, type: :integer, presence: true
|
16
|
+
validates :from_location, type: :object, presence: true
|
17
|
+
validates :to_location, type: :object, presence: true
|
18
|
+
validates :packages, type: :array, presence: true, items: [Package]
|
19
|
+
|
20
|
+
def initialize(type:, currency:, from_location:, to_location:, packages:, tariff_code:)
|
21
|
+
@type = type
|
22
|
+
@currency = CurrencyMapper.to_code(currency)
|
23
|
+
@from_location = from_location
|
24
|
+
@to_location = to_location
|
25
|
+
@packages = packages
|
26
|
+
@tariff_code = tariff_code
|
27
|
+
validate!
|
28
|
+
end
|
29
|
+
|
30
|
+
def to_json(*_args)
|
31
|
+
{
|
32
|
+
type: @type,
|
33
|
+
currency: @currency,
|
34
|
+
from_location: @from_location,
|
35
|
+
to_location: @to_location,
|
36
|
+
packages: @packages,
|
37
|
+
tariff_code: @tariff_code
|
38
|
+
}.to_json
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
@@ -0,0 +1,90 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module CDEKApiClient
|
4
|
+
module Entities
|
5
|
+
module Validatable
|
6
|
+
def self.included(base)
|
7
|
+
base.extend ClassMethods
|
8
|
+
end
|
9
|
+
|
10
|
+
module ClassMethods
|
11
|
+
def validates(attribute, options)
|
12
|
+
@validations ||= {}
|
13
|
+
@validations[attribute] = options
|
14
|
+
end
|
15
|
+
|
16
|
+
def validations
|
17
|
+
@validations
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
def validate!
|
22
|
+
self.class.validations.each do |attribute, rule|
|
23
|
+
value = send(attribute)
|
24
|
+
validate_presence(attribute, value, rule)
|
25
|
+
validate_type(attribute, value, rule)
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
private
|
30
|
+
|
31
|
+
def validate_presence(attribute, value, rule)
|
32
|
+
raise "#{attribute} is required" if rule[:presence] && value.nil?
|
33
|
+
end
|
34
|
+
|
35
|
+
def validate_type(attribute, value, rule)
|
36
|
+
case rule[:type]
|
37
|
+
when :string
|
38
|
+
raise "#{attribute} must be a String" unless value.is_a?(String)
|
39
|
+
when :integer
|
40
|
+
raise "#{attribute} must be an Integer" unless value.is_a?(Integer)
|
41
|
+
|
42
|
+
validate_positive(attribute, value, rule)
|
43
|
+
when :array
|
44
|
+
raise "#{attribute} must be an Array" unless value.is_a?(Array)
|
45
|
+
|
46
|
+
validate_array_items(attribute, value, rule)
|
47
|
+
when :object
|
48
|
+
validate_object(attribute, value, rule)
|
49
|
+
when :hash
|
50
|
+
validate_hash(attribute, value, rule)
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
def validate_positive(attribute, value, rule)
|
55
|
+
raise "#{attribute} must be a positive number" if rule[:positive] && value <= 0
|
56
|
+
end
|
57
|
+
|
58
|
+
def validate_array_items(attribute, array, rule)
|
59
|
+
array.each do |item|
|
60
|
+
if item.is_a?(Hash)
|
61
|
+
validate_hash(attribute, item, rule[:items].first)
|
62
|
+
elsif item.is_a?(self.class || Class)
|
63
|
+
validate_object(attribute, item, rule[:items].first)
|
64
|
+
else
|
65
|
+
rule[:items].each do |key, val_rule|
|
66
|
+
validate_presence(key, item, { type: val_rule })
|
67
|
+
validate_type(key, item, { type: val_rule })
|
68
|
+
end
|
69
|
+
end
|
70
|
+
end
|
71
|
+
end
|
72
|
+
|
73
|
+
def validate_object(_attribute, object, _rule)
|
74
|
+
object.class.validations.each do |attr, validation_rule|
|
75
|
+
value = object.send(attr)
|
76
|
+
validate_presence(attr, value, validation_rule)
|
77
|
+
validate_type(attr, value, validation_rule)
|
78
|
+
end
|
79
|
+
end
|
80
|
+
|
81
|
+
def validate_hash(_attribute, hash, rule)
|
82
|
+
rule[:schema].each do |attr, validation_rule|
|
83
|
+
value = hash[attr]
|
84
|
+
validate_presence(attr, value, validation_rule)
|
85
|
+
validate_type(attr, value, validation_rule)
|
86
|
+
end
|
87
|
+
end
|
88
|
+
end
|
89
|
+
end
|
90
|
+
end
|
@@ -0,0 +1,32 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_relative 'validatable'
|
4
|
+
|
5
|
+
module CDEKApiClient
|
6
|
+
module Entities
|
7
|
+
class Webhook
|
8
|
+
include Validatable
|
9
|
+
|
10
|
+
attr_accessor :url, :type, :event_types
|
11
|
+
|
12
|
+
validates :url, type: :string, presence: true
|
13
|
+
validates :type, type: :string, presence: true
|
14
|
+
validates :event_types, type: :array, presence: true, items: [{ type: :string, presence: true }]
|
15
|
+
|
16
|
+
def initialize(url:, type:, event_types:)
|
17
|
+
@url = url
|
18
|
+
@type = type
|
19
|
+
@event_types = event_types
|
20
|
+
validate!
|
21
|
+
end
|
22
|
+
|
23
|
+
def to_json(*_args)
|
24
|
+
{
|
25
|
+
url: @url,
|
26
|
+
type: @type,
|
27
|
+
event_types: @event_types
|
28
|
+
}.to_json
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
@@ -0,0 +1,32 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module CDEKApiClient
|
4
|
+
class Location
|
5
|
+
CITIES_URL = 'location/cities'
|
6
|
+
REGIONS_URL = 'location/regions'
|
7
|
+
|
8
|
+
def initialize(client)
|
9
|
+
@client = client
|
10
|
+
end
|
11
|
+
|
12
|
+
def cities
|
13
|
+
response = @client.auth_connection.get(CITIES_URL) do |req|
|
14
|
+
req.headers['Content-Type'] = 'application/json'
|
15
|
+
end
|
16
|
+
handle_response(response)
|
17
|
+
end
|
18
|
+
|
19
|
+
def regions
|
20
|
+
response = @client.auth_connection.get(REGIONS_URL) do |req|
|
21
|
+
req.headers['Content-Type'] = 'application/json'
|
22
|
+
end
|
23
|
+
handle_response(response)
|
24
|
+
end
|
25
|
+
|
26
|
+
private
|
27
|
+
|
28
|
+
def handle_response(response)
|
29
|
+
@client.send(:handle_response, response)
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
@@ -0,0 +1,43 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'cdek_api_client/entities/order_data'
|
4
|
+
|
5
|
+
module CDEKApiClient
|
6
|
+
class Order
|
7
|
+
BASE_URL = ENV.fetch('CDEK_API_URL', 'https://api.edu.cdek.ru/v2')
|
8
|
+
ORDERS_URL = "#{BASE_URL}/orders".freeze
|
9
|
+
|
10
|
+
def initialize(client)
|
11
|
+
@client = client
|
12
|
+
end
|
13
|
+
|
14
|
+
def create(order_data)
|
15
|
+
validate_order_data(order_data)
|
16
|
+
|
17
|
+
response = @client.auth_connection.post(ORDERS_URL) do |req|
|
18
|
+
req.headers['Content-Type'] = 'application/json'
|
19
|
+
req.body = order_data.to_json
|
20
|
+
end
|
21
|
+
handle_response(response)
|
22
|
+
end
|
23
|
+
|
24
|
+
def track(order_uuid)
|
25
|
+
@client.validate_uuid(order_uuid)
|
26
|
+
|
27
|
+
response = @client.auth_connection.get("#{ORDERS_URL}/#{order_uuid}") do |req|
|
28
|
+
req.headers['Content-Type'] = 'application/json'
|
29
|
+
end
|
30
|
+
handle_response(response)
|
31
|
+
end
|
32
|
+
|
33
|
+
private
|
34
|
+
|
35
|
+
def validate_order_data(order_data)
|
36
|
+
raise 'order_data must be a Hash' unless order_data.is_a?(Entities::OrderData)
|
37
|
+
end
|
38
|
+
|
39
|
+
def handle_response(response)
|
40
|
+
@client.send(:handle_response, response)
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
@@ -0,0 +1,37 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module CDEKApiClient
|
4
|
+
module Entities
|
5
|
+
class Recipient
|
6
|
+
attr_accessor :name, :phones, :email
|
7
|
+
|
8
|
+
VALIDATION_RULES = {
|
9
|
+
name: { type: :string, presence: true },
|
10
|
+
phones: { type: :array, presence: true, items: [{ type: :string, presence: true }] },
|
11
|
+
email: { type: :string, presence: true }
|
12
|
+
}.freeze
|
13
|
+
|
14
|
+
def initialize(name:, phones:, email:)
|
15
|
+
@name = name
|
16
|
+
@phones = phones
|
17
|
+
@email = email
|
18
|
+
|
19
|
+
Validator.validate(
|
20
|
+
{
|
21
|
+
name: @name,
|
22
|
+
phones: @phones,
|
23
|
+
email: @email
|
24
|
+
}, VALIDATION_RULES
|
25
|
+
)
|
26
|
+
end
|
27
|
+
|
28
|
+
def to_json(*_args)
|
29
|
+
{
|
30
|
+
name: @name,
|
31
|
+
phones: @phones,
|
32
|
+
email: @email
|
33
|
+
}.to_json
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
@@ -0,0 +1,32 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module CDEKApiClient
|
4
|
+
class Tariff
|
5
|
+
BASE_URL = ENV.fetch('CDEK_API_URL', 'https://api.edu.cdek.ru/v2')
|
6
|
+
TARIFF_URL = "#{BASE_URL}/calculator/tariff".freeze
|
7
|
+
|
8
|
+
def initialize(client)
|
9
|
+
@client = client
|
10
|
+
end
|
11
|
+
|
12
|
+
def calculate(tariff_data)
|
13
|
+
validate_tariff_data(tariff_data)
|
14
|
+
|
15
|
+
response = @client.auth_connection.post(TARIFF_URL) do |req|
|
16
|
+
req.headers['Content-Type'] = 'application/json'
|
17
|
+
req.body = tariff_data.to_json
|
18
|
+
end
|
19
|
+
handle_response(response)
|
20
|
+
end
|
21
|
+
|
22
|
+
private
|
23
|
+
|
24
|
+
def validate_tariff_data(tariff_data)
|
25
|
+
raise 'tariff_data must be a Hash' unless tariff_data.is_a?(Entities::TariffData)
|
26
|
+
end
|
27
|
+
|
28
|
+
def handle_response(response)
|
29
|
+
@client.send(:handle_response, response)
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
@@ -0,0 +1,29 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module CDEKApiClient
|
4
|
+
class TrackOrder
|
5
|
+
BASE_URL = ENV.fetch('CDEK_API_URL', 'https://api.edu.cdek.ru/v2')
|
6
|
+
TRACK_ORDER_URL = "#{BASE_URL}/orders/%<uuid>s".freeze
|
7
|
+
|
8
|
+
def initialize(client)
|
9
|
+
@client = client
|
10
|
+
end
|
11
|
+
|
12
|
+
def get(order_uuid)
|
13
|
+
validate_uuid(order_uuid)
|
14
|
+
|
15
|
+
response = @client.auth_connection.get(format(TRACK_ORDER_URL, uuid: order_uuid))
|
16
|
+
handle_response(response)
|
17
|
+
end
|
18
|
+
|
19
|
+
private
|
20
|
+
|
21
|
+
def validate_uuid(uuid)
|
22
|
+
@client.send(:validate_uuid, uuid)
|
23
|
+
end
|
24
|
+
|
25
|
+
def handle_response(response)
|
26
|
+
@client.send(:handle_response, response)
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
@@ -0,0 +1,54 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module CDEKApiClient
|
4
|
+
class Webhook
|
5
|
+
BASE_URL = ENV.fetch('CDEK_API_URL', 'https://api.edu.cdek.ru/v2')
|
6
|
+
WEBHOOKS_URL = "#{BASE_URL}/webhooks".freeze
|
7
|
+
|
8
|
+
def initialize(client)
|
9
|
+
@client = client
|
10
|
+
end
|
11
|
+
|
12
|
+
def register(webhook_data)
|
13
|
+
validate_webhook_data(webhook_data)
|
14
|
+
|
15
|
+
response = @client.auth_connection.post(WEBHOOKS_URL) do |req|
|
16
|
+
req.headers['Content-Type'] = 'application/json'
|
17
|
+
req.body = webhook_data.to_json
|
18
|
+
end
|
19
|
+
handle_response(response)
|
20
|
+
end
|
21
|
+
|
22
|
+
def list
|
23
|
+
response = @client.auth_connection.get(WEBHOOKS_URL) do |req|
|
24
|
+
req.headers['Content-Type'] = 'application/json'
|
25
|
+
end
|
26
|
+
handle_response(response)
|
27
|
+
end
|
28
|
+
|
29
|
+
def delete(webhook_id)
|
30
|
+
validate_uuid(webhook_id)
|
31
|
+
|
32
|
+
response = @client.auth_connection.delete("#{WEBHOOKS_URL}/#{webhook_id}") do |req|
|
33
|
+
req.headers['Content-Type'] = 'application/json'
|
34
|
+
end
|
35
|
+
handle_response(response)
|
36
|
+
end
|
37
|
+
|
38
|
+
private
|
39
|
+
|
40
|
+
def validate_webhook_data(webhook_data)
|
41
|
+
raise 'webhook_data must be a Webhook' unless webhook_data.is_a?(CDEKApiClient::Entities::Webhook)
|
42
|
+
end
|
43
|
+
|
44
|
+
def validate_uuid(uuid)
|
45
|
+
return if uuid.match?(/\A[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-4[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}\z/)
|
46
|
+
|
47
|
+
raise 'Invalid UUID format'
|
48
|
+
end
|
49
|
+
|
50
|
+
def handle_response(response)
|
51
|
+
@client.send(:handle_response, response)
|
52
|
+
end
|
53
|
+
end
|
54
|
+
end
|
@@ -0,0 +1,37 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_relative 'cdek_api_client/client'
|
4
|
+
require_relative 'cdek_api_client/order'
|
5
|
+
require_relative 'cdek_api_client/track_order'
|
6
|
+
require_relative 'cdek_api_client/tariff'
|
7
|
+
require_relative 'cdek_api_client/version'
|
8
|
+
require_relative 'cdek_api_client/location'
|
9
|
+
require_relative 'cdek_api_client/webhook'
|
10
|
+
require_relative 'cdek_api_client/entities/order_data'
|
11
|
+
require_relative 'cdek_api_client/entities/location'
|
12
|
+
require_relative 'cdek_api_client/entities/package'
|
13
|
+
require_relative 'cdek_api_client/entities/recipient'
|
14
|
+
require_relative 'cdek_api_client/entities/item'
|
15
|
+
require_relative 'cdek_api_client/entities/validatable'
|
16
|
+
require_relative 'cdek_api_client/entities/sender'
|
17
|
+
require_relative 'cdek_api_client/entities/currency_mapper'
|
18
|
+
require_relative 'cdek_api_client/entities/tariff_data'
|
19
|
+
require_relative 'cdek_api_client/entities/payment'
|
20
|
+
require_relative 'cdek_api_client/entities/service'
|
21
|
+
require_relative 'cdek_api_client/entities/webhook'
|
22
|
+
|
23
|
+
module CDEKApiClient
|
24
|
+
class Error < StandardError; end
|
25
|
+
|
26
|
+
class << self
|
27
|
+
def configure
|
28
|
+
yield self
|
29
|
+
end
|
30
|
+
|
31
|
+
attr_accessor :client_id, :client_secret
|
32
|
+
end
|
33
|
+
|
34
|
+
def self.client
|
35
|
+
@client ||= CDEKApiClient::Client.new(client_id, client_secret)
|
36
|
+
end
|
37
|
+
end
|
metadata
ADDED
@@ -0,0 +1,112 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: cdek_api_client
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.1.0
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Damir Mukimov
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2024-07-20 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: base64
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - "~>"
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: 0.2.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.2.0
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: faraday
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - "~>"
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: 1.10.3
|
34
|
+
type: :runtime
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - "~>"
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: 1.10.3
|
41
|
+
- !ruby/object:Gem::Dependency
|
42
|
+
name: faraday_middleware
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - "~>"
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: 1.2.0
|
48
|
+
type: :runtime
|
49
|
+
prerelease: false
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - "~>"
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: 1.2.0
|
55
|
+
description: This gem provides a Ruby client for interacting with the CDEK API, including
|
56
|
+
order creation, tracking, and tariff calculation.
|
57
|
+
email:
|
58
|
+
- mukimov.d@gmail.com
|
59
|
+
executables: []
|
60
|
+
extensions: []
|
61
|
+
extra_rdoc_files: []
|
62
|
+
files:
|
63
|
+
- README.md
|
64
|
+
- lib/cdek_api_client.rb
|
65
|
+
- lib/cdek_api_client/client.rb
|
66
|
+
- lib/cdek_api_client/entities/currency_mapper.rb
|
67
|
+
- lib/cdek_api_client/entities/item.rb
|
68
|
+
- lib/cdek_api_client/entities/location.rb
|
69
|
+
- lib/cdek_api_client/entities/order_data.rb
|
70
|
+
- lib/cdek_api_client/entities/package.rb
|
71
|
+
- lib/cdek_api_client/entities/payment.rb
|
72
|
+
- lib/cdek_api_client/entities/recipient.rb
|
73
|
+
- lib/cdek_api_client/entities/sender.rb
|
74
|
+
- lib/cdek_api_client/entities/service.rb
|
75
|
+
- lib/cdek_api_client/entities/tariff_data.rb
|
76
|
+
- lib/cdek_api_client/entities/validatable.rb
|
77
|
+
- lib/cdek_api_client/entities/webhook.rb
|
78
|
+
- lib/cdek_api_client/location.rb
|
79
|
+
- lib/cdek_api_client/order.rb
|
80
|
+
- lib/cdek_api_client/recipient.rb
|
81
|
+
- lib/cdek_api_client/tariff.rb
|
82
|
+
- lib/cdek_api_client/track_order.rb
|
83
|
+
- lib/cdek_api_client/version.rb
|
84
|
+
- lib/cdek_api_client/webhook.rb
|
85
|
+
homepage: http://glowing-pixels.com/cdek_api_client
|
86
|
+
licenses:
|
87
|
+
- MIT
|
88
|
+
metadata:
|
89
|
+
github_repo: git@github.com/SamyRai/cdek_api_client.git
|
90
|
+
homepage_uri: http://glowing-pixels.com/cdek_api_client
|
91
|
+
source_code_uri: http://github.com/SamyRai/cdek_api_client
|
92
|
+
changelog_uri: http://www.glowing-pixels.com/cdek_api_client/CHANGELOG.md
|
93
|
+
post_install_message:
|
94
|
+
rdoc_options: []
|
95
|
+
require_paths:
|
96
|
+
- lib
|
97
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
98
|
+
requirements:
|
99
|
+
- - ">="
|
100
|
+
- !ruby/object:Gem::Version
|
101
|
+
version: '3.0'
|
102
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
103
|
+
requirements:
|
104
|
+
- - ">="
|
105
|
+
- !ruby/object:Gem::Version
|
106
|
+
version: '0'
|
107
|
+
requirements: []
|
108
|
+
rubygems_version: 3.5.11
|
109
|
+
signing_key:
|
110
|
+
specification_version: 4
|
111
|
+
summary: A Ruby client for the CDEK API
|
112
|
+
test_files: []
|