hermes_api 0.3.0 → 0.5.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
  SHA256:
3
- metadata.gz: 2b1313c32c78bfdd9fb7a8256298157ca5a13f8a92a5074edeb1671969cb5f43
4
- data.tar.gz: 14a9dbfd88d46e2c0dce1e49baf0fd8d992332ac5051a60e24b7dc9af083c9a4
3
+ metadata.gz: b071e3f67cee6a1475d31ef398886a256a6caa74af59f57a4cd94b35982298e0
4
+ data.tar.gz: 0501c14dc98e8de9e9c1d3bdb703e19f69d41f55a048249ade0ab1cb102793ed
5
5
  SHA512:
6
- metadata.gz: 8bab7f7db1681634318f832ce9e2aacd1d059025f2745dfddc6a115581dfaad5de7baa552ceb23116e31fa3dae7cbdc16f9200ddad8ad61b7a828156a3fd925b
7
- data.tar.gz: 31f1ea2846b709e074a7a280b8ee7fa84820db2622370c2b011fe53d69d1bcd3ff536b921a8aaa20bfe2a6aad66d3098d1f81bea283866b74e9d5eb555e3cdff
6
+ metadata.gz: 7dd454207d4bcb9eea759890d4243b9486fbf704c29117614e51d1654621bbcde2c458916a0e89e6b1bd884cc65d40f41d113dcbe460c0f654b7a445e114a1bc
7
+ data.tar.gz: c6f727e2435134d77e00b856c61bd08467c374dd6cb95a58b9c517871fe325d50f2e468aad228a5f09b78958e507cff404216a32c206670763c18215138548b5
data/Gemfile.lock CHANGED
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- hermes_api (0.2.1)
4
+ hermes_api (0.4.1)
5
5
  activeresource (>= 4.1.0, < 6.0.0)
6
6
 
7
7
  GEM
data/bin/console CHANGED
@@ -6,7 +6,6 @@ require "dotenv/load"
6
6
  require "dev/zeitwerk_loader"
7
7
  require "dev/config"
8
8
  require "hermes_api"
9
-
10
9
  # You can add fixtures and/or initialization code here to make experimenting
11
10
  # with your gem easier. You can also use a different console, if you like.
12
11
  set_config
data/hermes_api.gemspec CHANGED
@@ -6,7 +6,7 @@ Gem::Specification.new do |spec|
6
6
  spec.name = "hermes_api"
7
7
  spec.version = HermesAPI::VERSION
8
8
  spec.authors = ["Andy Chong"]
9
- spec.email = ["andygg1996personal@gmail.com"]
9
+ spec.email = ["andy@postco.co"]
10
10
 
11
11
  spec.summary = "Unofficial Ruby object based Hermes UK API wrapper."
12
12
  spec.description = "Unofficial Ruby object based Hermes UK API wrapper."
data/lib/dev/config.rb CHANGED
@@ -2,12 +2,7 @@ require "dotenv/load"
2
2
 
3
3
  def set_config
4
4
  HermesAPI.configure do |config|
5
- config.user = ENV["HERMES_API_USER"]
6
- config.password = ENV["HERMES_API_PASSWORD"]
7
5
  config.env = :test
8
6
  config.proxy = ENV["HERMES_API_PROXY"]
9
- config.auth_id = ENV["HERMES_API_AUTH_ID"]
10
- config.auth_secret = ENV["HERMES_API_AUTH_SECRET"]
11
- config.api_key = ENV["HERMES_API_KEY"]
12
7
  end
13
8
  end
