solidus_six_saferpay 0.1.8 → 0.5.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.ruby-version +1 -0
- data/README.md +3 -0
- data/app/assets/javascripts/solidus_six_saferpay/saferpay_payment.js +4 -1
- data/app/controllers/spree/solidus_six_saferpay/checkout_controller.rb +65 -41
- data/app/controllers/spree/solidus_six_saferpay/transaction/checkout_controller.rb +1 -1
- data/app/models/spree/payment_method/saferpay_payment_method.rb +1 -1
- data/app/models/spree/payment_method/saferpay_payment_page.rb +2 -2
- data/app/models/spree/payment_method/saferpay_transaction.rb +2 -2
- data/app/services/spree/solidus_six_saferpay/cancel_authorized_payment.rb +33 -0
- data/app/services/spree/solidus_six_saferpay/initialize_payment.rb +0 -1
- data/app/services/spree/solidus_six_saferpay/initialize_transaction.rb +0 -1
- data/app/services/spree/solidus_six_saferpay/inquire_payment.rb +27 -1
- data/app/services/spree/solidus_six_saferpay/order_not_found_handler.rb +28 -0
- data/app/services/spree/solidus_six_saferpay/payment_not_found_handler.rb +28 -0
- data/app/services/spree/solidus_six_saferpay/payment_processing_success_handler.rb +26 -0
- data/app/views/spree/checkout/payment/_saferpay_payment.html.erb +2 -2
- data/app/views/spree/solidus_six_saferpay/checkout/{iframe_breakout_redirect.html.erb → iframe_breakout_redirect.erb} +1 -1
- data/config/locales/de.yml +3 -0
- data/config/locales/en.yml +3 -0
- data/config/locales/fr.yml +3 -0
- data/config/routes.rb +6 -6
- data/lib/solidus_six_saferpay/configuration.rb +0 -2
- data/lib/solidus_six_saferpay/gateway.rb +11 -11
- data/lib/solidus_six_saferpay/payment_page_gateway.rb +8 -9
- data/lib/solidus_six_saferpay/transaction_gateway.rb +8 -9
- data/lib/solidus_six_saferpay/version.rb +1 -1
- data/solidus_six_saferpay.gemspec +2 -1
- data/spec/controllers/spree/solidus_six_saferpay/payment_page/checkout_controller_spec.rb +8 -197
- data/spec/controllers/spree/solidus_six_saferpay/transaction/checkout_controller_spec.rb +8 -220
- data/spec/services/spree/solidus_six_saferpay/assert_payment_page_spec.rb +2 -128
- data/spec/services/spree/solidus_six_saferpay/authorize_transaction_spec.rb +3 -127
- data/spec/services/spree/solidus_six_saferpay/cancel_authorized_payment_spec.rb +58 -0
- data/spec/services/spree/solidus_six_saferpay/initialize_payment_page_spec.rb +0 -2
- data/spec/services/spree/solidus_six_saferpay/initialize_transaction_spec.rb +0 -1
- data/spec/services/spree/solidus_six_saferpay/inquire_payment_page_payment_spec.rb +2 -98
- data/spec/services/spree/solidus_six_saferpay/inquire_transaction_payment_spec.rb +2 -98
- data/spec/services/spree/solidus_six_saferpay/order_not_found_handler_spec.rb +30 -0
- data/spec/services/spree/solidus_six_saferpay/payment_not_found_handler_spec.rb +30 -0
- data/spec/services/spree/solidus_six_saferpay/payment_processing_success_handler_spec.rb +34 -0
- data/spec/services/spree/solidus_six_saferpay/process_payment_page_payment_spec.rb +1 -206
- data/spec/services/spree/solidus_six_saferpay/process_transaction_payment_spec.rb +1 -200
- data/spec/solidus_six_saferpay/configuration_spec.rb +0 -3
- data/spec/solidus_six_saferpay/gateway_spec.rb +1 -14
- data/spec/solidus_six_saferpay/payment_page_gateway_spec.rb +16 -14
- data/spec/solidus_six_saferpay/transaction_gateway_spec.rb +17 -14
- data/spec/support/shared_examples/authorize_payment.rb +132 -0
- data/spec/support/shared_examples/checkout_controller.rb +294 -0
- data/spec/support/shared_examples/inquire_payment.rb +118 -0
- data/spec/support/shared_examples/process_authorized_payment.rb +202 -0
- metadata +41 -10
- data/app/services/spree/solidus_six_saferpay/inquire_transaction.rb +0 -7
- data/spec/controllers/spree/solidus_six_saferpay/checkout_controller_spec.rb +0 -41
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 2bf3c36e740b9b6d5735b4ab0a9d9e2a3166c832cc25539f8df4af656b772ea9
|
4
|
+
data.tar.gz: 664c704fe719d59044d8f4566cfcbb48320cc2c5bfbc7619fff4de70c4639495
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 9236e3a2555bfbcc2934d556cf1cfcdacc1f7735b04f9452b5de7826fd5839c073c016b996acb47c9a3f93bacb33b62fad7077180c7ecdb63b6e7c99a8ea9cc2
|
7
|
+
data.tar.gz: '01816590075677c47c4d4c0c9b0bd24e81115acc4437a231f54a57da60db1a26d0c38e0283b1d0da3a8bafbd2a5c6c319156f43b426505cf70a4fcc2af0a0c23'
|
data/.ruby-version
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
2.7.2
|
data/README.md
CHANGED
@@ -2,6 +2,9 @@
|
|
2
2
|
|
3
3
|
The `solidus_six_saferpay` engine adds checkout options for the Saferpay Payment Page ([Integration Guide](https://saferpay.github.io/sndbx/Integration_PP.html), [JSON API documentation](http://saferpay.github.io/jsonapi/#ChapterPaymentPage)) and the Saferpay Transaction ([Integration Guide](https://saferpay.github.io/sndbx/Integration_trx.html), [JSON API documentation](https://saferpay.github.io/sndbx/Integration_trx.html)).
|
4
4
|
|
5
|
+
### Disclaimer
|
6
|
+
This gem is built to be a general-purpose integration of the Six Saferpay payment interface. However due to lack of resources and because we are (as far as we know) the only users of this gem, we are only testing our use cases (PaymentPage). Therefore we can not guarantee that this will work in any other solidus shop. If you consider using this gem, please test everything thoroughly.
|
7
|
+
|
5
8
|
## Status
|
6
9
|
Travis CI status: [![Build Status](https://travis-ci.org/fadendaten/solidus_six_saferpay.svg?branch=master)](https://travis-ci.org/fadendaten/solidus_six_saferpay)
|
7
10
|
|
@@ -18,7 +18,10 @@ let SaferpayPayment = {
|
|
18
18
|
},
|
19
19
|
|
20
20
|
error: function(xhr) {
|
21
|
-
|
21
|
+
// We have no other option for displaying this message, so to inform
|
22
|
+
// the user we must alert
|
23
|
+
alert(xhr.responseJSON.errors);
|
24
|
+
window.location.replace(xhr.responseJSON.redirect_url);
|
22
25
|
return false;
|
23
26
|
},
|
24
27
|
})
|
@@ -3,11 +3,25 @@ module Spree
|
|
3
3
|
class CheckoutController < StoreController
|
4
4
|
|
5
5
|
def init
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
6
|
+
order_number = params[:order_number]
|
7
|
+
@order = Spree::Order.find_by(number: order_number)
|
8
|
+
|
9
|
+
# We must make sure that the order for which the user requests a
|
10
|
+
# payment is still their `current_order`.
|
11
|
+
# This can be false if the user tries to add something to the cart
|
12
|
+
# after getting to the payment checkout step, and then switches back to
|
13
|
+
# the payment step and starts the payment process by selecting a
|
14
|
+
# payment method.
|
15
|
+
# In that case, we redirect to the checkout path so the user needs to
|
16
|
+
# go through the checkout process again to ensure that the real
|
17
|
+
# `current_order` contains all necessary information.
|
18
|
+
if @order.nil? || @order != current_order
|
19
|
+
render json: {
|
20
|
+
redirect_url: spree.cart_path,
|
21
|
+
errors: t('.order_was_modified_after_confirmation')
|
22
|
+
}, status: 422
|
23
|
+
return
|
24
|
+
end
|
11
25
|
|
12
26
|
payment_method = Spree::PaymentMethod.find(params[:payment_method_id])
|
13
27
|
initialized_payment = initialize_payment(@order, payment_method)
|
@@ -16,16 +30,35 @@ module Spree
|
|
16
30
|
redirect_url = initialized_payment.redirect_url
|
17
31
|
render json: { redirect_url: redirect_url }
|
18
32
|
else
|
19
|
-
render json: {
|
33
|
+
render json: {
|
34
|
+
redirect_url: spree.cart_path,
|
35
|
+
errors: t('.checkout_not_initialized')
|
36
|
+
}, status: 422
|
20
37
|
end
|
21
38
|
end
|
22
39
|
|
23
40
|
def success
|
24
|
-
|
25
|
-
|
26
|
-
|
41
|
+
order_number = params[:order_number]
|
42
|
+
@order = Spree::Order.find_by(number: order_number)
|
43
|
+
|
27
44
|
if @order.nil?
|
28
|
-
|
45
|
+
OrderNotFoundHandler.call(controller_context: self, order_number: order_number)
|
46
|
+
|
47
|
+
flash[:error] = t('.error_while_processing_payment')
|
48
|
+
@redirect_path ||= spree.cart_path
|
49
|
+
|
50
|
+
render :iframe_breakout_redirect, layout: false
|
51
|
+
return
|
52
|
+
end
|
53
|
+
|
54
|
+
saferpay_payment = Spree::SixSaferpayPayment.where(order_id: @order.id).order(:created_at).last
|
55
|
+
|
56
|
+
if saferpay_payment.nil?
|
57
|
+
PaymentNotFoundHandler.call(controller_context: self, order: @order)
|
58
|
+
|
59
|
+
flash[:error] = t('.error_while_processing_payment')
|
60
|
+
@redirect_path ||= spree.cart_path
|
61
|
+
|
29
62
|
render :iframe_breakout_redirect, layout: false
|
30
63
|
return
|
31
64
|
end
|
@@ -33,17 +66,14 @@ module Spree
|
|
33
66
|
# ensure that completed orders don't try to reprocess the
|
34
67
|
# authorization. This could happen if a user presses the back button
|
35
68
|
# after completing an order.
|
69
|
+
# There is no error handling because it should look like you are simply
|
70
|
+
# redirected to the cart page.
|
36
71
|
if @order.completed?
|
37
72
|
@redirect_path = spree.cart_path
|
38
73
|
render :iframe_breakout_redirect, layout: false
|
39
74
|
return
|
40
75
|
end
|
41
76
|
|
42
|
-
saferpay_payment = Spree::SixSaferpayPayment.where(order_id: @order.id).order(:created_at).last
|
43
|
-
|
44
|
-
if saferpay_payment.nil?
|
45
|
-
raise Spree::Core::GatewayError, t('.saferpay_payment_not_found')
|
46
|
-
end
|
47
77
|
|
48
78
|
# NOTE: PaymentPage payments are authorized directly. Instead, we
|
49
79
|
# perform an ASSERT here to gather the necessary details.
|
@@ -60,7 +90,7 @@ module Spree
|
|
60
90
|
|
61
91
|
processed_authorization = process_authorization(saferpay_payment)
|
62
92
|
if processed_authorization.success?
|
63
|
-
|
93
|
+
PaymentProcessingSuccessHandler.call(controller_context: self, order: @order)
|
64
94
|
else
|
65
95
|
flash[:error] = processed_authorization.user_message
|
66
96
|
end
|
@@ -75,24 +105,34 @@ module Spree
|
|
75
105
|
end
|
76
106
|
|
77
107
|
def fail
|
78
|
-
|
79
|
-
|
80
|
-
|
108
|
+
order_number = params[:order_number]
|
109
|
+
@order = Spree::Order.find_by(number: order_number)
|
110
|
+
|
81
111
|
if @order.nil?
|
82
|
-
|
112
|
+
OrderNotFoundHandler.call(controller_context: self, order_number: order_number)
|
113
|
+
|
114
|
+
flash[:error] = t('.error_while_processing_payment')
|
115
|
+
@redirect_path ||= spree.cart_path
|
116
|
+
|
83
117
|
render :iframe_breakout_redirect, layout: false
|
84
118
|
return
|
85
119
|
end
|
86
120
|
|
87
121
|
saferpay_payment = Spree::SixSaferpayPayment.where(order_id: @order.id).order(:created_at).last
|
88
122
|
|
89
|
-
if saferpay_payment
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
123
|
+
if saferpay_payment.nil?
|
124
|
+
PaymentNotFoundHandler.call(controller_context: self, order: @order)
|
125
|
+
|
126
|
+
flash[:error] = t('.error_while_processing_payment')
|
127
|
+
@redirect_path = spree.cart_path
|
128
|
+
render :iframe_breakout_redirect, layout: false
|
129
|
+
return
|
94
130
|
end
|
95
131
|
|
132
|
+
|
133
|
+
payment_inquiry = inquire_payment(saferpay_payment)
|
134
|
+
flash[:error] = payment_inquiry.user_message
|
135
|
+
|
96
136
|
@redirect_path = order_checkout_path(:payment)
|
97
137
|
render :iframe_breakout_redirect, layout: false
|
98
138
|
end
|
@@ -115,22 +155,6 @@ module Spree
|
|
115
155
|
raise NotImplementedError, "Must be implemented in PaymentPageCheckoutController or TransactionCheckoutController"
|
116
156
|
end
|
117
157
|
|
118
|
-
# Allows overriding of success behaviour in host application by setting
|
119
|
-
# SolidusSixSaferpay.config.payment_processing_success_handler
|
120
|
-
#
|
121
|
-
# By default, it will ensure that the order state is no longer "payment"
|
122
|
-
#
|
123
|
-
# Example
|
124
|
-
# config.payment_processing_success_handler = Proc.new { |order| puts "Order #{order} has been successfully paid!" }
|
125
|
-
#
|
126
|
-
def handle_payment_processing_success
|
127
|
-
if success_handler = ::SolidusSixSaferpay.config.payment_processing_success_handler.presence
|
128
|
-
success_handler.call(self, @order)
|
129
|
-
else
|
130
|
-
@order.next! if @order.payment?
|
131
|
-
end
|
132
|
-
end
|
133
|
-
|
134
158
|
def order_checkout_path(state)
|
135
159
|
Spree::Core::Engine.routes.url_helpers.checkout_state_path(state)
|
136
160
|
end
|
@@ -1,7 +1,7 @@
|
|
1
1
|
module Spree
|
2
2
|
module SolidusSixSaferpay
|
3
|
-
# explicit parent must be stated, otherwise Spree::CheckoutController has precendence
|
4
3
|
module Transaction
|
4
|
+
# explicit parent must be stated, otherwise Spree::CheckoutController has precendence
|
5
5
|
class CheckoutController < SolidusSixSaferpay::CheckoutController
|
6
6
|
|
7
7
|
private
|
@@ -0,0 +1,33 @@
|
|
1
|
+
module Spree
|
2
|
+
module SolidusSixSaferpay
|
3
|
+
class CancelAuthorizedPayment
|
4
|
+
|
5
|
+
attr_reader :saferpay_payment
|
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
|
+
end
|
14
|
+
|
15
|
+
def call
|
16
|
+
if transaction_id = saferpay_payment.transaction_id
|
17
|
+
gateway.void(saferpay_payment.transaction_id)
|
18
|
+
else
|
19
|
+
::SolidusSixSaferpay::ErrorHandler.handle(
|
20
|
+
::SolidusSixSaferpay::InvalidSaferpayPayment.new(
|
21
|
+
details: "Can not cancel payment #{saferpay_payment.id} because it has no transaction ID.")
|
22
|
+
)
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
private
|
27
|
+
|
28
|
+
def gateway
|
29
|
+
::SolidusSixSaferpay::Gateway.new
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
@@ -19,8 +19,9 @@ module Spree
|
|
19
19
|
inquiry = gateway.inquire(saferpay_payment)
|
20
20
|
|
21
21
|
if inquiry.success?
|
22
|
-
saferpay_payment.update_attributes(
|
22
|
+
saferpay_payment.update_attributes(saferpay_payment_attributes(inquiry.api_response))
|
23
23
|
else
|
24
|
+
saferpay_payment.update_attributes(response_hash: saferpay_payment.response_hash.merge(error: "#{inquiry.error_name}"))
|
24
25
|
general_error = I18n.t(:general_error, scope: [:solidus_six_saferpay, :errors])
|
25
26
|
specific_error = I18n.t(inquiry.error_name, scope: [:six_saferpay, :error_names])
|
26
27
|
@user_message = "#{general_error}: #{specific_error}"
|
@@ -38,6 +39,31 @@ module Spree
|
|
38
39
|
def gateway
|
39
40
|
raise NotImplementedError, "Must be implemented in AssertPaymentPage or AuthorizeTransaction with UsePaymentPageGateway or UseTransactionGateway"
|
40
41
|
end
|
42
|
+
|
43
|
+
private
|
44
|
+
|
45
|
+
def saferpay_payment_attributes(saferpay_response)
|
46
|
+
payment_means = saferpay_response.payment_means
|
47
|
+
brand = payment_means.brand
|
48
|
+
card = payment_means.card
|
49
|
+
|
50
|
+
attributes = {
|
51
|
+
transaction_id: saferpay_response.transaction.id,
|
52
|
+
transaction_status: saferpay_response.transaction.status,
|
53
|
+
transaction_date: DateTime.parse(saferpay_response.transaction.date),
|
54
|
+
six_transaction_reference: saferpay_response.transaction.six_transaction_reference,
|
55
|
+
display_text: saferpay_response.payment_means.display_text,
|
56
|
+
response_hash: saferpay_response.to_h
|
57
|
+
}
|
58
|
+
|
59
|
+
if card
|
60
|
+
attributes[:masked_number] = card.masked_number
|
61
|
+
attributes[:expiration_year] = card.exp_year
|
62
|
+
attributes[:expiration_month] = card.exp_month
|
63
|
+
end
|
64
|
+
|
65
|
+
attributes
|
66
|
+
end
|
41
67
|
end
|
42
68
|
end
|
43
69
|
end
|
@@ -0,0 +1,28 @@
|
|
1
|
+
module Spree
|
2
|
+
module SolidusSixSaferpay
|
3
|
+
|
4
|
+
# This handler can be overridden by host applications to manage control
|
5
|
+
# flow if no order can be found when SIX Saferpay performs the callback
|
6
|
+
# request after the user submits a payment.
|
7
|
+
# If not overridden, the handler will simply trigger an error.
|
8
|
+
class OrderNotFoundHandler
|
9
|
+
|
10
|
+
attr_reader :controller_context, :order_number
|
11
|
+
|
12
|
+
def self.call(controller_context:, order_number:)
|
13
|
+
new(controller_context: controller_context, order_number: order_number).call
|
14
|
+
end
|
15
|
+
|
16
|
+
def initialize(controller_context:, order_number:)
|
17
|
+
@controller_context = controller_context
|
18
|
+
@order_number = order_number
|
19
|
+
end
|
20
|
+
|
21
|
+
def call
|
22
|
+
::SolidusSixSaferpay::ErrorHandler.handle(
|
23
|
+
StandardError.new("No solidus order could be found for number #{order_number}")
|
24
|
+
)
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
@@ -0,0 +1,28 @@
|
|
1
|
+
module Spree
|
2
|
+
module SolidusSixSaferpay
|
3
|
+
|
4
|
+
# This handler can be overridden by host applications to manage control
|
5
|
+
# flow if no payment can be found when SIX Saferpay performs the callback
|
6
|
+
# request after the user submits a payment.
|
7
|
+
# If not overridden, the handler will simply trigger an error.
|
8
|
+
class PaymentNotFoundHandler
|
9
|
+
|
10
|
+
attr_reader :controller_context, :order
|
11
|
+
|
12
|
+
def self.call(controller_context:, order:)
|
13
|
+
new(controller_context: controller_context, order: order).call
|
14
|
+
end
|
15
|
+
|
16
|
+
def initialize(controller_context:, order:)
|
17
|
+
@controller_context = controller_context
|
18
|
+
@order = order
|
19
|
+
end
|
20
|
+
|
21
|
+
def call
|
22
|
+
::SolidusSixSaferpay::ErrorHandler.handle(
|
23
|
+
StandardError.new("No Saferpay Payment found for order #{order.number}")
|
24
|
+
)
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
@@ -0,0 +1,26 @@
|
|
1
|
+
module Spree
|
2
|
+
module SolidusSixSaferpay
|
3
|
+
|
4
|
+
# This handler can be overridden by host applications to manage control
|
5
|
+
# flow after the payment authorization was successful and the payment was verified.
|
6
|
+
# If not overridden, the handler will simply ensure that the order has
|
7
|
+
# moved from the "payment" state to the next state.
|
8
|
+
class PaymentProcessingSuccessHandler
|
9
|
+
|
10
|
+
attr_reader :controller_context, :order
|
11
|
+
|
12
|
+
def self.call(controller_context:, order:)
|
13
|
+
new(controller_context: controller_context, order: order).call
|
14
|
+
end
|
15
|
+
|
16
|
+
def initialize(controller_context:, order:)
|
17
|
+
@controller_context = controller_context
|
18
|
+
@order = order
|
19
|
+
end
|
20
|
+
|
21
|
+
def call
|
22
|
+
order.next! if order.payment?
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
@@ -3,10 +3,10 @@
|
|
3
3
|
<iframe class="saferpay-iframe" width='100%' height='550px' id="<%= payment_container_id %>" src="" frameborder="0">
|
4
4
|
</iframe>
|
5
5
|
<script charset="utf-8">
|
6
|
-
SaferpayPayment.registerIframePaymentMethod({id: "<%= payment_method.id %>", initUrl: "<%= payment_method.init_path %>", containerId: "#<%= payment_container_id %>"})
|
6
|
+
SaferpayPayment.registerIframePaymentMethod({id: "<%= payment_method.id %>", initUrl: "<%= payment_method.init_path(@order) %>", containerId: "#<%= payment_container_id %>"})
|
7
7
|
</script>
|
8
8
|
<% else %>
|
9
9
|
<script charset="utf-8">
|
10
|
-
SaferpayPayment.registerExternalRedirectPaymentMethod({id: "<%= payment_method.id %>", initUrl: "<%= payment_method.init_path %>"})
|
10
|
+
SaferpayPayment.registerExternalRedirectPaymentMethod({id: "<%= payment_method.id %>", initUrl: "<%= payment_method.init_path(@order) %>"})
|
11
11
|
</script>
|
12
12
|
<% end %>
|