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.
- checksums.yaml +4 -4
- data/MIT-LICENSE +20 -0
- data/README.md +63 -30
- data/Rakefile +30 -4
- data/app/assets/config/moneytree_manifest.js +1 -0
- data/app/assets/stylesheets/moneytree/application.css +15 -0
- data/app/controllers/moneytree/application_controller.rb +9 -0
- data/app/controllers/moneytree/oauth/square_controller.rb +14 -0
- data/app/controllers/moneytree/oauth/stripe_controller.rb +44 -0
- data/app/controllers/moneytree/webhooks/square_controller.rb +9 -0
- data/app/controllers/moneytree/webhooks/stripe_controller.rb +67 -0
- data/app/jobs/moneytree/application_job.rb +4 -0
- data/app/mailers/moneytree/application_mailer.rb +6 -0
- data/app/models/moneytree/application_record.rb +5 -0
- data/app/models/moneytree/payment.rb +23 -0
- data/app/models/moneytree/payment_gateway.rb +47 -0
- data/app/models/moneytree/refund.rb +46 -0
- data/app/models/moneytree/transaction.rb +30 -0
- data/app/views/layouts/moneytree/application.html.erb +15 -0
- data/config/routes.rb +8 -0
- data/db/migrate/20200914151648_create_moneytree_payment_gateways.rb +11 -0
- data/db/migrate/20201008161617_create_moneytree_transactions.rb +18 -0
- data/lib/moneytree-rails.rb +1 -0
- data/lib/moneytree.rb +16 -16
- data/lib/moneytree/account.rb +4 -34
- data/lib/moneytree/engine.rb +5 -0
- data/lib/moneytree/order.rb +15 -0
- data/lib/moneytree/payment_provider/base.rb +5 -2
- data/lib/moneytree/payment_provider/stripe.rb +80 -0
- data/lib/moneytree/transaction_response.rb +15 -0
- data/lib/moneytree/version.rb +1 -1
- data/lib/tasks/moneytree_tasks.rake +4 -0
- metadata +45 -33
- data/.github/workflows/ruby.yml +0 -33
- data/.gitignore +0 -12
- data/.rspec +0 -3
- data/.travis.yml +0 -6
- data/CHANGELOG.md +0 -7
- data/CODE_OF_CONDUCT.md +0 -74
- data/Gemfile +0 -15
- data/Gemfile.lock +0 -248
- data/Guardfile +0 -70
- data/LICENSE.txt +0 -21
- data/app/controllers/moneytree/oauth_controller.rb +0 -18
- data/bin/console +0 -14
- data/bin/setup +0 -8
- data/config.ru +0 -9
- data/lib/generators/moneytree/activerecord_generator.rb +0 -41
- data/lib/generators/moneytree/base_generator.rb +0 -13
- data/lib/generators/moneytree/install_generator.rb +0 -43
- data/lib/generators/moneytree/templates/active_record_event_model.rb.tt +0 -10
- data/lib/generators/moneytree/templates/active_record_migration.rb.tt +0 -62
- data/lib/generators/moneytree/templates/active_record_visit_model.rb.tt +0 -6
- data/lib/generators/moneytree/templates/base_store_initializer.rb.tt +0 -20
- data/lib/generators/moneytree/templates/moneytree_initializer.rb.tt +0 -15
- data/lib/moneytree/transaction.rb +0 -9
- data/moneytree.gemspec +0 -29
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 2006000e7eb666a0edd1d8e035330c00804f41460dcca1a7e73d75f855dcd254
|
4
|
+
data.tar.gz: 1a36220066504521f1d9d4b477d9eeca1fb5ddd7dce1abc37daefe0a4412001f
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 72fbbd0d1f6dd0e144e6d72a412aa7313487afa0d92c2bbb5213925a4d3e4eaebdcb1369a64060183d7b073de41823f97d1f978f8751151c82799a8565324530
|
7
|
+
data.tar.gz: 296df5c1b71b78acd51639d49caca1964bf8260c156ddc7ea68aa648dcf47a6fe8e1e0b9887e1cf20236365a8436dd9b76f45c7e1a5f18fdb74d537a3944d8bf
|
data/MIT-LICENSE
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
Copyright 2020 Kieran Klaassen
|
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/README.md
CHANGED
@@ -1,16 +1,9 @@
|
|
1
1
|
# 🚧 WORK IN PROGRESS 🚧
|
2
2
|
|
3
|
-
- [ ] OAuth
|
4
|
-
- [ ] Cards
|
5
|
-
- [ ] Customers
|
6
|
-
- [ ] Payments
|
7
|
-
- [ ] Refunds
|
8
|
-
- [ ] Notifications
|
9
|
-
|
10
3
|
# Moneytree 💵 🌴
|
11
4
|
|
12
5
|
[](https://github.com/kieranklaassen/moneytree/actions)
|
13
|
-
[](https://badge.fury.io/rb/moneytree)
|
6
|
+
[](https://badge.fury.io/rb/moneytree-rails)
|
14
7
|
|
15
8
|
🔥 A powerful, simple, and extendable payment engine for rails, centered around transactional payments. 💵 🌴
|
16
9
|
|
@@ -19,16 +12,16 @@ functionality with almost no work on your end:
|
|
19
12
|
|
20
13
|
- 💵💶💷💴 Multi-currency
|
21
14
|
- 🔑 OAuth to link your PSP account
|
22
|
-
- 👩💻PSP account creation, (with commission)
|
15
|
+
- 👩💻 PSP account creation, (with commission)
|
23
16
|
- ⚙️ Webhooks
|
24
|
-
- 💳 PCI compliance with Javascript libraries
|
25
|
-
- 🧲 Platform fees
|
17
|
+
- 💳 ~~PCI compliance with Javascript libraries~~ comming soon
|
18
|
+
- 🧲 Platform fees a.k.a. Market Places
|
26
19
|
|
27
20
|
Currently we support the following PSP's:
|
28
21
|
|
29
|
-
- Square
|
22
|
+
- ~~Square~~ comming soon
|
30
23
|
- Stripe
|
31
|
-
- Braintree
|
24
|
+
- ~~Braintree~~ comming soon
|
32
25
|
|
33
26
|
But if you want to add more PSP's, we make it easy to do so. Read our
|
34
27
|
[Contributing](https://github.com/kieranklaassen/moneytree#contributing) section to learn more.
|
@@ -48,33 +41,69 @@ rails app:template LOCATION='https://railsbytes.com/script/Xg8sOv'
|
|
48
41
|
Add the latest version of Moneytree to your gem Gemfile by running:
|
49
42
|
|
50
43
|
```bash
|
51
|
-
$ bundle add moneytree
|
44
|
+
$ bundle add moneytree-rails
|
52
45
|
$ bundle install
|
53
|
-
$
|
46
|
+
$ rails g moneytree:install:migrations
|
47
|
+
$ rails g db:migrate
|
54
48
|
```
|
55
49
|
|
56
|
-
Or your can use environment variables:
|
57
|
-
|
58
|
-
FIXME: add
|
59
|
-
|
60
50
|
## Configuration
|
61
51
|
|
52
|
+
### Initializer
|
53
|
+
|
62
54
|
Do you need to make some changes to how Moneytree is used? You can create an initializer
|
63
55
|
`config/initializers/moneytree.rb`
|
64
56
|
|
65
57
|
```ruby
|
66
58
|
Moneytree.setup do |config|
|
67
|
-
config.
|
68
|
-
config.
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
config.square_credentials = {
|
73
|
-
app_id: ENV['SQUARE_APP_ID'],
|
74
|
-
app_secret: ENV['SQUARE_APP_SECRET'],
|
75
|
-
environment: Rails.env.production? : 'production' : 'sandbox',
|
76
|
-
oauth_domain: Rails.env.production? ? 'https://connect.squareup.com' : 'https://connect.squareupsandbox.com'
|
59
|
+
config.current_account = :current_merchant
|
60
|
+
config.stripe_credentials = {
|
61
|
+
api_key: ENV['STRIPE_API_KEY'],
|
62
|
+
client_id: ENV['STRIPE_CLIENT_ID']
|
77
63
|
}
|
64
|
+
config.oauth_redirect = '/welcome_back'
|
65
|
+
config.refund_application_fee = true # false by default
|
66
|
+
end
|
67
|
+
```
|
68
|
+
|
69
|
+
### Routes
|
70
|
+
|
71
|
+
Add to your routes and authenticate if needed to make sure only admins can integrate with OAuth.
|
72
|
+
|
73
|
+
```ruby
|
74
|
+
authenticate :user, ->(u) { u.admin? } do
|
75
|
+
mount Moneytree::Engine => '/moneytree'
|
76
|
+
end
|
77
|
+
```
|
78
|
+
|
79
|
+
### Models
|
80
|
+
|
81
|
+
Include account concern into your models and make sure the following attributes work:
|
82
|
+
|
83
|
+
```ruby
|
84
|
+
class Merchant < ApplicationRecord
|
85
|
+
include Moneytree::Account
|
86
|
+
|
87
|
+
def email
|
88
|
+
owner.email
|
89
|
+
end
|
90
|
+
|
91
|
+
def currency_code
|
92
|
+
currency.code
|
93
|
+
end
|
94
|
+
|
95
|
+
def website
|
96
|
+
'https://www.boomtown.com'
|
97
|
+
end
|
98
|
+
end
|
99
|
+
```
|
100
|
+
|
101
|
+
And add `Moneytree::Order` concern to the model that will be the parent for all the transactions. In most cases this
|
102
|
+
will be an order. This model will keep a balance and you can add multiple payments and refunds to it.
|
103
|
+
|
104
|
+
```ruby
|
105
|
+
class Order < ApplicationRecord
|
106
|
+
include Moneytree::Order
|
78
107
|
end
|
79
108
|
```
|
80
109
|
|
@@ -88,6 +117,10 @@ transaction attached for the payment. You can name these models however you want
|
|
88
117
|
|
89
118
|
### The API
|
90
119
|
|
120
|
+
#### Moneytree::PaymentGateway
|
121
|
+
|
122
|
+
##### #method here
|
123
|
+
|
91
124
|
## Development
|
92
125
|
|
93
126
|
After checking out the repo, run `bin/setup` to install dependencies. Then, run `rake spec` to run the tests. You can
|
@@ -105,7 +138,7 @@ intended to be a safe, welcoming space for collaboration, and contributors are e
|
|
105
138
|
|
106
139
|
## License
|
107
140
|
|
108
|
-
The gem is available as open
|
141
|
+
The gem is available as open-source under the terms of the [MIT License](https://opensource.org/licenses/MIT).
|
109
142
|
|
110
143
|
## Code of Conduct
|
111
144
|
|
data/Rakefile
CHANGED
@@ -1,6 +1,32 @@
|
|
1
|
-
|
2
|
-
require
|
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
|
3
6
|
|
4
|
-
|
7
|
+
require 'rdoc/task'
|
5
8
|
|
6
|
-
|
9
|
+
RDoc::Task.new(:rdoc) do |rdoc|
|
10
|
+
rdoc.rdoc_dir = 'rdoc'
|
11
|
+
rdoc.title = 'Moneytree'
|
12
|
+
rdoc.options << '--line-numbers'
|
13
|
+
rdoc.rdoc_files.include('README.md')
|
14
|
+
rdoc.rdoc_files.include('lib/**/*.rb')
|
15
|
+
end
|
16
|
+
|
17
|
+
APP_RAKEFILE = File.expand_path("test/dummy/Rakefile", __dir__)
|
18
|
+
load 'rails/tasks/engine.rake'
|
19
|
+
|
20
|
+
load 'rails/tasks/statistics.rake'
|
21
|
+
|
22
|
+
require 'bundler/gem_tasks'
|
23
|
+
|
24
|
+
require 'rake/testtask'
|
25
|
+
|
26
|
+
Rake::TestTask.new(:test) do |t|
|
27
|
+
t.libs << 'test'
|
28
|
+
t.pattern = 'test/**/*_test.rb'
|
29
|
+
t.verbose = false
|
30
|
+
end
|
31
|
+
|
32
|
+
task default: :test
|
@@ -0,0 +1 @@
|
|
1
|
+
//= link_directory ../stylesheets/moneytree .css
|
@@ -0,0 +1,15 @@
|
|
1
|
+
/*
|
2
|
+
* This is a manifest file that'll be compiled into application.css, which will include all the files
|
3
|
+
* listed below.
|
4
|
+
*
|
5
|
+
* Any CSS and SCSS file within this directory, lib/assets/stylesheets, vendor/assets/stylesheets,
|
6
|
+
* or any plugin's vendor/assets/stylesheets directory can be referenced here using a relative path.
|
7
|
+
*
|
8
|
+
* You're free to add application-wide styles to this file and they'll appear at the bottom of the
|
9
|
+
* compiled file so the styles you add here take precedence over styles defined in any other CSS/SCSS
|
10
|
+
* files in this directory. Styles in this file should be added after the last require_* statement.
|
11
|
+
* It is generally better to create a new file per style scope.
|
12
|
+
*
|
13
|
+
*= require_tree .
|
14
|
+
*= require_self
|
15
|
+
*/
|
@@ -0,0 +1,44 @@
|
|
1
|
+
module Moneytree
|
2
|
+
module Oauth
|
3
|
+
class StripeController < ApplicationController
|
4
|
+
def new
|
5
|
+
redirect_to stripe_oauth_url
|
6
|
+
end
|
7
|
+
|
8
|
+
def callback
|
9
|
+
# TODO: Remove this module prefix once we figure out how to properly autoload this.
|
10
|
+
payment_gateway = Moneytree::PaymentGateway.create!(psp: 'stripe', account: current_account)
|
11
|
+
payment_gateway.oauth_callback(payment_gateway_params)
|
12
|
+
redirect_to Moneytree.oauth_redirect, notice: 'Connected to Stripe'
|
13
|
+
end
|
14
|
+
|
15
|
+
private
|
16
|
+
|
17
|
+
def payment_gateway_params
|
18
|
+
params.permit :scope, :code
|
19
|
+
end
|
20
|
+
|
21
|
+
def stripe_oauth_url
|
22
|
+
# https://stripe.com/docs/connect/oauth-reference
|
23
|
+
# https://stripe.com/docs/connect/oauth-reference#get-authorize
|
24
|
+
URI::HTTPS.build(
|
25
|
+
host: 'connect.stripe.com',
|
26
|
+
path: '/oauth/authorize',
|
27
|
+
query: {
|
28
|
+
response_type: :code,
|
29
|
+
client_id: Moneytree.stripe_credentials[:client_id],
|
30
|
+
scope: PaymentProvider::Stripe::PERMISSION,
|
31
|
+
redirect_uri: oauth_stripe_callback_url,
|
32
|
+
'stripe_user[email]': current_account.email,
|
33
|
+
'stripe_user[url]': current_account.website,
|
34
|
+
'stripe_user[currency]': current_account.currency_code
|
35
|
+
}.to_query
|
36
|
+
).to_s
|
37
|
+
end
|
38
|
+
|
39
|
+
def current_account
|
40
|
+
send(Moneytree.current_account)
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
@@ -0,0 +1,67 @@
|
|
1
|
+
module Moneytree
|
2
|
+
module Webhooks
|
3
|
+
class StripeController < ApplicationController
|
4
|
+
skip_before_action :verify_authenticity_token
|
5
|
+
|
6
|
+
def create
|
7
|
+
case webhook_params.type
|
8
|
+
when 'charge.succeeded'
|
9
|
+
process_charge!
|
10
|
+
when 'charge.refunded'
|
11
|
+
process_refund!
|
12
|
+
else
|
13
|
+
puts "Unhandled event type: #{webhook_params.type}"
|
14
|
+
end
|
15
|
+
|
16
|
+
head :ok
|
17
|
+
end
|
18
|
+
|
19
|
+
private
|
20
|
+
|
21
|
+
def webhook_params
|
22
|
+
@webhook_params ||=
|
23
|
+
::Stripe::Event.construct_from(
|
24
|
+
JSON.parse(request.body.read, symbolize_names: true)
|
25
|
+
)
|
26
|
+
end
|
27
|
+
|
28
|
+
def process_charge!
|
29
|
+
return if transaction.completed?
|
30
|
+
|
31
|
+
transaction.process_response(
|
32
|
+
TransactionResponse.new(:success, '', { charge_id: stripe_object.id })
|
33
|
+
)
|
34
|
+
|
35
|
+
if Moneytree.order_status_trigger_method
|
36
|
+
transaction.order.send(Moneytree.order_status_trigger_method, transaction)
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
def process_refund!
|
41
|
+
stripe_object.refunds.data.each do |stripe_refund_object|
|
42
|
+
# TODO: Create refund transaction in db for PSP-initiated refunds
|
43
|
+
next if stripe_refund_object.metadata[:moneytree_transaction_id].blank?
|
44
|
+
|
45
|
+
refund = transaction.refunds.find(stripe_refund_object.metadata[:moneytree_transaction_id])
|
46
|
+
|
47
|
+
next if refund.completed?
|
48
|
+
|
49
|
+
refund.process_response(
|
50
|
+
TransactionResponse.new(:success, '')
|
51
|
+
)
|
52
|
+
if Moneytree.order_status_trigger_method
|
53
|
+
transaction.order.send(Moneytree.order_status_trigger_method, transaction)
|
54
|
+
end
|
55
|
+
end
|
56
|
+
end
|
57
|
+
|
58
|
+
def transaction
|
59
|
+
@transaction ||= Transaction.find(stripe_object.metadata[:moneytree_transaction_id])
|
60
|
+
end
|
61
|
+
|
62
|
+
def stripe_object
|
63
|
+
@stripe_object ||= webhook_params.data.object
|
64
|
+
end
|
65
|
+
end
|
66
|
+
end
|
67
|
+
end
|
@@ -0,0 +1,23 @@
|
|
1
|
+
module Moneytree
|
2
|
+
class Payment < Transaction
|
3
|
+
has_many :refunds, class_name: 'Refund'
|
4
|
+
|
5
|
+
validates_absence_of :payment_id
|
6
|
+
|
7
|
+
validates_numericality_of :amount, greater_than: 0
|
8
|
+
validates_numericality_of :app_fee_amount, greater_than_or_equal_to: 0
|
9
|
+
|
10
|
+
private
|
11
|
+
|
12
|
+
def execute_transaction(metadata: {})
|
13
|
+
process_response(
|
14
|
+
payment_gateway.charge(
|
15
|
+
amount,
|
16
|
+
details,
|
17
|
+
app_fee_amount: app_fee_amount,
|
18
|
+
metadata: metadata.merge(moneytree_transaction_id: id)
|
19
|
+
)
|
20
|
+
)
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
@@ -0,0 +1,47 @@
|
|
1
|
+
module Moneytree
|
2
|
+
class PaymentGateway < ApplicationRecord
|
3
|
+
belongs_to :account, polymorphic: true
|
4
|
+
|
5
|
+
enum psp: Moneytree::PSPS
|
6
|
+
serialize :psp_credentials
|
7
|
+
# encrypts :psp_credentials
|
8
|
+
# FIXME: enable https://github.com/ankane/lockbox
|
9
|
+
delegate :oauth_link, :scope_correct?, :charge, :refund, to: :payment_provider
|
10
|
+
|
11
|
+
# has_many :orders
|
12
|
+
# has_many :transactions
|
13
|
+
# has_many :customers
|
14
|
+
# has_many :cards
|
15
|
+
|
16
|
+
def oauth_callback(params)
|
17
|
+
update! psp_credentials: payment_provider.get_access_token(params)
|
18
|
+
end
|
19
|
+
|
20
|
+
def psp_connected?
|
21
|
+
psp.present? && psp_credentials.present?
|
22
|
+
end
|
23
|
+
|
24
|
+
def needs_oauth?
|
25
|
+
!psp_connected? || !scope_correct?
|
26
|
+
end
|
27
|
+
|
28
|
+
def scope_correct?
|
29
|
+
psp_credentials[:scope] == payment_provider.scope
|
30
|
+
end
|
31
|
+
|
32
|
+
private
|
33
|
+
|
34
|
+
def payment_provider
|
35
|
+
@payment_provider ||=
|
36
|
+
case psp
|
37
|
+
when 'stripe'
|
38
|
+
# TODO: see if we only need to pass credentials
|
39
|
+
Moneytree::PaymentProvider::Stripe.new(self)
|
40
|
+
# when 'square'
|
41
|
+
# Moneytree::PaymentProvider::Square.new(self)
|
42
|
+
else
|
43
|
+
raise 'BOOM'
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|