spree_vpago 2.0.4.pre.beta1 → 2.0.5.pre.beta
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 +1 -1
- data/app/helpers/vpago/admin/base_helper_decorator.rb +1 -0
- data/app/models/spree/gateway/vattanac_mini_app.rb +75 -0
- data/app/models/vpago/payment_decorator.rb +5 -0
- data/app/models/vpago/payment_method_decorator.rb +7 -1
- data/app/services/vpago/aes_encrypter.rb +56 -0
- data/app/services/vpago/payment_finder.rb +19 -3
- data/app/services/vpago/payment_processable.rb +1 -1
- data/app/services/vpago/rsa_handler.rb +27 -0
- data/app/services/vpago/vattanac_mini_app_data_handler.rb +33 -0
- data/app/views/spree/admin/payments/source_views/_vattanac_mini_app.html.erb +6 -0
- data/app/views/spree/vpago_payments/forms/spree/gateway/_vattanac_mini_app.html.erb +89 -0
- data/lib/spree_vpago/engine.rb +2 -1
- data/lib/spree_vpago/version.rb +1 -1
- data/lib/vpago/vattanac_mini_app/base.rb +52 -0
- data/lib/vpago/vattanac_mini_app/checkout.rb +9 -0
- data/lib/vpago/vattanac_mini_app/refund_issuer.rb +54 -0
- metadata +11 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 693e45fc6915c023a690b5aa8c3e44cf18e21bcb5c6cc7fd8d520ee964db418a
|
4
|
+
data.tar.gz: 602e1ac04e520e6b11452125ae7a88801a8545845df3d5417cb46008ec04bf0a
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: ae4e9828ecb2d4cdc9d7abb038b5304ea5f7871a33fba13af4907e87b5351f9c15630137d7c4ae76796a2d469b55003806098f9fb5e8a4a37d83ade2d3e118d9
|
7
|
+
data.tar.gz: ff5ea0f427d105324e5d9726c0b7dc44ac84acac1ca8659aeb7f119c60244f577cd0a33e57b1057c0d48ca2f59344894eee7612c71f88b10fc4aa496e34632c7
|
data/Gemfile.lock
CHANGED
@@ -0,0 +1,75 @@
|
|
1
|
+
module Spree
|
2
|
+
class Gateway::VattanacMiniApp < PaymentMethod
|
3
|
+
|
4
|
+
def method_type
|
5
|
+
'vattanac_mini_app'
|
6
|
+
end
|
7
|
+
|
8
|
+
def payment_source_class
|
9
|
+
Spree::VpagoPaymentSource
|
10
|
+
end
|
11
|
+
|
12
|
+
# force to purchase instead of authorize
|
13
|
+
def auto_capture?
|
14
|
+
true
|
15
|
+
end
|
16
|
+
|
17
|
+
|
18
|
+
# override
|
19
|
+
# purchase is used when pre auth disabled
|
20
|
+
def purchase(_amount, _source, gateway_options = {})
|
21
|
+
_, payment_number = gateway_options[:order_id].split('-')
|
22
|
+
payment = Spree::Payment.find_by(number: payment_number)
|
23
|
+
|
24
|
+
params = {}
|
25
|
+
|
26
|
+
params[:payment_response] = payment.transaction_response
|
27
|
+
|
28
|
+
|
29
|
+
if payment.transaction_response["status"] == 'SUCCESS'
|
30
|
+
ActiveMerchant::Billing::Response.new(true, 'Payway Gateway: Purchased', params)
|
31
|
+
else
|
32
|
+
ActiveMerchant::Billing::Response.new(false, 'Payway Gateway: Purchasing Failed', params)
|
33
|
+
end
|
34
|
+
|
35
|
+
end
|
36
|
+
|
37
|
+
|
38
|
+
# override
|
39
|
+
def void(_response_code, gateway_options)
|
40
|
+
_, payment_number = gateway_options[:order_id].split('-')
|
41
|
+
payment = Spree::Payment.find_by(number: payment_number)
|
42
|
+
|
43
|
+
if payment.vattanac_mini_app_payment?
|
44
|
+
params = {}
|
45
|
+
success, params[:refund_response] = vattanac_mini_app_refund(payment)
|
46
|
+
|
47
|
+
if success
|
48
|
+
ActiveMerchant::Billing::Response.new(true, 'Payway Gateway: successfully canceled.', params)
|
49
|
+
else
|
50
|
+
ActiveMerchant::Billing::Response.new(false, 'Payway Gateway: Failed to canceleed', params)
|
51
|
+
end
|
52
|
+
else
|
53
|
+
ActiveMerchant::Billing::Response.new(true, 'Payway Gateway: Payment has been voided.')
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
57
|
+
|
58
|
+
def vattanac_mini_app_refund(payment)
|
59
|
+
|
60
|
+
refund_issuer = Vpago::VattanacMiniApp::RefundIssuer.new(payment, {})
|
61
|
+
refund_issuer.call
|
62
|
+
|
63
|
+
[refund_issuer.success?, refund_issuer.response]
|
64
|
+
|
65
|
+
end
|
66
|
+
|
67
|
+
def cancel(_response_code)
|
68
|
+
# we can use this to send request to payment gateway api to cancel the payment ( void )
|
69
|
+
# currently Payway does not support to cancel the gateway
|
70
|
+
|
71
|
+
# in our case don't do anything
|
72
|
+
ActiveMerchant::Billing::Response.new(true, 'Vattanc order has been cancelled.')
|
73
|
+
end
|
74
|
+
end
|
75
|
+
end
|
@@ -5,6 +5,7 @@ module Vpago
|
|
5
5
|
TYPE_WINGSDK = 'Spree::Gateway::WingSdk'.freeze
|
6
6
|
TYPE_ACLEDA = 'Spree::Gateway::Acleda'.freeze
|
7
7
|
TYPE_ACLEDA_MOBILE = 'Spree::Gateway::AcledaMobile'.freeze
|
8
|
+
TYPE_VATTANAC_MINI_APP = 'Spree::Gateway::VattanacMiniApp'.freeze
|
8
9
|
|
9
10
|
def self.prepended(base)
|
10
11
|
base.preference :icon_name, :string, default: 'cheque'
|
@@ -16,7 +17,8 @@ module Vpago
|
|
16
17
|
Spree::PaymentMethod::TYPE_PAYWAY,
|
17
18
|
Spree::PaymentMethod::TYPE_WINGSDK,
|
18
19
|
Spree::PaymentMethod::TYPE_ACLEDA,
|
19
|
-
Spree::PaymentMethod::TYPE_ACLEDA_MOBILE
|
20
|
+
Spree::PaymentMethod::TYPE_ACLEDA_MOBILE,
|
21
|
+
Spree::PaymentMethod::TYPE_VATTANAC_MINI_APP
|
20
22
|
]
|
21
23
|
end
|
22
24
|
end
|
@@ -85,6 +87,10 @@ module Vpago
|
|
85
87
|
def type_wingsdk?
|
86
88
|
type == Spree::PaymentMethod::TYPE_WINGSDK
|
87
89
|
end
|
90
|
+
|
91
|
+
def type_vattanac_mini_app?
|
92
|
+
type == Spree::PaymentMethod::TYPE_VATTANAC_MINI_APP
|
93
|
+
end
|
88
94
|
end
|
89
95
|
end
|
90
96
|
|
@@ -0,0 +1,56 @@
|
|
1
|
+
require 'base64'
|
2
|
+
require 'openssl'
|
3
|
+
|
4
|
+
module Vpago
|
5
|
+
class AesEncrypter
|
6
|
+
ALGORITHM = 'aes-256-gcm'.freeze
|
7
|
+
KEY_LENGTH = 32
|
8
|
+
IV_LENGTH = 12
|
9
|
+
TAG_LENGTH = 16
|
10
|
+
|
11
|
+
def self.encrypt(plaintext, base64_key)
|
12
|
+
key = Base64.decode64(base64_key)
|
13
|
+
validate_key!(key)
|
14
|
+
|
15
|
+
cipher = OpenSSL::Cipher.new(ALGORITHM)
|
16
|
+
cipher.encrypt
|
17
|
+
cipher.key = key[0, KEY_LENGTH]
|
18
|
+
iv = cipher.random_iv
|
19
|
+
cipher.iv = iv
|
20
|
+
|
21
|
+
ciphertext = cipher.update(plaintext) + cipher.final
|
22
|
+
tag = cipher.auth_tag
|
23
|
+
|
24
|
+
combined = iv + ciphertext + tag
|
25
|
+
Base64.strict_encode64(combined)
|
26
|
+
end
|
27
|
+
|
28
|
+
def self.decrypt(encrypted_text, base64_key)
|
29
|
+
key = Base64.decode64(base64_key)
|
30
|
+
validate_key!(key)
|
31
|
+
|
32
|
+
combined = Base64.decode64(encrypted_text)
|
33
|
+
iv = combined[0, IV_LENGTH]
|
34
|
+
tag = combined[-TAG_LENGTH..]
|
35
|
+
ciphertext = combined[IV_LENGTH...-TAG_LENGTH]
|
36
|
+
|
37
|
+
cipher = OpenSSL::Cipher.new(ALGORITHM)
|
38
|
+
cipher.decrypt
|
39
|
+
cipher.key = key[0, KEY_LENGTH]
|
40
|
+
cipher.iv = iv
|
41
|
+
cipher.auth_tag = tag
|
42
|
+
|
43
|
+
cipher.update(ciphertext) + cipher.final
|
44
|
+
rescue OpenSSL::Cipher::CipherError => e
|
45
|
+
raise "Decryption failed: #{e.message}"
|
46
|
+
end
|
47
|
+
|
48
|
+
def self.validate_key!(key)
|
49
|
+
return if key.is_a?(String) && key.bytesize >= KEY_LENGTH
|
50
|
+
|
51
|
+
raise ArgumentError, "Key must be a string of at least #{KEY_LENGTH} bytes"
|
52
|
+
end
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
56
|
+
|
@@ -7,6 +7,7 @@ module Vpago
|
|
7
7
|
end
|
8
8
|
|
9
9
|
def find_and_verify
|
10
|
+
|
10
11
|
find_and_verify!
|
11
12
|
rescue StandardError, ActiveRecord::RecordNotFound => e
|
12
13
|
Rails.logger.error("PaymentJwtVerifier#find_and_verify error: #{e.class} - #{e.message}")
|
@@ -14,14 +15,29 @@ module Vpago
|
|
14
15
|
end
|
15
16
|
|
16
17
|
def find_and_verify!
|
17
|
-
order = Spree::Order.find_by!(number: params_hash[:order_number])
|
18
|
-
verify_jwt!(order)
|
19
18
|
|
20
|
-
|
19
|
+
if vattanac_mini_app_payload?
|
20
|
+
payload = Vpago::VattanacMiniAppDataHandler.new.decrypt_data(@params_hash[:data])
|
21
|
+
payment = Spree::Payment.find_by!(number: payload['paymentId'])
|
22
|
+
payment.update(transaction_response: payload)
|
23
|
+
payment
|
24
|
+
else
|
25
|
+
order = Spree::Order.find_by!(number: params_hash[:order_number])
|
26
|
+
verify_jwt!(order)
|
27
|
+
|
28
|
+
Spree::Payment.find_by!(number: params_hash[:payment_number])
|
29
|
+
end
|
21
30
|
end
|
22
31
|
|
23
32
|
def verify_jwt!(order)
|
24
33
|
JWT.decode(params_hash[:order_jwt_token], order.token, 'HS256')
|
25
34
|
end
|
35
|
+
|
36
|
+
def vattanac_mini_app_payload?
|
37
|
+
params_hash[:data].present?
|
38
|
+
end
|
39
|
+
|
26
40
|
end
|
27
41
|
end
|
42
|
+
|
43
|
+
|
@@ -16,7 +16,7 @@ module Vpago
|
|
16
16
|
# 2. Pre-auth is enabled, ensuring funds can be released to user if processing fails.
|
17
17
|
# PaymentProcessor is usually called after payment is made, so canceling pre-auth typically works.
|
18
18
|
def can_cancel_pre_auth?
|
19
|
-
@payment.pending? || @payment.payment_method.enable_pre_auth?
|
19
|
+
@payment.pending? || @payment.payment_method.enable_pre_auth? || @payment.vattanac_mini_app_payment?
|
20
20
|
end
|
21
21
|
|
22
22
|
def extract_completer_failure_reason_code(error)
|
@@ -0,0 +1,27 @@
|
|
1
|
+
require 'base64'
|
2
|
+
require 'openssl'
|
3
|
+
|
4
|
+
module Vpago
|
5
|
+
class RsaHandler
|
6
|
+
def initialize(private_key: nil, public_key: nil)
|
7
|
+
@private_key = private_key
|
8
|
+
@public_key = public_key
|
9
|
+
end
|
10
|
+
|
11
|
+
def sign(data)
|
12
|
+
raise 'Private key is required to sign data' unless @private_key
|
13
|
+
|
14
|
+
private_key_object = OpenSSL::PKey::RSA.new(@private_key)
|
15
|
+
signature = private_key_object.sign(OpenSSL::Digest.new('SHA256'), data)
|
16
|
+
"#{data}.#{Base64.strict_encode64(signature)}"
|
17
|
+
end
|
18
|
+
|
19
|
+
def verify(data, signature)
|
20
|
+
raise 'Public key is required to verify signature' unless @public_key
|
21
|
+
|
22
|
+
public_key_object = OpenSSL::PKey::RSA.new(@public_key)
|
23
|
+
signature_bytes = Base64.decode64(signature)
|
24
|
+
public_key_object.verify(OpenSSL::Digest.new('SHA256'), signature_bytes, data)
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
@@ -0,0 +1,33 @@
|
|
1
|
+
module Vpago
|
2
|
+
class VattanacMiniAppDataHandler
|
3
|
+
def decrypt_data(data)
|
4
|
+
encrypted_data, signature = data.to_s.split('.', 2)
|
5
|
+
|
6
|
+
return nil unless Vpago::RsaHandler.new(public_key: vattanac_public_key).verify(encrypted_data, signature)
|
7
|
+
|
8
|
+
decrypted = Vpago::AesEncrypter.decrypt(encrypted_data, aes_key)
|
9
|
+
JSON.parse(decrypted) rescue nil
|
10
|
+
|
11
|
+
end
|
12
|
+
|
13
|
+
def encrypted_data(payload)
|
14
|
+
json_payload = payload.to_json
|
15
|
+
encrypted_data = Vpago::AesEncrypter.encrypt(json_payload, aes_key)
|
16
|
+
rsa_service = Vpago::RsaHandler.new(private_key: bookmeplus_private_key)
|
17
|
+
signed_data = rsa_service.sign(encrypted_data)
|
18
|
+
signed_data
|
19
|
+
end
|
20
|
+
|
21
|
+
def vattanac_public_key
|
22
|
+
ENV['VATTANAC_PUBLIC_KEY'].presence || Rails.application.credentials.vattanac.public_key
|
23
|
+
end
|
24
|
+
|
25
|
+
def bookmeplus_private_key
|
26
|
+
ENV['BOOKMEPLUS_PRIVATE_KEY'].presence || Rails.application.credentials.bookmeplus.private_key
|
27
|
+
end
|
28
|
+
|
29
|
+
def aes_key
|
30
|
+
ENV['VATTANAC_AES_SECRET_KEY'].presence || Rails.application.credentials.vattanac.aes_secret_key
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
@@ -0,0 +1,89 @@
|
|
1
|
+
<% @checkout = ::Vpago::VattanacMiniApp::Checkout.new(@payment) %>
|
2
|
+
<% @payment.user_informer.payment_is_processing(processing: true) %>
|
3
|
+
|
4
|
+
<p id="unsupported-message"
|
5
|
+
style="margin-top: 10px;
|
6
|
+
font-weight: bold;
|
7
|
+
color: red;
|
8
|
+
display: none;">
|
9
|
+
</p>
|
10
|
+
|
11
|
+
<h1 id="status">THIS IS CURRENT STATE</h1>
|
12
|
+
<p id="reason_code"></p>
|
13
|
+
<p id="processing"></p>
|
14
|
+
<p id="reason_message"></p>
|
15
|
+
|
16
|
+
<script>
|
17
|
+
|
18
|
+
function detectMobileOS() {
|
19
|
+
const ua = navigator.userAgent || navigator.vendor || window.opera;
|
20
|
+
if (/iPad|iPhone|iPod/.test(ua) && !window.MSStream) return 'iOS';
|
21
|
+
if (/Android/i.test(ua)) return 'Android';
|
22
|
+
return 'unknown';
|
23
|
+
}
|
24
|
+
|
25
|
+
document.addEventListener('DOMContentLoaded', () => {
|
26
|
+
const os = detectMobileOS();
|
27
|
+
const payload = {
|
28
|
+
data: "<%= j @checkout.signed_payload %>",
|
29
|
+
paymentId: "<%= @checkout.payment_id %>"
|
30
|
+
};
|
31
|
+
|
32
|
+
if (os === 'iOS' && window.webkit?.messageHandlers?.startPayment) {
|
33
|
+
window.webkit.messageHandlers.startPayment.postMessage(JSON.stringify(payload));
|
34
|
+
} else if (os === 'Android' && window.AndroidInterface?.startPayment) {
|
35
|
+
window.AndroidInterface.startPayment(JSON.stringify(payload));
|
36
|
+
} else {
|
37
|
+
const unsupported = document.getElementById('unsupported-message');
|
38
|
+
unsupported.style.display = 'block';
|
39
|
+
unsupported.innerText = 'Unsupported OS';
|
40
|
+
}
|
41
|
+
|
42
|
+
const firebaseConfigs = <%= Rails.application.credentials.firebase_web_config.to_json.html_safe %>;
|
43
|
+
|
44
|
+
window.listenToProcessingState({
|
45
|
+
firebaseConfigs: firebaseConfigs,
|
46
|
+
documentReferencePath: "<%= @payment.user_informer.document_reference_path %>",
|
47
|
+
onPaymentIsProcessing: function (orderState, paymentState, processing, reasonCode, reasonMessage) {
|
48
|
+
document.getElementById("status").innerText = "Payment is processing";
|
49
|
+
document.getElementById("reason_code").innerText = reasonCode;
|
50
|
+
document.getElementById("processing").innerText = processing ? "Processing..." : "No more process.";
|
51
|
+
document.getElementById("reason_message").innerText = reasonMessage;
|
52
|
+
},
|
53
|
+
onOrderIsProcessing: function (orderState, paymentState, processing, reasonCode, reasonMessage) {
|
54
|
+
document.getElementById("status").innerText = "Order is processing";
|
55
|
+
document.getElementById("reason_code").innerText = reasonCode;
|
56
|
+
document.getElementById("processing").innerText = processing ? "Processing..." : "No more process.";
|
57
|
+
document.getElementById("reason_message").innerText = reasonMessage;
|
58
|
+
},
|
59
|
+
onOrderIsCompleted: function (orderState, paymentState, processing, reasonCode, reasonMessage) {
|
60
|
+
document.getElementById("status").innerText = "Order is completed";
|
61
|
+
document.getElementById("reason_code").innerText = reasonCode;
|
62
|
+
document.getElementById("processing").innerText = processing ? "Processing..." : "No more process.";
|
63
|
+
document.getElementById("reason_message").innerText = reasonMessage;
|
64
|
+
},
|
65
|
+
onOrderProcessFailed: function (orderState, paymentState, processing, reasonCode, reasonMessage) {
|
66
|
+
document.getElementById("status").innerText = "Order process failed";
|
67
|
+
document.getElementById("reason_code").innerText = reasonCode;
|
68
|
+
document.getElementById("processing").innerText = processing ? "Processing..." : "No more process.";
|
69
|
+
document.getElementById("reason_message").innerText = reasonMessage;
|
70
|
+
},
|
71
|
+
onPaymentIsRefunded: function (orderState, paymentState, processing, reasonCode, reasonMessage) {
|
72
|
+
document.getElementById("status").innerText = "Payment is refunded";
|
73
|
+
document.getElementById("reason_code").innerText = reasonCode;
|
74
|
+
document.getElementById("processing").innerText = processing ? "Processing..." : "No more process.";
|
75
|
+
document.getElementById("reason_message").innerText = reasonMessage
|
76
|
+
},
|
77
|
+
onPaymentProcessFailed: function (orderState, paymentState, processing, reasonCode, reasonMessage) {
|
78
|
+
document.getElementById("status").innerText = "Payment process failed";
|
79
|
+
document.getElementById("reason_code").innerText = reasonCode;
|
80
|
+
document.getElementById("processing").innerText = processing ? "Processing..." : "No more process.";
|
81
|
+
document.getElementById("reason_message").innerText = reasonMessage;
|
82
|
+
},
|
83
|
+
onCompleted: function (orderState, paymentState, processing, reasonCode, reasonMessage) {
|
84
|
+
let successPath = "<%= @payment.success_url %>";
|
85
|
+
window.location.href = successPath;
|
86
|
+
},
|
87
|
+
});
|
88
|
+
});
|
89
|
+
</script>
|
data/lib/spree_vpago/engine.rb
CHANGED
data/lib/spree_vpago/version.rb
CHANGED
@@ -0,0 +1,52 @@
|
|
1
|
+
module Vpago
|
2
|
+
module VattanacMiniApp
|
3
|
+
class Base
|
4
|
+
|
5
|
+
def initialize(payment, options = {})
|
6
|
+
@options = options
|
7
|
+
@payment = payment
|
8
|
+
end
|
9
|
+
|
10
|
+
def payload
|
11
|
+
{
|
12
|
+
paymentId: payment_id,
|
13
|
+
amount: amount,
|
14
|
+
currency: currency || 'USD',
|
15
|
+
expiredIn: expired_at
|
16
|
+
}
|
17
|
+
end
|
18
|
+
|
19
|
+
def encrypt_data(payload)
|
20
|
+
SpreeCmCommissioner::AesEncryptionService.encrypt(payload.to_json, aes_key)
|
21
|
+
end
|
22
|
+
|
23
|
+
def amount
|
24
|
+
@payment.amount
|
25
|
+
end
|
26
|
+
|
27
|
+
def payment_id
|
28
|
+
@payment.number
|
29
|
+
end
|
30
|
+
|
31
|
+
def currency
|
32
|
+
'USD'
|
33
|
+
end
|
34
|
+
|
35
|
+
def transaction_id
|
36
|
+
@payment.number
|
37
|
+
end
|
38
|
+
|
39
|
+
def expired_at
|
40
|
+
(Time.now + 30.minutes).to_i * 1000
|
41
|
+
end
|
42
|
+
|
43
|
+
def partner_code
|
44
|
+
ENV['VATTANAC_PARTNER_CODE'].presence
|
45
|
+
end
|
46
|
+
|
47
|
+
def refund_url
|
48
|
+
ENV['VATTANAC_REFUND_URL'].presence
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
@@ -0,0 +1,54 @@
|
|
1
|
+
module Vpago
|
2
|
+
module VattanacMiniApp
|
3
|
+
class RefundIssuer < Base
|
4
|
+
attr_reader :response
|
5
|
+
|
6
|
+
def call
|
7
|
+
raw_response = send_refund_request
|
8
|
+
@response = handle_response(raw_response)
|
9
|
+
end
|
10
|
+
|
11
|
+
def success?
|
12
|
+
@success
|
13
|
+
end
|
14
|
+
|
15
|
+
def send_refund_request
|
16
|
+
Faraday.post(refund_url) do |req|
|
17
|
+
req.headers['Content-Type'] = 'application/json'
|
18
|
+
req.headers['Partner-Code'] = partner_code
|
19
|
+
req.body = {
|
20
|
+
data: Vpago::VattanacMiniAppDataHandler.new.encrypted_data(refund_payload)
|
21
|
+
}.to_json
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
def handle_response(response)
|
26
|
+
body = parse_json(response.body)
|
27
|
+
|
28
|
+
if body['status'] == 'SUCCESS'
|
29
|
+
json = Vpago::VattanacMiniAppDataHandler.new.decrypt_data(body['data'])
|
30
|
+
@success = true
|
31
|
+
json
|
32
|
+
else
|
33
|
+
@success = false
|
34
|
+
body
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
def refund_payload
|
39
|
+
{
|
40
|
+
transactionId: @payment.transaction_response["transactionId"],
|
41
|
+
paymentId: @payment.transaction_response["paymentId"],
|
42
|
+
amount: @payment.transaction_response["amount"],
|
43
|
+
currency: 'USD'
|
44
|
+
}
|
45
|
+
end
|
46
|
+
|
47
|
+
def parse_json(raw)
|
48
|
+
JSON.parse(raw)
|
49
|
+
rescue JSON::ParserError => e
|
50
|
+
raise StandardError, "Invalid JSON: #{e.message}"
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
54
|
+
end
|
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.0.
|
4
|
+
version: 2.0.5.pre.beta
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- You
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2025-06-
|
11
|
+
date: 2025-06-11 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: faraday
|
@@ -179,6 +179,7 @@ files:
|
|
179
179
|
- app/models/spree/gateway/acleda_mobile.rb
|
180
180
|
- app/models/spree/gateway/payway.rb
|
181
181
|
- app/models/spree/gateway/payway_v2.rb
|
182
|
+
- app/models/spree/gateway/vattanac_mini_app.rb
|
182
183
|
- app/models/spree/gateway/wing_sdk.rb
|
183
184
|
- app/models/spree/payout.rb
|
184
185
|
- app/models/spree/payout_profile.rb
|
@@ -231,6 +232,7 @@ files:
|
|
231
232
|
- app/serializers/spree/v2/storefront/payment_serializer_decorator.rb
|
232
233
|
- app/serializers/spree/v2/storefront/vpago_payment_source_serializer.rb
|
233
234
|
- app/services/.gitkeep
|
235
|
+
- app/services/vpago/aes_encrypter.rb
|
234
236
|
- app/services/vpago/payment_finder.rb
|
235
237
|
- app/services/vpago/payment_processable.rb
|
236
238
|
- app/services/vpago/payment_processor.rb
|
@@ -243,7 +245,9 @@ files:
|
|
243
245
|
- app/services/vpago/payout_profiles/payway/payout_profile_request_params_builder.rb
|
244
246
|
- app/services/vpago/payout_profiles/payway/payout_profile_request_updater.rb
|
245
247
|
- app/services/vpago/payway_return_options_builder.rb
|
248
|
+
- app/services/vpago/rsa_handler.rb
|
246
249
|
- app/services/vpago/user_informers/firebase.rb
|
250
|
+
- app/services/vpago/vattanac_mini_app_data_handler.rb
|
247
251
|
- app/views/.gitkeep
|
248
252
|
- app/views/layouts/acleda.html.erb
|
249
253
|
- app/views/layouts/payway.html.erb
|
@@ -258,6 +262,7 @@ files:
|
|
258
262
|
- app/views/spree/admin/payments/source_views/_acleda_mobile.html.erb
|
259
263
|
- app/views/spree/admin/payments/source_views/_payment_payway.html.erb
|
260
264
|
- app/views/spree/admin/payments/source_views/_payway_v2.html.erb
|
265
|
+
- app/views/spree/admin/payments/source_views/_vattanac_mini_app.html.erb
|
261
266
|
- app/views/spree/admin/payments/source_views/_vpago_payment_tmpl.html.erb
|
262
267
|
- app/views/spree/admin/payments/source_views/_wingsdk.html.erb
|
263
268
|
- app/views/spree/admin/payout_profile_products/_form.html.erb
|
@@ -304,6 +309,7 @@ files:
|
|
304
309
|
- app/views/spree/payway_v2_card_popups/show.html.erb
|
305
310
|
- app/views/spree/vpago_payments/checkout.html.erb
|
306
311
|
- app/views/spree/vpago_payments/forms/spree/gateway/_payway_v2.html.erb
|
312
|
+
- app/views/spree/vpago_payments/forms/spree/gateway/_vattanac_mini_app.html.erb
|
307
313
|
- app/views/spree/vpago_payments/processing.html.erb
|
308
314
|
- app/views/spree/vpago_payments/success.html.erb
|
309
315
|
- app/views/spree/wing_redirects/show.html.erb
|
@@ -371,6 +377,9 @@ files:
|
|
371
377
|
- lib/vpago/payway_v2/pre_auth_canceler.rb
|
372
378
|
- lib/vpago/payway_v2/pre_auth_completer.rb
|
373
379
|
- lib/vpago/payway_v2/transaction_status.rb
|
380
|
+
- lib/vpago/vattanac_mini_app/base.rb
|
381
|
+
- lib/vpago/vattanac_mini_app/checkout.rb
|
382
|
+
- lib/vpago/vattanac_mini_app/refund_issuer.rb
|
374
383
|
- lib/vpago/wing_sdk/base.rb
|
375
384
|
- lib/vpago/wing_sdk/checkout.rb
|
376
385
|
- lib/vpago/wing_sdk/payment_request_updater.rb
|