f2b 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,3 @@
1
+ *.gem
2
+ .yardoc
3
+ doc/
@@ -0,0 +1,69 @@
1
+ F2b
2
+ ===
3
+
4
+ Gem para integração com o serviço de pagamentos da [F2b](http://f2b.com.br).
5
+
6
+ Instalação
7
+ ----------
8
+
9
+ ### RubyGems ###
10
+
11
+ sudo gem install f2b
12
+
13
+ Depois insira o código de importação em algum lugar do seu projeto.
14
+
15
+ require 'rubygems'
16
+ require 'f2b'
17
+
18
+ ### Bundler ###
19
+
20
+ Se estiver usando o [Bundler](http://github.com/carlhuda/bundler) adicione a seguinte linha no seu Gemfile.
21
+
22
+ gem 'f2b'
23
+
24
+ Como usar
25
+ ---------
26
+
27
+ #### cobrancas_controller.rb (Rails) ####
28
+
29
+ def create
30
+ cobranca = F2b::Cobranca.new
31
+ cobranca.sacador = {:conta => "9023010001230123", :senha => "zero"}
32
+ # cobranca...
33
+ resposta = cobranca.submit!
34
+ # render stuff
35
+ end
36
+
37
+ Exemplo
38
+ -------
39
+
40
+ cobranca = F2b::Cobranca.new
41
+ cobranca.sacador = {:conta => "3127519739821794", :senha => "laszlo", :nome => "Pirate Laszlo the Bald"}
42
+ cobranca.cobranca = {:valor => 10.00}
43
+ cobranca.demonstrativo.concat ["Mensalidade"]
44
+ cobranca.agendamento = {:vencimento => (Date.today + 5).strftime, :periodos => 12, :titulo => "Mensalidade"}
45
+ cobranca.sacados.push({:nome => "Sheng Hou", :email => "teste@f2b.com.br", :envio => "e"})
46
+ @resposta = cobranca.submit!
47
+
48
+ Licença
49
+ -------
50
+
51
+ Copyright (c) 2011 Rainer Borene
52
+
53
+ Permission is hereby granted, free of charge, to any person obtaining a copy of
54
+ this software and associated documentation files (the "Software"), to deal in
55
+ the Software without restriction, including without limitation the rights to
56
+ use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
57
+ of the Software, and to permit persons to whom the Software is furnished to do
58
+ so, subject to the following conditions:
59
+
60
+ The above copyright notice and this permission notice shall be included in all
61
+ copies or substantial portions of the Software.
62
+
63
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
64
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
65
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
66
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
67
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
68
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
69
+ SOFTWARE.
@@ -0,0 +1,20 @@
1
+ $:.unshift File.expand_path('../lib', __FILE__)
2
+ require 'rake'
3
+ require 'spec/rake/spectask'
4
+ require 'f2b'
5
+
6
+ task :default => [:spec]
7
+
8
+ desc "Generate a gemspec file"
9
+ task :build do
10
+ system "gem build f2b.gemspec"
11
+ end
12
+
13
+ desc "Push gem to rubygems"
14
+ task :release => :build do
15
+ system "gem push f2b-#{F2b::VERSION}"
16
+ end
17
+
18
+ Spec::Rake::SpecTask.new do |t|
19
+ t.spec_files = Dir.glob('spec/*_spec.rb')
20
+ end
@@ -0,0 +1,25 @@
1
+ # encoding: utf-8
2
+ $:.unshift File.expand_path('../lib', __FILE__)
3
+ require 'f2b'
4
+
5
+ Gem::Specification.new do |s|
6
+ s.name = 'f2b'
7
+ s.version = F2b::VERSION
8
+ s.platform = Gem::Platform::RUBY
9
+ s.authors = ["Rainer Borene"]
10
+ s.email = "me@rainerborene.com"
11
+ s.homepage = "https://github.com/rainerborene/f2b"
12
+ s.summary = "F2b - Serviço de Cobranças"
13
+ s.description = "Integração com o serviço da F2b para envio e agendamento de cobranças."
14
+ s.required_ruby_version = ">= 1.8.6"
15
+
16
+ s.files = `git ls-files`.split("\n")
17
+ s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
18
+ s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
19
+
20
+ s.require_path = 'lib'
21
+
22
+ s.add_dependency("curb", ">= 0.7.8")
23
+ s.add_dependency("nokogiri", ">= 0")
24
+ s.add_dependency("handsoap", ">= 1.1.7")
25
+ end
@@ -0,0 +1,8 @@
1
+ require 'cgi'
2
+ require 'handsoap'
3
+ require 'f2b/cobranca'
4
+ require 'f2b/cobranca_status'
5
+
6
+ module F2b
7
+ VERSION = '0.1.0'
8
+ end
@@ -0,0 +1,155 @@
1
+ # encoding: utf-8
2
+ module F2b
3
+ class Cobranca < Handsoap::Service
4
+ endpoint :uri => "https://www.f2b.com.br/WSBilling", :version => 1
5
+
6
+ attr_accessor :numero
7
+ attr_accessor :sacador
8
+ attr_accessor :cobranca
9
+ attr_reader :demonstrativo
10
+ attr_accessor :desconto
11
+ attr_accessor :multa
12
+ attr_accessor :agendamento
13
+ attr_reader :sacados
14
+
15
+ def initialize
16
+ @demonstrativo = []
17
+ @sacados = []
18
+ end
19
+
20
+ def on_create_document(doc)
21
+ doc.alias 'wsb', 'http://www.f2b.com.br/soap/wsbilling.xsd'
22
+ end
23
+
24
+ def on_response_document(doc)
25
+ doc.add_namespace 'm', 'http://www.f2b.com.br/soap/wsbilling.xsd'
26
+ end
27
+
28
+ def submit!
29
+ response = invoke("wsb:F2bCobranca") do |message|
30
+ message.add "mensagem" do |m|
31
+ m.set_attr "data", Date.today.to_s
32
+ m.set_attr "numero", @numero unless @numero.nil?
33
+ m.set_attr "tipo_ws", "WebService"
34
+ end
35
+
36
+ message.add "sacador" do |s|
37
+ s.set_attr "conta", @sacador.fetch(:conta)
38
+ s.set_attr "senha", @sacador.fetch(:senha)
39
+ s.set_value @sacador.fetch(:nome)
40
+ end
41
+
42
+ if @cobranca
43
+ message.add "cobranca" do |c|
44
+ c.set_attr "valor", @cobranca.fetch(:valor)
45
+ c.set_attr "tipo_cobranca", @cobranca.fetch(:tipo_cobranca) if @cobranca.has_key? :tipo_cobranca
46
+ c.set_attr "num_document", @cobranca.fetch(:num_document) if @cobranca.has_key? :num_document
47
+ c.set_attr "cod_banco", @cobranca.fetch(:cod_banco) if @cobranca.has_key? :cod_banco
48
+
49
+ @demonstrativo.each do |value|
50
+ c.add "demonstrativo", value
51
+ end
52
+
53
+ if @desconto
54
+ c.add "desconto" do |d|
55
+ d.set_attr "valor", @desconto.fetch(:valor)
56
+ d.set_attr "tipo_desconto", @desconto.fetch(:tipo_desconto)
57
+ d.set_attr "antecedencia", @desconto.fetch(:antecedencia)
58
+ end
59
+ end
60
+
61
+ if @multa
62
+ c.add "multa" do |m|
63
+ m.set_attr "valor", @multa.fetch(:valor)
64
+ m.set_attr "tipo_multa", @multa.fetch(:tipo_multa)
65
+ m.set_attr "valor_dia", @multa.fetch(:valor_dia)
66
+ m.set_attr "tipo_multa_dia", @multa.fetch(:tipo_multa_dia)
67
+ m.set_attr "atraso", @multa.fetch(:atraso)
68
+ end
69
+ end
70
+ end
71
+
72
+ message.add "agendamento" do |a|
73
+ a.set_attr "vencimento", @agendamento.fetch(:vencimento)
74
+ a.set_attr "ultimo_dia", @agendamento.fetch(:ultimo_dia) if @agendamento.has_key? :ultimo_dia
75
+ a.set_attr "antecedencia", @agendamento.fetch(:antecedencia) if @agendamento.has_key? :antecedencia
76
+ a.set_attr "periodicidade", @agendamento.fetch(:periodicidade) if @agendamento.has_key? :periodicidade
77
+ a.set_attr "periodos", @agendamento.fetch(:periodos) if @agendamento.has_key? :periodos
78
+ a.set_attr "sem_vencimento", @agendamento.fetch(:sem_vencimento) if @agendamento.has_key? :sem_vencimento
79
+ a.set_value @agendamento.fetch(:titulo) if @agendamento.has_key? :titulo
80
+ end
81
+ end
82
+
83
+ # 1 ou mais sacados
84
+ @sacados.each do |sacado|
85
+ message.add "sacado" do |s|
86
+ s.set_attr "grupo", sacado.fetch(:grupo) if sacado.has_key? :grupo
87
+ s.set_attr "codigo", sacado.fetch(:codigo) if sacado.has_key? :codigo
88
+ s.set_attr "envio", sacado.fetch(:envio) if sacado.has_key? :envio
89
+ s.set_attr "atualizar", sacado.fetch(:atualizar) if sacado.has_key? :atualizar
90
+
91
+ s.add "nome", sacado.fetch(:nome)
92
+ s.add "email", sacado.fetch(:email)
93
+
94
+ build_address!(s, sacado[:endereco]) if sacado.has_key? :endereco
95
+ build_phones!(s, sacado)
96
+
97
+ s.add "cpf", sacado.fetch(:cpf) if sacado.has_key? :cpf
98
+ s.add "cnpj", sacado.fetch(:cnpj) if sacado.has_key? :cnpj
99
+ s.add "observacao", sacado.fetch(:observacao) if sacado.has_key? :observacao
100
+ end
101
+ end
102
+ end
103
+
104
+ parse_response(response)
105
+ end
106
+
107
+ private
108
+
109
+ def parse_response(response)
110
+ cobrancas = []
111
+ message = CGI.unescapeHTML((response/"//log").to_s)
112
+
113
+ if message.include? "ERRO"
114
+ raise message
115
+ else
116
+ (response/"//cobranca").each do |node|
117
+ cobranca = {}
118
+ cobranca[:nome] = node/"nome".to_s
119
+ cobranca[:email] = node/"email".to_s
120
+ cobranca[:url] = node/"url".to_s
121
+ cobrancas.push(cobranca)
122
+ end
123
+ end
124
+
125
+ cobrancas.empty? ? message : cobrancas
126
+ end
127
+
128
+ def build_address!(node, address)
129
+ node.add "endereco" do |e|
130
+ e.set_attr "logradouro", address.fetch(:logradouro)
131
+ e.set_attr "numero", address.fetch(:numero)
132
+ e.set_attr "complemento", address.fetch(:complemento) if address.has_key? :complemento
133
+ e.set_attr "bairro", address.fetch(:bairro) if address.has_key? :bairro
134
+ e.set_attr "cidade", address.fetch(:cidade)
135
+ e.set_attr "estado", address.fetch(:estado)
136
+ e.set_attr "cep", address.fetch(:cep)
137
+ end
138
+ end
139
+
140
+ def build_phones!(node, source)
141
+ phones = source.select { |k, v| [:telefone, :telefone_com, :telefone_cel].include? k }
142
+
143
+ phones.each do |key|
144
+ type = key.to_s.gsub("_\w+$").to_s
145
+ prefix = source[key][:ddd]
146
+ number = source[key][:numero]
147
+
148
+ node.add(key.to_s) do |p|
149
+ p.set_attr "ddd#{type}", prefix
150
+ p.set_attr "numero#{type}", number
151
+ end
152
+ end
153
+ end
154
+ end
155
+ end
@@ -0,0 +1,81 @@
1
+ # encoding: utf-8
2
+ module F2b
3
+ class Cobranca::Status < Handsoap::Service
4
+ endpoint :uri => "https://www.f2b.com.br/WSBillingStatus", :version => 1
5
+
6
+ attr_accessor :mensagem
7
+ attr_accessor :cliente
8
+ attr_accessor :cobranca
9
+
10
+ def on_create_document(doc)
11
+ doc.alias 'wsb', 'http://www.f2b.com.br/soap/wsbillingstatus.xsd'
12
+ end
13
+
14
+ def on_response_document(doc)
15
+ doc.add_namespace 'm', 'http://www.f2b.com.br/soap/wsbillingstatus.xsd'
16
+ end
17
+
18
+ def submit!
19
+ response = invoke("wsb:F2bSituacaoCobranca") do |message|
20
+ message.add "mensagem" do |m|
21
+ m.set_attr "data", @mensagem.fetch(:data)
22
+ m.set_attr "numero", @mensagem.fetch(:numero)
23
+ end
24
+
25
+ message.add "cliente" do |c|
26
+ c.set_attr "conta", @cliente.fetch(:conta)
27
+ c.set_attr "senha", @cliente.fetch(:senha)
28
+ end
29
+
30
+ message.add "cobranca" do |c|
31
+ build_chooseable_attr! c, :numero, @cobranca
32
+ build_chooseable_attr! c, :registro, @cobranca
33
+ build_chooseable_attr! c, :vencimento, @cobranca
34
+ build_chooseable_attr! c, :processamento, @cobranca
35
+ build_chooseable_attr! c, :credito, @cobranca
36
+
37
+ c.set_attr "cod_sacado", @cobranca.fetch(:cod_sacado) if @cobranca.has_key? :cod_sacado
38
+ c.set_attr "cod_grupo", @cobranca.fetch(:cod_grupo) if @cobranca.has_key? :cod_grupo
39
+ c.set_attr "tipo_pagamento", @cobranca.fetch(:tipo_pagamento) if @cobranca.has_key? :tipo_pagamento
40
+ c.set_attr "numero_documento", @cobranca.fetch(:numero_documento) if @cobranca.has_key? :numero_documento
41
+ end
42
+ end
43
+
44
+ parse_response(response)
45
+ end
46
+
47
+ private
48
+
49
+ def build_chooseable_attr!(node, name, source)
50
+ other = "#{name.to_s}_final".to_sym
51
+
52
+ if source.has_key? name
53
+ node.set_attr(name.to_s, source.fetch(name))
54
+ elsif source.has_key? other
55
+ node.set_attr(other.to_s, source.fetch(other))
56
+ end
57
+ end
58
+
59
+ def parse_response(response)
60
+ cobranca = {}
61
+ message = CGI.unescapeHTML((response/"//log").to_s)
62
+
63
+ if message.include? "ERRO"
64
+ raise message
65
+ else
66
+ (response/"//cobranca").each do |node|
67
+ node.attributes.each_pair do |key, value|
68
+ cobranca[key.to_sym] = value
69
+ end
70
+
71
+ node.xpath("*").each do |n|
72
+ nodename = n.nodename.to_sym
73
+ cobranca[nodename] = n.to_s
74
+ end
75
+ end
76
+ end
77
+
78
+ cobranca.empty? ? message : cobranca
79
+ end
80
+ end
81
+ end
@@ -0,0 +1,22 @@
1
+ # encoding: utf-8
2
+ require 'spec'
3
+ require 'f2b'
4
+
5
+ describe "Cobranca" do
6
+
7
+ before :all do
8
+ @cobranca = F2b::Cobranca.new
9
+ @cobranca.numero = "000000001"
10
+ @cobranca.sacador = {:conta => "5718973289173910", :senha => "morales", :nome => "Susan Morales"}
11
+ @cobranca.cobranca = {:valor => 10.00}
12
+ @cobranca.demonstrativo.concat ["Mensalidade"]
13
+ @cobranca.agendamento = {:vencimento => (Date.today + 5).to_s, :periodos => 12, :titulo => "Mensalidade"}
14
+ @cobranca.sacados.push({:nome => "Sheng Hou", :email => "teste@f2b.com.br", :envio => "e"})
15
+ @cobranca = @cobranca.submit!
16
+ end
17
+
18
+ it "should be sent without any errors" do
19
+ @cobranca.should == "OK\r\nTESTE"
20
+ end
21
+
22
+ end
@@ -0,0 +1,19 @@
1
+ # encoding: utf-8
2
+ require 'spec'
3
+ require 'f2b'
4
+
5
+ describe "Status" do
6
+
7
+ before :all do
8
+ @situacao = F2b::Cobranca::Status.new
9
+ @situacao.mensagem = {:data => Date.today.to_s, :numero => "000000001"}
10
+ @situacao.cliente = {:conta => "3712897519713890", :senha => "morales"}
11
+ @situacao.cobranca = {:numero => "000000001", :registro => "", :vencimento => "", :processamento => "", :credito => ""}
12
+ @situacao = @situacao.submit!
13
+ end
14
+
15
+ it "should be sent without any errors" do
16
+ @situacao.should == "OK\r\n"
17
+ end
18
+
19
+ end
metadata ADDED
@@ -0,0 +1,121 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: f2b
3
+ version: !ruby/object:Gem::Version
4
+ hash: 27
5
+ prerelease:
6
+ segments:
7
+ - 0
8
+ - 1
9
+ - 0
10
+ version: 0.1.0
11
+ platform: ruby
12
+ authors:
13
+ - Rainer Borene
14
+ autorequire:
15
+ bindir: bin
16
+ cert_chain: []
17
+
18
+ date: 2011-09-11 00:00:00 Z
19
+ dependencies:
20
+ - !ruby/object:Gem::Dependency
21
+ name: curb
22
+ prerelease: false
23
+ requirement: &id001 !ruby/object:Gem::Requirement
24
+ none: false
25
+ requirements:
26
+ - - ">="
27
+ - !ruby/object:Gem::Version
28
+ hash: 19
29
+ segments:
30
+ - 0
31
+ - 7
32
+ - 8
33
+ version: 0.7.8
34
+ type: :runtime
35
+ version_requirements: *id001
36
+ - !ruby/object:Gem::Dependency
37
+ name: nokogiri
38
+ prerelease: false
39
+ requirement: &id002 !ruby/object:Gem::Requirement
40
+ none: false
41
+ requirements:
42
+ - - ">="
43
+ - !ruby/object:Gem::Version
44
+ hash: 3
45
+ segments:
46
+ - 0
47
+ version: "0"
48
+ type: :runtime
49
+ version_requirements: *id002
50
+ - !ruby/object:Gem::Dependency
51
+ name: handsoap
52
+ prerelease: false
53
+ requirement: &id003 !ruby/object:Gem::Requirement
54
+ none: false
55
+ requirements:
56
+ - - ">="
57
+ - !ruby/object:Gem::Version
58
+ hash: 29
59
+ segments:
60
+ - 1
61
+ - 1
62
+ - 7
63
+ version: 1.1.7
64
+ type: :runtime
65
+ version_requirements: *id003
66
+ description: "Integra\xC3\xA7\xC3\xA3o com o servi\xC3\xA7o da F2b para envio e agendamento de cobran\xC3\xA7as."
67
+ email: me@rainerborene.com
68
+ executables: []
69
+
70
+ extensions: []
71
+
72
+ extra_rdoc_files: []
73
+
74
+ files:
75
+ - .gitignore
76
+ - README.md
77
+ - Rakefile
78
+ - f2b.gemspec
79
+ - lib/f2b.rb
80
+ - lib/f2b/cobranca.rb
81
+ - lib/f2b/cobranca_status.rb
82
+ - spec/cobranca_spec.rb
83
+ - spec/status_spec.rb
84
+ homepage: https://github.com/rainerborene/f2b
85
+ licenses: []
86
+
87
+ post_install_message:
88
+ rdoc_options: []
89
+
90
+ require_paths:
91
+ - lib
92
+ required_ruby_version: !ruby/object:Gem::Requirement
93
+ none: false
94
+ requirements:
95
+ - - ">="
96
+ - !ruby/object:Gem::Version
97
+ hash: 59
98
+ segments:
99
+ - 1
100
+ - 8
101
+ - 6
102
+ version: 1.8.6
103
+ required_rubygems_version: !ruby/object:Gem::Requirement
104
+ none: false
105
+ requirements:
106
+ - - ">="
107
+ - !ruby/object:Gem::Version
108
+ hash: 3
109
+ segments:
110
+ - 0
111
+ version: "0"
112
+ requirements: []
113
+
114
+ rubyforge_project:
115
+ rubygems_version: 1.8.5
116
+ signing_key:
117
+ specification_version: 3
118
+ summary: "F2b - Servi\xC3\xA7o de Cobran\xC3\xA7as"
119
+ test_files:
120
+ - spec/cobranca_spec.rb
121
+ - spec/status_spec.rb