moneytree-rails 0.1.0 → 0.1.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 (57) hide show
  1. checksums.yaml +4 -4
  2. data/MIT-LICENSE +20 -0
  3. data/README.md +63 -30
  4. data/Rakefile +30 -4
  5. data/app/assets/config/moneytree_manifest.js +1 -0
  6. data/app/assets/stylesheets/moneytree/application.css +15 -0
  7. data/app/controllers/moneytree/application_controller.rb +9 -0
  8. data/app/controllers/moneytree/oauth/square_controller.rb +14 -0
  9. data/app/controllers/moneytree/oauth/stripe_controller.rb +44 -0
  10. data/app/controllers/moneytree/webhooks/square_controller.rb +9 -0
  11. data/app/controllers/moneytree/webhooks/stripe_controller.rb +67 -0
  12. data/app/jobs/moneytree/application_job.rb +4 -0
  13. data/app/mailers/moneytree/application_mailer.rb +6 -0
  14. data/app/models/moneytree/application_record.rb +5 -0
  15. data/app/models/moneytree/payment.rb +23 -0
  16. data/app/models/moneytree/payment_gateway.rb +47 -0
  17. data/app/models/moneytree/refund.rb +46 -0
  18. data/app/models/moneytree/transaction.rb +30 -0
  19. data/app/views/layouts/moneytree/application.html.erb +15 -0
  20. data/config/routes.rb +8 -0
  21. data/db/migrate/20200914151648_create_moneytree_payment_gateways.rb +11 -0
  22. data/db/migrate/20201008161617_create_moneytree_transactions.rb +18 -0
  23. data/lib/moneytree-rails.rb +1 -0
  24. data/lib/moneytree.rb +16 -16
  25. data/lib/moneytree/account.rb +4 -34
  26. data/lib/moneytree/engine.rb +5 -0
  27. data/lib/moneytree/order.rb +15 -0
  28. data/lib/moneytree/payment_provider/base.rb +5 -2
  29. data/lib/moneytree/payment_provider/stripe.rb +80 -0
  30. data/lib/moneytree/transaction_response.rb +15 -0
  31. data/lib/moneytree/version.rb +1 -1
  32. data/lib/tasks/moneytree_tasks.rake +4 -0
  33. metadata +45 -33
  34. data/.github/workflows/ruby.yml +0 -33
  35. data/.gitignore +0 -12
  36. data/.rspec +0 -3
  37. data/.travis.yml +0 -6
  38. data/CHANGELOG.md +0 -7
  39. data/CODE_OF_CONDUCT.md +0 -74
  40. data/Gemfile +0 -15
  41. data/Gemfile.lock +0 -248
  42. data/Guardfile +0 -70
  43. data/LICENSE.txt +0 -21
  44. data/app/controllers/moneytree/oauth_controller.rb +0 -18
  45. data/bin/console +0 -14
  46. data/bin/setup +0 -8
  47. data/config.ru +0 -9
  48. data/lib/generators/moneytree/activerecord_generator.rb +0 -41
  49. data/lib/generators/moneytree/base_generator.rb +0 -13
  50. data/lib/generators/moneytree/install_generator.rb +0 -43
  51. data/lib/generators/moneytree/templates/active_record_event_model.rb.tt +0 -10
  52. data/lib/generators/moneytree/templates/active_record_migration.rb.tt +0 -62
  53. data/lib/generators/moneytree/templates/active_record_visit_model.rb.tt +0 -6
  54. data/lib/generators/moneytree/templates/base_store_initializer.rb.tt +0 -20
  55. data/lib/generators/moneytree/templates/moneytree_initializer.rb.tt +0 -15
  56. data/lib/moneytree/transaction.rb +0 -9
  57. data/moneytree.gemspec +0 -29
