solidus_six_saferpay 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/MIT-LICENSE +20 -0
- data/README.md +220 -0
- data/Rakefile +56 -0
- data/app/assets/config/solidus_six_saferpay_manifest.js +2 -0
- data/app/assets/images/solidus_six_saferpay/credit_cards/icons/amex.png +0 -0
- data/app/assets/images/solidus_six_saferpay/credit_cards/icons/cirrus.png +0 -0
- data/app/assets/images/solidus_six_saferpay/credit_cards/icons/delta.png +0 -0
- data/app/assets/images/solidus_six_saferpay/credit_cards/icons/diners_club.png +0 -0
- data/app/assets/images/solidus_six_saferpay/credit_cards/icons/directdebit.png +0 -0
- data/app/assets/images/solidus_six_saferpay/credit_cards/icons/discover.png +0 -0
- data/app/assets/images/solidus_six_saferpay/credit_cards/icons/egold.png +0 -0
- data/app/assets/images/solidus_six_saferpay/credit_cards/icons/maestro.png +0 -0
- data/app/assets/images/solidus_six_saferpay/credit_cards/icons/mastercard.png +0 -0
- data/app/assets/images/solidus_six_saferpay/credit_cards/icons/paypal.png +0 -0
- data/app/assets/images/solidus_six_saferpay/credit_cards/icons/solo.png +0 -0
- data/app/assets/images/solidus_six_saferpay/credit_cards/icons/switch.png +0 -0
- data/app/assets/images/solidus_six_saferpay/credit_cards/icons/twint.png +0 -0
- data/app/assets/images/solidus_six_saferpay/credit_cards/icons/visa.png +0 -0
- data/app/assets/images/solidus_six_saferpay/credit_cards/icons/visaelectron.png +0 -0
- data/app/assets/images/solidus_six_saferpay/credit_cards/icons/westernunion.png +0 -0
- data/app/assets/images/solidus_six_saferpay/credit_cards/icons/wirecard.png +0 -0
- data/app/assets/images/solidus_six_saferpay/credit_cards/icons/worldpay.png +0 -0
- data/app/assets/javascripts/solidus_six_saferpay/application.js +14 -0
- data/app/assets/javascripts/solidus_six_saferpay/saferpay_payment.js +120 -0
- data/app/assets/stylesheets/solidus_six_saferpay/application.css +15 -0
- data/app/assets/stylesheets/solidus_six_saferpay/loading_animation.scss +30 -0
- data/app/assets/stylesheets/solidus_six_saferpay/payments.scss +10 -0
- data/app/controllers/solidus_six_saferpay/application_controller.rb +5 -0
- data/app/controllers/spree/solidus_six_saferpay/checkout_controller.rb +93 -0
- data/app/controllers/spree/solidus_six_saferpay/payment_page/checkout_controller.rb +27 -0
- data/app/controllers/spree/solidus_six_saferpay/transaction/checkout_controller.rb +27 -0
- data/app/helpers/solidus_six_saferpay/application_helper.rb +4 -0
- data/app/jobs/solidus_six_saferpay/application_job.rb +4 -0
- data/app/mailers/solidus_six_saferpay/application_mailer.rb +6 -0
- data/app/models/solidus_six_saferpay/application_record.rb +5 -0
- data/app/models/spree/payment_method/saferpay_payment_method.rb +46 -0
- data/app/models/spree/payment_method/saferpay_payment_page.rb +13 -0
- data/app/models/spree/payment_method/saferpay_transaction.rb +12 -0
- data/app/models/spree/six_saferpay_payment.rb +69 -0
- data/app/services/spree/route_access.rb +5 -0
- data/app/services/spree/solidus_six_saferpay/assert_payment_page.rb +8 -0
- data/app/services/spree/solidus_six_saferpay/authorize_payment.rb +60 -0
- data/app/services/spree/solidus_six_saferpay/authorize_transaction.rb +8 -0
- data/app/services/spree/solidus_six_saferpay/initialize_payment.rb +57 -0
- data/app/services/spree/solidus_six_saferpay/initialize_payment_page.rb +15 -0
- data/app/services/spree/solidus_six_saferpay/initialize_transaction.rb +16 -0
- data/app/services/spree/solidus_six_saferpay/inquire_payment.rb +43 -0
- data/app/services/spree/solidus_six_saferpay/inquire_payment_page_payment.rb +7 -0
- data/app/services/spree/solidus_six_saferpay/inquire_transaction.rb +7 -0
- data/app/services/spree/solidus_six_saferpay/inquire_transaction_payment.rb +7 -0
- data/app/services/spree/solidus_six_saferpay/payment_validator.rb +62 -0
- data/app/services/spree/solidus_six_saferpay/process_authorized_payment.rb +87 -0
- data/app/services/spree/solidus_six_saferpay/process_payment_page_payment.rb +7 -0
- data/app/services/spree/solidus_six_saferpay/process_transaction_payment.rb +7 -0
- data/app/services/spree/solidus_six_saferpay/use_payment_page_gateway.rb +11 -0
- data/app/services/spree/solidus_six_saferpay/use_transaction_gateway.rb +11 -0
- data/app/views/spree/admin/payments/source_views/_saferpay_payment.erb +36 -0
- data/app/views/spree/api/payments/source_views/_saferpay_payment.json.jbuilder +1 -0
- data/app/views/spree/checkout/payment/_saferpay_payment.html.erb +12 -0
- data/app/views/spree/six_saferpay_payments/_six_saferpay_payment.html.erb +16 -0
- data/app/views/spree/solidus_six_saferpay/checkout/iframe_breakout_redirect.html.erb +7 -0
- data/config/locales/de.yml +52 -0
- data/config/locales/en.yml +52 -0
- data/config/locales/fr.yml +51 -0
- data/config/routes.rb +17 -0
- data/db/migrate/20190523075638_create_six_saferpay_payments.rb +31 -0
- data/lib/generators/solidus_six_saferpay/install/install_generator.rb +20 -0
- data/lib/solidus_six_saferpay.rb +5 -0
- data/lib/solidus_six_saferpay/configuration.rb +12 -0
- data/lib/solidus_six_saferpay/engine.rb +25 -0
- data/lib/solidus_six_saferpay/error_handler.rb +21 -0
- data/lib/solidus_six_saferpay/gateway.rb +183 -0
- data/lib/solidus_six_saferpay/gateway_response.rb +38 -0
- data/lib/solidus_six_saferpay/invalid_saferpay_payment.rb +11 -0
- data/lib/solidus_six_saferpay/payment_page_gateway.rb +55 -0
- data/lib/solidus_six_saferpay/transaction_gateway.rb +47 -0
- data/lib/solidus_six_saferpay/version.rb +3 -0
- data/lib/tasks/solidus_six_saferpay_tasks.rake +4 -0
- metadata +319 -0
@@ -0,0 +1,15 @@
|
|
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 any plugin's vendor/assets/stylesheets directory 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 other CSS/SCSS
|
10
|
+
* files in this directory. Styles in this file should be added after the last require_* statement.
|
11
|
+
* It is generally better to create a new file per style scope.
|
12
|
+
*
|
13
|
+
*= require_tree .
|
14
|
+
*= require_self
|
15
|
+
*/
|
@@ -0,0 +1,30 @@
|
|
1
|
+
.saferpay-iframe {
|
2
|
+
width: 100%;
|
3
|
+
}
|
4
|
+
|
5
|
+
.loading-animation {
|
6
|
+
text-align: center;
|
7
|
+
background-color: #222222;
|
8
|
+
|
9
|
+
-webkit-animation: sk-scaleout 0.5s infinite ease-in-out;
|
10
|
+
animation: sk-scaleout 0.5s infinite ease-in-out;
|
11
|
+
}
|
12
|
+
|
13
|
+
@-webkit-keyframes sk-scaleout {
|
14
|
+
0% { -webkit-transform: scale(0) }
|
15
|
+
100% {
|
16
|
+
-webkit-transform: scale(0.2);
|
17
|
+
opacity: 0;
|
18
|
+
}
|
19
|
+
}
|
20
|
+
|
21
|
+
@keyframes sk-scaleout {
|
22
|
+
0% {
|
23
|
+
-webkit-transform: scale(0);
|
24
|
+
transform: scale(0);
|
25
|
+
} 100% {
|
26
|
+
-webkit-transform: scale(0.2);
|
27
|
+
transform: scale(0.2);
|
28
|
+
opacity: 0;
|
29
|
+
}
|
30
|
+
}
|
@@ -0,0 +1,93 @@
|
|
1
|
+
module Spree
|
2
|
+
module SolidusSixSaferpay
|
3
|
+
class CheckoutController < StoreController
|
4
|
+
|
5
|
+
before_action :load_order
|
6
|
+
|
7
|
+
def init
|
8
|
+
payment_method = Spree::PaymentMethod.find(params[:payment_method_id])
|
9
|
+
initialized_payment = initialize_payment(@order, payment_method)
|
10
|
+
|
11
|
+
if initialized_payment.success?
|
12
|
+
redirect_url = initialized_payment.redirect_url
|
13
|
+
render json: { redirect_url: redirect_url }
|
14
|
+
else
|
15
|
+
render json: { errors: t('.checkout_not_initialized') }, status: 422
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
def success
|
20
|
+
saferpay_payment = Spree::SixSaferpayPayment.where(order_id: @order.id).order(:created_at).last
|
21
|
+
|
22
|
+
if saferpay_payment.nil?
|
23
|
+
raise Spree::Core::GatewayError, t('.payment_source_not_created')
|
24
|
+
end
|
25
|
+
|
26
|
+
# NOTE: PaymentPage payments are authorized directly. Instead, we
|
27
|
+
# perform an ASSERT here to gather the necessary details.
|
28
|
+
# This might be confusing at first, but doing it this way makes sense
|
29
|
+
# (and the code a LOT more readable) IMO. Feel free to disagree and PR
|
30
|
+
# a better solution.
|
31
|
+
# NOTE: Transaction payments are authorized here so that the money is
|
32
|
+
# already allocated when the user is on the confirm page. If the user
|
33
|
+
# then chooses another payment, the authorized payment is voided
|
34
|
+
# (cancelled).
|
35
|
+
payment_authorization = authorize_payment(saferpay_payment)
|
36
|
+
|
37
|
+
if payment_authorization.success?
|
38
|
+
|
39
|
+
processed_authorization = process_authorization(saferpay_payment)
|
40
|
+
if processed_authorization.success?
|
41
|
+
@order.next! if @order.payment?
|
42
|
+
else
|
43
|
+
flash[:error] = processed_authorization.user_message
|
44
|
+
end
|
45
|
+
|
46
|
+
else
|
47
|
+
payment_inquiry = inquire_payment(saferpay_payment)
|
48
|
+
flash[:error] = payment_inquiry.user_message
|
49
|
+
end
|
50
|
+
|
51
|
+
@redirect_path = order_checkout_path(@order.state)
|
52
|
+
render :iframe_breakout_redirect, layout: false
|
53
|
+
end
|
54
|
+
|
55
|
+
def fail
|
56
|
+
saferpay_payment = Spree::SixSaferpayPayment.where(order_id: @order.id).order(:created_at).last
|
57
|
+
|
58
|
+
payment_inquiry = inquire_payment(saferpay_payment)
|
59
|
+
|
60
|
+
@redirect_path = order_checkout_path(:payment)
|
61
|
+
flash[:error] = payment_inquiry.user_message
|
62
|
+
render :iframe_breakout_redirect, layout: false
|
63
|
+
end
|
64
|
+
|
65
|
+
private
|
66
|
+
|
67
|
+
def initialize_payment(order, payment_method)
|
68
|
+
raise NotImplementedError, "Must be implemented in PaymentPageCheckoutController or TransactionCheckoutController"
|
69
|
+
end
|
70
|
+
|
71
|
+
def authorize_payment(saferpay_payment)
|
72
|
+
raise NotImplementedError, "Must be implemented in PaymentPageCheckoutController or TransactionCheckoutController"
|
73
|
+
end
|
74
|
+
|
75
|
+
def process_authorization(saferpay_payment)
|
76
|
+
raise NotImplementedError, "Must be implemented in PaymentPageCheckoutController or TransactionCheckoutController"
|
77
|
+
end
|
78
|
+
|
79
|
+
def inquire_payment(saferpay_payment)
|
80
|
+
raise NotImplementedError, "Must be implemented in PaymentPageCheckoutController or TransactionCheckoutController"
|
81
|
+
end
|
82
|
+
|
83
|
+
def load_order
|
84
|
+
@order = current_order
|
85
|
+
redirect_to(spree.cart_path) && return unless @order
|
86
|
+
end
|
87
|
+
|
88
|
+
def order_checkout_path(state)
|
89
|
+
Spree::Core::Engine.routes.url_helpers.checkout_state_path(state)
|
90
|
+
end
|
91
|
+
end
|
92
|
+
end
|
93
|
+
end
|
@@ -0,0 +1,27 @@
|
|
1
|
+
module Spree
|
2
|
+
module SolidusSixSaferpay
|
3
|
+
module PaymentPage
|
4
|
+
# explicit parent must be stated, otherwise Spree::CheckoutController has precendence
|
5
|
+
class CheckoutController < SolidusSixSaferpay::CheckoutController
|
6
|
+
|
7
|
+
private
|
8
|
+
|
9
|
+
def initialize_payment(order, payment_method)
|
10
|
+
InitializePaymentPage.call(order, payment_method)
|
11
|
+
end
|
12
|
+
|
13
|
+
def authorize_payment(saferpay_payment)
|
14
|
+
AssertPaymentPage.call(saferpay_payment)
|
15
|
+
end
|
16
|
+
|
17
|
+
def process_authorization(saferpay_payment)
|
18
|
+
ProcessPaymentPagePayment.call(saferpay_payment)
|
19
|
+
end
|
20
|
+
|
21
|
+
def inquire_payment(saferpay_payment)
|
22
|
+
InquirePaymentPagePayment.call(saferpay_payment)
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
@@ -0,0 +1,27 @@
|
|
1
|
+
module Spree
|
2
|
+
module SolidusSixSaferpay
|
3
|
+
# explicit parent must be stated, otherwise Spree::CheckoutController has precendence
|
4
|
+
module Transaction
|
5
|
+
class CheckoutController < SolidusSixSaferpay::CheckoutController
|
6
|
+
|
7
|
+
private
|
8
|
+
|
9
|
+
def initialize_payment(order, payment_method)
|
10
|
+
InitializeTransaction.call(order, payment_method)
|
11
|
+
end
|
12
|
+
|
13
|
+
def authorize_payment(saferpay_payment)
|
14
|
+
AuthorizeTransaction.call(saferpay_payment)
|
15
|
+
end
|
16
|
+
|
17
|
+
def process_authorization(saferpay_payment)
|
18
|
+
ProcessTransactionPayment.call(saferpay_payment)
|
19
|
+
end
|
20
|
+
|
21
|
+
def inquire_payment(saferpay_payment)
|
22
|
+
InquireTransactionPayment.call(saferpay_payment)
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
@@ -0,0 +1,46 @@
|
|
1
|
+
module Spree
|
2
|
+
class PaymentMethod::SaferpayPaymentMethod < PaymentMethod::CreditCard
|
3
|
+
include RouteAccess
|
4
|
+
|
5
|
+
AVAILABLE_PAYMENT_METHODS = %w(ALIPAY AMEX BANCONTACT BONUS DINERS DIRECTDEBIT EPRZELEWY EPS GIROPAY IDEAL INVOICE JCB MAESTRO MASTERCARD MYONE PAYPAL PAYDIREKT POSTCARD POSTFINANCE SAFERPAYTEST SOFORT TWINT UNIONPAY VISA VPAY)
|
6
|
+
|
7
|
+
delegate :try_void, to: :gateway
|
8
|
+
|
9
|
+
preference :as_iframe, :boolean, default: true
|
10
|
+
|
11
|
+
preference :require_liability_shift, :boolean, default: true
|
12
|
+
|
13
|
+
# Configure all available Payment Methods for the Saferpay API as
|
14
|
+
# preferences
|
15
|
+
AVAILABLE_PAYMENT_METHODS.each do |six_payment_method|
|
16
|
+
preference "payment_method_#{six_payment_method.downcase}", :boolean, default: false
|
17
|
+
end
|
18
|
+
|
19
|
+
def enabled_payment_methods
|
20
|
+
AVAILABLE_PAYMENT_METHODS.select do |six_payment_method|
|
21
|
+
public_send("preferred_payment_method_#{six_payment_method.downcase}")
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
def payment_source_class
|
26
|
+
Spree::SixSaferpayPayment
|
27
|
+
end
|
28
|
+
|
29
|
+
def profiles_supported?
|
30
|
+
false
|
31
|
+
end
|
32
|
+
|
33
|
+
# We want to automatically capture the payment when the order is completed
|
34
|
+
def auto_capture
|
35
|
+
true
|
36
|
+
end
|
37
|
+
|
38
|
+
def partial_name
|
39
|
+
'saferpay_payment'
|
40
|
+
end
|
41
|
+
|
42
|
+
def init_path
|
43
|
+
raise NotImplementedError, "Must be implemented in SaferpayPaymentPage or SaferpayTransaction"
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
@@ -0,0 +1,13 @@
|
|
1
|
+
module Spree
|
2
|
+
class PaymentMethod::SaferpayPaymentPage < PaymentMethod::SaferpayPaymentMethod
|
3
|
+
|
4
|
+
|
5
|
+
def gateway_class
|
6
|
+
::SolidusSixSaferpay::PaymentPageGateway
|
7
|
+
end
|
8
|
+
|
9
|
+
def init_path
|
10
|
+
url_helpers.solidus_six_saferpay_payment_page_init_path
|
11
|
+
end
|
12
|
+
end
|
13
|
+
end
|
@@ -0,0 +1,12 @@
|
|
1
|
+
module Spree
|
2
|
+
class PaymentMethod::SaferpayTransaction < PaymentMethod::SaferpayPaymentMethod
|
3
|
+
|
4
|
+
def gateway_class
|
5
|
+
::SolidusSixSaferpay::TransactionGateway
|
6
|
+
end
|
7
|
+
|
8
|
+
def init_path
|
9
|
+
url_helpers.solidus_six_saferpay_transaction_init_path
|
10
|
+
end
|
11
|
+
end
|
12
|
+
end
|
@@ -0,0 +1,69 @@
|
|
1
|
+
module Spree
|
2
|
+
|
3
|
+
# attributes
|
4
|
+
# * :token
|
5
|
+
# * :expiration
|
6
|
+
# * :redirect_url
|
7
|
+
# * :transaction_id
|
8
|
+
# * :transaction_status
|
9
|
+
# * :transaction_date
|
10
|
+
# * :six_transaction_reference
|
11
|
+
# * :display_text
|
12
|
+
# * :masked_number
|
13
|
+
# * :expiration_year
|
14
|
+
# * :expiration_month
|
15
|
+
# * :response_hash
|
16
|
+
class SixSaferpayPayment < PaymentSource
|
17
|
+
belongs_to :order
|
18
|
+
belongs_to :payment_method
|
19
|
+
# store this anyway for accountability reasons
|
20
|
+
serialize :response_hash, Hash
|
21
|
+
|
22
|
+
validates :token, :expiration, presence: true
|
23
|
+
validates :token, :transaction_id, :six_transaction_reference, uniqueness: true, allow_blank: true
|
24
|
+
|
25
|
+
def create_solidus_payment!
|
26
|
+
payments.create!(order: order, response_code: transaction_id, payment_method: payment_method, amount: order.total, source: self)
|
27
|
+
end
|
28
|
+
|
29
|
+
def address
|
30
|
+
@address ||= order.bill_address
|
31
|
+
end
|
32
|
+
|
33
|
+
def payment_means
|
34
|
+
@payment_means ||= ::SixSaferpay::ResponsePaymentMeans.new(response_hash[:payment_means])
|
35
|
+
end
|
36
|
+
|
37
|
+
def transaction
|
38
|
+
@transaction ||= ::SixSaferpay::Transaction.new(response_hash[:transaction])
|
39
|
+
end
|
40
|
+
|
41
|
+
def liability
|
42
|
+
@liability ||= ::SixSaferpay::Liability.new(response_hash[:liability])
|
43
|
+
end
|
44
|
+
|
45
|
+
def card
|
46
|
+
payment_means.card
|
47
|
+
end
|
48
|
+
|
49
|
+
def name
|
50
|
+
card.holder_name
|
51
|
+
end
|
52
|
+
|
53
|
+
def brand_name
|
54
|
+
payment_means.brand.name
|
55
|
+
end
|
56
|
+
|
57
|
+
def month
|
58
|
+
card.exp_month
|
59
|
+
end
|
60
|
+
|
61
|
+
def year
|
62
|
+
card.exp_year
|
63
|
+
end
|
64
|
+
|
65
|
+
def icon_name
|
66
|
+
payment_means.brand.payment_method.downcase
|
67
|
+
end
|
68
|
+
end
|
69
|
+
end
|
@@ -0,0 +1,60 @@
|
|
1
|
+
module Spree
|
2
|
+
module SolidusSixSaferpay
|
3
|
+
class AuthorizePayment
|
4
|
+
attr_reader :saferpay_payment, :order, :success
|
5
|
+
|
6
|
+
def self.call(saferpay_payment)
|
7
|
+
new(saferpay_payment).call
|
8
|
+
end
|
9
|
+
|
10
|
+
def initialize(saferpay_payment)
|
11
|
+
@saferpay_payment = saferpay_payment
|
12
|
+
@order = saferpay_payment.order
|
13
|
+
end
|
14
|
+
|
15
|
+
def call
|
16
|
+
authorization = gateway.authorize(order.total, saferpay_payment)
|
17
|
+
|
18
|
+
if authorization.success?
|
19
|
+
saferpay_payment.update_attributes!(saferpay_payment_attributes(authorization.api_response))
|
20
|
+
@success = true
|
21
|
+
end
|
22
|
+
self
|
23
|
+
end
|
24
|
+
|
25
|
+
def success?
|
26
|
+
@success
|
27
|
+
end
|
28
|
+
|
29
|
+
|
30
|
+
def gateway
|
31
|
+
raise NotImplementedError, "Must be implemented in AssertPaymentPage or AuthorizeTransaction with UsePaymentPageGateway or UseTransactionGateway"
|
32
|
+
end
|
33
|
+
|
34
|
+
private
|
35
|
+
|
36
|
+
def saferpay_payment_attributes(saferpay_response)
|
37
|
+
payment_means = saferpay_response.payment_means
|
38
|
+
brand = payment_means.brand
|
39
|
+
card = payment_means.card
|
40
|
+
|
41
|
+
attributes = {
|
42
|
+
transaction_id: saferpay_response.transaction.id,
|
43
|
+
transaction_status: saferpay_response.transaction.status,
|
44
|
+
transaction_date: DateTime.parse(saferpay_response.transaction.date),
|
45
|
+
six_transaction_reference: saferpay_response.transaction.six_transaction_reference,
|
46
|
+
display_text: saferpay_response.payment_means.display_text,
|
47
|
+
response_hash: saferpay_response.to_h
|
48
|
+
}
|
49
|
+
|
50
|
+
if card
|
51
|
+
attributes[:masked_number] = card.masked_number
|
52
|
+
attributes[:expiration_year] = card.exp_year
|
53
|
+
attributes[:expiration_month] = card.exp_month
|
54
|
+
end
|
55
|
+
|
56
|
+
attributes
|
57
|
+
end
|
58
|
+
end
|
59
|
+
end
|
60
|
+
end
|