sendle-api 0.0.2 → 0.0.11

Sign up to get free protection for your applications and to get access to all the features.
Files changed (36) hide show
  1. checksums.yaml +4 -4
  2. data/Changelog.md +5 -0
  3. data/README.md +99 -5
  4. data/lib/sendle/api.rb +46 -3
  5. data/lib/sendle/api/actions/base.rb +51 -0
  6. data/lib/sendle/api/actions/create.rb +31 -0
  7. data/lib/sendle/api/actions/destroy.rb +23 -0
  8. data/lib/sendle/api/actions/index.rb +16 -14
  9. data/lib/sendle/api/actions/show.rb +23 -0
  10. data/lib/sendle/api/constants.rb +4 -0
  11. data/lib/sendle/api/errors/invalid_plan.rb +16 -0
  12. data/lib/sendle/api/errors/missing_params.rb +16 -0
  13. data/lib/sendle/api/errors/payment_required.rb +9 -0
  14. data/lib/sendle/api/errors/precondition_failed.rb +9 -0
  15. data/lib/sendle/api/errors/unprocessable_entity.rb +19 -0
  16. data/lib/sendle/api/factories/errors.rb +26 -0
  17. data/lib/sendle/api/order.rb +41 -0
  18. data/lib/sendle/api/ping.rb +8 -3
  19. data/lib/sendle/api/quote.rb +28 -0
  20. data/lib/sendle/api/resource.rb +64 -0
  21. data/lib/sendle/api/responses/json.rb +15 -0
  22. data/lib/sendle/api/sugars/create.rb +13 -0
  23. data/lib/sendle/api/sugars/destroy.rb +13 -0
  24. data/lib/sendle/api/sugars/index.rb +13 -0
  25. data/lib/sendle/api/sugars/show.rb +13 -0
  26. data/lib/sendle/api/utils.rb +24 -0
  27. data/lib/sendle/api/version.rb +1 -1
  28. data/spec/sendle/api/order_spec.rb +249 -0
  29. data/spec/sendle/api/ping_spec.rb +9 -1
  30. data/spec/sendle/api/quote_spec.rb +103 -0
  31. data/spec/sendle/api_spec.rb +22 -0
  32. data/spec/sendle/errors/missing_params_spec.rb +13 -0
  33. data/spec/support/helpers.rb +15 -1
  34. data/spec/support/shared_examples/with_credentials_spec.rb +1 -1
  35. metadata +29 -3
  36. data/lib/sendle/utils/actions.rb +0 -19
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: f736e0805af433eab79799321a145b9bcd88b735
4
- data.tar.gz: 2e2581b4fe3581e53c107555bafe975580b51f2c
3
+ metadata.gz: 68b93ccc7a2f1762a621462360bfd3efaa0b9a1e
4
+ data.tar.gz: eac48906b5c093d3fe83547bebaa9ddd1c3585c4
5
5
  SHA512:
6
- metadata.gz: 34253eefcf20f679aea3db0dd21f8fa775057174a4ba4f8611a9f36faf0483a64f7334c5209a3ac593f48f73a632fb47bc1a2cd15aaec7e3fb95b8c11478b082
7
- data.tar.gz: 3fac7d3704b385c72621ecec7e15e1dc3f2960ecddadaa4e7f26be568fc9645e76462660e1eeb6e062daf383c10e88e7253f74ba4281eb9e6dbfe8f08b75b143
6
+ metadata.gz: 6d63dfb209cb35f600b6d3f30a4e2ead269245a9a0681a16ab69fbfeb6e062491313e536b5b48be5b9e296881aa496638801fadf6fe40994cdefa22a2227c861
7
+ data.tar.gz: 5ec6cfacd67a5494cda6335786500ca45aa7ba13f0a6a9118e3093283f0e9abf01b39a6685af28904ecd8edd74b191489e11b6da9ab06febc75ad61ac546519a
@@ -0,0 +1,5 @@
1
+ # Sendle::Api Changes
2
+
3
+ ## 0.0.11
4
+
5
+ * Initial release!
data/README.md CHANGED
@@ -1,6 +1,6 @@
1
1
  # Sendle::Api
2
2
 
3
- TODO: Write a gem description
3
+ The Sendle API Ruby bindings provide a small SDK for convenient access to the Sendle API from applications written with the Ruby language.
4
4
 
5
5
  ## Installation
6
6
 
@@ -20,7 +20,101 @@ Or install it yourself as:
20
20
 
21
21
  ## Usage
22
22
 
