pagseguro 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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