solidus-adyen 0.1.2
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.gitignore +26 -0
- data/.rubocop.yml +9 -0
- data/.rubocop_todo.yml +325 -0
- data/Gemfile +9 -0
- data/LICENSE.txt +22 -0
- data/README.md +238 -0
- data/Rakefile +16 -0
- data/app/assets/javascripts/spree/backend/solidus-adyen.js +1 -0
- data/app/assets/javascripts/spree/checkout/payment/adyen.js +10 -0
- data/app/assets/javascripts/spree/frontend/solidus-adyen.js +1 -0
- data/app/assets/stylesheets/spree/backend/solidus-adyen/buttons.scss +15 -0
- data/app/assets/stylesheets/spree/backend/solidus-adyen/communication.scss +121 -0
- data/app/assets/stylesheets/spree/backend/solidus-adyen/variables.scss +4 -0
- data/app/assets/stylesheets/spree/backend/solidus-adyen.css +5 -0
- data/app/assets/stylesheets/spree/frontend/solidus-adyen.css +3 -0
- data/app/controllers/concerns/spree/adyen/admin/refunds_controller.rb +59 -0
- data/app/controllers/spree/adyen/hpps_controller.rb +22 -0
- data/app/controllers/spree/adyen_notifications_controller.rb +34 -0
- data/app/controllers/spree/adyen_redirect_controller.rb +90 -0
- data/app/models/adyen_notification.rb +159 -0
- data/app/models/concerns/spree/adyen/order.rb +11 -0
- data/app/models/concerns/spree/adyen/payment.rb +95 -0
- data/app/models/spree/adyen/hpp_source.rb +101 -0
- data/app/models/spree/adyen/notification_processor.rb +102 -0
- data/app/models/spree/adyen/presenters/communication.rb +31 -0
- data/app/models/spree/adyen/presenters/communications/adyen_notification.rb +26 -0
- data/app/models/spree/adyen/presenters/communications/base.rb +50 -0
- data/app/models/spree/adyen/presenters/communications/hpp_source.rb +31 -0
- data/app/models/spree/adyen/presenters/communications/log_entry.rb +28 -0
- data/app/models/spree/adyen/presenters/communications.rb +9 -0
- data/app/models/spree/gateway/adyen_hpp.rb +95 -0
- data/app/overrides/spree/admin/shared/_order_summary.rb +6 -0
- data/app/views/spree/admin/payments/source_forms/_adyen.html.erb +1 -0
- data/app/views/spree/admin/payments/source_views/_adyen.html.erb +14 -0
- data/app/views/spree/adyen/_manual_refund.html.erb +9 -0
- data/app/views/spree/adyen/communication/_communication.html.erb +42 -0
- data/app/views/spree/adyen/hpps/directory.html.erb +10 -0
- data/app/views/spree/checkout/payment/_adyen.html.erb +33 -0
- data/bin/checkout.rb +111 -0
- data/bin/regen.sh +1 -0
- data/config/initializers/solidus_adyen.rb +1 -0
- data/config/locales/en.yml +23 -0
- data/config/routes.rb +13 -0
- data/db/migrate/20131017040945_create_adyen_notifications.rb +29 -0
- data/db/migrate/20150911201942_add_index_adyen_notifications_psp_reference.rb +5 -0
- data/db/migrate/20150914162539_create_spree_adyen_hpp_sources.rb +21 -0
- data/db/migrate/20151007090519_add_days_to_ship_to_config.rb +5 -0
- data/db/migrate/20151020230830_remove_indices_on_adyen_notifications.rb +6 -0
- data/db/migrate/20151106093023_allow_merchant_reference_to_be_null_for_adyen_notification.rb +5 -0
- data/lib/solidus-adyen.rb +1 -0
- data/lib/spree/adyen/engine.rb +32 -0
- data/lib/spree/adyen/form.rb +135 -0
- data/lib/spree/adyen/hpp_check.rb +11 -0
- data/lib/spree/adyen/url.rb +30 -0
- data/lib/spree/adyen/version.rb +5 -0
- data/lib/spree/adyen.rb +6 -0
- data/solidus-adyen.gemspec +51 -0
- data/spec/controllers/concerns/spree/adyen/admin/refunds_controller_spec.rb +76 -0
- data/spec/controllers/spree/adyen/hpps_controller_spec.rb +43 -0
- data/spec/controllers/spree/adyen_notifications_controller_spec.rb +118 -0
- data/spec/controllers/spree/adyen_redirect_controller_spec.rb +154 -0
- data/spec/factories/active_merchant_billing_response.rb +23 -0
- data/spec/factories/adyen_notification.rb +91 -0
- data/spec/factories/spree_adyen_hpp_source.rb +15 -0
- data/spec/factories/spree_gateway_adyen_hpp.rb +23 -0
- data/spec/factories/spree_payment.rb +13 -0
- data/spec/lib/spree/adyen/form_spec.rb +214 -0
- data/spec/models/adyen_notification_spec.rb +86 -0
- data/spec/models/concerns/spree/adyen/order_spec.rb +22 -0
- data/spec/models/concerns/spree/adyen/payment_spec.rb +93 -0
- data/spec/models/spree/adyen/hpp_source_spec.rb +101 -0
- data/spec/models/spree/adyen/notification_processor_spec.rb +205 -0
- data/spec/models/spree/adyen/presenters/communication_spec.rb +62 -0
- data/spec/models/spree/gateway/adyen_hpp_spec.rb +76 -0
- data/spec/spec_helper.rb +65 -0
- data/spec/support/shared_contexts/mock_adyen_api.rb +47 -0
- metadata +463 -0
@@ -0,0 +1,101 @@
|
|
1
|
+
# This models the response that is received after a user is redirected from the
|
2
|
+
# Adyen Hosted Payment Pages. It's used as the the source for the Spree::Payment
|
3
|
+
# and keeps track of the messages received from the notifications end point.
|
4
|
+
#
|
5
|
+
# Attributes defined are dervived from the docs:
|
6
|
+
# https://docs.adyen.com/display/TD/HPP+payment+response
|
7
|
+
#
|
8
|
+
# Information about when certain action are valid:
|
9
|
+
# https://docs.adyen.com/display/TD/HPP+modifications
|
10
|
+
module Spree::Adyen
|
11
|
+
class HppSource < ::ActiveRecord::Base
|
12
|
+
MANUALLY_REFUNDABLE = [
|
13
|
+
"directEbanking"
|
14
|
+
].freeze
|
15
|
+
|
16
|
+
PENDING = "PENDING".freeze
|
17
|
+
AUTHORISED = "AUTHORISED".freeze
|
18
|
+
REFUSED = "REFUSED".freeze
|
19
|
+
CANCELLED = "CANCELLED".freeze
|
20
|
+
|
21
|
+
# support updates from capital-cased responses, which is what adyen gives
|
22
|
+
# us
|
23
|
+
alias_attribute :authResult, :auth_result
|
24
|
+
alias_attribute :pspReference, :psp_reference
|
25
|
+
alias_attribute :merchantReference, :merchant_reference
|
26
|
+
alias_attribute :skinCode, :skin_code
|
27
|
+
alias_attribute :merchantSig, :merchant_sig
|
28
|
+
alias_attribute :paymentMethod, :payment_method
|
29
|
+
alias_attribute :shopperLocale, :shopper_locale
|
30
|
+
alias_attribute :merchantReturnData, :merchant_return_data
|
31
|
+
|
32
|
+
belongs_to :order, class_name: "Spree::Order",
|
33
|
+
primary_key: :number,
|
34
|
+
foreign_key: :merchant_reference
|
35
|
+
|
36
|
+
has_one :payment, class_name: "Spree::Payment", as: :source
|
37
|
+
|
38
|
+
# FIXME should change this to find the auth notification by order number,
|
39
|
+
# then all notification that have a original ref that matches it's psp
|
40
|
+
has_many :notifications,
|
41
|
+
class_name: "AdyenNotification",
|
42
|
+
foreign_key: :merchant_reference,
|
43
|
+
primary_key: :merchant_reference
|
44
|
+
|
45
|
+
def can_capture? payment
|
46
|
+
payment.uncaptured_amount != 0.0
|
47
|
+
end
|
48
|
+
|
49
|
+
def actions
|
50
|
+
if mutable?
|
51
|
+
authorised_actions
|
52
|
+
else
|
53
|
+
[]
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
57
|
+
def can_cancel? payment
|
58
|
+
payment.refunds.empty?
|
59
|
+
end
|
60
|
+
|
61
|
+
def requires_manual_refund?
|
62
|
+
MANUALLY_REFUNDABLE.include?(payment_method)
|
63
|
+
end
|
64
|
+
|
65
|
+
def authorised?
|
66
|
+
# Many banks return pending, this is considered a valid response and
|
67
|
+
# the order should proceed.
|
68
|
+
[PENDING, AUTHORISED].include? auth_result
|
69
|
+
end
|
70
|
+
|
71
|
+
private
|
72
|
+
def mutable?
|
73
|
+
!payment.void? && !payment.processing?
|
74
|
+
end
|
75
|
+
|
76
|
+
# authorised_actions :: [String] | []
|
77
|
+
def authorised_actions
|
78
|
+
if auth_notification
|
79
|
+
auth_notification.
|
80
|
+
actions.map(&method(:transform_action))
|
81
|
+
|
82
|
+
else
|
83
|
+
[]
|
84
|
+
|
85
|
+
end
|
86
|
+
end
|
87
|
+
|
88
|
+
def transform_action action
|
89
|
+
if action == "refund"
|
90
|
+
# return credit so that we go to the new refund action
|
91
|
+
"credit"
|
92
|
+
else
|
93
|
+
action
|
94
|
+
end
|
95
|
+
end
|
96
|
+
|
97
|
+
def auth_notification
|
98
|
+
notifications.processed.authorisation.last
|
99
|
+
end
|
100
|
+
end
|
101
|
+
end
|
@@ -0,0 +1,102 @@
|
|
1
|
+
module Spree
|
2
|
+
module Adyen
|
3
|
+
class NotificationProcessor
|
4
|
+
attr_accessor :notification, :payment
|
5
|
+
|
6
|
+
def initialize(notification, payment = nil)
|
7
|
+
self.notification = notification
|
8
|
+
self.payment = payment ? payment : notification.payment
|
9
|
+
end
|
10
|
+
|
11
|
+
# for the given payment, process all notifications that are currently
|
12
|
+
# unprocessed in the order that they were dispatched.
|
13
|
+
def self.process_outstanding!(payment)
|
14
|
+
Spree::Payment.transaction do
|
15
|
+
payment.
|
16
|
+
source.
|
17
|
+
notifications(true). # bypass caching
|
18
|
+
unprocessed.
|
19
|
+
as_dispatched.
|
20
|
+
map do |notification|
|
21
|
+
new(notification, payment).process!
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
# only process the notification if there is a matching payment there's a
|
27
|
+
# number of reasons why there may not be a matching payment such as test
|
28
|
+
# notifications, reports etc, we just log them and then accept
|
29
|
+
def process!
|
30
|
+
Spree::Payment.transaction do
|
31
|
+
if payment
|
32
|
+
if !notification.success?
|
33
|
+
handle_failure
|
34
|
+
|
35
|
+
elsif notification.modification_event?
|
36
|
+
handle_modification_event
|
37
|
+
|
38
|
+
elsif notification.normal_event?
|
39
|
+
handle_normal_event
|
40
|
+
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
return notification
|
46
|
+
end
|
47
|
+
|
48
|
+
private
|
49
|
+
|
50
|
+
def handle_failure
|
51
|
+
notification.processed!
|
52
|
+
# ignore failures if the payment was already completed
|
53
|
+
return if payment.completed?
|
54
|
+
# might have to do something else on modification events,
|
55
|
+
# namely refunds
|
56
|
+
payment.failure!
|
57
|
+
end
|
58
|
+
|
59
|
+
def handle_modification_event
|
60
|
+
if notification.capture?
|
61
|
+
notification.processed!
|
62
|
+
complete_payment!
|
63
|
+
|
64
|
+
elsif notification.cancel_or_refund?
|
65
|
+
notification.processed!
|
66
|
+
payment.void
|
67
|
+
|
68
|
+
elsif notification.refund?
|
69
|
+
payment.refunds.create!(
|
70
|
+
amount: notification.value / 100, # cents to dollars
|
71
|
+
transaction_id: notification.psp_reference,
|
72
|
+
refund_reason_id: ::Spree::RefundReason.first.id # FIXME
|
73
|
+
)
|
74
|
+
# payment was processing, move back to completed
|
75
|
+
payment.complete!
|
76
|
+
notification.processed!
|
77
|
+
end
|
78
|
+
end
|
79
|
+
|
80
|
+
# normal event is defined as just AUTHORISATION
|
81
|
+
def handle_normal_event
|
82
|
+
if notification.auto_captured?
|
83
|
+
complete_payment!
|
84
|
+
|
85
|
+
else
|
86
|
+
payment.capture!
|
87
|
+
|
88
|
+
end
|
89
|
+
notification.processed!
|
90
|
+
end
|
91
|
+
|
92
|
+
def complete_payment!
|
93
|
+
money = ::Money.new(notification.value, notification.currency)
|
94
|
+
|
95
|
+
# this is copied from Spree::Payment::Processing#capture
|
96
|
+
payment.capture_events.create!(amount: money.to_f)
|
97
|
+
payment.update!(amount: payment.captured_amount)
|
98
|
+
payment.complete!
|
99
|
+
end
|
100
|
+
end
|
101
|
+
end
|
102
|
+
end
|
@@ -0,0 +1,31 @@
|
|
1
|
+
module Spree
|
2
|
+
module Adyen
|
3
|
+
module Presenters
|
4
|
+
# Factory for creating communication presenters, based on a payment
|
5
|
+
# source.
|
6
|
+
class Communication < SimpleDelegator
|
7
|
+
PRESENTERS = [
|
8
|
+
::Spree::Adyen::Presenters::Communications::AdyenNotification,
|
9
|
+
::Spree::Adyen::Presenters::Communications::HppSource,
|
10
|
+
::Spree::Adyen::Presenters::Communications::LogEntry
|
11
|
+
].freeze
|
12
|
+
|
13
|
+
def self.from_source source
|
14
|
+
([source] + source.notifications + source.payment.log_entries).
|
15
|
+
sort_by(&:created_at).
|
16
|
+
map { |x| build x }
|
17
|
+
end
|
18
|
+
|
19
|
+
def self.build object
|
20
|
+
presenter_for(object).new(object)
|
21
|
+
end
|
22
|
+
|
23
|
+
def self.presenter_for object
|
24
|
+
PRESENTERS.detect do |klass|
|
25
|
+
klass.applicable? object
|
26
|
+
end || fail("Couldn't map to a communication type")
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
@@ -0,0 +1,26 @@
|
|
1
|
+
module Spree
|
2
|
+
module Adyen
|
3
|
+
module Presenters
|
4
|
+
module Communications
|
5
|
+
class AdyenNotification <
|
6
|
+
::Spree::Adyen::Presenters::Communications::Base
|
7
|
+
|
8
|
+
def fields
|
9
|
+
{ event_code: event_code,
|
10
|
+
reason: reason,
|
11
|
+
amount: money.format
|
12
|
+
}
|
13
|
+
end
|
14
|
+
|
15
|
+
def inbound?
|
16
|
+
true
|
17
|
+
end
|
18
|
+
|
19
|
+
def self.applicable? obj
|
20
|
+
obj.is_a? ::AdyenNotification
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
@@ -0,0 +1,50 @@
|
|
1
|
+
module Spree
|
2
|
+
module Adyen
|
3
|
+
module Presenters
|
4
|
+
module Communications
|
5
|
+
# Base presenters for generic server-api communication representation
|
6
|
+
#
|
7
|
+
# All communication presenters are expected to implement
|
8
|
+
# fields
|
9
|
+
# success?
|
10
|
+
# processed?
|
11
|
+
# inbound?
|
12
|
+
class Base < SimpleDelegator
|
13
|
+
# force to_partial_path to be called on the delegator and not the
|
14
|
+
# delgatee
|
15
|
+
def to_model
|
16
|
+
self
|
17
|
+
end
|
18
|
+
|
19
|
+
def to_partial_path
|
20
|
+
"spree/adyen/communication/communication"
|
21
|
+
end
|
22
|
+
|
23
|
+
def created_at_s
|
24
|
+
created_at.strftime "%d %b %H:%M:%S.%4N"
|
25
|
+
end
|
26
|
+
|
27
|
+
def present_fields
|
28
|
+
fields.compact
|
29
|
+
end
|
30
|
+
|
31
|
+
def css_class
|
32
|
+
[
|
33
|
+
success? ? "success" : "failure",
|
34
|
+
processed? ? "processed" : "unprocessed",
|
35
|
+
inbound? ? "received" : "sent"
|
36
|
+
].
|
37
|
+
map { |klass| css_prefix klass }.
|
38
|
+
join(" ")
|
39
|
+
end
|
40
|
+
|
41
|
+
private
|
42
|
+
|
43
|
+
def css_prefix klass
|
44
|
+
"adyen-comm-" + klass
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
@@ -0,0 +1,31 @@
|
|
1
|
+
module Spree
|
2
|
+
module Adyen
|
3
|
+
module Presenters
|
4
|
+
module Communications
|
5
|
+
class HppSource < ::Spree::Adyen::Presenters::Communications::Base
|
6
|
+
def fields
|
7
|
+
{ result: auth_result,
|
8
|
+
payment_method: payment_method
|
9
|
+
}
|
10
|
+
end
|
11
|
+
|
12
|
+
def success?
|
13
|
+
true
|
14
|
+
end
|
15
|
+
|
16
|
+
def processed?
|
17
|
+
true
|
18
|
+
end
|
19
|
+
|
20
|
+
def inbound?
|
21
|
+
true
|
22
|
+
end
|
23
|
+
|
24
|
+
def self.applicable? obj
|
25
|
+
obj.is_a? Spree::Adyen::HppSource
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
@@ -0,0 +1,28 @@
|
|
1
|
+
module Spree
|
2
|
+
module Adyen
|
3
|
+
module Presenters
|
4
|
+
module Communications
|
5
|
+
class LogEntry < ::Spree::Adyen::Presenters::Communications::Base
|
6
|
+
delegate :success?, :message, to: :parsed_details
|
7
|
+
|
8
|
+
def processed?
|
9
|
+
true
|
10
|
+
end
|
11
|
+
|
12
|
+
def inbound?
|
13
|
+
false
|
14
|
+
end
|
15
|
+
|
16
|
+
def fields
|
17
|
+
{ message: message
|
18
|
+
}
|
19
|
+
end
|
20
|
+
|
21
|
+
def self.applicable? obj
|
22
|
+
obj.is_a? Spree::LogEntry
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
@@ -0,0 +1,95 @@
|
|
1
|
+
module Spree
|
2
|
+
# Gateway for Adyen Hosted Payment Pages solution
|
3
|
+
class Gateway::AdyenHPP < Gateway
|
4
|
+
preference :skin_code, :string
|
5
|
+
preference :shared_secret, :string
|
6
|
+
preference :days_to_ship, :integer, default: 1
|
7
|
+
preference :api_username, :string
|
8
|
+
preference :api_password, :string
|
9
|
+
preference :merchant_account, :string
|
10
|
+
|
11
|
+
def merchant_account
|
12
|
+
ENV["ADYEN_MERCHANT_ACCOUNT"] || preferred_merchant_account
|
13
|
+
end
|
14
|
+
|
15
|
+
def provider_class
|
16
|
+
::Adyen::API
|
17
|
+
end
|
18
|
+
|
19
|
+
def provider
|
20
|
+
::Adyen.configuration.api_username =
|
21
|
+
(ENV["ADYEN_API_USERNAME"] || preferred_api_username)
|
22
|
+
::Adyen.configuration.api_password =
|
23
|
+
(ENV["ADYEN_API_PASSWORD"] || preferred_api_password)
|
24
|
+
::Adyen.configuration.default_api_params[:merchant_account] =
|
25
|
+
merchant_account
|
26
|
+
|
27
|
+
provider_class
|
28
|
+
end
|
29
|
+
|
30
|
+
def method_type
|
31
|
+
"adyen"
|
32
|
+
end
|
33
|
+
|
34
|
+
def shared_secret
|
35
|
+
ENV["ADYEN_SHARED_SECRET"] || preferred_shared_secret
|
36
|
+
end
|
37
|
+
|
38
|
+
def skin_code
|
39
|
+
ENV["ADYEN_SKIN_CODE"] || preferred_skin_code
|
40
|
+
end
|
41
|
+
|
42
|
+
def ship_before_date
|
43
|
+
preferred_days_to_ship.days.from_now
|
44
|
+
end
|
45
|
+
|
46
|
+
def authorize(amount, source, gateway_options)
|
47
|
+
# to get around the order checking for processed payments we create payments
|
48
|
+
# in the checkout state and allow the payment method to attempt to auth
|
49
|
+
# them here. We just return a dummy response here because the payment has
|
50
|
+
# already been authorized
|
51
|
+
ActiveMerchant::Billing::Response.new(true, "successful hpp payment")
|
52
|
+
end
|
53
|
+
|
54
|
+
def capture(amount, psp_reference, currency:, **_opts)
|
55
|
+
value = { currency: currency, value: amount }
|
56
|
+
|
57
|
+
handle_response(
|
58
|
+
provider.capture_payment(psp_reference, value),
|
59
|
+
psp_reference)
|
60
|
+
end
|
61
|
+
|
62
|
+
def cancel(psp_reference, _gateway_options = {})
|
63
|
+
handle_response(
|
64
|
+
provider.cancel_or_refund_payment(psp_reference),
|
65
|
+
psp_reference)
|
66
|
+
end
|
67
|
+
|
68
|
+
def credit(amount, psp_reference, currency:, **_opts)
|
69
|
+
amount = { currency: currency, value: amount }
|
70
|
+
|
71
|
+
handle_response(
|
72
|
+
provider.refund_payment(psp_reference, amount),
|
73
|
+
psp_reference)
|
74
|
+
end
|
75
|
+
|
76
|
+
private
|
77
|
+
|
78
|
+
def handle_response response, original_reference
|
79
|
+
ActiveMerchant::Billing::Response.new(
|
80
|
+
response.success?,
|
81
|
+
message(response),
|
82
|
+
{},
|
83
|
+
authorization: original_reference
|
84
|
+
)
|
85
|
+
end
|
86
|
+
|
87
|
+
def message response
|
88
|
+
if response.success?
|
89
|
+
JSON.pretty_generate(response.params)
|
90
|
+
else
|
91
|
+
response.fault_message
|
92
|
+
end
|
93
|
+
end
|
94
|
+
end
|
95
|
+
end
|
@@ -0,0 +1 @@
|
|
1
|
+
Cannot create Hpp payments on the backend.
|
@@ -0,0 +1,14 @@
|
|
1
|
+
<% content_for :page_actions do %>
|
2
|
+
<li>
|
3
|
+
<%=
|
4
|
+
link_to "View in Customer Area",
|
5
|
+
Spree::Adyen::URL.payment_adyen_customer_area_url(
|
6
|
+
merchant_account: payment.payment_method.preferred_merchant_account,
|
7
|
+
psp_reference: payment.response_code
|
8
|
+
),
|
9
|
+
class: "button fa"
|
10
|
+
%>
|
11
|
+
</li>
|
12
|
+
<% end %>
|
13
|
+
|
14
|
+
<%= render Spree::Adyen::Presenters::Communication.from_source(payment.source) %>
|
@@ -0,0 +1,42 @@
|
|
1
|
+
<%= content_tag :div, class: "#{communication.css_class} clearfix" do %>
|
2
|
+
<div class="adyen-comm">
|
3
|
+
<div class="adyen-comm-body">
|
4
|
+
<div class="adyen-comm-icon">
|
5
|
+
<% if !communication.processed? %>
|
6
|
+
<i
|
7
|
+
class="fa fa-warning adyen-comm-icon-unprocessed"
|
8
|
+
title="<%= t("solidus-adyen.payment.unprocessed")%>"
|
9
|
+
></i>
|
10
|
+
<% end %>
|
11
|
+
<% if communication.success? %>
|
12
|
+
<i
|
13
|
+
class="fa fa-check adyen-comm-icon-success"
|
14
|
+
title="<%= t("solidus-adyen.payment.success")%>"
|
15
|
+
></i>
|
16
|
+
<% else %>
|
17
|
+
<i
|
18
|
+
class="fa fa-times adyen-comm-icon-failure"
|
19
|
+
title="<%= t("solidus-adyen.payment.failure")%>"
|
20
|
+
></i>
|
21
|
+
<% end %>
|
22
|
+
</div>
|
23
|
+
<div>
|
24
|
+
<div class="adyen-comm-content">
|
25
|
+
<% communication.present_fields.each do |name, val| %>
|
26
|
+
<div class="adyen-comm-content-row">
|
27
|
+
<div class="adyen-comm-content-cell">
|
28
|
+
<%= t(".#{name}") %>
|
29
|
+
</div>
|
30
|
+
<div class="adyen-comm-content-cell">
|
31
|
+
<%= val %>
|
32
|
+
</div>
|
33
|
+
</div>
|
34
|
+
<% end %>
|
35
|
+
</div>
|
36
|
+
<p class="adyen-comm-timestamp">
|
37
|
+
<%= communication.created_at_s %>
|
38
|
+
</p>
|
39
|
+
</div>
|
40
|
+
</div>
|
41
|
+
</div>
|
42
|
+
<% end %>
|
@@ -0,0 +1,33 @@
|
|
1
|
+
<% content_for :head do %>
|
2
|
+
<%= javascript_include_tag 'spree/checkout/payment/adyen.js' %>
|
3
|
+
<% end %>
|
4
|
+
|
5
|
+
<p>
|
6
|
+
You'll be redirected to Adyen Hosted Payment Pages. After completing the
|
7
|
+
payment form you'll be back to the store.
|
8
|
+
</p>
|
9
|
+
|
10
|
+
<%= content_tag :div, "", id: 'adyen-hpp-details', data: {
|
11
|
+
url: directory_adyen_hpp_path(
|
12
|
+
order_id: @order.id,
|
13
|
+
payment_method_id: payment_method.id) } %>
|
14
|
+
|
15
|
+
<script type="text/javascript">
|
16
|
+
$(function() {
|
17
|
+
var spreePaymentRadio = $("#checkout_form_payment input:radio")
|
18
|
+
|
19
|
+
var hideCheckoutButtonForAdyen = function() {
|
20
|
+
if ($("#checkout_form_payment input:radio:checked").val() == <%= payment_method.id %>) {
|
21
|
+
$("#checkout_form_payment .form-buttons").hide();
|
22
|
+
} else {
|
23
|
+
$("#checkout_form_payment .form-buttons").show();
|
24
|
+
}
|
25
|
+
}
|
26
|
+
|
27
|
+
spreePaymentRadio.change(function() {
|
28
|
+
hideCheckoutButtonForAdyen();
|
29
|
+
});
|
30
|
+
|
31
|
+
hideCheckoutButtonForAdyen();
|
32
|
+
});
|
33
|
+
</script>
|