@@ -0,0 +1,46 @@
1
+ module Moneytree
2
+ class Refund < Transaction
3
+ belongs_to :payment, class_name: 'Moneytree::Payment'
4
+
5
+ before_validation :set_order, :set_payment_gateway
6
+
7
+ validates_presence_of :payment
8
+
9
+ validates_numericality_of :amount, less_than: 0
10
+ validates_numericality_of :app_fee_amount, less_than_or_equal_to: 0
11
+
12
+ validate :order_matches_payment, :gateway_matches_payment
13
+
14
+ private
15
+
16
+ def execute_transaction(metadata: {})
17
+ process_response(
18
+ payment_gateway.refund(
19
+ amount,
20
+ payment.details,
21
+ metadata: metadata.merge(moneytree_transaction_id: id)
22
+ )
23
+ )
24
+ end
25
+
26
+ # validates_presence_of :payment
27
+ def set_order
28
+ self.order ||= payment&.order
29
+ end
30
+
31
+ # validates_presence_of :payment
32
+ def set_payment_gateway
33
+ self.payment_gateway ||= payment&.payment_gateway
34
+ end
35
+
36
+ # validates
37
+ def order_matches_payment
38
+ errors.add(:order_id, :mismatch) if order_id != payment&.order_id
39
+ end
40
+
41
+ # validates
42
+ def gateway_matches_payment
43
+ errors.add(:payment_gateway_id, :mismatch) if payment_gateway_id != payment&.payment_gateway_id
44
+ end
45
+ end
46
+ end
@@ -0,0 +1,30 @@
1
+ module Moneytree
2
+ class Transaction < ApplicationRecord
3
+ belongs_to :payment_gateway
4
+ belongs_to :order, polymorphic: true
5
+
6
+ validates_presence_of :psp_error, if: :failed?
7
+
8
+ enum status: %i[initialized pending completed failed]
9
+
10
+ serialize :details
11
+
12
+ after_create_commit :execute_transaction
13
+
14
+ def process_response(response)
15
+ if response.success?
16
+ update!(
17
+ status: :completed,
18
+ psp_error: response.message,
19
+ details: (details || {}).merge(response.body)
20
+ )
21
+ else
22
+ # FIXME: pending state
23
+ update!(
24
+ status: :failed,
25
+ psp_error: response.message
26
+ )
27
+ end
28
+ end
29
+ end
30
+ end
@@ -0,0 +1,15 @@
1
+ <!DOCTYPE html>
2
+ <html>
3
+ <head>
4
+ <title>Moneytree</title>
5
+ <%= csrf_meta_tags %>
6
+ <%= csp_meta_tag %>
7
+
8
+ <%= stylesheet_link_tag "moneytree/application", media: "all" %>
9
+ </head>
10
+ <body>
11
+
12
+ <%= yield %>
13
+
14
+ </body>
15
+ </html>
@@ -0,0 +1,8 @@
1
+ Moneytree::Engine.routes.draw do
2
+ get 'oauth/stripe/new', to: 'oauth/stripe#new'
3
+ get 'oauth/stripe/callback', to: 'oauth/stripe#callback'
4
+
5
+ namespace :webhooks do
6
+ resources :stripe, only: :create
7
+ end
8
+ end
@@ -0,0 +1,11 @@
1
+ class CreateMoneytreePaymentGateways < ActiveRecord::Migration[6.0]
2
+ def change
3
+ create_table :moneytree_payment_gateways do |t|
4
+ t.text :psp_credentials
5
+ t.integer :psp, null: false
6
+ t.references :account, polymorphic: true, index: { name: 'index_moneytree_pg_account_type_and_account_id' }
7
+
8
+ t.timestamps
9
+ end
10
+ end
11
+ end
@@ -0,0 +1,18 @@
1
+ class CreateMoneytreeTransactions < ActiveRecord::Migration[6.0]
2
+ def change
3
+ create_table :moneytree_transactions do |t|
4
+ t.decimal :amount, null: false, default: 0
5
+ t.decimal :app_fee_amount, null: false, default: 0
6
+ t.integer :status, null: false, default: 0
7
+ t.string :type, null: false, default: 'Moneytree::Payment'
8
+ t.references :order, polymorphic: true, null: false
9
+ t.references :payment_gateway, null: false
10
+ t.references :payment, foreign_key: { to_table: :moneytree_transactions }
11
+ t.text :psp_error
12
+ t.text :details
13
+ t.text :refund_reason
14
+
15
+ t.timestamps
16
+ end
17
+ end
18
+ end
@@ -0,0 +1 @@
1
+ require 'moneytree'
@@ -1,31 +1,31 @@
1
1
  # dependencies
2
- require 'active_support'
3
- require 'active_support/core_ext'
2
+ # require 'rails'
3
+ # require 'active_support/core_ext'
4
4
 
5
5
  # modules
6
6
  # FIXME: autoload instead? https :/ / github.com / excid3 / noticed / blob / master / lib / noticed.rb
7
7
  require 'moneytree/version'
8
+ require 'moneytree/transaction_response'
8
9
  require 'moneytree/account'
