dune-balanced-creditcard 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (86) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +20 -0
  3. data/.rspec +2 -0
  4. data/.travis.yml +13 -0
  5. data/CHANGELOG.md +5 -0
  6. data/Gemfile +6 -0
  7. data/LICENSE.txt +22 -0
  8. data/README.md +48 -0
  9. data/Rakefile +34 -0
  10. data/app/assets/images/dune/balanced/creditcard/.gitkeep +0 -0
  11. data/app/assets/javascripts/dune/balanced/creditcard/flash.js.coffee +15 -0
  12. data/app/assets/javascripts/dune/balanced/creditcard/payments.js.coffee.erb +86 -0
  13. data/app/assets/javascripts/dune-balanced-creditcard.js +1 -0
  14. data/app/assets/stylesheets/dune/balanced/creditcard/application.css +16 -0
  15. data/app/controllers/dune/balanced/creditcard/application_controller.rb +4 -0
  16. data/app/controllers/dune/balanced/creditcard/payments_controller.rb +84 -0
  17. data/app/models/dune/balanced/creditcard/payment.rb +94 -0
  18. data/app/models/dune/balanced/creditcard/transaction_additional_fee_calculator.rb +12 -0
  19. data/app/models/dune/balanced/creditcard/transaction_fee_calculator_base.rb +31 -0
  20. data/app/models/dune/balanced/creditcard/transaction_inclusive_fee_calculator.rb +13 -0
  21. data/app/views/dune/balanced/creditcard/.gitkeep +0 -0
  22. data/app/views/dune/balanced/creditcard/payments/new.html.slim +98 -0
  23. data/bin/rails +8 -0
  24. data/config/initializers/registration.rb +5 -0
  25. data/config/locales/en.yml +32 -0
  26. data/config/locales/simple_form.en.yml +12 -0
  27. data/config/routes.rb +5 -0
  28. data/dune-balanced-creditcard.gemspec +27 -0
  29. data/lib/dune/balanced/creditcard/engine.rb +9 -0
  30. data/lib/dune/balanced/creditcard/interface.rb +27 -0
  31. data/lib/dune/balanced/creditcard/version.rb +7 -0
  32. data/lib/dune/balanced/creditcard.rb +11 -0
  33. data/lib/float_extensions.rb +11 -0
  34. data/spec/controllers/neighborly/balanced/creditcard/payments_controller_spec.rb +199 -0
  35. data/spec/dummy/README.rdoc +28 -0
  36. data/spec/dummy/Rakefile +6 -0
  37. data/spec/dummy/app/assets/images/.keep +0 -0
  38. data/spec/dummy/app/assets/javascripts/application.js +13 -0
  39. data/spec/dummy/app/assets/stylesheets/application.css +13 -0
  40. data/spec/dummy/app/controllers/application_controller.rb +5 -0
  41. data/spec/dummy/app/controllers/concerns/.keep +0 -0
  42. data/spec/dummy/app/helpers/application_helper.rb +2 -0
  43. data/spec/dummy/app/mailers/.keep +0 -0
  44. data/spec/dummy/app/models/.keep +0 -0
  45. data/spec/dummy/app/models/concerns/.keep +0 -0
  46. data/spec/dummy/app/models/configuration.rb +9 -0
  47. data/spec/dummy/app/models/contribution.rb +32 -0
  48. data/spec/dummy/app/models/match.rb +31 -0
  49. data/spec/dummy/app/models/payment_engine.rb +5 -0
  50. data/spec/dummy/app/models/project.rb +9 -0
  51. data/spec/dummy/app/models/user.rb +2 -0
  52. data/spec/dummy/app/views/layouts/application.html.erb +14 -0
  53. data/spec/dummy/bin/bundle +3 -0
  54. data/spec/dummy/bin/rails +4 -0
  55. data/spec/dummy/bin/rake +4 -0
  56. data/spec/dummy/config/application.rb +24 -0
  57. data/spec/dummy/config/boot.rb +5 -0
  58. data/spec/dummy/config/database.yml +25 -0
  59. data/spec/dummy/config/environment.rb +5 -0
  60. data/spec/dummy/config/environments/development.rb +29 -0
  61. data/spec/dummy/config/environments/production.rb +80 -0
  62. data/spec/dummy/config/environments/test.rb +36 -0
  63. data/spec/dummy/config/initializers/backtrace_silencers.rb +7 -0
  64. data/spec/dummy/config/initializers/filter_parameter_logging.rb +4 -0
  65. data/spec/dummy/config/initializers/inflections.rb +16 -0
  66. data/spec/dummy/config/initializers/mime_types.rb +5 -0
  67. data/spec/dummy/config/initializers/secret_token.rb +12 -0
  68. data/spec/dummy/config/initializers/session_store.rb +3 -0
  69. data/spec/dummy/config/initializers/wrap_parameters.rb +14 -0
  70. data/spec/dummy/config/locales/en.yml +23 -0
  71. data/spec/dummy/config/routes.rb +8 -0
  72. data/spec/dummy/config.ru +4 -0
  73. data/spec/dummy/db/schema.rb +27 -0
  74. data/spec/dummy/db/test.sqlite3 +0 -0
  75. data/spec/dummy/lib/assets/.keep +0 -0
  76. data/spec/dummy/log/.keep +0 -0
  77. data/spec/dummy/public/404.html +58 -0
  78. data/spec/dummy/public/422.html +58 -0
  79. data/spec/dummy/public/500.html +57 -0
  80. data/spec/dummy/public/favicon.ico +0 -0
  81. data/spec/lib/neighborly/balanced/creditcard/interface_spec.rb +37 -0
  82. data/spec/models/neighborly/balanced/creditcard/payment_spec.rb +223 -0
  83. data/spec/models/neighborly/balanced/creditcard/transaction_additional_fee_calculator_spec.rb +38 -0
  84. data/spec/models/neighborly/balanced/creditcard/transaction_inclusive_fee_calculator_spec.rb +19 -0
  85. data/spec/spec_helper.rb +15 -0
  86. metadata +252 -0
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 14effd0d0371b543d21fe4c045d35dd4109e1e40
4
+ data.tar.gz: 68ef4267ea6a24e978c7d318a348c859e95493fc
5
+ SHA512:
6
+ metadata.gz: a5dc95a5b2653b6351b5744446157b1812ecf94a98977980017eb24e266ac94fae07a46a91a2e51cc427218d7be8143642feb6b1a5abaeea133aa6e215644db9
7
+ data.tar.gz: c38c301ed8689a0b1701c2a3773e7478cf627ca8cc4776bb932cc76d28abc5142064f18898d229a1f0bb176f3c8a2b8720d293b400d21b8ab8591565116d1582
data/.gitignore ADDED
@@ -0,0 +1,20 @@
1
+ *.gem
2
+ *.log
3
+ *.rbc
4
+ .bundle
5
+ .config
6
+ .yardoc
7
+ Gemfile.lock
8
+ InstalledFiles
9
+ _yardoc
10
+ coverage
11
+ doc/
12
+ lib/bundler/man
13
+ pkg
14
+ rdoc
15
+ spec/reports
16
+ spec/dummy/db/*.sqlite3
17
+ test/tmp
18
+ test/version_tmp
19
+ tmp
20
+ spec/dummy/log/*.log
data/.rspec ADDED
@@ -0,0 +1,2 @@
1
+ --color
2
+ --format d
data/.travis.yml ADDED
@@ -0,0 +1,13 @@
1
+ rvm:
2
+ - 2.1.5
3
+
4
+ before_install: gem update --remote bundler
5
+
6
+ before_script:
7
+ - "bundle install"
8
+
9
+ script:
10
+ - "bundle exec rspec"
11
+
12
+ notifications:
13
+ webhooks: https://ci.neighbor.ly/projects/421aaf06-fc95-41a4-9677-701f9c809fc6/status
data/CHANGELOG.md ADDED
@@ -0,0 +1,5 @@
1
+ # CHANGELOG
2
+
3
+ ## 1.0.0
4
+
5
+ * First refactor from neighborly-balanced-creditcard
data/Gemfile ADDED
@@ -0,0 +1,6 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in dune-balanced-creditcard.gemspec
4
+ gemspec
5
+
6
+ gem 'dune-balanced', github: 'FromUte/dune-balanced', branch: :master
data/LICENSE.txt ADDED
@@ -0,0 +1,22 @@
1
+ Copyright (c) 2014 Legrand Pierre
2
+
3
+ MIT License
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining
6
+ a copy of this software and associated documentation files (the
7
+ "Software"), to deal in the Software without restriction, including
8
+ without limitation the rights to use, copy, modify, merge, publish,
9
+ distribute, sublicense, and/or sell copies of the Software, and to
10
+ permit persons to whom the Software is furnished to do so, subject to
11
+ the following conditions:
12
+
13
+ The above copyright notice and this permission notice shall be
14
+ included in all copies or substantial portions of the Software.
15
+
16
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,48 @@
1
+ # Dune::Balanced::Creditcard
2
+
3
+
4
+ ## What
5
+
6
+ This is an integration between [Balanced](https://www.balancedpayments.com/) and [dune-investissement](https://github.com/FromUte/dune-donate), a crowdfunding platform.
7
+
8
+ ## How
9
+
10
+ Include this gem as dependency of your project, adding the following line in your `Gemfile`.
11
+
12
+ ```ruby
13
+ # Gemfile
14
+ gem 'dune-balanced-creditcard'
15
+ ```
16
+
17
+ Dune::Balanced::Creditcard is a Rails Engine, integrating with your (dune-investissement) Rails application with very little of effort. To turn the engine on, mount it in an appropriate route:
18
+
19
+ ```ruby
20
+ # config/routes.rb
21
+ mount Dune::Balanced::Creditcard::Engine => '/balanced/creditcard/', as: :dune_balanced_creditcard
22
+ ```
23
+
24
+ And load our JavaScript:
25
+
26
+ ```coffeescript
27
+ //= require dune-balanced-creditcard
28
+ ```
29
+
30
+ ## Contributing
31
+
32
+ 1. Fork it
33
+ 2. Create your feature branch (`git checkout -b my-new-feature`)
34
+ 3. Commit your changes (`git commit -am 'Add some feature'`)
35
+ 4. Push to the branch (`git push origin my-new-feature`)
36
+ 5. Create new Pull Request
37
+
38
+ ### Running specs
39
+
40
+ We prize for our test suite and coverage, so it would be great if you could run the specs to ensure that your patch is not breaking the existing codebase.
41
+
42
+ ```
43
+ bundle exec rspec
44
+ ```
45
+
46
+ ## License
47
+
48
+ Licensed under the [MIT license](LICENSE.txt).
data/Rakefile ADDED
@@ -0,0 +1,34 @@
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
6
+
7
+ require 'rdoc/task'
8
+
9
+ RDoc::Task.new(:rdoc) do |rdoc|
10
+ rdoc.rdoc_dir = 'rdoc'
11
+ rdoc.title = 'Dune::Balanced::Creditcard'
12
+ rdoc.options << '--line-numbers'
13
+ rdoc.rdoc_files.include('README.rdoc')
14
+ rdoc.rdoc_files.include('lib/**/*.rb')
15
+ end
16
+
17
+ APP_RAKEFILE = File.expand_path("../spec/dummy/Rakefile", __FILE__)
18
+ load 'rails/tasks/engine.rake'
19
+
20
+
21
+
22
+ Bundler::GemHelper.install_tasks
23
+
24
+ require 'rake/testtask'
25
+
26
+ Rake::TestTask.new(:test) do |t|
27
+ t.libs << 'lib'
28
+ t.libs << 'test'
29
+ t.pattern = 'test/**/*_test.rb'
30
+ t.verbose = false
31
+ end
32
+
33
+
34
+ task default: :test
@@ -0,0 +1,15 @@
1
+ Dune.Dune ?= {}
2
+ Dune.Dune.Balanced ?= {}
3
+ Dune.Dune.Balanced.Creditcard ?= {}
4
+
5
+ Dune.Dune.Balanced.Creditcard.Flash =
6
+ message: (text)->
7
+ this.remove()
8
+ alertBox = $('<div>', { 'class': 'alert-box error text-center', 'html':
9
+ $('<h5>', { 'html': text })
10
+ } )
11
+ errorBoxWrapper = $('<div>', { 'class': 'error-box large-12 columns hide', 'html': alertBox}).insertBefore('.dune-balanced-creditcard-form .submit')
12
+ errorBoxWrapper.fadeIn(300)
13
+
14
+ remove: ->
15
+ $('.error-box').remove()
@@ -0,0 +1,86 @@
1
+ Dune.Dune ?= {}
2
+ Dune.Dune.Balanced ?= {}
3
+ Dune.Dune.Balanced.Creditcard ?= {}
4
+ Dune.Dune.Balanced.Creditcard.Payments ?= {}
5
+
6
+ Dune.Dune.Balanced.Creditcard.Payments.New = Backbone.View.extend
7
+ el: '.dune-balanced-creditcard-form'
8
+
9
+ initialize: ->
10
+ _.bindAll(this, 'submit', 'submitToBalanced', 'toggleAddNewCard', 'toggleSelected')
11
+ this.Flash = Dune.Dune.Balanced.Creditcard.Flash
12
+
13
+ $.getScript 'https://js.balancedpayments.com/1.1/balanced.js'
14
+
15
+ this.$button = this.$('input[type=submit]')
16
+ this.$('form').bind('submit', this.submit)
17
+ this.$('input[type=radio]').bind('change', this.toggleAddNewCard)
18
+ this.$('input[type=radio]').bind('change', this.toggleSelected)
19
+ this.toggleSelected()
20
+
21
+ submit: (event) ->
22
+ selectedCard = this.$('[name="payment[use_card]"]:checked, [name="payment[use_card]"]:hidden')
23
+ return if $.inArray(selectedCard.val(), ['new', '']) == -1
24
+
25
+ event.preventDefault()
26
+ this.submitToBalanced(selectedCard)
27
+ # This return is necessary because of jquery_ujs was disabling the submit
28
+ # button even when we enable it.
29
+ return false
30
+
31
+ submitToBalanced: (selectedCard) ->
32
+ that = this
33
+ $.rails.disableFormElements(that.$el)
34
+
35
+ creditCardData =
36
+ number: this.$('#payment_card_number').val()
37
+ expiration_month: this.$('#payment_expiration_month').val()
38
+ expiration_year: this.$('#payment_expiration_year').val()
39
+ cvv: this.$('#payment_security_code').val()
40
+ name: this.$('#payment_user_name').val()
41
+ address:
42
+ postal_code: this.$('#payment_user_address_zip_code').val()
43
+ country_code: 'USA'
44
+
45
+ balanced_callback_for_201 = (response) ->
46
+ selectedCard.val(response.cards[0].href)
47
+ that.$('[data-balanced-credit-card-input]').val('')
48
+ that.$('form').submit()
49
+ that.Flash.remove()
50
+
51
+ <% i18n_scope = 'dune.balanced.creditcard.payments.new.errors' %>
52
+
53
+ balanced_callback_for_400 = (response) ->
54
+ that.Flash.message('<%= I18n.t("#{i18n_scope}.invalid_card") %>')
55
+
56
+ balanced_callback_for_402 = (response) ->
57
+ that.Flash.message('<%= I18n.t("#{i18n_scope}.card_tokenization_error") %>')
58
+
59
+ balanced_callback_for_404 = (response) ->
60
+ that.Flash.message('<%= I18n.t("#{i18n_scope}.marketplace_uri") %>')
61
+
62
+ balanced_callback_for_500 = (response) ->
63
+ that.Flash.message('<%= I18n.t("#{i18n_scope}.balanced") %>')
64
+
65
+ balanced.card.create creditCardData, (response) ->
66
+ switch response.status_code
67
+ when 201 then balanced_callback_for_201(response)
68
+ when 400 then balanced_callback_for_400(response)
69
+ when 402 then balanced_callback_for_402(response)
70
+ when 404 then balanced_callback_for_404(response)
71
+ when 500 then balanced_callback_for_500(response)
72
+
73
+ if response.status != 201
74
+ $.rails.enableFormElements(that.$el)
75
+ $submit = that.$('input[type=submit]')
76
+ $submit.val($submit.data('enable-with'))
77
+
78
+ toggleSelected: ->
79
+ this.$('.card-box').removeClass('selected')
80
+ this.$('input[type=radio]:checked').parents('.card-box').addClass('selected')
81
+
82
+ toggleAddNewCard: ->
83
+ if this.$('#payment_use_card_new').is(':checked')
84
+ this.$('.add-new-creditcard-form').removeClass('hide')
85
+ else
86
+ this.$('.add-new-creditcard-form').addClass('hide')
@@ -0,0 +1 @@
1
+ //= require_tree .
@@ -0,0 +1,16 @@
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 vendor/assets/stylesheets of plugins, if any, 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 styles
10
+ * defined in the other CSS/SCSS files in this directory. It is generally better to create a new
11
+ * file per style scope.
12
+ *
13
+ *= require_tree .
14
+ *= require_self
15
+ */
16
+
@@ -0,0 +1,4 @@
1
+ module Dune::Balanced::Creditcard
2
+ class ApplicationController < ActionController::Base
3
+ end
4
+ end
@@ -0,0 +1,84 @@
1
+ module Dune::Balanced::Creditcard
2
+ class PaymentsController < ActionController::Base
3
+ before_filter :authenticate_user!
4
+
5
+ def new
6
+ @cards = customer.cards
7
+ end
8
+
9
+ def create
10
+ attach_card_to_customer
11
+ update_customer
12
+
13
+ payment = Payment.new('balanced-creditcard',
14
+ customer,
15
+ resource,
16
+ resource_params)
17
+ payment.checkout!
18
+ redirect_to(*checkout_response_params(resource, payment.successful?))
19
+ end
20
+
21
+ private
22
+ def resource
23
+ @resource ||= if params[:payment][:match_id].present?
24
+ Match.find(params[:payment].fetch(:match_id))
25
+ else
26
+ Contribution.find(params[:payment].fetch(:contribution_id))
27
+ end
28
+ end
29
+
30
+ def resource_name
31
+ resource.class.model_name.singular.to_sym
32
+ end
33
+
34
+ def checkout_response_params(resource, success)
35
+ status = success ? :succeeded : :failed
36
+ route_params = [resource.project.permalink, resource.id]
37
+
38
+ {
39
+ contribution: {
40
+ succeeded: [
41
+ main_app.project_contribution_path(*route_params)
42
+ ],
43
+ failed: [
44
+ main_app.edit_project_contribution_path(*route_params),
45
+ alert: t('.errors.default')
46
+ ]
47
+ },
48
+ match: {
49
+ succeeded: [
50
+ main_app.project_match_path(*route_params)
51
+ ],
52
+ failed: [
53
+ main_app.edit_project_match_path(*route_params),
54
+ alert: t('.errors.default')
55
+ ]
56
+ }
57
+ }.fetch(resource_name).fetch(status)
58
+ end
59
+
60
+ def resource_params
61
+ params.require(:payment).
62
+ permit(:contribution_id,
63
+ :match_id,
64
+ :use_card,
65
+ :pay_fee,
66
+ user: {})
67
+ end
68
+
69
+ def attach_card_to_customer
70
+ card = Balanced::Card.fetch(resource_params.fetch(:use_card))
71
+ unless customer.cards.to_a.any? { |c| c.id.eql? card.id }
72
+ card.associate_to_customer(customer)
73
+ end
74
+ end
75
+
76
+ def customer
77
+ @customer ||= Dune::Balanced::Customer.new(current_user, params).fetch
78
+ end
79
+
80
+ def update_customer
81
+ Dune::Balanced::Customer.new(current_user, params).update!
82
+ end
83
+ end
84
+ end
@@ -0,0 +1,94 @@
1
+ module Dune::Balanced::Creditcard
2
+ class Payment
3
+ attr_reader :engine_name, :customer, :resource, :attrs
4
+
5
+ def initialize(engine_name, customer, resource, attrs = {})
6
+ @engine_name = engine_name
7
+ @customer = customer
8
+ @resource = resource
9
+ @attrs = attrs
10
+ end
11
+
12
+ def checkout!
13
+ perform_debit!
14
+ resource.confirm!
15
+ rescue Balanced::PaymentRequired
16
+ resource.cancel!
17
+ ensure
18
+ resource.update_attributes(
19
+ payment_id: @debit.try(:id),
20
+ payment_method: engine_name,
21
+ payment_service_fee: fee_calculator.fees,
22
+ payment_service_fee_paid_by_user: attrs[:pay_fee]
23
+ )
24
+ update_meta(@debit) if @debit
25
+ end
26
+
27
+ def amount_in_cents
28
+ (fee_calculator.gross_amount * 100).round
29
+ end
30
+
31
+ def fee_calculator
32
+ @fee_calculator and return @fee_calculator
33
+
34
+ calculator_class = if ActiveRecord::ConnectionAdapters::Column::TRUE_VALUES.include? attrs[:pay_fee]
35
+ TransactionAdditionalFeeCalculator
36
+ else
37
+ TransactionInclusiveFeeCalculator
38
+ end
39
+
40
+ @fee_calculator = calculator_class.new(resource.value)
41
+ end
42
+
43
+ def debit
44
+ @debit.try(:sanitize)
45
+ end
46
+
47
+ def successful?
48
+ %w(pending succeeded).include? @debit.try(:status)
49
+ end
50
+
51
+ private
52
+
53
+ def perform_debit!
54
+ debit_params = {
55
+ amount: amount_in_cents,
56
+ appears_on_statement_as: ::Configuration[:balanced_appears_on_statement_as],
57
+ description: debit_description,
58
+ meta: meta,
59
+ source: card
60
+ }
61
+
62
+ order = Dune::Balanced::OrderProxy.new(resource.project)
63
+ @debit = order.debit_from(debit_params)
64
+ end
65
+
66
+ def card
67
+ Balanced::Card.fetch(attrs.fetch(:use_card))
68
+ end
69
+
70
+ def update_meta(debit)
71
+ debit.meta = meta
72
+ debit.save
73
+ end
74
+
75
+ def resource_name
76
+ resource.class.model_name.singular
77
+ end
78
+
79
+ def debit_description
80
+ I18n.t('description',
81
+ project_name: resource.try(:project).try(:name),
82
+ scope: "dune.balanced.creditcard.payments.debit.#{resource_name}")
83
+ end
84
+
85
+ def project_owner_customer
86
+ @project_owner_customer ||= Dune::Balanced::Customer.new(
87
+ resource.project.user, {}).fetch
88
+ end
89
+
90
+ def meta
91
+ PayableResourceSerializer.new(resource).to_json
92
+ end
93
+ end
94
+ end
@@ -0,0 +1,12 @@
1
+ require 'float_extensions'
2
+
3
+ module Dune::Balanced::Creditcard
4
+ class TransactionAdditionalFeeCalculator < TransactionFeeCalculatorBase
5
+ using FloatExtensions
6
+
7
+ def net_amount
8
+ transaction_value.to_f.floor_with_two_decimal_places
9
+ end
10
+ end
11
+ end
12
+
@@ -0,0 +1,31 @@
1
+ require 'float_extensions'
2
+
3
+ module Dune::Balanced::Creditcard
4
+ class TransactionFeeCalculatorBase
5
+ using FloatExtensions
6
+
7
+ attr_writer :transaction_value
8
+
9
+ def initialize(transaction_value)
10
+ @transaction_value = transaction_value
11
+ end
12
+
13
+ def transaction_value
14
+ @transaction_value.to_f.floor_with_two_decimal_places
15
+ end
16
+
17
+ def gross_amount
18
+ net_amount + fees
19
+ end
20
+
21
+ def net_amount
22
+ raise NotImplementedError
23
+ end
24
+
25
+ # Base calculation of fees
26
+ # 2.9% + 30¢
27
+ def fees
28
+ (net_amount * 0.029 + 0.3).ceil_with_two_decimal_places
29
+ end
30
+ end
31
+ end
@@ -0,0 +1,13 @@
1
+ require 'float_extensions'
2
+
3
+ module Dune::Balanced::Creditcard
4
+ class TransactionInclusiveFeeCalculator < TransactionFeeCalculatorBase
5
+ using FloatExtensions
6
+
7
+ # Base calculation of fees
8
+ # 2.9% + 30¢
9
+ def net_amount
10
+ ((transaction_value - 0.3) / 1.029).floor_with_two_decimal_places
11
+ end
12
+ end
13
+ end
File without changes
@@ -0,0 +1,98 @@
1
+ = initjs_tag app_name: 'Dune', partial: true
2
+
3
+ .dune-balanced-creditcard-form[data-balanced-credit-card-form]
4
+ = simple_form_for :payment, url: payments_path, html: { novalidate: '' } do |f|
5
+ - if params[:match_id].present?
6
+ = f.input :match_id, as: :hidden, input_html: { value: params[:match_id] }
7
+ - else
8
+ = f.input :contribution_id, as: :hidden, input_html: { value: params[:contribution_id] }
9
+
10
+ = f.input :pay_fee, as: :hidden, input_html: { value: 1, 'data-pay-payment-fee' => '' }
11
+ section.highlighted[class="#{'use-existing-item' if @cards.any?}"]
12
+ - if @cards.any?
13
+ section.use-existing-item.row
14
+ .large-12.columns.title
15
+ h4 = t('.cards.title')
16
+
17
+ - @cards.reverse_each.with_index do |card,index|
18
+ .large-12.columns
19
+ .card-box
20
+ label.row
21
+ dl
22
+ .large-1.columns
23
+ = f.radio_button :use_card, card.href, { checked: index.zero?, label: false }
24
+ .large-6.columns
25
+ dt.hide
26
+ dd = t('.cards.card_ending_in', brand: card.brand, number: card.number)
27
+ .large-5.columns.expiration
28
+ dt = t('.cards.expiration')
29
+ dd = sprintf('%02i/%i', card.expiration_month, card.expiration_year)
30
+
31
+ - else
32
+ = f.input :use_card, as: :hidden
33
+
34
+ .row
35
+ .large-12.columns.title
36
+ h4 = t('.card.title')
37
+
38
+
39
+ section.row
40
+ .large-12.columns
41
+ .card-box[class="#{'new-card' unless @cards.any?}"]
42
+ .row
43
+ - if @cards.any?
44
+ label
45
+ .large-1.columns
46
+ = f.radio_button :use_card, 'new', { checked: false, label: false }
47
+ .large-8.columns
48
+ = t('.add_new_card')
49
+ .large-3.columns.expiration
50
+
51
+ .large-12.columns.add-new-creditcard-form[class="#{'hide with-others-cards' if @cards.any?}"]
52
+ .row
53
+ .large-5.columns
54
+ = f.input :card_number, input_html: { 'data-balanced-credit-card-input' => '' }
55
+ .large-2.columns
56
+ = f.input :security_code, maxlength: 4, input_html: { 'data-balanced-credit-card-input' => '' }
57
+ .large-5.columns
58
+ - date = Date.today + 1.month
59
+ = f.label :expiration
60
+ .row.collapse
61
+ .large-5.small-5.columns
62
+ = select_month date, { use_two_digit_numbers: true }, { name: 'payment[expiration_month]', id: 'payment_expiration_month', 'data-balanced-credit-card-input' => '' }
63
+ .large-1.small-1.columns.text-center.divider
64
+ | /
65
+ .large-6.small-6.columns
66
+ = select_year date, { start_year: date.year, end_year: date.year+15 }, { name: 'payment[expiration_year]', id: 'payment_expiration_year', 'data-balanced-credit-card-input' => '' }
67
+
68
+ section.user-informations.highlighted
69
+ = f.simple_fields_for :user do |fu|
70
+ .row
71
+ .large-12.columns.title
72
+ h4 = t('.billing.title')
73
+
74
+ .row
75
+ .large-6.columns
76
+ = fu.input :name, required: false, input_html: { value: @customer.name }
77
+ .large-6.columns
78
+ = fu.input :address_street, required: false, input_html: { value: @customer.address.try(:[], :line1) }
79
+ .row
80
+ .large-5.columns
81
+ = fu.input :address_city, required: false, input_html: { value: @customer.address.try(:[], :city) }
82
+ .large-4.columns
83
+ = fu.input :address_state, required: false, as: :select, collection: State.array, selected: @customer.address.try(:[], :state), include_blank: false
84
+ .large-3.columns
85
+ = fu.input :address_zip_code, input_html: { value: @customer.address.try(:[], :postal_code) }
86
+
87
+ section
88
+ .row
89
+ .large-12.columns.terms
90
+ = t('.terms', link: link_to(t('.terms-link'), main_app.terms_path(), data: { 'reveal-id' => 'terms-modal', 'reveal-ajax' => true })).html_safe
91
+
92
+ .row
93
+ .large-6.columns.submit
94
+ = f.button :submit, t('.confirm'), data: { disable_with: t('.proccessing'), enable_with: t('.confirm') }
95
+ .large-6.columns.text-right.balanced-seal
96
+ = link_to image_tag('https://balancedpowered.s3.amazonaws.com/secured-1-4.png'), 'https://www.balancedpayments.com/', target: :blank
97
+
98
+ #terms-modal.reveal-modal.small.fixed
data/bin/rails ADDED
@@ -0,0 +1,8 @@
1
+ #!/usr/bin/env ruby
2
+ # This command will automatically be run when you run "rails" with Rails 4 gems installed from the root of your application.
3
+
4
+ ENGINE_ROOT = File.expand_path('../..', __FILE__)
5
+ ENGINE_PATH = File.expand_path('../../lib/dune/balanced/creditcard/engine', __FILE__)
6
+
7
+ require 'rails/all'
8
+ require 'rails/engine/commands'
@@ -0,0 +1,5 @@
1
+ begin
2
+ PaymentEngine.new(Dune::Balanced::Creditcard::Interface.new).save
3
+ rescue Exception => e
4
+ puts "Error while registering payment engine: #{e}"
5
+ end