endicia_label_server-ruby 0.2.2
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 +7 -0
- data/.gitignore +22 -0
- data/.hound.yml +2 -0
- data/.rspec +1 -0
- data/.rubocop.yml +1065 -0
- data/.travis.yml +10 -0
- data/Gemfile +11 -0
- data/Gemfile.lock +62 -0
- data/LICENSE.txt +14 -0
- data/README.md +66 -0
- data/Rakefile +19 -0
- data/endicia.wsdl +4272 -0
- data/endicia_label_server.gemspec +23 -0
- data/lib/endicia_label_server-ruby.rb +2 -0
- data/lib/endicia_label_server.rb +33 -0
- data/lib/endicia_label_server/builders/builder_base.rb +91 -0
- data/lib/endicia_label_server/builders/change_pass_phrase_builder.rb +18 -0
- data/lib/endicia_label_server/builders/postage_label_builder.rb +24 -0
- data/lib/endicia_label_server/builders/postage_rate_builder.rb +23 -0
- data/lib/endicia_label_server/builders/postage_rates_builder.rb +23 -0
- data/lib/endicia_label_server/builders/user_sign_up_builder.rb +24 -0
- data/lib/endicia_label_server/connection.rb +96 -0
- data/lib/endicia_label_server/exceptions.rb +5 -0
- data/lib/endicia_label_server/parsers/change_pass_phrase_parser.rb +20 -0
- data/lib/endicia_label_server/parsers/parser_base.rb +42 -0
- data/lib/endicia_label_server/parsers/postage_label_parser.rb +52 -0
- data/lib/endicia_label_server/parsers/postage_rate_parser.rb +43 -0
- data/lib/endicia_label_server/parsers/postage_rates_parser.rb +16 -0
- data/lib/endicia_label_server/parsers/user_sign_up_parser.rb +24 -0
- data/lib/endicia_label_server/service/mailpiece_shape.rb +92 -0
- data/lib/endicia_label_server/services.rb +37 -0
- data/lib/endicia_label_server/util.rb +29 -0
- data/lib/endicia_label_server/version.rb +10 -0
- data/spec/endicia_label_server/builders/builder_base_spec.rb +47 -0
- data/spec/endicia_label_server/connection/change_pass_phrase_spec.rb +45 -0
- data/spec/endicia_label_server/connection/multiple_rate_spec.rb +96 -0
- data/spec/endicia_label_server/connection/postage_label_spec.rb +67 -0
- data/spec/endicia_label_server/connection/single_rate_spec.rb +57 -0
- data/spec/endicia_label_server/connection/user_sign_up_spec.rb +93 -0
- data/spec/endicia_label_server/connection_spec.rb +21 -0
- data/spec/endicia_label_server/service/mailpiece_shape_spec.rb +159 -0
- data/spec/spec_helper.rb +18 -0
- data/spec/stubs/change_pass_phrase_success.xml +8 -0
- data/spec/stubs/postage_label_success.xml +17 -0
- data/spec/stubs/postage_rate_success.xml +147 -0
- data/spec/stubs/postage_rates_success.xml +184 -0
- data/spec/stubs/user_sign_up_success.xml +7 -0
- metadata +150 -0
@@ -0,0 +1,23 @@
|
|
1
|
+
require File.expand_path('../lib/endicia_label_server/version', __FILE__)
|
2
|
+
|
3
|
+
Gem::Specification.new do |gem|
|
4
|
+
gem.name = 'endicia_label_server-ruby'
|
5
|
+
gem.version = EndiciaLabelServer::Version::STRING
|
6
|
+
gem.platform = Gem::Platform::RUBY
|
7
|
+
gem.authors = ['Veeqo']
|
8
|
+
gem.email = ['helpme@veeqo.com']
|
9
|
+
gem.homepage = 'https://github.com/veeqo/endicia_label_server-ruby'
|
10
|
+
gem.summary = 'Endicia Label Server'
|
11
|
+
gem.description = 'Gem for accessing the Endicia Label Server XML API from Ruby'
|
12
|
+
|
13
|
+
gem.license = 'AGPL-3.0'
|
14
|
+
|
15
|
+
gem.required_rubygems_version = '>= 1.3.6'
|
16
|
+
|
17
|
+
gem.add_runtime_dependency 'ox', '~> 2.2', '>= 2.2.0'
|
18
|
+
gem.add_runtime_dependency 'excon', '~> 0.45', '>= 0.45.3'
|
19
|
+
gem.add_runtime_dependency 'insensitive_hash', '~> 0.3.3', '>= 0.3.3'
|
20
|
+
|
21
|
+
gem.files = `git ls-files`.split($OUTPUT_RECORD_SEPARATOR)
|
22
|
+
gem.require_path = 'lib'
|
23
|
+
end
|
@@ -0,0 +1,33 @@
|
|
1
|
+
module EndiciaLabelServer
|
2
|
+
GEM_NAME = 'endicia_label_server'
|
3
|
+
|
4
|
+
autoload :SERVICES, "#{GEM_NAME}/services"
|
5
|
+
autoload :MAILPIECESHAPES, "#{GEM_NAME}/services"
|
6
|
+
|
7
|
+
module Service
|
8
|
+
autoload :MailpieceShape, "#{GEM_NAME}/service/mailpiece_shape"
|
9
|
+
end
|
10
|
+
|
11
|
+
autoload :Version, "#{GEM_NAME}/version"
|
12
|
+
autoload :Connection, "#{GEM_NAME}/connection"
|
13
|
+
autoload :Exceptions, "#{GEM_NAME}/exceptions"
|
14
|
+
autoload :Util, "#{GEM_NAME}/util"
|
15
|
+
|
16
|
+
module Builders
|
17
|
+
autoload :BuilderBase, "#{GEM_NAME}/builders/builder_base"
|
18
|
+
autoload :PostageRateBuilder, "#{GEM_NAME}/builders/postage_rate_builder"
|
19
|
+
autoload :PostageRatesBuilder, "#{GEM_NAME}/builders/postage_rates_builder"
|
20
|
+
autoload :UserSignUpBuilder, "#{GEM_NAME}/builders/user_sign_up_builder"
|
21
|
+
autoload :PostageLabelBuilder, "#{GEM_NAME}/builders/postage_label_builder"
|
22
|
+
autoload :ChangePassPhraseBuilder, "#{GEM_NAME}/builders/change_pass_phrase_builder"
|
23
|
+
end
|
24
|
+
|
25
|
+
module Parsers
|
26
|
+
autoload :ParserBase, "#{GEM_NAME}/parsers/parser_base"
|
27
|
+
autoload :PostageRateParser, "#{GEM_NAME}/parsers/postage_rate_parser"
|
28
|
+
autoload :PostageRatesParser, "#{GEM_NAME}/parsers/postage_rates_parser"
|
29
|
+
autoload :UserSignUpParser, "#{GEM_NAME}/parsers/user_sign_up_parser"
|
30
|
+
autoload :PostageLabelParser, "#{GEM_NAME}/parsers/postage_label_parser"
|
31
|
+
autoload :ChangePassPhraseParser, "#{GEM_NAME}/parsers/change_pass_phrase_parser"
|
32
|
+
end
|
33
|
+
end
|
@@ -0,0 +1,91 @@
|
|
1
|
+
require 'ox'
|
2
|
+
|
3
|
+
module EndiciaLabelServer
|
4
|
+
module Builders
|
5
|
+
# The {BuilderBase} class builds Endicia XML Objects.
|
6
|
+
#
|
7
|
+
# @author Paul Trippett
|
8
|
+
# @since 0.1.0
|
9
|
+
# @abstract
|
10
|
+
# @attr [Ox::Document] document The XML Document being built
|
11
|
+
# @attr [Ox::Element] root The XML Root
|
12
|
+
class BuilderBase
|
13
|
+
include Ox
|
14
|
+
include Exceptions
|
15
|
+
|
16
|
+
attr_accessor :document,
|
17
|
+
:root
|
18
|
+
|
19
|
+
# Initializes a new {BuilderBase} object
|
20
|
+
#
|
21
|
+
# @param [String] root_name The Name of the XML Root
|
22
|
+
# @return [void]
|
23
|
+
def initialize(root_name, opts = {})
|
24
|
+
initialize_xml_roots root_name
|
25
|
+
|
26
|
+
document << root
|
27
|
+
|
28
|
+
opts.each_pair { |k, v| add(k, v) }
|
29
|
+
end
|
30
|
+
|
31
|
+
def add(*args)
|
32
|
+
first_arg = args.first
|
33
|
+
last_arg = args.last
|
34
|
+
root_key = Util.camelize(first_arg)
|
35
|
+
|
36
|
+
if last_arg.is_a? Hash
|
37
|
+
add_hash root_key, last_arg
|
38
|
+
elsif last_arg.is_a? Array
|
39
|
+
|
40
|
+
else
|
41
|
+
root << element_with_value(root_key, last_arg)
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
def add_hash(root_key, data)
|
46
|
+
xml_root_key = (root_key.is_a? String) ? root_key : Util.camelize(root_key)
|
47
|
+
root << Element.new(xml_root_key).tap do |org|
|
48
|
+
data.each_pair do |key, value|
|
49
|
+
xml_child_key = (key.is_a? String) ? key : Util.camelize(key)
|
50
|
+
org << element_with_value(xml_child_key, value)
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
55
|
+
def add_array(root_key, data)
|
56
|
+
xml_root_key = Util.camelize(root_key)
|
57
|
+
root << Element.new(xml_root_key).tap do |org|
|
58
|
+
child_key = "#{Util.singularize(xml_root_key)}ID"
|
59
|
+
data.each do |value|
|
60
|
+
org << element_with_value(child_key, value)
|
61
|
+
end
|
62
|
+
end
|
63
|
+
end
|
64
|
+
|
65
|
+
# Returns a String representation of the XML document being built
|
66
|
+
#
|
67
|
+
# @return [String]
|
68
|
+
def to_xml
|
69
|
+
Ox.to_xml document
|
70
|
+
end
|
71
|
+
|
72
|
+
def to_http_post
|
73
|
+
"#{post_field}=#{to_xml}"
|
74
|
+
end
|
75
|
+
|
76
|
+
private
|
77
|
+
|
78
|
+
def initialize_xml_roots(root_name)
|
79
|
+
self.document = Document.new
|
80
|
+
self.root = Element.new(root_name)
|
81
|
+
end
|
82
|
+
|
83
|
+
def element_with_value(name, value)
|
84
|
+
fail InvalidAttributeError, name unless value.respond_to?(:to_str)
|
85
|
+
Element.new(name).tap do |request_action|
|
86
|
+
request_action << value.to_str
|
87
|
+
end
|
88
|
+
end
|
89
|
+
end
|
90
|
+
end
|
91
|
+
end
|
@@ -0,0 +1,18 @@
|
|
1
|
+
require 'ox'
|
2
|
+
|
3
|
+
module EndiciaLabelServer
|
4
|
+
module Builders
|
5
|
+
class ChangePassPhraseBuilder < BuilderBase
|
6
|
+
include Ox
|
7
|
+
|
8
|
+
def initialize(opts = {})
|
9
|
+
super 'ChangePassPhraseRequest', opts
|
10
|
+
root[:TokenRequested] = 'false'
|
11
|
+
end
|
12
|
+
|
13
|
+
def post_field
|
14
|
+
'ChangePassPhraseRequestXML'
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
@@ -0,0 +1,24 @@
|
|
1
|
+
require 'ox'
|
2
|
+
|
3
|
+
module EndiciaLabelServer
|
4
|
+
module Builders
|
5
|
+
# The {PostageLabelBuilder} class builds Endicia XML LabelRequest
|
6
|
+
# Objects.
|
7
|
+
#
|
8
|
+
# @author Paul Trippett
|
9
|
+
# @since 0.1.0
|
10
|
+
class PostageLabelBuilder < BuilderBase
|
11
|
+
include Ox
|
12
|
+
|
13
|
+
# Initializes a new {RateBuilder} object
|
14
|
+
#
|
15
|
+
def initialize(opts = {})
|
16
|
+
super 'LabelRequest', opts
|
17
|
+
end
|
18
|
+
|
19
|
+
def post_field
|
20
|
+
'labelRequestXML'
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
@@ -0,0 +1,23 @@
|
|
1
|
+
require 'ox'
|
2
|
+
|
3
|
+
module EndiciaLabelServer
|
4
|
+
module Builders
|
5
|
+
# The {PostageRateBuilder} class builds Endicia XML PostageRate Objects.
|
6
|
+
#
|
7
|
+
# @author Paul Trippett
|
8
|
+
# @since 0.1.0
|
9
|
+
class PostageRateBuilder < BuilderBase
|
10
|
+
include Ox
|
11
|
+
|
12
|
+
# Initializes a new {RateBuilder} object
|
13
|
+
#
|
14
|
+
def initialize(opts = {})
|
15
|
+
super 'PostageRateRequest', opts
|
16
|
+
end
|
17
|
+
|
18
|
+
def post_field
|
19
|
+
'postageRateRequestXML'
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
@@ -0,0 +1,23 @@
|
|
1
|
+
require 'ox'
|
2
|
+
|
3
|
+
module EndiciaLabelServer
|
4
|
+
module Builders
|
5
|
+
# The {PostageRatesBuilder} class builds Endicia XML Rate Objects.
|
6
|
+
#
|
7
|
+
# @author Paul Trippett
|
8
|
+
# @since 0.1.0
|
9
|
+
class PostageRatesBuilder < BuilderBase
|
10
|
+
include Ox
|
11
|
+
|
12
|
+
# Initializes a new {RateBuilder} object
|
13
|
+
#
|
14
|
+
def initialize(opts = {})
|
15
|
+
super 'PostageRatesRequest', opts
|
16
|
+
end
|
17
|
+
|
18
|
+
def post_field
|
19
|
+
'postageRatesRequestXML'
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
@@ -0,0 +1,24 @@
|
|
1
|
+
require 'ox'
|
2
|
+
|
3
|
+
module EndiciaLabelServer
|
4
|
+
module Builders
|
5
|
+
# The {UserSignUpBuilder} class builds Endicia XML Rate Objects.
|
6
|
+
#
|
7
|
+
# @author Paul Trippett
|
8
|
+
# @since 0.1.0
|
9
|
+
class UserSignUpBuilder < BuilderBase
|
10
|
+
include Ox
|
11
|
+
|
12
|
+
# Initializes a new {RateBuilder} object
|
13
|
+
#
|
14
|
+
def initialize(opts = {})
|
15
|
+
super 'UserSignUpRequest', opts
|
16
|
+
root[:TokenRequested] = 'true'
|
17
|
+
end
|
18
|
+
|
19
|
+
def post_field
|
20
|
+
'UserSignUpRequestXML'
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
@@ -0,0 +1,96 @@
|
|
1
|
+
require 'uri'
|
2
|
+
require 'excon'
|
3
|
+
require 'digest/md5'
|
4
|
+
require 'ox'
|
5
|
+
|
6
|
+
module EndiciaLabelServer
|
7
|
+
# The {Connection} class acts as the main entry point to performing rate and
|
8
|
+
# ship operations against the Endicia API.
|
9
|
+
#
|
10
|
+
# @author Paul Trippett
|
11
|
+
# @abstract
|
12
|
+
# @since 0.1.0
|
13
|
+
# @attr [String] url The base url to use either TEST_URL or LIVE_URL
|
14
|
+
class Connection
|
15
|
+
include EndiciaLabelServer::Builders
|
16
|
+
include EndiciaLabelServer::Parsers
|
17
|
+
|
18
|
+
attr_accessor :url
|
19
|
+
|
20
|
+
TEST_URL = 'https://elstestserver.endicia.com'
|
21
|
+
LIVE_URL = 'https://labelserver.endicia.com'
|
22
|
+
ROOT_PATH = '/LabelService/EwsLabelService.asmx/'
|
23
|
+
|
24
|
+
GET_POSTAGE_LABEL_ENDPOINT = 'GetPostageLabelXML'
|
25
|
+
REQUEST_RATE_ENDPOINT = 'CalculatePostageRateXML'
|
26
|
+
REQUEST_RATES_ENDPOINT = 'CalculatePostageRatesXML'
|
27
|
+
GET_USER_SIGNUP_ENDPOINT = 'GetUserSignUpXML'
|
28
|
+
CHANGE_PASS_PHRASE_ENDPOINT = 'ChangePassPhraseXML'
|
29
|
+
|
30
|
+
DEFAULT_PARAMS = {
|
31
|
+
test_mode: false
|
32
|
+
}
|
33
|
+
|
34
|
+
HEADERS = {
|
35
|
+
'Content-Type' => 'application/x-www-form-urlencoded'
|
36
|
+
}
|
37
|
+
|
38
|
+
# Initializes a new {Connection} object
|
39
|
+
#
|
40
|
+
# @param [Hash] params The initialization options
|
41
|
+
# @option params [Boolean] :test_mode If TEST_URL should be used for
|
42
|
+
# requests to the Endicia Label Server URL
|
43
|
+
def initialize(params = {})
|
44
|
+
params = DEFAULT_PARAMS.merge(params)
|
45
|
+
self.url = (params[:test_mode]) ? TEST_URL : LIVE_URL
|
46
|
+
end
|
47
|
+
|
48
|
+
def rate(builder = nil, &block)
|
49
|
+
builder_proxy(builder, REQUEST_RATE_ENDPOINT, PostageRateBuilder,
|
50
|
+
PostageRateParser, block)
|
51
|
+
end
|
52
|
+
|
53
|
+
def rates(builder = nil, &block)
|
54
|
+
builder_proxy(builder, REQUEST_RATES_ENDPOINT, PostageRatesBuilder,
|
55
|
+
PostageRatesParser, block)
|
56
|
+
end
|
57
|
+
|
58
|
+
def get_label(builder = nil, &block)
|
59
|
+
builder_proxy(builder, GET_POSTAGE_LABEL_ENDPOINT, PostageLabelBuilder,
|
60
|
+
PostageLabelParser, block)
|
61
|
+
end
|
62
|
+
|
63
|
+
def sign_up(builder = nil, &block)
|
64
|
+
builder_proxy(builder, GET_USER_SIGNUP_ENDPOINT, UserSignUpBuilder,
|
65
|
+
UserSignUpParser, block)
|
66
|
+
end
|
67
|
+
|
68
|
+
def change_pass_phrase(builder = nil, &block)
|
69
|
+
builder_proxy(builder, CHANGE_PASS_PHRASE_ENDPOINT, ChangePassPhraseBuilder,
|
70
|
+
ChangePassPhraseParser, block)
|
71
|
+
end
|
72
|
+
|
73
|
+
private
|
74
|
+
|
75
|
+
def build_url(endpoint)
|
76
|
+
"#{url}#{ROOT_PATH}#{endpoint}"
|
77
|
+
end
|
78
|
+
|
79
|
+
def get_response_stream(path, body)
|
80
|
+
response = Excon.post(build_url(path), body: body, headers: HEADERS)
|
81
|
+
StringIO.new(response.body)
|
82
|
+
end
|
83
|
+
|
84
|
+
def builder_proxy(builder, path, builder_type, parser, block)
|
85
|
+
if builder.nil? && block
|
86
|
+
builder = builder_type.new
|
87
|
+
block.call builder
|
88
|
+
end
|
89
|
+
|
90
|
+
response = get_response_stream path, builder.to_http_post
|
91
|
+
parser.new.tap do |p|
|
92
|
+
Ox.sax_parse(p, response)
|
93
|
+
end
|
94
|
+
end
|
95
|
+
end
|
96
|
+
end
|
@@ -0,0 +1,20 @@
|
|
1
|
+
module EndiciaLabelServer
|
2
|
+
module Parsers
|
3
|
+
class ChangePassPhraseParser < ParserBase
|
4
|
+
attr_accessor :requester_id, :request_id, :token
|
5
|
+
|
6
|
+
def value(value)
|
7
|
+
super
|
8
|
+
|
9
|
+
string_value = value.as_s
|
10
|
+
if switch_active? :RequesterID
|
11
|
+
self.requester_id = string_value
|
12
|
+
elsif switch_active? :RequestID
|
13
|
+
self.request_id = string_value
|
14
|
+
elsif switch_active? :Token
|
15
|
+
self.token = string_value
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
@@ -0,0 +1,42 @@
|
|
1
|
+
require 'uri'
|
2
|
+
require 'ox'
|
3
|
+
|
4
|
+
module EndiciaLabelServer
|
5
|
+
module Parsers
|
6
|
+
class ParserBase < ::Ox::Sax
|
7
|
+
attr_accessor :switches,
|
8
|
+
:status_code,
|
9
|
+
:error_description
|
10
|
+
|
11
|
+
def initialize
|
12
|
+
self.switches = {}
|
13
|
+
end
|
14
|
+
|
15
|
+
def start_element(name)
|
16
|
+
element_tracker_switch name, true
|
17
|
+
end
|
18
|
+
|
19
|
+
def end_element(name)
|
20
|
+
element_tracker_switch name, false
|
21
|
+
end
|
22
|
+
|
23
|
+
def value(value)
|
24
|
+
string_value = value.as_s
|
25
|
+
self.status_code = string_value if switch_active? :Status
|
26
|
+
self.error_description = string_value if switch_active? :ErrorMessage
|
27
|
+
end
|
28
|
+
|
29
|
+
def element_tracker_switch(element, currently_in)
|
30
|
+
switches[element] = currently_in
|
31
|
+
end
|
32
|
+
|
33
|
+
def switch_active?(*elements)
|
34
|
+
elements.all? { |element| switches[element] == true }
|
35
|
+
end
|
36
|
+
|
37
|
+
def success?
|
38
|
+
['0', 0].include? status_code
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|