shipping_easy 0.2.0 → 0.2.1

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: b51569e520e425f916ee5b73f0fcd9086ec23aa1
4
- data.tar.gz: 5c9bf4c89f508e002327c37b3670fd3ac3fdd0b8
3
+ metadata.gz: 3c67cb9d5219b8a9fcf9bffdc123ab2a02bdeed0
4
+ data.tar.gz: 3341af1622a0df5f7aac16b5bf9c86f06fce3bf6
5
5
  SHA512:
6
- metadata.gz: 0d2f8ce7d601b671c76186ab78eebe8fc2ccc886abf7af13c2adcc3a5071f10a134ea4511db8749ba97854d196dc59547d31918da9ac389711ff2832744c20fe
7
- data.tar.gz: e7c656651793f6fc67c5883e44b09e1d33397383ce5be7e87b7edc39fb65b129662846942363efc9311128b1b8651574ea6e1824c5667966d1433ef9078e28fe
6
+ metadata.gz: 0b070887687e1a6d9d267c88a4c16c1bb128a4cc8e19202c061a496ecb2ff7f5b7aabff0e5f3df61d9e897340beeb3a711867a288d3fd406dc5a111a0456f480
7
+ data.tar.gz: 00cf62427239f916acb74b19fad9c88c90cb8e824731db5734269f41cb6c89debe34f2f68524fc0bf85b56a6412bd130d8f5228eee39f86060be49e3804663a1
data/README.md CHANGED
@@ -1,8 +1,17 @@
1
+ [![Code Climate](https://codeclimate.com/repos/5315eeefe30ba01aa501c119/badges/92e9ca8e93ca2cbc260b/gpa.png)](https://codeclimate.com/repos/5315eeefe30ba01aa501c119/feed)
2
+
1
3
  # ShippingEasy
2
4
 
3
- Still in development. Please hold.
5
+ This is the official wrapper for the ShippingEasy API. Currently the API only exposes several functions so this wrapper only handles the following calls:
6
+
7
+ * Adding an order to a ShippingEasy store
8
+ * Cancelling an order before it has been shipped
9
+
10
+ We will keep this library up to date as we expand our API offerings.
11
+
12
+ ## Setup
4
13
 
5
- ## Installation
14
+ ### Installation
6
15
 
7
16
  Add this line to your application's Gemfile:
8
17
 
@@ -16,6 +25,307 @@ Or install it yourself as:
16
25
 
17
26
  $ gem install shipping_easy
18
27
 
28
+ ### Configuration
29
+
30
+ You will need a ShippingEasy API key and secret to sign your API requests. These can be found in your account's settings (https://app.shippingeasy.com/settings/api_credentials).
31
+
32
+ Once you have the credentials, add them to the libary's configuration. Do this in an intializer if you're running a Rails app:
33
+
34
+ ShippingEasy.configure do |config|
35
+ config.api_key = 'd8e8fca2dc0f896fd7cb4cb0031ba249'
36
+ config.api_secret = 'XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX'
37
+ end
38
+
39
+
40
+ If you are a 3rd party plugin developer and have a staging account with ShippingEasy, you can change the base URL like so:
41
+
42
+ config.base_url = 'https://staging.shippingeasy.com'
43
+
44
+ ## Authentication
45
+
46
+ The ShippingEasy API will hit a callback URL when an order, or a part of an order, has been shipped. The request to the callback URL will be also signed with the same shared secret found in the store's API settings.
47
+
48
+ This gem provides an Authenticator to handle verifying the signed request from ShippingEasy. Here's an example of how to use it (after you configured the library with your credentials in the step above):
49
+
50
+ ShippingEasy::Authenticator.authenticate(method: :post, path: "/callback", body: "{\"shipment\":{\"id\":\"1234\"}}")
51
+ # => true
52
+
53
+ The arguments for the constructor are as follows:
54
+
55
+ * **method** - The method of the http request. E.g. "post" or "get".
56
+ * **path** - The path of the request's uri. E.g. "/orders/callback"
57
+ * **params** - An associative array of the request's query string parameters. E.g. array("api_signature" => "asdsadsad", "api_timestamp" => "1234567899")
58
+ * **body** - The request body as a JSON string.
59
+ * **api_secret** - Optional. The ShippingEasy API secret for the customer account. Defaults to the global configuration if set.
60
+
61
+ ## API Calls
62
+
63
+ ### Adding an order
64
+
65
+ To add an order to a store, simply call the create method on the Order resource class. (A comprehensive list of the data attributes and their definitions can be found below.)
66
+
67
+ payload = { order: "external_order_identifier" => "ABC123", "subtotal_including_tax" => "12.38", ... }
68
+ ShippingEasy::Resources::Order.create(store_api_key: "d8821dde1d32f408def40b77273d5c11", payload: payload)
69
+
70
+ If successful the call will return a JSON hash with the ShippingEasy order ID, as well as the external order identifier originally supplied in your call.
71
+
72
+ { "order" => { "id" => "27654", "external_order_identifier" => "ABC123" } }
73
+
74
+ #### Possible Exceptions
75
+
76
+ ##### ShippingEasy::AccessDeniedError
77
+ Your credentials could not be authenticated or the store api_key could not be found.
78
+
79
+ ##### ShippingEasy::InvalidRequestError
80
+ The order could not be created on the server for one or more of the following reasons:
81
+
82
+ * The JSON payload could not be parsed.
83
+ * One or more of the supplied data attributes failed validation and is missing or incorrect.
84
+ * An order with the supplied external_order_identifier already exists for that store.
85
+
86
+ The exception will contain a message that indicates which of these conditions failed.
87
+
88
+ #### Order Attributes
89
+
90
+ The following is a list of attributes that should be provided to the ShippingEasy_Order object as a associative array.
91
+
92
+ An example hash for the create order API call may be found here: https://gist.github.com/twmills/9349053.
93
+
94
+ **ext_order_identifier**
95
+ : *Required.* The e-commerce system's order ID.
96
+
97
+ **ordered_at**
98
+ : *Required.* Timestamp when the order was created.
99
+
100
+ **order_status**
101
+ : Possible values are "awaiting_shipment", "awaiting_payment", "awaiting_fulfillment", "awaiting_shipment", "partially_shipped". Default is "awaiting_shipment".
102
+
103
+ **total_including_tax**
104
+ : Defaults to 0.0 if not specified.
105
+
106
+ **total_excluding_tax**
107
+ : Defaults to 0.0 if not specified.
108
+
109
+ **discount_amount**
110
+ : Defaults to 0.0 if not specified.
111
+
112
+ **coupon_discount**
113
+ : Defaults to 0.0 if not specified.
114
+
115
+ **subtotal_including_tax**
116
+ : Defaults to 0.0 if not specified.
117
+
118
+ **subtotal_excluding_tax**
119
+ : Defaults to 0.0 if not specified.
120
+
121
+ **subtotal_tax**
122
+ : Defaults to 0.0 if not specified.
123
+
124
+ **total_tax**
125
+ : Defaults to 0.0 if not specified.
126
+
127
+ **base_shipping_cost**
128
+ : Defaults to 0.0 if not specified.
129
+
130
+ **shipping_cost_including_tax**
131
+ : Defaults to 0.0 if not specified.
132
+
133
+ **shipping_cost_excluding_tax**
134
+ : Defaults to 0.0 if not specified.
135
+
136
+ **shipping_cost_tax**
137
+ : Defaults to 0.0 if not specified.
138
+
139
+ **base_handling_cost**
140
+ : Defaults to 0.0 if not specified.
141
+
142
+ **handling_cost_excluding_tax**
143
+ : Defaults to 0.0 if not specified.
144
+
145
+ **handling_cost_including_tax**
146
+ : Defaults to 0.0 if not specified.
147
+
148
+ **handling_cost_tax**
149
+ : Defaults to 0.0 if not specified.
150
+
151
+ **base_wrapping_cost**
152
+ : Defaults to 0.0 if not specified.
153
+
154
+ **wrapping_cost_excluding_tax**
155
+ : Defaults to 0.0 if not specified.
156
+
157
+ **wrapping_cost_including_tax**
158
+ : Defaults to 0.0 if not specified.
159
+
160
+ **wrapping_cost_tax**
161
+ : Defaults to 0.0 if not specified.
162
+
163
+ **notes**
164
+ : Customer notes on the order.
165
+
166
+ **billing_company**
167
+ : Company name for billing address
168
+
169
+ **billing_first_name**
170
+ : Customer first name for billing address
171
+
172
+ **billing_last_name**
173
+ : Customer last name for billing address
174
+
175
+ **billing_address**
176
+ : First address line for billing address
177
+
178
+ **billing_address2**
179
+ : Additional address line for billing address
180
+
181
+ **billing_city**
182
+ : City name for billing address
183
+
184
+ **billing_state**
185
+ : State name for billing address
186
+
187
+ **billing_country**
188
+ : Country name for billing address
189
+
190
+ **billing_postal_code**
191
+ : Postal code for billing address
192
+
193
+ **billing_phone_number**
194
+ : Phone number.
195
+
196
+ **billing_email**
197
+ : Email address
198
+
199
+ **recipients**
200
+ : A nested associative array of recipient attributes. At least one recipient is required.
201
+
202
+ **recipients > company**
203
+ : Company name for shipping address
204
+
205
+ **recipients > first_name**
206
+ : Customer first name for shipping address
207
+
208
+ **recipients > last_name**
209
+ : Customer last name for shipping address
210
+
211
+ **recipients > address**
212
+ : *Required.* First address line for shipping address
213
+
214
+ **recipients > address2**
215
+ : Additional address line for shipping address
216
+
217
+ **recipients > city**
218
+ : City name for shipping address
219
+
220
+ **recipients > state**
221
+ : State name for shipping address
222
+
223
+ **recipients > country**
224
+ : Country name for shipping address
225
+
226
+ **recipients > residential**
227
+ : Whether or not address is residential or not. Value can be "true" or "false".
228
+
229
+ **recipients > postal_code**
230
+ : *Required.* Postal code for shipping address
231
+
232
+ **recipients > postal_code_plus_4**
233
+ : Postal code plus 4 for shipping address
234
+
235
+ **recipients > phone_number**
236
+ : Customer phone number
237
+
238
+ **recipients > email**
239
+ : Customer email address
240
+
241
+ **recipients > base_cost**
242
+ : Cost before tax for all line items sent to this recipient
243
+
244
+ **recipients > cost_excluding_tax**
245
+ : Cost before tax for all line items sent to this recipient
246
+
247
+ **recipients > cost_including_tax**
248
+ : Cost including tax for all line items sent to this recipient
249
+
250
+ **recipients > cost_tax**
251
+ : Cost of the tax for all line items sent to this recipient
252
+
253
+ **recipients > base_handling_cost**
254
+ : Handling cost before tax for all line items sent to this recipient
255
+
256
+ **recipients > handling_cost_excluding_tax**
257
+ : Handling cost before tax for all line items sent to this recipient
258
+
259
+ **recipients > handling_cost_including_tax**
260
+ : Handling cost including tax for all line items sent to this recipient
261
+
262
+ **recipients > handling_cost_tax**
263
+ : Handling cost of the tax for all line items sent to this recipient
264
+
265
+ **recipients > shipping_zone_id**
266
+ : ID of the shipping zone.
267
+
268
+ **recipients > shipping_zone_name**
269
+ : Name of the shipping zone.
270
+
271
+ **recipients > shipping_method**
272
+ : Method of shipment.
273
+
274
+ **recipients > items_total**
275
+ : Total number of items.
276
+
277
+ **recipients > items_shipped**
278
+ : Total number of items shipped.
279
+
280
+ **recipients > line_items**
281
+ : A nested associative array of line item attributes. At least one line item is required.
282
+
283
+ **recipients > line_items > item_name**
284
+ : Name of the item/product.
285
+
286
+ **recipients > line_items > sku**
287
+ : SKU of the item/product.
288
+
289
+ **recipients > line_items > bin_picking_number**
290
+ : Bin number where the item may be stored in a warehouse.
291
+
292
+ **recipients > line_items > weight_in_ounces**
293
+ : Weight of the line item in ounces.
294
+
295
+ **recipients > line_items > quantity**
296
+ : Quantity of the the items for the line item.
297
+
298
+ **recipients > line_items > total_excluding_tax**
299
+ : Total excluding tax for the line item.
300
+
301
+ **recipients > line_items > unit_price**
302
+ : Unit price of the item.
303
+
304
+ ### Cancelling an order
305
+
306
+ Sometimes an e-commerce system will mark an order as shipped outside of the ShippingEasy system. Therefore an API call is required to remove this order from ShippingEasy so that it is not double-shipped.
307
+
308
+ Here's an example using your store's API key and the e-commerce order identifier used to create the order in ShippingEasy:
309
+
310
+ ShippingEasy::Resources::Cancellation.create(store_api_key: "d8821dde1d32f408def40b77273d5c11", external_order_identifier: "ABC123")
311
+
312
+ If successful the call will return a JSON hash with the ShippingEasy order ID, as well as the external order identifier originally supplied in your call.
313
+
314
+ { "order" => { "id" => "27654", "external_order_identifier" => "ABC123" } }
315
+
316
+ #### Possible Exceptions
317
+
318
+ ##### ShippingEasy::AccessDeniedError
319
+ Your credentials could not be authenticated or the store api_key could not be found.
320
+
321
+ ##### ShippingEasy::InvalidRequestError
322
+ The cancellation could not complete for one or more of the following reasons:
323
+
324
+ * The order could not be found.
325
+ * The order has already been marked as shipped in the ShippingEasy system and cannot be cancelled.
326
+
327
+ The exception will contain a message that indicates which of these conditions failed.
328
+
19
329
  ## Contributing
20
330
 
21
331
  1. Fork it
@@ -24,7 +24,7 @@ module ShippingEasy
24
24
  # :params - The query params passed in as part of the request.
25
25
  # :body - The body of the request which should normally be a JSON payload.
26
26
  def initialize(options = {})
27
- @api_secret = options.fetch(:api_secret)
27
+ @api_secret = options.fetch(:api_secret, ShippingEasy.api_secret)
28
28
  @method = options.fetch(:method, :get)
29
29
  @path = options.fetch(:path)
30
30
  @body = options.fetch(:body, nil)
@@ -16,11 +16,12 @@ class ShippingEasy::Http::ResponseHandler
16
16
 
17
17
  def run
18
18
  case status
19
- when 401 then raise ShippingEasy::AccessDeniedError, response.body
20
- when 404 then raise ShippingEasy::ResourceNotFoundError, response.body
21
- when 200, 201 then JSON.parse(response.body)
22
- else
23
- raise ShippingEasy::Error, response.body
19
+ when 200, 201 then JSON.parse(response.body)
20
+ when 400 then raise ShippingEasy::InvalidRequestError, response.body
21
+ when 401 then raise ShippingEasy::AccessDeniedError, response.body
22
+ when 404 then raise ShippingEasy::ResourceNotFoundError, response.body
23
+ else
24
+ raise ShippingEasy::Error, response.body
24
25
  end
25
26
  end
26
27
 
@@ -1,3 +1,3 @@
1
1
  module ShippingEasy
2
- VERSION = "0.2.0"
2
+ VERSION = "0.2.1"
3
3
  end
data/lib/shipping_easy.rb CHANGED
@@ -42,6 +42,7 @@ module ShippingEasy
42
42
 
43
43
  class Error < StandardError; end
44
44
  class ResourceNotFoundError < Error; end
45
+ class InvalidRequestError < Error; end
45
46
  class RequestExpiredError < Error
46
47
  def initialize(msg = "The request has expired.")
47
48
  super(msg)
@@ -13,6 +13,12 @@ describe ShippingEasy::Authenticator, api: true do
13
13
  let(:signature) { ShippingEasy::Signature.new(api_secret: api_secret, method: method, path: path, params: params, body: request_body) }
14
14
  subject { ShippingEasy::Authenticator.new(api_secret: api_secret, method: method, path: path, params: params_with_signature, body: request_body) }
15
15
 
16
+ before do
17
+ ShippingEasy.configure do |config|
18
+ config.api_secret = api_secret
19
+ end
20
+ end
21
+
16
22
  describe "#initialize" do
17
23
  specify { subject.api_secret.should == api_secret }
18
24
  specify { subject.method.should == :post }
@@ -23,6 +29,11 @@ describe ShippingEasy::Authenticator, api: true do
23
29
  specify { subject.expected_signature.should be_a(ShippingEasy::Signature) }
24
30
  end
25
31
 
32
+ context "when api_secret is not supplied" do
33
+ subject { ShippingEasy::Authenticator.new(api_secret: api_secret, method: method, path: path, params: params_with_signature, body: request_body) }
34
+ specify { subject.api_secret.should == api_secret }
35
+ end
36
+
26
37
  describe "#request_expires_at" do
27
38
  specify { subject.request_expires_at.to_s.should == (Time.now - ShippingEasy::Authenticator::EXPIRATION_INTERVAL).to_s }
28
39
  end
@@ -16,6 +16,10 @@ describe ShippingEasy::Http::ResponseHandler do
16
16
  context "when success" do
17
17
  specify { subject.run.should == body }
18
18
  end
19
+ context "when request is invalid" do
20
+ let(:status) { 400 }
21
+ specify { expect { subject.run }.to raise_error(ShippingEasy::InvalidRequestError) }
22
+ end
19
23
  context "when authentication fails" do
20
24
  let(:status) { 401 }
21
25
  specify { expect { subject.run }.to raise_error(ShippingEasy::AccessDeniedError) }
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: shipping_easy
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.0
4
+ version: 0.2.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - ShippingEasy
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2014-03-03 00:00:00.000000000 Z
11
+ date: 2014-03-04 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: faraday