23
- TODO: Write usage instructions here
23
+ Before you can use the Sendle API, you need to sign up for a Sendle account. Once you have signed up, you need to send an email to Sendle support requesting access to their API. When access has been granted, you will have access to your sendle_id and api_key, both which are required to access the api.
24
+
25
+ If you are accessing the Sendle API in sandbox mode, you need to repeat the above process on Sendle's sandbox servers.
26
+
27
+ ### Configuration
28
+
29
+ Before you can start using the library, you need to configure your api credentials. The instructions below assume you are using this library from a Rails application.
30
+
31
+ Create a file called 'sendle.rb' inside your config/initializers directory with the following content:
32
+ ```
33
+ Sendle::Api.api_key = Rails.application.secrets.sendle_api_key
34
+ Sendle::Api.sendle_id = Rails.application.secrets.sendle_id
35
+ Sendle::Api.sandbox = true #Only if you are accessing the Sendle sandbox servers, otherwise take out this line.
36
+ ```
37
+
38
+ ### Making a Request
39
+
40
+ Sendle's API documentation can be found here: http://sendle.github.io/sendle-api-doc.
41
+
42
+ #### Pinging the API
43
+ ```
44
+ Sendle::Api::Ping.execute
45
+ ```
46
+
47
+ Returns an instance of Sendle::Api::Responses::Pong upon a successful response from the API.
48
+
49
+ #### Getting a Delivery Quote
50
+ ```
51
+ params = { pickup_suburb: 'woolloomooloo',
52
+ pickup_postcode: '2011',
53
+ delivery_suburb: 'eastgardens',
54
+ delivery_postcode: '2036',
55
+ kilogram_weight: '1'
56
+ }
57
+ response = Sendle::Api::Quote.execute(params)
58
+
59
+ puts response.json #a hash
60
+ ```
61
+
62
+ Returns an instance of Sendle::Api::Responses::Json upon a successful response.
63
+
64
+ #### Creating an Order
65
+ ```
66
+ params = { pickup_date: "2016-05-05",
67
+ description: "Kryptonite",
68
+ kilogram_weight: 1,
69
+ cubic_metre_volume: 0.01,
70
+ customer_reference: "SupBdayPressie",
71
+ sender: {
72
+ contact: {
73
+ name: "Lex Luthor",
74
+ phone: "0412 345 678"
75
+ },
76
+ address: {
77
+ address_line1: "123 Gotham Ln",
78
+ suburb: "Sydney",
79
+ state_name: "NSW",
80
+ postcode: "2000",
81
+ country: "Australia"
82
+ },
83
+ instructions: "Knock loudly"
84
+ },
85
+ receiver: {
86
+ contact: {
87
+ name: "Clark Kent",
88
+ email: "clarkissuper@dailyplanet.xyz"
89
+ },
90
+ address: {
91
+ address_line1: "80 Wentworth Park Road",
92
+ suburb: "Glebe",
93
+ state_name: "NSW",
94
+ postcode: "2037",
95
+ country: "Australia"
96
+ },
97
+ instructions: "Give directly to Clark"
98
+ }
99
+ }
100
+ response = Sendle::Api::Order.create(params) #response is an instance of Sendle::Api::Responses::Json
101
+ ```
102
+
103
+ #### Viewing an Order
104
+ ```
105
+ #response is an instance of Sendle::Api::Responses::Json
106
+ response = Sendle::Api::Order.show("d9a5f8be-a245-4629-bfb5-e019bd9a2a06")
107
+ ```
108
+
109
+ #### Cancelling an Order (only orders with is_cancellable attribute set to true can be cancelled)
110
+ ```
111
+ #response is an instance of Sendle::Api::Responses::Json
112
+ response = Sendle::Api::Order.destroy("d9a5f8be-a245-4629-bfb5-e019bd9a2a06")
113
+ ```
114
+
115
+ #### Errors
116
+ Any of the methods described above can throw errors. Check the Sendle API docs for a list of errors and how to resolve them.
117
+
24
118
 
25
119
  ## Contributing
26
120
 
@@ -35,10 +129,10 @@ TODO: Write usage instructions here
35
129
  1. Navigate to root of this project
36
130
  2. Run bundle install to install the gems specified in sendle-api.gemspec
37
131
  3. Run bundle exec rake spec to run the tests
132
+ 4. After changes and ready to release, up the version in lib/sendle/api/version.rb
133
+ 5. Then run 'bundle install' on your testing project. Testing project is installing the sendle-api gem using a local path, so we don't need to release the gem to RubyGems.
134
+ 6. Once the gem is ready to be release, follow the instructions below.
38
135
 
39
136
  ### Release
40
137
  1. Make sure you have a RubyGems.org account
41
138
  2. bundle exec rake release
42
-
43
- ### Guide
44
- Based on this guide: https://quickleft.com/blog/engineering-lunch-series-step-by-step-guide-to-building-your-first-ruby-gem
@@ -1,17 +1,60 @@
1
+ # 3rd party libs
1
2
  require 'rest-client'
