after_ship 0.0.2 → 0.0.4
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 +4 -4
- data/.travis.yml +1 -1
- data/README.md +69 -32
- data/after_ship.gemspec +4 -4
- data/lib/after_ship/checkpoint.rb +35 -28
- data/lib/after_ship/core/attributes.rb +14 -0
- data/lib/after_ship/core/date_utils.rb +76 -0
- data/lib/after_ship/core/error.rb +29 -0
- data/lib/after_ship/core/error_handler.rb +67 -0
- data/lib/after_ship/core/request.rb +131 -0
- data/lib/after_ship/core/version.rb +4 -0
- data/lib/after_ship/courier.rb +45 -0
- data/lib/after_ship/tracking.rb +78 -6
- data/lib/after_ship.rb +158 -214
- data/spec/integration/after_ship_spec.rb +40 -0
- data/spec/request_stubs.rb +30 -97
- data/spec/requests/couriers.json +50 -0
- data/spec/requests/tracking/created.json +53 -0
- data/spec/requests/tracking/{delivered_ok.json → delivered.json} +79 -65
- data/spec/requests/trackings.json +654 -0
- data/spec/units/after_ship_spec.rb +104 -0
- data/spec/units/checkpoint_spec.rb +135 -0
- data/spec/units/courier_spec.rb +41 -0
- data/spec/{lib → units}/date_utils_spec.rb +17 -9
- data/spec/units/error_handler_spec.rb +168 -0
- data/spec/units/request_spec.rb +190 -0
- data/spec/units/tracking_spec.rb +276 -0
- metadata +39 -25
- data/lib/after_ship/version.rb +0 -3
- data/lib/attributes.rb +0 -12
- data/lib/date_utils.rb +0 -61
- data/spec/lib/after_ship_spec.rb +0 -137
- data/spec/lib/checkpoint_spec.rb +0 -139
- data/spec/lib/tracking_spec.rb +0 -89
- data/spec/requests/tracking/delivered_wild.json +0 -653
- data/spec/requests/tracking/in_transit.json +0 -443
@@ -0,0 +1,45 @@
|
|
1
|
+
class AfterShip
|
2
|
+
# Wrapper object for AfterShip courier:
|
3
|
+
# https://www.aftership.com/docs/api/4/couriers/get-couriers
|
4
|
+
class Courier
|
5
|
+
include Attributes
|
6
|
+
|
7
|
+
# Unique code of courier.
|
8
|
+
#
|
9
|
+
# @return [String]
|
10
|
+
attr_accessor :slug
|
11
|
+
|
12
|
+
# Name of courier.
|
13
|
+
#
|
14
|
+
# @return [String]
|
15
|
+
attr_accessor :name
|
16
|
+
|
17
|
+
# Contact phone number of courier.
|
18
|
+
#
|
19
|
+
# @return [String]
|
20
|
+
attr_accessor :phone
|
21
|
+
|
22
|
+
# Other name of courier.
|
23
|
+
#
|
24
|
+
# @return [String]
|
25
|
+
attr_accessor :other_name
|
26
|
+
|
27
|
+
# Website link of courier.
|
28
|
+
#
|
29
|
+
# @return [String]
|
30
|
+
attr_accessor :web_url
|
31
|
+
|
32
|
+
# The extra fields need for tracking, such as `tracking_account_number`,
|
33
|
+
# `tracking_postal_code`, `tracking_ship_date`.
|
34
|
+
#
|
35
|
+
# @return [Array]
|
36
|
+
attr_accessor :required_fields
|
37
|
+
|
38
|
+
# Better interface for a courier.
|
39
|
+
#
|
40
|
+
# @param data [Hash] tracking hash
|
41
|
+
def initialize(data)
|
42
|
+
load_attributes(data)
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
data/lib/after_ship/tracking.rb
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
class AfterShip
|
2
2
|
# Wrapper object for AfterShip tracking:
|
3
|
-
# https://www.aftership.com/docs/api/
|
3
|
+
# https://www.aftership.com/docs/api/4/trackings/get-trackings-slug-tracking_number
|
4
4
|
class Tracking
|
5
5
|
include Attributes
|
6
6
|
|
@@ -14,27 +14,59 @@ class AfterShip
|
|
14
14
|
# @return [DateTime]
|
15
15
|
attr_reader :updated_at
|
16
16
|
|
17
|
+
# A unique identifier generated by AfterShip for the tracking.
|
18
|
+
#
|
19
|
+
# @return [String]
|
20
|
+
attr_accessor :id
|
21
|
+
|
17
22
|
# Tracking number, e.g. +1ZA2207X6794165804+.
|
18
23
|
#
|
19
24
|
# @return [String]
|
20
25
|
attr_accessor :tracking_number
|
21
26
|
|
27
|
+
# The postal code of receiver's address. Required by some couriers, such
|
28
|
+
# as +deutsch-post+.
|
29
|
+
#
|
30
|
+
# @return [String]
|
31
|
+
attr_accessor :tracking_postal_code
|
32
|
+
|
33
|
+
# Shipping date in +YYYYMMDD+ format. Required by some couriers, such as
|
34
|
+
# +deutsch-post+.
|
35
|
+
#
|
36
|
+
# @return [String]
|
37
|
+
attr_reader :tracking_ship_date
|
38
|
+
|
39
|
+
# Account number of the shipper for a specific courier. Required by some
|
40
|
+
# couriers, such as +dynamic-logistics+.
|
41
|
+
#
|
42
|
+
# @return [String]
|
43
|
+
attr_accessor :tracking_account_number
|
44
|
+
|
22
45
|
# Unique code of courier.
|
23
46
|
#
|
24
47
|
# @return [String]
|
25
48
|
attr_reader :slug
|
26
49
|
|
27
|
-
# Courier name
|
50
|
+
# Courier name.
|
51
|
+
#
|
52
|
+
# Custom method!
|
28
53
|
#
|
29
54
|
# @return [String]
|
30
55
|
attr_accessor :courier
|
31
56
|
|
32
57
|
# Whether or not AfterShip will continue tracking the shipments. Value is
|
33
|
-
# +false+ when status is +Delivered+ or
|
58
|
+
# +false+ when tag (status) is +Delivered+, +Expired+, or further updates
|
59
|
+
# for 30 days since last update.
|
34
60
|
#
|
35
|
-
# @return [
|
61
|
+
# @return [Bool]
|
36
62
|
attr_accessor :active
|
37
63
|
|
64
|
+
# Google cloud message registration IDs to receive the push notifications.
|
65
|
+
# Accept either array or Comma comma separated as input.
|
66
|
+
#
|
67
|
+
# @return [Array, String]
|
68
|
+
attr_accessor :android
|
69
|
+
|
38
70
|
# Custom fields of the tracking.
|
39
71
|
#
|
40
72
|
# @return [Hash]
|
@@ -45,6 +77,19 @@ class AfterShip
|
|
45
77
|
# @return [String]
|
46
78
|
attr_accessor :customer_name
|
47
79
|
|
80
|
+
# Total delivery time in days.
|
81
|
+
#
|
82
|
+
# * Difference of 1st checkpoint time and delivered time for delivered
|
83
|
+
# shipments.
|
84
|
+
# * Difference of 1st checkpoint time and current time for non-delivered
|
85
|
+
# shipments.
|
86
|
+
#
|
87
|
+
# Value as +0+ for pending shipments or delivered shipment with only one
|
88
|
+
# checkpoint.
|
89
|
+
#
|
90
|
+
# @return [Fixnum]
|
91
|
+
attr_accessor :delivery_time
|
92
|
+
|
48
93
|
# Destination country of the tracking. ISO Alpha-3 (three letters). If you
|
49
94
|
# use postal service to send international shipments, AfterShip will
|
50
95
|
# automatically get tracking results from destination postal service based
|
@@ -69,6 +114,12 @@ class AfterShip
|
|
69
114
|
# @return [DateTime]
|
70
115
|
attr_reader :expected_delivery
|
71
116
|
|
117
|
+
# Apple iOS device IDs to receive the push notificaitons.
|
118
|
+
# Accept either array or Comma comma separated as input.
|
119
|
+
#
|
120
|
+
# @return [Array, String]
|
121
|
+
attr_accessor :ios
|
122
|
+
|
72
123
|
# Text field for order ID.
|
73
124
|
#
|
74
125
|
# @return [String]
|
@@ -84,8 +135,9 @@ class AfterShip
|
|
84
135
|
# @return [String]
|
85
136
|
attr_accessor :origin_country_iso3
|
86
137
|
|
87
|
-
#
|
88
|
-
# https://yourusername.aftership.com/unique_token
|
138
|
+
# The token to generate the direct tracking link:
|
139
|
+
# https://yourusername.aftership.com/unique_token or
|
140
|
+
# https://www.aftership.com/unique_token.
|
89
141
|
#
|
90
142
|
# @return [String]
|
91
143
|
attr_accessor :unique_token
|
@@ -100,6 +152,16 @@ class AfterShip
|
|
100
152
|
# @return [String]
|
101
153
|
attr_accessor :shipment_type
|
102
154
|
|
155
|
+
# Shipment weight provied by carrier (if any).
|
156
|
+
#
|
157
|
+
# @return [Fixnum]
|
158
|
+
attr_accessor :shipment_weight
|
159
|
+
|
160
|
+
# Weight unit provied by carrier, either in +kg+ or +lb+ (if any).
|
161
|
+
#
|
162
|
+
# @return [String]
|
163
|
+
attr_accessor :shipment_weight_unit
|
164
|
+
|
103
165
|
# Signed by information for delivered shipment (if any).
|
104
166
|
#
|
105
167
|
# @return [String]
|
@@ -129,6 +191,8 @@ class AfterShip
|
|
129
191
|
|
130
192
|
# Same as tag, except human-friendly:
|
131
193
|
#
|
194
|
+
# Custom method!
|
195
|
+
#
|
132
196
|
# * +Pending+ => +Pending+
|
133
197
|
# * +InfoReceived+ => +Info Received+
|
134
198
|
# * +InTransit+ => +In Transit+
|
@@ -178,6 +242,14 @@ class AfterShip
|
|
178
242
|
@updated_at = DateTime.parse(value)
|
179
243
|
end
|
180
244
|
|
245
|
+
# Shipping date in +YYYYMMDD+ format. Required by some couriers, such as
|
246
|
+
# +deutsch-post+.
|
247
|
+
#
|
248
|
+
# @return [DateTime]
|
249
|
+
def tracking_ship_date=(value)
|
250
|
+
@tracking_ship_date = DateUtils.parse(value)
|
251
|
+
end
|
252
|
+
|
181
253
|
# Unique code of courier.
|
182
254
|
#
|
183
255
|
# @return [String]
|
data/lib/after_ship.rb
CHANGED
@@ -1,118 +1,48 @@
|
|
1
|
+
# Gems.
|
1
2
|
require 'typhoeus'
|
2
3
|
require 'multi_json'
|
3
4
|
|
4
|
-
|
5
|
-
require '
|
6
|
-
require 'after_ship/
|
5
|
+
# Core classes.
|
6
|
+
require 'after_ship/core/version'
|
7
|
+
require 'after_ship/core/attributes'
|
8
|
+
require 'after_ship/core/date_utils'
|
9
|
+
require 'after_ship/core/request'
|
10
|
+
require 'after_ship/core/error'
|
11
|
+
require 'after_ship/core/error_handler'
|
12
|
+
|
13
|
+
# AfterShip classes.
|
7
14
|
require 'after_ship/tracking'
|
8
15
|
require 'after_ship/checkpoint'
|
16
|
+
require 'after_ship/courier'
|
9
17
|
|
10
|
-
#
|
18
|
+
# Quick rundown, check individual methods for more info:
|
11
19
|
#
|
12
20
|
# client = AfterShip.new(api_key: 'your-aftership-api-key')
|
13
|
-
#
|
14
|
-
# Get a list of trackings
|
15
|
-
# https://www.aftership.com/docs/api/3.0/tracking/get-trackings
|
16
|
-
#
|
17
21
|
# client.trackings
|
18
|
-
#
|
19
|
-
# # Will return list of Tracking objects:
|
20
|
-
#
|
21
|
-
# [
|
22
|
-
# #<AfterShip::Tracking ...>,
|
23
|
-
# #<AfterShip::Tracking ...>,
|
24
|
-
# ...
|
25
|
-
# ]
|
26
|
-
#
|
27
|
-
# Get a tracking
|
28
|
-
# https://www.aftership.com/docs/api/3.0/tracking/get-trackings-slug-tracking_number
|
29
|
-
#
|
30
22
|
# client.tracking('tracking-number', 'ups')
|
31
|
-
#
|
32
|
-
# # Will return Tracking object or raise AfterShip::ResourceNotFoundError
|
33
|
-
# # if not exists:
|
34
|
-
#
|
35
|
-
# #<AfterShip::Tracking:0x007fe555bd9560
|
36
|
-
# @active=false,
|
37
|
-
# @courier="UPS",
|
38
|
-
# @created_at=#<DateTime: 2014-05-08T15:25:01+00:00 ...>,
|
39
|
-
# @updated_at=#<DateTime: 2014-07-18T09:00:47+00:00 ...>>
|
40
|
-
# @custom_fields={},
|
41
|
-
# @customer_name=nil,
|
42
|
-
# @destination_country_iso3="USA",
|
43
|
-
# @emails=[],
|
44
|
-
# @expected_delivery=nil,
|
45
|
-
# @order_id="PL-12480166",
|
46
|
-
# @order_id_path=nil,
|
47
|
-
# @origin_country_iso3="IND",
|
48
|
-
# @shipment_package_count=0,
|
49
|
-
# @shipment_type="EXPEDITED",
|
50
|
-
# @signed_by="FRONT DOOR",
|
51
|
-
# @slug="ups",
|
52
|
-
# @smses=[],
|
53
|
-
# @source="api",
|
54
|
-
# @status="Delivered",
|
55
|
-
# @tag="Delivered",
|
56
|
-
# @title="1ZA2207X6790326683",
|
57
|
-
# @tracked_count=47,
|
58
|
-
# @tracking_number="1ZA2207X6790326683",
|
59
|
-
# @unique_token="ly9ueXUJC",
|
60
|
-
# @checkpoints=[
|
61
|
-
# #<AfterShip::Checkpoint:0x007fe555bb0340
|
62
|
-
# @checkpoint_time=#<DateTime: 2014-05-12T14:07:00+00:00 ...>,
|
63
|
-
# @city="NEW YORK",
|
64
|
-
# @country_iso3=nil,
|
65
|
-
# @country_name="US",
|
66
|
-
# @courier="UPS",
|
67
|
-
# @created_at=#<DateTime: 2014-05-12T18:34:32+00:00 ...>,
|
68
|
-
# @message="DELIVERED",
|
69
|
-
# @slug="ups",
|
70
|
-
# @state="NY",
|
71
|
-
# @status="Delivered",
|
72
|
-
# @tag="Delivered",
|
73
|
-
# @zip="10075">
|
74
|
-
# #<AfterShip::Checkpoint ...>,
|
75
|
-
# ...
|
76
|
-
# ]>
|
77
|
-
#
|
78
|
-
# Create a new tracking
|
79
|
-
# https://www.aftership.com/docs/api/3.0/tracking/post-trackings
|
80
|
-
#
|
81
23
|
# client.create_tracking('tracking-number', 'ups', order_id: 'external-id')
|
82
|
-
#
|
83
|
-
# # Will return Tracking object or raise AfterShip::InvalidArgumentError
|
84
|
-
# # if it exists:
|
85
|
-
#
|
86
|
-
# #<AfterShip::Tracking ...>
|
87
|
-
#
|
88
|
-
# Update a tracking
|
89
|
-
# https://www.aftership.com/docs/api/3.0/tracking/put-trackings-slug-tracking_number
|
90
|
-
#
|
91
24
|
# client.update_tracking('tracking-number', 'ups', order_id: 'external-id')
|
25
|
+
# client.couriers
|
92
26
|
#
|
93
27
|
# To debug:
|
94
28
|
#
|
95
29
|
# AfterShip.debug = true
|
96
30
|
#
|
97
|
-
#
|
98
|
-
#
|
99
|
-
#
|
100
|
-
# client.tracking('1ZA2207X6790326683', 'ups') # Delivered, ok
|
31
|
+
# Some test trackings:
|
32
|
+
#
|
33
|
+
# client.tracking('1ZA2207X0444990982', 'ups')
|
101
34
|
class AfterShip
|
102
|
-
|
103
|
-
|
104
|
-
class InvalidCredentialsError < Error; end # 401
|
105
|
-
class RequestFailedError < Error; end # 402
|
106
|
-
class ResourceNotFoundError < Error; end # 404
|
107
|
-
class InvalidArgumentError < Error; end # 409
|
108
|
-
class TooManyRequestsError < Error; end # 429
|
109
|
-
class ServerError < Error; end # 500, 502, 503, 504
|
110
|
-
class UnknownError < Error; end
|
35
|
+
# The API root URL.
|
36
|
+
DEFAULT_API_ADDRESS = 'https://api.aftership.com/v4'
|
111
37
|
|
112
|
-
|
113
|
-
TRACKINGS_ENDPOINT
|
38
|
+
# The trackings endpoint URL.
|
39
|
+
TRACKINGS_ENDPOINT = "#{ DEFAULT_API_ADDRESS }/trackings"
|
114
40
|
|
115
|
-
|
41
|
+
# The activated couriers endpoint URL.
|
42
|
+
COURIERS_ENDPOINT = "#{ DEFAULT_API_ADDRESS }/couriers"
|
43
|
+
|
44
|
+
# Common JSON loading/dumping options.
|
45
|
+
JSON_OPTIONS = {
|
116
46
|
symbolize_keys: true # Symbol keys to string keys
|
117
47
|
}
|
118
48
|
|
@@ -136,49 +66,127 @@ class AfterShip
|
|
136
66
|
attr_accessor :debug
|
137
67
|
end
|
138
68
|
|
69
|
+
# The API key required for the AfterShip service.
|
70
|
+
#
|
71
|
+
# @return [String]
|
139
72
|
attr_reader :api_key
|
140
73
|
|
74
|
+
# Init the client:
|
75
|
+
#
|
76
|
+
# client = AfterShip.new(api_key: 'your-aftership-api-key')
|
77
|
+
#
|
141
78
|
# @param options [Hash]
|
142
|
-
#
|
79
|
+
# @option options api_key [String]
|
143
80
|
def initialize(options)
|
144
|
-
|
145
|
-
api_key: options[:api_key]
|
146
|
-
)
|
147
|
-
|
148
|
-
@api_key = options.delete(:api_key)
|
81
|
+
@api_key = options.fetch(:api_key)
|
149
82
|
end
|
150
83
|
|
151
84
|
# Get a list of trackings.
|
152
|
-
# https://www.aftership.com/docs/api/
|
85
|
+
# https://www.aftership.com/docs/api/4/trackings/get-trackings
|
86
|
+
#
|
87
|
+
# client.trackings
|
88
|
+
#
|
89
|
+
# # Will return list of Tracking objects:
|
90
|
+
#
|
91
|
+
# [
|
92
|
+
# #<AfterShip::Tracking ...>,
|
93
|
+
# #<AfterShip::Tracking ...>,
|
94
|
+
# ...
|
95
|
+
# ]
|
153
96
|
#
|
154
97
|
# @return [Hash]
|
155
98
|
def trackings
|
156
|
-
|
157
|
-
|
99
|
+
data = Request.get(url: TRACKINGS_ENDPOINT, api_key: api_key) do |response|
|
100
|
+
response.fetch(:data).fetch(:trackings)
|
101
|
+
end
|
158
102
|
|
159
103
|
data.map { |datum| Tracking.new(datum) }
|
160
104
|
end
|
161
105
|
|
162
106
|
# Get a single tracking. Raises an error if not found.
|
163
|
-
# https://www.aftership.com/docs/api/
|
107
|
+
# https://www.aftership.com/docs/api/4/trackings/get-trackings-slug-tracking_number
|
108
|
+
#
|
109
|
+
# client.tracking('tracking-number', 'ups')
|
110
|
+
#
|
111
|
+
# # Will return Tracking object or raise AfterShip::Error::NotFound:
|
112
|
+
#
|
113
|
+
# #<AfterShip::Tracking:0x007f838ef44e58
|
114
|
+
# @active=false,
|
115
|
+
# @android=[],
|
116
|
+
# @courier="UPS",
|
117
|
+
# @created_at=#<DateTime: 2014-11-19T15:16:17+00:00 ...>,
|
118
|
+
# @custom_fields={},
|
119
|
+
# @customer_name=nil,
|
120
|
+
# @delivery_time=8,
|
121
|
+
# @destination_country_iso3="USA",
|
122
|
+
# @emails=[],
|
123
|
+
# @expected_delivery=nil,
|
124
|
+
# @id="546cb4414a1a2097122ae7b1",
|
125
|
+
# @ios=[],
|
126
|
+
# @order_id="PL-66448782",
|
127
|
+
# @order_id_path=nil,
|
128
|
+
# @origin_country_iso3="IND",
|
129
|
+
# @shipment_package_count=1,
|
130
|
+
# @shipment_type="UPS SAVER",
|
131
|
+
# @shipment_weight=0.5,
|
132
|
+
# @shipment_weight_unit="kg",
|
133
|
+
# @signed_by="MET CUSTOM",
|
134
|
+
# @slug="ups",
|
135
|
+
# @smses=[],
|
136
|
+
# @source="api",
|
137
|
+
# @status="Delivered",
|
138
|
+
# @tag="Delivered",
|
139
|
+
# @title="1ZA2207X0490715335",
|
140
|
+
# @tracked_count=6,
|
141
|
+
# @tracking_account_number=nil,
|
142
|
+
# @tracking_number="1ZA2207X0490715335",
|
143
|
+
# @tracking_postal_code=nil,
|
144
|
+
# @tracking_ship_date=nil,
|
145
|
+
# @unique_token="-y6ziF438",
|
146
|
+
# @updated_at=#<DateTime: 2014-11-19T22:12:32+00:00 ...>,
|
147
|
+
# @checkpoints=[
|
148
|
+
# #<AfterShip::Checkpoint:0x007f838ef57d50
|
149
|
+
# @checkpoint_time=
|
150
|
+
# #<DateTime: 2014-11-11T19:12:00+00:00 ...>,
|
151
|
+
# @city="MUMBAI",
|
152
|
+
# @country_iso3=nil,
|
153
|
+
# @country_name="IN",
|
154
|
+
# @courier="UPS",
|
155
|
+
# @created_at=
|
156
|
+
# #<DateTime: 2014-11-19T15:16:17+00:00 ...>,
|
157
|
+
# @message="PICKUP SCAN",
|
158
|
+
# @slug="ups",
|
159
|
+
# @state=nil,
|
160
|
+
# @status="In Transit",
|
161
|
+
# @tag="InTransit",
|
162
|
+
# @zip=nil>,
|
163
|
+
# #<AfterShip::Checkpoint ...>,
|
164
|
+
# ...
|
165
|
+
# ]
|
166
|
+
# >
|
164
167
|
#
|
165
168
|
# @param tracking_number [String]
|
166
169
|
# @param courier [String]
|
167
170
|
#
|
168
171
|
# @return [Hash]
|
169
172
|
def tracking(tracking_number, courier)
|
170
|
-
|
171
|
-
|
172
|
-
|
173
|
-
|
174
|
-
response = request_response(url, {}, :get)
|
175
|
-
data = response.fetch(:data).fetch(:tracking)
|
173
|
+
url = "#{ TRACKINGS_ENDPOINT }/#{ courier }/#{ tracking_number }"
|
174
|
+
data = Request.get(url: url, api_key: api_key) do |response|
|
175
|
+
response.fetch(:data).fetch(:tracking)
|
176
|
+
end
|
176
177
|
|
177
178
|
Tracking.new(data)
|
178
179
|
end
|
179
180
|
|
180
181
|
# Create a new tracking.
|
181
|
-
# https://www.aftership.com/docs/api/
|
182
|
+
# https://www.aftership.com/docs/api/4/trackings/post-trackings
|
183
|
+
#
|
184
|
+
# client.create_tracking('tracking-number', 'ups', order_id: 'external-id')
|
185
|
+
#
|
186
|
+
# # Will return Tracking object or raise
|
187
|
+
# # AfterShip::Error::TrackingAlreadyExists:
|
188
|
+
#
|
189
|
+
# #<AfterShip::Tracking ...>
|
182
190
|
#
|
183
191
|
# @param tracking_number [String]
|
184
192
|
# @param courier [String]
|
@@ -186,22 +194,30 @@ class AfterShip
|
|
186
194
|
#
|
187
195
|
# @return [Hash]
|
188
196
|
def create_tracking(tracking_number, courier, options = {})
|
189
|
-
|
190
|
-
|
191
|
-
params = {
|
197
|
+
body = {
|
192
198
|
tracking: {
|
193
199
|
tracking_number: tracking_number,
|
194
200
|
slug: courier
|
195
201
|
}.merge(options)
|
196
202
|
}
|
197
203
|
|
198
|
-
|
199
|
-
|
204
|
+
data = Request.post(url: TRACKINGS_ENDPOINT, api_key: api_key,
|
205
|
+
body: body) do |response|
|
206
|
+
response.fetch(:data).fetch(:tracking)
|
207
|
+
end
|
200
208
|
|
201
209
|
Tracking.new(data)
|
202
210
|
end
|
203
211
|
|
204
|
-
#
|
212
|
+
# Update a tracking.
|
213
|
+
# https://www.aftership.com/docs/api/4/trackings/put-trackings-slug-tracking_number
|
214
|
+
#
|
215
|
+
# client.update_tracking('tracking-number', 'ups', order_id: 'external-id')
|
216
|
+
#
|
217
|
+
# # Will return Tracking object or raise
|
218
|
+
# # AfterShip::Error::TrackingAlreadyExists:
|
219
|
+
#
|
220
|
+
# #<AfterShip::Tracking ...>
|
205
221
|
#
|
206
222
|
# @param tracking_number [String]
|
207
223
|
# @param courier [String]
|
@@ -209,115 +225,43 @@ class AfterShip
|
|
209
225
|
#
|
210
226
|
# @return [Hash]
|
211
227
|
def update_tracking(tracking_number, courier, options = {})
|
212
|
-
|
213
|
-
|
214
|
-
url = "#{ TRACKINGS_ENDPOINT }/#{ courier }/#{ tracking_number }"
|
215
|
-
params = {
|
228
|
+
url = "#{ TRACKINGS_ENDPOINT }/#{ courier }/#{ tracking_number }"
|
229
|
+
body = {
|
216
230
|
tracking: options
|
217
231
|
}
|
218
232
|
|
219
|
-
|
220
|
-
|
221
|
-
|
222
|
-
Tracking.new(data)
|
223
|
-
end
|
224
|
-
|
225
|
-
# Raises an ArgumentError if any of the args is empty or nil.
|
226
|
-
#
|
227
|
-
# @param hash [Hash] arguments needed in options
|
228
|
-
def require_arguments(hash)
|
229
|
-
hash.each do |name, value|
|
230
|
-
if value.respond_to?(:empty?)
|
231
|
-
invalid_argument!(name) if value.empty?
|
232
|
-
else
|
233
|
-
invalid_argument!(name)
|
234
|
-
end
|
233
|
+
data = Request.put(url: url, api_key: api_key, body: body) do |response|
|
234
|
+
response.fetch(:data).fetch(:tracking)
|
235
235
|
end
|
236
|
-
end
|
237
236
|
|
238
|
-
|
239
|
-
|
240
|
-
# @param name [Symbol]
|
241
|
-
def invalid_argument!(name)
|
242
|
-
fail ArgumentError, "Argument #{ name } cannot be empty"
|
237
|
+
Tracking.new(data)
|
243
238
|
end
|
244
239
|
|
245
|
-
#
|
246
|
-
#
|
240
|
+
# Get a list of activated couriers.
|
241
|
+
# https://www.aftership.com/docs/api/4/couriers/get-couriers
|
247
242
|
#
|
248
|
-
#
|
249
|
-
# @param body_hash [Hash]
|
250
|
-
# @param method [Symbol]
|
243
|
+
# client.couriers
|
251
244
|
#
|
252
|
-
#
|
253
|
-
def request_response(url, body_hash, method = :get)
|
254
|
-
body_json = MultiJson.dump(body_hash)
|
255
|
-
|
256
|
-
request = Typhoeus::Request.new(
|
257
|
-
url,
|
258
|
-
method: method,
|
259
|
-
verbose: self.class.debug,
|
260
|
-
body: body_json,
|
261
|
-
headers: {
|
262
|
-
'aftership-api-key' => @api_key,
|
263
|
-
'Content-Type' => 'application/json'
|
264
|
-
}
|
265
|
-
)
|
266
|
-
|
267
|
-
if self.class.debug
|
268
|
-
request.on_complete do |response|
|
269
|
-
puts
|
270
|
-
puts 'Request body:'
|
271
|
-
puts request.options[:body]
|
272
|
-
puts
|
273
|
-
puts 'Response body:'
|
274
|
-
puts response.body
|
275
|
-
puts
|
276
|
-
end
|
277
|
-
end
|
278
|
-
|
279
|
-
response = request.run
|
280
|
-
response_to_json(response)
|
281
|
-
end
|
282
|
-
|
283
|
-
# Deal with API response, either return a Hash or raise an error.
|
245
|
+
# # Will return list of Courier objects:
|
284
246
|
#
|
285
|
-
#
|
247
|
+
# [
|
248
|
+
# #<AfterShip::Courier:0x007fa2771d4bf8
|
249
|
+
# @name="USPS",
|
250
|
+
# @other_name="United States Postal Service",
|
251
|
+
# @phone="+1 800-275-8777",
|
252
|
+
# @required_fields=[],
|
253
|
+
# @slug="usps",
|
254
|
+
# @web_url="https://www.usps.com">,
|
255
|
+
# #<AfterShip::Courier ...>
|
256
|
+
# ...
|
257
|
+
# ]
|
286
258
|
#
|
287
259
|
# @return [Hash]
|
288
|
-
|
289
|
-
|
290
|
-
|
291
|
-
json_response = parse_response(response)
|
292
|
-
|
293
|
-
case json_response[:meta][:code]
|
294
|
-
when 200, 201
|
295
|
-
return json_response
|
296
|
-
when 400
|
297
|
-
fail InvalidJSONDataError, json_response[:meta][:error_message]
|
298
|
-
when 401
|
299
|
-
fail InvalidCredentialsError, json_response[:meta][:error_message]
|
300
|
-
when 402
|
301
|
-
fail RequestFailedError, json_response[:meta][:error_message]
|
302
|
-
when 404
|
303
|
-
fail ResourceNotFoundError, json_response[:meta][:error_message]
|
304
|
-
when 409
|
305
|
-
fail InvalidArgumentError, json_response[:meta][:error_message]
|
306
|
-
when 429
|
307
|
-
fail TooManyRequestsError, json_response[:meta][:error_message]
|
308
|
-
when 500, 502, 503, 504
|
309
|
-
fail ServerError, json_response[:meta][:error_message]
|
310
|
-
else
|
311
|
-
fail UnknownError, json_response[:meta][:error_message]
|
260
|
+
def couriers
|
261
|
+
data = Request.get(url: COURIERS_ENDPOINT, api_key: api_key) do |response|
|
262
|
+
response.fetch(:data).fetch(:couriers)
|
312
263
|
end
|
313
|
-
end
|
314
264
|
|
315
|
-
|
316
|
-
#
|
317
|
-
# @param response [Typhoeus::Response]
|
318
|
-
#
|
319
|
-
# @return [Hash]
|
320
|
-
def parse_response(response)
|
321
|
-
MultiJson.load(response.body, JSON_OPTIONS)
|
265
|
+
data.map { |datum| Courier.new(datum) }
|
322
266
|
end
|
323
267
|
end
|
@@ -0,0 +1,40 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
RSpec.describe AfterShip do
|
4
|
+
let(:client) { AfterShip.new(api_key: 'key') }
|
5
|
+
|
6
|
+
it 'trackings' do
|
7
|
+
trackings = client.trackings
|
8
|
+
expect(trackings.size).to eq(2)
|
9
|
+
end
|
10
|
+
|
11
|
+
it 'trackings with debug' do
|
12
|
+
AfterShip.debug = true
|
13
|
+
|
14
|
+
trackings = client.trackings
|
15
|
+
expect(trackings.size).to eq(2)
|
16
|
+
|
17
|
+
AfterShip.debug = nil
|
18
|
+
end
|
19
|
+
|
20
|
+
it 'tracking' do
|
21
|
+
tracking = client.tracking('delivered', 'ups')
|
22
|
+
expect(tracking.tracking_number).to eq('1ZA2207X0444990982')
|
23
|
+
expect(tracking.checkpoints.size).to eq(15)
|
24
|
+
end
|
25
|
+
|
26
|
+
it 'create_tracking' do
|
27
|
+
tracking = client.create_tracking('created', 'ups', order_id: 'external-id')
|
28
|
+
expect(tracking.tracking_number).to eq('1Z0659120300549388')
|
29
|
+
end
|
30
|
+
|
31
|
+
it 'update_tracking' do
|
32
|
+
tracking = client.update_tracking('updated', 'ups', order_id: 'external-id')
|
33
|
+
expect(tracking.tracking_number).to eq('1Z0659120300549388')
|
34
|
+
end
|
35
|
+
|
36
|
+
it 'couriers' do
|
37
|
+
couriers = client.couriers
|
38
|
+
expect(couriers.size).to eq(4)
|
39
|
+
end
|
40
|
+
end
|