parcel_api 0.4.1 → 1.0.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 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