2
3
 
4
+ # Version
3
5
  require "sendle/api/version"
4
6
 
5
- require 'stripe/api/ping'
7
+ # Constants
8
+ require "sendle/api/constants"
9
+
10
+ # Utils
11
+ require 'sendle/api/utils'
12
+
13
+ # Syntax Sugar
14
+ require 'sendle/api/sugars/index'
15
+ require 'sendle/api/sugars/create'
16
+ require 'sendle/api/sugars/show'
17
+ require 'sendle/api/sugars/destroy'
18
+
19
+ # Api resource actions
20
+ require 'sendle/api/actions/base'
21
+ require 'sendle/api/actions/index'
22
+ require 'sendle/api/actions/create'
23
+ require 'sendle/api/actions/show'
24
+ require 'sendle/api/actions/destroy'
25
+
26
+ # Factories
27
+ require 'sendle/api/factories/errors'
28
+
29
+ # Api errors
30
+ require 'sendle/api/errors/missing_api_key'
31
+ require 'sendle/api/errors/missing_sendle_id'
32
+ require 'sendle/api/errors/unauthorized'
33
+ require 'sendle/api/errors/payment_required'
34
+ require 'sendle/api/errors/missing_params'
35
+ require 'sendle/api/errors/invalid_plan'
36
+ require 'sendle/api/errors/unprocessable_entity'
37
+ require 'sendle/api/errors/precondition_failed'
38
+
39
+ # Api responses
40
+ require 'sendle/api/responses/pong'
41
+ require 'sendle/api/responses/json'
42
+
43
+ # Api resources
44
+ require 'sendle/api/resource'
45
+ require 'sendle/api/ping'
46
+ require 'sendle/api/quote'
47
+ require 'sendle/api/order'
6
48
 
7
49
  module Sendle
8
50
  module Api
51
+ @sandbox = false
9
52
 
10
53
  class << self
11
- attr_accessor :api_key, :sendle_id
54
+ attr_accessor :api_key, :sendle_id, :sandbox
12
55
 
13
56
  def base_url
14
- "https://sandbox.sendle.com/api/"
57
+ sandbox ? "https://sandbox.sendle.com/api/" : "https://www.sendle.com/api/"
15
58
  end
16
59
  end
17
60
 
@@ -0,0 +1,51 @@
1
+ module Sendle
2
+ module Api
3
+ module Actions
4
+ module Base
5
+
6
+ def request(params)
7
+ RestClient::Request.execute(params)
8
+ rescue RestClient::PreconditionFailed,
9
+ RestClient::Unauthorized,
10
+ RestClient::PaymentRequired,
11
+ RestClient::UnprocessableEntity => e
12
+ raise Sendle::Api::Factories::Errors.new_error(e)
13
+ end
14
+
15
+ protected
16
+
17
+ def rest_client_params
18
+ include_credentials? ? common_params_with_credentials : common_params
19
+ end
20
+
21
+ def common_params
22
+ {
23
+ headers: json_headers
24
+ }
25
+ end
26
+
27
+ def common_params_with_credentials
28
+ common_params.merge(credential_params)
29
+ end
30
+
31
+ def check_for_missing_credentials
32
+ return unless self.include_credentials?
33
+ raise Sendle::Api::Errors::MissingSendleId if Sendle::Api.sendle_id.nil?
34
+ raise Sendle::Api::Errors::MissingApiKey if Sendle::Api.api_key.nil?
35
+ end
36
+
37
+ def json_headers
38
+ { accept: :json, content_type: :json }
39
+ end
40
+
41
+ def credential_params
42
+ {
43
+ user: Sendle::Api.sendle_id,
44
+ password: Sendle::Api.api_key
45
+ }
46
+ end
47
+
48
+ end
49
+ end
50
+ end
51
+ end
@@ -0,0 +1,31 @@
1
+ module Sendle
2
+ module Api
3
+ module Actions
4
+ module Create
5
+
6
+ def create(params = {})
7
+ check_for_missing_credentials
8
+ validate_create_request!(params)
9
+
10
+ request_params = rest_client_params
11
+ request_params[:method] = :post
12
+ request_params[:url] = url
13
+ request_params[:payload] = params
14
+
15
+ process_create_response(request(request_params))
16
+ end
17
+
18
+ def self.included(base)
19
+ base.extend(Sendle::Api::Sugars::Create)
20
+ end
21
+
22
+ protected
23
+
24
+ def http_method
25
+ :post
26
+ end
27
+
28
+ end
29
+ end
30
+ end
31
+ end
@@ -0,0 +1,23 @@
1
+ module Sendle
2
+ module Api
3
+ module Actions
4
+ module Destroy
5
+
6
+ def destroy(id)
7
+ raise Sendle::Api::Errors::MissingParams.new(['id']) if nullish?(id)
8
+
9
+ request_params = rest_client_params
10
+ request_params[:method] = :delete
11
+ request_params[:url] = url + '/' + id
12
+
13
+ process_destroy_response(request(request_params))
14
+ end
15
+
16
+ def self.included(base)
17
+ base.extend(Sendle::Api::Sugars::Destroy)
18
+ end
19
+
20
+ end
21
+ end
22
+ end
23
+ end
@@ -2,21 +2,23 @@ module Sendle
2
2
  module Api
