trado_paypal_module 0.9.1
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.
- checksums.yaml +7 -0
- data/MIT-LICENSE +20 -0
- data/Rakefile +34 -0
- data/app/controllers/trado_paypal_module/ipn_controller.rb +26 -0
- data/app/controllers/trado_paypal_module/paypal_controller.rb +36 -0
- data/config/routes.rb +3 -0
- data/lib/generators/templates/controller.rb +6 -0
- data/lib/generators/templates/helper.rb +6 -0
- data/lib/generators/templates/migration.rb +13 -0
- data/lib/generators/trado_paypal_module/install_generator.rb +91 -0
- data/lib/tasks/trado_paypal_module_tasks.rake +4 -0
- data/lib/trado_paypal_module.rb +12 -0
- data/lib/trado_paypal_module/active_record.rb +15 -0
- data/lib/trado_paypal_module/engine.rb +6 -0
- data/lib/trado_paypal_module/paypaler.rb +219 -0
- data/lib/trado_paypal_module/version.rb +3 -0
- data/test/dummy/README.rdoc +28 -0
- data/test/dummy/Rakefile +6 -0
- data/test/dummy/app/assets/javascripts/application.js +13 -0
- data/test/dummy/app/assets/stylesheets/application.css +15 -0
- data/test/dummy/app/controllers/application_controller.rb +5 -0
- data/test/dummy/app/helpers/application_helper.rb +2 -0
- data/test/dummy/app/views/layouts/application.html.erb +14 -0
- data/test/dummy/bin/bundle +3 -0
- data/test/dummy/bin/rails +4 -0
- data/test/dummy/bin/rake +4 -0
- data/test/dummy/bin/setup +29 -0
- data/test/dummy/config.ru +4 -0
- data/test/dummy/config/application.rb +26 -0
- data/test/dummy/config/boot.rb +5 -0
- data/test/dummy/config/database.yml +25 -0
- data/test/dummy/config/environment.rb +5 -0
- data/test/dummy/config/environments/development.rb +41 -0
- data/test/dummy/config/environments/production.rb +79 -0
- data/test/dummy/config/environments/test.rb +42 -0
- data/test/dummy/config/initializers/assets.rb +11 -0
- data/test/dummy/config/initializers/backtrace_silencers.rb +7 -0
- data/test/dummy/config/initializers/cookies_serializer.rb +3 -0
- data/test/dummy/config/initializers/filter_parameter_logging.rb +4 -0
- data/test/dummy/config/initializers/inflections.rb +16 -0
- data/test/dummy/config/initializers/mime_types.rb +4 -0
- data/test/dummy/config/initializers/session_store.rb +3 -0
- data/test/dummy/config/initializers/wrap_parameters.rb +14 -0
- data/test/dummy/config/locales/en.yml +23 -0
- data/test/dummy/config/routes.rb +56 -0
- data/test/dummy/config/secrets.yml +22 -0
- data/test/dummy/public/404.html +67 -0
- data/test/dummy/public/422.html +67 -0
- data/test/dummy/public/500.html +66 -0
- data/test/dummy/public/favicon.ico +0 -0
- data/test/test_helper.rb +20 -0
- data/test/trado_paypal_module_test.rb +7 -0
- metadata +173 -0
checksums.yaml
ADDED
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
---
|
|
2
|
+
SHA1:
|
|
3
|
+
metadata.gz: eb0fc1e85e04eec3a1950232e9d16b9209263dba
|
|
4
|
+
data.tar.gz: 2865fc5e70d08593d5fa176c9be02582f0fa73bc
|
|
5
|
+
SHA512:
|
|
6
|
+
metadata.gz: 9ce411a3afd6fd97697e65cb7d6f24c130d75b94da7b4326fafadaa5ac8e01db4f8d49a5310a39c7ec67978d961397ead41b8c34a58592f37193fe31baec63ee
|
|
7
|
+
data.tar.gz: 388365d0b59ccfa689da49dc8876a12c2b226c31d1785e34af14f5dfdf3fe52707db304f98243bc2bf122775f224498d287ca7cb46549aca448f49a2c1ff20e2
|
data/MIT-LICENSE
ADDED
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
Copyright 2016 Tom Dallimore
|
|
2
|
+
|
|
3
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
|
4
|
+
a copy of this software and associated documentation files (the
|
|
5
|
+
"Software"), to deal in the Software without restriction, including
|
|
6
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
|
7
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
|
8
|
+
permit persons to whom the Software is furnished to do so, subject to
|
|
9
|
+
the following conditions:
|
|
10
|
+
|
|
11
|
+
The above copyright notice and this permission notice shall be
|
|
12
|
+
included in all copies or substantial portions of the Software.
|
|
13
|
+
|
|
14
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
|
15
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
|
16
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
|
17
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
|
18
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
|
19
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
|
20
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/Rakefile
ADDED
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
begin
|
|
2
|
+
require 'bundler/setup'
|
|
3
|
+
rescue LoadError
|
|
4
|
+
puts 'You must `gem install bundler` and `bundle install` to run rake tasks'
|
|
5
|
+
end
|
|
6
|
+
|
|
7
|
+
require 'rdoc/task'
|
|
8
|
+
|
|
9
|
+
RDoc::Task.new(:rdoc) do |rdoc|
|
|
10
|
+
rdoc.rdoc_dir = 'rdoc'
|
|
11
|
+
rdoc.title = 'TradoPaypalModule'
|
|
12
|
+
rdoc.options << '--line-numbers'
|
|
13
|
+
rdoc.rdoc_files.include('README.rdoc')
|
|
14
|
+
rdoc.rdoc_files.include('lib/**/*.rb')
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
Bundler::GemHelper.install_tasks
|
|
23
|
+
|
|
24
|
+
require 'rake/testtask'
|
|
25
|
+
|
|
26
|
+
Rake::TestTask.new(:test) do |t|
|
|
27
|
+
t.libs << 'lib'
|
|
28
|
+
t.libs << 'test'
|
|
29
|
+
t.pattern = 'test/**/*_test.rb'
|
|
30
|
+
t.verbose = false
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
|
|
34
|
+
task default: :test
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
class TradoPaypalModule::IpnController < ApplicationController
|
|
2
|
+
skip_before_action :authenticate_user!
|
|
3
|
+
|
|
4
|
+
# TODO: Find out why this is throwing an error.
|
|
5
|
+
include ActiveMerchant::Billing::Integrations
|
|
6
|
+
|
|
7
|
+
# Handler for incoming Instant Payment Notifications from paypal about orders
|
|
8
|
+
def update
|
|
9
|
+
notify = Paypal::Notification.new(request.raw_post)
|
|
10
|
+
|
|
11
|
+
if notify.acknowledge
|
|
12
|
+
transaction = Transaction.where(order_id: notify.params['invoice']).first
|
|
13
|
+
if notify.complete? and transaction.gross_amount.to_s == notify.params['mc_gross']
|
|
14
|
+
transaction.fee = notify.params['mc_fee']
|
|
15
|
+
transaction.completed!
|
|
16
|
+
else
|
|
17
|
+
transaction.failed!
|
|
18
|
+
end
|
|
19
|
+
if transaction.save
|
|
20
|
+
Mailatron4000::Orders.confirmation_email(transaction.order) rescue Rails.logger.warn("PayPal IPN: Order #{transaction.order.id} confirmation email failed to send")
|
|
21
|
+
end
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
render nothing: true
|
|
25
|
+
end
|
|
26
|
+
end
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
class TradoPaypalModule::PaypalController < ApplicationController
|
|
2
|
+
skip_before_action :authenticate_user!
|
|
3
|
+
include CartBuilder
|
|
4
|
+
|
|
5
|
+
def confirm
|
|
6
|
+
set_order
|
|
7
|
+
set_cart_totals
|
|
8
|
+
set_grouped_countries
|
|
9
|
+
set_browser_data
|
|
10
|
+
@order.attributes = params[:order]
|
|
11
|
+
if @order.save
|
|
12
|
+
@order.calculate(current_cart, Store.tax_rate)
|
|
13
|
+
generate_payment_url
|
|
14
|
+
if @redirect_url.nil?
|
|
15
|
+
flash_message :error, 'An error ocurred with your order. Please try again.'
|
|
16
|
+
Rails.logger.error "PayPal: Unable to generate redirect URL."
|
|
17
|
+
redirect_to checkout_carts_url
|
|
18
|
+
else
|
|
19
|
+
redirect_to @redirect_url
|
|
20
|
+
end
|
|
21
|
+
else
|
|
22
|
+
flash_message :error, 'An error ocurred with your order. Please try again.'
|
|
23
|
+
render theme_presenter.page_template_path('carts/checkout'), layout: theme_presenter.layout_template_path
|
|
24
|
+
end
|
|
25
|
+
rescue ActiveMerchant::ConnectionError
|
|
26
|
+
flash_message :error, 'An error ocurred with your order. Please try again.'
|
|
27
|
+
Rails.logger.error "PayPal: API is temporarily unavailable."
|
|
28
|
+
redirect_to checkout_carts_url
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
private
|
|
32
|
+
|
|
33
|
+
def generate_payment_url
|
|
34
|
+
@redirect_url = Store::PayProvider.new(cart: current_cart, order: @order, provider: @order.payment_type, ip_address: request.remote_ip).build
|
|
35
|
+
end
|
|
36
|
+
end
|
data/config/routes.rb
ADDED
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
class AddPaypalAttributes < ActiveRecord::Migration
|
|
2
|
+
def self.up
|
|
3
|
+
add_column :transactions, :paypal_id, :string
|
|
4
|
+
add_column :orders, :paypal_express_token, :string
|
|
5
|
+
add_column :orders, :paypal_express_payer_id, :string
|
|
6
|
+
end
|
|
7
|
+
|
|
8
|
+
def self.down
|
|
9
|
+
remove_column :transactions, :paypal_id
|
|
10
|
+
remove_column :orders, :paypal_express_token
|
|
11
|
+
remove_column :orders, :paypal_express_payer_id
|
|
12
|
+
end
|
|
13
|
+
end
|
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
module TradoPaypalModule
|
|
2
|
+
module Generators
|
|
3
|
+
class InstallGenerator < Rails::Generators::Base
|
|
4
|
+
source_root File.expand_path("../../templates", __FILE__)
|
|
5
|
+
|
|
6
|
+
def copy_migration
|
|
7
|
+
unless paypal_migration_already_exists?
|
|
8
|
+
timestamp_number = Time.now.utc.strftime("%Y%m%d%H%M%S").to_i
|
|
9
|
+
copy_file "migration.rb", "db/migrate/#{timestamp_number}_add_paypal_attributes.rb"
|
|
10
|
+
end
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
def copy_helper
|
|
14
|
+
template "helper.rb", "app/helpers/paypal_helper.rb"
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
def copy_controller
|
|
18
|
+
template "controller.rb", "app/controllers/carts/paypal_controller.rb"
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
def setup_routes
|
|
22
|
+
route_content = <<-CONTENT
|
|
23
|
+
|
|
24
|
+
mount TradoPaypalModule::Engine => '/paypal'
|
|
25
|
+
CONTENT
|
|
26
|
+
inject_into_file "config/routes.rb", route_content, after: "Trado::Application.routes.draw do"
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
def assign_model_concerns
|
|
30
|
+
order_content = <<-CONTENT
|
|
31
|
+
|
|
32
|
+
has_order_paypal
|
|
33
|
+
CONTENT
|
|
34
|
+
transaction_content = <<-CONTENT
|
|
35
|
+
|
|
36
|
+
has_transaction_paypal
|
|
37
|
+
CONTENT
|
|
38
|
+
|
|
39
|
+
inject_into_file "app/models/order.rb", order_content, after: "class Order < ActiveRecord::Base"
|
|
40
|
+
inject_into_file "app/models/transaction.rb", transaction_content, after: "class Transaction < ActiveRecord::Base"
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
def setup_env_configs
|
|
44
|
+
development_content = <<-CONTENT
|
|
45
|
+
|
|
46
|
+
# PayPal settings
|
|
47
|
+
config.after_initialize do
|
|
48
|
+
ActiveMerchant::Billing::Base.mode = :test
|
|
49
|
+
paypal_options = {
|
|
50
|
+
login: Rails.application.secrets.paypal_login,
|
|
51
|
+
password: Rails.application.secrets.paypal_password,
|
|
52
|
+
signature: Rails.application.secrets.paypal_signature
|
|
53
|
+
}
|
|
54
|
+
::EXPRESS_GATEWAY = ActiveMerchant::Billing::PaypalExpressGateway.new(paypal_options)
|
|
55
|
+
end
|
|
56
|
+
CONTENT
|
|
57
|
+
|
|
58
|
+
test_content = <<-CONTENT
|
|
59
|
+
|
|
60
|
+
# PayPal settings
|
|
61
|
+
config.after_initialize do
|
|
62
|
+
ActiveMerchant::Billing::Base.mode = :test
|
|
63
|
+
::EXPRESS_GATEWAY = ActiveMerchant::Billing::BogusGateway.new
|
|
64
|
+
end
|
|
65
|
+
CONTENT
|
|
66
|
+
|
|
67
|
+
production_content = <<-CONTENT
|
|
68
|
+
|
|
69
|
+
# PayPal settings
|
|
70
|
+
config.after_initialize do
|
|
71
|
+
paypal_options = {
|
|
72
|
+
login: Rails.application.secrets.paypal_login,
|
|
73
|
+
password: Rails.application.secrets.paypal_password,
|
|
74
|
+
signature: Rails.application.secrets.paypal_signature
|
|
75
|
+
}
|
|
76
|
+
::EXPRESS_GATEWAY = ActiveMerchant::Billing::PaypalExpressGateway.new(paypal_options)
|
|
77
|
+
end
|
|
78
|
+
CONTENT
|
|
79
|
+
inject_into_file "config/environments/development.rb", development_content, after: "Trado::Application.configure do"
|
|
80
|
+
inject_into_file "config/environments/test.rb", test_content, after: "Trado::Application.configure do"
|
|
81
|
+
inject_into_file "config/environments/production.rb", production_content, after: "Trado::Application.configure do"
|
|
82
|
+
end
|
|
83
|
+
|
|
84
|
+
private
|
|
85
|
+
|
|
86
|
+
def paypal_migration_already_exists?
|
|
87
|
+
Dir.glob("#{File.join(destination_root, File.join("db", "migrate"))}/[0-9]*_*.rb").grep(/\d+_add_paypal_attributes.rb$/).first
|
|
88
|
+
end
|
|
89
|
+
end
|
|
90
|
+
end
|
|
91
|
+
end
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
module TradoPaypalModule
|
|
2
|
+
end
|
|
3
|
+
|
|
4
|
+
require 'activemerchant'
|
|
5
|
+
require 'offsite_payments'
|
|
6
|
+
|
|
7
|
+
require 'trado_paypal_module/engine'
|
|
8
|
+
require 'trado_paypal_module/version'
|
|
9
|
+
require 'trado_paypal_module/active_record'
|
|
10
|
+
require 'trado_paypal_module/paypaler'
|
|
11
|
+
|
|
12
|
+
ActiveRecord::Base.send(:include, TradoPaypalModule::ActiveRecord)
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
module TradoPaypalModule
|
|
2
|
+
module ActiveRecord
|
|
3
|
+
extend ActiveSupport::Concern
|
|
4
|
+
|
|
5
|
+
module ClassMethods
|
|
6
|
+
def has_order_paypal
|
|
7
|
+
attr_accessible :paypal_express_token, :paypal_express_payer_id
|
|
8
|
+
end
|
|
9
|
+
|
|
10
|
+
def has_transaction_paypal
|
|
11
|
+
attr_accessible :paypal_id
|
|
12
|
+
end
|
|
13
|
+
end
|
|
14
|
+
end
|
|
15
|
+
end
|
|
@@ -0,0 +1,219 @@
|
|
|
1
|
+
require_dependency 'lib/payatron_4000'
|
|
2
|
+
|
|
3
|
+
module TradoPaypalModule
|
|
4
|
+
|
|
5
|
+
class Paypaler
|
|
6
|
+
|
|
7
|
+
# Builds the a PayPal purchase request from the order data
|
|
8
|
+
# If successful, redirect to PayPal for the user to login
|
|
9
|
+
# If unsuccessful, redirect to failed order page
|
|
10
|
+
#
|
|
11
|
+
# @param cart [Object]
|
|
12
|
+
# @param order [Object]
|
|
13
|
+
# @param ip_address [String]
|
|
14
|
+
# @return [String] redirect url
|
|
15
|
+
def self.build cart, order, ip_address
|
|
16
|
+
response = EXPRESS_GATEWAY.setup_purchase(
|
|
17
|
+
Store::Price.new(price: order.gross_amount, tax_type: 'net').singularize,
|
|
18
|
+
TradoPaypalModule::Paypaler.express_setup_options(
|
|
19
|
+
order,
|
|
20
|
+
cart,
|
|
21
|
+
ip_address,
|
|
22
|
+
Rails.application.routes.url_helpers.confirm_order_url(order, host: Trado::Application.config.action_mailer.default_url_options[:host]),
|
|
23
|
+
Rails.application.routes.url_helpers.mycart_carts_url(host: Trado::Application.config.action_mailer.default_url_options[:host])
|
|
24
|
+
)
|
|
25
|
+
)
|
|
26
|
+
if response.success?
|
|
27
|
+
return EXPRESS_GATEWAY.redirect_url_for(response.token)
|
|
28
|
+
else
|
|
29
|
+
TradoPaypalModule::Paypaler.failed(response, order)
|
|
30
|
+
Payatron4000.decommission_order(order)
|
|
31
|
+
return Rails.application.routes.url_helpers.failed_order_url(order, host: Trado::Application.config.action_mailer.default_url_options[:host])
|
|
32
|
+
end
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
# Creates the payment information object for PayPal to parse in the login
|
|
36
|
+
#
|
|
37
|
+
# @param order [Object]
|
|
38
|
+
# @param cart [Object]
|
|
39
|
+
# @param ip_address [String]
|
|
40
|
+
# @param return_url [String]
|
|
41
|
+
# @param cancel_url [String]
|
|
42
|
+
# @return [Object] order data from the store for PayPal
|
|
43
|
+
def self.express_setup_options order, cart, ip_address, return_url, cancel_url
|
|
44
|
+
{
|
|
45
|
+
:subtotal => Store::Price.new(price: (order.net_amount - order.delivery.price), tax_type: 'net').singularize,
|
|
46
|
+
:shipping => Store::Price.new(price: order.delivery.price, tax_type: 'net').singularize,
|
|
47
|
+
:tax => Store::Price.new(price: order.tax_amount, tax_type: 'net').singularize,
|
|
48
|
+
:handling => 0,
|
|
49
|
+
:order_id => order.id,
|
|
50
|
+
:items => TradoPaypalModule::Paypaler.express_items(cart.cart_items),
|
|
51
|
+
:address_override => 1,
|
|
52
|
+
:shipping_address => order.delivery_address.full_address,
|
|
53
|
+
:req_confirm_shipping => 0,
|
|
54
|
+
:ip => ip_address,
|
|
55
|
+
:return_url => return_url,
|
|
56
|
+
:cancel_return_url => cancel_url,
|
|
57
|
+
:currency => Store.settings.currency_code,
|
|
58
|
+
}
|
|
59
|
+
end
|
|
60
|
+
|
|
61
|
+
# Creates the payment information object for PayPal to parse in the confirmation step and complete the purchase
|
|
62
|
+
#
|
|
63
|
+
# @param order [Object]
|
|
64
|
+
# @return [Object] current customer order
|
|
65
|
+
def self.express_purchase_options order, ip_address
|
|
66
|
+
{
|
|
67
|
+
:subtotal => Store::Price.new(price: (order.net_amount - order.delivery.price), tax_type: 'net').singularize,
|
|
68
|
+
:shipping => Store::Price.new(price: order.delivery.price, tax_type: 'net').singularize,
|
|
69
|
+
:tax => Store::Price.new(price: order.tax_amount, tax_type: 'net').singularize,
|
|
70
|
+
:handling => 0,
|
|
71
|
+
:items => TradoPaypalModule::Paypaler.express_items(order.order_items),
|
|
72
|
+
:token => order.paypal_express_token,
|
|
73
|
+
:payer_id => order.paypal_express_payer_id,
|
|
74
|
+
:currency => Store.settings.currency_code,
|
|
75
|
+
:ip => ip_address,
|
|
76
|
+
}
|
|
77
|
+
end
|
|
78
|
+
|
|
79
|
+
# Creates an aray of items which represent cart_items or order_items
|
|
80
|
+
# This is passed into the express_setup_options and express_purchase_options methods
|
|
81
|
+
#
|
|
82
|
+
# @return [Array] list of cart or order items for PayPal
|
|
83
|
+
def self.express_items items
|
|
84
|
+
items.collect do |item|
|
|
85
|
+
{
|
|
86
|
+
:name => "#{item.sku.product.name} (#{item.sku.variants.map{|v| v.name.titleize}.join(' / ')})",
|
|
87
|
+
:description => "#{item.sku.product.name} (#{item.sku.variants.map{|v| v.name.titleize}.join(' / ')})",
|
|
88
|
+
:amount => Store::Price.new(price: item.price, tax_type: 'net').singularize,
|
|
89
|
+
:quantity => item.quantity
|
|
90
|
+
}
|
|
91
|
+
end
|
|
92
|
+
end
|
|
93
|
+
|
|
94
|
+
# Assign PayPal token to order after user logs into their account
|
|
95
|
+
#
|
|
96
|
+
# @param token [String]
|
|
97
|
+
# @param payer_id [Integer]
|
|
98
|
+
# @param order [Object]
|
|
99
|
+
def self.assign_paypal_token token, payer_id, order
|
|
100
|
+
order.paypal_express_token = token
|
|
101
|
+
order.paypal_express_payer_id = payer_id
|
|
102
|
+
order.save(validate: false)
|
|
103
|
+
end
|
|
104
|
+
|
|
105
|
+
# Completes the order process by communicating with PayPal; receives a response and in turn creates the relevant transaction records,
|
|
106
|
+
# sends a confirmation email and redirects the user.
|
|
107
|
+
#
|
|
108
|
+
# @param order [Object]
|
|
109
|
+
# @param session [Object
|
|
110
|
+
def self.complete order, session, ip_address
|
|
111
|
+
order.transfer(order.cart)
|
|
112
|
+
response = EXPRESS_GATEWAY.purchase(Store::Price.new(price: order.gross_amount, tax_type: 'net').singularize,
|
|
113
|
+
TradoPaypalModule::Paypaler.express_purchase_options(order, ip_address)
|
|
114
|
+
)
|
|
115
|
+
if response.success?
|
|
116
|
+
TradoPaypalModule::Paypaler.successful(response, order)
|
|
117
|
+
Payatron4000.destroy_cart(session)
|
|
118
|
+
Payatron4000.decommission_order(order)
|
|
119
|
+
order.reload
|
|
120
|
+
Mailatron4000::Orders.confirmation_email(order)
|
|
121
|
+
return Rails.application.routes.url_helpers.success_order_url(order, host: Trado::Application.config.action_mailer.default_url_options[:host])
|
|
122
|
+
else
|
|
123
|
+
TradoPaypalModule::Paypaler.failed(response, order)
|
|
124
|
+
order.reload
|
|
125
|
+
Mailatron4000::Orders.confirmation_email(order)
|
|
126
|
+
return Rails.application.routes.url_helpers.failed_order_url(order, host: Trado::Application.config.action_mailer.default_url_options[:host])
|
|
127
|
+
end
|
|
128
|
+
end
|
|
129
|
+
|
|
130
|
+
# Upon successfully completing an order with a PayPal payment option a new transaction record is created, stock is updated for the relevant SKU
|
|
131
|
+
#
|
|
132
|
+
# @param response [Object]
|
|
133
|
+
# @param order [Object]
|
|
134
|
+
def self.successful response, order
|
|
135
|
+
Transaction.new( :fee => response.params['PaymentInfo']['FeeAmount'],
|
|
136
|
+
:order_id => order.id,
|
|
137
|
+
:payment_status => response.params['PaymentInfo']['PaymentStatus'].downcase,
|
|
138
|
+
:transaction_type => 'Credit',
|
|
139
|
+
:tax_amount => response.params['PaymentInfo']['TaxAmount'],
|
|
140
|
+
:paypal_id => response.params['PaymentInfo']['TransactionID'],
|
|
141
|
+
:payment_type => 'paypal',
|
|
142
|
+
:net_amount => response.params['PaymentInfo']['GrossAmount'].to_d - response.params['PaymentInfo']['TaxAmount'].to_d,
|
|
143
|
+
:gross_amount => response.params['PaymentInfo']['GrossAmount'],
|
|
144
|
+
:status_reason => response.params['PaymentInfo']['PendingReason']
|
|
145
|
+
).save(validate: false)
|
|
146
|
+
Payatron4000.update_stock(order)
|
|
147
|
+
Payatron4000.increment_product_order_count(order.products)
|
|
148
|
+
end
|
|
149
|
+
|
|
150
|
+
|
|
151
|
+
# When an order has failed to complete, a new transaction record is created with a logged status reason
|
|
152
|
+
#
|
|
153
|
+
# @param response [Object]
|
|
154
|
+
# @param order [Object]
|
|
155
|
+
def self.failed response, order
|
|
156
|
+
Transaction.new( :fee => 0,
|
|
157
|
+
:gross_amount => order.gross_amount,
|
|
158
|
+
:order_id => order.id,
|
|
159
|
+
:payment_status => 'failed',
|
|
160
|
+
:transaction_type => 'Credit',
|
|
161
|
+
:tax_amount => order.tax_amount,
|
|
162
|
+
:paypal_id => nil,
|
|
163
|
+
:payment_type => 'paypal',
|
|
164
|
+
:net_amount => order.net_amount,
|
|
165
|
+
:status_reason => response.message,
|
|
166
|
+
:error_code => response.params["error_codes"].to_i
|
|
167
|
+
).save(validate: false)
|
|
168
|
+
Payatron4000.increment_product_order_count(order.products)
|
|
169
|
+
end
|
|
170
|
+
|
|
171
|
+
# A list of available currency codes for the PayPal payment system
|
|
172
|
+
#
|
|
173
|
+
# @return [Array] available currency codes
|
|
174
|
+
def self.currency_codes
|
|
175
|
+
return [
|
|
176
|
+
"AUD",
|
|
177
|
+
"CAD",
|
|
178
|
+
"CZK",
|
|
179
|
+
"DKK",
|
|
180
|
+
"EUR",
|
|
181
|
+
"HKD",
|
|
182
|
+
"HUF",
|
|
183
|
+
"ILS",
|
|
184
|
+
"JPY",
|
|
185
|
+
"MXN",
|
|
186
|
+
"NOK",
|
|
187
|
+
"NZD",
|
|
188
|
+
"PHP",
|
|
189
|
+
"PLN",
|
|
190
|
+
"GBP",
|
|
191
|
+
"RUB",
|
|
192
|
+
"SGD",
|
|
193
|
+
"SEK",
|
|
194
|
+
"CHF",
|
|
195
|
+
"TWD",
|
|
196
|
+
"THB",
|
|
197
|
+
"USD"
|
|
198
|
+
]
|
|
199
|
+
end
|
|
200
|
+
|
|
201
|
+
# A list of fatal error codes for an order
|
|
202
|
+
# If the passed in error code parameter is included in the fatal codes array, return true
|
|
203
|
+
#
|
|
204
|
+
# @param error_code [Integer] payment error code
|
|
205
|
+
# @return [Boolean]
|
|
206
|
+
def self.fatal_error_code? error_code
|
|
207
|
+
@fatal_codes =
|
|
208
|
+
[
|
|
209
|
+
10412, # PayPal: Payment has already been made for this InvoiceID.
|
|
210
|
+
10415 # PayPal: A successful transaction has already been completed for this token.
|
|
211
|
+
]
|
|
212
|
+
return @fatal_codes.include?(error_code) ? true : false
|
|
213
|
+
end
|
|
214
|
+
|
|
215
|
+
def self.valid_tokens? params
|
|
216
|
+
params[:token].present? && params[:PayerID].present?
|
|
217
|
+
end
|
|
218
|
+
end
|
|
219
|
+
end
|