pagseguro 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (42) hide show
  1. data/.rspec +1 -0
  2. data/Gemfile +8 -0
  3. data/Gemfile.lock +104 -0
  4. data/README.markdown +212 -0
  5. data/Rakefile +25 -0
  6. data/lib/pagseguro.rb +66 -0
  7. data/lib/pagseguro/action_controller.rb +11 -0
  8. data/lib/pagseguro/developer_controller.rb +26 -0
  9. data/lib/pagseguro/generator.rb +12 -0
  10. data/lib/pagseguro/helper.rb +8 -0
  11. data/lib/pagseguro/notification.rb +192 -0
  12. data/lib/pagseguro/order.rb +73 -0
  13. data/lib/pagseguro/railtie.rb +23 -0
  14. data/lib/pagseguro/rake.rb +96 -0
  15. data/lib/pagseguro/routes.rb +4 -0
  16. data/lib/pagseguro/version.rb +8 -0
  17. data/lib/pagseguro/views/_form.html.erb +21 -0
  18. data/lib/tasks/pagseguro.rake +6 -0
  19. data/pagseguro.gemspec +95 -0
  20. data/spec/controllers/developer_controller_spec.rb +26 -0
  21. data/spec/helpers/helper_spec.rb +80 -0
  22. data/spec/pagseguro/notification_spec.rb +336 -0
  23. data/spec/pagseguro/order_spec.rb +79 -0
  24. data/spec/pagseguro/pagseguro_spec.rb +48 -0
  25. data/spec/pagseguro/rake_spec.rb +134 -0
  26. data/spec/spec_helper.rb +10 -0
  27. data/spec/support/app/controllers/application_controller.rb +2 -0
  28. data/spec/support/app/models/account.rb +2 -0
  29. data/spec/support/app/models/user.rb +3 -0
  30. data/spec/support/app/views/dashboard/index.erb +0 -0
  31. data/spec/support/app/views/session/new.erb +0 -0
  32. data/spec/support/config/boot.rb +14 -0
  33. data/spec/support/config/database.yml +3 -0
  34. data/spec/support/config/pagseguro.yml +12 -0
  35. data/spec/support/config/routes.rb +4 -0
  36. data/spec/support/log/development.log +0 -0
  37. data/spec/support/log/test.log +375 -0
  38. data/spec/support/matcher.rb +39 -0
  39. data/spec/support/pagseguro-test.yml +30 -0
  40. data/spec/support/tmp/pagseguro-test.yml +30 -0
  41. data/templates/config.yml +13 -0
  42. metadata +130 -0
