spree_vpago 2.4.0.pre.pre2 → 2.4.0.pre.pre3
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 +4 -4
- data/Gemfile.lock +27 -26
- data/app/controllers/spree/admin/payment_acleda_v2_base_controller.rb +21 -0
- data/app/controllers/spree/admin/payment_acleda_v2_checkers_controller.rb +26 -0
- data/app/controllers/spree/admin/payment_acleda_v2_queriers_controller.rb +38 -0
- data/app/controllers/spree/admin/payment_payway_queriers_controller.rb +7 -0
- data/app/controllers/spree/admin/payment_vattanac_base_controller.rb +21 -0
- data/app/controllers/spree/admin/payment_vattanac_checkers_controller.rb +26 -0
- data/app/controllers/spree/admin/payment_vattanac_queriers_controller.rb +38 -0
- data/app/controllers/spree/vpago_payments_controller.rb +15 -3
- data/app/helpers/vpago/vpago_payments_helper.rb +6 -0
- data/app/models/vpago/payment_decorator.rb +0 -4
- data/app/models/vpago/payment_method_decorator.rb +8 -6
- data/app/serializers/spree/v2/storefront/payment_method_serializer_decorator.rb +6 -0
- data/app/views/spree/admin/payments/source_views/_acleda_v2.html.erb +2 -2
- data/app/views/spree/admin/payments/source_views/_vattanac.html.erb +3 -3
- data/app/views/spree/vpago_payments/_success_script.html.erb +7 -0
- data/app/views/spree/vpago_payments/success.html.erb +2 -0
- data/config/locales/en.yml +1 -0
- data/config/locales/km.yml +1 -0
- data/config/routes.rb +6 -7
- data/lib/spree_vpago/engine.rb +0 -1
- data/lib/spree_vpago/version.rb +1 -1
- data/lib/vpago/acleda_v2/payment_request_updater.rb +54 -0
- data/lib/vpago/http_timeouts.rb +6 -0
- data/lib/vpago/payway_v2/payment_request_updater.rb +5 -0
- data/lib/vpago/payway_v2/transaction_status.rb +2 -0
- data/lib/vpago/payway_v2/transaction_status_v2.rb +2 -0
- data/lib/vpago/true_money/base.rb +1 -1
- data/lib/vpago/true_money/transaction_status.rb +1 -1
- data/lib/vpago/vattanac/base.rb +3 -2
- data/lib/vpago/vattanac/payment_request_updater.rb +54 -0
- data/lib/vpago/vattanac/transaction_status.rb +17 -1
- data/spree_vpago.gemspec +1 -1
- metadata +16 -12
- data/app/controllers/spree/miniapp/acledas_controller.rb +0 -29
- data/app/models/spree/gateway/acleda_mini_app.rb +0 -20
- data/app/services/vpago/acleda_mini_app/session/create.rb +0 -99
- data/app/views/spree/admin/payments/source_views/_acleda_mini_app.html.erb +0 -6
- data/app/views/spree/vpago_payments/forms/spree/gateway/_acleda_mini_app.html.erb +0 -93
- data/lib/vpago/acleda_mini_app/checkout.rb +0 -23
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: e361db28503471424737c1633bb7e5fcacccdc7c1a63faddd76ad3e226ceb6f7
|
|
4
|
+
data.tar.gz: cd5936a07fdfcfb314ac0d068d88b0e6137e6f5cb7e37295aa034368bcea33af
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: e5691409e7f910c70fd1012358eafc766b45131e4db286106f5a58a8390c0f7bb2ad1fbba892805a6f7ab3b4ec75bb77f8df1e76ccde90f153efadc6e835bed0
|
|
7
|
+
data.tar.gz: 874db861928b7f5cd71ccd9d17172057de242748f2cc0c11735b03a49951c80151d02cde118ee4ea21961209113529bb1e89562c9e6e8e843f38c4369ef03f71
|
data/Gemfile.lock
CHANGED
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
PATH
|
|
2
2
|
remote: .
|
|
3
3
|
specs:
|
|
4
|
-
spree_vpago (2.4.0.pre.
|
|
4
|
+
spree_vpago (2.4.0.pre.pre3)
|
|
5
5
|
faraday
|
|
6
6
|
google-cloud-firestore
|
|
7
7
|
spree_api (>= 4.5)
|
|
8
8
|
spree_backend (>= 4.5)
|
|
9
9
|
spree_core (>= 4.5)
|
|
10
|
-
spree_extension
|
|
10
|
+
spree_extension (< 1.0)
|
|
11
11
|
spree_multi_vendor (>= 2.4.1)
|
|
12
12
|
|
|
13
13
|
GEM
|
|
@@ -128,7 +128,7 @@ GEM
|
|
|
128
128
|
babel-source (>= 4.0, < 6)
|
|
129
129
|
execjs (~> 2.0)
|
|
130
130
|
base64 (0.3.0)
|
|
131
|
-
bcrypt (3.1.
|
|
131
|
+
bcrypt (3.1.22)
|
|
132
132
|
bigdecimal (3.1.8)
|
|
133
133
|
bootstrap (4.6.2.1)
|
|
134
134
|
autoprefixer-rails (>= 9.1.0)
|
|
@@ -176,10 +176,11 @@ GEM
|
|
|
176
176
|
rainbow (>= 2.1.0)
|
|
177
177
|
diff-lcs (1.5.0)
|
|
178
178
|
docile (1.4.0)
|
|
179
|
-
doorkeeper (5.
|
|
179
|
+
doorkeeper (5.9.9)
|
|
180
180
|
railties (>= 5)
|
|
181
181
|
erubi (1.12.0)
|
|
182
|
-
execjs (2.10.
|
|
182
|
+
execjs (2.10.2)
|
|
183
|
+
json (>= 2)
|
|
183
184
|
factory_bot (4.11.1)
|
|
184
185
|
activesupport (>= 3.0.0)
|
|
185
186
|
faraday (2.7.4)
|
|
@@ -188,7 +189,7 @@ GEM
|
|
|
188
189
|
faraday-http-cache (2.5.0)
|
|
189
190
|
faraday (>= 0.8)
|
|
190
191
|
faraday-net_http (3.0.2)
|
|
191
|
-
faraday-retry (2.
|
|
192
|
+
faraday-retry (2.4.0)
|
|
192
193
|
faraday (~> 2.0)
|
|
193
194
|
ffaker (2.21.0)
|
|
194
195
|
ffi (1.15.5)
|
|
@@ -198,7 +199,7 @@ GEM
|
|
|
198
199
|
flatpickr (4.6.13.1)
|
|
199
200
|
friendly_id (5.5.0)
|
|
200
201
|
activerecord (>= 4.0.0)
|
|
201
|
-
gapic-common (1.
|
|
202
|
+
gapic-common (1.5.0)
|
|
202
203
|
faraday (>= 1.9, < 3.a)
|
|
203
204
|
faraday-retry (>= 1.0, < 3.a)
|
|
204
205
|
google-cloud-env (~> 2.2)
|
|
@@ -207,7 +208,7 @@ GEM
|
|
|
207
208
|
googleapis-common-protos (~> 1.6)
|
|
208
209
|
googleapis-common-protos-types (~> 1.15)
|
|
209
210
|
googleauth (~> 1.12)
|
|
210
|
-
grpc (
|
|
211
|
+
grpc (>= 1.83, < 2.a)
|
|
211
212
|
gem-release (2.2.2)
|
|
212
213
|
github_changelog_generator (1.16.4)
|
|
213
214
|
activesupport
|
|
@@ -221,45 +222,45 @@ GEM
|
|
|
221
222
|
globalid (1.1.0)
|
|
222
223
|
activesupport (>= 5.0)
|
|
223
224
|
glyphicons (1.0.2)
|
|
224
|
-
google-cloud-core (1.
|
|
225
|
+
google-cloud-core (1.9.0)
|
|
225
226
|
google-cloud-env (>= 1.0, < 3.a)
|
|
226
227
|
google-cloud-errors (~> 1.0)
|
|
227
|
-
google-cloud-env (2.
|
|
228
|
+
google-cloud-env (2.4.0)
|
|
228
229
|
base64 (~> 0.2)
|
|
229
230
|
faraday (>= 1.0, < 3.a)
|
|
230
|
-
google-cloud-errors (1.
|
|
231
|
-
google-cloud-firestore (3.
|
|
231
|
+
google-cloud-errors (1.7.0)
|
|
232
|
+
google-cloud-firestore (3.2.0)
|
|
232
233
|
bigdecimal (~> 3.0)
|
|
233
234
|
concurrent-ruby (~> 1.0)
|
|
234
235
|
google-cloud-core (~> 1.7)
|
|
235
236
|
google-cloud-firestore-v1 (~> 2.0)
|
|
236
237
|
rbtree (~> 0.4.2)
|
|
237
|
-
google-cloud-firestore-v1 (2.
|
|
238
|
-
gapic-common (~> 1.
|
|
238
|
+
google-cloud-firestore-v1 (2.4.0)
|
|
239
|
+
gapic-common (~> 1.3)
|
|
239
240
|
google-cloud-errors (~> 1.0)
|
|
240
241
|
google-cloud-location (~> 1.0)
|
|
241
|
-
google-cloud-location (1.
|
|
242
|
-
gapic-common (~> 1.
|
|
242
|
+
google-cloud-location (1.5.1)
|
|
243
|
+
gapic-common (~> 1.3)
|
|
243
244
|
google-cloud-errors (~> 1.0)
|
|
244
245
|
google-logging-utils (0.2.0)
|
|
245
|
-
google-protobuf (4.33.
|
|
246
|
+
google-protobuf (4.33.6)
|
|
246
247
|
bigdecimal
|
|
247
248
|
rake (>= 13)
|
|
248
|
-
googleapis-common-protos (1.
|
|
249
|
+
googleapis-common-protos (1.10.0)
|
|
249
250
|
google-protobuf (~> 4.26)
|
|
250
251
|
googleapis-common-protos-types (~> 1.21)
|
|
251
252
|
grpc (~> 1.41)
|
|
252
|
-
googleapis-common-protos-types (1.
|
|
253
|
+
googleapis-common-protos-types (1.23.0)
|
|
253
254
|
google-protobuf (~> 4.26)
|
|
254
|
-
googleauth (1.
|
|
255
|
+
googleauth (1.17.4)
|
|
255
256
|
faraday (>= 1.0, < 3.a)
|
|
256
257
|
google-cloud-env (~> 2.2)
|
|
257
258
|
google-logging-utils (~> 0.1)
|
|
258
259
|
jwt (>= 1.4, < 4.0)
|
|
259
|
-
multi_json (~> 1.11)
|
|
260
260
|
os (>= 0.9, < 2.0)
|
|
261
|
+
pstore (~> 0.1)
|
|
261
262
|
signet (>= 0.16, < 2.a)
|
|
262
|
-
grpc (1.
|
|
263
|
+
grpc (1.84.0)
|
|
263
264
|
google-protobuf (>= 3.25, < 5.0)
|
|
264
265
|
googleapis-common-protos-types (~> 1.0)
|
|
265
266
|
hashdiff (1.1.0)
|
|
@@ -369,6 +370,7 @@ GEM
|
|
|
369
370
|
pry (0.14.2)
|
|
370
371
|
coderay (~> 1.1)
|
|
371
372
|
method_source (~> 1.0)
|
|
373
|
+
pstore (0.2.1)
|
|
372
374
|
public_suffix (5.0.1)
|
|
373
375
|
puma (6.2.2)
|
|
374
376
|
nio4r (~> 2.0)
|
|
@@ -412,13 +414,13 @@ GEM
|
|
|
412
414
|
activerecord (>= 6.0.4)
|
|
413
415
|
activesupport (>= 6.0.4)
|
|
414
416
|
i18n
|
|
415
|
-
rbtree (0.4.
|
|
417
|
+
rbtree (0.4.7)
|
|
416
418
|
redis (5.0.6)
|
|
417
419
|
redis-client (>= 0.9.0)
|
|
418
420
|
redis-client (0.14.1)
|
|
419
421
|
connection_pool
|
|
420
422
|
regexp_parser (2.11.3)
|
|
421
|
-
responders (3.2.
|
|
423
|
+
responders (3.2.1)
|
|
422
424
|
actionpack (>= 7.0)
|
|
423
425
|
railties (>= 7.0)
|
|
424
426
|
rexml (3.2.9)
|
|
@@ -492,11 +494,10 @@ GEM
|
|
|
492
494
|
websocket (~> 1.0)
|
|
493
495
|
shoulda-matchers (6.2.0)
|
|
494
496
|
activesupport (>= 5.2.0)
|
|
495
|
-
signet (0.
|
|
497
|
+
signet (0.22.0)
|
|
496
498
|
addressable (~> 2.8)
|
|
497
499
|
faraday (>= 0.17.5, < 3.a)
|
|
498
500
|
jwt (>= 1.5, < 4.0)
|
|
499
|
-
multi_json (~> 1.10)
|
|
500
501
|
simplecov (0.22.0)
|
|
501
502
|
docile (~> 1.1)
|
|
502
503
|
simplecov-html (~> 0.11)
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
module Spree
|
|
2
|
+
module Admin
|
|
3
|
+
class PaymentAcledaV2BaseController < Spree::Admin::BaseController
|
|
4
|
+
include Spree::Backend::Callbacks
|
|
5
|
+
|
|
6
|
+
before_action :load_payment, only: %i[show update]
|
|
7
|
+
before_action :validate_order, only: [:update]
|
|
8
|
+
|
|
9
|
+
def validate_order
|
|
10
|
+
return unless @payment.order.completed?
|
|
11
|
+
|
|
12
|
+
flash[:error] = Spree.t('vpago.payments.not_allow_for_order_completed')
|
|
13
|
+
redirect_to admin_order_payment_path(order_id: @payment.order.number, id: @payment.number)
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
def load_payment
|
|
17
|
+
@payment = Payment.find_by!(number: params[:id])
|
|
18
|
+
end
|
|
19
|
+
end
|
|
20
|
+
end
|
|
21
|
+
end
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
module Spree
|
|
2
|
+
module Admin
|
|
3
|
+
class PaymentAcledaV2CheckersController < PaymentAcledaV2BaseController
|
|
4
|
+
include Spree::Backend::Callbacks
|
|
5
|
+
|
|
6
|
+
def update
|
|
7
|
+
options = {
|
|
8
|
+
updated_by_user_id: try_spree_current_user.id,
|
|
9
|
+
updated_reason: Spree.t('vpago.payments.checker_updated_by_description')
|
|
10
|
+
}
|
|
11
|
+
spree_updater = Vpago::AcledaV2::PaymentRequestUpdater.new(@payment, options)
|
|
12
|
+
spree_updater.call
|
|
13
|
+
|
|
14
|
+
@payment.reload
|
|
15
|
+
|
|
16
|
+
if @payment.order.completed?
|
|
17
|
+
flash[:success] = Spree.t(:successfully_updated, resource: Spree.t(:payments))
|
|
18
|
+
else
|
|
19
|
+
flash[:error] = Spree.t(:unsuccessfully_updated, resource: Spree.t(:payments))
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
redirect_to admin_order_payment_path(order_id: @payment.order.number, id: @payment.number)
|
|
23
|
+
end
|
|
24
|
+
end
|
|
25
|
+
end
|
|
26
|
+
end
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
module Spree
|
|
2
|
+
module Admin
|
|
3
|
+
class PaymentAcledaV2QueriersController < PaymentAcledaV2BaseController
|
|
4
|
+
include Spree::Backend::Callbacks
|
|
5
|
+
|
|
6
|
+
around_action :set_writing_role, only: %i[show]
|
|
7
|
+
|
|
8
|
+
def show
|
|
9
|
+
tran_status = @payment.payment_method.check_transaction(@payment)
|
|
10
|
+
|
|
11
|
+
if tran_status.success?
|
|
12
|
+
@payment.update_column(:gateway_status, true)
|
|
13
|
+
flash[:success] =
|
|
14
|
+
Spree.t('vpago.payments.payment_found_with_result', result: tran_status.json_response)
|
|
15
|
+
else
|
|
16
|
+
flash[:error] = Spree.t('vpago.payments.payment_not_found_with_error', error: tran_status.error_message)
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
redirect_to admin_order_payment_path(order_id: @payment.order.number, id: @payment.number)
|
|
20
|
+
rescue Faraday::TimeoutError, Faraday::ConnectionFailed => e
|
|
21
|
+
VpagoLogger.error(
|
|
22
|
+
label: 'Spree::Admin::PaymentAcledaV2QueriersController#show gateway_timeout',
|
|
23
|
+
data: { payment_number: @payment.number, error_class: e.class.name, error_message: e.message }
|
|
24
|
+
)
|
|
25
|
+
flash[:error] = Spree.t('vpago.payments.gateway_timeout')
|
|
26
|
+
redirect_to admin_order_payment_path(order_id: @payment.order.number, id: @payment.number)
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
private
|
|
30
|
+
|
|
31
|
+
def set_writing_role
|
|
32
|
+
ActiveRecord::Base.connected_to(role: :writing) do
|
|
33
|
+
yield if block_given?
|
|
34
|
+
end
|
|
35
|
+
end
|
|
36
|
+
end
|
|
37
|
+
end
|
|
38
|
+
end
|
|
@@ -16,6 +16,13 @@ module Spree
|
|
|
16
16
|
flash[:error] = Spree.t('vpago.payments.payment_not_found_with_error', error: tran_status.error_message)
|
|
17
17
|
end
|
|
18
18
|
|
|
19
|
+
redirect_to admin_order_payment_path(order_id: @payment.order.number, id: @payment.number)
|
|
20
|
+
rescue Faraday::TimeoutError, Faraday::ConnectionFailed => e
|
|
21
|
+
VpagoLogger.error(
|
|
22
|
+
label: 'Spree::Admin::PaymentPaywayQueriersController#show gateway_timeout',
|
|
23
|
+
data: { payment_number: @payment.number, error_class: e.class.name, error_message: e.message }
|
|
24
|
+
)
|
|
25
|
+
flash[:error] = Spree.t('vpago.payments.gateway_timeout')
|
|
19
26
|
redirect_to admin_order_payment_path(order_id: @payment.order.number, id: @payment.number)
|
|
20
27
|
end
|
|
21
28
|
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
module Spree
|
|
2
|
+
module Admin
|
|
3
|
+
class PaymentVattanacBaseController < Spree::Admin::BaseController
|
|
4
|
+
include Spree::Backend::Callbacks
|
|
5
|
+
|
|
6
|
+
before_action :load_payment, only: %i[show update]
|
|
7
|
+
before_action :validate_order, only: [:update]
|
|
8
|
+
|
|
9
|
+
def validate_order
|
|
10
|
+
return unless @payment.order.completed?
|
|
11
|
+
|
|
12
|
+
flash[:error] = Spree.t('vpago.payments.not_allow_for_order_completed')
|
|
13
|
+
redirect_to admin_order_payment_path(order_id: @payment.order.number, id: @payment.number)
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
def load_payment
|
|
17
|
+
@payment = Payment.find_by!(number: params[:id])
|
|
18
|
+
end
|
|
19
|
+
end
|
|
20
|
+
end
|
|
21
|
+
end
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
module Spree
|
|
2
|
+
module Admin
|
|
3
|
+
class PaymentVattanacCheckersController < PaymentVattanacBaseController
|
|
4
|
+
include Spree::Backend::Callbacks
|
|
5
|
+
|
|
6
|
+
def update
|
|
7
|
+
options = {
|
|
8
|
+
updated_by_user_id: try_spree_current_user.id,
|
|
9
|
+
updated_reason: Spree.t('vpago.payments.checker_updated_by_description')
|
|
10
|
+
}
|
|
11
|
+
spree_updater = Vpago::Vattanac::PaymentRequestUpdater.new(@payment, options)
|
|
12
|
+
spree_updater.call
|
|
13
|
+
|
|
14
|
+
@payment.reload
|
|
15
|
+
|
|
16
|
+
if @payment.order.completed?
|
|
17
|
+
flash[:success] = Spree.t(:successfully_updated, resource: Spree.t(:payments))
|
|
18
|
+
else
|
|
19
|
+
flash[:error] = Spree.t(:unsuccessfully_updated, resource: Spree.t(:payments))
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
redirect_to admin_order_payment_path(order_id: @payment.order.number, id: @payment.number)
|
|
23
|
+
end
|
|
24
|
+
end
|
|
25
|
+
end
|
|
26
|
+
end
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
module Spree
|
|
2
|
+
module Admin
|
|
3
|
+
class PaymentVattanacQueriersController < PaymentVattanacBaseController
|
|
4
|
+
include Spree::Backend::Callbacks
|
|
5
|
+
|
|
6
|
+
around_action :set_writing_role, only: %i[show]
|
|
7
|
+
|
|
8
|
+
def show
|
|
9
|
+
tran_status = @payment.payment_method.check_transaction(@payment)
|
|
10
|
+
|
|
11
|
+
if tran_status.success?
|
|
12
|
+
@payment.update_column(:gateway_status, true)
|
|
13
|
+
flash[:success] =
|
|
14
|
+
Spree.t('vpago.payments.payment_found_with_result', result: tran_status.json_response)
|
|
15
|
+
else
|
|
16
|
+
flash[:error] = Spree.t('vpago.payments.payment_not_found_with_error', error: tran_status.error_message)
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
redirect_to admin_order_payment_path(order_id: @payment.order.number, id: @payment.number)
|
|
20
|
+
rescue Faraday::TimeoutError, Faraday::ConnectionFailed => e
|
|
21
|
+
VpagoLogger.error(
|
|
22
|
+
label: 'Spree::Admin::PaymentVattanacQueriersController#show gateway_timeout',
|
|
23
|
+
data: { payment_number: @payment.number, error_class: e.class.name, error_message: e.message }
|
|
24
|
+
)
|
|
25
|
+
flash[:error] = Spree.t('vpago.payments.gateway_timeout')
|
|
26
|
+
redirect_to admin_order_payment_path(order_id: @payment.order.number, id: @payment.number)
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
private
|
|
30
|
+
|
|
31
|
+
def set_writing_role
|
|
32
|
+
ActiveRecord::Base.connected_to(role: :writing) do
|
|
33
|
+
yield if block_given?
|
|
34
|
+
end
|
|
35
|
+
end
|
|
36
|
+
end
|
|
37
|
+
end
|
|
38
|
+
end
|
|
@@ -24,6 +24,12 @@ module Spree
|
|
|
24
24
|
def processing
|
|
25
25
|
@order = @payment.order
|
|
26
26
|
|
|
27
|
+
# Common, not an edge case: the gateway callback or the checkout page's transaction
|
|
28
|
+
# checker often completes the order before the browser lands here. Skipping this page
|
|
29
|
+
# also skips its Firebase listener, so success must post order_is_completed itself
|
|
30
|
+
# (render_success_script) or an embedding iframe modal never closes.
|
|
31
|
+
return redirect_to @payment.success_url, allow_other_host: true if @order.completed?
|
|
32
|
+
|
|
27
33
|
VpagoLogger.log(label: 'Spree::VpagoPaymentsController#processing', data: vpago_log_context)
|
|
28
34
|
end
|
|
29
35
|
|
|
@@ -60,6 +66,12 @@ module Spree
|
|
|
60
66
|
else
|
|
61
67
|
render json: { status: :pending }, status: :ok
|
|
62
68
|
end
|
|
69
|
+
rescue Faraday::TimeoutError, Faraday::ConnectionFailed => e
|
|
70
|
+
VpagoLogger.error(
|
|
71
|
+
label: 'Spree::VpagoPaymentsController#check_transaction gateway_timeout',
|
|
72
|
+
data: vpago_log_context(error_class: e.class.name, error_message: e.message)
|
|
73
|
+
)
|
|
74
|
+
render json: { status: :pending }, status: :ok
|
|
63
75
|
end
|
|
64
76
|
|
|
65
77
|
# POST
|
|
@@ -146,9 +158,9 @@ module Spree
|
|
|
146
158
|
raise ActiveRecord::RecordNotFound unless @payment.present?
|
|
147
159
|
end
|
|
148
160
|
|
|
149
|
-
#
|
|
150
|
-
#
|
|
151
|
-
#
|
|
161
|
+
# These pages are embedded in iframes on many partner sites we don't
|
|
162
|
+
# enumerate, so framing is left unrestricted: no frame-ancestors policy, and
|
|
163
|
+
# Rails' default SAMEORIGIN header is dropped for the iframe actions.
|
|
152
164
|
def allow_iframe_embedding
|
|
153
165
|
response.headers.delete('X-Frame-Options')
|
|
154
166
|
end
|
|
@@ -13,6 +13,12 @@ module Vpago
|
|
|
13
13
|
render partial: 'spree/vpago_payments/transaction_checker'
|
|
14
14
|
end
|
|
15
15
|
|
|
16
|
+
# Host apps override success.html.erb; call this from every override so an
|
|
17
|
+
# embedding iframe modal still learns the order completed.
|
|
18
|
+
def render_success_script
|
|
19
|
+
render partial: 'spree/vpago_payments/success_script'
|
|
20
|
+
end
|
|
21
|
+
|
|
16
22
|
# Each payment method may have their own additional processing script,
|
|
17
23
|
# so we will look for the partial based on the payment method class name.
|
|
18
24
|
#
|
|
@@ -6,7 +6,6 @@ module Vpago
|
|
|
6
6
|
TYPE_ACLEDA = 'Spree::Gateway::Acleda'.freeze
|
|
7
7
|
TYPE_ACLEDA_V2 = 'Spree::Gateway::AcledaV2'.freeze
|
|
8
8
|
TYPE_ACLEDA_MOBILE = 'Spree::Gateway::AcledaMobile'.freeze
|
|
9
|
-
TYPE_ACLEDA_MINI_APP = 'Spree::Gateway::AcledaMiniApp'.freeze
|
|
10
9
|
TYPE_TRUE_MONEY = 'Spree::Gateway::TrueMoney'.freeze
|
|
11
10
|
TYPE_VATTANAC = 'Spree::Gateway::Vattanac'.freeze
|
|
12
11
|
TYPE_VATTANAC_MINI_APP = 'Spree::Gateway::VattanacMiniApp'.freeze
|
|
@@ -25,7 +24,6 @@ module Vpago
|
|
|
25
24
|
Spree::PaymentMethod::TYPE_ACLEDA,
|
|
26
25
|
Spree::PaymentMethod::TYPE_ACLEDA_V2,
|
|
27
26
|
Spree::PaymentMethod::TYPE_ACLEDA_MOBILE,
|
|
28
|
-
Spree::PaymentMethod::TYPE_ACLEDA_MINI_APP,
|
|
29
27
|
Spree::PaymentMethod::TYPE_VATTANAC,
|
|
30
28
|
Spree::PaymentMethod::TYPE_VATTANAC_MINI_APP,
|
|
31
29
|
Spree::PaymentMethod::TYPE_TRUE_MONEY,
|
|
@@ -82,6 +80,10 @@ module Vpago
|
|
|
82
80
|
::Vpago::Acleda::PaymentRequestUpdater
|
|
83
81
|
elsif type_acleda_mobile?
|
|
84
82
|
::Vpago::AcledaMobile::PaymentRequestUpdater
|
|
83
|
+
elsif type_acleda_v2?
|
|
84
|
+
::Vpago::AcledaV2::PaymentRequestUpdater
|
|
85
|
+
elsif type_vattanac?
|
|
86
|
+
::Vpago::Vattanac::PaymentRequestUpdater
|
|
85
87
|
end
|
|
86
88
|
end
|
|
87
89
|
|
|
@@ -97,10 +99,6 @@ module Vpago
|
|
|
97
99
|
type == Spree::PaymentMethod::TYPE_ACLEDA_V2
|
|
98
100
|
end
|
|
99
101
|
|
|
100
|
-
def type_acleda_mini_app?
|
|
101
|
-
type == Spree::PaymentMethod::TYPE_ACLEDA_MINI_APP
|
|
102
|
-
end
|
|
103
|
-
|
|
104
102
|
def type_payway?
|
|
105
103
|
type == Spree::PaymentMethod::TYPE_PAYWAY
|
|
106
104
|
end
|
|
@@ -113,6 +111,10 @@ module Vpago
|
|
|
113
111
|
type == Spree::PaymentMethod::TYPE_WINGSDK
|
|
114
112
|
end
|
|
115
113
|
|
|
114
|
+
def type_vattanac?
|
|
115
|
+
type == Spree::PaymentMethod::TYPE_VATTANAC
|
|
116
|
+
end
|
|
117
|
+
|
|
116
118
|
def type_vattanac_mini_app?
|
|
117
119
|
type == Spree::PaymentMethod::TYPE_VATTANAC_MINI_APP
|
|
118
120
|
end
|
|
@@ -14,6 +14,12 @@ module Spree
|
|
|
14
14
|
|
|
15
15
|
pref.blank? || pref[:payment_option].blank? ? payment_method.method_type : pref[:payment_option]
|
|
16
16
|
end
|
|
17
|
+
|
|
18
|
+
# Overried the payment method type to show all payment methods as one list on App.
|
|
19
|
+
# Controlled by ENV["PAYMENT_METHOD_VIEW"] = "split" | "join" (default: "join").
|
|
20
|
+
base.attribute :type do |payment_method|
|
|
21
|
+
ENV.fetch('PAYMENT_METHOD_VIEW', 'join') == 'split' ? payment_method.type : 'payment_method'
|
|
22
|
+
end
|
|
17
23
|
end
|
|
18
24
|
end
|
|
19
25
|
end
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
<%= render 'spree/admin/payments/source_views/vpago_payment_tmpl',
|
|
2
2
|
payment: payment,
|
|
3
|
-
check_status_url:
|
|
4
|
-
heal_payment_url:
|
|
3
|
+
check_status_url: admin_payment_acleda_v2_querier_path(payment),
|
|
4
|
+
heal_payment_url: admin_payment_acleda_v2_checker_path(payment),
|
|
5
5
|
manual_update_payment_url: '' %>
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
<%= render 'spree/admin/payments/source_views/vpago_payment_tmpl',
|
|
2
|
-
payment: payment,
|
|
3
|
-
check_status_url:
|
|
4
|
-
heal_payment_url:
|
|
2
|
+
payment: payment,
|
|
3
|
+
check_status_url: admin_payment_vattanac_querier_path(payment),
|
|
4
|
+
heal_payment_url: admin_payment_vattanac_checker_path(payment),
|
|
5
5
|
manual_update_payment_url: ''
|
|
6
6
|
%>
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
<script>
|
|
2
|
+
// processing redirects here without rendering once the order is complete, so its
|
|
3
|
+
// Firebase listener never posts this. success only renders for completed orders.
|
|
4
|
+
if (window.parent !== window) {
|
|
5
|
+
window.parent.postMessage("order_is_completed", "*");
|
|
6
|
+
}
|
|
7
|
+
</script>
|
data/config/locales/en.yml
CHANGED
|
@@ -35,5 +35,6 @@ en:
|
|
|
35
35
|
failed_require_updated_reason: "You must provide update reason"
|
|
36
36
|
payment_found_with_result: "Found payment with result: %{result}"
|
|
37
37
|
payment_not_found_with_error: "Payment not found with error: %{error}"
|
|
38
|
+
gateway_timeout: "The payment gateway did not respond in time. Please try again shortly."
|
|
38
39
|
query_status: "Query payment status"
|
|
39
40
|
confirm_manual_update: "Are you sure to update this order to complete"
|
data/config/locales/km.yml
CHANGED
|
@@ -31,5 +31,6 @@ spree:
|
|
|
31
31
|
failed_require_updated_reason: "អ្នកត្រូវតែផ្តល់ហេតុផល"
|
|
32
32
|
payment_found_with_result: "រកឃើញការទូទាត់ជាមួយលទ្ធផល %{result}"
|
|
33
33
|
payment_not_found_with_error: "ការទូទាត់មិនត្រូវបានរកឃើញដោយកំហុស: %{error}"
|
|
34
|
+
gateway_timeout: "ផ្នែកទូទាត់មិនបានឆ្លើយតបទាន់ពេលទេ។ សូមព្យាយាមម្តងទៀតក្នុងពេលឆាប់ៗនេះ។"
|
|
34
35
|
query_status: "សួរស្ថានភាពបង់ប្រាក់"
|
|
35
36
|
confirm_manual_update: "តើអ្នកប្រាកដជាធ្វើបច្ចុប្បន្នភាពការបញ្ជាទិញនេះដើម្បីបញ្ចប់"
|
data/config/routes.rb
CHANGED
|
@@ -17,13 +17,6 @@ Spree::Core::Engine.add_routes do
|
|
|
17
17
|
resources :transactions, only: [:show]
|
|
18
18
|
end
|
|
19
19
|
|
|
20
|
-
# ACLEDA Mini App session init (ACLEDA Mini App Integration Spec, Step 01).
|
|
21
|
-
# ACLEDA calls POST /miniapp/acleda with { phone, first_name, last_name }
|
|
22
|
-
# and receives a session-based miniAppUrl.
|
|
23
|
-
namespace :miniapp do
|
|
24
|
-
resources :acleda, only: [:create], controller: 'acledas'
|
|
25
|
-
end
|
|
26
|
-
|
|
27
20
|
resource :vpago_payments do
|
|
28
21
|
collection do
|
|
29
22
|
get :checkout
|
|
@@ -80,6 +73,12 @@ Spree::Core::Engine.add_routes do
|
|
|
80
73
|
resources :payment_payway_checkers
|
|
81
74
|
resources :payment_payway_markers
|
|
82
75
|
|
|
76
|
+
resources :payment_acleda_v2_queriers, only: [:show]
|
|
77
|
+
resources :payment_acleda_v2_checkers, only: [:update]
|
|
78
|
+
|
|
79
|
+
resources :payment_vattanac_queriers, only: [:show]
|
|
80
|
+
resources :payment_vattanac_checkers, only: [:update]
|
|
81
|
+
|
|
83
82
|
resources :products do
|
|
84
83
|
resources :payout_profile_products
|
|
85
84
|
end
|
data/lib/spree_vpago/engine.rb
CHANGED
data/lib/spree_vpago/version.rb
CHANGED
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
module Vpago
|
|
2
|
+
module AcledaV2
|
|
3
|
+
class PaymentRequestUpdater < ::Vpago::PaymentRequestUpdater
|
|
4
|
+
def call
|
|
5
|
+
return if @payment.order.paid?
|
|
6
|
+
|
|
7
|
+
if items_eligible?
|
|
8
|
+
process_payment_status
|
|
9
|
+
else
|
|
10
|
+
mark_items_as_ineligible
|
|
11
|
+
end
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
private
|
|
15
|
+
|
|
16
|
+
def process_payment_status
|
|
17
|
+
checker = @payment.payment_method.check_transaction(@payment)
|
|
18
|
+
|
|
19
|
+
if checker.success?
|
|
20
|
+
mark_payment_as_success
|
|
21
|
+
elsif checker.failed? && !ignore_on_failed?
|
|
22
|
+
mark_payment_as_failed(checker.error_message)
|
|
23
|
+
end
|
|
24
|
+
rescue Faraday::TimeoutError, Faraday::ConnectionFailed => e
|
|
25
|
+
VpagoLogger.error(
|
|
26
|
+
label: 'Vpago::AcledaV2::PaymentRequestUpdater#process_payment_status gateway_timeout',
|
|
27
|
+
data: { payment_number: @payment.number, error_class: e.class.name, error_message: e.message }
|
|
28
|
+
)
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
def items_eligible?
|
|
32
|
+
@payment&.order&.line_items&.all?(&:sufficient_stock?) == true # rubocop:disable Style/SafeNavigationChainLength
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
def mark_items_as_ineligible
|
|
36
|
+
@error_message = 'Items are not eligible due to insufficient stock'
|
|
37
|
+
marker_options = @options.merge(status: false, description: @error_message)
|
|
38
|
+
::Vpago::PaymentStatusMarker.new(@payment, marker_options).call
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
def mark_payment_as_success
|
|
42
|
+
@error_message = nil
|
|
43
|
+
marker_options = @options.merge(status: true, description: nil)
|
|
44
|
+
::Vpago::PaymentStatusMarker.new(@payment, marker_options).call
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
def mark_payment_as_failed(error_message)
|
|
48
|
+
@error_message = error_message
|
|
49
|
+
marker_options = @options.merge(status: false, description: @error_message)
|
|
50
|
+
::Vpago::PaymentStatusMarker.new(@payment, marker_options).call
|
|
51
|
+
end
|
|
52
|
+
end
|
|
53
|
+
end
|
|
54
|
+
end
|
|
@@ -28,6 +28,11 @@ module Vpago
|
|
|
28
28
|
elsif checker.failed?
|
|
29
29
|
mark_payment_as_failed(checker.error_message)
|
|
30
30
|
end
|
|
31
|
+
rescue Faraday::TimeoutError, Faraday::ConnectionFailed => e
|
|
32
|
+
VpagoLogger.error(
|
|
33
|
+
label: 'Vpago::PaywayV2::PaymentRequestUpdater#process_payment_status gateway_timeout',
|
|
34
|
+
data: { payment_number: @payment.number, error_class: e.class.name, error_message: e.message }
|
|
35
|
+
)
|
|
31
36
|
end
|
|
32
37
|
|
|
33
38
|
def mark_payment_as_success(checker)
|
|
@@ -37,6 +37,8 @@ module Vpago
|
|
|
37
37
|
def check_remote_status
|
|
38
38
|
conn = Faraday::Connection.new do |faraday|
|
|
39
39
|
faraday.request :url_encoded
|
|
40
|
+
faraday.options.open_timeout = Vpago::HttpTimeouts::OPEN_TIMEOUT
|
|
41
|
+
faraday.options.timeout = Vpago::HttpTimeouts::TIMEOUT
|
|
40
42
|
end
|
|
41
43
|
|
|
42
44
|
data = {
|
|
@@ -52,6 +52,8 @@ module Vpago
|
|
|
52
52
|
def check_remote_status
|
|
53
53
|
conn = Faraday::Connection.new do |faraday|
|
|
54
54
|
faraday.request :url_encoded
|
|
55
|
+
faraday.options.open_timeout = Vpago::HttpTimeouts::OPEN_TIMEOUT
|
|
56
|
+
faraday.options.timeout = Vpago::HttpTimeouts::TIMEOUT
|
|
55
57
|
end
|
|
56
58
|
|
|
57
59
|
data = {
|
|
@@ -100,7 +100,7 @@ module Vpago
|
|
|
100
100
|
end
|
|
101
101
|
|
|
102
102
|
def fetch_access_token
|
|
103
|
-
response = Faraday.post(
|
|
103
|
+
response = Faraday.new(request: { open_timeout: Vpago::HttpTimeouts::OPEN_TIMEOUT, timeout: Vpago::HttpTimeouts::TIMEOUT }).post(
|
|
104
104
|
access_token_url,
|
|
105
105
|
URI.encode_www_form(
|
|
106
106
|
grant_type: 'client_credentials',
|
|
@@ -2,7 +2,7 @@ module Vpago
|
|
|
2
2
|
module TrueMoney
|
|
3
3
|
class TransactionStatus < Base
|
|
4
4
|
def call
|
|
5
|
-
@response = Faraday.get(check_transaction_url, nil, default_headers)
|
|
5
|
+
@response = Faraday.new(request: { open_timeout: Vpago::HttpTimeouts::OPEN_TIMEOUT, timeout: Vpago::HttpTimeouts::TIMEOUT }).get(check_transaction_url, nil, default_headers)
|
|
6
6
|
end
|
|
7
7
|
|
|
8
8
|
def success?
|
data/lib/vpago/vattanac/base.rb
CHANGED
|
@@ -70,7 +70,8 @@ module Vpago
|
|
|
70
70
|
private
|
|
71
71
|
|
|
72
72
|
def fetch_access_token
|
|
73
|
-
response = Faraday.
|
|
73
|
+
response = Faraday.new(request: { open_timeout: Vpago::HttpTimeouts::OPEN_TIMEOUT, timeout: Vpago::HttpTimeouts::TIMEOUT })
|
|
74
|
+
.post(access_token_url, { username: username, password: password }.to_json, { 'Content-Type' => CONTENT_TYPE_JSON })
|
|
74
75
|
|
|
75
76
|
raise "Access Token Error: #{response.status} - #{response.body}" unless response.success?
|
|
76
77
|
|
|
@@ -78,7 +79,7 @@ module Vpago
|
|
|
78
79
|
end
|
|
79
80
|
|
|
80
81
|
def post(url, body)
|
|
81
|
-
response = Faraday.post(url, body.to_json, default_headers)
|
|
82
|
+
response = Faraday.new(request: { open_timeout: Vpago::HttpTimeouts::OPEN_TIMEOUT, timeout: Vpago::HttpTimeouts::TIMEOUT }).post(url, body.to_json, default_headers)
|
|
82
83
|
parse_json(response.body)
|
|
83
84
|
end
|
|
84
85
|
end
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
module Vpago
|
|
2
|
+
module Vattanac
|
|
3
|
+
class PaymentRequestUpdater < ::Vpago::PaymentRequestUpdater
|
|
4
|
+
def call
|
|
5
|
+
return if @payment.order.paid?
|
|
6
|
+
|
|
7
|
+
if items_eligible?
|
|
8
|
+
process_payment_status
|
|
9
|
+
else
|
|
10
|
+
mark_items_as_ineligible
|
|
11
|
+
end
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
private
|
|
15
|
+
|
|
16
|
+
def process_payment_status
|
|
17
|
+
checker = @payment.payment_method.check_transaction(@payment)
|
|
18
|
+
|
|
19
|
+
if checker.success?
|
|
20
|
+
mark_payment_as_success
|
|
21
|
+
elsif checker.failed? && !ignore_on_failed?
|
|
22
|
+
mark_payment_as_failed(checker.error_message)
|
|
23
|
+
end
|
|
24
|
+
rescue Faraday::TimeoutError, Faraday::ConnectionFailed => e
|
|
25
|
+
VpagoLogger.error(
|
|
26
|
+
label: 'Vpago::Vattanac::PaymentRequestUpdater#process_payment_status gateway_timeout',
|
|
27
|
+
data: { payment_number: @payment.number, error_class: e.class.name, error_message: e.message }
|
|
28
|
+
)
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
def items_eligible?
|
|
32
|
+
@payment&.order&.line_items&.all?(&:sufficient_stock?) == true # rubocop:disable Style/SafeNavigationChainLength
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
def mark_items_as_ineligible
|
|
36
|
+
@error_message = 'Items are not eligible due to insufficient stock'
|
|
37
|
+
marker_options = @options.merge(status: false, description: @error_message)
|
|
38
|
+
::Vpago::PaymentStatusMarker.new(@payment, marker_options).call
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
def mark_payment_as_success
|
|
42
|
+
@error_message = nil
|
|
43
|
+
marker_options = @options.merge(status: true, description: nil)
|
|
44
|
+
::Vpago::PaymentStatusMarker.new(@payment, marker_options).call
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
def mark_payment_as_failed(error_message)
|
|
48
|
+
@error_message = error_message
|
|
49
|
+
marker_options = @options.merge(status: false, description: @error_message)
|
|
50
|
+
::Vpago::PaymentStatusMarker.new(@payment, marker_options).call
|
|
51
|
+
end
|
|
52
|
+
end
|
|
53
|
+
end
|
|
54
|
+
end
|
|
@@ -13,6 +13,22 @@ module Vpago
|
|
|
13
13
|
@response.dig('data', 'status') == 'SUCCESS'
|
|
14
14
|
end
|
|
15
15
|
|
|
16
|
+
def error_message
|
|
17
|
+
@response.dig('msgEntity', 'message') || @response.dig('data', 'message') || 'Unknown error'
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
# msgEntity.code is the API-envelope result code ("0" = call succeeded; check
|
|
21
|
+
# data.status for the actual transaction state). Any other code is a gateway-level
|
|
22
|
+
# error with no transaction data (e.g. "03" / "Transaction not found") and is
|
|
23
|
+
# treated as terminal failure.
|
|
24
|
+
def failed?
|
|
25
|
+
@response.dig('msgEntity', 'code').to_s != '0'
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
def pending?
|
|
29
|
+
!success? && !failed?
|
|
30
|
+
end
|
|
31
|
+
|
|
16
32
|
private
|
|
17
33
|
|
|
18
34
|
def payload
|
|
@@ -20,4 +36,4 @@ module Vpago
|
|
|
20
36
|
end
|
|
21
37
|
end
|
|
22
38
|
end
|
|
23
|
-
end
|
|
39
|
+
end
|
data/spree_vpago.gemspec
CHANGED
|
@@ -26,7 +26,7 @@ Gem::Specification.new do |s|
|
|
|
26
26
|
s.add_dependency 'spree_api', spree_version
|
|
27
27
|
s.add_dependency 'spree_backend', spree_version
|
|
28
28
|
s.add_dependency 'spree_core', spree_version
|
|
29
|
-
s.add_dependency 'spree_extension'
|
|
29
|
+
s.add_dependency 'spree_extension', '< 1.0'
|
|
30
30
|
s.add_dependency 'spree_multi_vendor', '>= 2.4.1'
|
|
31
31
|
|
|
32
32
|
s.metadata['rubygems_mfa_required'] = 'true'
|
metadata
CHANGED
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: spree_vpago
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 2.4.0.pre.
|
|
4
|
+
version: 2.4.0.pre.pre3
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- You
|
|
8
8
|
autorequire:
|
|
9
9
|
bindir: bin
|
|
10
10
|
cert_chain: []
|
|
11
|
-
date: 2026-
|
|
11
|
+
date: 2026-09-30 00:00:00.000000000 Z
|
|
12
12
|
dependencies:
|
|
13
13
|
- !ruby/object:Gem::Dependency
|
|
14
14
|
name: faraday
|
|
@@ -84,16 +84,16 @@ dependencies:
|
|
|
84
84
|
name: spree_extension
|
|
85
85
|
requirement: !ruby/object:Gem::Requirement
|
|
86
86
|
requirements:
|
|
87
|
-
- - "
|
|
87
|
+
- - "<"
|
|
88
88
|
- !ruby/object:Gem::Version
|
|
89
|
-
version: '0'
|
|
89
|
+
version: '1.0'
|
|
90
90
|
type: :runtime
|
|
91
91
|
prerelease: false
|
|
92
92
|
version_requirements: !ruby/object:Gem::Requirement
|
|
93
93
|
requirements:
|
|
94
|
-
- - "
|
|
94
|
+
- - "<"
|
|
95
95
|
- !ruby/object:Gem::Version
|
|
96
|
-
version: '0'
|
|
96
|
+
version: '1.0'
|
|
97
97
|
- !ruby/object:Gem::Dependency
|
|
98
98
|
name: spree_multi_vendor
|
|
99
99
|
requirement: !ruby/object:Gem::Requirement
|
|
@@ -151,11 +151,17 @@ files:
|
|
|
151
151
|
- app/assets/javascripts/vpago/vpago_payments/user_informers/firebase.js
|
|
152
152
|
- app/controllers/.gitkeep
|
|
153
153
|
- app/controllers/spree/acleda_redirects_controller.rb
|
|
154
|
+
- app/controllers/spree/admin/payment_acleda_v2_base_controller.rb
|
|
155
|
+
- app/controllers/spree/admin/payment_acleda_v2_checkers_controller.rb
|
|
156
|
+
- app/controllers/spree/admin/payment_acleda_v2_queriers_controller.rb
|
|
154
157
|
- app/controllers/spree/admin/payment_methods_controller_decorator.rb
|
|
155
158
|
- app/controllers/spree/admin/payment_payway_base_controller.rb
|
|
156
159
|
- app/controllers/spree/admin/payment_payway_checkers_controller.rb
|
|
157
160
|
- app/controllers/spree/admin/payment_payway_markers_controller.rb
|
|
158
161
|
- app/controllers/spree/admin/payment_payway_queriers_controller.rb
|
|
162
|
+
- app/controllers/spree/admin/payment_vattanac_base_controller.rb
|
|
163
|
+
- app/controllers/spree/admin/payment_vattanac_checkers_controller.rb
|
|
164
|
+
- app/controllers/spree/admin/payment_vattanac_queriers_controller.rb
|
|
159
165
|
- app/controllers/spree/admin/payment_wing_sdk_base_controller.rb
|
|
160
166
|
- app/controllers/spree/admin/payment_wing_sdk_checkers_controller.rb
|
|
161
167
|
- app/controllers/spree/admin/payment_wing_sdk_markers_controller.rb
|
|
@@ -167,7 +173,6 @@ files:
|
|
|
167
173
|
- app/controllers/spree/admin/payouts_controller.rb
|
|
168
174
|
- app/controllers/spree/admin/suspicious_orders_controller.rb
|
|
169
175
|
- app/controllers/spree/api/v2/storefront/checkout_controller_decorator.rb
|
|
170
|
-
- app/controllers/spree/miniapp/acledas_controller.rb
|
|
171
176
|
- app/controllers/spree/payway_card_popups_controller.rb
|
|
172
177
|
- app/controllers/spree/payway_results_controller.rb
|
|
173
178
|
- app/controllers/spree/payway_v2_card_popups_controller.rb
|
|
@@ -193,7 +198,6 @@ files:
|
|
|
193
198
|
- app/models/.gitkeep
|
|
194
199
|
- app/models/concerns/vpago/payoutable.rb
|
|
195
200
|
- app/models/spree/gateway/acleda.rb
|
|
196
|
-
- app/models/spree/gateway/acleda_mini_app.rb
|
|
197
201
|
- app/models/spree/gateway/acleda_mobile.rb
|
|
198
202
|
- app/models/spree/gateway/acleda_v2.rb
|
|
199
203
|
- app/models/spree/gateway/payway.rb
|
|
@@ -258,7 +262,6 @@ files:
|
|
|
258
262
|
- app/serializers/spree/v2/storefront/payment_serializer_decorator.rb
|
|
259
263
|
- app/serializers/spree/v2/storefront/vpago_payment_source_serializer.rb
|
|
260
264
|
- app/services/.gitkeep
|
|
261
|
-
- app/services/vpago/acleda_mini_app/session/create.rb
|
|
262
265
|
- app/services/vpago/aes_encrypter.rb
|
|
263
266
|
- app/services/vpago/payment_finder.rb
|
|
264
267
|
- app/services/vpago/payment_processable.rb
|
|
@@ -286,7 +289,6 @@ files:
|
|
|
286
289
|
- app/views/spree/admin/payments/source_forms/_payment_payway.html.erb
|
|
287
290
|
- app/views/spree/admin/payments/source_forms/_payway_v2.html.erb
|
|
288
291
|
- app/views/spree/admin/payments/source_views/_acleda.html.erb
|
|
289
|
-
- app/views/spree/admin/payments/source_views/_acleda_mini_app.html.erb
|
|
290
292
|
- app/views/spree/admin/payments/source_views/_acleda_mobile.html.erb
|
|
291
293
|
- app/views/spree/admin/payments/source_views/_acleda_v2.html.erb
|
|
292
294
|
- app/views/spree/admin/payments/source_views/_payment_payway.html.erb
|
|
@@ -342,9 +344,9 @@ files:
|
|
|
342
344
|
- app/views/spree/payway_results/success.html.erb
|
|
343
345
|
- app/views/spree/payway_v2_card_popups/_form.html.erb
|
|
344
346
|
- app/views/spree/payway_v2_card_popups/show.html.erb
|
|
347
|
+
- app/views/spree/vpago_payments/_success_script.html.erb
|
|
345
348
|
- app/views/spree/vpago_payments/_transaction_checker.html.erb
|
|
346
349
|
- app/views/spree/vpago_payments/checkout.html.erb
|
|
347
|
-
- app/views/spree/vpago_payments/forms/spree/gateway/_acleda_mini_app.html.erb
|
|
348
350
|
- app/views/spree/vpago_payments/forms/spree/gateway/_acleda_v2.html.erb
|
|
349
351
|
- app/views/spree/vpago_payments/forms/spree/gateway/_payway_v2.html.erb
|
|
350
352
|
- app/views/spree/vpago_payments/forms/spree/gateway/_true_money.html.erb
|
|
@@ -396,7 +398,6 @@ files:
|
|
|
396
398
|
- lib/vpago/acleda/deeplink_checkout.rb
|
|
397
399
|
- lib/vpago/acleda/payment_request_updater.rb
|
|
398
400
|
- lib/vpago/acleda/transaction_status.rb
|
|
399
|
-
- lib/vpago/acleda_mini_app/checkout.rb
|
|
400
401
|
- lib/vpago/acleda_mobile/base.rb
|
|
401
402
|
- lib/vpago/acleda_mobile/callback_validator.php
|
|
402
403
|
- lib/vpago/acleda_mobile/callback_validator.rb
|
|
@@ -406,7 +407,9 @@ files:
|
|
|
406
407
|
- lib/vpago/acleda_mobile/transaction_status.rb
|
|
407
408
|
- lib/vpago/acleda_v2/base.rb
|
|
408
409
|
- lib/vpago/acleda_v2/checkout.rb
|
|
410
|
+
- lib/vpago/acleda_v2/payment_request_updater.rb
|
|
409
411
|
- lib/vpago/acleda_v2/transaction_status.rb
|
|
412
|
+
- lib/vpago/http_timeouts.rb
|
|
410
413
|
- lib/vpago/payment_amount_calculator.rb
|
|
411
414
|
- lib/vpago/payment_request_updater.rb
|
|
412
415
|
- lib/vpago/payment_status_marker.rb
|
|
@@ -430,6 +433,7 @@ files:
|
|
|
430
433
|
- lib/vpago/true_money/transaction_status.rb
|
|
431
434
|
- lib/vpago/vattanac/base.rb
|
|
432
435
|
- lib/vpago/vattanac/checkout.rb
|
|
436
|
+
- lib/vpago/vattanac/payment_request_updater.rb
|
|
433
437
|
- lib/vpago/vattanac/transaction_status.rb
|
|
434
438
|
- lib/vpago/vattanac_mini_app/base.rb
|
|
435
439
|
- lib/vpago/vattanac_mini_app/checkout.rb
|
|
@@ -1,29 +0,0 @@
|
|
|
1
|
-
module Spree
|
|
2
|
-
module Miniapp
|
|
3
|
-
# Partner Session Initialization API (ACLEDA Mini App Integration Spec, Step 01).
|
|
4
|
-
# ACLEDA (server-to-server) POSTs { phone, first_name, last_name }; we return a
|
|
5
|
-
# session-based miniAppUrl for ACLEDA to open in the WebView.
|
|
6
|
-
class AcledasController < Spree::Api::V2::BaseController
|
|
7
|
-
# POST /miniapp/acleda
|
|
8
|
-
def create
|
|
9
|
-
result = ::Vpago::AcledaMiniApp::Session::Create.call(
|
|
10
|
-
phone: session_params[:phone],
|
|
11
|
-
first_name: session_params[:first_name],
|
|
12
|
-
last_name: session_params[:last_name]
|
|
13
|
-
)
|
|
14
|
-
|
|
15
|
-
if result.success?
|
|
16
|
-
render json: { message: 'SUCCESS', miniAppUrl: result.value[:mini_app_url] }
|
|
17
|
-
else
|
|
18
|
-
render json: { message: 'FAILED', error: result.error.to_s }, status: :unprocessable_entity
|
|
19
|
-
end
|
|
20
|
-
end
|
|
21
|
-
|
|
22
|
-
private
|
|
23
|
-
|
|
24
|
-
def session_params
|
|
25
|
-
params.permit(:phone, :first_name, :last_name)
|
|
26
|
-
end
|
|
27
|
-
end
|
|
28
|
-
end
|
|
29
|
-
end
|
|
@@ -1,20 +0,0 @@
|
|
|
1
|
-
module Spree
|
|
2
|
-
# ACLEDA Mini App payment method.
|
|
3
|
-
#
|
|
4
|
-
# Reuses the ACLEDA V2 integration in deeplink mode: the deeplink produced by
|
|
5
|
-
# ACLEDA's openSessionV2 API is handed to the ACLEDA super-app through the
|
|
6
|
-
# `acledaJSBridge` (startPayment) instead of redirecting the page. Server-side
|
|
7
|
-
# verification reuses AcledaV2's #check_transaction (getTxnStatus).
|
|
8
|
-
class Gateway::AcledaMiniApp < Gateway::AcledaV2
|
|
9
|
-
# override: partial to render in admin / checkout form lookup
|
|
10
|
-
def method_type
|
|
11
|
-
'acleda_mini_app'
|
|
12
|
-
end
|
|
13
|
-
|
|
14
|
-
# The mini app always uses the deeplink + JS bridge, so admins don't need to
|
|
15
|
-
# set the ACLEDA V2 mode.
|
|
16
|
-
def deeplink?
|
|
17
|
-
true
|
|
18
|
-
end
|
|
19
|
-
end
|
|
20
|
-
end
|
|
@@ -1,99 +0,0 @@
|
|
|
1
|
-
module Vpago
|
|
2
|
-
module AcledaMiniApp
|
|
3
|
-
module Session
|
|
4
|
-
# Partner Session Initialization (ACLEDA Mini App Integration Spec, Step 01).
|
|
5
|
-
#
|
|
6
|
-
# ACLEDA calls POST /miniapp/acleda with { phone, first_name, last_name }.
|
|
7
|
-
# We find or create the customer (tagged with the acleda_bank identity),
|
|
8
|
-
# mint a session JWT, and return a session-based miniAppUrl for ACLEDA to
|
|
9
|
-
# open in the WebView. The generic session_id OAuth grant validates the JWT
|
|
10
|
-
# when the WebView later authenticates.
|
|
11
|
-
class Create
|
|
12
|
-
prepend Spree::ServiceModule::Base
|
|
13
|
-
|
|
14
|
-
def call(phone: nil, first_name: nil, last_name: nil)
|
|
15
|
-
return failure(nil, 'phone is required') if phone.blank?
|
|
16
|
-
|
|
17
|
-
@phone = phone
|
|
18
|
-
@first_name = first_name
|
|
19
|
-
@last_name = last_name
|
|
20
|
-
|
|
21
|
-
user = find_or_create_user
|
|
22
|
-
return failure(user, 'user creation failed') if user.nil? || !user.persisted?
|
|
23
|
-
|
|
24
|
-
success(mini_app_url: mini_app_url(user))
|
|
25
|
-
end
|
|
26
|
-
|
|
27
|
-
private
|
|
28
|
-
|
|
29
|
-
attr_reader :phone, :first_name, :last_name
|
|
30
|
-
|
|
31
|
-
def find_or_create_user
|
|
32
|
-
identity = acleda_identity
|
|
33
|
-
|
|
34
|
-
# Returning customer: the ACLEDA identity already points at a user.
|
|
35
|
-
return identity.user if identity.persisted?
|
|
36
|
-
|
|
37
|
-
# New to ACLEDA: reuse a customer matched by phone, otherwise build one,
|
|
38
|
-
# then tag them with the acleda_bank identity so the lookup above hits
|
|
39
|
-
# next time.
|
|
40
|
-
user = find_existing_user || build_user
|
|
41
|
-
identity.name = full_name
|
|
42
|
-
user.user_identity_providers << identity
|
|
43
|
-
user.save
|
|
44
|
-
|
|
45
|
-
user
|
|
46
|
-
end
|
|
47
|
-
|
|
48
|
-
def acleda_identity
|
|
49
|
-
SpreeCmCommissioner::UserIdentityProvider.acleda_bank.find_or_initialize_by(sub: phone)
|
|
50
|
-
end
|
|
51
|
-
|
|
52
|
-
def find_existing_user
|
|
53
|
-
return if intel_phone.blank?
|
|
54
|
-
|
|
55
|
-
Spree::User.by_non_tenant.find_by(intel_phone_number: intel_phone)
|
|
56
|
-
end
|
|
57
|
-
|
|
58
|
-
def build_user
|
|
59
|
-
Spree::User.new(
|
|
60
|
-
first_name: first_name,
|
|
61
|
-
last_name: last_name,
|
|
62
|
-
phone_number: phone,
|
|
63
|
-
intel_phone_number: intel_phone,
|
|
64
|
-
password: SecureRandom.base64(16),
|
|
65
|
-
confirmed_at: Time.zone.now
|
|
66
|
-
)
|
|
67
|
-
end
|
|
68
|
-
|
|
69
|
-
def mini_app_url(user)
|
|
70
|
-
# A JWT signed with the user's secure_token. Passed as `session_key` (not
|
|
71
|
-
# `session_id`) so the OAuth grant routes it to the ACLEDA authenticator,
|
|
72
|
-
# which enforces the signature.
|
|
73
|
-
session_key = SpreeCmCommissioner::UserSessionJwtToken.encode(
|
|
74
|
-
{ user_id: user.id },
|
|
75
|
-
user.reload.secure_token
|
|
76
|
-
)
|
|
77
|
-
|
|
78
|
-
"#{Spree::Store.default.formatted_url}/mini_app/acleda?session_key=#{session_key}&ds=#{CGI.escape(disable_services)}"
|
|
79
|
-
end
|
|
80
|
-
|
|
81
|
-
def full_name
|
|
82
|
-
[first_name, last_name].compact.join(' ').presence
|
|
83
|
-
end
|
|
84
|
-
|
|
85
|
-
def intel_phone
|
|
86
|
-
return @intel_phone if defined?(@intel_phone)
|
|
87
|
-
|
|
88
|
-
@intel_phone = SpreeCmCommissioner::PhoneNumberParser.call(phone_number: phone).intel_phone_number
|
|
89
|
-
end
|
|
90
|
-
|
|
91
|
-
# Services to disable in the mini app storefront. Configurable per ACLEDA's
|
|
92
|
-
# requirement; defaults to none.
|
|
93
|
-
def disable_services
|
|
94
|
-
ENV.fetch('ACLEDA_MINI_APP_DISABLE_SERVICES', '')
|
|
95
|
-
end
|
|
96
|
-
end
|
|
97
|
-
end
|
|
98
|
-
end
|
|
99
|
-
end
|
|
@@ -1,93 +0,0 @@
|
|
|
1
|
-
<%
|
|
2
|
-
opr_device = request.user_agent.to_s.downcase.match?(/iphone|ipad|ipod/) ? 'ios' : 'android'
|
|
3
|
-
checkout = ::Vpago::AcledaMiniApp::Checkout.new(@payment, { platform: 'app', opr_device: opr_device })
|
|
4
|
-
|
|
5
|
-
begin
|
|
6
|
-
checkout.call
|
|
7
|
-
rescue => e
|
|
8
|
-
Rails.logger.error("Acleda Mini App checkout.call failed: #{e.message}")
|
|
9
|
-
end
|
|
10
|
-
%>
|
|
11
|
-
|
|
12
|
-
<p id="unsupported-message"
|
|
13
|
-
style="margin-top: 10px; font-weight: bold; color: red; display: none;">
|
|
14
|
-
</p>
|
|
15
|
-
|
|
16
|
-
<% if checkout.failed? %>
|
|
17
|
-
<script>
|
|
18
|
-
console.error("[Vpago] Acleda Mini App checkout error: <%= j checkout.error_message.to_s %>");
|
|
19
|
-
document.addEventListener("DOMContentLoaded", () => {
|
|
20
|
-
const loadingContainer = document.getElementById('vpago_loading_container');
|
|
21
|
-
if (loadingContainer) {
|
|
22
|
-
loadingContainer.textContent = "We couldn't start your payment. Please go back and try again.";
|
|
23
|
-
}
|
|
24
|
-
});
|
|
25
|
-
</script>
|
|
26
|
-
<% else %>
|
|
27
|
-
<script>
|
|
28
|
-
// ACLEDA JS bridge (unified iOS + Android). Defined before use so it is
|
|
29
|
-
// available when the native layer injects its handlers.
|
|
30
|
-
window.acledaJSBridge = window.acledaJSBridge || {
|
|
31
|
-
call: function (action, data = {}) {
|
|
32
|
-
const payload = { action, data };
|
|
33
|
-
|
|
34
|
-
// iOS WKWebView
|
|
35
|
-
if (
|
|
36
|
-
window.webkit &&
|
|
37
|
-
window.webkit.messageHandlers &&
|
|
38
|
-
window.webkit.messageHandlers.acledaIOSJSBridge
|
|
39
|
-
) {
|
|
40
|
-
window.webkit.messageHandlers.acledaIOSJSBridge.postMessage(payload);
|
|
41
|
-
return true;
|
|
42
|
-
}
|
|
43
|
-
|
|
44
|
-
// Android WebView
|
|
45
|
-
if (
|
|
46
|
-
window.acledaAndroidJSBridge &&
|
|
47
|
-
typeof window.acledaAndroidJSBridge.postMessage === "function"
|
|
48
|
-
) {
|
|
49
|
-
window.acledaAndroidJSBridge.postMessage(JSON.stringify(payload));
|
|
50
|
-
return true;
|
|
51
|
-
}
|
|
52
|
-
|
|
53
|
-
console.warn("[acledaJSBridge] Native bridge not found");
|
|
54
|
-
return false;
|
|
55
|
-
}
|
|
56
|
-
};
|
|
57
|
-
|
|
58
|
-
function showRedirectContainer(buttonLabel, onClick) {
|
|
59
|
-
const loadingContainer = document.getElementById('vpago_loading_container');
|
|
60
|
-
const redirectContainer = document.getElementById('vpago_redirect_container');
|
|
61
|
-
const redirectButton = document.getElementById('vpago_redirect_button');
|
|
62
|
-
|
|
63
|
-
redirectButton.textContent = buttonLabel;
|
|
64
|
-
redirectButton.addEventListener('click', onClick);
|
|
65
|
-
|
|
66
|
-
loadingContainer.style.display = 'none';
|
|
67
|
-
redirectContainer.style.removeProperty('display');
|
|
68
|
-
}
|
|
69
|
-
|
|
70
|
-
document.addEventListener("DOMContentLoaded", () => {
|
|
71
|
-
const acledaDeeplink = "<%= raw checkout.acleda_deeplink %>";
|
|
72
|
-
const processingUrl = "<%= raw @payment.processing_url %>";
|
|
73
|
-
|
|
74
|
-
// Native -> JS after payment completes. Primary completion signal; the
|
|
75
|
-
// transaction checker polling is the fallback.
|
|
76
|
-
window.onPaymentResult = function (result) {
|
|
77
|
-
console.log("[acledaJSBridge] Payment result:", result);
|
|
78
|
-
// result.batchId, result.status = "success" | "failed" | "cancelled"
|
|
79
|
-
window.location.href = processingUrl;
|
|
80
|
-
};
|
|
81
|
-
|
|
82
|
-
const startPayment = () => window.acledaJSBridge.call("startPayment", { acleda_deeplink: acledaDeeplink });
|
|
83
|
-
|
|
84
|
-
if (startPayment()) {
|
|
85
|
-
showRedirectContainer("Continue", startPayment);
|
|
86
|
-
} else {
|
|
87
|
-
const unsupported = document.getElementById('unsupported-message');
|
|
88
|
-
unsupported.style.display = 'block';
|
|
89
|
-
unsupported.innerText = 'Unsupported environment';
|
|
90
|
-
}
|
|
91
|
-
});
|
|
92
|
-
</script>
|
|
93
|
-
<% end %>
|
|
@@ -1,23 +0,0 @@
|
|
|
1
|
-
module Vpago
|
|
2
|
-
module AcledaMiniApp
|
|
3
|
-
# ACLEDA Mini App checkout. Reuses ACLEDA V2's openSessionV2 flow to obtain a
|
|
4
|
-
# deeplink, which is passed to the ACLEDA super-app via the acledaJSBridge
|
|
5
|
-
# (startPayment) instead of redirecting the page.
|
|
6
|
-
class Checkout < Vpago::AcledaV2::Checkout
|
|
7
|
-
# The mini app always uses the deeplink + JS bridge, regardless of the
|
|
8
|
-
# gateway's configured mode.
|
|
9
|
-
def deeplink?
|
|
10
|
-
true
|
|
11
|
-
end
|
|
12
|
-
|
|
13
|
-
# The deeplink string handed to
|
|
14
|
-
# acledaJSBridge.call('startPayment', { acleda_deeplink: ... })
|
|
15
|
-
# Ensures openSessionV2 has run (persisting paymentTokenid for later
|
|
16
|
-
# getTxnStatus verification) before returning the deeplinkUrl.
|
|
17
|
-
def acleda_deeplink
|
|
18
|
-
call if @response.nil?
|
|
19
|
-
deeplink_url
|
|
20
|
-
end
|
|
21
|
-
end
|
|
22
|
-
end
|
|
23
|
-
end
|