solidus_pagseguro_oficial 1.1.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (41) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +14 -0
  3. data/.rspec +1 -0
  4. data/.ruby-gemset +1 -0
  5. data/.ruby-version +1 -0
  6. data/.travis.yml +15 -0
  7. data/Gemfile +9 -0
  8. data/LICENSE +26 -0
  9. data/README.md +50 -0
  10. data/Rakefile +21 -0
  11. data/app/assets/javascripts/spree/backend/solidus_pagseguro_oficial.js +2 -0
  12. data/app/assets/javascripts/spree/frontend/solidus_pagseguro_oficial.js +18 -0
  13. data/app/assets/stylesheets/spree/backend/solidus_pagseguro_oficial.css +4 -0
  14. data/app/assets/stylesheets/spree/frontend/solidus_pagseguro_oficial.css +4 -0
  15. data/app/controllers/spree/pagseguro_controller.rb +84 -0
  16. data/app/models/spree/gateway/pagseguro.rb +29 -0
  17. data/app/models/spree/pagseguro_checkout.rb +37 -0
  18. data/app/models/spree/pagseguro_provider.rb +61 -0
  19. data/app/overrides/spree/admin/general_settings/edit/add_env_vars_of_pagseguro_account.html.erb.deface +12 -0
  20. data/app/views/spree/checkout/payment/_pagseguro.html.erb +11 -0
  21. data/app/workers/spree/pagseguro_checkout_worker.rb +14 -0
  22. data/bin/rails +7 -0
  23. data/config/initializers/pagseguro.rb +8 -0
  24. data/config/locales/en.yml +5 -0
  25. data/config/locales/pt-BR.yml +8 -0
  26. data/config/routes.rb +5 -0
  27. data/db/default/payment_methods.rb +10 -0
  28. data/db/migrate/20140611173248_create_spree_pagseguro_checkouts.rb +9 -0
  29. data/db/seeds.rb +5 -0
  30. data/lib/generators/solidus_pagseguro_oficial/install/install_generator.rb +31 -0
  31. data/lib/solidus_pagseguro_oficial.rb +3 -0
  32. data/lib/solidus_pagseguro_oficial/engine.rb +24 -0
  33. data/lib/solidus_pagseguro_oficial/factories.rb +47 -0
  34. data/solidus_pagseguro_oficial.gemspec +33 -0
  35. data/spec/controllers/pagseguro_controller_spec.rb +51 -0
  36. data/spec/models/spree/pagseguro_checkout_spec.rb +60 -0
  37. data/spec/models/spree/pagseguro_provider_spec.rb +22 -0
  38. data/spec/spec_helper.rb +40 -0
  39. data/spec/support/database_cleaner.rb +24 -0
  40. data/spec/workers/spree/pagseguro_checkout_worker_spec.rb +47 -0
  41. metadata +282 -0
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: d1b9039e2a38286420e9e81621c99d816fd23575
4
+ data.tar.gz: 48494baa1f4f61743d5cc2e614f40217e00c336d
5
+ SHA512:
6
+ metadata.gz: 92d2db2dd682bdadf039980c0a5ce0856c00d394e3b7337e6dd1411a3bd17911d5c3f3c00cbe9874e1be54b4466bc837a3ff0f7b1674d8e65d05de37d223feda
7
+ data.tar.gz: 150d37dca7b03fb3cec2f879be2cc943231b2d1b6cbcab3746ae4dbde9857e954ce63c572500187b8a91892d83ea9d1fd2e7d9b3ac4e5760f7f1fcaf407688ef
@@ -0,0 +1,14 @@
1
+ \#*
2
+ *~
3
+ .#*
4
+ .DS_Store
5
+ .idea
6
+ .project
7
+ .sass-cache
8
+ coverage
9
+ Gemfile.lock
10
+ tmp
11
+ nbproject
12
+ pkg
13
+ *.swp
14
+ spec/dummy
data/.rspec ADDED
@@ -0,0 +1 @@
1
+ --color
@@ -0,0 +1 @@
1
+ solidus_pagseguro_oficial
@@ -0,0 +1 @@
1
+ ruby-2.2.2
@@ -0,0 +1,15 @@
1
+ language: ruby
2
+ cache: bundler
3
+ before_script:
4
+ - sh -e /etc/init.d/xvfb start
5
+ - export DISPLAY=:99.0
6
+ script:
7
+ - bundle exec rake
8
+ notifications:
9
+ email:
10
+ - diego.domingues16@gmail.com
11
+ rvm:
12
+ - 2.2.2
13
+ addons:
14
+ code_climate:
15
+ repo_token: 8c6bdfbec7879434fc4104044e2f9dfb0c7ffeb4b04d99f21256cf4e432a7617
data/Gemfile ADDED
@@ -0,0 +1,9 @@
1
+ source 'https://rubygems.org'
2
+
3
+ gem 'solidus', '~> 1.1'
4
+ gem 'solidus_auth_devise', '~> 1.2', '>= 1.2.3'
5
+ gem 'solidus_br_common', '~> 1.1'
6
+
7
+ gem 'codeclimate-test-reporter', group: :test, require: nil
8
+
9
+ gemspec
data/LICENSE ADDED
@@ -0,0 +1,26 @@
1
+ Copyright (c) 2014 [name of plugin creator]
2
+ All rights reserved.
3
+
4
+ Redistribution and use in source and binary forms, with or without modification,
5
+ are permitted provided that the following conditions are met:
6
+
7
+ * Redistributions of source code must retain the above copyright notice,
8
+ this list of conditions and the following disclaimer.
9
+ * Redistributions in binary form must reproduce the above copyright notice,
10
+ this list of conditions and the following disclaimer in the documentation
11
+ and/or other materials provided with the distribution.
12
+ * Neither the name Spree nor the names of its contributors may be used to
13
+ endorse or promote products derived from this software without specific
14
+ prior written permission.
15
+
16
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
17
+ "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
18
+ LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
19
+ A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
20
+ CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
21
+ EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
22
+ PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
23
+ PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
24
+ LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
25
+ NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
26
+ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
@@ -0,0 +1,50 @@
1
+ SolidusPagseguroOficial
2
+ =====================
3
+
4
+ Extension that integrates with the pagseguro
5
+
6
+ [![Build Status](https://travis-ci.org/ddomingues/solidus_pagseguro_oficial.svg?branch=master)](https://travis-ci.org/ddomingues/solidus_pagseguro_oficial)
7
+ [![Code Climate](https://codeclimate.com/github/ddomingues/solidus_pagseguro_oficial/badges/gpa.svg)](https://codeclimate.com/github/ddomingues/solidus_pagseguro_oficial)
8
+ [![Test Coverage](https://codeclimate.com/github/ddomingues/solidus_pagseguro_oficial/badges/coverage.svg)](https://codeclimate.com/github/ddomingues/solidus_pagseguro_oficial/coverage)
9
+
10
+ Installation
11
+ ------------
12
+
13
+ Add solidus_pagseguro_oficial to your Gemfile:
14
+
15
+ ```ruby
16
+ gem 'solidus_pagseguro_oficial'
17
+ ```
18
+
19
+ Bundle your dependencies and run the installation generator:
20
+
21
+ ```shell
22
+ bundle
23
+ bundle exec rails g solidus_pagseguro_oficial:install
24
+ ```
25
+
26
+ You must set 2 environment variables using your PagSeguro account as the following example:
27
+
28
+ ```shell
29
+ export PAGSEGURO_EMAIL=xxx@xxx.com
30
+ export PAGSEGURO_TOKEN=1232328947843794
31
+ ```
32
+
33
+ Testing
34
+ -------
35
+
36
+ First bundle your dependencies, then run `rake`. `rake` will default to building the dummy app if it does not exist, then it will run specs. The dummy app can be regenerated by using `rake test_app`.
37
+
38
+ ```shell
39
+ bundle
40
+ bundle exec rake
41
+ ```
42
+
43
+ When testing your applications integration with this extension you may use it's factories.
44
+ Simply add this require statement to your spec_helper:
45
+
46
+ ```ruby
47
+ require 'solidus_pagseguro_oficial/factories'
48
+ ```
49
+
50
+ Copyright (c) 2016 Diego Domingues, released under the New BSD License
@@ -0,0 +1,21 @@
1
+ require 'bundler'
2
+ Bundler::GemHelper.install_tasks
3
+
4
+ require 'rspec/core/rake_task'
5
+ require 'spree/testing_support/extension_rake'
6
+
7
+ RSpec::Core::RakeTask.new
8
+
9
+ task :default do
10
+ if Dir['spec/dummy'].empty?
11
+ Rake::Task[:test_app].invoke
12
+ Dir.chdir('../../')
13
+ end
14
+ Rake::Task[:spec].invoke
15
+ end
16
+
17
+ desc 'Generates a dummy app for testing'
18
+ task :test_app do
19
+ ENV['LIB_NAME'] = 'solidus_pagseguro_oficial'
20
+ Rake::Task['extension:test_app'].invoke
21
+ end
@@ -0,0 +1,2 @@
1
+ // Placeholder manifest file.
2
+ // the installer will append this file to the app vendored assets here: vendor/assets/javascripts/spree/backend/all.js'
@@ -0,0 +1,18 @@
1
+ SpreePagSeguro = function(paymentMethodID) {
2
+
3
+ function isSelected(paymentMethod) {
4
+ return paymentMethodID && paymentMethod == paymentMethodID
5
+ }
6
+
7
+ function showOrHide(selector) {
8
+ return function() {
9
+ var paymentMethod = $(this).val();
10
+ $(selector)[ isSelected(paymentMethod) ? 'hide' : 'show' ]();
11
+ }
12
+ }
13
+
14
+ return {
15
+ showOrHide: showOrHide
16
+ }
17
+
18
+ }
@@ -0,0 +1,4 @@
1
+ /*
2
+ Placeholder manifest file.
3
+ the installer will append this file to the app vendored assets here: 'vendor/assets/stylesheets/spree/backend/all.css'
4
+ */
@@ -0,0 +1,4 @@
1
+ /*
2
+ Placeholder manifest file.
3
+ the installer will append this file to the app vendored assets here: 'vendor/assets/stylesheets/spree/frontend/all.css'
4
+ */
@@ -0,0 +1,84 @@
1
+ module Spree
2
+ class PagseguroController < StoreController
3
+ skip_before_action :verify_authenticity_token, only: :notify
4
+ before_action :load_order, only: [:init_transaction, :confirm]
5
+ around_action :lock_order, only: [:init_transaction, :confirm]
6
+
7
+ def init_transaction
8
+ begin
9
+ response = provider.init_transaction!
10
+
11
+ if response.errors.any?
12
+ flash[:error] = Spree.t('flash.payment_with_pagseguro', reasons: response.errors.join("\n"))
13
+ redirect_to checkout_state_path(@order.state)
14
+ else
15
+ redirect_to response.url
16
+ end
17
+
18
+ rescue SocketError
19
+ flash[:error] = Spree.t('flash.connection_failed')
20
+ redirect_to checkout_state_path(@order.state)
21
+ end
22
+ end
23
+
24
+ def confirm
25
+ pagseguro_checkout = Spree::PagseguroCheckout.create! transaction_id: transaction_id
26
+
27
+ @order.payments.create!(
28
+ {
29
+ :source => pagseguro_checkout,
30
+ :amount => @order.total,
31
+ :payment_method => payment_method
32
+ }
33
+ )
34
+
35
+ unless @order.next
36
+ flash[:error] = @order.errors.full_messages.join("\n")
37
+ redirect_to checkout_state_path(@order.state) and return
38
+ end
39
+
40
+ pagseguro_checkout.process!
41
+
42
+ if @order.completed?
43
+ session[:order_id] = nil
44
+ flash.notice = Spree.t(:order_processed_successfully).html_safe
45
+ redirect_to spree.order_path(@order)
46
+ else
47
+ redirect_to checkout_state_path(@order.state)
48
+ end
49
+ end
50
+
51
+ def notify
52
+ checkout_worker.perform notification_code
53
+
54
+ render nothing: true, status: 200
55
+ end
56
+
57
+ private
58
+ def notification_code
59
+ params.require(:notificationCode)
60
+ end
61
+
62
+ def transaction_id
63
+ params.require(:transaction_id)
64
+ end
65
+
66
+ def load_order
67
+ @order = current_order
68
+ redirect_to spree.cart_path and return unless @order
69
+ end
70
+
71
+ def payment_method
72
+ Spree::PaymentMethod.find( params.require(:payment_method_id) )
73
+ end
74
+
75
+ def provider
76
+ redirect_url = pagseguro_confirm_url(payment_method_id: params.require(:payment_method_id))
77
+ payment_method.provider_class.new @order, spree_current_user, pagseguro_notify_url, redirect_url
78
+ end
79
+
80
+ def checkout_worker
81
+ Spree::PagseguroCheckoutWorker.new
82
+ end
83
+ end
84
+ end
@@ -0,0 +1,29 @@
1
+ module Spree
2
+ class Gateway::Pagseguro < Gateway
3
+ def provider_class
4
+ Spree::PagseguroProvider
5
+ end
6
+
7
+ def method_type
8
+ 'pagseguro'
9
+ end
10
+
11
+ def supports?(source)
12
+ true
13
+ end
14
+
15
+ def auto_capture?
16
+ false
17
+ end
18
+
19
+ def authorize(amount, source, gateway_options = {})
20
+ transaction = PagSeguro::Transaction.find_by_code(source.transaction_id)
21
+
22
+ if transaction
23
+ ActiveMerchant::Billing::Response.new(true, 'PagSeguro Gateway: Realizado com sucesso', {}, :authorization => source.transaction_id)
24
+ else
25
+ ActiveMerchant::Billing::Response.new(false, 'PagSeguro Gateway: Realizado com falha', { :message => 'Pagamento com PagSeguro inconsistente, por favor verificar!' })
26
+ end
27
+ end
28
+ end
29
+ end
@@ -0,0 +1,37 @@
1
+ module Spree
2
+ class PagseguroCheckout < ActiveRecord::Base
3
+ validates_presence_of :transaction_id
4
+
5
+ has_many :payments, as: :source
6
+
7
+ def process!
8
+ payments.pending.each do |payment|
9
+ raise RuntimeError.new('Payment and Order not belongs to same transaction') unless payment.order.id === transaction.reference.to_i
10
+
11
+ case
12
+ when status_paid? then payment.complete!
13
+ when status_cancelled?
14
+ payment.failure
15
+ payment.order.cancel!
16
+ end
17
+ end
18
+ end
19
+
20
+ private
21
+ def transaction
22
+ @transaction ||= PagSeguro::Transaction.find_by_code transaction_id
23
+ end
24
+
25
+ def status
26
+ transaction.status
27
+ end
28
+
29
+ def status_paid?
30
+ status.paid? || status.available?
31
+ end
32
+
33
+ def status_cancelled?
34
+ status.cancelled? || status.refunded?
35
+ end
36
+ end
37
+ end
@@ -0,0 +1,61 @@
1
+ class Spree::PagseguroProvider
2
+ def initialize(order, user, notification_url, redirect_url)
3
+ @order = order
4
+ @user = user
5
+ @notification_url = notification_url
6
+ @redirect_url = redirect_url
7
+ end
8
+
9
+ def init_transaction!
10
+ payment = PagSeguro::PaymentRequest.new
11
+ payment.reference = @order.id
12
+ payment.extra_amount = @order.adjustment_total
13
+ build_items_to payment
14
+ payment.shipping = PagSeguro::Shipping.new shipping_options
15
+ payment.sender = sender
16
+ payment.notification_url = @notification_url
17
+ payment.redirect_url = @redirect_url
18
+ payment.register
19
+ end
20
+
21
+ private
22
+ def build_items_to(payment)
23
+ @order.line_items.each do |item|
24
+ payment.items << {
25
+ id: item.product.id,
26
+ description: item.product.name,
27
+ amount: item.price,
28
+ quantity: item.quantity,
29
+ weight: item.product.weight.round
30
+ }
31
+ end
32
+ end
33
+
34
+ def sender
35
+ {
36
+ name: @user.bill_address.full_name,
37
+ email: @user.email,
38
+ cpf: @user.cpf,
39
+ phone: {
40
+ area_code: @user.phone_area_code,
41
+ number: @user.phone_number
42
+ }
43
+ }
44
+ end
45
+
46
+ def shipping_options
47
+ {
48
+ type_name: @order.shipments.first.selected_shipping_rate.shipping_method.name.downcase,
49
+ cost: @order.shipment_total,
50
+ address: {
51
+ street: @order.bill_address.address1,
52
+ number: @order.bill_address.number,
53
+ complement: @order.bill_address.address2,
54
+ district: @order.bill_address.district,
55
+ city: @order.bill_address.city.name,
56
+ state: @order.bill_address.state.abbr,
57
+ postal_code: @order.bill_address.zipcode
58
+ }
59
+ }
60
+ end
61
+ end
@@ -0,0 +1,12 @@
1
+ <!-- insert_after '[data-hook="admin_general_setting_mail_from_address"]' -->
2
+ <div class="field" data-hook="admin_general_setting_mail_from_address">
3
+ <label for="user_account"><%= Spree.t('pagseguro.user_account') %></label>
4
+ <br />
5
+ <input type="text" id="user_account" value="<%= ENV.fetch('PAGSEGURO_EMAIL') %>" readonly="readonly" class="fullwidth"/>
6
+ </div>
7
+
8
+ <div class="field" data-hook="admin_general_setting_mail_from_address">
9
+ <label for="user_account"><%= Spree.t('pagseguro.user_token') %></label>
10
+ <br />
11
+ <input type="text" id="user_account" value="<%= ENV.fetch('PAGSEGURO_TOKEN') %>" readonly="readonly" class="fullwidth"/>
12
+ </div>
@@ -0,0 +1,11 @@
1
+ <%= link_to pagseguro_init_transaction_url(:payment_method_id => payment_method.id), :method => :post, :id => "pagseguro_button", class: 'btn' do %>
2
+ <%= image_tag "https://p.simg.uol.com.br/out/pagseguro/i/botoes/pagamentos/209x48-pagar-roxo-assina.gif", alt: "Pague com PagSeguro - é rápido e seguro!" %>
3
+ <% end %>
4
+
5
+ <script>
6
+ (function(spreePagSeguro){
7
+ $('div[data-hook="checkout_payment_step"] input[type="radio"]')
8
+ .on('click', spreePagSeguro.showOrHide('.continue,[data-hook="coupon_code"]'))
9
+ .filter(':checked').trigger('click');
10
+ })(new SpreePagSeguro("<%= payment_method.id %>"));
11
+ </script>
@@ -0,0 +1,14 @@
1
+ module Spree
2
+ class PagseguroCheckoutWorker
3
+ def perform(notification_code)
4
+ transaction = PagSeguro::Transaction.find_by_notification_code( notification_code )
5
+
6
+ if transaction.errors.empty?
7
+ @pagseguroCheckout = Spree::PagseguroCheckout.find_by! transaction_id: transaction.code
8
+ @pagseguroCheckout.process!
9
+ else
10
+ # logger.error transaction.errors
11
+ end
12
+ end
13
+ end
14
+ end
@@ -0,0 +1,7 @@
1
+ # This command will automatically be run when you run "rails" with Rails 3 gems installed from the root of your application.
2
+
3
+ ENGINE_ROOT = File.expand_path('../..', __FILE__)
4
+ ENGINE_PATH = File.expand_path('../../lib/spree_pagseguro_oficial/engine', __FILE__)
5
+
6
+ require 'rails/all'
7
+ require 'rails/engine/commands'
@@ -0,0 +1,8 @@
1
+ I18n.locale = 'pt-BR'
2
+
3
+ PagSeguro.configure do |config|
4
+ config.email = ENV.fetch('PAGSEGURO_EMAIL')
5
+ config.token = ENV.fetch('PAGSEGURO_TOKEN')
6
+ config.environment = Rails.env.production? ? :production : :sandbox
7
+ end
8
+
@@ -0,0 +1,5 @@
1
+ en:
2
+ spree:
3
+ flash:
4
+ connection_failed: "Could not connect to PagSeguro."
5
+ generic_error: "PagSeguro failed. %{reasons}"
@@ -0,0 +1,8 @@
1
+ pt-BR:
2
+ spree:
3
+ flash:
4
+ connection_failed: "Nao foi possível conectar a PagSeguro"
5
+ payment_with_pagseguro: "Processo de Pagamento com a PagSeguro não pode ser iniciado. Razões: %{reasons}"
6
+ pagseguro:
7
+ user_account: Conta PagSeguro
8
+ user_token: Token PagSeguro
@@ -0,0 +1,5 @@
1
+ Spree::Core::Engine.routes.draw do
2
+ post '/pagseguro', to: 'pagseguro#init_transaction', as: :pagseguro_init_transaction
3
+ post '/pagseguro/notify', to: 'pagseguro#notify', as: :pagseguro_notify
4
+ get '/pagseguro/confirm', to: 'pagseguro#confirm', as: :pagseguro_confirm
5
+ end
@@ -0,0 +1,10 @@
1
+ %w(development production staging).each do |environment|
2
+ Spree::Gateway::Pagseguro.create!(
3
+ {
4
+ name: "PagSeguro - #{environment}",
5
+ description: "PagSeguro gateway para #{environment}.",
6
+ environment: environment,
7
+ active: true
8
+ }
9
+ )
10
+ end
@@ -0,0 +1,9 @@
1
+ class CreateSpreePagseguroCheckouts < ActiveRecord::Migration
2
+ def change
3
+ create_table :spree_pagseguro_checkouts do |t|
4
+ t.string :transaction_id
5
+
6
+ t.timestamps null: false
7
+ end
8
+ end
9
+ end
@@ -0,0 +1,5 @@
1
+ # Loads seed data out of default dir
2
+ default_path = File.join(File.dirname(__FILE__), 'default')
3
+
4
+ Rake::Task['db:load_dir'].reenable
5
+ Rake::Task['db:load_dir'].invoke(default_path)
@@ -0,0 +1,31 @@
1
+ module SolidusPagseguroOficial
2
+ module Generators
3
+ class InstallGenerator < Rails::Generators::Base
4
+
5
+ class_option :auto_run_migrations, type: :boolean, default: false
6
+
7
+ def add_javascripts
8
+ append_file 'vendor/assets/javascripts/spree/frontend/all.js', "//= require spree/frontend/solidus_pagseguro_oficial\n"
9
+ append_file 'vendor/assets/javascripts/spree/backend/all.js', "//= require spree/backend/solidus_pagseguro_oficial\n"
10
+ end
11
+
12
+ def add_stylesheets
13
+ inject_into_file 'vendor/assets/stylesheets/spree/frontend/all.css', " *= require spree/frontend/solidus_pagseguro_oficial\n", :before => /\*\//, :verbose => true
14
+ inject_into_file 'vendor/assets/stylesheets/spree/backend/all.css', " *= require spree/backend/solidus_pagseguro_oficial\n", :before => /\*\//, :verbose => true
15
+ end
16
+
17
+ def add_migrations
18
+ run 'bundle exec rake railties:install:migrations FROM=solidus_pagseguro_oficial'
19
+ end
20
+
21
+ def run_migrations
22
+ run_migrations = options[:auto_run_migrations] || ['', 'y', 'Y'].include?(ask 'Would you like to run the migrations now? [Y/n]')
23
+ if run_migrations
24
+ run 'bundle exec rake db:migrate'
25
+ else
26
+ puts 'Skipping rake db:migrate, don\'t forget to run it!'
27
+ end
28
+ end
29
+ end
30
+ end
31
+ end
@@ -0,0 +1,3 @@
1
+ require 'spree_core'
2
+ require 'pagseguro-oficial'
3
+ require 'solidus_pagseguro_oficial/engine'
@@ -0,0 +1,24 @@
1
+ module SolidusPagseguroOficial
2
+ class Engine < Rails::Engine
3
+ require 'spree/core'
4
+ isolate_namespace Spree
5
+ engine_name 'solidus_pagseguro_oficial'
6
+
7
+ # use rspec for tests
8
+ config.generators do |g|
9
+ g.test_framework :rspec
10
+ end
11
+
12
+ def self.activate
13
+ Dir.glob(File.join(File.dirname(__FILE__), '../../app/**/*_decorator*.rb')) do |c|
14
+ Rails.configuration.cache_classes ? require(c) : load(c)
15
+ end
16
+ end
17
+
18
+ config.to_prepare &method(:activate).to_proc
19
+
20
+ initializer 'spree.pagseguro.payment_methods', after: 'spree.register.payment_methods' do |app|
21
+ app.config.spree.payment_methods << Spree::Gateway::Pagseguro
22
+ end
23
+ end
24
+ end
@@ -0,0 +1,47 @@
1
+ FactoryGirl.define do
2
+ factory :pagseguro_payment_method, class: Spree::Gateway::Pagseguro do
3
+ name 'PagSeguro'
4
+ end
5
+
6
+ factory :country_brazil, class: Spree::Country do
7
+ iso_name 'BRASIL'
8
+ name 'Brasil'
9
+ iso 'BR'
10
+ iso3 'BR'
11
+ numcode 55
12
+ end
13
+
14
+ factory :state_sao_paulo, class: Spree::State do
15
+ name 'São Paulo'
16
+ abbr 'SP'
17
+ country {|country| country.association(:country_brazil) }
18
+ end
19
+
20
+ factory :address_brazil, class: Spree::Address do
21
+ firstname 'José'
22
+ lastname 'Maria'
23
+ company 'Company'
24
+ address1 'Avenida Paulista'
25
+ city {|address| address.association(:city)}
26
+ zipcode '01310917'
27
+ phone '11-989898989'
28
+ alternative_phone '11-987878787'
29
+ number 2323
30
+ district 'Bela Vista'
31
+
32
+ state { |address| address.association(:state_sao_paulo) }
33
+ country do |address|
34
+ if address.state
35
+ address.state.country
36
+ else
37
+ address.association(:country_brazil)
38
+ end
39
+ end
40
+ end
41
+ end
42
+
43
+ FactoryGirl.modify do
44
+ factory :shipping_method do
45
+ name 'SEDEX'
46
+ end
47
+ end
@@ -0,0 +1,33 @@
1
+ # encoding: UTF-8
2
+ Gem::Specification.new do |s|
3
+ s.platform = Gem::Platform::RUBY
4
+ s.name = 'solidus_pagseguro_oficial'
5
+ s.version = '1.1.0'
6
+ s.summary = 'Solidus Extension to PagSeguro integration'
7
+ s.description = s.summary
8
+ s.required_ruby_version = '>= 2.2.2'
9
+
10
+ s.author = 'Diego Domingues'
11
+ s.email = 'diego.domingues16@gmail.com'
12
+ s.homepage = 'https://github.com/ddomingues/solidus_pagseguro_oficial'
13
+
14
+ s.files = `git ls-files`.split("\n")
15
+ s.test_files = `git ls-files -- spec/*`.split("\n")
16
+ s.require_path = 'lib'
17
+ s.requirements << 'none'
18
+
19
+ s.add_runtime_dependency 'solidus_core', '~> 1.1'
20
+ s.add_runtime_dependency 'solidus_br_common', '~> 1.1'
21
+ s.add_dependency 'pagseguro-oficial', '~> 2.4'
22
+
23
+ s.add_development_dependency 'capybara', '~> 2.4'
24
+ s.add_development_dependency 'coffee-rails', '~> 4.1', '>= 4.1.0'
25
+ s.add_development_dependency 'database_cleaner', '~> 1.5', '>= 1.5.1'
26
+ s.add_development_dependency 'factory_girl', '~> 4.5'
27
+ s.add_development_dependency 'ffaker'
28
+ s.add_development_dependency 'rspec-rails', '~> 3.4'
29
+ s.add_development_dependency 'sass-rails', '~> 5.0.4'
30
+ s.add_development_dependency 'selenium-webdriver'
31
+ s.add_development_dependency 'simplecov'
32
+ s.add_development_dependency 'sqlite3'
33
+ end
@@ -0,0 +1,51 @@
1
+ require 'spec_helper'
2
+
3
+ module Spree
4
+ describe PagseguroController do
5
+ let(:address) { build(:address_brazil) }
6
+ let(:order) { create(:order_with_line_items, bill_address: address, ship_address: address) }
7
+ let(:user) {create(:user_with_addreses, bill_address: address, ship_address: address)}
8
+ let(:payment_method) { create(:pagseguro_payment_method) }
9
+
10
+ context '#init_transaction' do
11
+ before { allow(controller).to receive(:current_order).and_return(order) }
12
+
13
+ it 'init transaction case user is present' do
14
+ allow(controller).to receive(:spree_current_user).and_return(user)
15
+
16
+ spree_post :init_transaction, {payment_method_id: "#{payment_method.id}"}
17
+
18
+ expect(response).to be_redirect
19
+ end
20
+ end
21
+
22
+ context '#confirm' do
23
+ context 'when current_order is nil' do
24
+ before do
25
+ allow(controller).to receive(:current_order).and_return(nil)
26
+ allow(controller).to receive(:current_spree_user).and_return(nil)
27
+ end
28
+
29
+ it 'redirects to cart path' do
30
+ spree_post :confirm, {transaction_id: '232'}
31
+
32
+ is_expected.to redirect_to spree.cart_path
33
+ end
34
+ end
35
+ end
36
+
37
+ context '#notify' do
38
+ before do
39
+ allow(controller).to receive(:current_order).and_return(nil)
40
+ allow(controller).to receive(:current_spree_user).and_return(nil)
41
+ end
42
+
43
+ it 'raise error when not inform notificationCode' do
44
+ expect {
45
+ spree_post :notify
46
+ }.to raise_error(ActionController::ParameterMissing)
47
+ end
48
+ end
49
+ end
50
+ end
51
+
@@ -0,0 +1,60 @@
1
+ require 'spec_helper'
2
+
3
+ describe Spree::PagseguroCheckout do
4
+ subject { described_class.new transaction_id: '1223' }
5
+
6
+ ORDER_ID = 1
7
+ STATUS_PAID = 3
8
+ STATUS_CANCELLED = 7
9
+
10
+ context '#process' do
11
+ let(:transaction) { double('transaction').as_null_object }
12
+ let(:status_paid) { PagSeguro::PaymentStatus.new STATUS_PAID}
13
+ let(:status_cancelled) { PagSeguro::PaymentStatus.new STATUS_CANCELLED }
14
+ let(:order) { double('order').as_null_object }
15
+ let(:payment) { double('payment').as_null_object }
16
+
17
+ before do
18
+ allow(order).to receive(:id).and_return(ORDER_ID)
19
+
20
+ allow(payment).to receive(:order).and_return(order)
21
+
22
+ payments = [payment]
23
+ allow(payments).to receive(:pending).and_return(payments)
24
+
25
+ allow(subject).to receive(:payments).and_return(payments)
26
+ allow(subject).to receive(:transaction).and_return(transaction)
27
+ end
28
+
29
+ context 'when valid' do
30
+ before { allow(transaction).to receive(:reference).and_return(ORDER_ID) }
31
+
32
+ it 'completes payment' do
33
+ allow(transaction).to receive(:status).and_return(status_paid)
34
+
35
+ expect(payment).to receive(:complete!)
36
+
37
+ subject.process!
38
+ end
39
+
40
+ it 'voids payment' do
41
+ allow(transaction).to receive(:status).and_return(status_cancelled)
42
+
43
+ expect(payment).to receive(:failure)
44
+ expect(order).to receive(:cancel!)
45
+
46
+ subject.process!
47
+ end
48
+ end
49
+
50
+ context 'when invalid' do
51
+ it 'raises an error when id of the order is not the same in the reference transaction' do
52
+ allow(transaction).to receive(:reference).and_return(2)
53
+
54
+ expect {
55
+ subject.process!
56
+ }.to raise_error(RuntimeError)
57
+ end
58
+ end
59
+ end
60
+ end
@@ -0,0 +1,22 @@
1
+ require 'spec_helper'
2
+
3
+ module Spree
4
+ describe PagseguroProvider do
5
+ HOST = 'http://localhost:3000'
6
+
7
+ context '#init_transaction' do
8
+ let(:address) { build(:address_brazil) }
9
+ let(:order) { create(:order_with_line_items, bill_address: address, ship_address: address) }
10
+ let(:user) { create(:user, bill_address: address) }
11
+
12
+ subject { PagseguroProvider.new order, user, "#{HOST}/notify", "#{HOST}/confirm" }
13
+
14
+ it 'responds success' do
15
+ response = subject.init_transaction!
16
+
17
+ expect(response.errors).to be_empty
18
+ end
19
+ end
20
+ end
21
+ end
22
+
@@ -0,0 +1,40 @@
1
+ # Run Coverage report
2
+ require 'codeclimate-test-reporter'
3
+ CodeClimate::TestReporter.start
4
+
5
+ # Configure Rails Environment
6
+ ENV['RAILS_ENV'] = 'test'
7
+
8
+ require File.expand_path('../dummy/config/environment.rb', __FILE__)
9
+
10
+ require 'rspec/rails'
11
+ require 'database_cleaner'
12
+ require 'ffaker'
13
+
14
+ # Requires supporting ruby files with custom matchers and macros, etc,
15
+ # in spec/support/ and its subdirectories.
16
+ Dir[File.join(File.dirname(__FILE__), 'support/**/*.rb')].each { |f| require f }
17
+
18
+ # Requires factories defined in solidus_core
19
+ require 'spree/testing_support/authorization_helpers'
20
+ require 'spree/testing_support/capybara_ext'
21
+ require 'spree/testing_support/controller_requests'
22
+ require 'spree/testing_support/factories'
23
+ require 'spree/testing_support/url_helpers'
24
+
25
+ require 'solidus_br_common/factories'
26
+ require 'solidus_pagseguro_oficial/factories'
27
+
28
+ RSpec.configure do |config|
29
+ config.include FactoryGirl::Syntax::Methods
30
+ config.include Spree::TestingSupport::UrlHelpers
31
+ config.include Spree::TestingSupport::AuthorizationHelpers::Controller
32
+ config.include Spree::TestingSupport::ControllerRequests, :type => :controller
33
+
34
+ config.mock_with :rspec
35
+ config.color = true
36
+ config.fixture_path = "#{::Rails.root}/spec/fixtures"
37
+ config.fail_fast = ENV['FAIL_FAST'] || false
38
+ config.order = 'random'
39
+ config.infer_spec_type_from_file_location!
40
+ end
@@ -0,0 +1,24 @@
1
+ RSpec.configure do |config|
2
+ # Capybara javascript drivers require transactional fixtures set to false, and we use DatabaseCleaner
3
+ # to cleanup after each test instead. Without transactional fixtures set to false the records created
4
+ # to setup a test will be unavailable to the browser, which runs under a separate server instance.
5
+ config.use_transactional_fixtures = false
6
+
7
+ config.before(:suite) do
8
+ DatabaseCleaner.strategy = :transaction
9
+ DatabaseCleaner.clean_with(:truncation)
10
+ end
11
+
12
+ # Before each spec check if it is a Javascript test and switch between using database transactions or not where necessary.
13
+ config.before(:each) do
14
+ DatabaseCleaner.strategy = RSpec.current_example.metadata[:js] ? :truncation : :transaction
15
+ end
16
+
17
+ config.before(:each) do
18
+ DatabaseCleaner.start
19
+ end
20
+
21
+ config.after(:each) do
22
+ DatabaseCleaner.clean
23
+ end
24
+ end
@@ -0,0 +1,47 @@
1
+ require 'spec_helper'
2
+
3
+ module Spree
4
+ describe PagseguroCheckoutWorker do
5
+ let(:transaction) { double('transaction') }
6
+ let(:pagseguro_checkout) { double('pagseguro_checkout') }
7
+
8
+ before do
9
+ allow(PagSeguro::Transaction).to receive(:find_by_notification_code).with('123').and_return(transaction)
10
+ end
11
+
12
+ it 'process payment when transaction no contains error' do
13
+ mock_errors(transaction)
14
+ allow(transaction).to receive(:code).and_return('321')
15
+ mock_find_with(pagseguro_checkout)
16
+
17
+ expect(pagseguro_checkout).to receive(:process!)
18
+
19
+ subject.perform('123')
20
+ end
21
+
22
+ it 'do not process payment when transaction contains error' do
23
+ mock_errors(transaction, false)
24
+
25
+ expect(pagseguro_checkout).to_not receive(:process!)
26
+
27
+ subject.perform('123')
28
+ end
29
+
30
+ it 'raises error when not exists Spree::PagseguroCheckout for code transaction' do
31
+ mock_errors(transaction)
32
+ allow(transaction).to receive(:code).and_return('222')
33
+
34
+ expect {
35
+ subject.perform('123')
36
+ }.to raise_error(ActiveRecord::RecordNotFound)
37
+ end
38
+
39
+ def mock_errors(transaction, errors_empty=true)
40
+ allow(transaction).to receive_message_chain(:errors, :empty?).and_return(errors_empty)
41
+ end
42
+
43
+ def mock_find_with(pagseguro_checkout)
44
+ allow(Spree::PagseguroCheckout).to receive(:find_by!).with(transaction_id: '321').and_return(pagseguro_checkout)
45
+ end
46
+ end
47
+ end
metadata ADDED
@@ -0,0 +1,282 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: solidus_pagseguro_oficial
3
+ version: !ruby/object:Gem::Version
4
+ version: 1.1.0
5
+ platform: ruby
6
+ authors:
7
+ - Diego Domingues
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2016-01-04 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: solidus_core
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: '1.1'
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: '1.1'
27
+ - !ruby/object:Gem::Dependency
28
+ name: solidus_br_common
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - "~>"
32
+ - !ruby/object:Gem::Version
33
+ version: '1.1'
34
+ type: :runtime
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - "~>"
39
+ - !ruby/object:Gem::Version
40
+ version: '1.1'
41
+ - !ruby/object:Gem::Dependency
42
+ name: pagseguro-oficial
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - "~>"
46
+ - !ruby/object:Gem::Version
47
+ version: '2.4'
48
+ type: :runtime
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - "~>"
53
+ - !ruby/object:Gem::Version
54
+ version: '2.4'
55
+ - !ruby/object:Gem::Dependency
56
+ name: capybara
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - "~>"
60
+ - !ruby/object:Gem::Version
61
+ version: '2.4'
62
+ type: :development
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - "~>"
67
+ - !ruby/object:Gem::Version
68
+ version: '2.4'
69
+ - !ruby/object:Gem::Dependency
70
+ name: coffee-rails
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - "~>"
74
+ - !ruby/object:Gem::Version
75
+ version: '4.1'
76
+ - - ">="
77
+ - !ruby/object:Gem::Version
78
+ version: 4.1.0
79
+ type: :development
80
+ prerelease: false
81
+ version_requirements: !ruby/object:Gem::Requirement
82
+ requirements:
83
+ - - "~>"
84
+ - !ruby/object:Gem::Version
85
+ version: '4.1'
86
+ - - ">="
87
+ - !ruby/object:Gem::Version
88
+ version: 4.1.0
89
+ - !ruby/object:Gem::Dependency
90
+ name: database_cleaner
91
+ requirement: !ruby/object:Gem::Requirement
92
+ requirements:
93
+ - - "~>"
94
+ - !ruby/object:Gem::Version
95
+ version: '1.5'
96
+ - - ">="
97
+ - !ruby/object:Gem::Version
98
+ version: 1.5.1
99
+ type: :development
100
+ prerelease: false
101
+ version_requirements: !ruby/object:Gem::Requirement
102
+ requirements:
103
+ - - "~>"
104
+ - !ruby/object:Gem::Version
105
+ version: '1.5'
106
+ - - ">="
107
+ - !ruby/object:Gem::Version
108
+ version: 1.5.1
109
+ - !ruby/object:Gem::Dependency
110
+ name: factory_girl
111
+ requirement: !ruby/object:Gem::Requirement
112
+ requirements:
113
+ - - "~>"
114
+ - !ruby/object:Gem::Version
115
+ version: '4.5'
116
+ type: :development
117
+ prerelease: false
118
+ version_requirements: !ruby/object:Gem::Requirement
119
+ requirements:
120
+ - - "~>"
121
+ - !ruby/object:Gem::Version
122
+ version: '4.5'
123
+ - !ruby/object:Gem::Dependency
124
+ name: ffaker
125
+ requirement: !ruby/object:Gem::Requirement
126
+ requirements:
127
+ - - ">="
128
+ - !ruby/object:Gem::Version
129
+ version: '0'
130
+ type: :development
131
+ prerelease: false
132
+ version_requirements: !ruby/object:Gem::Requirement
133
+ requirements:
134
+ - - ">="
135
+ - !ruby/object:Gem::Version
136
+ version: '0'
137
+ - !ruby/object:Gem::Dependency
138
+ name: rspec-rails
139
+ requirement: !ruby/object:Gem::Requirement
140
+ requirements:
141
+ - - "~>"
142
+ - !ruby/object:Gem::Version
143
+ version: '3.4'
144
+ type: :development
145
+ prerelease: false
146
+ version_requirements: !ruby/object:Gem::Requirement
147
+ requirements:
148
+ - - "~>"
149
+ - !ruby/object:Gem::Version
150
+ version: '3.4'
151
+ - !ruby/object:Gem::Dependency
152
+ name: sass-rails
153
+ requirement: !ruby/object:Gem::Requirement
154
+ requirements:
155
+ - - "~>"
156
+ - !ruby/object:Gem::Version
157
+ version: 5.0.4
158
+ type: :development
159
+ prerelease: false
160
+ version_requirements: !ruby/object:Gem::Requirement
161
+ requirements:
162
+ - - "~>"
163
+ - !ruby/object:Gem::Version
164
+ version: 5.0.4
165
+ - !ruby/object:Gem::Dependency
166
+ name: selenium-webdriver
167
+ requirement: !ruby/object:Gem::Requirement
168
+ requirements:
169
+ - - ">="
170
+ - !ruby/object:Gem::Version
171
+ version: '0'
172
+ type: :development
173
+ prerelease: false
174
+ version_requirements: !ruby/object:Gem::Requirement
175
+ requirements:
176
+ - - ">="
177
+ - !ruby/object:Gem::Version
178
+ version: '0'
179
+ - !ruby/object:Gem::Dependency
180
+ name: simplecov
181
+ requirement: !ruby/object:Gem::Requirement
182
+ requirements:
183
+ - - ">="
184
+ - !ruby/object:Gem::Version
185
+ version: '0'
186
+ type: :development
187
+ prerelease: false
188
+ version_requirements: !ruby/object:Gem::Requirement
189
+ requirements:
190
+ - - ">="
191
+ - !ruby/object:Gem::Version
192
+ version: '0'
193
+ - !ruby/object:Gem::Dependency
194
+ name: sqlite3
195
+ requirement: !ruby/object:Gem::Requirement
196
+ requirements:
197
+ - - ">="
198
+ - !ruby/object:Gem::Version
199
+ version: '0'
200
+ type: :development
201
+ prerelease: false
202
+ version_requirements: !ruby/object:Gem::Requirement
203
+ requirements:
204
+ - - ">="
205
+ - !ruby/object:Gem::Version
206
+ version: '0'
207
+ description: Solidus Extension to PagSeguro integration
208
+ email: diego.domingues16@gmail.com
209
+ executables: []
210
+ extensions: []
211
+ extra_rdoc_files: []
212
+ files:
213
+ - ".gitignore"
214
+ - ".rspec"
215
+ - ".ruby-gemset"
216
+ - ".ruby-version"
217
+ - ".travis.yml"
218
+ - Gemfile
219
+ - LICENSE
220
+ - README.md
221
+ - Rakefile
222
+ - app/assets/javascripts/spree/backend/solidus_pagseguro_oficial.js
223
+ - app/assets/javascripts/spree/frontend/solidus_pagseguro_oficial.js
224
+ - app/assets/stylesheets/spree/backend/solidus_pagseguro_oficial.css
225
+ - app/assets/stylesheets/spree/frontend/solidus_pagseguro_oficial.css
226
+ - app/controllers/spree/pagseguro_controller.rb
227
+ - app/models/spree/gateway/pagseguro.rb
228
+ - app/models/spree/pagseguro_checkout.rb
229
+ - app/models/spree/pagseguro_provider.rb
230
+ - app/overrides/spree/admin/general_settings/edit/add_env_vars_of_pagseguro_account.html.erb.deface
231
+ - app/views/spree/checkout/payment/_pagseguro.html.erb
232
+ - app/workers/spree/pagseguro_checkout_worker.rb
233
+ - bin/rails
234
+ - config/initializers/pagseguro.rb
235
+ - config/locales/en.yml
236
+ - config/locales/pt-BR.yml
237
+ - config/routes.rb
238
+ - db/default/payment_methods.rb
239
+ - db/migrate/20140611173248_create_spree_pagseguro_checkouts.rb
240
+ - db/seeds.rb
241
+ - lib/generators/solidus_pagseguro_oficial/install/install_generator.rb
242
+ - lib/solidus_pagseguro_oficial.rb
243
+ - lib/solidus_pagseguro_oficial/engine.rb
244
+ - lib/solidus_pagseguro_oficial/factories.rb
245
+ - solidus_pagseguro_oficial.gemspec
246
+ - spec/controllers/pagseguro_controller_spec.rb
247
+ - spec/models/spree/pagseguro_checkout_spec.rb
248
+ - spec/models/spree/pagseguro_provider_spec.rb
249
+ - spec/spec_helper.rb
250
+ - spec/support/database_cleaner.rb
251
+ - spec/workers/spree/pagseguro_checkout_worker_spec.rb
252
+ homepage: https://github.com/ddomingues/solidus_pagseguro_oficial
253
+ licenses: []
254
+ metadata: {}
255
+ post_install_message:
256
+ rdoc_options: []
257
+ require_paths:
258
+ - lib
259
+ required_ruby_version: !ruby/object:Gem::Requirement
260
+ requirements:
261
+ - - ">="
262
+ - !ruby/object:Gem::Version
263
+ version: 2.2.2
264
+ required_rubygems_version: !ruby/object:Gem::Requirement
265
+ requirements:
266
+ - - ">="
267
+ - !ruby/object:Gem::Version
268
+ version: '0'
269
+ requirements:
270
+ - none
271
+ rubyforge_project:
272
+ rubygems_version: 2.4.8
273
+ signing_key:
274
+ specification_version: 4
275
+ summary: Solidus Extension to PagSeguro integration
276
+ test_files:
277
+ - spec/controllers/pagseguro_controller_spec.rb
278
+ - spec/models/spree/pagseguro_checkout_spec.rb
279
+ - spec/models/spree/pagseguro_provider_spec.rb
280
+ - spec/spec_helper.rb
281
+ - spec/support/database_cleaner.rb
282
+ - spec/workers/spree/pagseguro_checkout_worker_spec.rb