@@ -0,0 +1,38 @@
1
+ module HermesAPI
2
+ module BearerAuth
3
+ def with_oauth_session(api_key, client_id, client_secret)
4
+ headers["apikey"] = api_key
5
+ connection.bearer_token = fetch_token(client_id, client_secret)
6
+ response = yield
7
+ connection.bearer_token = nil
8
+ headers["apikey"] = nil
9
+ response
10
+ rescue ActiveResource::UnauthorizedAccess => e
11
+ clear_token_cache(client_id, client_secret)
12
+ raise e
13
+ end
14
+
15
+ def oauth_audience
16
+ prefix.match(/^\/?([^\/]*)/).captures.first
17
+ end
18
+
19
+ def clear_token_cache(client_id, client_secret)
20
+ cache_key = "HermesAPI/#{client_id}/#{client_secret}/#{oauth_audience}/oauth_token"
21
+ HermesAPI.cache.delete(cache_key)
22
+ end
23
+
24
+ def fetch_token(client_id, client_secret)
25
+ cache_key = "HermesAPI/#{client_id}/#{client_secret}/#{oauth_audience}/oauth_token"
26
+ cached_token = HermesAPI.cache.read(cache_key)
27
+ return cached_token if cached_token
28
+
29
+ response = OAuth.create(audience: oauth_audience, client_id: client_id, client_secret: client_secret)
30
+ HermesAPI.cache.write(
31
+ cache_key,
32
+ response.access_token,
33
+ expires_in: response.expires_in - 15 # clear cache earlier
34
+ )
35
+ response.access_token
36
+ end
37
+ end
38
+ end
@@ -1,6 +1,6 @@
1
1
  module HermesAPI
2
2
  class Configuration
3
- attr_accessor :proxy, :env, :user, :password, :auth_id, :auth_secret, :api_key
3
+ attr_accessor :proxy, :env
4
4
  end
5
5
 
6
6
  PRODUCTION_SITE = "https://www.hermes-europe.co.uk"
@@ -10,9 +10,9 @@ module HermesAPI
10
10
  OAUTH_TESTING_SITE = "https://hermes-client-integration-pre.eu.auth0.com"
11
11
 
12
12
  JSON_PRODUCTION_SITE = "https://api.hermesworld.co.uk"
13
- JSON_TESTING_SITE = "https://api.hermesworld.co.uk"
14
13
  # temporarily disabled until it is fixed
15
14
  # JSON_TESTING_SITE = "https://hermeslive-pre-prod.apigee.net"
15
+ JSON_TESTING_SITE = JSON_PRODUCTION_SITE
16
16
 
17
17
  class << self
18
18
  def config
@@ -22,13 +22,9 @@ module HermesAPI
22
22
  def after_configure
23
23
  HermesAPI::Base.site = config.env.to_s == "production" ? PRODUCTION_SITE : TESTING_SITE
24
24
  HermesAPI::Base.proxy = config.proxy
25
- HermesAPI::Base.user = config.user
26
- HermesAPI::Base.password = config.password
27
25
 
28
26
  HermesAPI::JsonBase.site = config.env.to_s == "production" ? JSON_PRODUCTION_SITE : JSON_TESTING_SITE
29
27
  HermesAPI::OAuth.site = config.env.to_s == "production" ? OAUTH_PRODUCTION_SITE : OAUTH_TESTING_SITE
30
-
31
- HermesAPI::JsonBase.headers["apikey"] = config.api_key
32
28
  end
33
29
 
34
30
  def configure
@@ -3,24 +3,8 @@ module HermesAPI
3
3
  self.include_format_in_path = false
4
4
  self.auth_type = :bearer
5
5
 
6
- OAUTH_AUDIENCE = nil
7
-
8
- def save
9
- token = HermesAPI.cache.read("#{self.class.name}/oauth_token") || fetch_token
10
- connection.bearer_token = token
11
- super
12
- end
13
-
14
- private
15
-
16
- def fetch_token
17
- response = OAuth.create(audience: self.class::OAUTH_AUDIENCE)
18
- HermesAPI.cache.write(
19
- "#{self.class.name}/oauth_token",
20
- response.access_token,
21
- expires_in: response.expires_in - 15 # clear cache earlier
22
- )
23
- response.access_token
6
+ def self.inherited(subclass)
7
+ subclass.extend(BearerAuth)
24
8
  end