@@ -0,0 +1,6 @@
1
+ namespace :pagseguro do
2
+ desc "Send notification to the URL specified in your config/pagseguro.yml file"
3
+ task :notify => :environment do
4
+ PagSeguro::Rake.run
5
+ end
6
+ end
data/pagseguro.gemspec ADDED
@@ -0,0 +1,95 @@
1
+ # Generated by jeweler
2
+ # DO NOT EDIT THIS FILE DIRECTLY
3
+ # Instead, edit Jeweler::Tasks in Rakefile, and run the gemspec command
4
+ # -*- encoding: utf-8 -*-
5
+
6
+ Gem::Specification.new do |s|
7
+ s.name = %q{pagseguro}
8
+ s.version = "0.1.0"
9
+
10
+ s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
11
+ s.authors = ["Nando Vieira"]
12
+ s.date = %q{2010-09-10}
13
+ s.description = %q{}
14
+ s.email = %q{fnando.vieira@gmail.com}
15
+ s.extra_rdoc_files = [
16
+ "README.markdown"
17
+ ]
18
+ s.files = [
19
+ ".rspec",
20
+ "Gemfile",
21
+ "Gemfile.lock",
22
+ "README.markdown",
23
+ "Rakefile",
24
+ "lib/pagseguro.rb",
25
+ "lib/pagseguro/action_controller.rb",
26
+ "lib/pagseguro/developer_controller.rb",
27
+ "lib/pagseguro/generator.rb",
28
+ "lib/pagseguro/helper.rb",
29
+ "lib/pagseguro/notification.rb",
30
+ "lib/pagseguro/order.rb",
31
+ "lib/pagseguro/railtie.rb",
32
+ "lib/pagseguro/rake.rb",
33
+ "lib/pagseguro/routes.rb",
34
+ "lib/pagseguro/version.rb",
35
+ "lib/pagseguro/views/_form.html.erb",
36
+ "lib/tasks/pagseguro.rake",
37
+ "pagseguro.gemspec",
38
+ "spec/controllers/developer_controller_spec.rb",
39
+ "spec/helpers/helper_spec.rb",
40
+ "spec/pagseguro/notification_spec.rb",
41
+ "spec/pagseguro/order_spec.rb",
42
+ "spec/pagseguro/pagseguro_spec.rb",
43
+ "spec/pagseguro/rake_spec.rb",
44
+ "spec/spec_helper.rb",
45
+ "spec/support/app/controllers/application_controller.rb",
46
+ "spec/support/app/models/account.rb",
47
+ "spec/support/app/models/user.rb",
48
+ "spec/support/app/views/dashboard/index.erb",
49
+ "spec/support/app/views/session/new.erb",
50
+ "spec/support/config/boot.rb",
51
+ "spec/support/config/database.yml",
52
+ "spec/support/config/pagseguro.yml",
53
+ "spec/support/config/routes.rb",
54
+ "spec/support/log/development.log",
55
+ "spec/support/log/test.log",
56
+ "spec/support/matcher.rb",
57
+ "spec/support/pagseguro-test.yml",
58
+ "spec/support/tmp/pagseguro-test.yml",
59
+ "templates/config.yml"
60
+ ]
61
+ s.homepage = %q{http://github.com/fnando/pagseguro}
62
+ s.rdoc_options = ["--charset=UTF-8"]
63
+ s.require_paths = ["lib"]
64
+ s.rubygems_version = %q{1.3.7}
65
+ s.summary = %q{A wrapper for the PagSeguro payment gateway.}
66
+ s.test_files = [
67
+ "spec/controllers/developer_controller_spec.rb",
68
+ "spec/helpers/helper_spec.rb",
69
+ "spec/pagseguro/notification_spec.rb",
70
+ "spec/pagseguro/order_spec.rb",
71
+ "spec/pagseguro/pagseguro_spec.rb",
72
+ "spec/pagseguro/rake_spec.rb",
73
+ "spec/spec_helper.rb",
74
+ "spec/support/app/controllers/application_controller.rb",
75
+ "spec/support/app/models/account.rb",
76
+ "spec/support/app/models/user.rb",
77
+ "spec/support/config/boot.rb",
78
+ "spec/support/config/routes.rb",
79
+ "spec/support/matcher.rb"
80
+ ]
81
+
82
+ if s.respond_to? :specification_version then
83
+ current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION
84
+ s.specification_version = 3
85
+
86
+ if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.2.0') then
87
+ s.add_development_dependency(%q<rspec>, [">= 2.0.0"])
88
+ else
89
+ s.add_dependency(%q<rspec>, [">= 2.0.0"])
90
+ end
91
+ else
92
+ s.add_dependency(%q<rspec>, [">= 2.0.0"])
93
+ end
94
+ end
95
+
@@ -0,0 +1,26 @@
1
+ require "spec_helper"
2
+
3
+ describe PagSeguro::DeveloperController do
4
+ let(:file_path) { PagSeguro::DeveloperController::PAGSEGURO_ORDERS_FILE }
5
+ let(:orders) { YAML.load_file(file_path) }
6
+
7
+ before do
8
+ File.unlink(file_path) if File.exist?(file_path)
9
+ end
10
+
11
+ it "should create file when it doesn't exist" do
12
+ post :create
13
+ File.should be_file(file_path)
14
+ end
15
+
16
+ it "should save sent params" do
17
+ post :create, :email_cobranca => "john@doe.com", :ref_transacao => "I1001"
18
+ orders["I1001"]["email_cobranca"].should == "john@doe.com"
19
+ orders["I1001"]["ref_transacao"].should == "I1001"
20
+ end
21
+
22
+ it "should redirect to the return url" do
23
+ post :create, :ref_transacao => "I1001"
24
+ response.should redirect_to("/invoices/confirmation")
25
+ end
26
+ end
@@ -0,0 +1,80 @@
1
+ # encoding: utf-8
2
+ require "spec_helper"
3
+
4
+ describe PagSeguro::Helper do
5
+ before do
6
+ @order = PagSeguro::Order.new("I1001")
7
+ PagSeguro.stub :developer?
8
+ end
9
+
10
+ subject {
11
+ Nokogiri::HTML(helper.pagseguro_form(@order)).css("form").first
12
+ }
13
+
14
+ context "with default attributes" do
15
+ it { should have_attr("accept-charset", "ISO-8859-1") }
16
+ it { should have_attr("action", PagSeguro::GATEWAY_URL) }
17
+ it { should have_attr("id", "pagseguro") }
18
+ it { should have_attr("class", "pagseguro") }
19
+ it { should have_input(:name => "tipo", :value => "CP") }
20
+ it { should have_input(:name => "moeda", :value => "BRL") }
21
+ it { should have_input(:name => "ref_transacao", :value => "I1001") }
22
+ it { should_not have_input(:name => "tipo_frete") }
23
+ it { should have_input(:name => "email_cobranca", :value => "john@doe.com") }
24
+ it { should have_input(:type => "submit", :value => "Pagar com PagSeguro") }
25
+ end
26
+
27
+ it "should include shipping type" do
28
+ @order.shipping_type = "SD"
29
+ subject.should have_input(:name => "tipo_frete", :value => "SD")
30
+ end
31
+
32
+ context "with custom attributes" do
33
+ subject {
34
+ Nokogiri::HTML(helper.pagseguro_form(@order, :submit => "Pague agora!", :email => "mary@example.com")).css("form").first
35
+ }
36
+
37
+ it { should have_input(:name => "email_cobranca", :value => "mary@example.com") }
38
+ it { should have_input(:type => "submit", :value => "Pague agora!") }
39
+ end
40
+
41
+ context "with minimum product info" do
42
+ before do
43
+ @order << { :id => 1001, :price => 10.00, :description => "Rails 3 e-Book" }
44
+ end
45
+
46
+ it { should have_input(:name => "item_quant_1", :value => "1") }
47
+ it { should have_input(:name => "item_id_1", :value => "1001") }
48
+ it { should have_input(:name => "item_valor_1", :value => "1000") }
49
+ it { should have_input(:name => "item_descr_1", :value => "Rails 3 e-Book") }
50
+ it { should_not have_input(:name => "item_peso_1") }
51
+ it { should_not have_input(:name => "item_frete_1") }
52
+ end
53
+
54
+ context "with optional product info" do
55
+ before do
56
+ @order << { :id => 1001, :price => 10.00, :description => "T-Shirt", :weight => 300, :shipping => 8.50, :quantity => 2 }
57
+ end
58
+
59
+ it { should have_input(:name => "item_quant_1", :value => "2") }
60
+ it { should have_input(:name => "item_peso_1", :value => "300") }
61
+ it { should have_input(:name => "item_frete_1", :value => "850") }
62
+ end
63
+
64
+ context "with multiple products" do
65
+ before do
66
+ @order << { :id => 1001, :price => 10.00, :description => "Rails 3 e-Book" }
67
+ @order << { :id => 1002, :price => 19.00, :description => "Rails 3 e-Book + Screencast" }
68
+ end
69
+
70
+ it { should have_input(:name => "item_quant_1", :value => "1") }
71
+ it { should have_input(:name => "item_id_1", :value => "1001") }
72
+ it { should have_input(:name => "item_valor_1", :value => "1000") }
73
+ it { should have_input(:name => "item_descr_1", :value => "Rails 3 e-Book") }
74
+
75
+ it { should have_input(:name => "item_quant_2", :value => "1") }
76
+ it { should have_input(:name => "item_id_2", :value => "1002") }
77
+ it { should have_input(:name => "item_valor_2", :value => "1900") }
78
+ it { should have_input(:name => "item_descr_2", :value => "Rails 3 e-Book + Screencast") }
79
+ end
80
+ end
@@ -0,0 +1,336 @@
1
+ # encoding: utf-8
2
+ require "spec_helper"
3
+
4
+ describe PagSeguro::Notification do
5
+ before do
6
+ @the_params = {}
7
+ @notification = PagSeguro::Notification.new(@the_params)
8
+ end
9
+
10
+ it "should not request the confirmation url when running developer mode" do
11
+ PagSeguro.stub!(:developer?).and_return(true)
12
+ Net::HTTP.should_not_receive(:new)
13
+ @notification.should be_valid
14
+ end
15
+
16
+ describe "status mapping" do
17
+ it "should be completed" do
18
+ set_status!("Completo")
19
+ @notification.status.should == :completed
20
+ end
21
+
22
+ it "should be pending" do
23
+ set_status!("Aguardando Pagto")
24
+ @notification.status.should == :pending
25
+ end
26
+
27
+ it "should be approved" do
28
+ set_status!("Aprovado")
29
+ @notification.status.should == :approved
30
+ end
31
+
32
+ it "should be verifying" do
33
+ set_status!("Em Análise")
34
+ @notification.status.should == :verifying
35
+ end
36
+
37
+ it "should be canceled" do
38
+ set_status!("Cancelado")
39
+ @notification.status.should == :canceled
40
+ end
41
+
42
+ it "should be refunded" do
43
+ set_status!("Devolvido")
44
+ @notification.status.should == :refunded
45
+ end
46
+ end
47
+
48
+ describe "payment mapping" do
49
+ it "should be credit card" do
50
+ set_payment!("Cartão de Crédito")
51
+ @notification.payment_method.should == :credit_card
52
+ end
53
+
54
+ it "should be invoice" do
55
+ set_payment!("Boleto")
56
+ @notification.payment_method.should == :invoice
57
+ end
58
+
59
+ it "should be pagseguro" do
60
+ set_payment!("Pagamento")
61
+ @notification.payment_method.should == :pagseguro
62
+ end
63
+
64
+ it "should be online transfer" do
65
+ set_payment!("Pagamento online")
66
+ @notification.payment_method.should == :online_transfer
67
+ end
68
+ end
69
+
70
+ describe "buyer mapping" do
71
+ it "should return client name" do
72
+ param!("CliNome", "John Doe")
73
+ @notification.buyer[:name].should == "John Doe"
74
+ end
75
+
76
+ it "should return client email" do
77
+ param!("CliEmail", "john@doe.com")
78
+ @notification.buyer[:email].should == "john@doe.com"
79
+ end
80
+
81
+ it "should return client phone" do
82
+ param!("CliTelefone", "11 55551234")
83
+ @notification.buyer[:phone][:area_code].should == "11"
84
+ @notification.buyer[:phone][:number].should == "55551234"
85
+ end
86
+
87
+ describe "address" do
88
+ it "should return street" do
89
+ param!("CliEndereco", "Av. Paulista")
90
+ @notification.buyer[:address][:street].should == "Av. Paulista"
91
+ end
92
+
93
+ it "should return number" do
94
+ param!("CliNumero", "2500")
95
+ @notification.buyer[:address][:number].should == "2500"
96
+ end
97
+
98
+ it "should return complements" do
99
+ param!("CliComplemento", "Apto 123-A")
100
+ @notification.buyer[:address][:complements].should == "Apto 123-A"
101
+ end
102
+
103
+ it "should return neighbourhood" do
104
+ param!("CliBairro", "Bela Vista")
105
+ @notification.buyer[:address][:neighbourhood].should == "Bela Vista"
106
+ end
107
+
108
+ it "should return city" do
109
+ param!("CliCidade", "São Paulo")
110
+ @notification.buyer[:address][:city].should == "São Paulo"
111
+ end
112
+
113
+ it "should return state" do
114
+ param!("CliEstado", "SP")
115
+ @notification.buyer[:address][:state].should == "SP"
116
+ end
117
+
118
+ it "should return postal code" do
119
+ param!("CliCEP", "01310300")
120
+ @notification.buyer[:address][:postal_code].should == "01310300"
121
+ end
122
+ end
123
+ end
124
+
125
+ describe "other mappings" do
126
+ it "should map the order id" do
127
+ param!("Referencia", "ABCDEF")
128
+ @notification.order_id.should == "ABCDEF"
129
+ end
130
+
131
+ it "should map the processing date" do
132
+ param!("DataTransacao", "04/09/2009 16:23:44")
133
+ @notification.processed_at.should == Time.parse("2009-09-04 16:23:44").utc
134
+ end
135
+
136
+ it "should map the shipping type" do
137
+ param!("TipoFrete", "SD")
138
+ @notification.shipping_type.should == "SD"
139
+ end
140
+
141
+ it "should map the client annotation" do
142
+ param!("Anotacao", "Gift package, please!")
143
+ @notification.notes.should == "Gift package, please!"
144
+ end
145
+
146
+ it "should map the shipping price" do
147
+ param!("ValorFrete", "199,38")
148
+ @notification.shipping.should == 199.38
149
+
150
+ param!("ValorFrete", "1.799,38")
151
+ @notification.shipping.should == 1799.38
152
+ end
153
+
154
+ it "should map the transaction id" do
155
+ param!("TransacaoID", "ABCDEF")
156
+ @notification.transaction_id.should == "ABCDEF"
157
+ end
158
+ end
159
+
160
+ describe "products" do
161
+ before do
162
+ @__products = []
163
+ end
164
+
165
+ it "should map 5 products" do
166
+ param!("NumItens", "5")
167
+ @notification.products.should have(5).items
168
+ end
169
+
170
+ it "should map 25 products" do
171
+ param!("NumItens", "25")
172
+ @notification.products.should have(25).items
173
+ end
174
+
175
+ it "should set attributes with defaults" do
176
+ set_product! :description => "Ruby 1.9 PDF", :price => "12,90", :id => 1
177
+ p = @notification.products.first
178
+
179
+ p[:description].should == "Ruby 1.9 PDF"
180
+ p[:price].should == 12.90
181
+ p[:id].should == "1"
182
+ p[:quantity].should == 1
183
+ p[:fees].should be_zero
184
+ p[:shipping].should be_zero
185
+ end
186
+
187
+ it "should set attributes with custom values" do
188
+ set_product!({
189
+ :description => "Rails Application Templates",
190
+ :price => "1,00",
191
+ :id => 8,
192
+ :fees => "2,53",
193
+ :shipping => "3,50",
194
+ :quantity => 10
195
+ })
196
+
197
+ p = @notification.products.first
198
+
199
+ p[:description].should == "Rails Application Templates"
200
+ p[:price].should == 1.00
201
+ p[:id].should == "8"
202
+ p[:quantity].should == 10
203
+ p[:fees].should == 2.53
204
+ p[:shipping].should == 3.50
205
+ end
206
+ end
207
+
208
+ describe "confirmation" do
209
+ before do
210
+ PagSeguro.stub!(:developer?).and_return(false)
211
+ @url = PagSeguro::Notification::API_URL
212
+ @notification.stub!(:api_url).and_return(@url)
213
+ end
214
+
215
+ it "should be valid" do
216
+ FakeWeb.register_uri(:post, @url, :body => "VERIFICADO")
217
+ @notification.should be_valid
218
+ end
219
+
220
+ it "should be invalid" do
221
+ FakeWeb.register_uri(:post, @url, :body => "")
222
+ @notification.should_not be_valid
223
+ end
224
+
225
+ it "should force validation" do
226
+ FakeWeb.register_uri(:post, @url, :body => "")
227
+ @notification.should_not be_valid
228
+
229
+ FakeWeb.register_uri(:post, @url, :body => "VERIFICADO")
230
+ @notification.should_not be_valid
231
+ @notification.should be_valid(:nocache)
232
+ end
233
+
234
+ it "should set the authenticity token from the initialization" do
235
+ notification = PagSeguro::Notification.new(@the_params, 'ABCDEF')
236
+
237
+ post = mock("post").as_null_object
238
+ post.should_receive(:set_form_data).with({:Comando => "validar", :Token => "ABCDEF"})
239
+
240
+ Net::HTTP.should_receive(:new).and_return(mock("http").as_null_object)
241
+ Net::HTTP::Post.should_receive(:new).and_return(post)
242
+
243
+ notification.valid?
244
+ end
245
+
246
+ it "should set the authenticity token from the configuration" do
247
+ PagSeguro.stub!(:config).and_return("authenticity_token" => "ABCDEF")
248
+
249
+ post = mock("post").as_null_object
250
+ post.should_receive(:set_form_data).with({:Comando => "validar", :Token => "ABCDEF"})
251
+
252
+ Net::HTTP.should_receive(:new).and_return(mock("http").as_null_object)
253
+ Net::HTTP::Post.should_receive(:new).and_return(post)
254
+
255
+ @notification.valid?
256
+ end
257
+
258
+ it "should propagate params" do
259
+ param!("VendedorEmail", "john@doe.com")
260
+ param!("NumItens", "14")
261
+ PagSeguro.stub!(:config).and_return("authenticity_token" => "ABCDEF")
262
+
263
+ post = mock("post").as_null_object
264
+ post.should_receive(:set_form_data).with({
265
+ :Comando => "validar",
266
+ :Token => "ABCDEF",
267
+ "VendedorEmail" => "john@doe.com",
268
+ "NumItens" => "14"
269
+ })
270
+
271
+ Net::HTTP.should_receive(:new).and_return(mock("http").as_null_object)
272
+ Net::HTTP::Post.should_receive(:new).and_return(post)
273
+
274
+ @notification.valid?
275
+ end
276
+
277
+ it "should propagate params in ISO-8859-1" do
278
+ param!("CliNome", "João Doão")
279
+ PagSeguro.stub!(:config).and_return("authenticity_token" => "ABCDEF")
280
+
281
+ post = mock("post").as_null_object
282
+ post.should_receive(:set_form_data).with({
283
+ :Comando => "validar",
284
+ :Token => "ABCDEF",
285
+ "CliNome" => to_iso("João Doão")
286
+ })
287
+
288
+ Net::HTTP.should_receive(:new).and_return(mock("http").as_null_object)
289
+ Net::HTTP::Post.should_receive(:new).and_return(post)
290
+
291
+ @notification.valid?
292
+ end
293
+ end
294
+
295
+ private
296
+ def set_status!(value)
297
+ param!("StatusTransacao", value)
298
+ end
299
+
300
+ def set_payment!(value)
301
+ param!("TipoPagamento", value)
302
+ end
303
+
304
+ def param!(name, value)
305
+ @notification.params.merge!(name => value)
306
+ end
307
+
308
+ def to_iso(str)
309
+ str.unpack('U*').pack('C*')
310
+ end
311
+
312
+ def set_product!(options={})
313
+ @__products ||= []
314
+
315
+ i = @__products.size + 1
316
+
317
+ options = {
318
+ :quantity => 1,
319
+ :fees => "0,00",
320
+ :shipping => "0,00"
321
+ }.merge(options)
322
+
323
+ @__products << {
324
+ "ProdID_#{i}" => options[:id].to_s,
325
+ "ProdDescricao_#{i}" => options[:description].to_s,
326
+ "ProdValor_#{i}" => options[:price].to_s,
327
+ "ProdFrete_#{i}" => options[:shipping].to_s,
328
+ "ProdExtras_#{i}" => options[:fees].to_s,
329
+ "ProdQuantidade_#{i}" => options[:quantity].to_s
330
+ }
331
+
332
+ @notification.params.merge!(@__products.last)
333
+ @notification.params.merge!("NumItens" => i)
334
+ @__products.last
335
+ end
336
+ end