active_payment 0.0.5

Sign up to get free protection for your applications and to get access to all the features.
Files changed (68) hide show
  1. checksums.yaml +7 -0
  2. data/app/controllers/active_payment/paypal_adaptive_payment_callback_controller.rb +26 -0
  3. data/app/controllers/active_payment/paypal_express_checkout_callback_controller.rb +33 -0
  4. data/app/models/active_payment/transaction.rb +18 -0
  5. data/config/routes.rb +9 -0
  6. data/db/migrate/20150813161144_create_payments_transactions.rb +22 -0
  7. data/lib/active_payment/configuration.rb +14 -0
  8. data/lib/active_payment/engine.rb +23 -0
  9. data/lib/active_payment/gateway.rb +125 -0
  10. data/lib/active_payment/gateways/paypal_adaptive_payment.rb +85 -0
  11. data/lib/active_payment/gateways/paypal_express_checkout.rb +86 -0
  12. data/lib/active_payment/models/concerns/payable.rb +32 -0
  13. data/lib/active_payment/models/concerns/payee.rb +27 -0
  14. data/lib/active_payment/models/concerns/payer.rb +13 -0
  15. data/lib/active_payment/models/sale.rb +60 -0
  16. data/lib/active_payment/models/sales.rb +78 -0
  17. data/lib/active_payment/version.rb +3 -0
  18. data/lib/active_payment.rb +36 -0
  19. data/spec/active_payment/configuration_spec.rb +59 -0
  20. data/spec/active_payment/controllers/paypal_adaptive_payment_callback_controller_spec.rb +77 -0
  21. data/spec/active_payment/controllers/paypal_express_checkout_callback_controller_spec.rb +102 -0
  22. data/spec/active_payment/gateway_spec.rb +140 -0
  23. data/spec/active_payment/gateways/paypal_adaptive_payment_spec.rb +105 -0
  24. data/spec/active_payment/gateways/paypal_express_checkout_spec.rb +144 -0
  25. data/spec/active_payment/models/sale_spec.rb +109 -0
  26. data/spec/active_payment/models/sales_spec.rb +93 -0
  27. data/spec/active_payment/models/transaction_spec.rb +31 -0
  28. data/spec/dummy/README.rdoc +28 -0
  29. data/spec/dummy/Rakefile +6 -0
  30. data/spec/dummy/app/assets/javascripts/application.js +13 -0
  31. data/spec/dummy/app/assets/stylesheets/application.css +13 -0
  32. data/spec/dummy/app/controllers/application_controller.rb +5 -0
  33. data/spec/dummy/app/helpers/application_helper.rb +2 -0
  34. data/spec/dummy/app/views/layouts/application.html.erb +14 -0
  35. data/spec/dummy/bin/bundle +3 -0
  36. data/spec/dummy/bin/rails +4 -0
  37. data/spec/dummy/bin/rake +4 -0
  38. data/spec/dummy/config/application.rb +29 -0
  39. data/spec/dummy/config/boot.rb +5 -0
  40. data/spec/dummy/config/database.yml +25 -0
  41. data/spec/dummy/config/environment.rb +5 -0
  42. data/spec/dummy/config/environments/development.rb +32 -0
  43. data/spec/dummy/config/environments/production.rb +80 -0
  44. data/spec/dummy/config/environments/test.rb +39 -0
  45. data/spec/dummy/config/initializers/active_payment.rb +7 -0
  46. data/spec/dummy/config/initializers/backtrace_silencers.rb +7 -0
  47. data/spec/dummy/config/initializers/filter_parameter_logging.rb +4 -0
  48. data/spec/dummy/config/initializers/inflections.rb +16 -0
  49. data/spec/dummy/config/initializers/mime_types.rb +5 -0
  50. data/spec/dummy/config/initializers/secret_token.rb +12 -0
  51. data/spec/dummy/config/initializers/session_store.rb +3 -0
  52. data/spec/dummy/config/initializers/wrap_parameters.rb +14 -0
  53. data/spec/dummy/config/locales/en.yml +23 -0
  54. data/spec/dummy/config/routes.rb +3 -0
  55. data/spec/dummy/config.ru +4 -0
  56. data/spec/dummy/db/development.sqlite3 +0 -0
  57. data/spec/dummy/db/migrate/20150813161144_create_payments_transactions.rb +22 -0
  58. data/spec/dummy/db/schema.rb +35 -0
  59. data/spec/dummy/db/test.sqlite3 +0 -0
  60. data/spec/dummy/log/development.log +33 -0
  61. data/spec/dummy/log/test.log +73016 -0
  62. data/spec/dummy/public/404.html +58 -0
  63. data/spec/dummy/public/422.html +58 -0
  64. data/spec/dummy/public/500.html +57 -0
  65. data/spec/dummy/public/favicon.ico +0 -0
  66. data/spec/factories/transaction.rb +15 -0
  67. data/spec/helper.rb +86 -0
  68. 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
@@ -0,0 +1,3 @@
1
+ module ActivePayment
2
+ VERSION = '0.0.5'
3
+ end