From 90a324bd62ca5a5376182b64d5595f31f0235aeb Mon Sep 17 00:00:00 2001 From: Sem van Nieuwenhuizen Date: Tue, 24 Sep 2024 21:22:48 +0200 Subject: [PATCH 1/7] feat: update to mollie v3 api --- Gemfile | 3 ++ Gemfile.lock | 2 ++ app/models/payment.rb | 74 ++++++++++++++++--------------------------- config/application.rb | 5 +++ gemset.nix | 10 ++++++ sample.env | 2 -- 6 files changed, 47 insertions(+), 49 deletions(-) diff --git a/Gemfile b/Gemfile index 34c26d262..5fff1dbdd 100644 --- a/Gemfile +++ b/Gemfile @@ -27,6 +27,9 @@ gem 'impressionist', github: 'charlotte-ruby/impressionist' # rests calls for mailgun gem 'rest-client' +# mollie +gem 'mollie-api-ruby' + gem 'responders' # pagination diff --git a/Gemfile.lock b/Gemfile.lock index 679b14960..8f2b3933a 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -179,6 +179,7 @@ GEM mini_mime (1.1.2) mini_portile2 (2.7.1) minitest (5.15.0) + mollie-api-ruby (4.13.0) netrc (0.11.0) nio4r (2.5.8) nokogiri (1.13.1) @@ -352,6 +353,7 @@ DEPENDENCIES impressionist! listen mimemagic (= 0.3.9) + mollie-api-ruby pagy pg pg_search diff --git a/app/models/payment.rb b/app/models/payment.rb index 4ea4ad10f..e4b817793 100644 --- a/app/models/payment.rb +++ b/app/models/payment.rb @@ -1,7 +1,5 @@ #:nodoc: class Payment < ApplicationRecord - require 'request' - self.primary_key = :token attr_accessor :issuer, :payment_uri, :message @@ -12,6 +10,7 @@ class Payment < ApplicationRecord validates :payment_type, presence: true enum status: { failed: 0, in_progress: 1, successful: 2 } + # Keep payconiq_online because it is still present in the database enum payment_type: { ideal: 0, payconiq_online: 1, pin: 3 } enum transaction_type: { checkout: 0, activity: 1 } @@ -26,6 +25,7 @@ class Payment < ApplicationRecord after_validation :request_payment, on: :create include PgSearch::Model + pg_search_scope :search_by_name, against: [:trxid], associated_against: { @@ -47,38 +47,26 @@ def request_payment case payment_type.to_sym when :ideal - http = ConstipatedKoala::Request.new(ENV['MOLLIE_DOMAIN']) self.token = Digest::SHA256.hexdigest("#{ member.id }#{ Time.now.to_f }#{ redirect_uri }") webhook_url = if Rails.env.development? - "#{ ENV['NGROK_HOST'] }/api/hook/mollie" - else - Rails.application.routes.url_helpers.mollie_hook_url - end - - request = http.post("/#{ ENV['MOLLIE_VERSION'] }/payments", - amount: amount, - description: description, - - method: 'ideal', - issuer: issuer, - - metadata: { - member: member.name, - transaction_type: transaction_type, - transaction_id: transaction_id - - }, - webhookUrl: webhook_url, - redirectUrl: Rails.application.routes.url_helpers.payment_redirect_url(token: token)) + "#{ ENV['NGROK_HOST'] }/api/hook/mollie" + else + Rails.application.routes.url_helpers.mollie_hook_url + end - request['Authorization'] = "Bearer #{ ENV['MOLLIE_TOKEN'] }" - response = http.send!(request) + payment = Mollie::Payment.create( + amount: { value: amount.to_s, currency: 'EUR' }, + description: description, + webhookUrl: webhook_url, + redirectUrl: Rails.application.routes.url_helpers.payment_redirect_url(token: token), + ) - self.trxid = response.id - self.payment_uri = response.links.paymentUrl + self.trxid = payment.id + self.payment_uri = payment._links['checkout']['href'] self.status = :in_progress - # pin payment shouldn't have any extra work + + # pin payment shouldn't have any extra work when :pin end end @@ -86,15 +74,11 @@ def request_payment def update_transaction! case payment_type.to_sym when :ideal - http = ConstipatedKoala::Request.new(ENV['MOLLIE_DOMAIN']) @status = status - request = http.get("/#{ ENV['MOLLIE_VERSION'] }/payments/#{ trxid }") - request['Authorization'] = "Bearer #{ ENV['MOLLIE_TOKEN'] }" - - response = http.send!(request) + payment = Mollie::Payment.get(trxid) - status_update(response.status) + status_update(payment.status) save! @@ -161,13 +145,9 @@ def self.ideal_issuers return [] if ENV['MOLLIE_TOKEN'].blank? Rails.cache.fetch('mollie_issuers', expires_in: 12.hours) do - http = ConstipatedKoala::Request.new(ENV['MOLLIE_DOMAIN']) + method = Mollie::Method.get('ideal', include: 'issuers') - request = http.get("/#{ ENV['MOLLIE_VERSION'] }/issuers") - request['Authorization'] = "Bearer #{ ENV['MOLLIE_TOKEN'] }" - - response = http.send!(request) - response.data.map { |issuer| [issuer.name, issuer.id] } + method.issuers.map { |issuer| [issuer["name"], issuer["id"]] } end end @@ -179,12 +159,12 @@ def activities def status_update(new_status) self.status = case new_status.downcase - when "succeeded", "paid" - :successful - when "expired", "canceled", "failed", "cancelled", "authorization_failed" - :failed - else - :in_progress - end + when "succeeded", "paid" + :successful + when "expired", "canceled", "failed", "cancelled", "authorization_failed" + :failed + else + :in_progress + end end end diff --git a/config/application.rb b/config/application.rb index 46a103944..ba0381127 100644 --- a/config/application.rb +++ b/config/application.rb @@ -75,3 +75,8 @@ class Application < Rails::Application config.middleware.use(I18n::JS::Middleware) end end + +# Mollie configuration +Mollie::Client.configure do |config| + config.api_key = ENV['MOLLIE_TOKEN'] +end diff --git a/gemset.nix b/gemset.nix index 9de9c6cf0..25b4447d8 100644 --- a/gemset.nix +++ b/gemset.nix @@ -713,6 +713,16 @@ }; version = "5.15.0"; }; + mollie-api-ruby = { + groups = ["default"]; + platforms = []; + source = { + remotes = ["https://rubygems.org"]; + sha256 = "0z4z0cf5lq3bmdbjsdzjj2spvg351b32nzwrn9rf3zqm9rldai6w"; + type = "gem"; + }; + version = "4.13.0"; + }; netrc = { groups = ["default"]; platforms = []; diff --git a/sample.env b/sample.env index abeb5472b..d5afb53aa 100644 --- a/sample.env +++ b/sample.env @@ -76,8 +76,6 @@ MAILCHIMP_TEACHER_ID= NGROK_HOST=http # MOLLIE credentials for the iDEAL integration. -MOLLIE_DOMAIN=https://api.mollie.nl -MOLLIE_VERSION=v1 MOLLIE_TOKEN= # Secret for error reporting. From 5f6c30a42f414f37e5eb11018e5eb95bc3910687 Mon Sep 17 00:00:00 2001 From: Sem van Nieuwenhuizen Date: Tue, 24 Sep 2024 21:30:47 +0200 Subject: [PATCH 2/7] chore: run linter --- app/models/payment.rb | 28 ++++++++++++++-------------- 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/app/models/payment.rb b/app/models/payment.rb index e4b817793..502ce9891 100644 --- a/app/models/payment.rb +++ b/app/models/payment.rb @@ -10,7 +10,7 @@ class Payment < ApplicationRecord validates :payment_type, presence: true enum status: { failed: 0, in_progress: 1, successful: 2 } - + # Keep payconiq_online because it is still present in the database enum payment_type: { ideal: 0, payconiq_online: 1, pin: 3 } enum transaction_type: { checkout: 0, activity: 1 } @@ -50,22 +50,22 @@ def request_payment self.token = Digest::SHA256.hexdigest("#{ member.id }#{ Time.now.to_f }#{ redirect_uri }") webhook_url = if Rails.env.development? - "#{ ENV['NGROK_HOST'] }/api/hook/mollie" - else - Rails.application.routes.url_helpers.mollie_hook_url - end + "#{ ENV['NGROK_HOST'] }/api/hook/mollie" + else + Rails.application.routes.url_helpers.mollie_hook_url + end payment = Mollie::Payment.create( amount: { value: amount.to_s, currency: 'EUR' }, description: description, webhookUrl: webhook_url, - redirectUrl: Rails.application.routes.url_helpers.payment_redirect_url(token: token), + redirectUrl: Rails.application.routes.url_helpers.payment_redirect_url(token: token) ) self.trxid = payment.id self.payment_uri = payment._links['checkout']['href'] self.status = :in_progress - + # pin payment shouldn't have any extra work when :pin end @@ -159,12 +159,12 @@ def activities def status_update(new_status) self.status = case new_status.downcase - when "succeeded", "paid" - :successful - when "expired", "canceled", "failed", "cancelled", "authorization_failed" - :failed - else - :in_progress - end + when "succeeded", "paid" + :successful + when "expired", "canceled", "failed", "cancelled", "authorization_failed" + :failed + else + :in_progress + end end end From 0e3f5c8c2a04dfde57b9bfcf1a8eacd9d8ecd75d Mon Sep 17 00:00:00 2001 From: Sem van Nieuwenhuizen Date: Mon, 16 Dec 2024 19:41:40 +0100 Subject: [PATCH 3/7] fix: add ideal as method so we return to Koala on failure --- app/models/payment.rb | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/app/models/payment.rb b/app/models/payment.rb index 502ce9891..a1a4679e5 100644 --- a/app/models/payment.rb +++ b/app/models/payment.rb @@ -54,12 +54,15 @@ def request_payment else Rails.application.routes.url_helpers.mollie_hook_url end + redirect_url = Rails.application.routes.url_helpers.payment_redirect_url(token: token) payment = Mollie::Payment.create( - amount: { value: amount.to_s, currency: 'EUR' }, + amount: { value: "#{'%.2f' % amount}", currency: 'EUR' }, + method: 'ideal', # only ideal for now + issuer: issuer, description: description, - webhookUrl: webhook_url, - redirectUrl: Rails.application.routes.url_helpers.payment_redirect_url(token: token) + webhook_url: webhook_url, + redirect_url: redirect_url, ) self.trxid = payment.id @@ -158,10 +161,10 @@ def activities private def status_update(new_status) - self.status = case new_status.downcase - when "succeeded", "paid" + self.status = case new_status + when "paid", "authorized" :successful - when "expired", "canceled", "failed", "cancelled", "authorization_failed" + when "expired", "failed", "canceled" :failed else :in_progress From 490ec799d8514858c9d0fe97c92fe79e388c254f Mon Sep 17 00:00:00 2001 From: Sem van Nieuwenhuizen Date: Mon, 16 Dec 2024 19:52:04 +0100 Subject: [PATCH 4/7] =?UTF-8?q?chore:=20linter=20=E2=9C=A8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/models/payment.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/models/payment.rb b/app/models/payment.rb index a1a4679e5..d94d254bb 100644 --- a/app/models/payment.rb +++ b/app/models/payment.rb @@ -57,7 +57,7 @@ def request_payment redirect_url = Rails.application.routes.url_helpers.payment_redirect_url(token: token) payment = Mollie::Payment.create( - amount: { value: "#{'%.2f' % amount}", currency: 'EUR' }, + amount: { value: sprintf('%.2f', amount), currency: 'EUR' }, method: 'ideal', # only ideal for now issuer: issuer, description: description, From 80243bf8fca8dd7bdfd180e6584cafbf6c63f761 Mon Sep 17 00:00:00 2001 From: Sem van Nieuwenhuizen Date: Mon, 16 Dec 2024 19:53:19 +0100 Subject: [PATCH 5/7] =?UTF-8?q?chore:=20satisfy=20linter=20=F0=9F=A4=A1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/models/payment.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/models/payment.rb b/app/models/payment.rb index d94d254bb..5a964dc7e 100644 --- a/app/models/payment.rb +++ b/app/models/payment.rb @@ -62,7 +62,7 @@ def request_payment issuer: issuer, description: description, webhook_url: webhook_url, - redirect_url: redirect_url, + redirect_url: redirect_url ) self.trxid = payment.id From c24afa8e22b64b707c122ea480bda0346bac4d3f Mon Sep 17 00:00:00 2001 From: Sem van Nieuwenhuizen Date: Mon, 16 Dec 2024 19:56:46 +0100 Subject: [PATCH 6/7] =?UTF-8?q?chore:=20satisfy=20linter=20=F0=9F=A4=A1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/models/payment.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/models/payment.rb b/app/models/payment.rb index 5a964dc7e..031bb02be 100644 --- a/app/models/payment.rb +++ b/app/models/payment.rb @@ -57,7 +57,7 @@ def request_payment redirect_url = Rails.application.routes.url_helpers.payment_redirect_url(token: token) payment = Mollie::Payment.create( - amount: { value: sprintf('%.2f', amount), currency: 'EUR' }, + amount: { value: format('%.2f', amount), currency: 'EUR' }, method: 'ideal', # only ideal for now issuer: issuer, description: description, From 560297f0355e475ef826bc8b4045923149583642 Mon Sep 17 00:00:00 2001 From: Sem van Nieuwenhuizen Date: Mon, 16 Dec 2024 20:11:15 +0100 Subject: [PATCH 7/7] feat: remove issuer --- app/controllers/members/payments_controller.rb | 7 +++---- app/models/payment.rb | 12 ------------ app/views/members/payments/index.html.haml | 5 +---- 3 files changed, 4 insertions(+), 20 deletions(-) diff --git a/app/controllers/members/payments_controller.rb b/app/controllers/members/payments_controller.rb index 04238f40a..18adbbc22 100644 --- a/app/controllers/members/payments_controller.rb +++ b/app/controllers/members/payments_controller.rb @@ -35,10 +35,10 @@ def pay_activities redirect_to(member_payments_path) return end + payment = Payment.new( description: description, amount: amount, - issuer: transaction_params[:bank], member: member, payment_type: :ideal, transaction_id: unpaid.pluck(:activity_id), @@ -97,13 +97,12 @@ def add_funds description: description, amount: amount, member: member, - issuer: transaction_params[:bank], payment_type: :ideal, - transaction_id: nil, transaction_type: :checkout, redirect_uri: member_payments_path ) + if payment.save redirect_to(payment.payment_uri) else @@ -115,6 +114,6 @@ def add_funds private def transaction_params - params.permit(:amount, :bank, :activity_ids, :payment_type) + params.permit(:amount, :activity_ids, :payment_type) end end diff --git a/app/models/payment.rb b/app/models/payment.rb index 031bb02be..012809283 100644 --- a/app/models/payment.rb +++ b/app/models/payment.rb @@ -59,7 +59,6 @@ def request_payment payment = Mollie::Payment.create( amount: { value: format('%.2f', amount), currency: 'EUR' }, method: 'ideal', # only ideal for now - issuer: issuer, description: description, webhook_url: webhook_url, redirect_url: redirect_url @@ -143,17 +142,6 @@ def transaction_fee end end - def self.ideal_issuers - # cache the payment issuers for 12 hours, don't request it to often. Stored in tmp/cache - return [] if ENV['MOLLIE_TOKEN'].blank? - - Rails.cache.fetch('mollie_issuers', expires_in: 12.hours) do - method = Mollie::Method.get('ideal', include: 'issuers') - - method.issuers.map { |issuer| [issuer["name"], issuer["id"]] } - end - end - def activities Activity.find(transaction_id) if activity? end diff --git a/app/views/members/payments/index.html.haml b/app/views/members/payments/index.html.haml index 6caacf8c5..a22d943d5 100644 --- a/app/views/members/payments/index.html.haml +++ b/app/views/members/payments/index.html.haml @@ -42,13 +42,10 @@ %tr %td %td - .ideal-activities - = I18n.t("members.payments.unpaid_activity.footer.bank") - .float-xl-right= f.select :bank, options_for_select(Payment::ideal_issuers), {}, {style: '', class:'ideal-activities'} %td %div = I18n.t("members.payments.unpaid_activity.footer.transactioncosts") - %span.transaction_cost_activities.ideal-activities{:price =>@transaction_costs}= number_to_currency(@transaction_costs, :unit => '€') + %span.transaction_cost_activities.ideal-activities{:price => @transaction_costs}= number_to_currency(@transaction_costs, :unit => '€') %tr %td %td