9
- require 'moneytree/transaction'
10
- require 'moneytree/payment_provider/square'
11
-
12
- require "'moneytree/engine" if defined?(Rails)
10
+ require 'moneytree/order'
11
+ require 'moneytree/payment_provider/base'
12
+ require 'moneytree/payment_provider/stripe'
13
+ require 'moneytree/engine'
13
14
 
14
15
  module Moneytree
15
- PSPS = %i[square stripe braintree].freeze
16
+ PSPS = %i[stripe].freeze
16
17
 
17
18
  mattr_accessor :enabled_psps
18
- mattr_accessor :account_class
19
- mattr_accessor :order_class
20
- mattr_accessor :transaction_class
21
- mattr_accessor :square_credentials
19
+ mattr_accessor :stripe_credentials
22
20
  mattr_accessor :current_account
21
+ mattr_accessor :oauth_redirect
22
+ mattr_accessor :refund_application_fee
23
+ mattr_accessor :order_status_trigger_method
23
24
 
24
25
  @@enabled_psps = PSPS
25
- @@account_class = 'Account'
26
- @@order_class = 'Order'
27
- @@transaction_class = 'Transaction'
28
- @@current_account = 'current_account'
26
+ @@current_account = :current_account
27
+ @@oauth_redirect = '/'
28
+ @@refund_application_fee = false
29
29
 
30
30
  def self.setup
31
31
  yield self
@@ -35,7 +35,7 @@ module Moneytree
35
35
  class Error < StandardError; end
36
36
  end
37
37
 
38
- # FIXME: See if we need this, example: https://github.com/ankane/ahoy/blob/master/lib/ahoy/model.rb
38
+ # FIXME: See if we need this
39
39
  ActiveSupport.on_load(:action_controller) do
40
40
  # include Moneytree::Controller
41
41
  end
@@ -1,42 +1,12 @@
1
+ require 'active_support/concern'
2
+
1
3
  module Moneytree
2
4
  module Account
3
5
  extend ActiveSupport::Concern
6
+ # FIXME: see if we can remove config.current_account = :current_merchant and set it from here
4
7
 
5
8
  included do
6
- enum moneytree_psp: Moneytree::PSPS
7
- serialize :psp_credentials
8
- # encrypts :psp_credentials
9
- # FIXME: enable https://github.com/ankane/lockbox
10
- delegate :client, :oauth_link, to: :psp
11
- end
12
-
13
- def oauth_callback(params)
14
- update! psp_credentials: psp.oauth_callback(params)
15
- end
16
-
17
- def psp_connected?
18
- false
19
- # moneytree_psp && psp_credentials
20
- end
21
-
22
- def needs_oauth?
23
- true
24
- end
25
-
26
- def charge; end
27
-
28
- def refund; end
29
-
30
- private
31
-
32
- def psp
33
- @psp ||=
34
- case moneytree_psp
35
- when 'square'
36
- Moneytree::PaymentProvider::Square.new(self)
37
- else
38
- raise 'BOOM'
39
- end
9
+ has_one :moneytree_payment_gateway, class_name: 'Moneytree::PaymentGateway', foreign_key: 'account_id', inverse_of: :account, as: :account
40
10
  end
41
11
  end
42
12
  end
@@ -0,0 +1,5 @@
1
+ module Moneytree
2
+ class Engine < ::Rails::Engine
3
+ isolate_namespace Moneytree
4
+ end
5
+ end
@@ -0,0 +1,15 @@
1
+ require 'active_support/concern'
2
+
3
+ module Moneytree
4
+ module Order
5
+ extend ActiveSupport::Concern
6
+
7
+ included do
8
+ has_many :moneytree_transactions, class_name: 'Moneytree::Transaction', foreign_key: 'order_id', inverse_of: :order, as: :order
9
+ end
10
+
11
+ def new_payment(*args)
12
+ moneytree_transactions << Payment.new(*args)
13
+ end
14
+ end
15
+ end
@@ -1,8 +1,11 @@
1
1
  module Moneytree
2
2
  module PaymentProvider
3
3
  class Base
4
- def initialize(account)
5
- @account = account
4
+ attr_reader :payment_gateway, :account
5
+
6
+ def initialize(payment_gateway)
7
+ @payment_gateway = payment_gateway
8
+ @account = @payment_gateway.account
6
9
  end
7
10
  end
8
11
  end
