reactive_shipping 3.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 +7 -0
- data/.gitignore +15 -0
- data/.travis.yml +33 -0
- data/.yardopts +13 -0
- data/CHANGELOG.md +225 -0
- data/CONTRIBUTING.md +23 -0
- data/Gemfile +3 -0
- data/MIT-LICENSE +21 -0
- data/README.md +158 -0
- data/Rakefile +35 -0
- data/dev.yml +17 -0
- data/gemfiles/activesupport42.gemfile +5 -0
- data/gemfiles/activesupport50.gemfile +6 -0
- data/gemfiles/activesupport51.gemfile +5 -0
- data/gemfiles/activesupport52.gemfile +5 -0
- data/gemfiles/activesupport_master.gemfile +5 -0
- data/lib/certs/eParcel.dtd +111 -0
- data/lib/reactive_shipping.rb +26 -0
- data/lib/reactive_shipping/address_validation_response.rb +30 -0
- data/lib/reactive_shipping/carrier.rb +184 -0
- data/lib/reactive_shipping/carriers.rb +35 -0
- data/lib/reactive_shipping/carriers/australia_post.rb +248 -0
- data/lib/reactive_shipping/carriers/benchmark_carrier.rb +31 -0
- data/lib/reactive_shipping/carriers/bogus_carrier.rb +12 -0
- data/lib/reactive_shipping/carriers/canada_post.rb +263 -0
- data/lib/reactive_shipping/carriers/canada_post_pws.rb +908 -0
- data/lib/reactive_shipping/carriers/fedex.rb +797 -0
- data/lib/reactive_shipping/carriers/kunaki.rb +155 -0
- data/lib/reactive_shipping/carriers/new_zealand_post.rb +260 -0
- data/lib/reactive_shipping/carriers/shipwire.rb +178 -0
- data/lib/reactive_shipping/carriers/stamps.rb +860 -0
- data/lib/reactive_shipping/carriers/ups.rb +1060 -0
- data/lib/reactive_shipping/carriers/usps.rb +708 -0
- data/lib/reactive_shipping/carriers/usps_returns.rb +86 -0
- data/lib/reactive_shipping/delivery_date_estimate.rb +20 -0
- data/lib/reactive_shipping/delivery_date_estimates_response.rb +11 -0
- data/lib/reactive_shipping/errors.rb +35 -0
- data/lib/reactive_shipping/external_return_label_request.rb +417 -0
- data/lib/reactive_shipping/external_return_label_response.rb +26 -0
- data/lib/reactive_shipping/label.rb +10 -0
- data/lib/reactive_shipping/label_response.rb +10 -0
- data/lib/reactive_shipping/location.rb +166 -0
- data/lib/reactive_shipping/package.rb +165 -0
- data/lib/reactive_shipping/package_item.rb +60 -0
- data/lib/reactive_shipping/rate_estimate.rb +197 -0
- data/lib/reactive_shipping/rate_response.rb +33 -0
- data/lib/reactive_shipping/response.rb +44 -0
- data/lib/reactive_shipping/shipment_event.rb +22 -0
- data/lib/reactive_shipping/shipment_packer.rb +108 -0
- data/lib/reactive_shipping/shipping_response.rb +34 -0
- data/lib/reactive_shipping/tracking_response.rb +120 -0
- data/lib/reactive_shipping/version.rb +3 -0
- data/reactive_shipping.gemspec +38 -0
- data/shipit.rubygems.yml +1 -0
- data/test/console.rb +39 -0
- data/test/credentials.yml +76 -0
- data/test/fixtures/files/label1.pdf +0 -0
- data/test/fixtures/files/ups-shipping-label.gif +0 -0
- data/test/fixtures/json/australia_post/calculate_domestic.json +13 -0
- data/test/fixtures/json/australia_post/calculate_domestic_2.json +19 -0
- data/test/fixtures/json/australia_post/calculate_international.json +12 -0
- data/test/fixtures/json/australia_post/calculate_international_2.json +15 -0
- data/test/fixtures/json/australia_post/error_message.json +5 -0
- data/test/fixtures/json/australia_post/service_domestic.json +117 -0
- data/test/fixtures/json/australia_post/service_domestic_2.json +117 -0
- data/test/fixtures/json/australia_post/service_international.json +76 -0
- data/test/fixtures/json/australia_post/service_international_2.json +59 -0
- data/test/fixtures/json/newzealandpost/domestic_book.json +1 -0
- data/test/fixtures/json/newzealandpost/domestic_default.json +1 -0
- data/test/fixtures/json/newzealandpost/domestic_error.json +1 -0
- data/test/fixtures/json/newzealandpost/domestic_poster.json +1 -0
- data/test/fixtures/json/newzealandpost/domestic_small_half_pound.json +1 -0
- data/test/fixtures/json/newzealandpost/international_book.json +1 -0
- data/test/fixtures/json/newzealandpost/international_new_zealand_wii.json +1 -0
- data/test/fixtures/json/newzealandpost/international_small_half_pound.json +1 -0
- data/test/fixtures/json/newzealandpost/international_wii.json +1 -0
- data/test/fixtures/xml/canadapost/example_request.xml +25 -0
- data/test/fixtures/xml/canadapost/example_response.xml +130 -0
- data/test/fixtures/xml/canadapost/example_response_error.xml +16 -0
- data/test/fixtures/xml/canadapost/example_response_french.xml +122 -0
- data/test/fixtures/xml/canadapost/example_response_with_nil_value.xml +164 -0
- data/test/fixtures/xml/canadapost/example_response_with_postal_outlet.xml +155 -0
- data/test/fixtures/xml/canadapost/example_response_with_postal_outlet_french.xml +274 -0
- data/test/fixtures/xml/canadapost/example_response_with_strange_delivery_date.xml +130 -0
- data/test/fixtures/xml/canadapost_pws/dnc_tracking_details_en.xml +112 -0
- data/test/fixtures/xml/canadapost_pws/merchant_details_error.xml +7 -0
- data/test/fixtures/xml/canadapost_pws/merchant_details_response.xml +7 -0
- data/test/fixtures/xml/canadapost_pws/option_response.xml +13 -0
- data/test/fixtures/xml/canadapost_pws/option_response_no_conflicts.xml +7 -0
- data/test/fixtures/xml/canadapost_pws/rates_info.xml +190 -0
- data/test/fixtures/xml/canadapost_pws/rates_info_error.xml +7 -0
- data/test/fixtures/xml/canadapost_pws/receipt_response.xml +42 -0
- data/test/fixtures/xml/canadapost_pws/receipt_response_no_priced_options.xml +36 -0
- data/test/fixtures/xml/canadapost_pws/register_token_error.xml +7 -0
- data/test/fixtures/xml/canadapost_pws/register_token_response.xml +3 -0
- data/test/fixtures/xml/canadapost_pws/service_options_response.xml +42 -0
- data/test/fixtures/xml/canadapost_pws/services_error.xml +6 -0
- data/test/fixtures/xml/canadapost_pws/services_response.xml +32 -0
- data/test/fixtures/xml/canadapost_pws/shipment_domestic.xml +69 -0
- data/test/fixtures/xml/canadapost_pws/shipment_response.xml +20 -0
- data/test/fixtures/xml/canadapost_pws/shipment_us.xml +69 -0
- data/test/fixtures/xml/canadapost_pws/tracking_details_en.xml +152 -0
- data/test/fixtures/xml/canadapost_pws/tracking_details_en_error.xml +7 -0
- data/test/fixtures/xml/canadapost_pws/tracking_details_en_undelivered.xml +116 -0
- data/test/fixtures/xml/canadapost_pws/tracking_details_fr.xml +156 -0
- data/test/fixtures/xml/canadapost_pws/tracking_details_no_expected_delivery_date.xml +40 -0
- data/test/fixtures/xml/fedex/create_shipment_response.xml +2 -0
- data/test/fixtures/xml/fedex/freight_rate_request.xml +82 -0
- data/test/fixtures/xml/fedex/freight_rate_response.xml +506 -0
- data/test/fixtures/xml/fedex/invalid_fedex_reply.xml +27 -0
- data/test/fixtures/xml/fedex/ottawa_to_beverly_hills_commercial_rate_request.xml +79 -0
- data/test/fixtures/xml/fedex/ottawa_to_beverly_hills_no_saturday_rate_request.xml +79 -0
- data/test/fixtures/xml/fedex/ottawa_to_beverly_hills_rate_request.xml +80 -0
- data/test/fixtures/xml/fedex/ottawa_to_beverly_hills_rate_response.xml +214 -0
- data/test/fixtures/xml/fedex/raterequest_reply.xml +213 -0
- data/test/fixtures/xml/fedex/raterequest_response_with_ground_home_delivery.xml +206 -0
- data/test/fixtures/xml/fedex/reply_without_notifications.xml +185 -0
- data/test/fixtures/xml/fedex/tracking_request.xml +29 -0
- data/test/fixtures/xml/fedex/tracking_response_bad_tracking_number.xml +20 -0
- data/test/fixtures/xml/fedex/tracking_response_delivered_at_door.xml +254 -0
- data/test/fixtures/xml/fedex/tracking_response_delivered_at_facility.xml +403 -0
- data/test/fixtures/xml/fedex/tracking_response_delivered_with_signature.xml +269 -0
- data/test/fixtures/xml/fedex/tracking_response_empty_status_detail.xml +84 -0
- data/test/fixtures/xml/fedex/tracking_response_failure_code_9045.xml +52 -0
- data/test/fixtures/xml/fedex/tracking_response_failure_code_9080.xml +51 -0
- data/test/fixtures/xml/fedex/tracking_response_in_transit.xml +127 -0
- data/test/fixtures/xml/fedex/tracking_response_invalid_tracking_number.xml +52 -0
- data/test/fixtures/xml/fedex/tracking_response_missing_status_code.xml +89 -0
- data/test/fixtures/xml/fedex/tracking_response_multiple_results.xml +100 -0
- data/test/fixtures/xml/fedex/tracking_response_not_found.xml +52 -0
- data/test/fixtures/xml/fedex/tracking_response_shipment_exception.xml +209 -0
- data/test/fixtures/xml/fedex/tracking_response_unable_to_process.xml +32 -0
- data/test/fixtures/xml/fedex/tracking_response_with_blank_state.xml +107 -0
- data/test/fixtures/xml/fedex/unknown_fedex_document_reply.xml +3 -0
- data/test/fixtures/xml/kunaki/invalid_state_response.xml +3 -0
- data/test/fixtures/xml/kunaki/no_valid_items_response.xml +3 -0
- data/test/fixtures/xml/kunaki/successful_rates_response.xml +3 -0
- data/test/fixtures/xml/kunaki/unsuccessful_rates_response.xml +9 -0
- data/test/fixtures/xml/shipwire/international_rates_response.xml +17 -0
- data/test/fixtures/xml/shipwire/new_carrier_rate_response.xml +18 -0
- data/test/fixtures/xml/shipwire/no_rates_response.xml +7 -0
- data/test/fixtures/xml/shipwire/rates_response.xml +36 -0
- data/test/fixtures/xml/shipwire/rates_response_no_estimate.xml +14 -0
- data/test/fixtures/xml/stamps/authenticate_user_request.xml +15 -0
- data/test/fixtures/xml/stamps/authenticate_user_response.xml +10 -0
- data/test/fixtures/xml/stamps/cleanse_address_request.xml +19 -0
- data/test/fixtures/xml/stamps/cleanse_address_response.xml +27 -0
- data/test/fixtures/xml/stamps/create_indicium_request.xml +69 -0
- data/test/fixtures/xml/stamps/create_indicium_response.xml +40 -0
- data/test/fixtures/xml/stamps/expired_authenticator_response.xml +15 -0
- data/test/fixtures/xml/stamps/get_account_info_request.xml +11 -0
- data/test/fixtures/xml/stamps/get_account_info_response.xml +36 -0
- data/test/fixtures/xml/stamps/get_purchase_status_request.xml +12 -0
- data/test/fixtures/xml/stamps/get_purchase_status_response.xml +16 -0
- data/test/fixtures/xml/stamps/get_rates_request.xml +19 -0
- data/test/fixtures/xml/stamps/get_rates_response.xml +351 -0
- data/test/fixtures/xml/stamps/purchase_postage_request.xml +13 -0
- data/test/fixtures/xml/stamps/purchase_postage_response.xml +17 -0
- data/test/fixtures/xml/stamps/track_shipment_request.xml +12 -0
- data/test/fixtures/xml/stamps/track_shipment_response.xml +45 -0
- data/test/fixtures/xml/ups/access_request.xml +6 -0
- data/test/fixtures/xml/ups/delivered_shipment_with_refund.xml +290 -0
- data/test/fixtures/xml/ups/delivered_shipment_without_events_tracking_response.xml +62 -0
- data/test/fixtures/xml/ups/delivery_dates_response.xml +140 -0
- data/test/fixtures/xml/ups/example_tracking_response.xml +53 -0
- data/test/fixtures/xml/ups/in_transit_shipment.xml +183 -0
- data/test/fixtures/xml/ups/out_for_delivery_shipment.xml +165 -0
- data/test/fixtures/xml/ups/package_exceeds_maximum_length.xml +12 -0
- data/test/fixtures/xml/ups/rate_single_service.xml +54 -0
- data/test/fixtures/xml/ups/rescheduled_shipment.xml +204 -0
- data/test/fixtures/xml/ups/shipment_accept_response.xml +42 -0
- data/test/fixtures/xml/ups/shipment_confirm_response.xml +33 -0
- data/test/fixtures/xml/ups/shipment_from_tiger_direct.xml +222 -0
- data/test/fixtures/xml/ups/test_real_home_as_residential_destination_response.xml +290 -0
- data/test/fixtures/xml/ups/test_real_home_as_residential_destination_response_with_insured.xml +289 -0
- data/test/fixtures/xml/ups/test_real_home_as_residential_destination_with_origin_account_response.xml +311 -0
- data/test/fixtures/xml/ups/tracking_request.xml +9 -0
- data/test/fixtures/xml/ups/triple_accept_response.xml +72 -0
- data/test/fixtures/xml/ups/triple_confirm_response.xml +32 -0
- data/test/fixtures/xml/ups/void_shipment_response.xml +11 -0
- data/test/fixtures/xml/usps/api_error_rate_response.xml +53 -0
- data/test/fixtures/xml/usps/beverly_hills_to_new_york_book_commercial_base_rate_response.xml +2 -0
- data/test/fixtures/xml/usps/beverly_hills_to_new_york_book_commercial_plus_rate_response.xml +258 -0
- data/test/fixtures/xml/usps/beverly_hills_to_new_york_book_rate_response.xml +108 -0
- data/test/fixtures/xml/usps/beverly_hills_to_ottawa_american_wii_commercial_base_rate_response.xml +84 -0
- data/test/fixtures/xml/usps/beverly_hills_to_ottawa_american_wii_commercial_plus_rate_response.xml +212 -0
- data/test/fixtures/xml/usps/beverly_hills_to_ottawa_american_wii_rate_response.xml +230 -0
- data/test/fixtures/xml/usps/first_class_packages_with_invalid_mail_type_response.xml +12 -0
- data/test/fixtures/xml/usps/first_class_packages_with_mail_type_response.xml +16 -0
- data/test/fixtures/xml/usps/first_class_packages_without_mail_type_response.xml +12 -0
- data/test/fixtures/xml/usps/invalid_xml_response.xml +10 -0
- data/test/fixtures/xml/usps/invalid_xml_tracking_response_error.xml +2 -0
- data/test/fixtures/xml/usps/tracking_request.xml +10 -0
- data/test/fixtures/xml/usps/tracking_request_batch.xml +12 -0
- data/test/fixtures/xml/usps/tracking_response.xml +162 -0
- data/test/fixtures/xml/usps/tracking_response_alt.xml +53 -0
- data/test/fixtures/xml/usps/tracking_response_batch.xml +231 -0
- data/test/fixtures/xml/usps/tracking_response_failure.xml +11 -0
- data/test/fixtures/xml/usps/tracking_response_not_available.xml +12 -0
- data/test/fixtures/xml/usps/tracking_response_test_error.xml +8 -0
- data/test/fixtures/xml/usps/us_rate_request.xml +18 -0
- data/test/fixtures/xml/usps/us_rate_request_large.xml +18 -0
- data/test/fixtures/xml/usps/world_rate_request_only_country.xml +22 -0
- data/test/fixtures/xml/usps/world_rate_request_with_value.xml +24 -0
- data/test/fixtures/xml/usps/world_rate_request_without_value.xml +24 -0
- data/test/fixtures/xml/usps_returns/external_return_label_response.xml +2 -0
- data/test/fixtures/xml/usps_returns/external_return_label_response_failure.xml +10 -0
- data/test/remote/australia_post_test.rb +140 -0
- data/test/remote/canada_post_pws_platform_test.rb +259 -0
- data/test/remote/canada_post_pws_test.rb +169 -0
- data/test/remote/canada_post_test.rb +55 -0
- data/test/remote/fedex_test.rb +400 -0
- data/test/remote/kunaki_test.rb +37 -0
- data/test/remote/new_zealand_post_test.rb +149 -0
- data/test/remote/shipwire_test.rb +84 -0
- data/test/remote/stamps_test.rb +396 -0
- data/test/remote/usps_returns_test.rb +72 -0
- data/test/remote/usps_test.rb +243 -0
- data/test/test_helper.rb +296 -0
- data/test/unit/carrier_test.rb +130 -0
- data/test/unit/carriers/australia_post_test.rb +181 -0
- data/test/unit/carriers/benchmark_test.rb +18 -0
- data/test/unit/carriers/canada_post_pws_rating_test.rb +379 -0
- data/test/unit/carriers/canada_post_pws_register_test.rb +76 -0
- data/test/unit/carriers/canada_post_pws_shipping_test.rb +258 -0
- data/test/unit/carriers/canada_post_pws_test.rb +59 -0
- data/test/unit/carriers/canada_post_pws_tracking_test.rb +154 -0
- data/test/unit/carriers/canada_post_test.rb +148 -0
- data/test/unit/carriers/fedex_test.rb +693 -0
- data/test/unit/carriers/kunaki_test.rb +56 -0
- data/test/unit/carriers/new_zealand_post_test.rb +177 -0
- data/test/unit/carriers/shipwire_test.rb +188 -0
- data/test/unit/carriers/stamps_test.rb +245 -0
- data/test/unit/carriers/ups_test.rb +580 -0
- data/test/unit/carriers/usps_returns_test.rb +45 -0
- data/test/unit/carriers/usps_test.rb +633 -0
- data/test/unit/carriers_test.rb +16 -0
- data/test/unit/external_return_label_request_test.rb +258 -0
- data/test/unit/location_test.rb +234 -0
- data/test/unit/package_item_test.rb +232 -0
- data/test/unit/package_test.rb +404 -0
- data/test/unit/rate_estimate_test.rb +93 -0
- data/test/unit/response_test.rb +38 -0
- data/test/unit/shipment_event_test.rb +20 -0
- data/test/unit/shipment_packer_test.rb +212 -0
- data/test/unit/tracking_response_test.rb +41 -0
- metadata +684 -0
data/Rakefile
ADDED
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
require 'bundler/gem_tasks'
|
|
2
|
+
require 'rake/testtask'
|
|
3
|
+
|
|
4
|
+
desc "Run the unit and functional remote tests"
|
|
5
|
+
Rake::TestTask.new(:test) do |t|
|
|
6
|
+
t.libs << "test"
|
|
7
|
+
t.pattern = 'test/**/*_test.rb'
|
|
8
|
+
t.verbose = true
|
|
9
|
+
t.warning = false
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
namespace :test do
|
|
13
|
+
desc "Run unit tests"
|
|
14
|
+
Rake::TestTask.new(:unit) do |t|
|
|
15
|
+
t.libs << "test"
|
|
16
|
+
t.pattern = 'test/unit/**/*_test.rb'
|
|
17
|
+
t.verbose = true
|
|
18
|
+
t.warning = false
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
desc "Run functional remote tests"
|
|
22
|
+
Rake::TestTask.new(:remote) do |t|
|
|
23
|
+
t.libs << "test"
|
|
24
|
+
t.pattern = 'test/remote/*_test.rb'
|
|
25
|
+
t.verbose = true
|
|
26
|
+
t.warning = false
|
|
27
|
+
end
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
desc "Open a pry session preloaded with this library"
|
|
31
|
+
task :console do
|
|
32
|
+
sh 'ruby -Ilib -Itest test/console.rb'
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
task :default => 'test'
|
data/dev.yml
ADDED
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
name: active-shipping
|
|
2
|
+
|
|
3
|
+
up:
|
|
4
|
+
- ruby: 2.3.1
|
|
5
|
+
- bundler
|
|
6
|
+
|
|
7
|
+
commands:
|
|
8
|
+
test:
|
|
9
|
+
syntax:
|
|
10
|
+
optional: file args...
|
|
11
|
+
desc: 'run all tests or a specific test file'
|
|
12
|
+
run: |
|
|
13
|
+
if [[ $# -eq 0 ]]; then
|
|
14
|
+
bundle exec rake test
|
|
15
|
+
else
|
|
16
|
+
bundle exec ruby -Itest "$@"
|
|
17
|
+
fi
|
|
@@ -0,0 +1,111 @@
|
|
|
1
|
+
<!-- EVERY REQUEST CONTAIN THE eparcel TAG -->
|
|
2
|
+
<!ELEMENT eparcel (language?,
|
|
3
|
+
( ratesAndServicesRequest |
|
|
4
|
+
ratesAndServicesResponse |
|
|
5
|
+
error
|
|
6
|
+
)+)>
|
|
7
|
+
|
|
8
|
+
<!ELEMENT language (#PCDATA)>
|
|
9
|
+
<!ELEMENT comment (#PCDATA)>
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
<!-- Standard request to ask for rates and services -->
|
|
13
|
+
<!ELEMENT ratesAndServicesRequest ( merchantCPCID,
|
|
14
|
+
fromPostalCode?,
|
|
15
|
+
turnAroundTime?,
|
|
16
|
+
itemsPrice?,
|
|
17
|
+
lineItems,
|
|
18
|
+
city?,
|
|
19
|
+
provOrState,
|
|
20
|
+
country,
|
|
21
|
+
postalCode)>
|
|
22
|
+
<!ELEMENT merchantID (#PCDATA)>
|
|
23
|
+
<!ELEMENT fromPostalCode (#PCDATA)>
|
|
24
|
+
<!ELEMENT turnAroundTime (#PCDATA)>
|
|
25
|
+
<!ELEMENT itemsPrice (#PCDATA)>
|
|
26
|
+
<!ELEMENT merchantCPCID (#PCDATA)>
|
|
27
|
+
<!ELEMENT lineItems (item)+>
|
|
28
|
+
<!ELEMENT item (quantity, weight, length, width, height, description, imageURL?, readyToShip)>
|
|
29
|
+
<!ELEMENT quantity (#PCDATA)>
|
|
30
|
+
<!ELEMENT weight (#PCDATA)>
|
|
31
|
+
<!ELEMENT length (#PCDATA)>
|
|
32
|
+
<!ELEMENT width (#PCDATA)>
|
|
33
|
+
<!ELEMENT height (#PCDATA)>
|
|
34
|
+
<!ELEMENT description (#PCDATA)>
|
|
35
|
+
<!ELEMENT imageURL (#PCDATA)>
|
|
36
|
+
<!ELEMENT readyToShip (#PCDATA)>
|
|
37
|
+
<!ELEMENT city (#PCDATA)>
|
|
38
|
+
<!ELEMENT provOrState (#PCDATA)>
|
|
39
|
+
<!ELEMENT country (#PCDATA)>
|
|
40
|
+
<!ELEMENT postalCode (#PCDATA)>
|
|
41
|
+
|
|
42
|
+
<!-- Standard response for request for rates and services -->
|
|
43
|
+
<!ELEMENT ratesAndServicesResponse (statusCode,
|
|
44
|
+
statusMessage+,
|
|
45
|
+
requestID,
|
|
46
|
+
handling,
|
|
47
|
+
language,
|
|
48
|
+
product+,
|
|
49
|
+
packing*,
|
|
50
|
+
emptySpace*,
|
|
51
|
+
shippingOptions,
|
|
52
|
+
comment,
|
|
53
|
+
nearestPostalOutlet*)>
|
|
54
|
+
|
|
55
|
+
<!ELEMENT statusCode (#PCDATA)>
|
|
56
|
+
<!ELEMENT statusMessage (#PCDATA)>
|
|
57
|
+
<!ELEMENT requestID (#PCDATA)>
|
|
58
|
+
<!ELEMENT handling (#PCDATA)>
|
|
59
|
+
|
|
60
|
+
<!ELEMENT product (name, rate, shippingDate, deliveryDate, deliveryDayOfWeek, nextDayAM?, packingID)>
|
|
61
|
+
<!ATTLIST product id CDATA #REQUIRED>
|
|
62
|
+
<!ATTLIST product sequence CDATA #REQUIRED>
|
|
63
|
+
<!ELEMENT name (#PCDATA)>
|
|
64
|
+
<!ELEMENT rate (#PCDATA)>
|
|
65
|
+
<!ELEMENT shippingDate (#PCDATA)>
|
|
66
|
+
<!ELEMENT deliveryDate (#PCDATA)>
|
|
67
|
+
<!ELEMENT deliveryDayOfWeek (#PCDATA)>
|
|
68
|
+
<!ELEMENT nextDayAM (#PCDATA)>
|
|
69
|
+
<!ELEMENT packingID (#PCDATA)>
|
|
70
|
+
|
|
71
|
+
<!ELEMENT packing (packingID, box+)>
|
|
72
|
+
<!ELEMENT box (name, weight, expediterWeight, length, width, height, packedItem+)>
|
|
73
|
+
<!ELEMENT expediterWeight (#PCDATA)>
|
|
74
|
+
<!ELEMENT packedItem (quantity, description)>
|
|
75
|
+
|
|
76
|
+
<!ELEMENT emptySpace (length, width, height, weight)>
|
|
77
|
+
|
|
78
|
+
<!ELEMENT shippingOptions (insurance, deliveryConfirmation, signature)>
|
|
79
|
+
<!ELEMENT insurance (#PCDATA)>
|
|
80
|
+
<!ELEMENT deliveryConfirmation (#PCDATA)>
|
|
81
|
+
<!ELEMENT signature (#PCDATA)>
|
|
82
|
+
|
|
83
|
+
|
|
84
|
+
<!-- ********************************************************* -->
|
|
85
|
+
<!-- * 'nearestPostalOutlet' is optional and is returned * -->
|
|
86
|
+
<!-- * only if the merchant profile has this option enabled * -->
|
|
87
|
+
<!-- ********************************************************* -->
|
|
88
|
+
<!ELEMENT nearestPostalOutlet (postalOutletSequenceNo,
|
|
89
|
+
distance,
|
|
90
|
+
outletName,
|
|
91
|
+
businessName ,
|
|
92
|
+
postalAddress,
|
|
93
|
+
phoneNumber,
|
|
94
|
+
businessHours+)>
|
|
95
|
+
<!ELEMENT postalOutletSequenceNo (#PCDATA)>
|
|
96
|
+
<!ELEMENT distance (#PCDATA)>
|
|
97
|
+
<!ELEMENT outletName (#PCDATA)>
|
|
98
|
+
<!ELEMENT businessName (#PCDATA)>
|
|
99
|
+
<!ELEMENT postalAddress (addressLine+, postalCode , municipality)>
|
|
100
|
+
<!ELEMENT addressLine (#PCDATA)>
|
|
101
|
+
<!ELEMENT municipality (#PCDATA)>
|
|
102
|
+
<!ELEMENT phoneNumber (#PCDATA)>
|
|
103
|
+
<!ELEMENT businessHours (dayId, dayOfWeek, time)>
|
|
104
|
+
<!ELEMENT dayId (#PCDATA)>
|
|
105
|
+
<!ELEMENT dayOfWeek (#PCDATA)>
|
|
106
|
+
<!ELEMENT time (#PCDATA)>
|
|
107
|
+
|
|
108
|
+
|
|
109
|
+
<!-- Standard error format returned -->
|
|
110
|
+
<!ELEMENT error (statusCode,statusMessage*)>
|
|
111
|
+
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
require 'active_support/all'
|
|
2
|
+
require 'active_utils'
|
|
3
|
+
|
|
4
|
+
require 'nokogiri'
|
|
5
|
+
require 'measured'
|
|
6
|
+
|
|
7
|
+
require 'reactive_shipping/response'
|
|
8
|
+
require 'reactive_shipping/rate_response'
|
|
9
|
+
require 'reactive_shipping/tracking_response'
|
|
10
|
+
require 'reactive_shipping/delivery_date_estimates_response'
|
|
11
|
+
require 'reactive_shipping/shipping_response'
|
|
12
|
+
require 'reactive_shipping/label_response'
|
|
13
|
+
require 'reactive_shipping/label'
|
|
14
|
+
require 'reactive_shipping/package_item'
|
|
15
|
+
require 'reactive_shipping/package'
|
|
16
|
+
require 'reactive_shipping/location'
|
|
17
|
+
require 'reactive_shipping/rate_estimate'
|
|
18
|
+
require 'reactive_shipping/delivery_date_estimate'
|
|
19
|
+
require 'reactive_shipping/shipment_event'
|
|
20
|
+
require 'reactive_shipping/shipment_packer'
|
|
21
|
+
require 'reactive_shipping/carrier'
|
|
22
|
+
require 'reactive_shipping/carriers'
|
|
23
|
+
require 'reactive_shipping/errors'
|
|
24
|
+
require 'reactive_shipping/external_return_label_request'
|
|
25
|
+
require 'reactive_shipping/external_return_label_response'
|
|
26
|
+
require 'reactive_shipping/address_validation_response'
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
module ReactiveShipping
|
|
2
|
+
|
|
3
|
+
# Response object class for calls to {ReactiveShipping::Carrier#validate_address}.
|
|
4
|
+
#
|
|
5
|
+
# @!attribute location
|
|
6
|
+
# The Location to be validated
|
|
7
|
+
# @return [String]
|
|
8
|
+
class AddressValidationResponse < Response
|
|
9
|
+
attr_reader :validity, :classification, :candidate_addresses, :options, :params
|
|
10
|
+
|
|
11
|
+
def initialize(success, message, params = {}, options = {})
|
|
12
|
+
@validity = options[:validity]
|
|
13
|
+
@candidate_addresses = options[:candidate_addresses]
|
|
14
|
+
@classification = options[:classification]
|
|
15
|
+
super
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
def address_match?
|
|
19
|
+
@validity == :valid
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
def residential?
|
|
23
|
+
@classification == :residential
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
def commercial?
|
|
27
|
+
@classification == :commercial
|
|
28
|
+
end
|
|
29
|
+
end
|
|
30
|
+
end
|
|
@@ -0,0 +1,184 @@
|
|
|
1
|
+
module ReactiveShipping
|
|
2
|
+
|
|
3
|
+
# Carrier is the abstract base class for all supported carriers.
|
|
4
|
+
#
|
|
5
|
+
# To implement support for a carrier, you should subclass this class and
|
|
6
|
+
# implement all the methods that the carrier supports.
|
|
7
|
+
#
|
|
8
|
+
# @see #find_rates
|
|
9
|
+
# @see #create_shipment
|
|
10
|
+
# @see #cancel_shipment
|
|
11
|
+
# @see #find_tracking_info
|
|
12
|
+
#
|
|
13
|
+
# @!attribute test_mode
|
|
14
|
+
# Whether to interact with the carrier's sandbox environment.
|
|
15
|
+
# @return [Boolean]
|
|
16
|
+
#
|
|
17
|
+
# @!attribute last_request
|
|
18
|
+
# The last request performed against the carrier's API.
|
|
19
|
+
# @see #save_request
|
|
20
|
+
class Carrier
|
|
21
|
+
attr_reader :last_request
|
|
22
|
+
attr_accessor :test_mode
|
|
23
|
+
alias_method :test_mode?, :test_mode
|
|
24
|
+
|
|
25
|
+
# Credentials should be in options hash under keys :login, :password and/or :key.
|
|
26
|
+
# @param options [Hash] The details needed to connect to the carrier's API.
|
|
27
|
+
# @option options [Boolean] :test Set this to true to connect to the carrier's
|
|
28
|
+
# sandbox environment instead of the production environment.
|
|
29
|
+
def initialize(options = {})
|
|
30
|
+
requirements.each { |key| requires!(options, key) }
|
|
31
|
+
@options = options
|
|
32
|
+
@last_request = nil
|
|
33
|
+
@test_mode = @options[:test]
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
# Asks the carrier for rate estimates for a given shipment.
|
|
37
|
+
#
|
|
38
|
+
# @note Override with whatever you need to get the rates from the carrier.
|
|
39
|
+
#
|
|
40
|
+
# @param origin [ReactiveShipping::Location] Where the shipment will originate from.
|
|
41
|
+
# @param destination [ReactiveShipping::Location] Where the package will go.
|
|
42
|
+
# @param packages [Array<ReactiveShipping::Package>] The list of packages that will
|
|
43
|
+
# be in the shipment.
|
|
44
|
+
# @param options [Hash] Carrier-specific parameters.
|
|
45
|
+
# @return [ReactiveShipping::RateResponse] The response from the carrier, which
|
|
46
|
+
# includes 0 or more rate estimates for different shipping products
|
|
47
|
+
def find_rates(origin, destination, packages, options = {})
|
|
48
|
+
raise NotImplementedError, "#find_rates is not supported by #{self.class.name}."
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
# Registers a new shipment with the carrier, to get a tracking number and
|
|
52
|
+
# potentially shipping labels
|
|
53
|
+
#
|
|
54
|
+
# @note Override with whatever you need to register a shipment, and obtain
|
|
55
|
+
# shipping labels if supported by the carrier.
|
|
56
|
+
#
|
|
57
|
+
# @param origin [ReactiveShipping::Location] Where the shipment will originate from.
|
|
58
|
+
# @param destination [ReactiveShipping::Location] Where the package will go.
|
|
59
|
+
# @param packages [Array<ReactiveShipping::Package>] The list of packages that will
|
|
60
|
+
# be in the shipment.
|
|
61
|
+
# @param options [Hash] Carrier-specific parameters.
|
|
62
|
+
# @return [ReactiveShipping::ShipmentResponse] The response from the carrier. This
|
|
63
|
+
# response should include a shipment identifier or tracking_number if successful,
|
|
64
|
+
# and potentially shipping labels.
|
|
65
|
+
def create_shipment(origin, destination, packages, options = {})
|
|
66
|
+
raise NotImplementedError, "#create_shipment is not supported by #{self.class.name}."
|
|
67
|
+
end
|
|
68
|
+
|
|
69
|
+
# Cancels a shipment with a carrier.
|
|
70
|
+
#
|
|
71
|
+
# @note Override with whatever you need to cancel a shipping label
|
|
72
|
+
#
|
|
73
|
+
# @param shipment_id [String] The unique identifier of the shipment to cancel.
|
|
74
|
+
# This can be shipment_id or tracking number depending on carrier. Up to you and
|
|
75
|
+
# the carrier
|
|
76
|
+
# @param options [Hash] Carrier-specific parameters.
|
|
77
|
+
# @return [ReactiveShipping::ShipmentResponse] The response from the carrier. This
|
|
78
|
+
# response in most cases has a cancellation id.
|
|
79
|
+
def cancel_shipment(shipment_id, options = {})
|
|
80
|
+
raise NotImplementedError, "#cancel_shipment is not supported by #{self.class.name}."
|
|
81
|
+
end
|
|
82
|
+
|
|
83
|
+
# Retrieves tracking information for a previous shipment
|
|
84
|
+
#
|
|
85
|
+
# @note Override with whatever you need to get a shipping label
|
|
86
|
+
#
|
|
87
|
+
# @param tracking_number [String] The unique identifier of the shipment to track.
|
|
88
|
+
# @param options [Hash] Carrier-specific parameters.
|
|
89
|
+
# @return [ReactiveShipping::TrackingResponse] The response from the carrier. This
|
|
90
|
+
# response should a list of shipment tracking events if successful.
|
|
91
|
+
def find_tracking_info(tracking_number, options = {})
|
|
92
|
+
raise NotImplementedError, "#find_tracking_info is not supported by #{self.class.name}."
|
|
93
|
+
end
|
|
94
|
+
|
|
95
|
+
# Get a list of services available for the a specific route
|
|
96
|
+
#
|
|
97
|
+
# @param origin_country_code [String] The country of origin
|
|
98
|
+
# @param destination_country_code [String] The destination country
|
|
99
|
+
# @return [Array<String>] A list of names of the available services
|
|
100
|
+
#
|
|
101
|
+
def available_services(origin_country_code, destination_country_code, options = {})
|
|
102
|
+
raise NotImplementedError, "#available_services is not supported by #{self.class.name}."
|
|
103
|
+
end
|
|
104
|
+
|
|
105
|
+
# Validate credentials with a call to the API.
|
|
106
|
+
#
|
|
107
|
+
# By default this just does a `find_rates` call with the origin and destination both as
|
|
108
|
+
# the carrier's default_location. Override to provide alternate functionality, such as
|
|
109
|
+
# checking for `test_mode` to use test servers, etc.
|
|
110
|
+
#
|
|
111
|
+
# @return [Boolean] Should return `true` if the provided credentials proved to work,
|
|
112
|
+
# `false` otherswise.
|
|
113
|
+
def valid_credentials?
|
|
114
|
+
location = self.class.default_location
|
|
115
|
+
find_rates(location, location, Package.new(100, [5, 15, 30]), :test => test_mode)
|
|
116
|
+
rescue ReactiveShipping::ResponseError
|
|
117
|
+
false
|
|
118
|
+
else
|
|
119
|
+
true
|
|
120
|
+
end
|
|
121
|
+
|
|
122
|
+
# The maximum weight the carrier will accept.
|
|
123
|
+
# @return [Measured::Weight]
|
|
124
|
+
def maximum_weight
|
|
125
|
+
Measured::Weight.new(150, :pounds)
|
|
126
|
+
end
|
|
127
|
+
|
|
128
|
+
# The address field maximum length accepted by the carrier
|
|
129
|
+
# @return [Integer]
|
|
130
|
+
def maximum_address_field_length
|
|
131
|
+
255
|
|
132
|
+
end
|
|
133
|
+
|
|
134
|
+
protected
|
|
135
|
+
|
|
136
|
+
include ActiveUtils::RequiresParameters
|
|
137
|
+
include ActiveUtils::PostsData
|
|
138
|
+
|
|
139
|
+
# Returns the keys that are required to be passed to the options hash
|
|
140
|
+
# @note Override to return required keys in options hash for initialize method.
|
|
141
|
+
# @return [Array<Symbol>]
|
|
142
|
+
def requirements
|
|
143
|
+
[]
|
|
144
|
+
end
|
|
145
|
+
|
|
146
|
+
# The default location to use for {#valid_credentials?}.
|
|
147
|
+
# @note Override for non-U.S.-based carriers.
|
|
148
|
+
# @return [ReactiveShipping::Location]
|
|
149
|
+
def self.default_location
|
|
150
|
+
Location.new( :country => 'US',
|
|
151
|
+
:state => 'CA',
|
|
152
|
+
:city => 'Beverly Hills',
|
|
153
|
+
:address1 => '455 N. Rexford Dr.',
|
|
154
|
+
:address2 => '3rd Floor',
|
|
155
|
+
:zip => '90210',
|
|
156
|
+
:phone => '1-310-285-1013',
|
|
157
|
+
:fax => '1-310-275-8159')
|
|
158
|
+
end
|
|
159
|
+
|
|
160
|
+
# Use after building the request to save for later inspection.
|
|
161
|
+
# @return [void]
|
|
162
|
+
def save_request(r)
|
|
163
|
+
@last_request = r
|
|
164
|
+
end
|
|
165
|
+
|
|
166
|
+
# Calculates a timestamp that corresponds a given number of business days in the future
|
|
167
|
+
#
|
|
168
|
+
# @param days [Integer] The number of business days from now.
|
|
169
|
+
# @return [DateTime] A timestamp, the provided number of business days in the future.
|
|
170
|
+
def timestamp_from_business_day(days)
|
|
171
|
+
return unless days
|
|
172
|
+
date = DateTime.now.utc
|
|
173
|
+
|
|
174
|
+
days.times do
|
|
175
|
+
date += 1.day
|
|
176
|
+
|
|
177
|
+
date += 2.days if date.saturday?
|
|
178
|
+
date += 1.day if date.sunday?
|
|
179
|
+
end
|
|
180
|
+
|
|
181
|
+
date.to_datetime
|
|
182
|
+
end
|
|
183
|
+
end
|
|
184
|
+
end
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
module ReactiveShipping
|
|
2
|
+
module Carriers
|
|
3
|
+
extend self
|
|
4
|
+
|
|
5
|
+
attr_reader :registered
|
|
6
|
+
@registered = []
|
|
7
|
+
|
|
8
|
+
def register(class_name, autoload_require)
|
|
9
|
+
ReactiveShipping.autoload(class_name, autoload_require)
|
|
10
|
+
self.registered << class_name
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
def all
|
|
14
|
+
ReactiveShipping::Carriers.registered.map { |name| ReactiveShipping.const_get(name) }
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
def find(name)
|
|
18
|
+
all.find { |c| c.name.downcase == name.to_s.downcase } or raise NameError, "unknown carrier #{name}"
|
|
19
|
+
end
|
|
20
|
+
end
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
ReactiveShipping::Carriers.register :BenchmarkCarrier, 'reactive_shipping/carriers/benchmark_carrier'
|
|
24
|
+
ReactiveShipping::Carriers.register :BogusCarrier, 'reactive_shipping/carriers/bogus_carrier'
|
|
25
|
+
ReactiveShipping::Carriers.register :UPS, 'reactive_shipping/carriers/ups'
|
|
26
|
+
ReactiveShipping::Carriers.register :USPS, 'reactive_shipping/carriers/usps'
|
|
27
|
+
ReactiveShipping::Carriers.register :USPSReturns, 'reactive_shipping/carriers/usps_returns'
|
|
28
|
+
ReactiveShipping::Carriers.register :FedEx, 'reactive_shipping/carriers/fedex'
|
|
29
|
+
ReactiveShipping::Carriers.register :Shipwire, 'reactive_shipping/carriers/shipwire'
|
|
30
|
+
ReactiveShipping::Carriers.register :Kunaki, 'reactive_shipping/carriers/kunaki'
|
|
31
|
+
ReactiveShipping::Carriers.register :CanadaPost, 'reactive_shipping/carriers/canada_post'
|
|
32
|
+
ReactiveShipping::Carriers.register :NewZealandPost, 'reactive_shipping/carriers/new_zealand_post'
|
|
33
|
+
ReactiveShipping::Carriers.register :CanadaPostPWS, 'reactive_shipping/carriers/canada_post_pws'
|
|
34
|
+
ReactiveShipping::Carriers.register :Stamps, 'reactive_shipping/carriers/stamps'
|
|
35
|
+
ReactiveShipping::Carriers.register :AustraliaPost, 'reactive_shipping/carriers/australia_post'
|