simple_shipping 0.4.6
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/.document +5 -0
- data/.metrics +6 -0
- data/.rspec +4 -0
- data/.ruby-gemset +1 -0
- data/.ruby-version +1 -0
- data/.simplecov +43 -0
- data/Gemfile +26 -0
- data/Gemfile.lock +201 -0
- data/LICENSE.txt +21 -0
- data/README.markdown +207 -0
- data/Rakefile +68 -0
- data/VERSION +1 -0
- data/coverage/.resultset.json +1579 -0
- data/lib/colorized_text.rb +34 -0
- data/lib/simple_shipping.rb +27 -0
- data/lib/simple_shipping/abstract.rb +11 -0
- data/lib/simple_shipping/abstract/builder.rb +47 -0
- data/lib/simple_shipping/abstract/client.rb +111 -0
- data/lib/simple_shipping/abstract/model.rb +40 -0
- data/lib/simple_shipping/abstract/request.rb +27 -0
- data/lib/simple_shipping/abstract/response.rb +26 -0
- data/lib/simple_shipping/address.rb +22 -0
- data/lib/simple_shipping/contact.rb +24 -0
- data/lib/simple_shipping/demo.rb +9 -0
- data/lib/simple_shipping/demo/base.rb +71 -0
- data/lib/simple_shipping/demo/fedex.rb +46 -0
- data/lib/simple_shipping/demo/ups.rb +68 -0
- data/lib/simple_shipping/exceptions.rb +40 -0
- data/lib/simple_shipping/fedex.rb +14 -0
- data/lib/simple_shipping/fedex/client.rb +41 -0
- data/lib/simple_shipping/fedex/package_builder.rb +24 -0
- data/lib/simple_shipping/fedex/party_builder.rb +50 -0
- data/lib/simple_shipping/fedex/request.rb +54 -0
- data/lib/simple_shipping/fedex/response.rb +5 -0
- data/lib/simple_shipping/fedex/shipment_builder.rb +123 -0
- data/lib/simple_shipping/fedex/shipment_request.rb +14 -0
- data/lib/simple_shipping/fedex/shipment_response.rb +12 -0
- data/lib/simple_shipping/package.rb +43 -0
- data/lib/simple_shipping/party.rb +21 -0
- data/lib/simple_shipping/shipment.rb +42 -0
- data/lib/simple_shipping/ups.rb +24 -0
- data/lib/simple_shipping/ups/client.rb +46 -0
- data/lib/simple_shipping/ups/package_builder.rb +101 -0
- data/lib/simple_shipping/ups/party_builder.rb +38 -0
- data/lib/simple_shipping/ups/request.rb +27 -0
- data/lib/simple_shipping/ups/response.rb +63 -0
- data/lib/simple_shipping/ups/ship_accept_request.rb +21 -0
- data/lib/simple_shipping/ups/ship_accept_response.rb +6 -0
- data/lib/simple_shipping/ups/ship_client.rb +70 -0
- data/lib/simple_shipping/ups/ship_confirm_request.rb +22 -0
- data/lib/simple_shipping/ups/ship_confirm_response.rb +6 -0
- data/lib/simple_shipping/ups/shipment_builder.rb +66 -0
- data/lib/simple_shipping/ups/shipment_request.rb +22 -0
- data/lib/simple_shipping/ups/shipment_response.rb +6 -0
- data/lib/simple_shipping/ups/void_client.rb +50 -0
- data/lib/simple_shipping/ups/void_request.rb +42 -0
- data/lib/simple_shipping/ups/void_response.rb +6 -0
- data/lib/tasks/demo.rake +58 -0
- data/script/ups_certification.rb +140 -0
- data/simple_shipping.gemspec +168 -0
- data/spec/fixtures/fedex_shipment_request.soap.xml.erb +85 -0
- data/spec/fixtures/fedex_shipment_response.soap.xml.erb +182 -0
- data/spec/fixtures/ups_shipment_request.soap.xml.erb +88 -0
- data/spec/fixtures/ups_shipment_response.soap.xml.erb +58 -0
- data/spec/fixtures/ups_shipment_response_with_faked_label_data.soap.xml.erb +54 -0
- data/spec/fixtures/ups_void_request.soap.xml.erb +29 -0
- data/spec/fixtures/ups_void_response.soap.xml.erb +21 -0
- data/spec/lib/simple_shipping/address_spec.rb +19 -0
- data/spec/lib/simple_shipping/contact_spec.rb +28 -0
- data/spec/lib/simple_shipping/exceptions_spec.rb +58 -0
- data/spec/lib/simple_shipping/fedex/package_builder_spec.rb +5 -0
- data/spec/lib/simple_shipping/fedex/party_builder_spec.rb +5 -0
- data/spec/lib/simple_shipping/fedex/response/shipment_reponse_spec.rb +5 -0
- data/spec/lib/simple_shipping/fedex/response_spec.rb +5 -0
- data/spec/lib/simple_shipping/fedex/shipment_builder_spec.rb +23 -0
- data/spec/lib/simple_shipping/package_spec.rb +32 -0
- data/spec/lib/simple_shipping/party_spec.rb +18 -0
- data/spec/lib/simple_shipping/shipment_spec.rb +35 -0
- data/spec/lib/simple_shipping/ups/package_builder_spec.rb +26 -0
- data/spec/lib/simple_shipping/ups/party_builder_spec.rb +47 -0
- data/spec/lib/simple_shipping/ups/response/shipment_response_spec.rb +5 -0
- data/spec/lib/simple_shipping/ups/response_spec.rb +33 -0
- data/spec/lib/simple_shipping/ups/shipment_builder_spec.rb +19 -0
- data/spec/requests/fedex_spec.rb +47 -0
- data/spec/requests/ups_spec.rb +75 -0
- data/spec/spec_helper.rb +47 -0
- data/spec/support/custom_matchers/basic_matcher.rb +13 -0
- data/spec/support/custom_matchers/have_attribute_matcher.rb +22 -0
- data/spec/support/custom_matchers/have_default_value_matcher.rb +26 -0
- data/spec/support/custom_matchers/have_errors_on_matcher.rb +23 -0
- data/spec/support/custom_matchers/validate_inclusion_of_matcher.rb +37 -0
- data/spec/support/custom_matchers/validate_presence_of_matcher.rb +24 -0
- data/spec/support/custom_matchers/validate_submodel_matcher.rb +44 -0
- data/spec/support/shared_behaviours/builders_behaviour.rb +9 -0
- data/spec/support/shared_behaviours/responses_behaviour.rb +10 -0
- data/tmp/metric_fu/_data/20131210.yml +9964 -0
- data/wsdl/fedex/ship_service_v10.wsdl +5566 -0
- data/wsdl/ups/Ship.wsdl +120 -0
- data/wsdl/ups/Void.wsdl +58 -0
- metadata +308 -0
@@ -0,0 +1,14 @@
|
|
1
|
+
module SimpleShipping::Fedex
|
2
|
+
# The model that represents shipment request to FedEx.
|
3
|
+
class ShipmentRequest < Request
|
4
|
+
def initialize(credentials, shipment)
|
5
|
+
super
|
6
|
+
@type = :process_shipment
|
7
|
+
end
|
8
|
+
|
9
|
+
# :nodoc:
|
10
|
+
def response_class
|
11
|
+
ShipmentResponse
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
@@ -0,0 +1,12 @@
|
|
1
|
+
module SimpleShipping::Fedex
|
2
|
+
# A wrapper for UPS ShipmentResponse.
|
3
|
+
class ShipmentResponse < Response
|
4
|
+
# Get the label as abstract64 encoded data
|
5
|
+
# response.label_image_base64 # => "odGqk/KmgLaawV..."
|
6
|
+
# This can be used directly in an HTML image tag with
|
7
|
+
# src="data:image/gif;base64,..."
|
8
|
+
def label_image_base64
|
9
|
+
value_of(:process_shipment_reply, :completed_shipment_detail, :completed_package_details, :label, :parts, :image)
|
10
|
+
end
|
11
|
+
end
|
12
|
+
end
|
@@ -0,0 +1,43 @@
|
|
1
|
+
module SimpleShipping
|
2
|
+
# Represents a package which should be sent from {SimpleShipping::Party shipper}
|
3
|
+
# to {SimpleShipping::Party recipient}.
|
4
|
+
#
|
5
|
+
# == Attributes:
|
6
|
+
# * _dimenstion_units_ (:in, :cm). Default is :in.
|
7
|
+
# * _weight_units_ (:kg, :lb). Default is :lb.
|
8
|
+
# * _legth_ (in dimension units)
|
9
|
+
# * _width_ (in dimension units)
|
10
|
+
# * _height_ (in dimension units)
|
11
|
+
# * _weight_ (in weight units)
|
12
|
+
# * _packaging_type_
|
13
|
+
#
|
14
|
+
# == Packaging type values:
|
15
|
+
# * :envelope
|
16
|
+
# * :your
|
17
|
+
# * :tube
|
18
|
+
# * :pak
|
19
|
+
# * :box
|
20
|
+
# * :box_10kg
|
21
|
+
# * :box_25kg
|
22
|
+
class Package < Abstract::Model
|
23
|
+
attr_accessor :length, :width, :height, :dimension_units
|
24
|
+
attr_accessor :weight, :weight_units, :packaging_type
|
25
|
+
attr_accessor :insured_value, :declared_value
|
26
|
+
|
27
|
+
validates_presence_of :length, :width, :height, :dimension_units, :if => :custom_package?
|
28
|
+
validates_presence_of :weight, :weight_units
|
29
|
+
|
30
|
+
validates_inclusion_of :weight_units , :in => [:kg, :lb]
|
31
|
+
validates_inclusion_of :dimension_units, :in => [:in, :cm], :if => :custom_package?
|
32
|
+
validates_inclusion_of :packaging_type , :in => [:envelope, :pak, :tube, :your, :box, :box_10kg, :box_25kg]
|
33
|
+
|
34
|
+
set_default_values :packaging_type => :your,
|
35
|
+
:weight_units => :lb,
|
36
|
+
:dimension_units => :in
|
37
|
+
|
38
|
+
# Whether the package is a custom package.
|
39
|
+
def custom_package?
|
40
|
+
packaging_type == :your
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
@@ -0,0 +1,21 @@
|
|
1
|
+
module SimpleShipping
|
2
|
+
# Party is a person or company who takes a part in shipment process.
|
3
|
+
# Party is used to represent a shipper or a recipient.
|
4
|
+
#
|
5
|
+
# == Attributes
|
6
|
+
# * _contact_ (instance of {SimpleShipping::Contact})
|
7
|
+
# * _address_ (instance of {SimpleShipping::Address})
|
8
|
+
# * _account_number_ (optional, but in some cases required)
|
9
|
+
#
|
10
|
+
# If one of attributes is missed an appropriate exception will be raised
|
11
|
+
# when you build a request.
|
12
|
+
class Party < Abstract::Model
|
13
|
+
attr_accessor :contact,
|
14
|
+
:address,
|
15
|
+
:account_number
|
16
|
+
|
17
|
+
validates_presence_of :contact, :address
|
18
|
+
validates_submodel :address, :as => SimpleShipping::Address
|
19
|
+
validates_submodel :contact, :as => SimpleShipping::Contact
|
20
|
+
end
|
21
|
+
end
|
@@ -0,0 +1,42 @@
|
|
1
|
+
module SimpleShipping
|
2
|
+
# Represents a shipment.
|
3
|
+
#
|
4
|
+
# == Attributes:
|
5
|
+
# * _shipper_ (an instance of {SimpleShipping::Party}
|
6
|
+
# * _recipient_ (an instance of {SimpleShipping::Party}
|
7
|
+
# * _package_ (an instance of {SimpleShipping::Package}
|
8
|
+
# * _payor_ (:shipper, :recipient). Default value is :shipper
|
9
|
+
class Shipment < Abstract::Model
|
10
|
+
attr_accessor :shipper,
|
11
|
+
:recipient,
|
12
|
+
:package,
|
13
|
+
:payor
|
14
|
+
|
15
|
+
set_default_values :payor => :shipper
|
16
|
+
|
17
|
+
validates_presence_of :shipper, :recipient, :package, :payor
|
18
|
+
validates_inclusion_of :payor, :in => [:shipper, :recipient]
|
19
|
+
validates_submodel :shipper , :as => SimpleShipping::Party
|
20
|
+
validates_submodel :recipient, :as => SimpleShipping::Party
|
21
|
+
validates_submodel :package , :as => SimpleShipping::Package
|
22
|
+
validate :validate_payor_account_number
|
23
|
+
|
24
|
+
# Account number of payor.
|
25
|
+
def payor_account_number
|
26
|
+
case payor
|
27
|
+
when :shipper
|
28
|
+
shipper.account_number if shipper.respond_to?(:account_number)
|
29
|
+
when :recipient
|
30
|
+
recipient.account_number if recipient.respond_to?(:account_number)
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
# Validate presence of payor account number.
|
35
|
+
#
|
36
|
+
# @return [void]
|
37
|
+
def validate_payor_account_number
|
38
|
+
errors.add(:abstract, "Payor account number is missing") unless payor_account_number
|
39
|
+
end
|
40
|
+
private :validate_payor_account_number
|
41
|
+
end
|
42
|
+
end
|
@@ -0,0 +1,24 @@
|
|
1
|
+
# Namespace for UPS provider.
|
2
|
+
module SimpleShipping::Ups
|
3
|
+
extend ActiveSupport::Autoload
|
4
|
+
|
5
|
+
autoload :Client
|
6
|
+
autoload :ShipClient
|
7
|
+
autoload :VoidClient
|
8
|
+
|
9
|
+
autoload :Request
|
10
|
+
autoload :Response
|
11
|
+
autoload :PackageBuilder
|
12
|
+
autoload :PartyBuilder
|
13
|
+
autoload :ShipmentBuilder
|
14
|
+
|
15
|
+
autoload :ShipConfirmResponse
|
16
|
+
autoload :ShipAcceptResponse
|
17
|
+
autoload :ShipmentResponse
|
18
|
+
autoload :VoidResponse
|
19
|
+
|
20
|
+
autoload :ShipConfirmRequest
|
21
|
+
autoload :ShipAcceptRequest
|
22
|
+
autoload :ShipmentRequest
|
23
|
+
autoload :VoidRequest
|
24
|
+
end
|
@@ -0,0 +1,46 @@
|
|
1
|
+
module SimpleShipping::Ups
|
2
|
+
# Abstract class for all UPS clients.
|
3
|
+
# The problem with UPS is that its WSDL imports schemas. However schema imports are not supported
|
4
|
+
# by Savon as by v.2.1.0. See: https://github.com/savonrb/wasabi/issues/1
|
5
|
+
# Because of this we have to manually:
|
6
|
+
# 1. Assign additional namespaces
|
7
|
+
# 2. Switch to :qualified :elemen_form_default
|
8
|
+
# (to have all requests elements prepended with namespace
|
9
|
+
# if its namespace is not specified explicitly)
|
10
|
+
# 3. Explicitly prepend namespace to all elements which not belong to WSDL target namespace
|
11
|
+
# i.e. UPSSecurity, Request/RequestOptions etc
|
12
|
+
#
|
13
|
+
class Client < SimpleShipping::Abstract::Client
|
14
|
+
|
15
|
+
# @param [Hash] options Savon client options
|
16
|
+
def client_options(options = {})
|
17
|
+
super.deep_merge(
|
18
|
+
:element_form_default => :qualified,
|
19
|
+
:namespaces => {
|
20
|
+
'xmlns:upss' => "http://www.ups.com/XMLSchema/XOLTWS/UPSS/v1.0",
|
21
|
+
'xmlns:common' => "http://www.ups.com/XMLSchema/XOLTWS/Common/v1.0",
|
22
|
+
},
|
23
|
+
:soap_header => soap_header
|
24
|
+
)
|
25
|
+
end
|
26
|
+
protected :client_options
|
27
|
+
|
28
|
+
# @return [Hash] of SOAP envelope header contents
|
29
|
+
def soap_header
|
30
|
+
{
|
31
|
+
'upss:UPSSecurity' => {
|
32
|
+
'upss:UsernameToken' => {
|
33
|
+
'upss:Username' => @credentials.username,
|
34
|
+
'upss:Password' => @credentials.password,
|
35
|
+
:order! => ['upss:Username', 'upss:Password']
|
36
|
+
},
|
37
|
+
'upss:ServiceAccessToken' => {
|
38
|
+
'upss:AccessLicenseNumber' => @credentials.access_license_number
|
39
|
+
},
|
40
|
+
:order! => ['upss:UsernameToken', 'upss:ServiceAccessToken']
|
41
|
+
}
|
42
|
+
}
|
43
|
+
end
|
44
|
+
protected :soap_header
|
45
|
+
end
|
46
|
+
end
|
@@ -0,0 +1,101 @@
|
|
1
|
+
# Builds hash for Savon which represents {Package package}.
|
2
|
+
module SimpleShipping::Ups
|
3
|
+
# Builds hash structure for Savon that represents package element in UPS's API.
|
4
|
+
class PackageBuilder < SimpleShipping::Abstract::Builder
|
5
|
+
# Mapping for UPS packaging types
|
6
|
+
# Not all UPS values listed here in order to provide common interface with FedEx.
|
7
|
+
PACKAGING_TYPES = {
|
8
|
+
:envelope => '01', # letter
|
9
|
+
:your => '02', # customer supplied
|
10
|
+
:tube => '03', # tube
|
11
|
+
:pak => '04', # UPS Packaging
|
12
|
+
:box => '2b', # medium box
|
13
|
+
:box_10kg => '25',
|
14
|
+
:box_10kg => '24'
|
15
|
+
}
|
16
|
+
|
17
|
+
# Mapping for UPS weight units.
|
18
|
+
WEIGHT_UNITS = {
|
19
|
+
:kg => 'KGS',
|
20
|
+
:lb => 'LBS'
|
21
|
+
}
|
22
|
+
|
23
|
+
# Mapping for UPS dimension units.
|
24
|
+
DIMENSION_UNITS = {
|
25
|
+
:in => 'IN',
|
26
|
+
:cm => 'CM'
|
27
|
+
}
|
28
|
+
|
29
|
+
# Custom package order.
|
30
|
+
CUSTOM_PACKAGE_ORDER = %w(Packaging PackageServiceOptions Dimensions PackageWeight)
|
31
|
+
|
32
|
+
# Standard package order.
|
33
|
+
STANDARD_PACKAGE_ORDER = %w(Packaging PackageServiceOptions PackageWeight)
|
34
|
+
|
35
|
+
# Build basic skeleton for package element. It can be customized by
|
36
|
+
# overriding some subelements.
|
37
|
+
#
|
38
|
+
# @return [Hash]
|
39
|
+
def base_package
|
40
|
+
base = {
|
41
|
+
'Packaging' => {
|
42
|
+
'Code' => PACKAGING_TYPES[@model.packaging_type]
|
43
|
+
},
|
44
|
+
'PackageWeight' => {
|
45
|
+
'UnitOfMeasurement' => {
|
46
|
+
'Code' => WEIGHT_UNITS[@model.weight_units]
|
47
|
+
},
|
48
|
+
'Weight' => @model.weight,
|
49
|
+
:order! => ['UnitOfMeasurement', 'Weight']
|
50
|
+
},
|
51
|
+
'PackageServiceOptions' => {}
|
52
|
+
}
|
53
|
+
|
54
|
+
if @model.insured_value
|
55
|
+
base['PackageServiceOptions']['InsuredValue'] = {
|
56
|
+
'CurrencyCode' => 'USD',
|
57
|
+
'MonetaryValue' => @model.insured_value
|
58
|
+
}
|
59
|
+
end
|
60
|
+
|
61
|
+
if @model.declared_value
|
62
|
+
base['PackageServiceOptions']['DeclaredValue'] = {
|
63
|
+
'CurrencyCode' => 'USD',
|
64
|
+
'MonetaryValue' => @model.declared_value
|
65
|
+
}
|
66
|
+
end
|
67
|
+
|
68
|
+
base
|
69
|
+
end
|
70
|
+
|
71
|
+
# Build a hash from a custom {Package package} which will be used by Savon.
|
72
|
+
# A custom package requires specification of LWH dimensions.
|
73
|
+
def custom_package
|
74
|
+
base_package.tap do |package|
|
75
|
+
package['Dimensions'] = {
|
76
|
+
'UnitOfMeasurement' => {
|
77
|
+
'Code' => DIMENSION_UNITS[@model.dimension_units].clone
|
78
|
+
},
|
79
|
+
'Length' => @model.length,
|
80
|
+
'Width' => @model.width,
|
81
|
+
'Height' => @model.height,
|
82
|
+
:order! => ['UnitOfMeasurement', 'Length', 'Width', 'Height']
|
83
|
+
}
|
84
|
+
package[:order!] = CUSTOM_PACKAGE_ORDER.clone
|
85
|
+
end
|
86
|
+
end
|
87
|
+
|
88
|
+
# Build a hash from a standard {Package package} which will be used by Savon.
|
89
|
+
# A standard package requires no specification of LWH dimensions.
|
90
|
+
def standard_package
|
91
|
+
base_package.tap do |package|
|
92
|
+
package[:order!] = STANDARD_PACKAGE_ORDER.clone
|
93
|
+
end
|
94
|
+
end
|
95
|
+
|
96
|
+
# Build the package, whether custom or standard.
|
97
|
+
def build
|
98
|
+
@model.custom_package? ? custom_package : standard_package
|
99
|
+
end
|
100
|
+
end
|
101
|
+
end
|
@@ -0,0 +1,38 @@
|
|
1
|
+
module SimpleShipping::Ups
|
2
|
+
# Knows how to convert {Party} model to SOAP element for UPS.
|
3
|
+
class PartyBuilder < SimpleShipping::Abstract::Builder
|
4
|
+
# Builds a hash for Savon which represents {Party party}.
|
5
|
+
def build
|
6
|
+
contact = @model.contact
|
7
|
+
{'Name' => (contact.person_name || contact.company_name),
|
8
|
+
'Phone' => {'Number' => contact.phone_number},
|
9
|
+
'ShipperNumber' => @model.account_number,
|
10
|
+
'Address' => build_address,
|
11
|
+
:order! => ['Name', 'Phone', 'ShipperNumber', 'Address']
|
12
|
+
}
|
13
|
+
end
|
14
|
+
|
15
|
+
# Build address element.
|
16
|
+
#
|
17
|
+
# @return [Hash]
|
18
|
+
def build_address
|
19
|
+
addr = @model.address
|
20
|
+
{'AddressLine' => [addr.street_line, addr.street_line_2, addr.street_line_3].compact,
|
21
|
+
'City' => addr.city,
|
22
|
+
'StateProvinceCode' => addr.state_code,
|
23
|
+
'PostalCode' => addr.postal_code,
|
24
|
+
'CountryCode' => addr.country_code,
|
25
|
+
:order! => ['AddressLine', 'City', 'StateProvinceCode', 'PostalCode', 'CountryCode']
|
26
|
+
}
|
27
|
+
end
|
28
|
+
|
29
|
+
# Validate presence of account_number.
|
30
|
+
#
|
31
|
+
# @return [void]
|
32
|
+
def validate
|
33
|
+
if @opts[:shipper] && !@model.account_number
|
34
|
+
raise SimpleShipping::ValidationError.new("account_number is required for party who is shipper")
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
@@ -0,0 +1,27 @@
|
|
1
|
+
module SimpleShipping::Ups
|
2
|
+
# Builds complete request for UPS
|
3
|
+
class Request < SimpleShipping::Abstract::Request
|
4
|
+
# Value for <common:RequestOption> XML element in request.
|
5
|
+
REQUEST_OPTION = 'nonvalidate'
|
6
|
+
|
7
|
+
# Define label parameters according to UPS's API.
|
8
|
+
#
|
9
|
+
# @return [Hash]
|
10
|
+
def label_specification
|
11
|
+
{ 'LabelImageFormat' => {'Code' => 'GIF'},
|
12
|
+
'LabelStockSize' => {
|
13
|
+
'Height' => '6',
|
14
|
+
'Width' => '4',
|
15
|
+
:order! => ['Height', 'Width']
|
16
|
+
},
|
17
|
+
:order! => ['LabelImageFormat', 'LabelStockSize']
|
18
|
+
}
|
19
|
+
end
|
20
|
+
|
21
|
+
# The class of the response in the same name space.
|
22
|
+
def response_class
|
23
|
+
self.class.name.sub(/Request/, 'Response').constantize
|
24
|
+
end
|
25
|
+
private :response_class
|
26
|
+
end
|
27
|
+
end
|
@@ -0,0 +1,63 @@
|
|
1
|
+
module SimpleShipping::Ups
|
2
|
+
# Response from UPS.
|
3
|
+
class Response < SimpleShipping::Abstract::Response
|
4
|
+
# Digest what can be used to get a label.
|
5
|
+
#
|
6
|
+
# @return [String]
|
7
|
+
def digest
|
8
|
+
value_of(:shipment_results, :shipment_digest)
|
9
|
+
end
|
10
|
+
|
11
|
+
# Unique shipment ID returned by UPS.
|
12
|
+
#
|
13
|
+
# @return [Strig]
|
14
|
+
def shipment_identification_number
|
15
|
+
value_of(:shipment_results, :shipment_identification_number)
|
16
|
+
end
|
17
|
+
|
18
|
+
# Get package tracking number to look for delivery process on UPS site.
|
19
|
+
#
|
20
|
+
# @return [String] tracking number
|
21
|
+
def tracking_number
|
22
|
+
value_of(:shipment_results, :package_results, :tracking_number)
|
23
|
+
end
|
24
|
+
|
25
|
+
# Get the label as base64 encoded data
|
26
|
+
# response.label_image_base64 # => "odGqk/KmgLaawV..."
|
27
|
+
# This can be used directly in an HTML image tag with
|
28
|
+
# src="data:image/gif;base64,..."
|
29
|
+
def label_image_base64
|
30
|
+
value_of(:shipment_results, :package_results, :shipping_label, :graphic_image)
|
31
|
+
end
|
32
|
+
|
33
|
+
# Label image.
|
34
|
+
#
|
35
|
+
# @return [String] binary
|
36
|
+
def label_html
|
37
|
+
value = value_of(:shipment_results, :package_results, :shipping_label, :html_image)
|
38
|
+
Base64.decode64(value) if value
|
39
|
+
end
|
40
|
+
|
41
|
+
# Receipt.
|
42
|
+
#
|
43
|
+
# @return [String] binary
|
44
|
+
def receipt_html
|
45
|
+
value = value_of(:shipment_results, :control_log_receipt, :graphic_image)
|
46
|
+
Base64.decode64(value) if value
|
47
|
+
end
|
48
|
+
|
49
|
+
# Fetch the value of an XML attribute at the path specified as an array
|
50
|
+
# of node names but appends the implicit namespace on to the front of the
|
51
|
+
# path.
|
52
|
+
def value_of(*path)
|
53
|
+
super(*path.unshift(name_token))
|
54
|
+
end
|
55
|
+
|
56
|
+
# All UPS requests are namespaced within the same name of the class by
|
57
|
+
# convention.
|
58
|
+
def name_token
|
59
|
+
self.class.name.split('::').last.underscore.to_sym
|
60
|
+
end
|
61
|
+
private :name_token
|
62
|
+
end
|
63
|
+
end
|