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
data/.rspec ADDED
@@ -0,0 +1 @@
1
+ --color --format documentation
data/Gemfile ADDED
@@ -0,0 +1,8 @@
1
+ source :rubygems
2
+
3
+ gem "rails", "3.0.0"
4
+ gem "fakeweb"
5
+ gem "rspec-rails", "2.0.0.beta.20"
6
+ gem "faker"
7
+ gem "ruby-debug19", :require => false
8
+ gem "nokogiri"
data/Gemfile.lock ADDED
@@ -0,0 +1,104 @@
1
+ GEM
2
+ remote: http://rubygems.org/
3
+ specs:
4
+ abstract (1.0.0)
5
+ actionmailer (3.0.0)
6
+ actionpack (= 3.0.0)
7
+ mail (~> 2.2.5)
8
+ actionpack (3.0.0)
9
+ activemodel (= 3.0.0)
10
+ activesupport (= 3.0.0)
11
+ builder (~> 2.1.2)
12
+ erubis (~> 2.6.6)
13
+ i18n (~> 0.4.1)
14
+ rack (~> 1.2.1)
15
+ rack-mount (~> 0.6.12)
16
+ rack-test (~> 0.5.4)
17
+ tzinfo (~> 0.3.23)
18
+ activemodel (3.0.0)
19
+ activesupport (= 3.0.0)
20
+ builder (~> 2.1.2)
21
+ i18n (~> 0.4.1)
22
+ activerecord (3.0.0)
23
+ activemodel (= 3.0.0)
24
+ activesupport (= 3.0.0)
25
+ arel (~> 1.0.0)
26
+ tzinfo (~> 0.3.23)
27
+ activeresource (3.0.0)
28
+ activemodel (= 3.0.0)
29
+ activesupport (= 3.0.0)
30
+ activesupport (3.0.0)
31
+ archive-tar-minitar (0.5.2)
32
+ arel (1.0.1)
33
+ activesupport (~> 3.0.0)
34
+ builder (2.1.2)
35
+ columnize (0.3.1)
36
+ diff-lcs (1.1.2)
37
+ erubis (2.6.6)
38
+ abstract (>= 1.0.0)
39
+ faker (0.3.1)
40
+ fakeweb (1.3.0)
41
+ i18n (0.4.1)
42
+ linecache19 (0.5.11)
43
+ ruby_core_source (>= 0.1.4)
44
+ mail (2.2.5)
45
+ activesupport (>= 2.3.6)
46
+ mime-types
47
+ treetop (>= 1.4.5)
48
+ mime-types (1.16)
49
+ nokogiri (1.4.3.1)
50
+ polyglot (0.3.1)
51
+ rack (1.2.1)
52
+ rack-mount (0.6.13)
53
+ rack (>= 1.0.0)
54
+ rack-test (0.5.4)
55
+ rack (>= 1.0)
56
+ rails (3.0.0)
57
+ actionmailer (= 3.0.0)
58
+ actionpack (= 3.0.0)
59
+ activerecord (= 3.0.0)
60
+ activeresource (= 3.0.0)
61
+ activesupport (= 3.0.0)
62
+ bundler (~> 1.0.0)
63
+ railties (= 3.0.0)
64
+ railties (3.0.0)
65
+ actionpack (= 3.0.0)
66
+ activesupport (= 3.0.0)
67
+ rake (>= 0.8.4)
68
+ thor (~> 0.14.0)
69
+ rake (0.8.7)
70
+ rspec (2.0.0.beta.20)
71
+ rspec-core (= 2.0.0.beta.20)
72
+ rspec-expectations (= 2.0.0.beta.20)
73
+ rspec-mocks (= 2.0.0.beta.20)
74
+ rspec-core (2.0.0.beta.20)
75
+ rspec-expectations (2.0.0.beta.20)
76
+ diff-lcs (>= 1.1.2)
77
+ rspec-mocks (2.0.0.beta.20)
78
+ rspec-rails (2.0.0.beta.20)
79
+ rspec (= 2.0.0.beta.20)
80
+ ruby-debug-base19 (0.11.24)
81
+ columnize (>= 0.3.1)
82
+ linecache19 (>= 0.5.11)
83
+ ruby_core_source (>= 0.1.4)
84
+ ruby-debug19 (0.11.6)
85
+ columnize (>= 0.3.1)
86
+ linecache19 (>= 0.5.11)
87
+ ruby-debug-base19 (>= 0.11.19)
88
+ ruby_core_source (0.1.4)
89
+ archive-tar-minitar (>= 0.5.2)
90
+ thor (0.14.0)
91
+ treetop (1.4.8)
92
+ polyglot (>= 0.3.1)
93
+ tzinfo (0.3.23)
94
+
95
+ PLATFORMS
96
+ ruby
97
+
98
+ DEPENDENCIES
99
+ faker
100
+ fakeweb
101
+ nokogiri
102
+ rails (= 3.0.0)
103
+ rspec-rails (= 2.0.0.beta.20)
104
+ ruby-debug19
data/README.markdown ADDED
@@ -0,0 +1,212 @@
1
+ PAGSEGURO
2
+ =========
3
+
4
+ Este é um plugin do Ruby on Rails que permite utilizar o [PagSeguro](https://pagseguro.uol.com.br/?ind=689659), gateway de pagamentos do [UOL](http://uol.com.br).
5
+
6
+ SOBRE O PAGSEGURO
7
+ -----------------
8
+
9
+ ### Carrinho Próprio
10
+
11
+ Trabalhando com carrinho próprio, sua loja mantém os dados do carrinho. O processo de inclusão de produtos no carrinho de compras acontece no próprio site da loja. Quando o comprador quiser finalizar sua compra, ele é enviado ao PagSeguro uma única vez com todos os dados de seu pedido. Aqui também, você tem duas opções. Pode enviar os dados do pedido e deixar o PagSeguro solicitar os dados do comprador, ou pode solicitar todos os dados necessários para a compra em sua loja e enviá-los ao PagSeguro.
12
+
13
+ ### Retorno Automático
14
+
15
+ Após o processo de compra e pagamento, o usuário é enviado de volta a seu site. Para isso, você deve configurar uma [URL de retorno](https://pagseguro.uol.com.br/Security/ConfiguracoesWeb/RetornoAutomatico.aspx).
16
+
17
+ Antes de enviar o usuário para essa URL, o robô do PagSeguro faz um POST para ela, em segundo plano, com os dados e status da transação. Lendo esse POST, você pode obter o status do pedido. Se o pagamento entrou em análise, ou se o usuário pagou usando boleto bancário, o status será "Aguardando Pagamento" ou "Em Análise". Nesses casos, quando a transação for confirmada (o que pode acontecer alguns dias depois) a loja receberá outro POST, informando o novo status. **Cada vez que a transação muda de status, um POST é enviado.**
18
+
19
+ REQUISITOS
20
+ ----------
21
+
22
+ A versão atual que está sendo mantida suporta Rails 3.0.0 ou superior.
23
+
24
+ Se você quiser esta biblioteca em versão mais antigas do Rails (2.3, por exemplo) deverá usar o [branch legacy](http://github.com/fnando/pagseguro/tree/legacy). Note que esta versão não será mais atualizada com novas funcionalidades; apenas correções de bugs serão aplicadas.
25
+
26
+ COMO USAR
27
+ ---------
28
+
29
+ ### Configuração
30
+
31
+ O primeiro passo é instalar a biblioteca. Para isso, basta executar o comando
32
+
33
+ gem install pagseguro
34
+
35
+ Se for utilizar o modo de desenvolvimento também precisará da gem Faker:
36
+
37
+ gem install faker
38
+
39
+ Depois de instalar a biblioteca, você precisará executar gerar o arquivo de configuração, que deve residir em `config/pagseguro.yml`. Para gerar um arquivo de modelo execute
40
+
41
+ rails generate pagseguro:install
42
+
43
+ O arquivo de configuração gerado será parecido com isto:
44
+
45
+ development: &development
46
+ developer: true
47
+ base: "http://localhost:3000"
48
+ return_to: "/pedido/efetuado"
49
+ email: user@example.com
50
+
51
+ test:
52
+ <<: *development
53
+
54
+ production:
55
+ authenticity_token: 9CA8D46AF0C6177CB4C23D76CAF5E4B0
56
+ email: user@example.com
57
+ return_to: "/pedido/efetuado"
58
+
59
+ Este plugin possui um modo de desenvolvimento que permite simular a realização de pedidos e envio de notificações; basta utilizar a opção `developer`. Ela é ativada por padrão nos ambientes de desenvolvimento e teste. Você deve configurar as opções `base`, que deverá apontar para o seu servidor e a URL de retorno, que deverá ser configurada no próprio [PagSeguro](https://pagseguro.uol.com.br/?ind=689659), na página <https://pagseguro.uol.com.br/Security/ConfiguracoesWeb/RetornoAutomatico.aspx>.
60
+
61
+ Para o ambiente de produção, que irá efetivamente enviar os dados para o [PagSeguro](https://pagseguro.uol.com.br/?ind=689659), você precisará adicionar o e-mail cadastrado como vendedor e o `authenticity_token`, que é o Token para Conferência de Segurança, que pode ser conseguido na página <https://pagseguro.uol.com.br/Security/ConfiguracoesWeb/RetornoAutomatico.aspx>.
62
+
63
+ ### Montando o formulário
64
+
65
+ Para montar o seu formulário, você deverá utilizar a classe `PagSeguro::Order`. Esta classe deverá ser instanciada recebendo um identificador único do pedido. Este identificador permitirá identificar o pedido quando o [PagSeguro](https://pagseguro.uol.com.br/?ind=689659) notificar seu site sobre uma alteração no status do pedido.
66
+
67
+ class CartController < ApplicationController
68
+ def checkout
69
+ # Busca o pedido associado ao usuário; esta lógica deve
70
+ # ser implementada por você, da maneira que achar melhor
71
+ @invoice = current_user.invoices.last
72
+
73
+ # Instanciando o objeto para geração do formulário
74
+ @order = PagSeguro::Order.new(@invoice.id)
75
+
76
+ # adicionando os produtos do pedido ao objeto do formulário
77
+ @invoice.products.each do |product|
78
+ # Estes são os atributos necessários. Por padrão, peso (:weight) é definido para 0,
79
+ # quantidade é definido como 1 e frete (:shipping) é definido como 0.
80
+ @order.add :id => product.id, :price => product.price, :description => product.title
81
+ end
82
+ end
83
+ end
84
+
85
+ Se você precisar, pode definir o tipo de frete com o método `shipping_type`.
86
+
87
+ @order.shipping_type = "SD" # Sedex
88
+ @order.shipping_type = "EN" # PAC
89
+ @order.shipping_type = "FR" # Frete Próprio
90
+
91
+ Depois que você definiu os produtos do pedido, você pode exibir o formulário.
92
+
93
+ <!-- app/views/cart/checkout.html.erb -->
94
+ <%= pagseguro_form @order, :submit => "Efetuar pagamento!" %>
95
+
96
+ Por padrão, o formulário é enviado para o email no arquivo de configuração. Você pode mudar o email com a opção `:email`.
97
+
98
+ <%= pagseguro_form @order, :submit => "Efetuar pagamento!", :email => @account.email %>
99
+
100
+ ### Recebendo notificações
101
+
102
+ Toda vez que o status de pagamento for alterado, o [PagSeguro](https://pagseguro.uol.com.br/?ind=689659) irá notificar sua URL de retorno com diversos dados. Você pode interceptar estas notificações com o método `pagseguro_notification`. O bloco receberá um objeto da classe `PagSeguro::Notification` e só será executado se for uma notificação verificada junto ao [PagSeguro](https://pagseguro.uol.com.br/?ind=689659).
103
+
104
+ class CartController < ApplicationController
105
+ skip_before_filter :verify_authenticity_token
106
+
107
+ def confirm
108
+ return unless request.post?
109
+
110
+ pagseguro_notification do |notification|
111
+ # Aqui você deve verificar se o pedido possui os mesmos produtos
112
+ # que você cadastrou. O produto só deve ser liberado caso o status
113
+ # do pedido seja "completed" ou "approved"
114
+ end
115
+
116
+ render :nothing => true
117
+ end
118
+ end
119
+
120
+ O método `pagseguro_notification` também pode receber como parâmetro o `authenticity_token` que será usado pra verificar a autenticação.
121
+
122
+ class CartController < ApplicationController
123
+ skip_before_filter :verify_authenticity_token
124
+
125
+ def confirm
126
+ return unless request.post?
127
+ # Se você receber pagamentos de contas diferentes, pode passar o
128
+ # authenticity_token adequado como parâmetro para pagseguro_notification
129
+ account = Account.find(params[:seller_id])
130
+ pagseguro_notification(account.authenticity_token) do |notification|
131
+ end
132
+
133
+ render :nothing => true
134
+ end
135
+ end
136
+
137
+ O objeto `notification` possui os seguintes métodos:
138
+
139
+ * `PagSeguro::Notification#products`: Lista de produtos enviados na notificação.
140
+ * `PagSeguro::Notification#shipping`: Valor do frete
141
+ * `PagSeguro::Notification#status`: Status do pedido
142
+ * `PagSeguro::Notification#payment_method`: Tipo de pagamento
143
+ * `PagSeguro::Notification#processed_at`: Data e hora da transação
144
+ * `PagSeguro::Notification#buyer`: Dados do comprador
145
+ * `PagSeguro::Notification#valid?(force=false)`: Verifica se a notificação é válido, confirmando-a junto ao PagSeguro. A resposta é jogada em cache e pode ser forçada com `PagSeguro::Notification#valid?(:force)`
146
+
147
+ **ATENÇÃO:** Não se esqueça de adicionar `skip_before_filter :verify_authenticity_token` ao controller que receberá a notificação; caso contrário, uma exceção será lançada.
148
+
149
+ ### Utilizando modo de desenvolvimento
150
+
151
+ Toda vez que você enviar o formulário no modo de desenvolvimento, um arquivo YAML será criado em `tmp/pagseguro-#{Rails.env}.yml`. Esse arquivo conterá todos os pedidos enviados.
152
+
153
+ Depois, você será redirecionado para a URL de retorno que você configurou no arquivo `config/pagseguro.yml`. Para simular o envio de notificações, você deve utilizar a rake `pagseguro:notify`.
154
+
155
+ $ rake pagseguro:notify ID=<id do pedido>
156
+
157
+ O ID do pedido deve ser o mesmo que foi informado quando você instanciou a class `PagSeguro::Order`. Por padrão, o status do pedido será `completed` e o tipo de pagamento `credit_card`. Você pode especificar esses parâmetros como o exemplo abaixo.
158
+
159
+ $ rake pagamento:notify ID=1 PAYMENT_METHOD=invoice STATUS=canceled NOTE="Enviar por motoboy" NAME="José da Silva" EMAIL="jose@dasilva.com"
160
+
161
+ #### PAYMENT_METHOD
162
+
163
+ * `credit_card`: Cartão de crédito
164
+ * `invoice`: Boleto
165
+ * `online_transfer`: Pagamento online
166
+ * `pagseguro`: Transferência entre contas do PagSeguro
167
+
168
+ #### STATUS
169
+
170
+ * `completed`: Completo
171
+ * `pending`: Aguardando pagamento
172
+ * `approved`: Aprovado
173
+ * `verifying`: Em análise
174
+ * `canceled`: Cancelado
175
+ * `refunded`: Devolvido
176
+
177
+ AUTOR:
178
+ ------
179
+
180
+ Nando Vieira (<http://simplesideias.com.br>)
181
+
182
+ Recomendar no [Working With Rails](http://www.workingwithrails.com/person/7846-nando-vieira)
183
+
184
+ COLABORADORES:
185
+ --------------
186
+
187
+ * Elomar (<http://github.com/elomar>)
188
+ * Rafael (<http://github.com/rafaels>)
189
+
190
+ LICENÇA:
191
+ --------
192
+
193
+ (The MIT License)
194
+
195
+ Permission is hereby granted, free of charge, to any person obtaining
196
+ a copy of this software and associated documentation files (the
197
+ 'Software'), to deal in the Software without restriction, including
198
+ without limitation the rights to use, copy, modify, merge, publish,
199
+ distribute, sublicense, and/or sell copies of the Software, and to
200
+ permit persons to whom the Software is furnished to do so, subject to
201
+ the following conditions:
202
+
203
+ The above copyright notice and this permission notice shall be
204
+ included in all copies or substantial portions of the Software.
205
+
206
+ THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,
207
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
208
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
209
+ IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
210
+ CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
211
+ TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
212
+ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/Rakefile ADDED
@@ -0,0 +1,25 @@
1
+ require "rspec/core/rake_task"
2
+ require File.dirname(__FILE__) + "/lib/pagseguro/version"
3
+
4
+ RSpec::Core::RakeTask.new
5
+
6
+ begin
7
+ require "jeweler"
8
+
9
+ JEWEL = Jeweler::Tasks.new do |gem|
10
+ gem.name = "pagseguro"
11
+ gem.version = PagSeguro::Version::STRING
12
+ gem.summary = "A wrapper for the PagSeguro payment gateway."
13
+ gem.description = ""
14
+ gem.authors = ["Nando Vieira"]
15
+ gem.email = "fnando.vieira@gmail.com"
16
+ gem.homepage = "http://github.com/fnando/pagseguro"
17
+ gem.has_rdoc = false
18
+ gem.files = FileList["{.rspec,Gemfile,Gemfile.lock,Rakefile,README.markdown,pagseguro.gemspec}", "{lib,spec,templates,test}/**/*"]
19
+ gem.add_development_dependency "rspec", ">= 2.0.0"
20
+ end
21
+
22
+ Jeweler::GemcutterTasks.new
23
+ rescue LoadError => e
24
+ puts "You don't have Jeweler installed, so you won't be able to build gems."
25
+ end
data/lib/pagseguro.rb ADDED
@@ -0,0 +1,66 @@
1
+ require "net/https"
2
+ require "uri"
3
+ require "time"
4
+
5
+ require "pagseguro/rake"
6
+ require "pagseguro/railtie"
7
+ require "pagseguro/notification"
8
+ require "pagseguro/order"
9
+ require "pagseguro/action_controller"
10
+ require "pagseguro/helper"
11
+
12
+ module PagSeguro
13
+ extend self
14
+
15
+ # PagSeguro receives all invoices in this URL. If developer mode is enabled,
16
+ # then the URL will be /pagseguro_developer/invoice
17
+ GATEWAY_URL = "https://pagseguro.uol.com.br/security/webpagamentos/webpagto.aspx"
18
+
19
+ # Hold the config/pagseguro.yml contents
20
+ @@config = nil
21
+
22
+ # The path to the configuration file
23
+ def config_file
24
+ Rails.root.join("config/pagseguro.yml")
25
+ end
26
+
27
+ # Check if configuration file exists.
28
+ def config?
29
+ File.exist?(config_file)
30
+ end
31
+
32
+ # Load configuration file.
33
+ def config
34
+ raise MissingConfigurationException, "file not found on #{config_file.inspect}" unless config?
35
+
36
+ # load file if is not loaded yet
37
+ @@config ||= YAML.load_file(config_file)
38
+
39
+ # raise an exception if the environment hasn't been set
40
+ # or if file is empty
41
+ if @@config == false || !@@config[Rails.env]
42
+ raise MissingEnvironmentException, ":#{Rails.env} environment not set on #{config_file.inspect}"
43
+ end
44
+
45
+ # retrieve the environment settings
46
+ @@config[Rails.env]
47
+ end
48
+
49
+ # The gateway URL will point to a local URL is
50
+ # app is running in developer mode
51
+ def gateway_url
52
+ if developer?
53
+ "/pagseguro_developer"
54
+ else
55
+ GATEWAY_URL
56
+ end
57
+ end
58
+
59
+ # Reader for the `developer` configuration
60
+ def developer?
61
+ config? && config["developer"] == true
62
+ end
63
+
64
+ class MissingEnvironmentException < StandardError; end
65
+ class MissingConfigurationException < StandardError; end
66
+ end
@@ -0,0 +1,11 @@
1
+ module PagSeguro
2
+ module ActionController
3
+ private
4
+ def pagseguro_notification(token = nil, &block)
5
+ return unless request.post?
6
+
7
+ notification = PagSeguro::Notification.new(params, token)
8
+ yield notification if notification.valid?
9
+ end
10
+ end
11
+ end
@@ -0,0 +1,26 @@
1
+ module PagSeguro
2
+ class DeveloperController < ApplicationController
3
+ skip_before_filter :verify_authenticity_token
4
+ PAGSEGURO_ORDERS_FILE = File.join(Rails.root, "tmp", "pagseguro-#{Rails.env}.yml")
5
+
6
+ def create
7
+ # create the orders file if doesn't exist
8
+ FileUtils.touch(PAGSEGURO_ORDERS_FILE) unless File.exist?(PAGSEGURO_ORDERS_FILE)
9
+
10
+ # YAML caveat: if file is empty false is returned;
11
+ # we need to set default to an empty hash in this case
12
+ orders = YAML.load_file(PAGSEGURO_ORDERS_FILE) || {}
13
+
14
+ # add a new order, associating it with the order id
15
+ orders[params[:ref_transacao]] = params.except(:controller, :action, :only_path, :authenticity_token)
16
+
17
+ # save the file
18
+ File.open(PAGSEGURO_ORDERS_FILE, "w+") do |file|
19
+ file << orders.to_yaml
20
+ end
21
+
22
+ # redirect to the configuration url
23
+ redirect_to PagSeguro.config["return_to"]
24
+ end
25
+ end
26
+ end