parcel_api 0.4.1 → 1.0.0

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: ccdca5cd657ddcfb47012dc2c74f75093f77584c
4
- data.tar.gz: 70cfd65377e6a41742aeec933cc3e7a123d2c732
3
+ metadata.gz: fdcd9ebea24a37f29ed1417078791e96ae59470b
4
+ data.tar.gz: 10626cce08a88d97bd32692ad2aeb0eb3b67f095
5
5
  SHA512:
6
- metadata.gz: f37606c5c842c634eba7139fcc7447c855ca82981c4ad611a81dfe22dee7ac7333dbdb815b9902c27dcf757a6ed57d3c43fc9608f0525ff03d14abbe5435b328
7
- data.tar.gz: 2393821656fd4c4de1672526f95f9290d97151bec8672e61400ba6f1b9340220c849aa7818016e399f0e8ba557bb892b8c1cf289c9397c22299c3d7abfd8da3b
6
+ metadata.gz: f959eed9357c58808b3305f5f5fbfb58fb32c7eec335c9614f40a9848af2d88bf02878fe0315478f13800e951428c4a1c9760373eb3555aad2831160607bc9e4
7
+ data.tar.gz: add3bf34df5be59889a28e7f091ac70547903f07fd914e7f671da025e149202d9be28679a909eaffbee0589dab2c72a3f96d8a6f58c86a1a1e45ab2d7d3b9a62
@@ -6,3 +6,5 @@ rvm:
6
6
  addons:
7
7
  code_climate:
8
8
  repo_token: 71a1f8fa6b8f4bd0e13542f237fd8f060d4dab088c71e5f980ed6247197d1820
9
+ services:
10
+ - redis-server
@@ -1,16 +1,22 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- parcel_api (0.4.1)
5
- faraday (~> 0.9)
6
- faraday_middleware (~> 0.9)
4
+ parcel_api (1.0.0)
5
+ activesupport (~> 4.2)
7
6
  oauth2 (~> 1.0)
8
7
  recursive-open-struct (~> 0.6)
8
+ redis (~> 3.2)
9
9
  thor (~> 0.19)
10
10
 
11
11
  GEM
12
12
  remote: https://rubygems.org/
13
13
  specs:
14
+ activesupport (4.2.7.1)
15
+ i18n (~> 0.7)
16
+ json (~> 1.7, >= 1.7.7)
17
+ minitest (~> 5.1)
18
+ thread_safe (~> 0.3, >= 0.3.4)
19
+ tzinfo (~> 1.1)
14
20
  addressable (2.3.8)
15
21
  codeclimate-test-reporter (0.4.7)
16
22
  simplecov (>= 0.7.1, < 1.0.0)
@@ -21,10 +27,11 @@ GEM
21
27
  docile (1.1.5)
22
28
  faraday (0.9.2)
23
29
  multipart-post (>= 1.2, < 3)
24
- faraday_middleware (0.10.0)
25
- faraday (>= 0.7.4, < 0.10)
30
+ i18n (0.7.0)
31
+ json (1.8.3)
26
32
  jwt (1.5.6)
27
33
  method_source (0.8.2)
34
+ minitest (5.9.0)
28
35
  multi_json (1.11.0)
29
36
  multi_xml (0.5.5)
30
37
  multipart-post (2.0.0)
@@ -41,6 +48,7 @@ GEM
41
48
  rack (1.6.4)
42
49
  rake (10.4.2)
43
50
  recursive-open-struct (0.6.5)
51
+ redis (3.3.1)
44
52
  rspec (3.2.0)
45
53
  rspec-core (~> 3.2.0)
46
54
  rspec-expectations (~> 3.2.0)
@@ -62,6 +70,9 @@ GEM
62
70
  simplecov-html (0.9.0)
63
71
  slop (3.6.0)
64
72
  thor (0.19.1)
73
+ thread_safe (0.3.5)
74
+ tzinfo (1.2.2)
75
+ thread_safe (~> 0.1)
65
76
  vcr (2.9.3)
