spree_vpago 2.2.1 → 2.2.2.pre.pre1
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 +3 -3
- data/app/controllers/spree/vpago_payments_controller.rb +6 -50
- data/app/controllers/spree/webhook/payways_controller.rb +2 -2
- data/app/jobs/vpago/payment_processor_job.rb +0 -60
- data/app/services/vpago/payment_redirect_handler.rb +1 -1
- data/app/views/spree/vpago_payments/forms/spree/gateway/_payway_v2.html.erb +33 -5
- data/lib/spree_vpago/version.rb +1 -1
- data/lib/vpago/payway_v2/transaction_status.rb +1 -30
- metadata +4 -6
- data/app/lib/vpago/timing_helper.rb +0 -28
- data/lib/vpago_logger.rb +0 -21
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 34f988ac706caee9ab0414c2af33a8694157e2a61ef2f0e8bbd2078f4f84f6b7
|
|
4
|
+
data.tar.gz: 695bb8a11c50fba8cca3098509f9001df921cd07347541aa286d5475ca6cc998
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 2d5597af9933d549fb87f3f8523246561e51ddcefad4a972aecb99e81dfbd9a9961710d0013fa3be6bba6c4f848cc191c05413ea3ce6c2200f69cdeb8d8f1c96
|
|
7
|
+
data.tar.gz: c97478d640a636fed25fa67a6476685fc481dd6b2db5d875b71b6c35a79c5b88aa2f0ff07525d34ae74f2886fb7f47e8fc7bf7c3a90d6d0b67cb843d9cf67926
|
data/Gemfile.lock
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
PATH
|
|
2
2
|
remote: .
|
|
3
3
|
specs:
|
|
4
|
-
spree_vpago (2.2.
|
|
4
|
+
spree_vpago (2.2.2.pre.pre1)
|
|
5
5
|
faraday
|
|
6
6
|
google-cloud-firestore
|
|
7
7
|
spree_api (>= 4.5)
|
|
@@ -242,7 +242,7 @@ GEM
|
|
|
242
242
|
gapic-common (~> 1.2)
|
|
243
243
|
google-cloud-errors (~> 1.0)
|
|
244
244
|
google-logging-utils (0.2.0)
|
|
245
|
-
google-protobuf (4.33.
|
|
245
|
+
google-protobuf (4.33.5)
|
|
246
246
|
bigdecimal
|
|
247
247
|
rake (>= 13)
|
|
248
248
|
googleapis-common-protos (1.9.0)
|
|
@@ -259,7 +259,7 @@ GEM
|
|
|
259
259
|
multi_json (~> 1.11)
|
|
260
260
|
os (>= 0.9, < 2.0)
|
|
261
261
|
signet (>= 0.16, < 2.a)
|
|
262
|
-
grpc (1.
|
|
262
|
+
grpc (1.78.0)
|
|
263
263
|
google-protobuf (>= 3.25, < 5.0)
|
|
264
264
|
googleapis-common-protos-types (~> 1.0)
|
|
265
265
|
hashdiff (1.1.0)
|
|
@@ -44,15 +44,14 @@ module Spree
|
|
|
44
44
|
return render_not_found unless @payment.present?
|
|
45
45
|
|
|
46
46
|
unless @payment.order.paid?
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
Vpago::PaymentProcessorJob.perform_later(payment_number: @payment.number, enqueued_at: enqueued_at)
|
|
47
|
+
Vpago::PaymentProcessorJob.perform_later(
|
|
48
|
+
payment_number: @payment.number
|
|
49
|
+
)
|
|
51
50
|
end
|
|
52
51
|
|
|
53
52
|
render json: { status: :ok }, status: :ok
|
|
54
53
|
rescue StandardError => e
|
|
55
|
-
|
|
54
|
+
Rails.logger.error("Failed to enqueued payment processor job: #{params} #{e.message}")
|
|
56
55
|
render json: { status: :internal_server_error, message: 'Failed to enqueue payment processor job' }, status: :internal_server_error
|
|
57
56
|
end
|
|
58
57
|
|
|
@@ -63,21 +62,14 @@ module Spree
|
|
|
63
62
|
@payment = Spree::Payment.find_by(number: params.dig(:data, :external_ref_id))
|
|
64
63
|
return render_not_found unless @payment
|
|
65
64
|
|
|
66
|
-
unless @payment.order.paid?
|
|
67
|
-
enqueued_at = Time.now.to_f
|
|
68
|
-
log_enqueue_start(@payment, enqueued_at)
|
|
69
|
-
|
|
70
|
-
Vpago::PaymentProcessorJob.perform_later(payment_number: @payment.number, enqueued_at: enqueued_at)
|
|
71
|
-
end
|
|
65
|
+
Vpago::PaymentProcessorJob.perform_later(payment_number: @payment.number) unless @payment.order.paid?
|
|
72
66
|
|
|
73
67
|
render json: { status: { code: '000001', message: 'success' }, data: nil }, status: :ok
|
|
74
68
|
rescue StandardError => e
|
|
75
|
-
|
|
69
|
+
Rails.logger.error("Payment error: #{e.message}")
|
|
76
70
|
render json: { status: :internal_server_error, message: 'Failed to enqueue payment processor job' }, status: :internal_server_error
|
|
77
71
|
end
|
|
78
72
|
|
|
79
|
-
private
|
|
80
|
-
|
|
81
73
|
def sanitize_return_params
|
|
82
74
|
sanitized_params = params.permit!.to_h
|
|
83
75
|
|
|
@@ -100,41 +92,5 @@ module Spree
|
|
|
100
92
|
format.json { render json: { status: :unauthorized }, status: :unauthorized }
|
|
101
93
|
end
|
|
102
94
|
end
|
|
103
|
-
|
|
104
|
-
def log_enqueue_start(payment, enqueued_at, return_params = {})
|
|
105
|
-
VpagoLogger.log(
|
|
106
|
-
event: 'vpago.payment_processor_job.enqueue',
|
|
107
|
-
data: {
|
|
108
|
-
payment_number: payment.number,
|
|
109
|
-
order_number: payment.order&.number,
|
|
110
|
-
request_id: request.request_id,
|
|
111
|
-
payment_method_type: payment.payment_method&.type,
|
|
112
|
-
payment_method_name: payment.payment_method&.name,
|
|
113
|
-
gateway: detect_payway_gateway_version(payment.payment_method),
|
|
114
|
-
tran_id: (return_params[:tran_id] || return_params['tran_id']),
|
|
115
|
-
enqueued_at: enqueued_at
|
|
116
|
-
}
|
|
117
|
-
)
|
|
118
|
-
end
|
|
119
|
-
|
|
120
|
-
def log_enqueue_error(error)
|
|
121
|
-
VpagoLogger.error(
|
|
122
|
-
event: 'vpago.payment_processor_job.enqueue.error',
|
|
123
|
-
data: {
|
|
124
|
-
request_id: request.request_id,
|
|
125
|
-
payment_number: @payment&.number,
|
|
126
|
-
error_class: error.class.name,
|
|
127
|
-
error_message: error.message
|
|
128
|
-
}
|
|
129
|
-
)
|
|
130
|
-
end
|
|
131
|
-
|
|
132
|
-
def detect_payway_gateway_version(payment_method)
|
|
133
|
-
return nil unless payment_method
|
|
134
|
-
return 'payway_v2' if payment_method.type_payway_v2?
|
|
135
|
-
return 'payway_v1' if payment_method.type_payway?
|
|
136
|
-
|
|
137
|
-
nil
|
|
138
|
-
end
|
|
139
95
|
end
|
|
140
96
|
end
|
|
@@ -4,7 +4,7 @@ module Spree
|
|
|
4
4
|
skip_before_action :verify_authenticity_token, only: %i[return v2_return continue v2_continue]
|
|
5
5
|
|
|
6
6
|
# match via: [:get, :post]
|
|
7
|
-
# {"response"=>"{\"tran_id\":\"PE13LXT1\",\"status\":0}"}
|
|
7
|
+
# {"response"=>"{\"tran_id\":\"PE13LXT1\",\"status\":0"}"}
|
|
8
8
|
def v2_return
|
|
9
9
|
handler_service = v2_request_updater_service
|
|
10
10
|
|
|
@@ -48,7 +48,7 @@ module Spree
|
|
|
48
48
|
request_updater.call
|
|
49
49
|
|
|
50
50
|
order = payment.order
|
|
51
|
-
order.reload
|
|
51
|
+
order = order.reload
|
|
52
52
|
|
|
53
53
|
if order.paid? || payment.pending?
|
|
54
54
|
render plain: :success
|
|
@@ -1,71 +1,11 @@
|
|
|
1
1
|
# Put :payment_processing at a higher priority in your project: config/sidekiq.yml
|
|
2
|
-
require 'vpago/timing_helper'
|
|
3
|
-
|
|
4
2
|
module Vpago
|
|
5
3
|
class PaymentProcessorJob < ::ApplicationUniqueJob
|
|
6
4
|
queue_as :payment_processing
|
|
7
5
|
|
|
8
6
|
def perform(options)
|
|
9
|
-
started_at = Vpago::TimingHelper.current_time
|
|
10
|
-
enqueued_at = options[:enqueued_at]
|
|
11
|
-
queue_wait_ms = calculate_queue_wait_ms(enqueued_at)
|
|
12
|
-
|
|
13
|
-
log_job_start(options[:payment_number], queue_wait_ms)
|
|
14
|
-
|
|
15
7
|
payment = Spree::Payment.find_by!(number: options[:payment_number])
|
|
16
8
|
Vpago::PaymentProcessor.new(payment: payment).call
|
|
17
|
-
|
|
18
|
-
log_job_finish(options[:payment_number], queue_wait_ms, started_at)
|
|
19
|
-
rescue StandardError => e
|
|
20
|
-
log_job_error(options[:payment_number], queue_wait_ms, started_at, e)
|
|
21
|
-
raise
|
|
22
|
-
end
|
|
23
|
-
|
|
24
|
-
private
|
|
25
|
-
|
|
26
|
-
def calculate_queue_wait_ms(enqueued_at)
|
|
27
|
-
return nil unless enqueued_at
|
|
28
|
-
|
|
29
|
-
((Time.now.to_f - enqueued_at.to_f) * 1000.0).round(1)
|
|
30
|
-
end
|
|
31
|
-
|
|
32
|
-
def log_job_start(payment_number, queue_wait_ms)
|
|
33
|
-
VpagoLogger.log(
|
|
34
|
-
event: 'vpago.payment_processor_job.start',
|
|
35
|
-
data: {
|
|
36
|
-
payment_number: payment_number,
|
|
37
|
-
queue: self.class.queue_name,
|
|
38
|
-
queue_wait_ms: queue_wait_ms
|
|
39
|
-
}
|
|
40
|
-
)
|
|
41
|
-
end
|
|
42
|
-
|
|
43
|
-
def log_job_finish(payment_number, queue_wait_ms, started_at)
|
|
44
|
-
runtime_ms = Vpago::TimingHelper.elapsed_ms(started_at)
|
|
45
|
-
VpagoLogger.log(
|
|
46
|
-
event: 'vpago.payment_processor_job.finish',
|
|
47
|
-
data: {
|
|
48
|
-
payment_number: payment_number,
|
|
49
|
-
queue: self.class.queue_name,
|
|
50
|
-
queue_wait_ms: queue_wait_ms,
|
|
51
|
-
runtime_ms: runtime_ms
|
|
52
|
-
}
|
|
53
|
-
)
|
|
54
|
-
end
|
|
55
|
-
|
|
56
|
-
def log_job_error(payment_number, queue_wait_ms, started_at, error)
|
|
57
|
-
runtime_ms = Vpago::TimingHelper.elapsed_ms(started_at)
|
|
58
|
-
VpagoLogger.error(
|
|
59
|
-
event: 'vpago.payment_processor_job.error',
|
|
60
|
-
data: {
|
|
61
|
-
payment_number: payment_number,
|
|
62
|
-
queue: self.class.queue_name,
|
|
63
|
-
queue_wait_ms: queue_wait_ms,
|
|
64
|
-
runtime_ms: runtime_ms,
|
|
65
|
-
error_class: error.class.name,
|
|
66
|
-
error_message: error.message
|
|
67
|
-
}
|
|
68
|
-
)
|
|
69
9
|
end
|
|
70
10
|
end
|
|
71
11
|
end
|
|
@@ -66,7 +66,7 @@ module Vpago
|
|
|
66
66
|
def process_aba_v2_gateway
|
|
67
67
|
payment_option = @payment.payment_method.preferences[:payment_option]
|
|
68
68
|
|
|
69
|
-
if
|
|
69
|
+
if payment_option == 'abapay'
|
|
70
70
|
process_abapay_v2_deeplink
|
|
71
71
|
else
|
|
72
72
|
# construct web url for render web view.
|
|
@@ -1,13 +1,41 @@
|
|
|
1
1
|
<% @checkout = ::Vpago::PaywayV2::Checkout.new(@payment) %>
|
|
2
|
+
<% payment_option = @payment.payment_method.preferences[:payment_option] %>
|
|
3
|
+
|
|
4
|
+
<form method="POST"
|
|
5
|
+
action="<%= @checkout.checkout_url %>"
|
|
6
|
+
id="aba_merchant_request"
|
|
7
|
+
data-payment-option="<%= payment_option %>"
|
|
8
|
+
style="<%= 'display:none;' if payment_option == 'abapay_khqr_deeplink' %>">
|
|
2
9
|
|
|
3
|
-
<form method="POST" action="<%= @checkout.checkout_url %>" id="aba_merchant_request">
|
|
4
10
|
<% @checkout.gateway_params.each do |key, value| %>
|
|
5
|
-
<input type=
|
|
11
|
+
<input type="hidden" name="<%= key %>" value="<%= value %>">
|
|
6
12
|
<% end %>
|
|
7
13
|
</form>
|
|
8
14
|
|
|
9
15
|
<script>
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
16
|
+
document.addEventListener("DOMContentLoaded", function () {
|
|
17
|
+
const form = document.getElementById("aba_merchant_request");
|
|
18
|
+
const paymentOption = form.dataset.paymentOption;
|
|
19
|
+
|
|
20
|
+
// 🔹 CASE 1: ABA KHQR Deeplink → fetch JSON then redirect
|
|
21
|
+
if (paymentOption === "abapay_khqr_deeplink") {
|
|
22
|
+
fetch(form.action, {
|
|
23
|
+
method: "POST",
|
|
24
|
+
body: new FormData(form)
|
|
25
|
+
})
|
|
26
|
+
.then(res => res.json())
|
|
27
|
+
.then(data => {
|
|
28
|
+
if (data.checkout_qr_url) {
|
|
29
|
+
window.location.href = data.checkout_qr_url;
|
|
30
|
+
} else {
|
|
31
|
+
console.error("checkout_qr_url missing", data);
|
|
32
|
+
}
|
|
33
|
+
})
|
|
34
|
+
.catch(err => console.error("ABA Deeplink Error:", err));
|
|
35
|
+
|
|
36
|
+
// 🔹 CASE 2: Normal ABA KHQR → regular redirect form post
|
|
37
|
+
} else {
|
|
38
|
+
form.submit();
|
|
39
|
+
}
|
|
40
|
+
});
|
|
13
41
|
</script>
|
data/lib/spree_vpago/version.rb
CHANGED
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
require 'faraday'
|
|
2
|
-
require 'vpago/timing_helper'
|
|
3
2
|
|
|
4
3
|
module Vpago
|
|
5
4
|
module PaywayV2
|
|
@@ -36,8 +35,6 @@ module Vpago
|
|
|
36
35
|
end
|
|
37
36
|
|
|
38
37
|
def check_remote_status
|
|
39
|
-
started_at = Process.clock_gettime(Process::CLOCK_MONOTONIC)
|
|
40
|
-
|
|
41
38
|
conn = Faraday::Connection.new do |faraday|
|
|
42
39
|
faraday.request :url_encoded
|
|
43
40
|
end
|
|
@@ -49,33 +46,7 @@ module Vpago
|
|
|
49
46
|
hash: checker_hmac
|
|
50
47
|
}
|
|
51
48
|
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
runtime_ms = Vpago::TimingHelper.elapsed_ms(started_at)
|
|
55
|
-
Rails.logger.info(
|
|
56
|
-
{
|
|
57
|
-
event: 'vpago.payway.check_transaction',
|
|
58
|
-
version: 'v2',
|
|
59
|
-
payment_number: transaction_id,
|
|
60
|
-
http_status: response.status,
|
|
61
|
-
runtime_ms: runtime_ms
|
|
62
|
-
}
|
|
63
|
-
)
|
|
64
|
-
|
|
65
|
-
response
|
|
66
|
-
rescue StandardError => e
|
|
67
|
-
runtime_ms = Vpago::TimingHelper.elapsed_ms(started_at)
|
|
68
|
-
Rails.logger.error(
|
|
69
|
-
{
|
|
70
|
-
event: 'vpago.payway.check_transaction.error',
|
|
71
|
-
version: 'v2',
|
|
72
|
-
payment_number: transaction_id,
|
|
73
|
-
runtime_ms: runtime_ms,
|
|
74
|
-
error_class: e.class.name,
|
|
75
|
-
error_message: e.message
|
|
76
|
-
}
|
|
77
|
-
)
|
|
78
|
-
raise
|
|
49
|
+
conn.post(check_transaction_url, data)
|
|
79
50
|
end
|
|
80
51
|
|
|
81
52
|
def payout_total
|
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.2.
|
|
4
|
+
version: 2.2.2.pre.pre1
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- You
|
|
8
8
|
autorequire:
|
|
9
9
|
bindir: bin
|
|
10
10
|
cert_chain: []
|
|
11
|
-
date: 2026-02-
|
|
11
|
+
date: 2026-02-10 00:00:00.000000000 Z
|
|
12
12
|
dependencies:
|
|
13
13
|
- !ruby/object:Gem::Dependency
|
|
14
14
|
name: faraday
|
|
@@ -188,7 +188,6 @@ files:
|
|
|
188
188
|
- app/jobs/vpago/payment_capturer_job.rb
|
|
189
189
|
- app/jobs/vpago/payment_processor_job.rb
|
|
190
190
|
- app/jobs/vpago/payment_voider_job.rb
|
|
191
|
-
- app/lib/vpago/timing_helper.rb
|
|
192
191
|
- app/models/.gitkeep
|
|
193
192
|
- app/models/concerns/vpago/payoutable.rb
|
|
194
193
|
- app/models/spree/gateway/acleda.rb
|
|
@@ -419,7 +418,6 @@ files:
|
|
|
419
418
|
- lib/vpago/wing_sdk/payment_retriever.rb
|
|
420
419
|
- lib/vpago/wing_sdk/transaction_status_checker.rb
|
|
421
420
|
- lib/vpago/wing_sdk/transaction_status_response.rb
|
|
422
|
-
- lib/vpago_logger.rb
|
|
423
421
|
- node_modules/.yarn-integrity
|
|
424
422
|
- package-lock.json
|
|
425
423
|
- package.json
|
|
@@ -441,9 +439,9 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
|
441
439
|
version: 3.2.0
|
|
442
440
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
|
443
441
|
requirements:
|
|
444
|
-
- - "
|
|
442
|
+
- - ">"
|
|
445
443
|
- !ruby/object:Gem::Version
|
|
446
|
-
version:
|
|
444
|
+
version: 1.3.1
|
|
447
445
|
requirements:
|
|
448
446
|
- none
|
|
449
447
|
rubygems_version: 3.4.1
|
|
@@ -1,28 +0,0 @@
|
|
|
1
|
-
module Vpago
|
|
2
|
-
module TimingHelper
|
|
3
|
-
# Gets the current monotonic timestamp.
|
|
4
|
-
#
|
|
5
|
-
# @return [Float] current timestamp from Process.clock_gettime(Process::CLOCK_MONOTONIC)
|
|
6
|
-
def self.current_time
|
|
7
|
-
Process.clock_gettime(Process::CLOCK_MONOTONIC)
|
|
8
|
-
end
|
|
9
|
-
|
|
10
|
-
# Measures elapsed time in milliseconds from a given start timestamp.
|
|
11
|
-
#
|
|
12
|
-
# @param started_at [Float] timestamp from Process.clock_gettime(Process::CLOCK_MONOTONIC)
|
|
13
|
-
# @return [Float] elapsed time in milliseconds, rounded to 1 decimal place
|
|
14
|
-
def self.elapsed_ms(started_at)
|
|
15
|
-
((Process.clock_gettime(Process::CLOCK_MONOTONIC) - started_at) * 1000.0).round(1)
|
|
16
|
-
end
|
|
17
|
-
|
|
18
|
-
# Yields to a block and measures its execution time in milliseconds.
|
|
19
|
-
#
|
|
20
|
-
# @yield the block to measure
|
|
21
|
-
# @return [Float] elapsed time in milliseconds, rounded to 1 decimal place
|
|
22
|
-
def self.measure_ms
|
|
23
|
-
started_at = Process.clock_gettime(Process::CLOCK_MONOTONIC)
|
|
24
|
-
yield
|
|
25
|
-
elapsed_ms(started_at)
|
|
26
|
-
end
|
|
27
|
-
end
|
|
28
|
-
end
|
data/lib/vpago_logger.rb
DELETED
|
@@ -1,21 +0,0 @@
|
|
|
1
|
-
module VpagoLogger
|
|
2
|
-
def self.log(event:, data: nil)
|
|
3
|
-
message = { event: event }
|
|
4
|
-
message.merge!(data) if data
|
|
5
|
-
|
|
6
|
-
Rails.logger.info(message.to_json)
|
|
7
|
-
message
|
|
8
|
-
rescue StandardError
|
|
9
|
-
message
|
|
10
|
-
end
|
|
11
|
-
|
|
12
|
-
def self.error(event:, data: nil)
|
|
13
|
-
message = { event: event }
|
|
14
|
-
message.merge!(data) if data
|
|
15
|
-
|
|
16
|
-
Rails.logger.error(message.to_json)
|
|
17
|
-
message
|
|
18
|
-
rescue StandardError
|
|
19
|
-
message
|
|
20
|
-
end
|
|
21
|
-
end
|