@@ -0,0 +1,80 @@
1
+ module Moneytree
2
+ module PaymentProvider
3
+ class Stripe < Base
4
+ # The permissions we request from Square OAuth, we store them in the database
5
+ PERMISSION = :read_write
6
+
7
+ def initialize(args)
8
+ raise Error, 'Please set your Stripe credentials' if credentitals.nil?
9
+ raise Error, 'Please include the stripe gem to your Gemfile' unless Object.const_defined?('::Stripe')
10
+
11
+ ::Stripe.api_key = credentitals[:api_key]
12
+ super
13
+ end
14
+
15
+ def get_access_token(params)
16
+ # FIXME: add error handling
17
+ ::Stripe::OAuth.token(
18
+ {
19
+ grant_type: 'authorization_code',
20
+ code: params[:code]
21
+ }
22
+ ).to_hash
23
+ end
24
+
25
+ def scope
26
+ PERMISSION.to_s
27
+ end
28
+
29
+ def charge(amount, details, app_fee_amount: 0, description: "Charge for #{account.name}", metadata:)
30
+ # `source` is obtained with Stripe.js; see https://stripe.com/docs/payments/accept-a-payment-charges#web-create-token
31
+ response = ::Stripe::Charge.create(
32
+ {
33
+ amount: (amount * 100).to_i,
34
+ currency: account.currency_code,
35
+ source: details[:card_token],
36
+ description: description,
37
+ metadata: metadata,
38
+ application_fee_amount: (app_fee_amount * 100).to_i
39
+ },
40
+ stripe_account: payment_gateway.psp_credentials[:stripe_user_id]
41
+ )
42
+ # succeeded, pending, or failed
43
+ TransactionResponse.new(
44
+ { succeeded: :success, pending: :pending, failed: :failed }[response[:status].to_sym],
45
+ response[:failure_message],
46
+ { charge_id: response[:id] }
47
+ )
48
+ rescue ::Stripe::StripeError => e
49
+ TransactionResponse.new(:failed, e.message)
50
+ end
51
+
52
+ def refund(amount, details, metadata:)
53
+ response = ::Stripe::Refund.create(
54
+ {
55
+ charge: details[:charge_id],
56
+ amount: (-amount * 100).to_i,
57
+ metadata: metadata,
58
+ refund_application_fee: Moneytree.refund_application_fee
59
+ },
60
+ stripe_account: payment_gateway.psp_credentials[:stripe_user_id]
61
+ )
62
+
63
+ # succeeded, pending, or failed
64
+ TransactionResponse.new(
65
+ { succeeded: :success, pending: :pending, failed: :failed }[response[:status].to_sym],
66
+ response[:failure_message],
67
+ { refund_id: response[:id] }
68
+ )
69
+ rescue ::Stripe::StripeError => e
70
+ TransactionResponse.new(:failed, e.message)
71
+ end
72
+
73
+ private
74
+
75
+ def credentitals
76
+ Moneytree.stripe_credentials
77
+ end
78
+ end
79
+ end
80
+ end
@@ -0,0 +1,15 @@
1
+ module Moneytree
2
+ class TransactionResponse
3
+ attr_reader :message, :status, :body
4
+
5
+ def initialize(status, message, body = {})
6
+ @status = status
7
+ @message = message
8
+ @body = body
9
+ end
10
+
11
+ def success?
12
+ @status == :success
13
+ end
14
+ end
15
+ end
@@ -1,3 +1,3 @@
1
1
  module Moneytree
2
- VERSION = "0.1.0"
2
+ VERSION = '0.1.5'.freeze
3
3
  end
@@ -0,0 +1,4 @@
1
+ # desc "Explaining what the task does"
2
+ # task :moneytree do
3
+ # # Task goes here
4
+ # end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: moneytree-rails
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.0
4
+ version: 0.1.5
5
5
  platform: ruby
6
6
  authors:
7
7
  - Kieran Klaassen
8
8
  autorequire:
9
- bindir: exe
9
+ bindir: bin
10
10
  cert_chain: []
11
- date: 2020-09-02 00:00:00.000000000 Z
11
+ date: 2020-11-27 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rails
@@ -24,6 +24,20 @@ dependencies:
24
24
  - - ">="
25
25
  - !ruby/object:Gem::Version
26
26
  version: '4.2'
27
+ - !ruby/object:Gem::Dependency
28
+ name: sqlite3
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - ">="
32
+ - !ruby/object:Gem::Version
33
+ version: '0'
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - ">="
39
+ - !ruby/object:Gem::Version
40
+ version: '0'
27
41
  description: A payments engine for rails centered aorund transactional payments and