25
9
  end
26
10
  end
@@ -1,17 +1,15 @@
1
1
  module HermesAPI
2
2
  class OAuth < ActiveResource::Base
3
3
  self.include_format_in_path = false
4
- self.element_name=""
5
- self.prefix="/oauth/token"
4
+ self.element_name = ""
5
+ self.prefix = "/oauth/token"
6
6
 
7
7
  def initialize(attributes = {}, persisted = false)
8
8
  attributes = {
9
9
  grant_type: "client_credentials",
10
- client_id: HermesAPI.config.auth_id,
11
- client_secret: HermesAPI.config.auth_secret,
12
10
  **attributes
13
11
  }
14
12
  super
15
13
  end
16
14
  end
17
- end
15
+ end
@@ -1,14 +1,17 @@
1
1
  module HermesAPI
2
- class PrintInStoreQr < JsonBase
2
+ class PrintInStoreQrCode < JsonBase
3
3
  self.element_name = ""
4
4
  self.prefix = "/client-print-in-store-api/v1/references"
5
5
 
6
- OAUTH_AUDIENCE = "client-print-in-store-api"
7
-
8
6
  def load(attributes, remove_root = false, persisted = false)
9
7
  # remove the outer array before parsing the response body
10
8
  attributes = attributes[0] if attributes.is_a?(Array) && attributes.length == 1
11
9
  super
12
10
  end
11
+
12
+ def qr_code
13
+ base64_data = as_json.dig("qrCode", "base64EncodedBytes")
14
+ Base64.decode64(base64_data) if base64_data
15
+ end
13
16
  end
14
17
  end
@@ -1,9 +1,56 @@
1
- "
2
- Create return label(s).
3
- You can choose to create a batch of return labels by passing in multiple collectionRoutingRequestEntry.
4
- "
5
1
  module HermesAPI
6
2
  class ReturnLabel < Base
3
+ # Create return label(s).
4
+ # You can choose to create a batch of return labels by passing in multiple collectionRoutingRequestEntry.
5
+ # Example:
6
+ # HermesAPI::Base.with_session("username", "password") do
7
+ # request_body = {clientId: "1234",
8
+ # clientName: "Life",
9
+ # childClientId: "",
10
+ # childClientName: "",
11
+ # sourceOfRequest: "CLIENTWS",
12
+ # collectionRoutingRequestEntries: [{ #collectionRoutingRequestEntry
13
+ # customer: {
14
+ # address: {
15
+ # firstName: "Leonie", lastName: "E", houseName: "2", streetName: "Street",
16
+ # addressLine1: "2 Street", addressLine2: "Fulham", postCode: "SW6 6EL",
17
+ # city: "London", region: "", countryCode: "GB"
18
+ # },
19
+ # mobilePhoneNo: "+447884571522",
20
+ # email: "leonie@london.com",
21
+ # customerReference1: "8284"
22
+ # },
23
+ # countryOfOrigin: "GB"
24
+ # }]}
25
+ # @order = HermesAPI::ReturnLabel.new(request_body)
26
+ # @order.save
27
+ #
28
+ # # Request for a single print in store QR code by wrapping in an oauth session block, only work with 1 label.
29
+ # # To request a batch of QR codes, use the HermesAPI::PrintInStoreQrCode#create directly.
30
+ #
31
+ # HermesAPI::PrintInStoreQrCode.with_oauth_session("api_key", "client_id/auth_id", "client_secret/auth_secret") do
32
+ # @order.request_print_in_store_qr_code(
33
+ # deliveryAddress: {
34
+ # name: "Andy",
35
+ # addressLine1: "7 Street",
36
+ # addressLine2: "Fulham",
37
+ # countryCode: "GB",
38
+ # postcode: "SW6 6EL"
39
+ # },
40
+ # dimensions: {
41
+ # depth: 15,
42
+ # length: 20,
43
+ # width: 15,
44
+ # weight: 1
45
+ # },
46
+ # value: {
47
+ # currency: "GBP",
48
+ # amount: 10
49
+ # }
50
+ # )
51
+ # end
52
+ # end
53
+ #
7
54
  self.prefix = "/routing/service/rest/v4/createReturnBarcodeAndLabel"
