require 'date' module Trackerific require 'builder' require 'httparty' # Provides package tracking support for USPS. class USPS < Base include HTTParty format :xml base_uri defined?(Rails) ? case Rails.env when 'test', 'development' then 'http://testing.shippingapis.com' when 'production' then 'https://secure.shippingapis.com' end : 'https://secure.shippingapis.com' def initialize(options = {}) super @options = options end # The required option for tracking a UPS package is :user_id # # @return [Array] the required options for tracking a UPS package. def required_options [:user_id] end # Tracks a USPS package. # A Trackerific::Error is raised when a package cannot be tracked. # @return [Trackerific::Details] the tracking details def track_package(package_id) super response = self.class.get('/ShippingAPITest.dll', :query => {:API => 'TrackV2', :XML => build_xml_request}.to_query) response.error! unless response.code == 200 raise Trackerific::Error, response['Error']['Description'] unless response['Error'].nil? raise Trackerific::Error, "Tracking information not found in response from server." if response['TrackResponse'].nil? tracking_info = response['TrackResponse']['TrackInfo'] details = [] tracking_info['TrackDetail'].each do |d| # each tracking detail is a string in this format: # MM DD HH:MM am/pm DESCRIPTION CITY STATE ZIP. # unfortunately, it will not be possible to tell the difference between # the location, and the summary. So, for USPS, the location will be in # the summary d = d.split(" ") date = DateTime.parse(d[0..3].join(" ")) desc = d[4..d.length].join(" ") details << Trackerific::Event.new(date, desc, "") end Trackerific::Details.new( tracking_info['ID'], tracking_info['TrackSummary'], details ) end protected # Parses the response from UPS # @return [Trackerific::Details] def build_xml_request tracking_request = "" builder = ::Builder::XmlMarkup.new(:target => tracking_request) builder.TrackRequest(:USERID => @options[:user_id]) do |t| t.TrackID(:ID => @package_id) end return tracking_request end end end