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.
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