correios-sro-xml 0.0.4 → 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- data/.gitignore +25 -0
- data/CHANGELOG.rdoc +14 -8
- data/Gemfile +1 -12
- data/README.rdoc +181 -35
- data/Rakefile +13 -35
- data/correios-sro-xml.gemspec +24 -80
- data/lib/correios-sro-xml.rb +4 -4
- data/lib/correios/sro.rb +11 -0
- data/lib/correios/sro/destination.rb +16 -0
- data/lib/correios/sro/event.rb +31 -0
- data/lib/correios/sro/object.rb +13 -0
- data/lib/correios/sro/parser.rb +5 -5
- data/lib/correios/sro/tracker.rb +43 -0
- data/lib/correios/sro/version.rb +1 -6
- data/lib/correios/sro/web_service.rb +64 -11
- data/misc/correios_sro_xml_manual_v1.5.pdf +0 -0
- data/spec/correios/sro/event_spec.rb +15 -0
- data/spec/correios/sro/parser_spec.rb +44 -44
- data/spec/correios/sro/tracker_spec.rb +116 -0
- data/spec/correios/sro/web_service_spec.rb +10 -4
- data/spec/correios/sro_spec.rb +22 -0
- data/spec/spec_helper.rb +3 -5
- data/spec/support/mock_request.rb +22 -0
- data/spec/support/responses/failure_response_not_found.xml +6 -0
- data/spec/support/responses/{success-response-many-objects.xml → success_response_many_objects.xml} +0 -0
- data/spec/support/responses/{success-response-many-objects-international.xml → success_response_many_objects_international.xml} +0 -0
- data/spec/support/responses/{success-response-one-object.xml → success_response_one_object.xml} +0 -0
- metadata +54 -59
- data/Gemfile.lock +0 -62
- data/lib/correios/sro/destino.rb +0 -16
- data/lib/correios/sro/evento.rb +0 -31
- data/lib/correios/sro/objeto.rb +0 -13
- data/lib/correios/sro/rastreador.rb +0 -43
- data/spec/correios/sro/evento_spec.rb +0 -15
- data/spec/correios/sro/rastreador_spec.rb +0 -53
- data/spec/support/fake_request.rb +0 -21
data/lib/correios-sro-xml.rb
CHANGED
@@ -1,10 +1,10 @@
|
|
1
1
|
# encoding: UTF-8
|
2
2
|
require 'rubygems'
|
3
3
|
require 'correios/sro'
|
4
|
-
require 'correios/sro/
|
5
|
-
require 'correios/sro/
|
6
|
-
require 'correios/sro/
|
4
|
+
require 'correios/sro/destination'
|
5
|
+
require 'correios/sro/event'
|
6
|
+
require 'correios/sro/object'
|
7
7
|
require 'correios/sro/parser'
|
8
|
-
require 'correios/sro/
|
8
|
+
require 'correios/sro/tracker'
|
9
9
|
require 'correios/sro/string'
|
10
10
|
require 'correios/sro/web_service'
|
data/lib/correios/sro.rb
CHANGED
@@ -4,5 +4,16 @@ require 'log-me'
|
|
4
4
|
module Correios
|
5
5
|
module SRO
|
6
6
|
extend LogMe
|
7
|
+
|
8
|
+
module Timeout
|
9
|
+
DEFAULT_REQUEST_TIMEOUT = 5 #seconds
|
10
|
+
attr_writer :request_timeout
|
11
|
+
|
12
|
+
def request_timeout
|
13
|
+
(@request_timeout ||= DEFAULT_REQUEST_TIMEOUT).to_i
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
extend Timeout
|
7
18
|
end
|
8
19
|
end
|
@@ -0,0 +1,16 @@
|
|
1
|
+
# encoding: UTF-8
|
2
|
+
require 'sax-machine'
|
3
|
+
|
4
|
+
module Correios
|
5
|
+
module SRO
|
6
|
+
class Destination
|
7
|
+
include SAXMachine
|
8
|
+
|
9
|
+
element :local, :as => :place
|
10
|
+
element :codigo, :as => :code
|
11
|
+
element :cidade, :as => :city
|
12
|
+
element :bairro, :as => :neighborhood
|
13
|
+
element :uf, :as => :state
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
@@ -0,0 +1,31 @@
|
|
1
|
+
# encoding: UTF-8
|
2
|
+
require 'sax-machine'
|
3
|
+
|
4
|
+
module Correios
|
5
|
+
module SRO
|
6
|
+
class Event
|
7
|
+
include SAXMachine
|
8
|
+
|
9
|
+
element :tipo, :as => :type
|
10
|
+
element :status, :as => :status
|
11
|
+
element :data, :as => :date
|
12
|
+
element :hora, :as => :hour
|
13
|
+
element :descricao, :as => :description
|
14
|
+
element :recebedor, :as => :receiver
|
15
|
+
element :documento, :as => :document
|
16
|
+
element :comentario, :as => :comment
|
17
|
+
element :local, :as => :place
|
18
|
+
element :codigo, :as => :code
|
19
|
+
element :cidade, :as => :city
|
20
|
+
element :uf, :as => :state
|
21
|
+
element :sto, :as => :sto
|
22
|
+
element :destino, :as => :destination, :class => Correios::SRO::Destination
|
23
|
+
|
24
|
+
[:receiver, :document, :comment].each do |method|
|
25
|
+
define_method "#{method}=" do |value|
|
26
|
+
instance_variable_set("@#{method}", value.to_s.strip)
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
data/lib/correios/sro/parser.rb
CHANGED
@@ -4,17 +4,17 @@ require 'nokogiri'
|
|
4
4
|
module Correios
|
5
5
|
module SRO
|
6
6
|
class Parser
|
7
|
-
def
|
8
|
-
|
7
|
+
def objects(xml)
|
8
|
+
objects = {}
|
9
9
|
xml = xml.backward_encode("UTF-8", "ISO-8859-1")
|
10
10
|
|
11
11
|
doc = Nokogiri::XML(xml)
|
12
12
|
doc.xpath("//objeto").each do |element|
|
13
|
-
|
14
|
-
|
13
|
+
object = Correios::SRO::Object.parse(element.to_xml)
|
14
|
+
objects[object.number] = object
|
15
15
|
end
|
16
16
|
|
17
|
-
|
17
|
+
objects
|
18
18
|
end
|
19
19
|
end
|
20
20
|
end
|
@@ -0,0 +1,43 @@
|
|
1
|
+
# encoding: UTF-8
|
2
|
+
module Correios
|
3
|
+
module SRO
|
4
|
+
class Tracker
|
5
|
+
attr_accessor :user, :password
|
6
|
+
attr_accessor :query_type, :result_mode
|
7
|
+
attr_reader :object_numbers
|
8
|
+
|
9
|
+
DEFAULT_OPTIONS = { :query_type => :list, :result_mode => :last }
|
10
|
+
|
11
|
+
def initialize(options = {})
|
12
|
+
DEFAULT_OPTIONS.merge(options).each do |attr, value|
|
13
|
+
self.send("#{attr}=", value)
|
14
|
+
end
|
15
|
+
|
16
|
+
yield self if block_given?
|
17
|
+
@object_numbers = []
|
18
|
+
end
|
19
|
+
|
20
|
+
def get(*object_numbers)
|
21
|
+
@object_numbers = object_numbers
|
22
|
+
response = web_service.request!
|
23
|
+
objects = parser.objects(response)
|
24
|
+
|
25
|
+
if @object_numbers.size == 1
|
26
|
+
objects.values.first
|
27
|
+
else
|
28
|
+
objects
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
private
|
33
|
+
|
34
|
+
def web_service
|
35
|
+
@web_service ||= Correios::SRO::WebService.new(self)
|
36
|
+
end
|
37
|
+
|
38
|
+
def parser
|
39
|
+
@parser ||= Correios::SRO::Parser.new
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
data/lib/correios/sro/version.rb
CHANGED
@@ -6,29 +6,82 @@ module Correios
|
|
6
6
|
module SRO
|
7
7
|
class WebService
|
8
8
|
URL = "http://websro.correios.com.br/sro_bin/sroii_xml.eventos"
|
9
|
-
|
10
|
-
|
9
|
+
QUERY_TYPES = { :list => "L", :range => "F" }
|
10
|
+
RESULT_MODES = { :all => "T", :last => "U" }
|
11
11
|
|
12
|
-
def initialize
|
12
|
+
def initialize(tracker)
|
13
13
|
@uri = URI.parse(URL)
|
14
|
+
@tracker = tracker
|
14
15
|
end
|
15
16
|
|
16
|
-
def request
|
17
|
-
|
17
|
+
def request!
|
18
|
+
http = build_http
|
19
|
+
|
20
|
+
request = build_request
|
21
|
+
log_request(request)
|
22
|
+
|
23
|
+
response = http.request(request)
|
24
|
+
log_response(response)
|
25
|
+
|
18
26
|
response.body
|
19
27
|
end
|
20
28
|
|
21
29
|
private
|
22
30
|
|
23
|
-
def
|
31
|
+
def build_http
|
32
|
+
http = Net::HTTP.new(@uri.host, @uri.port)
|
33
|
+
http.open_timeout = Correios::SRO.request_timeout
|
34
|
+
http
|
35
|
+
end
|
36
|
+
|
37
|
+
def build_request
|
38
|
+
request = Net::HTTP::Post.new(@uri.path)
|
39
|
+
request.set_form_data(request_params)
|
40
|
+
request
|
41
|
+
end
|
42
|
+
|
43
|
+
def request_params
|
24
44
|
{
|
25
|
-
:Usuario =>
|
26
|
-
:Senha =>
|
27
|
-
:Tipo =>
|
28
|
-
:Resultado =>
|
29
|
-
:Objetos =>
|
45
|
+
:Usuario => @tracker.user,
|
46
|
+
:Senha => @tracker.password,
|
47
|
+
:Tipo => QUERY_TYPES[@tracker.query_type],
|
48
|
+
:Resultado => RESULT_MODES[@tracker.result_mode],
|
49
|
+
:Objetos => @tracker.object_numbers.join
|
30
50
|
}
|
31
51
|
end
|
52
|
+
|
53
|
+
def log_request(request)
|
54
|
+
message = format_message(request) do
|
55
|
+
message = with_line_break { "Correios-SRO-XML Request:" }
|
56
|
+
message << with_line_break { "POST #{URL}" }
|
57
|
+
end
|
58
|
+
|
59
|
+
Correios::SRO.log(message)
|
60
|
+
end
|
61
|
+
|
62
|
+
def log_response(response)
|
63
|
+
message = format_message(response) do
|
64
|
+
message = with_line_break { "Correios-SRO-XML Response:" }
|
65
|
+
message << with_line_break { "HTTP/#{response.http_version} #{response.code} #{response.message}" }
|
66
|
+
end
|
67
|
+
|
68
|
+
Correios::SRO.log(message)
|
69
|
+
end
|
70
|
+
|
71
|
+
def format_message(http)
|
72
|
+
message = yield
|
73
|
+
message << with_line_break { format_headers_for(http) } if Correios::SRO.log_level == :debug
|
74
|
+
message << with_line_break { http.body }
|
75
|
+
end
|
76
|
+
|
77
|
+
def format_headers_for(http)
|
78
|
+
# I'm using an empty block in each_header method for Ruby 1.8.7 compatibility.
|
79
|
+
http.each_header{}.map { |name, values| "#{name}: #{values.first}" }.join("\n")
|
80
|
+
end
|
81
|
+
|
82
|
+
def with_line_break
|
83
|
+
"#{yield}\n"
|
84
|
+
end
|
32
85
|
end
|
33
86
|
end
|
34
87
|
end
|
Binary file
|
@@ -0,0 +1,15 @@
|
|
1
|
+
# encoding: UTF-8
|
2
|
+
require 'spec_helper'
|
3
|
+
|
4
|
+
describe Correios::SRO::Event do
|
5
|
+
let(:event) { Correios::SRO::Event.new }
|
6
|
+
|
7
|
+
[:receiver, :document, :comment].each do |method|
|
8
|
+
describe "##{method}=" do
|
9
|
+
it "strips string" do
|
10
|
+
event.send("#{method}=", " Texto. ")
|
11
|
+
event.send(method).should == "Texto."
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
@@ -2,87 +2,87 @@
|
|
2
2
|
require 'spec_helper'
|
3
3
|
|
4
4
|
describe Correios::SRO::Parser do
|
5
|
-
describe "#
|
5
|
+
describe "#objects" do
|
6
6
|
let(:xml) { body_for :success_response_many_objects }
|
7
7
|
let(:parser) { Correios::SRO::Parser.new }
|
8
8
|
|
9
9
|
it "encodes from ISO-8859-1 to UTF-8" do
|
10
10
|
xml.should_receive(:backward_encode).with("UTF-8", "ISO-8859-1").and_return(xml)
|
11
|
-
parser.
|
11
|
+
parser.objects(xml)
|
12
12
|
end
|
13
13
|
|
14
14
|
["SI047624825BR", "SX104110463BR"].each do |number|
|
15
15
|
it "returns object number" do
|
16
|
-
|
17
|
-
|
16
|
+
objects = parser.objects(xml)
|
17
|
+
objects[number].number.should == number
|
18
18
|
end
|
19
19
|
end
|
20
20
|
|
21
21
|
context "returns event" do
|
22
|
-
before(:each) { @
|
22
|
+
before(:each) { @objects = parser.objects(xml) }
|
23
23
|
|
24
24
|
{ "SI047624825BR" => {
|
25
|
-
:
|
25
|
+
:type => "BDI",
|
26
26
|
:status => "01",
|
27
|
-
:
|
28
|
-
:
|
29
|
-
:
|
30
|
-
:
|
31
|
-
:
|
32
|
-
:
|
33
|
-
:
|
34
|
-
:
|
35
|
-
:
|
36
|
-
:
|
27
|
+
:date => "26/12/2011",
|
28
|
+
:hour => "15:22",
|
29
|
+
:description => "Entregue",
|
30
|
+
:receiver => "",
|
31
|
+
:document => "",
|
32
|
+
:comment => "?",
|
33
|
+
:place => "AC CENTRAL DE SAO PAULO",
|
34
|
+
:code => "01009972",
|
35
|
+
:city => "SAO PAULO",
|
36
|
+
:state => "SP",
|
37
37
|
:sto => "00024419"
|
38
38
|
},
|
39
39
|
"SX104110463BR" => {
|
40
|
-
:
|
40
|
+
:type => "BDE",
|
41
41
|
:status => "01",
|
42
|
-
:
|
43
|
-
:
|
44
|
-
:
|
45
|
-
:
|
46
|
-
:
|
47
|
-
:
|
48
|
-
:
|
49
|
-
:
|
50
|
-
:
|
51
|
-
:
|
42
|
+
:date => "08/12/2011",
|
43
|
+
:hour => "09:30",
|
44
|
+
:description => "Entregue",
|
45
|
+
:receiver => "",
|
46
|
+
:document => "",
|
47
|
+
:comment => "",
|
48
|
+
:place => "CEE JUNDIAI",
|
49
|
+
:code => "13211970",
|
50
|
+
:city => "JUNDIAI",
|
51
|
+
:state => "SP",
|
52
52
|
:sto => "74654209"
|
53
53
|
},
|
54
54
|
}.each do |number, first_event|
|
55
55
|
first_event.each do |attr, value|
|
56
56
|
it attr do
|
57
|
-
|
58
|
-
|
57
|
+
event = @objects[number].events.first
|
58
|
+
event.send(attr).should == value
|
59
59
|
end
|
60
60
|
end
|
61
61
|
end
|
62
62
|
end
|
63
63
|
|
64
64
|
context "returns destination" do
|
65
|
-
before(:each) { @
|
65
|
+
before(:each) { @objects = parser.objects(xml) }
|
66
66
|
|
67
67
|
{ "SI047624825BR" => {
|
68
|
-
:
|
69
|
-
:
|
70
|
-
:
|
71
|
-
:
|
72
|
-
:
|
68
|
+
:place => "CTE VILA MARIA",
|
69
|
+
:code => "02170975",
|
70
|
+
:city => "SAO PAULO",
|
71
|
+
:neighborhood => "PQ NOVO MUNDO",
|
72
|
+
:state => "SP"
|
73
73
|
},
|
74
74
|
"SX104110463BR" => {
|
75
|
-
:
|
76
|
-
:
|
77
|
-
:
|
78
|
-
:
|
79
|
-
:
|
75
|
+
:place => "CTE CAMPINAS",
|
76
|
+
:code => "13050971",
|
77
|
+
:city => "VALINHOS",
|
78
|
+
:neighborhood => "MACUCO",
|
79
|
+
:state => "SP"
|
80
80
|
},
|
81
|
-
}.each do |number,
|
82
|
-
|
81
|
+
}.each do |number, destinations|
|
82
|
+
destinations.each do |attr, value|
|
83
83
|
it attr do
|
84
|
-
|
85
|
-
|
84
|
+
destination = @objects[number].events[3].destination
|
85
|
+
destination.send(attr).should == value
|
86
86
|
end
|
87
87
|
end
|
88
88
|
end
|
@@ -0,0 +1,116 @@
|
|
1
|
+
# encoding: UTF-8
|
2
|
+
require 'spec_helper'
|
3
|
+
|
4
|
+
describe Correios::SRO::Tracker do
|
5
|
+
describe ".new" do
|
6
|
+
it "creates with default values" do
|
7
|
+
sro = Correios::SRO::Tracker.new
|
8
|
+
sro.query_type.should == :list
|
9
|
+
sro.result_mode.should == :last
|
10
|
+
sro.object_numbers.should == []
|
11
|
+
end
|
12
|
+
|
13
|
+
{ :user => "PRODIS",
|
14
|
+
:password => "pim321",
|
15
|
+
:query_type => :range,
|
16
|
+
:result_mode => :all
|
17
|
+
}.each do |attr, value|
|
18
|
+
context "when #{attr} is supplied" do
|
19
|
+
it "sets #{attr}" do
|
20
|
+
sro = Correios::SRO::Tracker.new(attr => value)
|
21
|
+
sro.send(attr).should == value
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
context "when #{attr} is supplied in a block" do
|
26
|
+
it "sets #{attr}" do
|
27
|
+
sro = Correios::SRO::Tracker.new { |t| t.send("#{attr}=", value) }
|
28
|
+
sro.send(attr).should == value
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
describe "#get" do
|
35
|
+
around do |example|
|
36
|
+
Correios::SRO.configure { |config| config.log_enabled = false }
|
37
|
+
example.run
|
38
|
+
Correios::SRO.configure { |config| config.log_enabled = true }
|
39
|
+
end
|
40
|
+
|
41
|
+
let(:sro) { Correios::SRO::Tracker.new(:user => "PRODIS", :password => "pim321") }
|
42
|
+
|
43
|
+
context "to many objects" do
|
44
|
+
before(:each) { mock_request_for(:success_response_many_objects) }
|
45
|
+
|
46
|
+
it "sets objects numbers" do
|
47
|
+
sro.get("SI047624825BR", "SX104110463BR")
|
48
|
+
sro.object_numbers.size.should == 2
|
49
|
+
sro.object_numbers.first.should == "SI047624825BR"
|
50
|
+
sro.object_numbers.last.should == "SX104110463BR"
|
51
|
+
end
|
52
|
+
|
53
|
+
it "creates a WebService with correct params" do
|
54
|
+
web_service = Correios::SRO::WebService.new(sro)
|
55
|
+
Correios::SRO::WebService.should_receive(:new).with(sro).and_return(web_service)
|
56
|
+
sro.get("SI047624825BR", "SX104110463BR")
|
57
|
+
end
|
58
|
+
|
59
|
+
it "returns all objects" do
|
60
|
+
objects = sro.get("SI047624825BR", "SX104110463BR")
|
61
|
+
objects.size.should == 2
|
62
|
+
objects["SI047624825BR"].number.should == "SI047624825BR"
|
63
|
+
objects["SX104110463BR"].number.should == "SX104110463BR"
|
64
|
+
end
|
65
|
+
|
66
|
+
context "when only one object found" do
|
67
|
+
before(:each) { mock_request_for(:success_response_one_object) }
|
68
|
+
|
69
|
+
it "returns a Hash" do
|
70
|
+
objects = sro.get("SI047624825BR", "SX104110463BR")
|
71
|
+
objects.should be_an_instance_of Hash
|
72
|
+
end
|
73
|
+
|
74
|
+
it "returns the object found" do
|
75
|
+
objects = sro.get("SI047624825BR", "SX104110463BR")
|
76
|
+
objects.size.should == 1
|
77
|
+
objects["SI047624825BR"].number.should == "SI047624825BR"
|
78
|
+
end
|
79
|
+
|
80
|
+
it "returns nil in object not found" do
|
81
|
+
objects = sro.get("SI047624825BR", "SX104110463BR")
|
82
|
+
objects["SX104110463BR"].should be_nil
|
83
|
+
end
|
84
|
+
end
|
85
|
+
end
|
86
|
+
|
87
|
+
context "to one object" do
|
88
|
+
before(:each) { mock_request_for(:success_response_one_object) }
|
89
|
+
|
90
|
+
it "sets object number" do
|
91
|
+
sro.get("SI047624825BR")
|
92
|
+
sro.object_numbers.size.should == 1
|
93
|
+
sro.object_numbers.first.should == "SI047624825BR"
|
94
|
+
end
|
95
|
+
|
96
|
+
it "creates a WebService with correct params" do
|
97
|
+
web_service = Correios::SRO::WebService.new(sro)
|
98
|
+
Correios::SRO::WebService.should_receive(:new).with(sro).and_return(web_service)
|
99
|
+
sro.get("SI047624825BR")
|
100
|
+
end
|
101
|
+
|
102
|
+
it "returns only one object" do
|
103
|
+
object = sro.get("SI047624825BR")
|
104
|
+
object.number.should == "SI047624825BR"
|
105
|
+
end
|
106
|
+
|
107
|
+
context "when object not found" do
|
108
|
+
it "returns nil" do
|
109
|
+
mock_request_for(:failure_response_not_found)
|
110
|
+
object = sro.get("SI047624825BR")
|
111
|
+
object.should be_nil
|
112
|
+
end
|
113
|
+
end
|
114
|
+
end
|
115
|
+
end
|
116
|
+
end
|