solidus_six_saferpay 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- 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,57 @@
|
|
|
1
|
+
module Spree
|
|
2
|
+
module SolidusSixSaferpay
|
|
3
|
+
|
|
4
|
+
class InitializePayment
|
|
5
|
+
|
|
6
|
+
attr_reader :order, :payment_method, :redirect_url, :success
|
|
7
|
+
|
|
8
|
+
def self.call(order, payment_method)
|
|
9
|
+
new(order, payment_method).call
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
def initialize(order, payment_method)
|
|
13
|
+
@order = order
|
|
14
|
+
@payment_method = payment_method
|
|
15
|
+
@success = false
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
def call
|
|
19
|
+
gateway_response = gateway.initialize_payment(order, payment_method)
|
|
20
|
+
|
|
21
|
+
if gateway_response.success?
|
|
22
|
+
|
|
23
|
+
saferpay_payment = build_saferpay_payment(gateway_response.api_response)
|
|
24
|
+
|
|
25
|
+
@redirect_url = saferpay_payment.redirect_url
|
|
26
|
+
@success = saferpay_payment.save!
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
self
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
def success?
|
|
33
|
+
@success
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
def gateway
|
|
37
|
+
raise NotImplementedError, "Must be implemented in InitializePaymentPage or InitializeTransaction by including UsePaymentPageGateway or UseTransactionGateway"
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
private
|
|
41
|
+
|
|
42
|
+
def build_saferpay_payment(api_response)
|
|
43
|
+
Spree::SixSaferpayPayment.new(saferpay_payment_attributes(api_response))
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
def saferpay_payment_attributes(api_response)
|
|
47
|
+
{
|
|
48
|
+
order: order,
|
|
49
|
+
payment_method: payment_method,
|
|
50
|
+
token: api_response.token,
|
|
51
|
+
expiration: DateTime.parse(api_response.expiration),
|
|
52
|
+
response_hash: api_response.to_h
|
|
53
|
+
}
|
|
54
|
+
end
|
|
55
|
+
end
|
|
56
|
+
end
|
|
57
|
+
end
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
module Spree
|
|
2
|
+
module SolidusSixSaferpay
|
|
3
|
+
class InitializePaymentPage < InitializePayment
|
|
4
|
+
include UsePaymentPageGateway
|
|
5
|
+
|
|
6
|
+
private
|
|
7
|
+
|
|
8
|
+
def saferpay_payment_attributes(api_response)
|
|
9
|
+
super.merge(
|
|
10
|
+
redirect_url: api_response.redirect_url
|
|
11
|
+
)
|
|
12
|
+
end
|
|
13
|
+
end
|
|
14
|
+
end
|
|
15
|
+
end
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
module Spree
|
|
2
|
+
module SolidusSixSaferpay
|
|
3
|
+
|
|
4
|
+
class InitializeTransaction < InitializePayment
|
|
5
|
+
include UseTransactionGateway
|
|
6
|
+
|
|
7
|
+
private
|
|
8
|
+
|
|
9
|
+
def saferpay_payment_attributes(initialize_response)
|
|
10
|
+
super.merge(
|
|
11
|
+
redirect_url: initialize_response.redirect.redirect_url
|
|
12
|
+
)
|
|
13
|
+
end
|
|
14
|
+
end
|
|
15
|
+
end
|
|
16
|
+
end
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
module Spree
|
|
2
|
+
module SolidusSixSaferpay
|
|
3
|
+
class InquirePayment
|
|
4
|
+
attr_reader :saferpay_payment, :order, :success, :user_message
|
|
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
|
+
# NOTE: This will be successful regardless of the API response.
|
|
16
|
+
# The reason is that the API returns HTTP error codes for failed
|
|
17
|
+
# payments, but the inquiry was still successful
|
|
18
|
+
def call
|
|
19
|
+
inquiry = gateway.inquire(saferpay_payment)
|
|
20
|
+
|
|
21
|
+
if inquiry.success?
|
|
22
|
+
saferpay_payment.update_attributes(response_hash: inquiry.api_response.to_h)
|
|
23
|
+
else
|
|
24
|
+
general_error = I18n.t(:general_error, scope: [:solidus_six_saferpay, :errors])
|
|
25
|
+
specific_error = I18n.t(inquiry.error_name, scope: [:six_saferpay, :error_names])
|
|
26
|
+
@user_message = "#{general_error}: #{specific_error}"
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
@success = true
|
|
30
|
+
|
|
31
|
+
self
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
def success?
|
|
35
|
+
@success
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
def gateway
|
|
39
|
+
raise NotImplementedError, "Must be implemented in AssertPaymentPage or AuthorizeTransaction with UsePaymentPageGateway or UseTransactionGateway"
|
|
40
|
+
end
|
|
41
|
+
end
|
|
42
|
+
end
|
|
43
|
+
end
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
module Spree
|
|
2
|
+
module SolidusSixSaferpay
|
|
3
|
+
class PaymentValidator
|
|
4
|
+
attr_reader :order, :saferpay_payment
|
|
5
|
+
|
|
6
|
+
def self.call(saferpay_payment)
|
|
7
|
+
new(saferpay_payment).call
|
|
8
|
+
end
|
|
9
|
+
|
|
10
|
+
def initialize(saferpay_payment)
|
|
11
|
+
@order = saferpay_payment.order
|
|
12
|
+
@saferpay_payment = saferpay_payment
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
def call
|
|
16
|
+
saferpay_transaction = saferpay_payment.transaction
|
|
17
|
+
|
|
18
|
+
validate_payment_authorized(saferpay_transaction)
|
|
19
|
+
validate_order_reference(saferpay_transaction)
|
|
20
|
+
validate_order_amount(saferpay_transaction)
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
def validate_payment_authorized(saferpay_transaction)
|
|
24
|
+
if saferpay_transaction.status != "AUTHORIZED"
|
|
25
|
+
error("Status should be 'AUTHORIZED', is: '#{saferpay_transaction.status}'")
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
true
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
def validate_order_reference(saferpay_transaction)
|
|
32
|
+
if order.number != saferpay_transaction.order_id
|
|
33
|
+
error("Order ID should be '#{order.number}', is: '#{saferpay_transaction.order_id}'")
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
true
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
def validate_order_amount(saferpay_transaction)
|
|
40
|
+
order_amount = Spree::Money.new(order.total, currency: order.currency)
|
|
41
|
+
|
|
42
|
+
saferpay_transaction_currency = saferpay_transaction.amount.currency_code
|
|
43
|
+
if order_amount.currency.iso_code != saferpay_transaction_currency
|
|
44
|
+
error("Currency should be '#{order.currency}', is: '#{saferpay_transaction_currency}'")
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
saferpay_transaction_cents = saferpay_transaction.amount.value
|
|
48
|
+
if order_amount.cents.to_s != saferpay_transaction_cents
|
|
49
|
+
error("Order total (cents) should be '#{order_amount.cents}', is: '#{saferpay_transaction_cents}'")
|
|
50
|
+
end
|
|
51
|
+
|
|
52
|
+
true
|
|
53
|
+
end
|
|
54
|
+
|
|
55
|
+
private
|
|
56
|
+
|
|
57
|
+
def error(details)
|
|
58
|
+
raise ::SolidusSixSaferpay::InvalidSaferpayPayment.new(details: details)
|
|
59
|
+
end
|
|
60
|
+
end
|
|
61
|
+
end
|
|
62
|
+
end
|
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
module Spree
|
|
2
|
+
module SolidusSixSaferpay
|
|
3
|
+
class ProcessAuthorizedPayment
|
|
4
|
+
|
|
5
|
+
attr_reader :saferpay_payment, :order, :success, :user_message
|
|
6
|
+
|
|
7
|
+
def self.call(saferpay_payment)
|
|
8
|
+
new(saferpay_payment).call
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
def initialize(saferpay_payment)
|
|
12
|
+
@saferpay_payment = saferpay_payment
|
|
13
|
+
@order = saferpay_payment.order
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
def call
|
|
17
|
+
check_liability_shift_requirements!
|
|
18
|
+
|
|
19
|
+
validate_payment!
|
|
20
|
+
|
|
21
|
+
# SUCCESS!
|
|
22
|
+
|
|
23
|
+
cancel_old_solidus_payments
|
|
24
|
+
saferpay_payment.create_solidus_payment!
|
|
25
|
+
@success = true
|
|
26
|
+
|
|
27
|
+
self
|
|
28
|
+
|
|
29
|
+
rescue ::SolidusSixSaferpay::InvalidSaferpayPayment => e
|
|
30
|
+
cancel_saferpay_payment
|
|
31
|
+
# TODO: Check if messages from liability shift check and PaymentValidator are appropriate for user!
|
|
32
|
+
@user_message = e.full_message
|
|
33
|
+
@success = false
|
|
34
|
+
|
|
35
|
+
self
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
def success?
|
|
39
|
+
@success
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
def gateway
|
|
43
|
+
raise NotImplementedError, "Must be implemented in ProcessPaymentPagePayment or ProcessTransactionPayment"
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
private
|
|
47
|
+
|
|
48
|
+
def validate_payment!
|
|
49
|
+
PaymentValidator.call(saferpay_payment)
|
|
50
|
+
end
|
|
51
|
+
|
|
52
|
+
# Cancels only the saferpay payment without affecting solidus
|
|
53
|
+
def cancel_saferpay_payment
|
|
54
|
+
if transaction_id = saferpay_payment.transaction_id
|
|
55
|
+
gateway.void(transaction_id)
|
|
56
|
+
end
|
|
57
|
+
end
|
|
58
|
+
|
|
59
|
+
# Cancels the solidus payments which automatically cancels the saferpay
|
|
60
|
+
# payments
|
|
61
|
+
def cancel_old_solidus_payments
|
|
62
|
+
solidus_payments_to_cancel.each do |payment|
|
|
63
|
+
# void or create refund
|
|
64
|
+
payment.cancel!
|
|
65
|
+
end
|
|
66
|
+
end
|
|
67
|
+
|
|
68
|
+
def check_liability_shift_requirements!
|
|
69
|
+
if require_liability_shift? && !liability_shifted?
|
|
70
|
+
raise ::SolidusSixSaferpay::InvalidSaferpayPayment.new(details: I18n.t(:liability_shift_not_granted, scope: [:solidus_six_saferpay, :errors]))
|
|
71
|
+
end
|
|
72
|
+
end
|
|
73
|
+
|
|
74
|
+
def require_liability_shift?
|
|
75
|
+
saferpay_payment.payment_method.preferred_require_liability_shift
|
|
76
|
+
end
|
|
77
|
+
|
|
78
|
+
def liability_shifted?
|
|
79
|
+
saferpay_payment.liability.liability_shift
|
|
80
|
+
end
|
|
81
|
+
|
|
82
|
+
def solidus_payments_to_cancel
|
|
83
|
+
order.payments.valid.where.not(state: [:void])
|
|
84
|
+
end
|
|
85
|
+
end
|
|
86
|
+
end
|
|
87
|
+
end
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
<% source = payment.source %>
|
|
2
|
+
<% address = source.address %>
|
|
3
|
+
<fieldset data-hook="credit_card">
|
|
4
|
+
<legend align="center"><%= Spree::CreditCard.model_name.human %></legend>
|
|
5
|
+
|
|
6
|
+
<div class="row">
|
|
7
|
+
<div class="col-4">
|
|
8
|
+
<dl>
|
|
9
|
+
<dt><%= t('spree.name_on_card') %>:</dt>
|
|
10
|
+
<dd><%= source.card.holder_name %></dd>
|
|
11
|
+
|
|
12
|
+
<dt><%= Spree::CreditCard.human_attribute_name(:cc_type) %>:</dt>
|
|
13
|
+
<dd><%= source.brand_name %></dd>
|
|
14
|
+
|
|
15
|
+
<dt><%= Spree::CreditCard.human_attribute_name(:number) %>:</dt>
|
|
16
|
+
<dd><%= source.display_text %></dd>
|
|
17
|
+
|
|
18
|
+
<dt><%= Spree::CreditCard.human_attribute_name(:expiration) %>:</dt>
|
|
19
|
+
<dd><%= source.month %>/<%= source.year %></dd>
|
|
20
|
+
</dl>
|
|
21
|
+
|
|
22
|
+
<div data-hook="address">
|
|
23
|
+
<%= "#{address.first_name} #{address.last_name}" %><br />
|
|
24
|
+
<% if address.phone %>
|
|
25
|
+
<%= address.phone %><br />
|
|
26
|
+
<% end %>
|
|
27
|
+
<%= address.address1 %><br />
|
|
28
|
+
<% if address.address2.present? %>
|
|
29
|
+
<%= address.address2 %><br />
|
|
30
|
+
<% end %>
|
|
31
|
+
<%= "#{address.zipcode} #{address.city}" %><br />
|
|
32
|
+
<%= address.country %>
|
|
33
|
+
</div>
|
|
34
|
+
</div>
|
|
35
|
+
</div>
|
|
36
|
+
</fieldset>
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
json.call(payment_source, :id, :token, :created_at)
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
<% payment_container_id = "saferpay-payment-container-#{payment_method.id}" %>
|
|
2
|
+
<% if payment_method.preferred_as_iframe %>
|
|
3
|
+
<iframe class="loading-animation saferpay-iframe" width='100%' height='550px' id="<%= payment_container_id %>" src="" frameborder="0">
|
|
4
|
+
</iframe>
|
|
5
|
+
<script charset="utf-8">
|
|
6
|
+
SaferpayPayment.registerIframePaymentMethod({id: "<%= payment_method.id %>", initUrl: "<%= payment_method.init_path %>", containerId: "#<%= payment_container_id %>"})
|
|
7
|
+
</script>
|
|
8
|
+
<% else %>
|
|
9
|
+
<script charset="utf-8">
|
|
10
|
+
SaferpayPayment.registerExternalRedirectPaymentMethod({id: "<%= payment_method.id %>", initUrl: "<%= payment_method.init_path %>"})
|
|
11
|
+
</script>
|
|
12
|
+
<% end %>
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
<% saferpay_payment = payment.source %>
|
|
2
|
+
<% container_class = "saferpay-payment #{payment.state}" %>
|
|
3
|
+
<div class="<%= container_class %>">
|
|
4
|
+
<div class="credit-card">
|
|
5
|
+
<span><%= image_tag "solidus_six_saferpay/credit_cards/icons/#{saferpay_payment.icon_name}.png" %></span>
|
|
6
|
+
<span><%= saferpay_payment.display_text %></span>
|
|
7
|
+
</div>
|
|
8
|
+
<div>
|
|
9
|
+
<div class="amount">
|
|
10
|
+
<%= payment.display_amount %>
|
|
11
|
+
</div>
|
|
12
|
+
<div class="state">
|
|
13
|
+
<%= t("spree.payment_states.#{payment.state}") %>
|
|
14
|
+
</div>
|
|
15
|
+
</div>
|
|
16
|
+
</div>
|