3
3
  module Actions
4
4
  module Index
5
-
6
- def index
7
- Sendle::Api::Utils::Actions.check_for_missing_credentials
8
- RestClient::Request.execute(
9
- method: :get,
10
- url: self.url,
11
- user: Sendle::Api.sendle_id,
12
- password: Sendle::Api.api_key,
13
- headers: Sendle::Api::Utils::Actions.json_headers
14
- )
15
- Sendle::Api::Responses::Pong.new
16
- rescue RestClient::Unauthorized => e
17
- response = JSON.parse(e.response)
18
- raise Sendle::Api::Errors::Unauthorized.new(response['error_description'])
5
+
6
+ def index(params = {})
7
+ check_for_missing_credentials if include_credentials?
8
+ validate_index_request!(params)
9
+
10
+ request_params = rest_client_params
11
+ request_params[:method] = :get
12
+ request_params[:url] = url
13
+ request_params[:headers][:params] = params unless params.empty?
14
+
15
+ process_index_response(request(request_params))
19
16
  end
17
+
18
+ def self.included(base)
19
+ base.extend(Sendle::Api::Sugars::Index)
20
+ end
21
+
20
22
  end
21
23
  end
22
24
  end
@@ -0,0 +1,23 @@
1
+ module Sendle
2
+ module Api
3
+ module Actions
4
+ module Show
5
+
6
+ def show(id)
7
+ raise Sendle::Api::Errors::MissingParams.new(['id']) if nullish?(id)
8
+
9
+ request_params = rest_client_params
10
+ request_params[:method] = :get
11
+ request_params[:url] = url + '/' + id
12
+
13
+ process_show_response(request(request_params))
14
+ end
15
+
16
+ def self.included(base)
17
+ base.extend(Sendle::Api::Sugars::Show)
18
+ end
19
+
20
+ end
21
+ end
22
+ end
23
+ end
@@ -0,0 +1,4 @@
1
+ PLAN_EASY = 'easy'
2
+ PLAN_PREMIUM = 'premium'
3
+ PLAN_PRO = 'pro'
4
+ PLANS = [ PLAN_EASY, PLAN_PREMIUM, PLAN_PRO ]
@@ -0,0 +1,16 @@
1
+ module Sendle
2
+ module Api
3
+ module Errors
4
+ class InvalidPlan < StandardError
5
+ def initialize(plan)
6
+ @plan = plan
7
+ end
8
+
9
+ def to_s
10
+ "#{@plan} is not in the list of valid plans: #{PLANS.join(', ')}"
11
+ end
12
+
13
+ end
14
+ end
15
+ end
16
+ end
@@ -0,0 +1,16 @@
1
+ module Sendle
2
+ module Api
3
+ module Errors
4
+ class MissingParams < StandardError
5
+ def initialize(*params)
6
+ @missing_params = params
7
+ end
8
+
9
+ def to_s
10
+ "The following params are required: #{@missing_params.join(', ')}. Please check your request and try again."
11
+ end
12
+
13
+ end
14
+ end
15
+ end
16
+ end
@@ -0,0 +1,9 @@
1
+ module Sendle
2
+ module Api
3
+ module Errors
4
+ class PaymentRequired < StandardError
5
+
6
+ end
7
+ end
8
+ end
9
+ end
@@ -0,0 +1,9 @@
1
+ module Sendle
2
+ module Api
3
+ module Errors
4
+ class PreconditionFailed < StandardError
5
+
6
+ end
7
+ end
8
+ end
9
+ end
@@ -0,0 +1,19 @@
1
+ module Sendle
2
+ module Api
3
+ module Errors
4
+ class UnprocessableEntity < StandardError
5
+
6
+ def initialize(messages)
7
+ @messages = messages
8
+ end
9
+
10
+ def to_s
11
+ msg = "Please fix the following errors and try again - "
12
+ @messages.each { |k, v| msg += "#{k}: #{v.join(', ')}" }
13
+ msg
14
+ end
15
+
16
+ end
17
+ end
18
+ end
19
+ end