28
42
  orders.
29
43
  email:
@@ -32,44 +46,42 @@ executables: []
32
46
  extensions: []
33
47
  extra_rdoc_files: []
34
48
  files:
35
- - ".github/workflows/ruby.yml"
36
- - ".gitignore"
37
- - ".rspec"
38
- - ".travis.yml"
39
- - CHANGELOG.md
40
- - CODE_OF_CONDUCT.md
41
- - Gemfile
42
- - Gemfile.lock
43
- - Guardfile
44
- - LICENSE.txt
49
+ - MIT-LICENSE
45
50
  - README.md
46
51
  - Rakefile
47
- - app/controllers/moneytree/oauth_controller.rb
48
- - bin/console
49
- - bin/setup
50
- - config.ru
51
- - lib/generators/moneytree/activerecord_generator.rb
52
- - lib/generators/moneytree/base_generator.rb
53
- - lib/generators/moneytree/install_generator.rb
54
- - lib/generators/moneytree/templates/active_record_event_model.rb.tt
55
- - lib/generators/moneytree/templates/active_record_migration.rb.tt
56
- - lib/generators/moneytree/templates/active_record_visit_model.rb.tt
57
- - lib/generators/moneytree/templates/base_store_initializer.rb.tt
58
- - lib/generators/moneytree/templates/moneytree_initializer.rb.tt
52
+ - app/assets/config/moneytree_manifest.js
53
+ - app/assets/stylesheets/moneytree/application.css
54
+ - app/controllers/moneytree/application_controller.rb
55
+ - app/controllers/moneytree/oauth/square_controller.rb
56
+ - app/controllers/moneytree/oauth/stripe_controller.rb
57
+ - app/controllers/moneytree/webhooks/square_controller.rb
58
+ - app/controllers/moneytree/webhooks/stripe_controller.rb
59
+ - app/jobs/moneytree/application_job.rb
60
+ - app/mailers/moneytree/application_mailer.rb
61
+ - app/models/moneytree/application_record.rb
62
+ - app/models/moneytree/payment.rb
63
+ - app/models/moneytree/payment_gateway.rb
64
+ - app/models/moneytree/refund.rb
65
+ - app/models/moneytree/transaction.rb
66
+ - app/views/layouts/moneytree/application.html.erb
67
+ - config/routes.rb
68
+ - db/migrate/20200914151648_create_moneytree_payment_gateways.rb
69
+ - db/migrate/20201008161617_create_moneytree_transactions.rb
70
+ - lib/moneytree-rails.rb
59
71
  - lib/moneytree.rb
60
72
  - lib/moneytree/account.rb
73
+ - lib/moneytree/engine.rb
74
+ - lib/moneytree/order.rb
61
75
  - lib/moneytree/payment_provider/base.rb
62
76
  - lib/moneytree/payment_provider/square.rb
63
- - lib/moneytree/transaction.rb
77
+ - lib/moneytree/payment_provider/stripe.rb
78
+ - lib/moneytree/transaction_response.rb
64
79
  - lib/moneytree/version.rb
65
- - moneytree.gemspec
80
+ - lib/tasks/moneytree_tasks.rake
66
81
  homepage: https://github.com/kieranklaassen/moneytree
67
82
  licenses:
68
83
  - MIT
69
- metadata:
70
- homepage_uri: https://github.com/kieranklaassen/moneytree
71
- source_code_uri: https://github.com/kieranklaassen/moneytree
72
- changelog_uri: https://github.com/kieranklaassen/moneytree/blob/master/CHANGELOG.md
84
+ metadata: {}
73
85
  post_install_message:
74
86
  rdoc_options: []
75
87
  require_paths:
@@ -78,14 +90,14 @@ required_ruby_version: !ruby/object:Gem::Requirement
78
90
  requirements:
79
91
  - - ">="
80
92
  - !ruby/object:Gem::Version
81
- version: 2.3.0
93
+ version: '0'
82
94
  required_rubygems_version: !ruby/object:Gem::Requirement
83
95
  requirements:
84
96
  - - ">="
85
97
  - !ruby/object:Gem::Version
86
98
  version: '0'
87
99
  requirements: []
88
- rubygems_version: 3.1.2
100
+ rubygems_version: 3.1.4
89
101
  signing_key:
90
102
  specification_version: 4
91
103
  summary: A payments engine for rails centered aorund transactional payments and orders.