8
55
  self.element_name = ""
9
56
 
@@ -66,18 +113,11 @@ module HermesAPI
66
113
 
67
114
  alias_method :tracking_number, :tracking_numbers
68
115
 
69
- def request_print_in_store_qr_code(attrs = {
70
- dimensions: {
71
- depth: 15,
72
- length: 20,
73
- width: 15,
74
- weight: 1
75
- },
76
- value: {
77
- currency: "GBP",
78
- amount: 10
79
- }
80
- })
116
+ def request_print_in_store_qr_code(**attrs)
117
+ if ([:dimensions, :value, :deliveryAddress] - attrs.keys).length > 0
118
+ raise ArgumentError, request_print_in_store_qr_code_error_message
119
+ end
120
+
81
121
  return nil if attributes["routingResponseEntries"].blank?
82
122
 
83
123
  entries = routingResponseEntries.routingResponseEntry
@@ -86,17 +126,10 @@ module HermesAPI
86
126
  barcode = carrier.barcode1
87
127
  customer = collectionRoutingRequestEntries[0].customer
88
128
  address = customer.address
89
-
90
- self.print_in_store_qr_code = PrintInStoreQr.create(
129
+ self.print_in_store_qr_code = PrintInStoreQrCode.create(
91
130
  customer: {
92
131
  customerReference1: customer.customerReference1
93
132
  },
94
- deliveryAddress: {
95
- name: "#{address.firstName} #{address.lastName}",
96
- addressLine1: address.addressLine1,
97
- countryCode: address.countryCode,
98
- postcode: address.postCode
99
- },
100
133
  labelType: "RETURN",
101
134
  barcode: {
102
135
  barcode: barcode.barcodeNumber,
@@ -121,8 +154,32 @@ module HermesAPI
121
154
  )
122
155
  end
123
156
 
124
- def base64_print_in_store_qr_code
125
- as_json.dig("print_in_store_qr_code", "qrCode", "base64EncodedBytes")
157
+ private
158
+
159
+ def request_print_in_store_qr_code_error_message
160
+ <<~HEREDOC
161
+ Missing attributes
162
+ Example:
163
+ HermesAPI::ReturnLabel#request_print_in_store_qr_code(
164
+ dimensions: {
165
+ depth: 15,
166
+ length: 20,
167
+ width: 15,
168
+ weight: 1
169
+ },
170
+ value: {
171
+ currency: 'GBP',
172
+ amount: 10
173
+ },
174
+ deliveryAddress: {
175
+ name: 'Don Joe',
176
+ addressLine1: 'Real Logic',
177
+ addressLine2: '4-4 Ridings Park, Eastern Way',
178
+ countryCode: 'GB',
179
+ postcode: 'WS117FJ'
180
+ }
181
+ )
182
+ HEREDOC
126
183
  end
127
184
  end
128
185
  end
@@ -0,0 +1,16 @@
1
+ module HermesAPI
2
+ class TrackingEvent < JsonBase
3
+ # # Retrieve TrackingEvents by wrapping in an oauth session block
4
+ #
5
+ # HermesAPI::TrackingEvent.with_oauth_session("api_key", "client_id/auth_id", "client_secret/auth_secret") do
6
+ # HermesAPI::TrackingEvent.where(barcode: "123456789")
7
+ # end
8
+
9
+ self.element_name = ""
10
+ self.prefix = "/client-tracking-api/v1/events"
11
+
12
+ def self.where(barcode:)
13
+ super(barcode: barcode, descriptionType: "CLIENT")
14
+ end
15
+ end
16
+ end
@@ -0,0 +1,29 @@
1
+ module HermesAPI
2
+ class WebTracking < ActiveResource::Base
3
+ self.element_name = ""
4
+ self.site = "https://api.hermesworld.co.uk"
5
+ self.prefix = "/enterprise-tracking-api/v1/parcels"
6
+ self.include_format_in_path = false
7
+ headers["apiKey"] = ENV["HERMES_WEB_TRACKING_API_KEY"]
8
+
9
+ MAPPING = {
10
+ "715" => "pending_drop_off",
11
+ "708" => "dropped_off",
12
+ "690" => "dropped_off",
13
+ "710" => "collected_by_courier",
14
+ "688" => "collected_by_courier",
15
+ "689" => "collected_by_courier",
16
+ "711" => "collected_by_courier"
17
+ }
18
+
19
+ def load(attributes, remove_root = false, persisted = false)
20
+ attributes = attributes.dig("results", 0)
21
+ super(attributes)
22
+ end
23
+
24
+ def self.find(barcode)
25
+ uniqueId = format.decode(connection.get("#{prefix}/search/#{barcode}", headers).body).first
26
+ find_single("", params: {uniqueIds: uniqueId})
27
+ end
28
+ end
29
+ end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module HermesAPI
4
- VERSION = "0.3.0"
4
+ VERSION = "0.5.0"
5
5
  end
data/lib/hermes_api.rb CHANGED
@@ -5,15 +5,17 @@ require "active_resource"
5
5
 
6
6
  module HermesAPI
7
7
  require "hermes_api/cache"
8
+ require "hermes_api/bearer_auth"
8
9
  require "hermes_api/configuration"
9
10
  require "hermes_api/creation_error"
10
11
  require "hermes_api/connection"
11
12
 
12
13
  require "hermes_api/resources/base"
13
14
  require "hermes_api/resources/return_label"
14
-
15
+
15
16
  require "hermes_api/resources/o_auth"
16
17
  require "hermes_api/resources/json_base"
17
- require "hermes_api/resources/print_in_store_qr"
18
-
18
+ require "hermes_api/resources/print_in_store_qr_code"
19
+ require "hermes_api/resources/tracking_event"
20
+ require "hermes_api/resources/web_tracking"
19
21
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: hermes_api
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.3.0
4
+ version: 0.5.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Andy Chong
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2021-08-03 00:00:00.000000000 Z
11
+ date: 2021-08-27 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: activeresource
@@ -130,7 +130,7 @@ dependencies:
130
130
  version: '0'
131
131
  description: Unofficial Ruby object based Hermes UK API wrapper.
132
132
  email:
133
- - andygg1996personal@gmail.com
133
+ - andy@postco.co
134
134
  executables: []
135
135
  extensions: []
136
136
  extra_rdoc_files: []
@@ -151,6 +151,7 @@ files:
151
151
  - lib/dev/config.rb
152
152
  - lib/dev/zeitwerk_loader.rb
153
153
  - lib/hermes_api.rb
154
+ - lib/hermes_api/bearer_auth.rb
154
155
  - lib/hermes_api/cache.rb
155
156
  - lib/hermes_api/configuration.rb
156
157
  - lib/hermes_api/connection.rb
@@ -158,8 +159,10 @@ files:
158
159
  - lib/hermes_api/resources/base.rb
159
160
  - lib/hermes_api/resources/json_base.rb
160
161
  - lib/hermes_api/resources/o_auth.rb
161
- - lib/hermes_api/resources/print_in_store_qr.rb
162
+ - lib/hermes_api/resources/print_in_store_qr_code.rb
162
163
  - lib/hermes_api/resources/return_label.rb
164
+ - lib/hermes_api/resources/tracking_event.rb
165
+ - lib/hermes_api/resources/web_tracking.rb
163
166
  - lib/hermes_api/version.rb
164
167
  homepage: https://github.com/PostCo/hermes_api
165
168
  licenses: