-
Notifications
You must be signed in to change notification settings - Fork 147
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
21 changed files
with
1,105 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,7 @@ | ||
.bundle/ | ||
log/*.log | ||
pkg/ | ||
test/dummy/db/*.sqlite3 | ||
test/dummy/log/*.log | ||
test/dummy/tmp/ | ||
test/dummy/.sass-cache |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,6 @@ | ||
source "http://rubygems.org" | ||
|
||
# Declare your gem's dependencies in foodsoft_mollie.gemspec. | ||
# Bundler will treat runtime dependencies like base dependencies, and | ||
# development dependencies will be added by default to the :development group. | ||
gemspec |
Large diffs are not rendered by default.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,37 @@ | ||
FoodsoftMollie | ||
============== | ||
|
||
This project adds support for iDEAL payments using Mollie to Foodsoft. | ||
|
||
* Make sure the gem is uncommented in foodsoft's `Gemfile` | ||
* Enter your Mollie account details in `config/app_config.yml` | ||
|
||
```yaml | ||
# Mollie payment settings | ||
mollie: | ||
# API key for account: 1234567, website profile: FooInc | ||
api_key: test_1234567890abcdef1234567890abcd | ||
# Transaction fee per payment method, fixed rate and/or percentage. | ||
# This is substracted from the amount actually credited to the ordergroup's account balance. | ||
fee: | ||
# example fees from May 2014 incl. 21% VAT (verify before using!) | ||
ideal: 1.20 | ||
banktransfer: 0.30 | ||
creditcard: 3.39% + 0.05 | ||
paypal: 0.18 + 0.35 + 3.4% | ||
``` | ||
The transaction fee is sub will be added on each payment when set; it is not set by default, | ||
meaning that the foodcoop will pay any transaction costs (out of the margin). | ||
To initiate a payment, redirect to `new_payments_mollie_path` at `/:foodcoop/payments/mollie/new`. | ||
The following url parameters are recognised: | ||
* ''amount'' - default amount to charge (optional) | ||
* ''fixed'' - when "true", the amount cannot be changed (optional) | ||
* ''title'' - page title (optional) | ||
* ''label'' - label for amount (optional) | ||
* ''min'' - minimum amount accepted (optional) | ||
|
||
This plugin also introduces the foodcoop config option `use_mollie`, which can | ||
be set to `false` to disable this plugin's functionality. May be useful in | ||
multicoop deployments. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,26 @@ | ||
#!/usr/bin/env rake | ||
begin | ||
require 'bundler/setup' | ||
rescue LoadError | ||
puts 'You must `gem install bundler` and `bundle install` to run rake tasks' | ||
end | ||
begin | ||
require 'rdoc/task' | ||
rescue LoadError | ||
require 'rdoc/rdoc' | ||
require 'rake/rdoctask' | ||
RDoc::Task = Rake::RDocTask | ||
end | ||
|
||
RDoc::Task.new(:rdoc) do |rdoc| | ||
rdoc.rdoc_dir = 'rdoc' | ||
rdoc.title = 'FoodsoftMollie' | ||
rdoc.options << '--line-numbers' | ||
rdoc.rdoc_files.include('README.rdoc') | ||
rdoc.rdoc_files.include('lib/**/*.rb') | ||
end | ||
|
||
# APP_RAKEFILE = File.expand_path("../../../Rakefile", __FILE__) | ||
# load 'rails/tasks/engine.rake' | ||
|
||
Bundler::GemHelper.install_tasks |
160 changes: 160 additions & 0 deletions
160
plugins/mollie/app/controllers/payments/mollie_ideal_controller.rb
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,160 @@ | ||
# Mollie payment page | ||
class Payments::MollieIdealController < ApplicationController | ||
before_action -> { require_plugin_enabled FoodsoftMollie } | ||
skip_before_action :authenticate, :only => [:check] | ||
skip_before_action :verify_authenticity_token, :only => [:check] | ||
before_action :accept_return_to, only: [:new] | ||
before_action :ordergroup, only: [:new, :create, :result] | ||
before_action :transaction, only: [:result] | ||
before_action :configure_api_key | ||
|
||
def new | ||
@amount = (params[:amount] or [10, -@ordergroup.get_available_funds].max) | ||
@amount = [params[:min], params[:amount]].max if params[:min] | ||
end | ||
|
||
def create | ||
# store parameters so we can redirect to original form on problems | ||
session[:mollie_params] = params.select { |k, _| %w[amount label title fixed min text].include?(k) }.to_h | ||
|
||
amount = params[:amount].to_f | ||
amount = [params[:min].to_f, amount].max if params[:min] | ||
|
||
redirect_to new_payments_mollie_path(session[:mollie_params]), alert: t('.invalid_amount') and return if amount <= 0 | ||
|
||
ft_type = FinancialTransactionType.find_by_id(FoodsoftConfig[:mollie][:financial_transaction_type]) || FinancialTransactionType.first | ||
|
||
@transaction = FinancialTransaction.create!( | ||
amount: nil, | ||
ordergroup: @ordergroup, | ||
user: @current_user, | ||
payment_plugin: 'mollie', | ||
payment_amount: amount, | ||
# @todo payment_currency | ||
payment_state: 'created', | ||
financial_transaction_type_id: ft_type.id, | ||
note: t('.controller.transaction_note', method: nil) | ||
) | ||
|
||
payment = Mollie::Payment.create( | ||
amount: { | ||
value: format('%.2f', amount), | ||
currency: 'EUR' # @todo payment_currency | ||
}, | ||
description: "#{@transaction.id}, #{@ordergroup.id}, #{FoodsoftConfig[:name]}", | ||
redirectUrl: result_payments_mollie_url(id: @transaction.id), | ||
webhookUrl: (request.local? ? check_payments_mollie_url : 'https://example.com'), # Mollie doesn't accept localhost here | ||
metadata: { | ||
scope: FoodsoftConfig.scope, | ||
transaction_id: @transaction.id, | ||
user: @current_user.id, | ||
ordergroup: @ordergroup.id | ||
} | ||
) | ||
@transaction.update payment_id: payment.id, payment_state: 'pending' | ||
|
||
logger.info "Mollie start: #{amount} for ##{@current_user.id} (#{@current_user.display})" | ||
|
||
redirect_to payment.checkout_url, allow_other_host: true | ||
rescue Mollie::Exception => e | ||
Rails.logger.info "Mollie create warning: #{e}" | ||
redirect_to new_payments_mollie_path(session[:mollie_params]), :alert => t('errors.general_msg', msg: e.message) | ||
end | ||
|
||
# Endpoint that Mollie calls when a payment status changes. | ||
def check | ||
logger.info "Mollie check: #{params[:id]}" | ||
@transaction = FinancialTransaction.find_by_payment_plugin_and_payment_id!('mollie', params[:id]) | ||
logger.debug " financial transaction: #{@transaction.inspect}" | ||
render plain: update_transaction(@transaction) | ||
rescue StandardError => e | ||
Rails.logger.error "Mollie check error: #{e}" | ||
render plain: "Error: #{e.message}" | ||
end | ||
|
||
# User is redirect here after payment | ||
def result | ||
update_transaction @transaction # @todo if request.local? # so localhost works too | ||
logger.info "Mollie result: transaction #{@transaction.id} (#{@transaction.payment_id}) is #{@transaction.payment_state}" | ||
case @transaction.payment_state | ||
when 'paid' | ||
redirect_to_return_or root_path, :notice => t('.controller.result.notice', amount: @transaction.amount, fee: @transaction.payment_fee) | ||
when 'pending' | ||
redirect_to_return_or root_path, :notice => t('.controller.result.wait') | ||
else | ||
pms = { foodcoop: FoodsoftConfig.scope }.merge((session[:mollie_params] or {})) | ||
session[:mollie_params] = nil | ||
redirect_to new_payments_mollie_path(pms), :alert => t('.controller.result.failed') | ||
end | ||
end | ||
|
||
def cancel | ||
redirect_to_return_or root_path | ||
end | ||
|
||
protected | ||
|
||
def ordergroup | ||
@ordergroup = current_user.ordergroup | ||
redirect_to root_path, alert: t('.no_ordergroup') and return if @ordergroup.nil? | ||
end | ||
|
||
def transaction | ||
@transaction = @ordergroup.financial_transactions.find(params[:id]) | ||
end | ||
|
||
# @todo move this to ApplicationController, use it in SessionController too | ||
# @todo use a stack of return_to urls | ||
def accept_return_to | ||
session[:return_to] = nil # or else an unfollowed previous return_to may interfere | ||
return if params[:return_to].blank? | ||
|
||
return unless params[:return_to].starts_with?(root_path) || params[:return_to].starts_with?(root_url) | ||
|
||
session[:return_to] = params[:return_to] | ||
end | ||
|
||
def redirect_to_return_or(fallback_url, options = {}) | ||
if session[:return_to].present? | ||
redirect_to_url = session[:return_to] | ||
session[:return_to] = nil | ||
else | ||
redirect_to_url = fallback_url | ||
end | ||
redirect_to redirect_to_url, options | ||
end | ||
|
||
# Query Mollie status and update financial transaction | ||
def update_transaction(transaction) | ||
payment = Mollie::Payment.get transaction.payment_id | ||
logger.debug "Mollie update_transaction: #{payment.inspect}" | ||
update_transaction_details(transaction, payment) | ||
update_transaction_amount(transaction, payment) | ||
payment.status | ||
end | ||
|
||
def update_transaction_amount(transaction, payment) | ||
if payment.status == 'paid' | ||
payment_fee = FoodsoftMollie.payment_fee payment.amount.value, transaction.payment_method | ||
amount = payment.amount.value.to_f - payment_fee.to_f | ||
end | ||
transaction.update payment_state: payment.status, amount: amount || 0, payment_fee: payment_fee || nil | ||
end | ||
|
||
def update_transaction_details(transaction, payment) | ||
if payment.details | ||
transaction.payment_acct_number = payment.details.consumerAccount | ||
transaction.payment_acct_name = payment.details.consumerName | ||
end | ||
transaction.payment_method = payment.method | ||
transaction.note = t('.controller.transaction_note', method: payment.method) | ||
end | ||
|
||
private | ||
|
||
def configure_api_key | ||
Mollie::Client.configure do |config| | ||
config.api_key = FoodsoftConfig[:mollie]['api_key'] | ||
end | ||
end | ||
end |
12 changes: 12 additions & 0 deletions
12
plugins/mollie/app/overrides/admin/configs/_tab_others/add_config.html.haml.deface
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,12 @@ | ||
/ insert_after 'erb:contains(":webstats_tracking_code")' | ||
%h4= 'Mollie' | ||
= config_input form, :use_mollie, as: :boolean | ||
= form.fields_for :mollie do |fields| | ||
= config_input fields, :api_key, input_html: {class: 'input-xlarge'} | ||
= config_input fields, :financial_transaction_type, :as => :select, :collection => FinancialTransactionType.order(:name).map { |t| [ t.name, t.id ] } | ||
%h5= 'Fee' | ||
= fields.fields_for :fee do |fields| | ||
= config_input fields, :ideal, input_html: {class: 'input-xlarge'} | ||
= config_input fields, :banktransfer, input_html: {class: 'input-xlarge'} | ||
= config_input fields, :creditcard, input_html: {class: 'input-xlarge'} | ||
= config_input fields, :paypal, input_html: {class: 'input-xlarge'} |
4 changes: 4 additions & 0 deletions
4
plugins/mollie/app/overrides/home/index/new_payment_link.html.haml.deface
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,4 @@ | ||
/ insert_after 'erb[silent]:contains("<dashboard_ordergroup_mark>")' | ||
= link_to new_payments_mollie_path do | ||
= t '.credit_your_account' | ||
%i.icon.icon-chevron-right |
2 changes: 2 additions & 0 deletions
2
plugins/mollie/app/overrides/home/ordergroup/new_payment_button.html.haml.deface
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,2 @@ | ||
/ insert_after 'erb[silent]:contains("<home_ordergroup_well_mark>")' | ||
= link_to t('.credit_your_account'), new_payments_mollie_path, class: 'btn btn-secondary' |
60 changes: 60 additions & 0 deletions
60
plugins/mollie/app/views/payments/mollie_ideal/_form.html.haml
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,60 @@ | ||
- content_for :javascript do | ||
:javascript | ||
// @todo code duplication of foodsoft_mollie.rb | ||
function paymentFee(amount, feeSpec) { | ||
if (typeof feeSpec === 'number') { | ||
return feeSpec; | ||
} | ||
|
||
return feeSpec.split('+').reduce((sum, c) => { | ||
const parsed = c.trim().match(/^(.*)\s*%\s*$/); | ||
if (parsed) { | ||
return sum + (parseFloat(parsed[1]) / 100 * parseFloat(amount)); | ||
} else { | ||
return sum + parseFloat(c); | ||
} | ||
}, 0).toFixed(2); | ||
} | ||
|
||
function handleInputAmount(){ | ||
var amount = parseFloat($('#amount').val()); | ||
var isError = false; | ||
$('#fee_list').children('#fee').each(function(){ | ||
var fee = $(this).data('fee'); | ||
if (amount){ | ||
$(this).text(I18n.l("currency", paymentFee(amount, fee))); | ||
} else { | ||
$(this).text(fee); | ||
} | ||
}); | ||
} | ||
|
||
$('#amount').on('keyup', handleInputAmount); | ||
$(document).ready(handleInputAmount); | ||
|
||
%h5= t '.fee' | ||
%dl.dl-horizontal#fee_list | ||
- FoodsoftConfig[:mollie][:fee].each do |k, v| | ||
%dt= k | ||
%dd{id: "fee", data: { fee: v}}" | ||
= form_tag payments_mollie_path, method: :post do | ||
- if params[:text] | ||
.well= params[:text] | ||
.control-group | ||
.control-label | ||
= label_tag 'amount', ((params[:label] or t('.amount_pay'))) | ||
.controls | ||
.input-prepend | ||
%span.add-on= t 'number.currency.format.unit' | ||
= text_field_tag 'amount', @amount, readonly: (params[:fixed]=='true'), class: 'input-mini' | ||
- if params[:min] | ||
.help-inline{style: 'margin-bottom: 10px'} | ||
= "(min #{number_to_currency params[:min], precision: 0})" | ||
.control-group | ||
.controls | ||
= submit_tag t('.submit') | ||
= link_to t('ui.or_cancel'), cancel_payments_mollie_path | ||
|
||
-# pass through options to allow reusing on error | ||
- %w(label title fixed min text).each do |k| | ||
= hidden_field_tag k, params[k] if params[k] |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,2 @@ | ||
- title (params[:title] or t('.title')) | ||
= render :partial => 'form' |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,35 @@ | ||
en: | ||
activerecord: | ||
attributes: | ||
home: | ||
credit_your_account: 'Credit your Account' | ||
payments: | ||
mollie_ideal: | ||
new: | ||
title: 'Credit your account' | ||
no_ordergroup: 'You need to be member of an ordergroup' | ||
create: | ||
invalid_amount: 'Invalid amount' | ||
form: | ||
amount_pay: 'Amount to pay' | ||
method: 'Pay using' | ||
submit: 'Pay at your bank' | ||
financial_transaction_type: 'Financial Transaction Type' | ||
fee: 'The transaction fee depends on your payment method' | ||
controller: | ||
result: | ||
notice: 'Your account was credited %{amount} (transaction fee of %{fee}).' | ||
failed: 'Payment failed.' | ||
wait: 'Your account will be credited when the payment is received.' | ||
transaction_note: '%{method} payment' | ||
config: | ||
keys: | ||
use_mollie: 'Use Mollie' | ||
mollie: | ||
api_key: 'API key' | ||
financial_transaction_type: 'Transaction type' | ||
fee: | ||
ideal: 'Ideal' | ||
banktransfer: 'banktransfer' | ||
creditcard: 'creditcard' | ||
paypal: 'paypal' |
Oops, something went wrong.