66
77
  webmock (1.21.0)
67
78
  addressable (>= 2.3.6)
data/README.md CHANGED
@@ -50,9 +50,12 @@ client = ParcelApi::Client.new.tap do |config|
50
50
  config.username = ENV['USERNAME']
51
51
  config.password = ENV['PASSWORD']
52
52
  config.address = 'https://api.uat.nzpost.co.nz/' # defaults to api.nzpost.co.nz
53
+ config.redis = Redis.new(url: 'redis://:p4ssw0rd@10.0.1.1:6380/15') # defaults to Redis.new
53
54
  end
54
55
  ```
55
56
 
57
+ Redis is currently required, Oauth2 `access_token`'s are cached in Redis and expired automatically. You can use an existing Redis connection.
58
+
56
59
  Client connections can be passed to each method:
57
60
 
58
61
  `ParcelApi::Address(client.connection)`
@@ -46,7 +46,7 @@ intl_details.to_h.each {|k, v| puts "#{k}: #{v}"}
46
46
  # Tracking Example
47
47
 
48
48
  tracking = ParcelApi::Track.new
49
- results = tracking.details('1818120002213401AKL003HN')
49
+ results = tracking.details('8144152543878001AKL002PN')
50
50
 
51
51
  # example tracking output
52
52
  last_event = results.tracking_events.last
@@ -196,8 +196,9 @@ intl_label_options = {
196
196
  indicia_number: '123456',
197
197
  insurance_required: true,
198
198
  contains_only_documents: true,
199
- export_type: 'Gift',
200
- harmonised_system_tariff: '12121212'
199
+ export_type: 'Documents',
200
+ harmonised_system_tariff: '12121212',
201
+ user_reference_code: SecureRandom.hex(1),
201
202
  }
202
203
  ]
203
204
  }
@@ -219,7 +220,7 @@ File.open("#{intl.label_id}.pdf", 'w') do |f|
219
220
  end
220
221
 
221
222
 
222
- ShippingOptions Example
223
+ ## ShippingOptions Example
223
224
 
224
225
  shipping_options = ParcelApi::ShippingOptions.new
225
226
 
@@ -251,8 +252,7 @@ intl_options.to_h.each {|k, v| puts "#{k}: #{v}"}
251
252
 
252
253
  pickup_params = {
253
254
  carrier: 'CourierPost',
254
- message_id: 'Test Message ID',
255
- message_date_time: '2015-05-27T14:19:50',
255
+ caller: 'Test Caller',
256
256
  account_number: '91327067',
257
257
  pickup_address: {
258
258
  site_code: '28979',
@@ -1,9 +1,6 @@
1
- require 'faraday'
2
- require 'faraday_middleware'
3
1
  require 'recursive-open-struct'
4
2
 
5
3
  require 'parcel_api/version'
6
- require 'parcel_api/error'
7
4
  require 'parcel_api/address'
8
5
  require 'parcel_api/track'
9
6
  require 'parcel_api/label'
@@ -21,9 +21,8 @@ module ParcelApi
21
21
 
22
22
  def search(query, count=10)
23
23
  return [] if query.length < 4
24
-
25
- response = @connection.get DOMESTIC_URL, { q: query, count: count }
26
- addresses = response.body['addresses'].each do |a|
24
+ response = @connection.get DOMESTIC_URL, params: { q: query, count: count }
25
+ addresses = response.parsed['addresses'].each do |a|
27
26
  a['address_id'] = Integer(a['address_id'])
28
27
  a['dpid'] = Integer(a['dpid']) if a['dpid']
29
28
  end
@@ -37,7 +36,7 @@ module ParcelApi
37
36
  def details(address_id)
38
37
  details_url = File.join(DOMESTIC_URL, address_id.to_s)
39
38
  response = @connection.get details_url
40
- OpenStruct.new(response.body['address'])
39
+ OpenStruct.new(response.parsed['address'])
41
40
  end
42
41
 
43
42
  # Search for an Australian Address
@@ -56,7 +55,7 @@ module ParcelApi
56
55
  def australian_details(address_id)
57
56
  details_url = File.join(AUSTRALIAN_URL, address_id.to_s)
58
57
  response = @connection.get details_url
59
- RecursiveOpenStruct.new(response.body['address'], recurse_over_arrays: true)
58
+ RecursiveOpenStruct.new(response.parsed['address'], recurse_over_arrays: true)
60
59
  end
61
60
 
62
61
  # Search for an International Address
@@ -68,8 +67,8 @@ module ParcelApi
68
67
  def international_search(query, count=5, country_code=nil)
69
68
  return [] if query.length < 4
70
69
 
71
- response = @connection.get INTERNATIONAL_URL, { q: query, count: count, country_code: country_code }
72
- response.body['addresses'].map {|address| OpenStruct.new(address)}
70
+ response = @connection.get INTERNATIONAL_URL, params: { q: query, count: count, country_code: country_code }
71
+ response.parsed['addresses'].map {|address| OpenStruct.new(address)}
73
72
  end
74
73
 
75
74
  # Return international address details for a specific international address id
@@ -79,7 +78,7 @@ module ParcelApi
79
78
  def international_details(address_id)
80
79
  details_url = File.join(INTERNATIONAL_URL, address_id.to_s)
81
80
  response = @connection.get details_url
82
- RecursiveOpenStruct.new(response.body['result'], recurse_over_arrays: true)
81
+ RecursiveOpenStruct.new(response.parsed['result'], recurse_over_arrays: true)
83
82
  end
84
83
 
85
84
  end
@@ -1,3 +1,9 @@
1
+ require 'oauth2'
2
+ require 'redis'
3
+
4
+ require 'active_support'
5
+ require 'active_support/core_ext/numeric/time'
6
+
1
7
  module ParcelApi
2
8
  class Client
3
9
 
@@ -6,7 +12,8 @@ module ParcelApi
6
12
  :username,
7
13
  :password,
8
14
  :address,
9
- :auth_address
15
+ :auth_address,
16
+ :redis
10
17
 
11
18
  def self.connection
12
19
  @connection ||= new.connection
@@ -19,38 +26,25 @@ module ParcelApi
19
26
  @password = password || ENV['PASSWORD']
20
27
  @address = address || 'https://api.nzpost.co.nz'
21
28
  @auth_address = auth_address || 'https://oauth.nzpost.co.nz/as/token.oauth2'
29
+ @redis = redis || Redis.new
22
30
  end
23
31
 
24
32
  def connection
25
- Faraday.new(url: @address) do |conn|
26
- conn.authorization 'Bearer', token
27
- conn.headers['client_id'] = @client_id
28
- conn.request :json
29
- conn.response :json, :content_type => /\bjson$/
30
- conn.use FaradayMiddleware::RaiseHttpException
31
- conn.adapter Faraday.default_adapter
33
+ @access_token_cache ||= begin
34
+ if json = @redis.get(:parcel_api_access_token)
35
+ access_token = OAuth2::AccessToken.from_hash client, JSON.parse(json)
36
+ else
37
+ access_token = client.password.get_token @username, @password
38
+ @redis.set(:parcel_api_access_token, access_token.to_hash.to_json, ex: access_token.expires_in.seconds - 1.minute)
39
+ access_token
40
+ end
32
41
  end
33
42
  end
34
43
 
35
44
  private
36
45
 
37
- def token
38
- params = {
39
- client_id: @client_id,
40
- client_secret: @client_secret,
41
- username: @username,
42
- password: @password,
43
- grant_type: 'password',
44
- }
45
-
46
- auth_api = Faraday.new do |conn|
47
- conn.request :url_encoded
48
- conn.response :json
49
- conn.use FaradayMiddleware::RaiseHttpException
50
- conn.adapter Faraday.default_adapter
51
- end
52
- response = auth_api.post @auth_address, params
53
- response.body['access_token']
46
+ def client
47
+ OAuth2::Client.new(@client_id, @client_secret, site: @address, token_url: @auth_address, connection_opts: { headers: { 'client_id' => @client_id } })
54
48
  end
55
49
 
56
50
  end
@@ -18,8 +18,8 @@ module ParcelApi
18
18
 
19
19
  def create(label_options)
20
20
  domestic_url = File.join(LABEL_URL, 'domestic')
21
- response = @connection.post domestic_url, label_options
22
- labels = response.body['labels'].map {|label| OpenStruct.new(label)}
21
+ response = @connection.post domestic_url, body: label_options.to_json, headers: { 'Content-Type' => 'application/json' }
22
+ labels = response.parsed['labels'].map {|label| OpenStruct.new(label)}
23
23
  labels.first if labels.count == 1
24
24
  end
25
25
 
@@ -29,8 +29,8 @@ module ParcelApi
29
29
 
30
30
  def international_create(label_options)
31
31
  international_url = File.join(LABEL_URL, 'international')
32
- response = @connection.post international_url, label_options
33
- labels = response.body['labels'].map {|label| OpenStruct.new(label)}
32
+ response = @connection.post international_url, body: label_options.to_json, headers: { 'Content-Type' => 'application/json' }
33
+ labels = response.parsed['labels'].map {|label| OpenStruct.new(label)}
34
34
  labels.first if labels.count == 1
35
35
  end
36
36
 
@@ -41,7 +41,7 @@ module ParcelApi
41
41
  def details(label_id)
42
42
  details_url = File.join(LABEL_URL, "#{label_id}.json")
43
43
  response = @connection.get details_url
44
- details = response.body.tap {|d| d.delete('success')}
44
+ details = response.parsed.tap {|d| d.delete('success')}
45
45
  OpenStruct.new(details)
46
46
  end
47
47
 
@@ -4,7 +4,7 @@ module ParcelApi
4
4
  # The integrator provides the pick up location in the form of a site id or an address to create the pick up record.
5
5
 
6
6
  class Pickup
7
- PARCELPICKUP_URL = '/ParcelPickUp/2.0/bookings'
7
+ PARCELPICKUP_URL = '/ParcelPickUp/3.0/bookings'
8
8
 
9
9
  # Creates a new ParcelApi::Pickup instance.
10
10
 
@@ -17,8 +17,8 @@ module ParcelApi
17
17
  # @return Object of pickup details
18
18
 
19
19
  def create(pickup_options)
20
- response = @connection.post PARCELPICKUP_URL, pickup_options
21
- RecursiveOpenStruct.new(response.body, recurse_over_arrays: true)
20
+ response = @connection.post PARCELPICKUP_URL, body: pickup_options.to_json, headers: { 'Content-Type' => 'application/json' }
21
+ RecursiveOpenStruct.new(response.parsed, recurse_over_arrays: true)
22
22
  end
23
23
 
24
24
  end
@@ -19,8 +19,8 @@ module ParcelApi
19
19
  # @return [Array] return array of shipping options
20
20
 
21
21
  def get_domestic(parcel_params)
22
- response = @connection.get DOMESTIC_URL, parcel_params
23
- options = response.body.tap do |so|
22
+ response = @connection.get DOMESTIC_URL, params: parcel_params
23
+ options = response.parsed.tap do |so|
24
24
  so.delete('success')
25
25
  so.delete('message_id')
26
26
  end
@@ -32,8 +32,8 @@ module ParcelApi
32
32
  # @return [Array] return array of shipping options
33
33
 
34
34
  def get_international(parcel_params)
35
- response = @connection.get INTERNATIONAL_URL, parcel_params
36
- options = response.body.tap do |so|
35
+ response = @connection.get INTERNATIONAL_URL, params: parcel_params
36
+ options = response.parsed.tap do |so|
37
37
  so.delete('success')
38
38
  so.delete('message_id')
39
39
  end
@@ -4,7 +4,7 @@ module ParcelApi
4
4
  # return tracking information for a specific tracking reference.
5
5
 
6
6
  class Track
7
- PARCELTRACK_URL = '/ParcelTrack/2.0/parcels'
7
+ PARCELTRACK_URL = '/ParcelTrack/3.0/parcels'
8
8
 
9
9
  # Creates a new ParcelApi::Track instance.
10
10
 
@@ -19,8 +19,7 @@ module ParcelApi
19
19
  def details(tracking_reference)
20
20
  details_url = File.join(PARCELTRACK_URL, tracking_reference.to_s)
21
21
  response = @connection.get details_url
22
- events = response.body.tap do |d|
23
- d.delete('success')
22
+ events = response.parsed['results'].tap do |d|
24
23
  d['tracking_events'].map {|e| e['event_datetime'] = Time.parse(e['event_datetime'])}
25
24
  d['tracking_events'].sort_by! {|k| k['event_datetime'].to_i}
26
25
  end
@@ -1,3 +1,3 @@
1
1
  module ParcelApi
2
- VERSION = '0.4.1'
2
+ VERSION = '1.0.0'
3
3
  end
@@ -19,9 +19,9 @@ Gem::Specification.new do |spec|
19
19
  spec.require_paths = ['lib']
20
20
 
21
21
  spec.add_dependency 'thor', '~> 0.19'
22
- spec.add_dependency 'faraday', '~> 0.9'
23
- spec.add_dependency 'faraday_middleware', '~> 0.9'
24
22
  spec.add_dependency 'oauth2', '~> 1.0'
23
+ spec.add_dependency 'redis', '~> 3.2'
24
+ spec.add_dependency 'activesupport', '~> 4.2'
25
25
  spec.add_dependency 'recursive-open-struct', '~> 0.6'
26
26
 
27
27
  spec.add_development_dependency 'bundler', '~> 1.8'
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: parcel_api
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.4.1
4
+ version: 1.0.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Robert Coleman
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2016-09-24 00:00:00.000000000 Z
11
+ date: 2016-09-28 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: thor
@@ -25,47 +25,47 @@ dependencies:
25
25
  - !ruby/object:Gem::Version
26
26
  version: '0.19'
27
27
  - !ruby/object:Gem::Dependency
28
- name: faraday
28
+ name: oauth2
29
29
  requirement: !ruby/object:Gem::Requirement
30
30
  requirements:
31
31
  - - "~>"
32
32
  - !ruby/object:Gem::Version
33
- version: '0.9'
33
+ version: '1.0'
34
34
  type: :runtime
35
35
  prerelease: false
36
36
  version_requirements: !ruby/object:Gem::Requirement
37
37
  requirements:
38
38
  - - "~>"
39
39
  - !ruby/object:Gem::Version
40
- version: '0.9'
40
+ version: '1.0'
41
41
  - !ruby/object:Gem::Dependency
42
- name: faraday_middleware
42
+ name: redis
43
43
  requirement: !ruby/object:Gem::Requirement
44
44
  requirements:
45
45
  - - "~>"
46
46
  - !ruby/object:Gem::Version
47
- version: '0.9'
47
+ version: '3.2'
48
48
  type: :runtime
49
49
  prerelease: false
50
50
  version_requirements: !ruby/object:Gem::Requirement
51
51
  requirements:
52
52
  - - "~>"
53
53
  - !ruby/object:Gem::Version
54
- version: '0.9'
54
+ version: '3.2'
55
55
  - !ruby/object:Gem::Dependency
56
- name: oauth2
56
+ name: activesupport
57
57
  requirement: !ruby/object:Gem::Requirement
58
58
  requirements:
59
59
  - - "~>"
60
60
  - !ruby/object:Gem::Version
61
- version: '1.0'
61
+ version: '4.2'
62
62
  type: :runtime
63
63
  prerelease: false
64
64
  version_requirements: !ruby/object:Gem::Requirement
65
65
  requirements:
66
66
  - - "~>"
67
67
  - !ruby/object:Gem::Version
68
- version: '1.0'
68
+ version: '4.2'
69
69
  - !ruby/object:Gem::Dependency
70
70
  name: recursive-open-struct
71
71
  requirement: !ruby/object:Gem::Requirement
@@ -202,7 +202,6 @@ files:
202
202
  - lib/parcel_api/address.rb
203
203
  - lib/parcel_api/cli.rb
204
204
  - lib/parcel_api/client.rb
205
- - lib/parcel_api/error.rb
206
205
  - lib/parcel_api/label.rb
207
206
  - lib/parcel_api/pickup.rb
208
207
  - lib/parcel_api/shipping_options.rb
@@ -1,80 +0,0 @@
1
- # @private
2
- module FaradayMiddleware
3
- # @private
4
- class RaiseHttpException < Faraday::Middleware
5
- def call(env)
6
- @app.call(env).on_complete do |response|
7
- case response[:status].to_i
8
- when 400
9
- raise ParcelApi::BadRequest, error_message_400(response)
10
- when 404
11
- raise ParcelApi::NotFound, error_message_400(response)
12
- when 500
13
- raise ParcelApi::InternalServerError, error_message_500(response, "Something is technically wrong.")
14
- when 502
15
- raise ParcelApi::BadGateway, error_message_500(response, "The server returned an invalid or incomplete response.")
16
- when 503
17
- raise ParcelApi::ServiceUnavailable, error_message_500(response, "NZ Post is rate limiting your requests.")
18
- when 504
19
- raise ParcelApi::GatewayTimeout, error_message_500(response, "504 Gateway Time-out")
20
- end
21
- end
22
- end
23
-
24
- def initialize(app)
25
- super app
26
- @parser = nil
27
- end
28
-
29
- private
30
-
31
- def error_message_400(response)
32
- "#{response[:method].to_s.upcase} #{response[:url].to_s} status: #{response[:status]}#{error_body(response[:body])}"
33
- end
34
-
35
- def error_body(body)
36
- # body gets passed as a string, not sure if it is passed as something else from other spots?
37
- if not body.nil? and not body.empty? and body.kind_of?(String)
38
- body = ::JSON.parse(body)
39
- end
40
-
41
- if body.nil? || body['errors'].nil?
42
- nil
43
- else
44
- body_errors = body['errors'].flat_map {|error| error.map {|k,v| "#{k}: #{v}" }}.compact.join(', ')
45
- " - #{body_errors}"
46
- end
47
- end
48
-
49
- def error_message_500(response, body=nil)
50
- "#{response[:method].to_s.upcase} #{response[:url].to_s} status: #{[response[:status].to_s + ':', body].compact.join(' ')}"
51
- end
52
- end
53
- end
54
-
55
- module ParcelApi
56
- # Custom error class for rescuing from all NZ Post errors
57
- class Error < StandardError; end
58
-
59
- # Raised when NZ Post returns the HTTP status code 400
60
- class BadRequest < Error; end
61
-
62
- # Raised when NZ Post returns the HTTP status code 404
63
- class NotFound < Error; end
64
-
65
- # Raised when NZ Post returns the HTTP status code 429
66
- class TooManyRequests < Error; end
67
-
68
- # Raised when NZ Post returns the HTTP status code 500
69
- class InternalServerError < Error; end
70
-
71
- # Raised when NZ Post returns the HTTP status code 502
72
- class BadGateway < Error; end
73
-
74
- # Raised when NZ Post returns the HTTP status code 503
75
- class ServiceUnavailable < Error; end
76
-
77
- # Raised when NZ Post returns the HTTP status code 504
78
- class GatewayTimeout < Error; end
79
-
80
- end