itau_shopline 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source "http://rubygems.org"
2
+
3
+ # Specify your gem's dependencies in itau_cripto.gemspec
4
+ gemspec
data/README.markdown ADDED
@@ -0,0 +1,157 @@
1
+ Itau Shopline (itau_cripto)
2
+ ------------
3
+
4
+ Gem para integração com Itau Shopline.
5
+
6
+ ### Observação
7
+
8
+ O código desta gem é muito ruim pois foi "extraído" de uma classe Java fornecido pelo banco,
9
+ em breve estarei melhorando isso inclusive adicionando testes unitários, caso você possa
10
+ contribuir entre em contato comigo.
11
+
12
+ COMO USAR
13
+ ---------
14
+
15
+
16
+ ### Configuração
17
+
18
+ O primeiro passo é instalar a gem.
19
+
20
+ ```ruby
21
+ gem install itau_shopline
22
+ ```
23
+
24
+ ou no Gemfile
25
+
26
+ ```ruby
27
+ gem itau_shopline
28
+ ```
29
+
30
+ Depois de instalar, você precisará informar seus dados criando o arquivo:
31
+
32
+ ### config/itau_shopline.yml
33
+
34
+ ```yaml
35
+ development:
36
+ codigo_empresa: CÓDIGO DA EMPRESA
37
+ chave: CHAVE FORNECIDA PELO BANCO
38
+
39
+ test:
40
+ codigo_empresa: CÓDIGO DA EMPRESA
41
+ chave: CHAVE FORNECIDA PELO BANCO
42
+
43
+ production:
44
+ codigo_empresa: CÓDIGO DA EMPRESA
45
+ chave: CHAVE FORNECIDA PELO BANCO
46
+
47
+ staging:
48
+ codigo_empresa: CÓDIGO DA EMPRESA
49
+ chave: CHAVE FORNECIDA PELO BANCO
50
+
51
+ ```
52
+
53
+ Efetuando uma transação
54
+ -----------------------
55
+
56
+ Para efetuar uma compra você pode usar a ```ItauCripto``` direto e seguir o manual do banco,
57
+ ou usar uma helper class chamada ```ItauShopline```, segue exemplo.
58
+
59
+ ```ruby
60
+
61
+ # gera_dados(invoice_id, total_price, full_name, city_name, state_uf, due_date=nil, return_url="")
62
+ # Atenção: Você deve passar somente o path de retorno,
63
+ # pois o banco ira concatenar isso ao endereço principal do site cadastrado.
64
+
65
+ @itau_dc = ItauShopline.new.gera_dados(1, 22.50, 'Fulano de Tal', 'Goiânia', 'GO', nil, 'faturamento/itau/aviso')
66
+
67
+ ```
68
+
69
+ Após isso vc deve chamar a tela para pagamentos.
70
+
71
+ ```html
72
+ <script type="text/javascript" charset="utf-8">
73
+ function carregaItauShopline() {
74
+ window.open('https://shopline.itau.com.br/shopline/shopline.aspx?DC=<%= @itau_dc %>', 'SHOPLINE', "toolbar=yes,menubar=yes,resizable=yes,status=no,scrollbars=yes,width=675,height=485");
75
+ }
76
+
77
+ $(function(){
78
+ carregaItauShopline();
79
+ });
80
+ </script>
81
+ <div id="itau-shopline">
82
+ <h1>Iniciando Itaú Shopline...</h1><br />
83
+ <%= link_to 'Caso o Itau Shopline não inicie automaticamente, clique aqui...', '#', :onclick => 'carregaItauShopline();' %>
84
+ </div>
85
+ ```
86
+
87
+ ### Recebendo retorno dos dados.
88
+
89
+ Após fazer o pagamento, o usuário vai ser direcionado para a URL de retorno informada, juntamente
90
+ com os dados da compra em um parâmetro chamado 'DC'
91
+
92
+ ```ruby
93
+ class BillingController < ApplicationController
94
+
95
+ def notify
96
+ notification = ItauShopline.new.dcript_transaction_notify(params['DC'])
97
+
98
+ # Pesquiso a fatura usando o código do pedido.
99
+ invoice = Invoice.find notification[:num_ped]
100
+
101
+ # Muda o status do pedido de acordo com os dados fornecidos.
102
+ invoice.update_by_itau_shopline
103
+
104
+ # Redireciona para uma página de pós compra.
105
+ redirect_to payment_confirmation_url
106
+ end
107
+ end
108
+
109
+ ```
110
+
111
+ ### Outras informação de retorno.
112
+
113
+ ```ruby
114
+
115
+ ItauShopline.new.dcript_transaction_notify(params['DC'])
116
+ => {"CodEmp"=>"NNNNNNNNNNNNNNN", "Pedido"=>"00010000", "Valor"=>"", "tipPag"=>:undefined, "sitPag"=>:pending, "dtPag"=>"", "codAut"=>"", "numId"=>"", "compVend"=>"", "tipCart"=>""}
117
+
118
+ ```
119
+ ## Pesquisando um pedido.
120
+
121
+ Caso seja necessário pesquisar por uma fatura:
122
+
123
+ ```ruby
124
+ shopline = ItauShopline.new
125
+ shopline.get_invoice_details(1) # Número do pedido.
126
+ => {"CodEmp"=>"NNNNNNNNNNNNNNN", "Pedido"=>"00000001", "Valor"=>"", "tipPag"=>:undefined, "sitPag"=>:pending, "dtPag"=>"", "codAut"=>"", "numId"=>"", "compVend"=>"", "tipCart"=>""}
127
+ end
128
+ ```
129
+
130
+ AUTOR:
131
+ ------
132
+
133
+ Bruno Frank Silva Cordeiro bfscordeiro (at) gmail (dot) com
134
+
135
+ LICENÇA:
136
+ --------
137
+
138
+ (The MIT License)
139
+
140
+ Permission is hereby granted, free of charge, to any person obtaining
141
+ a copy of this software and associated documentation files (the
142
+ 'Software'), to deal in the Software without restriction, including
143
+ without limitation the rights to use, copy, modify, merge, publish,
144
+ distribute, sublicense, and/or sell copies of the Software, and to
145
+ permit persons to whom the Software is furnished to do so, subject to
146
+ the following conditions:
147
+
148
+ The above copyright notice and this permission notice shall be
149
+ included in all copies or substantial portions of the Software.
150
+
151
+ THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,
152
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
153
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
154
+ IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
155
+ CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
156
+ TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
157
+ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/Rakefile ADDED
@@ -0,0 +1 @@
1
+ require "bundler/gem_tasks"
@@ -0,0 +1,23 @@
1
+ # -*- encoding: utf-8 -*-
2
+ $:.push File.expand_path("../lib", __FILE__)
3
+ require "itau_shopline/version"
4
+
5
+ Gem::Specification.new do |s|
6
+ s.name = "itau_shopline"
7
+ s.version = ItauShopline::VERSION
8
+ s.authors = ["Bruno Frank Cordeiro"]
9
+ s.email = ["bfscordeiro@gmail.com"]
10
+ s.homepage = ""
11
+ s.summary = %q{Integração com Itau Shopline}
12
+ s.description = %q{Gem para integração com Itau Shopline e implementação do itaucripto}
13
+
14
+
15
+ s.files = `git ls-files`.split("\n")
16
+ s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
17
+ s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
18
+ s.require_paths = ["lib"]
19
+
20
+ # specify any dependencies here; for example:
21
+ # s.add_development_dependency "rspec"
22
+ # s.add_runtime_dependency "rest-client"
23
+ end
@@ -0,0 +1,235 @@
1
+ # -*- encoding: utf-8 -*-
2
+
3
+ class ItauCripto
4
+
5
+ attr_reader :codEmp, :tipPag, :numPed
6
+
7
+ CHAVE_ITAU = "SEGUNDA12345ITAU"
8
+ TAM_COD_EMP = 26
9
+ TAM_CHAVE = 16
10
+
11
+ def initialize
12
+ @sbox = []
13
+ @key = []
14
+ @numPed = ''
15
+ @tipPag = ''
16
+ @codEmp = ''
17
+ @dados = nil
18
+ end
19
+
20
+ def gera_dados(param_string1, param_string2, param_string3, param_string4, param_string5, param_string6, param_string7, param_string8, param_string9, param_string10, param_string11, param_string12, param_string13, param_string14, param_string15, param_string16, param_string17, param_string18)
21
+ param_string1 = param_string1.upcase
22
+ param_string5 = param_string5.upcase
23
+
24
+
25
+ return "Erro: tamanho do codigo da empresa diferente de 26 posições." if param_string1.size != TAM_COD_EMP
26
+ return "Erro: tamanho da chave da chave diferente de 16 posições." if param_string5.size != TAM_CHAVE
27
+ return "Erro: número do pedido inválido." if param_string2.size < 1 || param_string2.size > 8
28
+
29
+ if is_numeric(param_string2)
30
+ param_string2 = preenche_zero(param_string2, 8)
31
+ else
32
+ return "Erro: numero do pedido não é numérico."
33
+ end
34
+
35
+ return "Erro: valor da compra inválido." if param_string3.size < 1 || param_string3.size > 11
36
+
37
+ i = param_string3 =~ /,/
38
+ if i
39
+ str3 = param_string3[(i + 1)..-1]
40
+
41
+ return "Erro: valor decimal não é numérico." if !is_numeric(str3)
42
+ return "Erro: valor decimal da compra deve possuir 2 posições após a virgula." if str3.size != 2
43
+
44
+ param_string3 = param_string3[0, (param_string3.size - 3)] + str3
45
+ else
46
+ return "Erro: valor da compra não é numérico." if !is_numeric(param_string3)
47
+ return "Erro: valor da compra deve possuir no máximo 8 posições antes da virgula." if param_string3.size > 8
48
+
49
+ param_string3 = param_string3 + "00"
50
+ end
51
+
52
+ param_string3 = preenche_zero(param_string3, 10)
53
+
54
+ param_string7 = param_string7.strip
55
+
56
+
57
+ return "Erro: código de inscrição inválido." if param_string7 != "02" && param_string7 != "01" && param_string7 != ""
58
+ return "Erro: número de inscrição inválido." if param_string8 != "" && !is_numeric(param_string8) && param_string8.size > 14
59
+ return "Erro: cep inválido." if param_string11 != "" && !is_numeric(param_string11) || param_string11.size != 8
60
+ return "Erro: data de vencimento inválida." if param_string14 != "" && !is_numeric(param_string14) || param_string14.size != 8
61
+ return "Erro: observação adicional 1 inválida." if param_string16.size > 60
62
+ return "Erro: observação adicional 2 inválida." if param_string17.size > 60
63
+ return "Erro: observação adicional 3 inválida." if param_string18.size > 60
64
+
65
+ param_string4 = preenche_branco(param_string4, 40)
66
+ param_string6 = preenche_branco(param_string6, 30)
67
+ param_string7 = preenche_branco(param_string7, 2)
68
+ param_string8 = preenche_branco(param_string8, 14)
69
+ param_string9 = preenche_branco(param_string9, 40)
70
+ param_string10 = preenche_branco(param_string10, 15)
71
+ param_string11 = preenche_branco(param_string11, 8)
72
+ param_string12 = preenche_branco(param_string12, 15)
73
+ param_string13 = preenche_branco(param_string13, 2)
74
+ param_string14 = preenche_branco(param_string14, 8)
75
+ param_string15 = preenche_branco(param_string15, 60)
76
+ param_string16 = preenche_branco(param_string16, 60)
77
+ param_string17 = preenche_branco(param_string17, 60)
78
+ param_string18 = preenche_branco(param_string18, 60)
79
+
80
+ str1 = algoritmo(param_string2 + param_string3 + param_string4 + param_string6 + param_string7 + param_string8 + param_string9 + param_string10 + param_string11 + param_string12 + param_string13 + param_string14 + param_string15 + param_string16 + param_string17 + param_string18, param_string5)
81
+ str2 = algoritmo(param_string1 + str1, CHAVE_ITAU)
82
+
83
+ converte(str2)
84
+ end
85
+
86
+ def gera_cripto(param_string1, param_string2, param_string3)
87
+ return "Erro: tamanho do codigo da empresa diferente de 26 posições." if param_string1.size != TAM_COD_EMP
88
+ return "Erro: tamanho da chave da chave diferente de 16 posições." if param_string3.size != TAM_CHAVE
89
+
90
+ param_string2 = param_string2.strip
91
+
92
+ return "Erro: código do sacado inválido." if param_string2 == ""
93
+
94
+ str1 = algoritmo(param_string2, param_string3)
95
+ str2 = algoritmo(param_string1 + str1, CHAVE_ITAU)
96
+
97
+ converte(str2)
98
+ end
99
+
100
+ def gera_consulta(param_string1, param_string2, param_string3, param_string4)
101
+ return "Erro: tamanho do codigo da empresa diferente de 26 posições." if param_string1.size != TAM_COD_EMP
102
+ return "Erro: tamanho da chave da chave diferente de 16 posições." if param_string4.size != TAM_CHAVE
103
+ return "Erro: número do pedido inválido." if param_string2.size < 1 || param_string2.size > 8
104
+
105
+ if is_numeric(param_string2)
106
+ param_string2 = preenche_zero(param_string2, 8)
107
+ else
108
+ return "Erro: numero do pedido não é numérico."
109
+ end
110
+
111
+ return "Erro: formato inválido." if param_string3 != "0" && param_string3 != "1"
112
+
113
+ str1 = algoritmo(param_string2 + param_string3, param_string4)
114
+
115
+ str2 = algoritmo(param_string1 + str1, CHAVE_ITAU)
116
+
117
+ converte(str2)
118
+ end
119
+
120
+ def decripto(param_string1, param_string2)
121
+ param_string1 = desconverte(param_string1)
122
+
123
+ str = algoritmo(param_string1, param_string2)
124
+
125
+ {:cod_emp => str[0, 26], :num_ped => str[26, 8], :tip_pag => str[34, 2]}
126
+ end
127
+
128
+ def gera_dados_generico(param_string1, param_string2, param_string3)
129
+ param_string1 = param_string1.upcase
130
+ param_string3 = param_string3.upcase
131
+
132
+
133
+ return "Erro: tamanho do codigo da empresa diferente de 26 posições." if param_string1.size != TAM_COD_EMP
134
+ return "Erro: tamanho da chave da chave diferente de 16 posições." if param_string3.size != TAM_CHAVE
135
+ return "Erro: sem dados." if param_string2.size < 1
136
+
137
+ str1 = algoritmo(param_string2, param_string3)
138
+
139
+ str2 = algoritmo(param_string1 + str1, CHAVE_ITAU)
140
+
141
+ converte(str2)
142
+ end
143
+
144
+ #private
145
+
146
+ def algoritmo(param_string1, param_string2)
147
+ k = 0
148
+ m = 0
149
+
150
+ str = ""
151
+ inicializa(param_string2)
152
+ for j in 1..param_string1.size do
153
+ k = (k + 1) % 256
154
+ m = (m + @sbox[k]) % 256
155
+ i = @sbox[k]
156
+ @sbox[k] = @sbox[m]
157
+ @sbox[m] = i
158
+
159
+ n = @sbox[((@sbox[k] + @sbox[m]) % 256)]
160
+
161
+ i1 = param_string1[j - 1].ord ^ n
162
+
163
+ str = str + i1.chr
164
+ end
165
+
166
+ str
167
+ end
168
+
169
+ def preenche_zero(param_string, param_int)
170
+ "%0#{param_int}d" % param_string
171
+ end
172
+
173
+ def is_numeric(param_string)
174
+ param_string =~ /^[0-9]+$/
175
+ end
176
+
177
+ def inicializa(param_string)
178
+ m = param_string.size
179
+ for j in 0..255 do
180
+ @key[j] = param_string[j % m].ord
181
+ @sbox[j] = j
182
+ end
183
+
184
+ k = 0
185
+ for j in 0..255 do
186
+ k = (k + @sbox[j] + @key[j]) % 256
187
+ i = @sbox[j]
188
+ @sbox[j] = @sbox[k]
189
+ @sbox[k] = i
190
+ end
191
+ end
192
+
193
+ def preenche_branco(param_string, param_int)
194
+ "%-#{param_int}s" % param_string
195
+ end
196
+
197
+ def converte(param_string)
198
+ c = (26.00 * rand + 65.00).to_i.chr
199
+ str = c
200
+
201
+ for i in 0..(param_string.size - 1) do
202
+
203
+ k = param_string[i].ord
204
+ j = k
205
+
206
+ str = str + j.to_s
207
+ c = (26.00 * rand + 65.00).to_i.chr
208
+ str = str + c
209
+ end
210
+
211
+ str
212
+ end
213
+
214
+ def desconverte(param_string)
215
+ str1 = ""
216
+ i = 0
217
+ while i < param_string.size do
218
+ str2 = ""
219
+
220
+ c = param_string[i]
221
+ puts c
222
+ while c =~ /[0-9]/ do
223
+ str2 = str2 + param_string[i]
224
+ i += 1
225
+ c = param_string[i]
226
+ end
227
+
228
+ str1 += str2.to_i.chr if str2 != ""
229
+
230
+ i += 1
231
+ end
232
+
233
+ str1
234
+ end
235
+ end
@@ -0,0 +1,112 @@
1
+ # -*- encoding: UTF-8 -*-
2
+
3
+ require "net/https"
4
+ require "uri"
5
+ require "rexml/document"
6
+ require "open-uri"
7
+
8
+ class ItauShopline
9
+ include ActionView::Helpers::NumberHelper
10
+
11
+ STATUS_TRANSLATE = {
12
+ :pending => 'Pendente',
13
+ :paid => 'Pago'
14
+ }
15
+
16
+ PAYMENT_TRANSLATE = {
17
+ :undefined => 'Não definido',
18
+ :online_transfer => 'Transferência',
19
+ :invoice => 'Boleto',
20
+ :credit_card => 'Cartão de crédito'
21
+ }
22
+
23
+ STATUS = {
24
+ :undefined => {
25
+ '01' => :pending,
26
+ '02' => :pending,
27
+ '03' => :pending
28
+ },
29
+ :online_transfer => {
30
+ '00' => :paid,
31
+ '01' => :pending,
32
+ '02' => :pending,
33
+ '03' => :pending
34
+ },
35
+ :invoice => {
36
+ '00' => :paid,
37
+ '01' => :pending,
38
+ '02' => :pending,
39
+ '03' => :pending,
40
+ '04' => :pending,
41
+ '05' => :paid,
42
+ '06' => :pending
43
+ },
44
+ :credit_card => {
45
+ '00' => :paid,
46
+ '01' => :pending,
47
+ '02' => :pending,
48
+ '03' => :pending
49
+ }
50
+ }
51
+
52
+ PAYMENT_METHODS = {
53
+ '00' => :undefined,
54
+ '01' => :online_transfer,
55
+ '02' => :invoice,
56
+ '03' => :credit_card
57
+ }
58
+
59
+ def gera_dados(invoice_id, total_price, full_name, city_name, state_uf, due_date=nil, return_url="")
60
+ cripto = ItauCripto.new
61
+ due_date ||= (Date.today + 3.days).strftime('%d%m%Y')
62
+ cripto.gera_dados(config['codigo_empresa'], invoice_id.to_s, number_to_currency(total_price, :unit => "", :separator => ",", :delimiter => ""), "", config['chave'], full_name, '01', '00000000000', '', '', "00000000", city_name[0,15], state_uf[0,2], due_date, return_url[0,60], '', '', '')
63
+ end
64
+
65
+ def dcript_transaction_notify(dados)
66
+ cripto = ItauCripto.new
67
+ cripto.decripto(dados, config['chave'])
68
+ end
69
+
70
+ def get_invoice_details(invoice_id)
71
+ cripto = ItauCripto.new
72
+ token = cripto.gera_consulta(config['codigo_empresa'], invoice_id.to_s, '1',config['chave'])
73
+ xml = open("https://shopline.itau.com.br/shopline/consulta.aspx?DC=#{token}").read
74
+
75
+ treat_itau_data xml
76
+ end
77
+
78
+ private
79
+ def treat_itau_data(dados)
80
+ treated_data = {}
81
+
82
+ response = REXML::Document.new(dados)
83
+ params = response.elements['consulta'].elements['PARAMETER']
84
+ params.elements.each do |param|
85
+ treated_data[param.attributes['ID']] = param.attributes['VALUE']
86
+ end
87
+
88
+ new_result = {}
89
+ treated_data.each do |field, value|
90
+ value = PAYMENT_METHODS[value] if field == 'tipPag'
91
+ value = STATUS[PAYMENT_METHODS[treated_data['tipPag']]][value] if field == 'sitPag'
92
+
93
+ new_result[field] = value
94
+ end
95
+
96
+ new_result
97
+ end
98
+
99
+ def config
100
+ # load file if is not loaded yet
101
+ @@config ||= YAML.load_file(Rails.root.join("config/itau_shopline.yml"))
102
+
103
+ # raise an exception if the environment hasn't been set
104
+ # or if file is empty
105
+ if @@config == false || !@@config[Rails.env]
106
+ raise MissingEnvironmentError, ":#{Rails.env} environment not set on #{config_file.inspect}"
107
+ end
108
+
109
+ # retrieve the environment settings
110
+ @@config[Rails.env]
111
+ end # Load configuration file.
112
+ end
@@ -0,0 +1,3 @@
1
+ module ItauShopline
2
+ VERSION = "0.0.1"
3
+ end
@@ -0,0 +1,7 @@
1
+ require "itau_shopline/version"
2
+ require "itau_shopline/itau_cripto"
3
+ require "itau_shopline/itau_shopline"
4
+
5
+ module ItauShopline
6
+ # Your code goes here...
7
+ end
metadata ADDED
@@ -0,0 +1,64 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: itau_shopline
3
+ version: !ruby/object:Gem::Version
4
+ prerelease:
5
+ version: 0.0.1
6
+ platform: ruby
7
+ authors:
8
+ - Bruno Frank Cordeiro
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+
13
+ date: 2012-01-18 00:00:00 -02:00
14
+ default_executable:
15
+ dependencies: []
16
+
17
+ description: "Gem para integra\xC3\xA7\xC3\xA3o com Itau Shopline e implementa\xC3\xA7\xC3\xA3o do itaucripto"
18
+ email:
19
+ - bfscordeiro@gmail.com
20
+ executables: []
21
+
22
+ extensions: []
23
+
24
+ extra_rdoc_files: []
25
+
26
+ files:
27
+ - Gemfile
28
+ - README.markdown
29
+ - Rakefile
30
+ - itau_shopline.gemspec
31
+ - lib/itau_shopline.rb
32
+ - lib/itau_shopline/itau_cripto.rb
33
+ - lib/itau_shopline/itau_shopline.rb
34
+ - lib/itau_shopline/version.rb
35
+ has_rdoc: true
36
+ homepage: ""
37
+ licenses: []
38
+
39
+ post_install_message:
40
+ rdoc_options: []
41
+
42
+ require_paths:
43
+ - lib
44
+ required_ruby_version: !ruby/object:Gem::Requirement
45
+ none: false
46
+ requirements:
47
+ - - ">="
48
+ - !ruby/object:Gem::Version
49
+ version: "0"
50
+ required_rubygems_version: !ruby/object:Gem::Requirement
51
+ none: false
52
+ requirements:
53
+ - - ">="
54
+ - !ruby/object:Gem::Version
55
+ version: "0"
56
+ requirements: []
57
+
58
+ rubyforge_project:
59
+ rubygems_version: 1.6.2
60
+ signing_key:
61
+ specification_version: 3
62
+ summary: "Integra\xC3\xA7\xC3\xA3o com Itau Shopline"
63
+ test_files: []
64
+