From 46330f57b00c9a95c1138dae0ebd797530c7b1cb Mon Sep 17 00:00:00 2001 From: Guillaume Dott Date: Fri, 27 Aug 2021 15:20:35 +0200 Subject: [PATCH] Add Ept class and form helpers --- .gitignore | 1 + lib/monetico_paiement.rb | 40 +++++++++++++++- lib/monetico_paiement/ept.rb | 70 ++++++++++++++++++++++++++++ lib/monetico_paiement/form_helper.rb | 25 ++++++++++ lib/monetico_paiement/parameters.rb | 36 ++++++++++++++ lib/monetico_paiement/railtie.rb | 9 ++++ monetico_paiement.gemspec | 10 ++-- 7 files changed, 185 insertions(+), 6 deletions(-) create mode 100644 lib/monetico_paiement/ept.rb create mode 100644 lib/monetico_paiement/form_helper.rb create mode 100644 lib/monetico_paiement/parameters.rb create mode 100644 lib/monetico_paiement/railtie.rb diff --git a/.gitignore b/.gitignore index 9106b2a..dc96cb9 100644 --- a/.gitignore +++ b/.gitignore @@ -6,3 +6,4 @@ /pkg/ /spec/reports/ /tmp/ +/Gemfile.lock diff --git a/lib/monetico_paiement.rb b/lib/monetico_paiement.rb index c77787e..d9d4bc0 100644 --- a/lib/monetico_paiement.rb +++ b/lib/monetico_paiement.rb @@ -1,8 +1,44 @@ # frozen_string_literal: true -require_relative "monetico_paiement/version" +require "monetico_paiement/version" +require "monetico_paiement/parameters" +require "monetico_paiement/ept" +require "monetico_paiement/railtie" if defined?(Rails) module MoneticoPaiement class Error < StandardError; end - # Your code goes here... + + API_VERSION = "3.0" + DATE_FORMAT = "%d/%m/%Y:%H:%M:%S" + + END_POINTS = { + production: 'https://p.monetico-services.com/paiement.cgi', + test: 'https://p.monetico-services.com/test/paiement.cgi' + } + DEFAULT_ENV = :test + + def self.configure(&block) + yield default_config + end + + def self.default_config + @@default_config ||= MoneticoPaiement::Config.new + end + + class Config + attr_accessor :hmac_key, :ept_number, :company_code, :env + attr_writer :target_url + + def initialize(hmac_key: nil, ept_number: nil, company_code: nil, env: MoneticoPaiement::DEFAULT_ENV, target_url: nil) + self.hmac_key = hmac_key + self.ept_number = ept_number + self.company_code = company_code + self.env = env + self.target_url = target_url + end + + def target_url + @target_url || END_POINTS[env] + end + end end diff --git a/lib/monetico_paiement/ept.rb b/lib/monetico_paiement/ept.rb new file mode 100644 index 0000000..b1d04cc --- /dev/null +++ b/lib/monetico_paiement/ept.rb @@ -0,0 +1,70 @@ +require 'base64' +require 'openssl' +require 'json' + +module MoneticoPaiement + class Ept + attr_reader :config + + def initialize(config = nil) + @config = config ? config : MoneticoPaiement.default_config + end + + def attributes(reference, price, context:, email:, url_error:, url_success:, text: '', currency: 'EUR', locale: 'FR') + { + TPE: config.ept_number, + contexte_commande: Base64.strict_encode64(context.to_json), + date: Time.now.strftime(MoneticoPaiement::DATE_FORMAT), + lgue: locale, + mail: email, + montant: ("%.2f" % price) + currency, + reference: reference, + societe: config.company_code, + 'texte-libre': text, + url_retour_err: url_error, + url_retour_ok: url_success, + version: MoneticoPaiement::API_VERSION + } + end + + def mac_string(params) + compute_hmac_sha1 generate_data(params) + end + + def valid_hmac?(params) + return false unless params.key?('MAC') + + mac_string(params) == params['MAC'].downcase + end + + private + + def generate_data(params) + params.reject { |k| k == 'MAC' } + .sort + .map { |pair| pair.join('=') } + .join('*') + end + + def compute_hmac_sha1(data) + OpenSSL::HMAC.hexdigest(OpenSSL::Digest::SHA1.new, usable_key, data).downcase + end + + def usable_key + hex_string_key = config.hmac_key[0..37] + hex_final = config.hmac_key[38..40] + "00"; + + cca0 = hex_final[0].ord + + if cca0 > 70 && cca0 < 97 + hex_string_key += (cca0 - 23).chr + hex_final[1..2] + elsif hex_final[1..2] == "M" + hex_string_key += hex_final[0..1] + "0" + else + hex_string_key += hex_final[0..2] + end + + [hex_string_key].pack("H*") + end + end +end diff --git a/lib/monetico_paiement/form_helper.rb b/lib/monetico_paiement/form_helper.rb new file mode 100644 index 0000000..a8cbc28 --- /dev/null +++ b/lib/monetico_paiement/form_helper.rb @@ -0,0 +1,25 @@ +module MoneticoPaiement + module FormHelper + def monetico_paiement_form_tag(reference, price, form_options: {}, context:, email:, url_error:, url_success:, currency: 'EUR', locale: 'FR', ept: MoneticoPaiement::Ept.new, &block) + form_tag ept.config.target_url, method: :post, authenticity_token: false, remote: false, enforce_utf8: false, **form_options do + monetico_paiement_fields(reference, price, + context: context, email: email, url_error: url_error, + url_success: url_success, currency: currency, locale: locale, ept: ept) + capture(&block) + end + end + + def monetico_paiement_fields(reference, price, context:, email:, url_error:, url_success:, currency: 'EUR', locale: 'FR', ept: MoneticoPaiement::Ept.new) + attributes = ept.attributes(reference, price, + context: context, email: email, url_error: url_error, + url_success: url_success, currency: currency, locale: locale) + + html = hidden_field_tag('MAC', ept.mac_string(attributes)) + + attributes.each do |name, value| + html << hidden_field_tag(name, value) + end + + html + end + end +end diff --git a/lib/monetico_paiement/parameters.rb b/lib/monetico_paiement/parameters.rb new file mode 100644 index 0000000..a905859 --- /dev/null +++ b/lib/monetico_paiement/parameters.rb @@ -0,0 +1,36 @@ +module MoneticoPaiement + ALLOWED_PARAMS = %i{ + code-retour + MAC + TPE + montant + montantestime + reference + texte-libre + date + cvx + vld + brand + numauto + authentification + usage + typecompte + ecard + motifrefus + motifrefusautorisation + originecb + bincb + hpancb + ipclient + originetr + montantech + numero_dossier + typefacture + filtragecause + filtragevaleur + filtrage_etat + cbenregistree + cbmasquee + modepaiement + } +end diff --git a/lib/monetico_paiement/railtie.rb b/lib/monetico_paiement/railtie.rb new file mode 100644 index 0000000..38f17dc --- /dev/null +++ b/lib/monetico_paiement/railtie.rb @@ -0,0 +1,9 @@ +require 'monetico_paiement/form_helper' + +module MoneticoPaiement + class Railtie < Rails::Railtie + initializer "monetico_paiement.form_helpers" do + ActionView::Base.send :include, FormHelper + end + end +end diff --git a/monetico_paiement.gemspec b/monetico_paiement.gemspec index 6efb6b8..9f3d7ea 100644 --- a/monetico_paiement.gemspec +++ b/monetico_paiement.gemspec @@ -26,9 +26,11 @@ Gem::Specification.new do |spec| spec.executables = spec.files.grep(%r{\Aexe/}) { |f| File.basename(f) } spec.require_paths = ["lib"] - # Uncomment to register a new dependency of your gem - # spec.add_dependency "example-gem", "~> 1.0" + spec.add_dependency "openssl", "~> 2.2" + spec.add_dependency "json" - # For more information and examples about making a new gem, checkout our - # guide at: https://bundler.io/guides/creating_gem.html + spec.add_development_dependency "bundler", "~> 2.2" + spec.add_development_dependency "rake", "~> 13.0" + spec.add_development_dependency "irb" + spec.add_development_dependency "minitest" end