active_payment 0.0.5
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/app/controllers/active_payment/paypal_adaptive_payment_callback_controller.rb +26 -0
- data/app/controllers/active_payment/paypal_express_checkout_callback_controller.rb +33 -0
- data/app/models/active_payment/transaction.rb +18 -0
- data/config/routes.rb +9 -0
- data/db/migrate/20150813161144_create_payments_transactions.rb +22 -0
- data/lib/active_payment/configuration.rb +14 -0
- data/lib/active_payment/engine.rb +23 -0
- data/lib/active_payment/gateway.rb +125 -0
- data/lib/active_payment/gateways/paypal_adaptive_payment.rb +85 -0
- data/lib/active_payment/gateways/paypal_express_checkout.rb +86 -0
- data/lib/active_payment/models/concerns/payable.rb +32 -0
- data/lib/active_payment/models/concerns/payee.rb +27 -0
- data/lib/active_payment/models/concerns/payer.rb +13 -0
- data/lib/active_payment/models/sale.rb +60 -0
- data/lib/active_payment/models/sales.rb +78 -0
- data/lib/active_payment/version.rb +3 -0
- data/lib/active_payment.rb +36 -0
- data/spec/active_payment/configuration_spec.rb +59 -0
- data/spec/active_payment/controllers/paypal_adaptive_payment_callback_controller_spec.rb +77 -0
- data/spec/active_payment/controllers/paypal_express_checkout_callback_controller_spec.rb +102 -0
- data/spec/active_payment/gateway_spec.rb +140 -0
- data/spec/active_payment/gateways/paypal_adaptive_payment_spec.rb +105 -0
- data/spec/active_payment/gateways/paypal_express_checkout_spec.rb +144 -0
- data/spec/active_payment/models/sale_spec.rb +109 -0
- data/spec/active_payment/models/sales_spec.rb +93 -0
- data/spec/active_payment/models/transaction_spec.rb +31 -0
- data/spec/dummy/README.rdoc +28 -0
- data/spec/dummy/Rakefile +6 -0
- data/spec/dummy/app/assets/javascripts/application.js +13 -0
- data/spec/dummy/app/assets/stylesheets/application.css +13 -0
- data/spec/dummy/app/controllers/application_controller.rb +5 -0
- data/spec/dummy/app/helpers/application_helper.rb +2 -0
- data/spec/dummy/app/views/layouts/application.html.erb +14 -0
- data/spec/dummy/bin/bundle +3 -0
- data/spec/dummy/bin/rails +4 -0
- data/spec/dummy/bin/rake +4 -0
- data/spec/dummy/config/application.rb +29 -0
- data/spec/dummy/config/boot.rb +5 -0
- data/spec/dummy/config/database.yml +25 -0
- data/spec/dummy/config/environment.rb +5 -0
- data/spec/dummy/config/environments/development.rb +32 -0
- data/spec/dummy/config/environments/production.rb +80 -0
- data/spec/dummy/config/environments/test.rb +39 -0
- data/spec/dummy/config/initializers/active_payment.rb +7 -0
- data/spec/dummy/config/initializers/backtrace_silencers.rb +7 -0
- data/spec/dummy/config/initializers/filter_parameter_logging.rb +4 -0
- data/spec/dummy/config/initializers/inflections.rb +16 -0
- data/spec/dummy/config/initializers/mime_types.rb +5 -0
- data/spec/dummy/config/initializers/secret_token.rb +12 -0
- data/spec/dummy/config/initializers/session_store.rb +3 -0
- data/spec/dummy/config/initializers/wrap_parameters.rb +14 -0
- data/spec/dummy/config/locales/en.yml +23 -0
- data/spec/dummy/config/routes.rb +3 -0
- data/spec/dummy/config.ru +4 -0
- data/spec/dummy/db/development.sqlite3 +0 -0
- data/spec/dummy/db/migrate/20150813161144_create_payments_transactions.rb +22 -0
- data/spec/dummy/db/schema.rb +35 -0
- data/spec/dummy/db/test.sqlite3 +0 -0
- data/spec/dummy/log/development.log +33 -0
- data/spec/dummy/log/test.log +73016 -0
- data/spec/dummy/public/404.html +58 -0
- data/spec/dummy/public/422.html +58 -0
- data/spec/dummy/public/500.html +57 -0
- data/spec/dummy/public/favicon.ico +0 -0
- data/spec/factories/transaction.rb +15 -0
- data/spec/helper.rb +86 -0
- metadata +298 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: 13454003f9a1b0df32efb32c30378f63983dabcf
|
4
|
+
data.tar.gz: d1d0536e55d51f5ae1d0397d9ddc0bc51b63db4b
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: a7aca4a74ca3bc90e5d07dde125a1c5d51f750abbdc243881601fb3c11224ee77ced3d3fb6c00ddbb4c5b02a13cb5df77c4d001af230bd4d2d973566cf43cbaa
|
7
|
+
data.tar.gz: c68190e976e1b7c4e28bd7924789cdc6e8b7a0f70fce7fbea2656cbda515caa8b60d1aec89661045790343367795fafb604f14d361ff27cd3f06276d8a4e1c3d
|
@@ -0,0 +1,26 @@
|
|
1
|
+
module ActivePayment
|
2
|
+
class PaypalAdaptivePaymentCallbackController < ActionController::Base
|
3
|
+
protect_from_forgery with: :null_session
|
4
|
+
|
5
|
+
def success
|
6
|
+
flash[:success] = 'Thank you!'
|
7
|
+
redirect_to '/'
|
8
|
+
end
|
9
|
+
|
10
|
+
def cancel
|
11
|
+
ActivePayment::Gateway.cancel_purchase_from_request(
|
12
|
+
gateway: 'paypal_adaptive_payment',
|
13
|
+
request: request)
|
14
|
+
flash[:error] = 'Your transaction has been canceled'
|
15
|
+
redirect_to '/'
|
16
|
+
end
|
17
|
+
|
18
|
+
def ipn
|
19
|
+
ActivePayment::Gateway.verify_purchase_from_request(
|
20
|
+
gateway: 'paypal_adaptive_payment',
|
21
|
+
request: request,
|
22
|
+
data: request.raw_post)
|
23
|
+
head :ok
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
@@ -0,0 +1,33 @@
|
|
1
|
+
module ActivePayment
|
2
|
+
class PaypalExpressCheckoutCallbackController < ActionController::Base
|
3
|
+
protect_from_forgery with: :null_session
|
4
|
+
|
5
|
+
def success
|
6
|
+
ActivePayment::Gateway.verify_purchase_from_request(
|
7
|
+
gateway: 'paypal_express_checkout',
|
8
|
+
request: request,
|
9
|
+
data: purchase_params)
|
10
|
+
flash[:success] = 'Thank you!'
|
11
|
+
|
12
|
+
redirect_to '/'
|
13
|
+
end
|
14
|
+
|
15
|
+
def cancel
|
16
|
+
ActivePayment::Gateway.cancel_purchase_from_request(
|
17
|
+
gateway: 'paypal_express_checkout',
|
18
|
+
request: request)
|
19
|
+
flash[:error] = 'Your transaction has been cancelled'
|
20
|
+
|
21
|
+
redirect_to '/'
|
22
|
+
end
|
23
|
+
|
24
|
+
private
|
25
|
+
|
26
|
+
def purchase_params
|
27
|
+
{
|
28
|
+
ip: request.remote_ip,
|
29
|
+
token: params[:token]
|
30
|
+
}
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
@@ -0,0 +1,18 @@
|
|
1
|
+
module ActivePayment
|
2
|
+
class Transaction < ActiveRecord::Base
|
3
|
+
enum state: [:pending, :completed, :canceled, :error]
|
4
|
+
serialize :metadata
|
5
|
+
|
6
|
+
validates :amount, :currency, :external_id, :ip_address,
|
7
|
+
:payee_id, :payer_id, :gateway, :state, presence: true
|
8
|
+
|
9
|
+
# in cents
|
10
|
+
validates :amount, numericality: { only_integer: true, greater_than: 0 }
|
11
|
+
|
12
|
+
after_initialize do
|
13
|
+
if self.new_record?
|
14
|
+
self.state ||= Transaction.states[:pending]
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
data/config/routes.rb
ADDED
@@ -0,0 +1,9 @@
|
|
1
|
+
ActivePayment::Engine.routes.draw do
|
2
|
+
#payments callbacks
|
3
|
+
get '/paypal/success', to: 'paypal_express_checkout_callback#success'
|
4
|
+
get '/paypal/cancel', to: 'paypal_express_checkout_callback#cancel'
|
5
|
+
|
6
|
+
get '/paypal_adaptive/success', to: 'paypal_adaptive_payment_callback#success'
|
7
|
+
get '/paypal_adaptive/cancel', to: 'paypal_adaptive_payment_callback#cancel'
|
8
|
+
post '/paypal_adaptive/ipn', to: 'paypal_adaptive_payment_callback#ipn'
|
9
|
+
end
|
@@ -0,0 +1,22 @@
|
|
1
|
+
class CreatePaymentsTransactions < ActiveRecord::Migration
|
2
|
+
def change
|
3
|
+
create_table :active_payment_transactions do |t|
|
4
|
+
t.integer :amount
|
5
|
+
t.string :currency
|
6
|
+
t.string :reference_number
|
7
|
+
t.string :external_id
|
8
|
+
t.integer :payee_id
|
9
|
+
t.integer :payer_id
|
10
|
+
t.integer :payable_id
|
11
|
+
t.string :payable_type
|
12
|
+
t.string :gateway
|
13
|
+
t.integer :source
|
14
|
+
t.integer :state
|
15
|
+
t.text :metadata
|
16
|
+
t.string :ip_address
|
17
|
+
t.datetime :paid_at, default: nil
|
18
|
+
|
19
|
+
t.timestamps
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
@@ -0,0 +1,14 @@
|
|
1
|
+
module ActivePayment
|
2
|
+
class Configuration
|
3
|
+
attr_accessor :paypal_login, :paypal_password, :paypal_signature, :paypal_appid
|
4
|
+
attr_accessor :min_amount, :ip_security
|
5
|
+
attr_accessor :default_url_host
|
6
|
+
attr_accessor :test
|
7
|
+
|
8
|
+
def initialize
|
9
|
+
@min_amount = 0
|
10
|
+
@ip_security = false
|
11
|
+
@test = false
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
@@ -0,0 +1,23 @@
|
|
1
|
+
module ActivePayment
|
2
|
+
class Engine < ::Rails::Engine
|
3
|
+
isolate_namespace ActivePayment
|
4
|
+
|
5
|
+
# append migrations
|
6
|
+
initializer :append_migrations do |app|
|
7
|
+
unless app.root.to_s.match root.to_s
|
8
|
+
config.paths["db/migrate"].expanded.each do |expanded_path|
|
9
|
+
app.config.paths["db/migrate"] << expanded_path
|
10
|
+
end
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
14
|
+
# Force routes to be loaded if we are doing any eager load.
|
15
|
+
config.before_eager_load { |app| app.reload_routes! }
|
16
|
+
|
17
|
+
config.generators do |g|
|
18
|
+
g.test_framework :rspec
|
19
|
+
g.assets false
|
20
|
+
g.helper false
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
@@ -0,0 +1,125 @@
|
|
1
|
+
module ActivePayment
|
2
|
+
class Gateway
|
3
|
+
attr_accessor :gateway, :purchase_token, :transactions
|
4
|
+
|
5
|
+
def initialize(name)
|
6
|
+
@transactions = []
|
7
|
+
|
8
|
+
name_str = name.to_s.strip.downcase
|
9
|
+
raise(ArgumentError, 'A gateway provider must be specified') if name_str.blank?
|
10
|
+
|
11
|
+
ActiveMerchant::Billing::Base.mode = :test if ActivePayment.configuration.test
|
12
|
+
|
13
|
+
begin
|
14
|
+
@gateway = ActivePayment::Gateways.const_get("#{name_str}".camelize).new
|
15
|
+
rescue SyntaxError, NameError
|
16
|
+
raise ArgumentError, "The specified gateway is not valid (#{name_str})"
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
def setup_purchase(sales, ip_address)
|
21
|
+
amount = sales.amount_in_cents
|
22
|
+
raise ActivePayment::InvalidAmountError unless amount >= ActivePayment.configuration.min_amount
|
23
|
+
|
24
|
+
url = @gateway.setup_purchase(sales)
|
25
|
+
@purchase_token = @gateway.purchase_token
|
26
|
+
create_transactions(ip_address)
|
27
|
+
|
28
|
+
url
|
29
|
+
end
|
30
|
+
|
31
|
+
def verify_purchase(external_id, remote_ip, raw_data)
|
32
|
+
@transactions = ActivePayment::Transaction.where(external_id: external_id)
|
33
|
+
fail ActivePayment::NoTransactionError unless @transactions.size > 0
|
34
|
+
verify_ip_address(@transactions, remote_ip)
|
35
|
+
|
36
|
+
if raw_data.is_a?(Hash) && raw_data[:amount].blank?
|
37
|
+
raw_data[:amount] = @transactions.map(&:amount).inject(0, &:+)
|
38
|
+
end
|
39
|
+
|
40
|
+
if @gateway.verify_purchase(raw_data)
|
41
|
+
transactions_success(@transactions)
|
42
|
+
else
|
43
|
+
transactions_error(@transactions)
|
44
|
+
fail ActivePayment::InvalidGatewayResponseError
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
def cancel_purchase(external_id, remote_ip)
|
49
|
+
@transactions = ActivePayment::Transaction.where(external_id: external_id)
|
50
|
+
fail ActivePayment::NoTransactionError unless @transactions.size > 0
|
51
|
+
verify_ip_address(@transactions, remote_ip)
|
52
|
+
|
53
|
+
transactions_cancel(@transactions)
|
54
|
+
end
|
55
|
+
|
56
|
+
def external_id_from_request(request)
|
57
|
+
@gateway.external_id_from_request(request)
|
58
|
+
end
|
59
|
+
|
60
|
+
def livemode?
|
61
|
+
@gateway.livemode?
|
62
|
+
end
|
63
|
+
|
64
|
+
def self.verify_purchase_from_request(gateway:, request:, data:)
|
65
|
+
payment_gateway = ActivePayment::Gateway.new(gateway)
|
66
|
+
external_id = payment_gateway.external_id_from_request(request)
|
67
|
+
payment_gateway.verify_purchase(external_id, request.remote_ip, data)
|
68
|
+
end
|
69
|
+
|
70
|
+
def self.cancel_purchase_from_request(gateway:, request:)
|
71
|
+
payment_gateway = ActivePayment::Gateway.new(gateway)
|
72
|
+
external_id = payment_gateway.external_id_from_request(request)
|
73
|
+
payment_gateway.cancel_purchase(external_id, request.remote_ip)
|
74
|
+
end
|
75
|
+
|
76
|
+
private
|
77
|
+
|
78
|
+
def create_transactions(ip_address)
|
79
|
+
fail 'You must called setup_purchase before creating a transaction' unless @gateway.sales
|
80
|
+
|
81
|
+
@gateway.sales.each do |sale|
|
82
|
+
@transactions << ActivePayment::Transaction.create({
|
83
|
+
currency: 'USD',
|
84
|
+
gateway: @gateway.class.to_s,
|
85
|
+
amount: sale.amount_in_cents,
|
86
|
+
ip_address: ip_address,
|
87
|
+
payee_id: sale.payee.id,
|
88
|
+
payer_id: sale.payer.id,
|
89
|
+
payable_id: sale.payable ? sale.payable.id : nil,
|
90
|
+
payable_type: sale.payable ? sale.payable.class.to_s : nil,
|
91
|
+
reference_number: sale.payable.reference,
|
92
|
+
external_id: @purchase_token,
|
93
|
+
metadata: { description: sale.payable.description }
|
94
|
+
})
|
95
|
+
end
|
96
|
+
end
|
97
|
+
|
98
|
+
def verify_ip_address(transactions, remote_ip)
|
99
|
+
if ActivePayment.configuration.ip_security
|
100
|
+
transactions.each do |transaction|
|
101
|
+
fail ActivePayment::SecurityError unless transaction.ip_address == remote_ip
|
102
|
+
end
|
103
|
+
end
|
104
|
+
end
|
105
|
+
|
106
|
+
def transactions_success(transactions)
|
107
|
+
transactions.each do |transaction|
|
108
|
+
transaction.paid_at = DateTime.now
|
109
|
+
transaction.completed!
|
110
|
+
end
|
111
|
+
end
|
112
|
+
|
113
|
+
def transactions_error(transactions)
|
114
|
+
transactions.each do |transaction|
|
115
|
+
transaction.error!
|
116
|
+
end
|
117
|
+
end
|
118
|
+
|
119
|
+
def transactions_cancel(transactions)
|
120
|
+
transactions.each do |transaction|
|
121
|
+
transaction.canceled!
|
122
|
+
end
|
123
|
+
end
|
124
|
+
end
|
125
|
+
end
|
@@ -0,0 +1,85 @@
|
|
1
|
+
require 'active_merchant'
|
2
|
+
|
3
|
+
module ActivePayment
|
4
|
+
module Gateways
|
5
|
+
class PaypalAdaptivePayment
|
6
|
+
include ActionView::Helpers
|
7
|
+
include ActionDispatch::Routing
|
8
|
+
include ActivePayment::Engine.routes.url_helpers
|
9
|
+
|
10
|
+
attr_accessor :purchase_token, :sales
|
11
|
+
|
12
|
+
def initialize
|
13
|
+
@gateway = ActiveMerchant::Billing::PaypalAdaptivePayment.new(paypal_options)
|
14
|
+
end
|
15
|
+
|
16
|
+
def setup_purchase(sales)
|
17
|
+
@sales = sales
|
18
|
+
|
19
|
+
response = @gateway.setup_purchase(purchase_data(sales))
|
20
|
+
raise ActivePayment::InvalidGatewayResponseError unless response.success?
|
21
|
+
|
22
|
+
@purchase_token = response['payKey']
|
23
|
+
@gateway.set_payment_options(payment_options_data(@purchase_token, @sales))
|
24
|
+
@gateway.redirect_url_for(response['payKey'])
|
25
|
+
end
|
26
|
+
|
27
|
+
# return boolean
|
28
|
+
def verify_purchase(params)
|
29
|
+
notify = ActiveMerchant::Billing::Integrations::PaypalAdaptivePayment.notification(params)
|
30
|
+
|
31
|
+
notify.acknowledge && notify.complete?
|
32
|
+
end
|
33
|
+
|
34
|
+
def livemode?
|
35
|
+
ActiveMerchant::Billing::Base.mode != :test
|
36
|
+
end
|
37
|
+
|
38
|
+
def external_id_from_request(request)
|
39
|
+
notify = ActiveMerchant::Billing::Integrations::PaypalAdaptivePayment.notification(request.raw_post)
|
40
|
+
|
41
|
+
notify.params['pay_key']
|
42
|
+
end
|
43
|
+
|
44
|
+
private
|
45
|
+
|
46
|
+
def paypal_options
|
47
|
+
{
|
48
|
+
action_type: "CREATE",
|
49
|
+
login: ActivePayment.configuration.paypal_login,
|
50
|
+
password: ActivePayment.configuration.paypal_password,
|
51
|
+
signature: ActivePayment.configuration.paypal_signature,
|
52
|
+
appid: ActivePayment.configuration.paypal_appid
|
53
|
+
}
|
54
|
+
end
|
55
|
+
|
56
|
+
def purchase_data(sales)
|
57
|
+
{
|
58
|
+
return_url: return_url,
|
59
|
+
cancel_url: cancel_return_url,
|
60
|
+
ipn_notification_url: ipn_notification_url,
|
61
|
+
receiver_list: sales.paypal_recipients,
|
62
|
+
}
|
63
|
+
end
|
64
|
+
|
65
|
+
def payment_options_data(key, sales)
|
66
|
+
{
|
67
|
+
pa_key: key,
|
68
|
+
receiver_options: sales.paypal_hash,
|
69
|
+
}
|
70
|
+
end
|
71
|
+
|
72
|
+
def return_url
|
73
|
+
url_for(controller: 'active_payment/paypal_adaptive_payment_callback', action: :success, only_path: false, host: ActivePayment.configuration.default_url_host)
|
74
|
+
end
|
75
|
+
|
76
|
+
def cancel_return_url
|
77
|
+
url_for(controller: 'active_payment/paypal_adaptive_payment_callback', action: :cancel, only_path: false, host: ActivePayment.configuration.default_url_host)
|
78
|
+
end
|
79
|
+
|
80
|
+
def ipn_notification_url
|
81
|
+
url_for(controller: 'active_payment/paypal_adaptive_payment_callback', action: :ipn, only_path: false, host: ActivePayment.configuration.default_url_host)
|
82
|
+
end
|
83
|
+
end
|
84
|
+
end
|
85
|
+
end
|
@@ -0,0 +1,86 @@
|
|
1
|
+
require 'active_merchant'
|
2
|
+
|
3
|
+
module ActivePayment
|
4
|
+
module Gateways
|
5
|
+
class PaypalExpressCheckout
|
6
|
+
include ActionView::Helpers
|
7
|
+
include ActionDispatch::Routing
|
8
|
+
include ActivePayment::Engine.routes.url_helpers
|
9
|
+
|
10
|
+
attr_accessor :purchase_token, :sales
|
11
|
+
|
12
|
+
def initialize
|
13
|
+
@gateway = ActiveMerchant::Billing::PaypalExpressGateway.new(paypal_options)
|
14
|
+
end
|
15
|
+
|
16
|
+
def setup_purchase(sales)
|
17
|
+
@sales = sales
|
18
|
+
|
19
|
+
payables = @sales.map(&:payable)
|
20
|
+
amount = @sales.amount_in_cents.to_i
|
21
|
+
|
22
|
+
response = @gateway.setup_purchase(amount, paypal_data(payables))
|
23
|
+
raise ActivePayment::InvalidGatewayResponseError unless response.success?
|
24
|
+
|
25
|
+
@purchase_token = response.token
|
26
|
+
@gateway.redirect_url_for(response.token)
|
27
|
+
end
|
28
|
+
|
29
|
+
# return boolean
|
30
|
+
def verify_purchase(params)
|
31
|
+
token = params[:token]
|
32
|
+
|
33
|
+
begin
|
34
|
+
response = @gateway.details_for(token)
|
35
|
+
fail ActivePayment::InvalidGatewayResponseError unless response.success?
|
36
|
+
|
37
|
+
amount = params[:amount]
|
38
|
+
purchase_response = @gateway.purchase(amount, params.merge(payer_id: response.payer_id))
|
39
|
+
fail ActivePayment::InvalidGatewayResponseError unless purchase_response.success?
|
40
|
+
rescue ActivePayment::InvalidGatewayResponseError
|
41
|
+
return false
|
42
|
+
end
|
43
|
+
|
44
|
+
true
|
45
|
+
end
|
46
|
+
|
47
|
+
def external_id_from_request(request)
|
48
|
+
request.params[:token]
|
49
|
+
end
|
50
|
+
|
51
|
+
def livemode?
|
52
|
+
ActiveMerchant::Billing::Base.mode != :test
|
53
|
+
end
|
54
|
+
|
55
|
+
private
|
56
|
+
|
57
|
+
def paypal_options
|
58
|
+
{
|
59
|
+
login: ActivePayment.configuration.paypal_login,
|
60
|
+
password: ActivePayment.configuration.paypal_password,
|
61
|
+
signature: ActivePayment.configuration.paypal_signature,
|
62
|
+
}
|
63
|
+
end
|
64
|
+
|
65
|
+
def paypal_data(payables)
|
66
|
+
{
|
67
|
+
items: payables.map(&:to_paypal_hash),
|
68
|
+
return_url: return_url,
|
69
|
+
cancel_return_url: cancel_return_url,
|
70
|
+
currency_code: 'USD',
|
71
|
+
allow_note: false,
|
72
|
+
allow_guest_checkout: true
|
73
|
+
}
|
74
|
+
end
|
75
|
+
|
76
|
+
def return_url
|
77
|
+
url_for(controller: 'active_payment/paypal_express_checkout_callback', action: :success, only_path: false, host: ActivePayment.configuration.default_url_host)
|
78
|
+
end
|
79
|
+
|
80
|
+
def cancel_return_url
|
81
|
+
url_for(controller: 'active_payment/paypal_express_checkout_callback', action: :cancel, only_path: false, host: ActivePayment.configuration.default_url_host)
|
82
|
+
end
|
83
|
+
end
|
84
|
+
|
85
|
+
end
|
86
|
+
end
|
@@ -0,0 +1,32 @@
|
|
1
|
+
module ActivePayment
|
2
|
+
module Models
|
3
|
+
module Payable
|
4
|
+
extend ActiveSupport::Concern
|
5
|
+
|
6
|
+
def to_paypal_hash
|
7
|
+
{
|
8
|
+
name: description,
|
9
|
+
amount: amount.to_i,
|
10
|
+
number: 1,
|
11
|
+
quantity: 1,
|
12
|
+
}
|
13
|
+
end
|
14
|
+
|
15
|
+
def shipping
|
16
|
+
shipping
|
17
|
+
end
|
18
|
+
|
19
|
+
def tax
|
20
|
+
tax
|
21
|
+
end
|
22
|
+
|
23
|
+
def reference
|
24
|
+
id
|
25
|
+
end
|
26
|
+
|
27
|
+
def description
|
28
|
+
description
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
@@ -0,0 +1,27 @@
|
|
1
|
+
module ActivePayment
|
2
|
+
module Models
|
3
|
+
module Payee
|
4
|
+
extend ActiveSupport::Concern
|
5
|
+
|
6
|
+
included do
|
7
|
+
if superclass == ActiveRecord::Base
|
8
|
+
has_many :received_transactions, foreign_key: 'payee_id', class_name: ActivePayment::Transaction
|
9
|
+
end
|
10
|
+
end
|
11
|
+
|
12
|
+
def to_paypal_hash
|
13
|
+
{
|
14
|
+
email: paypal_identifier,
|
15
|
+
primary: false
|
16
|
+
}
|
17
|
+
end
|
18
|
+
|
19
|
+
def paypal_identifier
|
20
|
+
paypal
|
21
|
+
end
|
22
|
+
|
23
|
+
module ClassMethods
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
@@ -0,0 +1,13 @@
|
|
1
|
+
module ActivePayment
|
2
|
+
module Models
|
3
|
+
module Payer
|
4
|
+
extend ActiveSupport::Concern
|
5
|
+
|
6
|
+
included do
|
7
|
+
if superclass == ActiveRecord::Base
|
8
|
+
has_many :sent_transactions, foreign_key: 'payer_id', class_name: ActivePayment::Transaction
|
9
|
+
end
|
10
|
+
end
|
11
|
+
end
|
12
|
+
end
|
13
|
+
end
|
@@ -0,0 +1,60 @@
|
|
1
|
+
module ActivePayment
|
2
|
+
module Models
|
3
|
+
class Sale
|
4
|
+
attr_accessor :payable, :payer, :payee
|
5
|
+
|
6
|
+
def initialize(payable:, payer:, payee:)
|
7
|
+
@payable = payable
|
8
|
+
@payer = payer
|
9
|
+
@payee = payee
|
10
|
+
end
|
11
|
+
|
12
|
+
def amount
|
13
|
+
payable.amount.to_f / 100
|
14
|
+
end
|
15
|
+
|
16
|
+
def amount_in_cents
|
17
|
+
payable.amount.to_i
|
18
|
+
end
|
19
|
+
|
20
|
+
def description
|
21
|
+
payable.description
|
22
|
+
end
|
23
|
+
|
24
|
+
def shipping
|
25
|
+
payable.shipping || 0
|
26
|
+
end
|
27
|
+
|
28
|
+
def tax
|
29
|
+
payable.tax || 0
|
30
|
+
end
|
31
|
+
|
32
|
+
def paypal_recipient
|
33
|
+
{
|
34
|
+
email: payee.paypal_identifier,
|
35
|
+
amount: amount,
|
36
|
+
primary: false
|
37
|
+
}
|
38
|
+
end
|
39
|
+
|
40
|
+
def paypal_hash
|
41
|
+
{
|
42
|
+
description: payable.description,
|
43
|
+
invoice_data: {
|
44
|
+
item: [{
|
45
|
+
name: payable.description,
|
46
|
+
item_count: 1,
|
47
|
+
item_price: amount,
|
48
|
+
price: amount
|
49
|
+
}],
|
50
|
+
total_shipping: payable.shipping,
|
51
|
+
total_tax: payable.tax
|
52
|
+
},
|
53
|
+
receiver: {
|
54
|
+
email: @payee.paypal_identifier
|
55
|
+
}
|
56
|
+
}
|
57
|
+
end
|
58
|
+
end
|
59
|
+
end
|
60
|
+
end
|
@@ -0,0 +1,78 @@
|
|
1
|
+
module ActivePayment
|
2
|
+
module Models
|
3
|
+
class Sales
|
4
|
+
include Enumerable
|
5
|
+
|
6
|
+
attr_accessor :sales
|
7
|
+
|
8
|
+
def initialize(sales = [])
|
9
|
+
@sales = sales
|
10
|
+
end
|
11
|
+
|
12
|
+
def amount
|
13
|
+
@sales.map(&:amount).inject(0, &:+)
|
14
|
+
end
|
15
|
+
|
16
|
+
def amount_in_cents
|
17
|
+
@sales.map(&:amount_in_cents).inject(0, &:+)
|
18
|
+
end
|
19
|
+
|
20
|
+
def total_shipping
|
21
|
+
total_shipping = 0
|
22
|
+
|
23
|
+
@sales.each do |sale|
|
24
|
+
total_shipping += sale.shipping if sale.shipping
|
25
|
+
end
|
26
|
+
|
27
|
+
total_shipping
|
28
|
+
end
|
29
|
+
|
30
|
+
def total_tax
|
31
|
+
total_tax = 0
|
32
|
+
|
33
|
+
@sales.each do |sale|
|
34
|
+
total_tax += sale.tax if sale.tax
|
35
|
+
end
|
36
|
+
|
37
|
+
total_tax
|
38
|
+
end
|
39
|
+
|
40
|
+
def paypal_hash
|
41
|
+
paypal_hash = []
|
42
|
+
@sales.each do |sale|
|
43
|
+
paypal_hash << sale.paypal_hash
|
44
|
+
end
|
45
|
+
|
46
|
+
paypal_hash
|
47
|
+
end
|
48
|
+
|
49
|
+
def each
|
50
|
+
@sales.each do |sale|
|
51
|
+
yield sale
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
55
|
+
def paypal_recipients
|
56
|
+
recipients = []
|
57
|
+
@sales.each do |sale|
|
58
|
+
recipients << sale.paypal_recipient
|
59
|
+
end
|
60
|
+
|
61
|
+
recipients
|
62
|
+
end
|
63
|
+
|
64
|
+
|
65
|
+
private
|
66
|
+
|
67
|
+
def items_data
|
68
|
+
data = []
|
69
|
+
|
70
|
+
@sales.each do |sale|
|
71
|
+
data << { name: sale.description, item_count: 1, item_price: sale.amount, price: sale.amount }
|
72
|
+
end
|
73
|
+
|
74
|
+
data
|
75
|
+
end
|
76
|
+
end
|
77
|
+
end
|
78
|
+
end
|