diff --git a/app/assets/images/every_pay.png b/app/assets/images/every_pay.png new file mode 100644 index 000000000..fcd4a2c67 Binary files /dev/null and b/app/assets/images/every_pay.png differ diff --git a/app/controllers/registrar/payments_controller.rb b/app/controllers/registrar/payments_controller.rb index 18c892ea7..57565b9c2 100644 --- a/app/controllers/registrar/payments_controller.rb +++ b/app/controllers/registrar/payments_controller.rb @@ -1,30 +1,34 @@ class Registrar class PaymentsController < BaseController - protect_from_forgery except: :back + protect_from_forgery except: [:back, :callback] skip_authorization_check # actually anyone can pay, no problems at all - skip_before_action :authenticate_user!, :check_ip_restriction, only: [:back] - before_action :check_bank + skip_before_action :authenticate_user!, :check_ip_restriction, only: [:back, :callback] + before_action :check_supported_payment_method - # to handle existing model we should - # get invoice_id and then get number - # build BankTransaction without connection with right reference number - # do not connect transaction and invoice def pay invoice = Invoice.find(params[:invoice_id]) - @bank_link = BankLink::Request.new(params[:bank], invoice, self) - @bank_link.make_transaction + bank = params[:bank] + opts = { + return_url: registrar_return_payment_with_url( + bank, invoice_id: invoice + ), + response_url: registrar_response_payment_with_url( + bank, invoice_id: invoice + ) + } + @payment = ::PaymentOrders.create_with_type(bank, invoice, opts) + @payment.create_transaction end - - # connect invoice and transaction - # both back and IPN def back - @bank_link = BankLink::Response.new(params[:bank], params) - if @bank_link.valid? && @bank_link.ok? - @bank_link.complete_payment + invoice = Invoice.find(params[:invoice_id]) + opts = { response: params } + @payment = ::PaymentOrders.create_with_type(params[:bank], invoice, opts) + if @payment.valid_response_from_intermediary? && @payment.settled_payment? + @payment.complete_transaction - if @bank_link.invoice.binded? + if invoice.binded? flash[:notice] = t(:pending_applied) else flash[:alert] = t(:something_wrong) @@ -32,17 +36,31 @@ class Registrar else flash[:alert] = t(:something_wrong) end - redirect_to registrar_invoice_path(@bank_link.invoice) + redirect_to registrar_invoice_path(invoice) + end + + def callback + invoice = Invoice.find(params[:invoice_id]) + opts = { response: params } + @payment = ::PaymentOrders.create_with_type(params[:bank], invoice, opts) + + if @payment.valid_response_from_intermediary? && @payment.settled_payment? + @payment.complete_transaction + end + + render status: 200, json: { status: 'ok' } end private - def banks - ENV['payments_banks'].split(",").map(&:strip) + def check_supported_payment_method + return if supported_payment_method? + raise StandardError.new("Not supported payment method") end - def check_bank - raise StandardError.new("Not Implemented bank") unless banks.include?(params[:bank]) + + def supported_payment_method? + PaymentOrders::PAYMENT_METHODS.include?(params[:bank]) end end end diff --git a/app/models/bank_link.rb b/app/models/bank_link.rb deleted file mode 100644 index e388a0f8b..000000000 --- a/app/models/bank_link.rb +++ /dev/null @@ -1,158 +0,0 @@ -class BankLink - module Base - def prepend_size(value) - value = (value || "").to_s.strip - string = "" - string << sprintf("%03i", value.size) - string << value - end - end - - class Request - include Base - include ActionView::Helpers::NumberHelper - - # need controller here in order to handle random ports and domains - # I don't want to do it but has to - attr_accessor :type, :invoice, :controller - def initialize(type, invoice, controller) - @type, @invoice, @controller = type, invoice, controller - end - - def url - ENV["payments_#{type}_url"] - end - - def fields - @fields ||= (hash = {} - hash["VK_SERVICE"] = "1012" - hash["VK_VERSION"] = "008" - hash["VK_SND_ID"] = ENV["payments_#{type}_seller_account"] - hash["VK_STAMP"] = invoice.number - hash["VK_AMOUNT"] = number_with_precision(invoice.total, :precision => 2, :separator => ".") - hash["VK_CURR"] = invoice.currency - hash["VK_REF"] = "" - hash["VK_MSG"] = invoice.order - hash["VK_RETURN"] = controller.registrar_return_payment_with_url(type) - hash["VK_CANCEL"] = controller.registrar_return_payment_with_url(type) - hash["VK_DATETIME"] = Time.now.strftime("%Y-%m-%dT%H:%M:%S%z") - hash["VK_MAC"] = calc_mac(hash) - hash["VK_ENCODING"] = "UTF-8" - hash["VK_LANG"] = "ENG" - hash) - end - - def calc_mac(fields) - pars = %w(VK_SERVICE VK_VERSION VK_SND_ID VK_STAMP VK_AMOUNT VK_CURR VK_REF - VK_MSG VK_RETURN VK_CANCEL VK_DATETIME).freeze - data = pars.map{|e| prepend_size(fields[e]) }.join - - sign(data) - end - - def make_transaction - transaction = BankTransaction.where(description: fields["VK_MSG"]).first_or_initialize( - reference_no: invoice.reference_no, - currency: invoice.currency, - iban: invoice.seller_iban - ) - - transaction.save! - end - - private - def sign(data) - private_key = OpenSSL::PKey::RSA.new(File.read(ENV["payments_#{type}_seller_private"])) - - signed_data = private_key.sign(OpenSSL::Digest::SHA1.new, data) - signed_data = Base64.encode64(signed_data).gsub(/\n|\r/, '') - signed_data - end - end - - - - - class Response - include Base - include ActionView::Helpers::NumberHelper - - attr_accessor :type, :params, :invoice - def initialize(type, params) - @type, @params = type, params - - @invoice = Invoice.find_by(number: params["VK_STAMP"]) if params["VK_STAMP"].present? - end - - def valid? - !!validate - end - - def ok? - params["VK_SERVICE"] == "1111" - end - - def complete_payment - if valid? - transaction = BankTransaction.find_by(description: params["VK_MSG"]) - transaction.sum = BigDecimal.new(params["VK_AMOUNT"].to_s) - transaction.bank_reference = params['VK_T_NO'] - transaction.buyer_bank_code = params["VK_SND_ID"] - transaction.buyer_iban = params["VK_SND_ACC"] - transaction.buyer_name = params["VK_SND_NAME"] - transaction.paid_at = Time.parse(params["VK_T_DATETIME"]) - transaction.save! - - transaction.autobind_invoice - end - end - - - - def validate - case params["VK_SERVICE"] - when "1111" - validate_success && validate_amount && validate_currency - when "1911" - validate_cancel - else - false - end - end - - def validate_success - pars = %w(VK_SERVICE VK_VERSION VK_SND_ID VK_REC_ID VK_STAMP VK_T_NO VK_AMOUNT VK_CURR - VK_REC_ACC VK_REC_NAME VK_SND_ACC VK_SND_NAME VK_REF VK_MSG VK_T_DATETIME).freeze - - @validate_success ||= ( - data = pars.map{|e| prepend_size(params[e]) }.join - verify_mac(data, params["VK_MAC"]) - ) - end - - def validate_cancel - pars = %w(VK_SERVICE VK_VERSION VK_SND_ID VK_REC_ID VK_STAMP VK_REF VK_MSG).freeze - @validate_cancel ||= ( - data = pars.map{|e| prepend_size(params[e]) }.join - verify_mac(data, params["VK_MAC"]) - ) - end - - def validate_amount - source = number_with_precision(BigDecimal.new(params["VK_AMOUNT"].to_s), precision: 2, separator: ".") - target = number_with_precision(invoice.total, precision: 2, separator: ".") - - source == target - end - - def validate_currency - invoice.currency == params["VK_CURR"] - end - - - def verify_mac(data, mac) - bank_public_key = OpenSSL::X509::Certificate.new(File.read(ENV["payments_#{type}_bank_certificate"])).public_key - bank_public_key.verify(OpenSSL::Digest::SHA1.new, Base64.decode64(mac), data) - end - end -end diff --git a/app/models/payment_orders.rb b/app/models/payment_orders.rb new file mode 100644 index 000000000..921af0cd4 --- /dev/null +++ b/app/models/payment_orders.rb @@ -0,0 +1,15 @@ +module PaymentOrders + PAYMENT_INTERMEDIARIES = ENV['payments_intermediaries'].to_s.strip.split(', ').freeze + PAYMENT_BANKLINK_BANKS = ENV['payments_banks'].to_s.strip.split(', ').freeze + PAYMENT_METHODS = [PAYMENT_INTERMEDIARIES, PAYMENT_BANKLINK_BANKS].flatten.freeze + + def self.create_with_type(type, invoice, opts = {}) + raise ArgumentError unless PAYMENT_METHODS.include?(type) + + if PAYMENT_BANKLINK_BANKS.include?(type) + BankLink.new(type, invoice, opts) + elsif type == 'every_pay' + EveryPay.new(type, invoice, opts) + end + end +end diff --git a/app/models/payment_orders/bank_link.rb b/app/models/payment_orders/bank_link.rb new file mode 100644 index 000000000..e568da0df --- /dev/null +++ b/app/models/payment_orders/bank_link.rb @@ -0,0 +1,146 @@ +module PaymentOrders + class BankLink < Base + BANK_LINK_VERSION = '008' + + NEW_TRANSACTION_SERVICE_NUMBER = '1012' + SUCCESSFUL_PAYMENT_SERVICE_NUMBER = '1111' + CANCELLED_PAYMENT_SERVICE_NUMBER = '1911' + + NEW_MESSAGE_KEYS = %w(VK_SERVICE VK_VERSION VK_SND_ID VK_STAMP VK_AMOUNT + VK_CURR VK_REF VK_MSG VK_RETURN VK_CANCEL + VK_DATETIME).freeze + SUCCESS_MESSAGE_KEYS = %w(VK_SERVICE VK_VERSION VK_SND_ID VK_REC_ID VK_STAMP + VK_T_NO VK_AMOUNT VK_CURR VK_REC_ACC VK_REC_NAME + VK_SND_ACC VK_SND_NAME VK_REF VK_MSG + VK_T_DATETIME).freeze + CANCEL_MESSAGE_KEYS = %w(VK_SERVICE VK_VERSION VK_SND_ID VK_REC_ID VK_STAMP + VK_REF VK_MSG).freeze + + def form_fields + hash = {} + hash["VK_SERVICE"] = NEW_TRANSACTION_SERVICE_NUMBER + hash["VK_VERSION"] = BANK_LINK_VERSION + hash["VK_SND_ID"] = seller_account + hash["VK_STAMP"] = invoice.number + hash["VK_AMOUNT"] = number_with_precision(invoice.total, precision: 2, separator: ".") + hash["VK_CURR"] = invoice.currency + hash["VK_REF"] = "" + hash["VK_MSG"] = invoice.order + hash["VK_RETURN"] = return_url + hash["VK_CANCEL"] = return_url + hash["VK_DATETIME"] = Time.zone.now.strftime("%Y-%m-%dT%H:%M:%S%z") + hash["VK_MAC"] = calc_mac(hash) + hash["VK_ENCODING"] = "UTF-8" + hash["VK_LANG"] = "ENG" + hash + end + + def valid_response_from_intermediary? + return false unless response + + case response["VK_SERVICE"] + when SUCCESSFUL_PAYMENT_SERVICE_NUMBER + valid_successful_transaction? + when CANCELLED_PAYMENT_SERVICE_NUMBER + valid_cancel_notice? + else + false + end + end + + def complete_transaction + return unless valid_successful_transaction? + + transaction = BankTransaction.find_by( + description: invoice.order, + currency: invoice.currency, + iban: invoice.seller_iban + ) + + transaction.sum = response['VK_AMOUNT'] + transaction.bank_reference = response['VK_T_NO'] + transaction.buyer_bank_code = response["VK_SND_ID"] + transaction.buyer_iban = response["VK_SND_ACC"] + transaction.buyer_name = response["VK_SND_NAME"] + transaction.paid_at = Time.parse(response["VK_T_DATETIME"]) + + transaction.save! + transaction.autobind_invoice + end + + def settled_payment? + response["VK_SERVICE"] == SUCCESSFUL_PAYMENT_SERVICE_NUMBER + end + + private + + def valid_successful_transaction? + valid_success_notice? && valid_amount? && valid_currency? + end + + def valid_cancel_notice? + valid_mac?(response, CANCEL_MESSAGE_KEYS) + end + + def valid_success_notice? + valid_mac?(response, SUCCESS_MESSAGE_KEYS) + end + + def valid_amount? + source = number_with_precision( + BigDecimal.new(response["VK_AMOUNT"]), precision: 2, separator: "." + ) + target = number_with_precision( + invoice.total, precision: 2, separator: "." + ) + + source == target + end + + def valid_currency? + invoice.currency == response["VK_CURR"] + end + + def sign(data) + private_key = OpenSSL::PKey::RSA.new(File.read(seller_certificate)) + signed_data = private_key.sign(OpenSSL::Digest::SHA1.new, data) + signed_data = Base64.encode64(signed_data).gsub(/\n|\r/, '') + signed_data + end + + def calc_mac(fields) + pars = NEW_MESSAGE_KEYS + data = pars.map { |element| prepend_size(fields[element]) }.join + sign(data) + end + + def valid_mac?(hash, keys) + data = keys.map { |element| prepend_size(hash[element]) }.join + verify_mac(data, hash["VK_MAC"]) + end + + def verify_mac(data, mac) + bank_public_key = OpenSSL::X509::Certificate.new(File.read(bank_certificate)).public_key + bank_public_key.verify(OpenSSL::Digest::SHA1.new, Base64.decode64(mac), data) + end + + def prepend_size(value) + value = (value || "").to_s.strip + string = "" + string << format("%03i", value.size) + string << value + end + + def seller_account + ENV["payments_#{type}_seller_account"] + end + + def seller_certificate + ENV["payments_#{type}_seller_private"] + end + + def bank_certificate + ENV["payments_#{type}_bank_certificate"] + end + end +end diff --git a/app/models/payment_orders/base.rb b/app/models/payment_orders/base.rb new file mode 100644 index 000000000..cf0293025 --- /dev/null +++ b/app/models/payment_orders/base.rb @@ -0,0 +1,33 @@ +module PaymentOrders + class Base + include ActionView::Helpers::NumberHelper + + attr_reader :type, + :invoice, + :return_url, + :response_url, + :response + + def initialize(type, invoice, opts = {}) + @type = type + @invoice = invoice + @return_url = opts[:return_url] + @response_url = opts[:response_url] + @response = opts[:response] + end + + def create_transaction + transaction = BankTransaction.where(description: invoice.order).first_or_initialize( + reference_no: invoice.reference_no, + currency: invoice.currency, + iban: invoice.seller_iban + ) + + transaction.save! + end + + def form_url + ENV["payments_#{type}_url"] + end + end +end diff --git a/app/models/payment_orders/every_pay.rb b/app/models/payment_orders/every_pay.rb new file mode 100644 index 000000000..b4ddcdf29 --- /dev/null +++ b/app/models/payment_orders/every_pay.rb @@ -0,0 +1,84 @@ +module PaymentOrders + class EveryPay < Base + USER = ENV['payments_every_pay_api_user'].freeze + KEY = ENV['payments_every_pay_api_key'].freeze + ACCOUNT_ID = ENV['payments_every_pay_seller_account'].freeze + SUCCESSFUL_PAYMENT = %w(settled authorized).freeze + + def form_fields + base_json = base_params + base_json[:nonce] = SecureRandom.hex(15) + hmac_fields = (base_json.keys + ['hmac_fields']).sort.uniq! + + base_json[:hmac_fields] = hmac_fields.join(',') + hmac_string = hmac_fields.map { |key, _v| "#{key}=#{base_json[key]}" }.join('&') + hmac = OpenSSL::HMAC.hexdigest('sha1', KEY, hmac_string) + base_json[:hmac] = hmac + + base_json + end + + def valid_response_from_intermediary? + return false unless response + valid_hmac? && valid_amount? && valid_account? + end + + def settled_payment? + SUCCESSFUL_PAYMENT.include?(response[:payment_state]) + end + + def complete_transaction + return unless valid_response_from_intermediary? && settled_payment? + + transaction = BankTransaction.find_by( + description: invoice.order, + currency: invoice.currency, + iban: invoice.seller_iban + ) + + transaction.sum = response[:amount] + transaction.paid_at = Date.strptime(response[:timestamp], '%s') + transaction.buyer_name = response[:cc_holder_name] + + transaction.save! + transaction.autobind_invoice + end + + private + + def base_params + { + api_username: USER, + account_id: ACCOUNT_ID, + timestamp: Time.now.to_i.to_s, + callback_url: response_url, + customer_url: return_url, + amount: number_with_precision(invoice.total, precision: 2), + order_reference: SecureRandom.hex(15), + transaction_type: 'charge', + hmac_fields: '' + }.with_indifferent_access + end + + def valid_hmac? + hmac_fields = response[:hmac_fields].split(',') + hmac_hash = {} + hmac_fields.map do |field| + symbol = field.to_sym + hmac_hash[symbol] = response[symbol] + end + + hmac_string = hmac_hash.map { |key, _v| "#{key}=#{hmac_hash[key]}" }.join('&') + expected_hmac = OpenSSL::HMAC.hexdigest('sha1', KEY, hmac_string) + expected_hmac == response[:hmac] + end + + def valid_amount? + invoice.total == BigDecimal.new(response[:amount]) + end + + def valid_account? + response[:account_id] == ACCOUNT_ID + end + end +end diff --git a/app/views/registrar/invoices/partials/_banklinks.haml b/app/views/registrar/invoices/partials/_banklinks.haml index 133a8d9c0..84f6e1399 100644 --- a/app/views/registrar/invoices/partials/_banklinks.haml +++ b/app/views/registrar/invoices/partials/_banklinks.haml @@ -1,6 +1,7 @@ -%h4= t(:pay_by_bank_link) +%h4= t('registrar.invoices.pay_invoice') %hr -- ENV['payments_banks'].split(",").each do |meth| + +- locals[:payment_channels].each do |meth| - meth = meth.strip = link_to registrar_payment_with_path(meth, invoice_id: params[:id]) do = image_tag("#{meth}.png") diff --git a/app/views/registrar/invoices/show.haml b/app/views/registrar/invoices/show.haml index ed0c4d1d2..c2c5331c2 100644 --- a/app/views/registrar/invoices/show.haml +++ b/app/views/registrar/invoices/show.haml @@ -17,4 +17,4 @@ - if !@invoice.cancelled? && !@invoice.binded? .row.semifooter - .col-md-12.text-right= render 'registrar/invoices/partials/banklinks' + .col-md-6-offset-6.text-right= render 'registrar/invoices/partials/banklinks', locals: { payment_channels: PaymentOrders::PAYMENT_METHODS } diff --git a/app/views/registrar/payments/pay.html.haml b/app/views/registrar/payments/pay.html.haml index c0fd8b6ad..8e759f9ea 100644 --- a/app/views/registrar/payments/pay.html.haml +++ b/app/views/registrar/payments/pay.html.haml @@ -1,11 +1,14 @@ +.h3 + = t('registrar.invoices.redirected_to_intermediary') + .payment-form - = form_tag @bank_link.url, method: :post do - - @bank_link.fields.each do |k, v| + = form_tag @payment.form_url, method: :post do + - @payment.form_fields.each do |k, v| = hidden_field_tag k, v - = submit_tag "Mine maksma" + = submit_tag t('registrar.invoices.go_to_intermediary') - -:coffeescript - load_listener = -> - $('.payment-form form').submit() - window.addEventListener 'load', load_listener +:javascript + function load_listener() { + $('.payment-form form').submit(); + } + window.addEventListener('load', load_listener) diff --git a/config/application-example.yml b/config/application-example.yml index bf846f23b..7785aafb5 100644 --- a/config/application-example.yml +++ b/config/application-example.yml @@ -106,10 +106,13 @@ sk_digi_doc_service_name: 'Testimine' secret_key_base: 'please-change-it-you-can-generate-it-with-rake-secret' devise_secret: 'please-change-it-you-can-generate-it-with-rake-secret' +# You should list only payment methods that +# conform with the Estonian BankLink standard payments_banks: > seb, swed, lhv + payments_seb_url: 'https://www.seb.ee/cgi-bin/dv.sh/ipank.r' payments_seb_bank_certificate: 'eyp_pub.pem' payments_seb_seller_private: 'kaupmees_priv.pem' @@ -123,6 +126,26 @@ payments_lhv_bank_certificate: 'eyp_pub.pem' payments_lhv_seller_private: 'kaupmees_priv.pem' payments_lhv_seller_account: 'testvpos' +# You should list other payment intermediaries here. Each one of them needs their own class in /app/models/payments/ +payments_intermediaries: > + every_pay + +# Other intermediaries should follow this naming convention: +# payments_intermediary_url - URL to intiate payments +# payments_intermediary_seller_account - your username in the bank system +# payments_intermediary_api_user - API username, in case it's different than the seller account +# payments_intermediary_api_key - API key given to you by intermediary +payments_every_pay_url: 'https://igw-demo.every-pay.com/transactions/' +payments_every_pay_seller_account: 'EUR3D1' +payments_every_pay_api_user: 'api_user' +payments_every_pay_api_key: 'api_key' + user_session_timeout: '3600' # 1 hour secure_session_cookies: 'false' # true|false same_site_session_cookies: 'false' # false|strict|lax + + +# Since the keys for staging are absent from the repo, we need to supply them separate for testing. +test: + payments_seb_bank_certificate: 'test/fixtures/files/seb_bank_cert.pem' + payments_seb_seller_private: 'test/fixtures/files/seb_seller_key.pem' diff --git a/config/locales/en.yml b/config/locales/en.yml index 7ac84379f..2afbb45a5 100644 --- a/config/locales/en.yml +++ b/config/locales/en.yml @@ -541,7 +541,6 @@ en: your_current_account_balance_is: 'Your current account balance is %{balance} %{currency}' billing: 'Billing' your_account: 'Your account' - pay_by_bank_link: 'Pay by bank link' issue_date: 'Issue date' due_date: 'Due date' payment_term: 'Payment term' diff --git a/config/locales/registrar/invoices.en.yml b/config/locales/registrar/invoices.en.yml index 1e8ecaafc..8415c3d61 100644 --- a/config/locales/registrar/invoices.en.yml +++ b/config/locales/registrar/invoices.en.yml @@ -1,5 +1,11 @@ en: registrar: invoices: + pay_invoice: 'Pay invoice' + redirected_to_intermediary: 'Click the button below to redirect to payment intermediary' + to_card_payment: Open card payment + go_to_intermediary: 'Go to intermediary' + pay_by_credit_card: Pay by credit card + payment_complete: Credit Card payment Complete index: reset_btn: Reset diff --git a/config/routes.rb b/config/routes.rb index 5ef26a195..83155d7bb 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -91,10 +91,11 @@ Rails.application.routes.draw do end end - - get 'pay/return/:bank' => 'payments#back', as: 'return_payment_with' - post 'pay/return/:bank' => 'payments#back' - get 'pay/go/:bank' => 'payments#pay', as: 'payment_with' + get 'pay/return/:bank' => 'payments#back', as: 'return_payment_with' + post 'pay/return/:bank' => 'payments#back' + put 'pay/return/:bank' => 'payments#back' + post 'pay/callback/:bank' => 'payments#callback', as: 'response_payment_with' + get 'pay/go/:bank' => 'payments#pay', as: 'payment_with' end namespace :registrant do diff --git a/test/fixtures/bank_transactions.yml b/test/fixtures/bank_transactions.yml index b0b4d661c..290be1597 100644 --- a/test/fixtures/bank_transactions.yml +++ b/test/fixtures/bank_transactions.yml @@ -1,3 +1,8 @@ one: sum: 1 currency: EUR + +for_payments_test: + description: "Order nr. 1" + currency: "EUR" + iban: "1234" diff --git a/test/fixtures/files/seb_bank_cert.pem b/test/fixtures/files/seb_bank_cert.pem new file mode 100644 index 000000000..a98508d36 --- /dev/null +++ b/test/fixtures/files/seb_bank_cert.pem @@ -0,0 +1,15 @@ +-----BEGIN CERTIFICATE----- +MIICVTCCAb4CCQCdHk6fGGIg9DANBgkqhkiG9w0BAQsFADBvMQswCQYDVQQGEwJF +RTERMA8GA1UECAwISGFyanVtYWExEDAOBgNVBAcMB1RhbGxpbm4xJTAjBgNVBAoM +HEVzdG9uaWFuIEludGVybmV0IEZvdW5kYXRpb24xFDASBgNVBAMMC2ludGVybmV0 +LmVlMB4XDTE4MDQyMTEyNDEyMloXDTE4MDUyMTEyNDEyMlowbzELMAkGA1UEBhMC +RUUxETAPBgNVBAgMCEhhcmp1bWFhMRAwDgYDVQQHDAdUYWxsaW5uMSUwIwYDVQQK +DBxFc3RvbmlhbiBJbnRlcm5ldCBGb3VuZGF0aW9uMRQwEgYDVQQDDAtpbnRlcm5l +dC5lZTCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEA4QPTaFdN+03vC63vgcSd +OsURjrt/eslJkPXr53VgkcFoD2AI+z1AoUbOMJ/FfXb+iY4o70we3YeRP8SeaDFn +pjOlSmS+DTsh5s3DCahbdbFzvyBDD5A4yKRaVRSCWFEjC684Uvg9Pf/ifP6GxHN6 +uVFg9/YhkS9XwfE0deJhxUUCAwEAATANBgkqhkiG9w0BAQsFAAOBgQCKC6bL+4Eu ++Dz+RQEZ9IEerZSKnnV2mygN9usddg46BnMqceWCA19Ei71C2UQsVD2e+7XkLjrl +0IDGciQqAjOUp4KKG+jQbtlcP0BBvP6CnirwqFfeV0XLWKapLetDjtdlmACAtHXj +8U0YFVbj5GGPJWAfAPnzpsiTxnQIinXNZw== +-----END CERTIFICATE----- diff --git a/test/fixtures/files/seb_seller_key.pem b/test/fixtures/files/seb_seller_key.pem new file mode 100644 index 000000000..be1febf79 --- /dev/null +++ b/test/fixtures/files/seb_seller_key.pem @@ -0,0 +1,16 @@ +-----BEGIN PRIVATE KEY----- +MIICeAIBADANBgkqhkiG9w0BAQEFAASCAmIwggJeAgEAAoGBAOED02hXTftN7wut +74HEnTrFEY67f3rJSZD16+d1YJHBaA9gCPs9QKFGzjCfxX12/omOKO9MHt2HkT/E +nmgxZ6YzpUpkvg07IebNwwmoW3Wxc78gQw+QOMikWlUUglhRIwuvOFL4PT3/4nz+ +hsRzerlRYPf2IZEvV8HxNHXiYcVFAgMBAAECgYEAxLXAgm4YaUK3YOF9CVgmD/Oq +Jrp5dpEzs/uZcO4nLyUCYLaXA3SH5LXumYmDb+ywFvbliFVmgkn6y+GKjhHqxjhx +KtyK3w1vGVkk6RyA076vgnOEp3un7j9XXM5U93Osk25Ezzb4pqslU7nDPb1OGg2A +q4UG+zHyj9UkI2S1V10CQQD39JtA3eiSlJ4jtr7QP3/KFV3O7Sku5TTmc6aMUhja +9qZCUMaK/67aMFjl62E9vdNBb1gGg28dBo/zV0uZAdsrAkEA6FCvyzaMOOzWqz6N +/uzeU7NTW9cHNQRx1d7e3vjWhYxvvknNrFim3sH+tbTock5MeNr4d4yCYFM72Zc5 +wH/pTwJBAIrD7OMnjZIC9GGeUzluYBDzVjWJCmRBSBK0pH+hLmHUaYVxeTuvDebz +6bx6t0f7ZTAYpRW4FsYStxsDPr6ZiFMCQFh7SslKSFPyGLz2QVzj2LXmagxjtLID +tFux3A7ulb4dw/2k3HoU9dGH77xDX/kRS10IgXP/BzUq3nO8flmMHk8CQQCCnqcJ +CEA+kqwPvgQ8YdeJOBFEc4spQ+OFbLUAtMt8+9YfeWtHyUlyNhtGXmwN8kGAHcPz +qtfPVIDR4dU0uvCw +-----END PRIVATE KEY----- diff --git a/test/fixtures/invoices.yml b/test/fixtures/invoices.yml index c395da425..71189f6b6 100644 --- a/test/fixtures/invoices.yml +++ b/test/fixtures/invoices.yml @@ -31,3 +31,9 @@ outstanding: overdue: <<: *DEFAULTS due_date: <%= Date.parse '2010-07-03' %> + +for_payments_test: + <<: *DEFAULTS + total: 12.00 + id: 1 + number: 1 diff --git a/test/integration/registrar/billing/balance_top_up_test.rb b/test/integration/registrar/billing/balance_top_up_test.rb index c77c9ff37..15face70c 100644 --- a/test/integration/registrar/billing/balance_top_up_test.rb +++ b/test/integration/registrar/billing/balance_top_up_test.rb @@ -6,6 +6,7 @@ class BalanceTopUpTest < ActionDispatch::IntegrationTest end def test_creates_new_invoice + original_vat_prc = Setting.registry_vat_prc Setting.registry_vat_prc = 0.1 visit registrar_invoices_url @@ -21,5 +22,7 @@ class BalanceTopUpTest < ActionDispatch::IntegrationTest assert_equal BigDecimal(10), invoice.vat_rate assert_equal BigDecimal('28.05'), invoice.total assert_text 'Please pay the following invoice' + + Setting.registry_vat_prc = original_vat_prc end end diff --git a/test/integration/registrar/invoices/list_test.rb b/test/integration/registrar/invoices/list_test.rb new file mode 100644 index 000000000..45e7d5f8b --- /dev/null +++ b/test/integration/registrar/invoices/list_test.rb @@ -0,0 +1,28 @@ +require 'test_helper' + +class ListInvoicesTest < ActionDispatch::IntegrationTest + def setup + super + + @user = users(:api_bestnames) + @registrar_invoices = @user.registrar.invoices + login_as @user + end + + def test_show_balance + visit registrar_invoices_path + assert_text "Your current account balance is 100,00 EUR" + end + + def test_show_multiple_invoices + @invoices = invoices + @registrar_invoices = [] + @invoices.each do |invoice| + @registrar_invoices << invoice + end + + visit registrar_invoices_path + assert_text "Unpaid", count: 5 + assert_text "Invoice no.", count: 7 + end +end diff --git a/test/integration/registrar/invoices/new_invoice_payment_test.rb b/test/integration/registrar/invoices/new_invoice_payment_test.rb new file mode 100644 index 000000000..995379edc --- /dev/null +++ b/test/integration/registrar/invoices/new_invoice_payment_test.rb @@ -0,0 +1,40 @@ +require 'test_helper' + +class NewInvoicePaymentTest < ActionDispatch::IntegrationTest + def setup + super + + @user = users(:api_bestnames) + login_as @user + end + + def create_invoice_and_visit_its_page + visit registrar_invoices_path + click_link_or_button 'Add deposit' + fill_in 'Amount', with: '200.00' + fill_in 'Description', with: 'My first invoice' + click_link_or_button 'Add' + end + + def test_create_new_SEB_payment + create_invoice_and_visit_its_page + click_link_or_button 'Seb' + form = page.find('form') + assert_equal('https://www.seb.ee/cgi-bin/dv.sh/ipank.r', form['action']) + assert_equal('post', form['method']) + assert_equal('240.00', form.find_by_id('VK_AMOUNT', visible: false).value) + end + + def test_create_new_Every_Pay_payment + create_invoice_and_visit_its_page + click_link_or_button 'Every pay' + expected_hmac_fields = 'account_id,amount,api_username,callback_url,' + + 'customer_url,hmac_fields,nonce,order_reference,timestamp,transaction_type' + + form = page.find('form') + assert_equal('https://igw-demo.every-pay.com/transactions/', form['action']) + assert_equal('post', form['method']) + assert_equal(expected_hmac_fields, form.find_by_id('hmac_fields', visible: false).value) + assert_equal('240.00', form.find_by_id('amount', visible: false).value) + end +end diff --git a/test/integration/registrar/invoices/new_test.rb b/test/integration/registrar/invoices/new_test.rb new file mode 100644 index 000000000..738e06d3c --- /dev/null +++ b/test/integration/registrar/invoices/new_test.rb @@ -0,0 +1,48 @@ +require 'test_helper' + +class NewInvoiceTest < ActionDispatch::IntegrationTest + def setup + super + + @user = users(:api_bestnames) + login_as @user + end + + def test_show_balance + visit registrar_invoices_path + assert_text "Your current account balance is 100,00 EUR" + end + + def test_create_new_invoice_with_positive_amount + visit registrar_invoices_path + click_link_or_button 'Add deposit' + fill_in 'Amount', with: '200.00' + fill_in 'Description', with: 'My first invoice' + + assert_difference 'Invoice.count', 1 do + click_link_or_button 'Add' + end + + assert_text 'Please pay the following invoice' + assert_text 'Invoice no. 131050' + assert_text 'Subtotal 200,00 €' + assert_text 'Pay invoice' + end + + # This test case should fail once issue #651 gets fixed + def test_create_new_invoice_with_amount_0_goes_through + visit registrar_invoices_path + click_link_or_button 'Add deposit' + fill_in 'Amount', with: '0.00' + fill_in 'Description', with: 'My first invoice' + + assert_difference 'Invoice.count', 1 do + click_link_or_button 'Add' + end + + assert_text 'Please pay the following invoice' + assert_text 'Invoice no. 131050' + assert_text 'Subtotal 0,00 €' + assert_text 'Pay invoice' + end +end diff --git a/test/integration/registrar/invoices/payment_callback_test.rb b/test/integration/registrar/invoices/payment_callback_test.rb new file mode 100644 index 000000000..9e8996214 --- /dev/null +++ b/test/integration/registrar/invoices/payment_callback_test.rb @@ -0,0 +1,49 @@ +require 'test_helper' + +class PaymentCallbackTest < ActionDispatch::IntegrationTest + def setup + super + + @user = users(:api_bestnames) + login_as @user + end + + def create_invoice_with_items + @invoice = invoices(:for_payments_test) + invoice_item = invoice_items(:one) + + @invoice.invoice_items << invoice_item + @invoice.invoice_items << invoice_item + @user.registrar.invoices << @invoice + end + + def every_pay_request_params + { + nonce: "392f2d7748bc8cb0d14f263ebb7b8932", + timestamp: "1524136727", + api_username: "ca8d6336dd750ddb", + transaction_result: "completed", + payment_reference: "fd5d27b59a1eb597393cd5ff77386d6cab81ae05067e18d530b10f3802e30b56", + payment_state: "settled", + amount: "12.00", + order_reference: "e468a2d59a731ccc546f2165c3b1a6", + account_id: "EUR3D1", + cc_type: "master_card", + cc_last_four_digits: "0487", + cc_month: "10", + cc_year: "2018", + cc_holder_name: "John Doe", + hmac_fields: "account_id,amount,api_username,cc_holder_name,cc_last_four_digits,cc_month,cc_type,cc_year,hmac_fields,nonce,order_reference,payment_reference,payment_state,timestamp,transaction_result", + hmac: "efac1c732835668cd86023a7abc140506c692f0d", + invoice_id: "12900000", + payment_method: "every_pay" + } + end + + def test_every_pay_callback_returns_status_200 + create_invoice_with_items + request_params = every_pay_request_params.merge(invoice_id: @invoice.id) + post "/registrar/pay/callback/every_pay", request_params + assert_equal(200, response.status) + end +end diff --git a/test/integration/registrar/invoices/payment_return_test.rb b/test/integration/registrar/invoices/payment_return_test.rb new file mode 100644 index 000000000..4524dc1ef --- /dev/null +++ b/test/integration/registrar/invoices/payment_return_test.rb @@ -0,0 +1,100 @@ +require 'test_helper' + +class PaymentReturnTest < ActionDispatch::IntegrationTest + def setup + super + + @user = users(:api_bestnames) + login_as @user + end + + def create_invoice_with_items + @invoice = invoices(:for_payments_test) + invoice_item = invoice_items(:one) + + @invoice.invoice_items << invoice_item + @invoice.invoice_items << invoice_item + @user.registrar.invoices << @invoice + end + + def every_pay_request_params + { + nonce: "392f2d7748bc8cb0d14f263ebb7b8932", + timestamp: "1524136727", + api_username: "ca8d6336dd750ddb", + transaction_result: "completed", + payment_reference: "fd5d27b59a1eb597393cd5ff77386d6cab81ae05067e18d530b10f3802e30b56", + payment_state: "settled", + amount: "12.00", + order_reference: "e468a2d59a731ccc546f2165c3b1a6", + account_id: "EUR3D1", + cc_type: "master_card", + cc_last_four_digits: "0487", + cc_month: "10", + cc_year: "2018", + cc_holder_name: "John Doe", + hmac_fields: "account_id,amount,api_username,cc_holder_name,cc_last_four_digits,cc_month,cc_type,cc_year,hmac_fields,nonce,order_reference,payment_reference,payment_state,timestamp,transaction_result", + hmac: "efac1c732835668cd86023a7abc140506c692f0d", + invoice_id: "12900000", + payment_method: "every_pay" + } + end + + def bank_link_request_params + { + "VK_SERVICE": "1111", + "VK_VERSION": "008", + "VK_SND_ID": "testvpos", + "VK_REC_ID": "seb", + "VK_STAMP": 1, + "VK_T_NO": "1", + "VK_AMOUNT": "12.00", + "VK_CURR": "EUR", + "VK_REC_ACC": "1234", + "VK_REC_NAME": "Eesti Internet", + "VK_SND_ACC": "1234", + "VK_SND_NAME": "John Doe", + "VK_REF": "", + "VK_MSG": "Order nr 1", + "VK_T_DATETIME": "2018-04-01T00:30:00+0300", + "VK_MAC": "CZZvcptkxfuOxRR88JmT4N+Lw6Hs4xiQfhBWzVYldAcRTQbcB/lPf9MbJzBE4e1/HuslQgkdCFt5g1xW2lJwrVDBQTtP6DAHfvxU3kkw7dbk0IcwhI4whUl68/QCwlXEQTAVDv1AFnGVxXZ40vbm/aLKafBYgrirB5SUe8+g9FE=", + "VK_ENCODING": "UTF-8", + "VK_LANG": "ENG", + payment_method: "seb" + } + end + + def test_every_pay_return_creates_activity_redirects_to_invoice_path + create_invoice_with_items + request_params = every_pay_request_params.merge(invoice_id: @invoice.id) + + post "/registrar/pay/return/every_pay", request_params + assert_equal(302, response.status) + assert_redirected_to(registrar_invoice_path(@invoice)) + end + + def test_Every_Pay_return_raises_RecordNotFound + create_invoice_with_items + request_params = every_pay_request_params.merge(invoice_id: "178907") + assert_raises(ActiveRecord::RecordNotFound) do + post "/registrar/pay/return/every_pay", request_params + end + end + + def test_bank_link_return_redirects_to_invoice_paths + create_invoice_with_items + request_params = bank_link_request_params.merge(invoice_id: @invoice.id) + + post "/registrar/pay/return/seb", request_params + assert_equal(302, response.status) + assert_redirected_to(registrar_invoice_path(@invoice)) + end + + def test_bank_link_return + create_invoice_with_items + request_params = bank_link_request_params.merge(invoice_id: "178907") + assert_raises(ActiveRecord::RecordNotFound) do + post "/registrar/pay/return/seb", request_params + end + end +end diff --git a/test/models/payment_orders/bank_link_test.rb b/test/models/payment_orders/bank_link_test.rb new file mode 100644 index 000000000..16f790d13 --- /dev/null +++ b/test/models/payment_orders/bank_link_test.rb @@ -0,0 +1,134 @@ +require 'test_helper' + +class BankLinkTest < ActiveSupport::TestCase + # Note: Files stored in: test/fixtures/files/seb_seller_key.pem + # test/fixtures/files/seb_bank_cert.pem + # are autogenerated, they will not work against production or even staging. + def setup + super + + @invoice = invoices(:for_payments_test) + invoice_item = invoice_items(:one) + + @invoice.invoice_items << invoice_item + @invoice.invoice_items << invoice_item + + travel_to '2018-04-01 00:30 +0300' + create_new_bank_link + create_completed_bank_link + create_cancelled_bank_link + end + + def teardown + super + + travel_back + end + + def create_completed_bank_link + params = { + 'VK_SERVICE': '1111', + 'VK_VERSION': '008', + 'VK_SND_ID': 'testvpos', + 'VK_REC_ID': 'seb', + 'VK_STAMP': 1, + 'VK_T_NO': '1', + 'VK_AMOUNT': '12.00', + 'VK_CURR': 'EUR', + 'VK_REC_ACC': '1234', + 'VK_REC_NAME': 'Eesti Internet', + 'VK_SND_ACC': '1234', + 'VK_SND_NAME': 'John Doe', + 'VK_REF': '', + 'VK_MSG': 'Order nr 1', + 'VK_T_DATETIME': '2018-04-01T00:30:00+0300', + 'VK_MAC': 'CZZvcptkxfuOxRR88JmT4N+Lw6Hs4xiQfhBWzVYldAcRTQbcB/lPf9MbJzBE4e1/HuslQgkdCFt5g1xW2lJwrVDBQTtP6DAHfvxU3kkw7dbk0IcwhI4whUl68/QCwlXEQTAVDv1AFnGVxXZ40vbm/aLKafBYgrirB5SUe8+g9FE=', + 'VK_ENCODING': 'UTF-8', + 'VK_LANG': 'ENG' + }.with_indifferent_access + + @completed_bank_link = PaymentOrders::BankLink.new( + 'seb', @invoice, { response: params } + ) + end + + def create_cancelled_bank_link + params = { + 'VK_SERVICE': '1911', + 'VK_VERSION': '008', + 'VK_SND_ID': 'testvpos', + 'VK_REC_ID': 'seb', + 'VK_STAMP': 1, + 'VK_REF': '', + 'VK_MSG': 'Order nr 1', + 'VK_MAC': 'PElE2mYXXN50q2UBvTuYU1rN0BmOQcbafPummDnWfNdm9qbaGQkGyOn0XaaFGlrdEcldXaHBbZKUS0HegIgjdDfl2NOk+wkLNNH0Iu38KzZaxHoW9ga7vqiyKHC8dcxkHiO9HsOnz77Sy/KpWCq6cz48bi3fcMgo+MUzBMauWoQ=', + 'VK_ENCODING': 'UTF-8', + 'VK_LANG': 'ENG' + }.with_indifferent_access + + @cancelled_bank_link = PaymentOrders::BankLink.new( + 'seb', @invoice, { response: params } + ) + end + + def create_new_bank_link + params = { return_url: 'return.url', response_url: 'response.url' } + @new_bank_link = PaymentOrders::BankLink.new('seb', @invoice, params) + end + + def test_response_is_not_valid_when_it_is_missing + refute(false, @new_bank_link.valid_response_from_intermediary?) + end + + def test_form_fields + expected_response = { + 'VK_SERVICE': '1012', + 'VK_VERSION': '008', + 'VK_SND_ID': 'testvpos', + 'VK_STAMP': 1, + 'VK_AMOUNT': '12.00', + 'VK_CURR': 'EUR', + 'VK_REF': '', + 'VK_MSG': 'Order nr. 1', + 'VK_RETURN': 'return.url', + 'VK_CANCEL': 'return.url', + 'VK_DATETIME': '2018-04-01T00:30:00+0300', + 'VK_MAC': 'q70UNFV4ih1qYij2+CyrHaApc3OE66igy3ijuR1m9dl0Cg+lIrAUsP47JChAF7PRErwZ78vSuZwrg0Vabhlp3WoC934ik2FiE04BBxUUTndONvguaNR1wvl0FiwfXFljLncX7TOmRraywJljKC5vTnIRNT2+1HXvmv0v576PGao=', + 'VK_ENCODING': 'UTF-8', + 'VK_LANG': 'ENG' + }.with_indifferent_access + + assert_equal(expected_response, @new_bank_link.form_fields) + end + + def test_valid_success_response_from_intermediary? + assert(@completed_bank_link.valid_response_from_intermediary?) + end + + def test_valid_cancellation_response_from_intermediary? + assert(@cancelled_bank_link.valid_response_from_intermediary?) + end + + def test_settled_payment? + assert(@completed_bank_link.settled_payment?) + refute(@cancelled_bank_link.settled_payment?) + end + + def test_complete_transaction_calls_methods_on_transaction + mock_transaction = MiniTest::Mock.new + mock_transaction.expect(:sum= , '12.00', ['12.00']) + mock_transaction.expect(:bank_reference= , '1', ['1']) + mock_transaction.expect(:buyer_bank_code= , 'testvpos', ['testvpos']) + mock_transaction.expect(:buyer_iban= , '1234', ['1234']) + mock_transaction.expect(:paid_at= , Date.parse('2018-04-01 00:30:00 +0300'), [Time.parse('2018-04-01T00:30:00+0300')]) + mock_transaction.expect(:buyer_name=, 'John Doe', ['John Doe']) + mock_transaction.expect(:save!, true) + mock_transaction.expect(:autobind_invoice, AccountActivity.new) + + BankTransaction.stub(:find_by, mock_transaction) do + @completed_bank_link.complete_transaction + end + + mock_transaction.verify + end +end diff --git a/test/models/payment_orders/every_pay_test.rb b/test/models/payment_orders/every_pay_test.rb new file mode 100644 index 000000000..2be3401dc --- /dev/null +++ b/test/models/payment_orders/every_pay_test.rb @@ -0,0 +1,92 @@ +require 'test_helper' + +class EveryPayTest < ActiveSupport::TestCase + def setup + super + + @invoice = invoices(:for_payments_test) + invoice_item = invoice_items(:one) + + @invoice.invoice_items << invoice_item + @invoice.invoice_items << invoice_item + + params = { + response: + { + utf8: '✓', + _method: 'put', + authenticity_token: 'OnA69vbccQtMt3C9wxEWigs5Gpf/7z+NoxRCMkFPlTvaATs8+OgMKF1I4B2f+vuK37zCgpWZaWWtyuslRRSwkw==', + nonce: '392f2d7748bc8cb0d14f263ebb7b8932', + timestamp: '1524136727', + api_username: 'ca8d6336dd750ddb', + transaction_result: 'completed', + payment_reference: 'fd5d27b59a1eb597393cd5ff77386d6cab81ae05067e18d530b10f3802e30b56', + payment_state: 'settled', + amount: '12.00', + order_reference: 'e468a2d59a731ccc546f2165c3b1a6', + account_id: 'EUR3D1', + cc_type: 'master_card', + cc_last_four_digits: '0487', + cc_month: '10', + cc_year: '2018', + cc_holder_name: 'John Doe', + hmac_fields: 'account_id,amount,api_username,cc_holder_name,cc_last_four_digits,cc_month,cc_type,cc_year,hmac_fields,nonce,order_reference,payment_reference,payment_state,timestamp,transaction_result', + hmac: 'efac1c732835668cd86023a7abc140506c692f0d', + invoice_id: '1', + }, + } + @every_pay = PaymentOrders::EveryPay.new('every_pay', @invoice, params) + @other_pay = PaymentOrders::EveryPay.new('every_pay', @invoice, {}) + + travel_to Time.zone.parse('2018-04-01 00:30:00 +0000') + end + + def teardown + super + + travel_back + end + + def test_form_fields + expected_fields = { + api_username: 'api_user', + account_id: 'EUR3D1', + timestamp: '1522542600', + amount: '12.00', + transaction_type: 'charge', + hmac_fields: 'account_id,amount,api_username,callback_url,customer_url,hmac_fields,nonce,order_reference,timestamp,transaction_type' + } + form_fields = @every_pay.form_fields + expected_fields.each do |k, v| + assert_equal(v, form_fields[k]) + end + end + + def test_valid_response_from_intermediary? + assert(@every_pay.valid_response_from_intermediary?) + refute(@other_pay.valid_response_from_intermediary?) + end + + def test_settled_payment? + assert(@every_pay.settled_payment?) + other_pay = PaymentOrders::EveryPay.new( + 'every_pay', @invoice, {response: {payment_state: 'CANCELLED'}} + ) + refute(other_pay.settled_payment?) + end + + def test_complete_transaction_calls_methods_on_transaction + mock_transaction = MiniTest::Mock.new + mock_transaction.expect(:sum= , '12.00', ['12.00']) + mock_transaction.expect(:paid_at= , Date.strptime('1524136727', '%s'), [Date.strptime('1524136727', '%s')]) + mock_transaction.expect(:buyer_name=, 'John Doe', ['John Doe']) + mock_transaction.expect(:save!, true) + mock_transaction.expect(:autobind_invoice, AccountActivity.new) + + BankTransaction.stub(:find_by, mock_transaction) do + @every_pay.complete_transaction + end + + mock_transaction.verify + end +end diff --git a/test/models/payment_orders_test.rb b/test/models/payment_orders_test.rb new file mode 100644 index 000000000..252ba0582 --- /dev/null +++ b/test/models/payment_orders_test.rb @@ -0,0 +1,58 @@ +require 'test_helper' + +class PaymentOrdersTest < ActiveSupport::TestCase + def setup + super + + @original_methods = ENV['payment_methods'] + @original_seb_URL = ENV['seb_payment_url'] + ENV['payment_methods'] = 'seb, swed, credit_card' + ENV['seb_payment_url'] = nil + @not_implemented_payment = PaymentOrders::Base.new( + 'not_implemented', Invoice.new + ) + end + + def teardown + super + + ENV['payment_methods'] = @original_methods + ENV['seb_payment_url'] = @original_seb_URL + end + + def test_variable_assignment + assert_equal 'not_implemented', @not_implemented_payment.type + assert_nil @not_implemented_payment.response_url + assert_nil @not_implemented_payment.return_url + assert_nil @not_implemented_payment.form_url + end + + def test_that_errors_are_raised_on_missing_methods + assert_raise NoMethodError do + @not_implemented_payment.valid_response? + end + + assert_raise NoMethodError do + @not_implemented_payment.settled_payment? + end + + assert_raise NoMethodError do + @not_implemented_payment.form_fields + end + + assert_raise NoMethodError do + @not_implemented_payment.complete_transaction + end + end + + def test_that_create_with_type_raises_argument_error + assert_raise ArgumentError do + PaymentOrders.create_with_type("not_implemented", Invoice.new) + end + end + + def test_create_with_correct_subclass + payment = PaymentOrders.create_with_type('seb', Invoice.new) + assert_equal PaymentOrders::BankLink, payment.class + end +end diff --git a/test/models/registry_test.rb b/test/models/registry_test.rb index 90a603e15..80c88c8bf 100644 --- a/test/models/registry_test.rb +++ b/test/models/registry_test.rb @@ -10,7 +10,11 @@ class RegistryTest < ActiveSupport::TestCase end def test_vat_rate + original_vat_prc = Setting.registry_vat_prc Setting.registry_vat_prc = 0.25 + assert_equal BigDecimal(25), @registry.vat_rate + + Setting.registry_vat_prc = original_vat_prc end end