spree_vpago 2.3.4 → 2.3.5.pre.pre.pre.2

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 4e73bfb9e0eac7606f41017d8ca6c90e9853296a588f4fccd305331ec4c0c6bc
4
- data.tar.gz: d8180f240e40c47b8983c460892079d2d954638a486855deda122e7971c90bed
3
+ metadata.gz: ab21d4fcbe691887d5e573acc9d10f1a320f7a9afa3605a1a4e6b2b678a9e844
4
+ data.tar.gz: 181e9fa1b7726e24a1bea16e87996e5146722ad94c7b237bd9bf8e180c4e955c
5
5
  SHA512:
6
- metadata.gz: 34e2bd88bce6cb6a090d57fe8e6ea7c9ade90f813d834c998a66a697a96b881700ac084b78dd1074a9ec62d63a87d77942f421a25d9f6c046272526a6a407231
7
- data.tar.gz: 231f3bdd5f51c7dd42b78dd1e93b45937031e32abf49383388f4c62c57de4668d2b64dd9bb89fa6f81d325a25db760c7daaa296b2dc5d69c64ee94b9b3badebf
6
+ metadata.gz: faecabd5b9dc1cf45f3ecda6fa90ca8a26f5f8e8473ca3dfd9199f32e5ab8ccae87c6efc0ba51e80e7995182767b80ace96fcc51af32f83f8dfa5eee2b62a97d
7
+ data.tar.gz: 13d01feda0edcead9ef152b4530b6e951d1f136e1835f91beb4f78923b346a17e0b1d50d0f6c36ca622c4225b3aca65252bdb5cc20a40d303170c1fa6f65c383
data/Gemfile.lock CHANGED
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- spree_vpago (2.3.4)
4
+ spree_vpago (2.3.5.pre.pre.pre.2)
5
5
  faraday
6
6
  google-cloud-firestore
7
7
  spree_api (>= 4.5)
@@ -12,6 +12,7 @@ module Vpago
12
12
  payway_abapay
13
13
  payway_alipay
14
14
  payway_wechat
15
+ acleda_v2
15
16
  acleda
16
17
  acleda_khqr
17
18
  acleda_cards
@@ -28,6 +29,10 @@ module Vpago
28
29
  %w[khqr deeplink all]
29
30
  end
30
31
 
32
+ def available_acleda_v2_modes
33
+ Spree::Gateway::AcledaV2::MODES
34
+ end
35
+
31
36
  def preference_field_for(form, field, options)
32
37
  case field
33
38
  when 'preferred_acleda_type'
@@ -45,6 +50,8 @@ module Vpago
45
50
  return form.select(:preferred_abapay_khqr_deeplink_option, Spree::Gateway::PaywayV2::ABAPAY_KHQR_DEEPLINK_OPTIONS, {}, class: 'fullwidth select2')
46
51
  when 'preferred_vattanac_payment_option'
47
52
  return form.select(:preferred_vattanac_payment_option, available_vattanac_payment_options, {}, class: 'fullwidth select2')
53
+ when 'preferred_acleda_v2_mode'
54
+ return form.select(:preferred_acleda_v2_mode, available_acleda_v2_modes, {}, class: 'fullwidth select2')
48
55
  end
49
56
  super
50
57
  end
@@ -0,0 +1,89 @@
1
+ module Spree
2
+ class Gateway::AcledaV2 < PaymentMethod
3
+ MODES = %w[khqr card deeplink].freeze
4
+
5
+ preference :merchant_name, :string
6
+ preference :xpay_service_base_url, :string
7
+ preference :payment_page_url, :string
8
+ preference :merchant_id, :string
9
+ preference :login_id, :string
10
+ preference :password, :string
11
+ preference :secret, :string # HMAC-SHA512 key
12
+ preference :payment_expiry_time_in_mn, :integer, default: 5
13
+ preference :acleda_v2_mode, :string, default: 'khqr'
14
+
15
+ validates :preferred_acleda_v2_mode, inclusion: { in: MODES }
16
+
17
+ def khqr?
18
+ preferred_acleda_v2_mode == 'khqr'
19
+ end
20
+
21
+ def card?
22
+ preferred_acleda_v2_mode == 'card'
23
+ end
24
+
25
+ def deeplink?
26
+ preferred_acleda_v2_mode == 'deeplink'
27
+ end
28
+
29
+ # KHQR (Scan with Bank under Bakong) = "0"; Credit/debit card = "1"
30
+ def payment_card_value
31
+ card? ? '1' : '0'
32
+ end
33
+
34
+ # override: partial to render in admin
35
+ def method_type
36
+ 'acleda_v2'
37
+ end
38
+
39
+ # override
40
+ def payment_source_class
41
+ Spree::VpagoPaymentSource
42
+ end
43
+
44
+ # override
45
+ def payment_profiles_supported?
46
+ false
47
+ end
48
+
49
+ # override
50
+ def available_for_order?(_order)
51
+ true
52
+ end
53
+
54
+ # override: process! -> purchase! immediately (no pre-auth for ACLEDA V2)
55
+ def auto_capture?
56
+ true
57
+ end
58
+
59
+ # override
60
+ def purchase(_amount, _source, gateway_options = {})
61
+ _, payment_number = gateway_options[:order_id].split('-')
62
+ payment = Spree::Payment.find_by(number: payment_number)
63
+
64
+ checker = check_transaction(payment)
65
+ payment.update(transaction_response: checker.json_response)
66
+
67
+ params = { check: { response: checker.json_response } }
68
+
69
+ if checker.success?
70
+ ActiveMerchant::Billing::Response.new(true, 'Acleda V2: Purchased', params)
71
+ else
72
+ ActiveMerchant::Billing::Response.new(false, 'Acleda V2: Purchasing Failed', params)
73
+ end
74
+ end
75
+
76
+ # Defining check_transaction makes support_check_transaction_api? true,
77
+ # enabling the /vpago_payments/check_transaction poller.
78
+ def check_transaction(payment)
79
+ checker = Vpago::AcledaV2::TransactionStatus.new(payment)
80
+ checker.call
81
+ checker
82
+ end
83
+
84
+ # override
85
+ def cancel(_response_code, _payment = nil)
86
+ ActiveMerchant::Billing::Response.new(true, 'Acleda V2: Payment has been canceled.')
87
+ end
88
+ end
89
+ end
@@ -1,9 +1,10 @@
1
1
  module Vpago
2
- module PaymentMethodDecorator
2
+ module PaymentMethodDecorator # rubocop:disable Metrics/ModuleLength
3
3
  TYPE_PAYWAY = 'Spree::Gateway::Payway'.freeze
4
4
  TYPE_PAYWAY_V2 = 'Spree::Gateway::PaywayV2'.freeze
5
5
  TYPE_WINGSDK = 'Spree::Gateway::WingSdk'.freeze
6
6
  TYPE_ACLEDA = 'Spree::Gateway::Acleda'.freeze
7
+ TYPE_ACLEDA_V2 = 'Spree::Gateway::AcledaV2'.freeze
7
8
  TYPE_ACLEDA_MOBILE = 'Spree::Gateway::AcledaMobile'.freeze
8
9
  TYPE_TRUE_MONEY = 'Spree::Gateway::TrueMoney'.freeze
9
10
  TYPE_VATTANAC = 'Spree::Gateway::Vattanac'.freeze
@@ -21,6 +22,7 @@ module Vpago
21
22
  Spree::PaymentMethod::TYPE_PAYWAY,
22
23
  Spree::PaymentMethod::TYPE_WINGSDK,
23
24
  Spree::PaymentMethod::TYPE_ACLEDA,
25
+ Spree::PaymentMethod::TYPE_ACLEDA_V2,
24
26
  Spree::PaymentMethod::TYPE_ACLEDA_MOBILE,
25
27
  Spree::PaymentMethod::TYPE_VATTANAC,
26
28
  Spree::PaymentMethod::TYPE_VATTANAC_MINI_APP,
@@ -89,6 +91,10 @@ module Vpago
89
91
  type == Spree::PaymentMethod::TYPE_ACLEDA
90
92
  end
91
93
 
94
+ def type_acleda_v2?
95
+ type == Spree::PaymentMethod::TYPE_ACLEDA_V2
96
+ end
97
+
92
98
  def type_payway?
93
99
  type == Spree::PaymentMethod::TYPE_PAYWAY
94
100
  end
@@ -14,11 +14,15 @@ module Vpago
14
14
  end
15
15
 
16
16
  def find_and_verify!
17
- if vattanac_mini_app_payload?
17
+ if vattanac_mini_app_callback?
18
18
  payload = Vpago::VattanacMiniAppDataHandler.new.decrypt_data(@params_hash[:data])
19
19
  payment = Spree::Payment.find_by!(number: payload['paymentId'])
20
20
  payment.update(transaction_response: payload)
21
21
  payment
22
+ elsif acleda_v2_callback?
23
+ # ACLEDA V2's static portal callback echoes back _transactionid, which is
24
+ # the payment number we sent as transactionID/txid at openSessionV2.
25
+ Spree::Payment.find_by!(number: params_hash[:_transactionid])
22
26
  else
23
27
  order = Spree::Order.find_by!(number: params_hash[:order_number])
24
28
  verify_jwt!(order)
@@ -31,8 +35,12 @@ module Vpago
31
35
  JWT.decode(params_hash[:order_jwt_token], order.token, 'HS256')
32
36
  end
33
37
 
34
- def vattanac_mini_app_payload?
38
+ def vattanac_mini_app_callback?
35
39
  params_hash[:data].present?
36
40
  end
41
+
42
+ def acleda_v2_callback?
43
+ params_hash[:_paymenttokenid].present?
44
+ end
37
45
  end
38
46
  end
@@ -0,0 +1,5 @@
1
+ <%= render 'spree/admin/payments/source_views/vpago_payment_tmpl',
2
+ payment: payment,
3
+ check_status_url: '',
4
+ heal_payment_url: '',
5
+ manual_update_payment_url: '' %>
@@ -0,0 +1,12 @@
1
+ <form method="post" action="<%= action_url %>" id="acleda_v2_checkout_form" style="display:none;">
2
+ <% gateway_params.each do |name, value| %>
3
+ <input type="hidden" name="<%= name %>" value="<%= value %>">
4
+ <% end %>
5
+ </form>
6
+
7
+ <script>
8
+ (function () {
9
+ var form = document.getElementById("acleda_v2_checkout_form");
10
+ if (form) form.submit();
11
+ })();
12
+ </script>
@@ -0,0 +1,53 @@
1
+ <%
2
+ opr_device = request.user_agent.to_s.downcase.match?(/iphone|ipad|ipod/) ? 'ios' : 'android'
3
+ checkout = ::Vpago::AcledaV2::Checkout.new(@payment, { platform: params[:platform], opr_device: opr_device })
4
+
5
+ begin
6
+ checkout.call
7
+ rescue => e
8
+ Rails.logger.error("Acleda V2 checkout.call failed: #{e.message}")
9
+ end
10
+ %>
11
+
12
+ <% if checkout.failed? %>
13
+ <script>
14
+ console.error("[Vpago] Acleda V2 checkout error: <%= j checkout.error_message.to_s %>");
15
+ document.addEventListener("DOMContentLoaded", () => {
16
+ const loadingContainer = document.getElementById('vpago_loading_container');
17
+ if (loadingContainer) {
18
+ loadingContainer.textContent = "We couldn't start your payment. Please go back and try again.";
19
+ }
20
+ });
21
+ </script>
22
+ <% elsif checkout.deeplink? %>
23
+ <script>
24
+ function showRedirectContainer(buttonLabel, onClick) {
25
+ const loadingContainer = document.getElementById('vpago_loading_container');
26
+ const redirectContainer = document.getElementById('vpago_redirect_container');
27
+ const redirectButton = document.getElementById('vpago_redirect_button');
28
+
29
+ redirectButton.textContent = buttonLabel;
30
+ redirectButton.addEventListener('click', onClick);
31
+
32
+ loadingContainer.style.display = 'none';
33
+ redirectContainer.style.removeProperty('display');
34
+ }
35
+
36
+ const deeplinkUrl = "<%= raw checkout.deeplink_url %>";
37
+ const redirectTo = (url) => { if (url) window.location.href = url; };
38
+
39
+
40
+ <<<<<<< Updated upstream
41
+ redirectTo(deeplinkUrl);
42
+ showRedirectContainer("Open ACLEDA", () => redirectTo(deeplinkUrl));
43
+ =======
44
+ redirectTo(deeplinkUrl);
45
+ showRedirectContainer("Open ACLEDA", () => redirectTo(deeplinkUrl));
46
+
47
+ >>>>>>> Stashed changes
48
+ </script>
49
+ <% else %>
50
+ <%= render 'spree/checkout/payment/acleda_v2_checkout_form',
51
+ gateway_params: checkout.gateway_params,
52
+ action_url: checkout.action_url %>
53
+ <% end %>
@@ -21,6 +21,7 @@ module SpreeVpago
21
21
  Spree::Gateway::PaywayV2,
22
22
  Spree::Gateway::WingSdk,
23
23
  Spree::Gateway::Acleda,
24
+ Spree::Gateway::AcledaV2,
24
25
  Spree::Gateway::AcledaMobile,
25
26
  Spree::Gateway::Vattanac,
26
27
  Spree::Gateway::VattanacMiniApp,
@@ -1,7 +1,7 @@
1
1
  module SpreeVpago
2
2
  module_function
3
3
 
4
- VERSION = '2.3.4'.freeze
4
+ VERSION = '2.3.5-pre-2'.freeze
5
5
 
6
6
  def version
7
7
  Gem::Version.new VERSION
@@ -0,0 +1,152 @@
1
+ module Vpago
2
+ module AcledaV2
3
+ class Base
4
+ CONTENT_TYPE_JSON = 'application/json'.freeze
5
+ # ACLEDA requires purchaseDesc to be <= 16 chars, English only.
6
+ PURCHASE_DESC = 'Purchase goods'.freeze
7
+
8
+ def initialize(payment, options = {})
9
+ @options = options
10
+ @payment = payment
11
+ end
12
+
13
+ def payment_method
14
+ @payment.payment_method
15
+ end
16
+
17
+ def payment_number
18
+ @payment.number
19
+ end
20
+
21
+ def amount
22
+ format('%.2f', @payment.amount)
23
+ end
24
+
25
+ # txid <= 16 chars; payment.number fits.
26
+ alias transaction_id payment_number
27
+
28
+ def order_number
29
+ @payment.order.number
30
+ end
31
+
32
+ def merchant_name
33
+ payment_method.preferences[:merchant_name]
34
+ end
35
+
36
+ def merchant_id
37
+ payment_method.preferences[:merchant_id]
38
+ end
39
+
40
+ def login_id
41
+ payment_method.preferences[:login_id]
42
+ end
43
+
44
+ def password
45
+ payment_method.preferences[:password]
46
+ end
47
+
48
+ def secret
49
+ payment_method.preferences[:secret]
50
+ end
51
+
52
+ # Dynamically mirrors the shopper's remaining seat/inventory hold time so the bank's
53
+ # QR/session doesn't outlive the hold. Falls back to the admin-configured preference
54
+ # when the order has no hold (e.g. non-inventory items) or the hold has already lapsed.
55
+ def expiry_time
56
+ @expiry_time ||= (remaining_hold_minutes || payment_method.preferences[:payment_expiry_time_in_mn]).to_s
57
+ end
58
+
59
+ def purchase_date
60
+ @payment.created_at.utc.strftime('%Y-%m-%d')
61
+ end
62
+
63
+ def purchase_currency
64
+ @payment.order.currency
65
+ end
66
+
67
+ def xpay_service_base_url
68
+ strip_whitespace(payment_method.preferences[:xpay_service_base_url])
69
+ end
70
+
71
+ def open_session_url
72
+ "#{xpay_service_base_url}/openSessionV2"
73
+ end
74
+
75
+ def get_txn_status_url # rubocop:disable Naming/AccessorMethodName
76
+ "#{xpay_service_base_url}/getTxnStatus"
77
+ end
78
+
79
+ # KHQR/Card secure web redirect target
80
+ def action_url
81
+ strip_whitespace(payment_method.preferences[:payment_page_url])
82
+ end
83
+
84
+ # successUrlToReturn / errorUrl. The bank appends its own query string
85
+ # (_paymenttokenid, _resultCode, ...) when it redirects back.
86
+ def continue_success_url
87
+ @payment.processing_url
88
+ end
89
+
90
+ def callback_url
91
+ @payment.processing_url
92
+ end
93
+
94
+ def app_scheme
95
+ payment_method.preferences[:app_scheme]
96
+ end
97
+
98
+ # android | ios (defaults to android when not supplied by the caller)
99
+ def opr_device
100
+ @options[:opr_device].presence || 'android'
101
+ end
102
+
103
+ def platform
104
+ @options[:platform]
105
+ end
106
+
107
+ def deeplink?
108
+ payment_method.deeplink? && platform == 'app'
109
+ end
110
+
111
+ # --- HMAC-SHA512 (uppercase hex) signing ---
112
+ # openSessionV2 message: merchantID + loginId + password + txid
113
+ def open_session_hash
114
+ hmac512("#{merchant_id}#{login_id}#{password}#{payment_number}")
115
+ end
116
+
117
+ # getTxnStatus message: merchantId + loginId + password + paymentTokenid
118
+ def txn_status_hash(token)
119
+ hmac512("#{merchant_id}#{login_id}#{password}#{token}")
120
+ end
121
+
122
+ def hmac512(message)
123
+ OpenSSL::HMAC.hexdigest(OpenSSL::Digest.new('sha512'), secret, message).upcase
124
+ end
125
+
126
+ def parse_json(body)
127
+ JSON.parse(body)
128
+ rescue JSON::ParserError
129
+ {}
130
+ end
131
+
132
+ private
133
+
134
+ # Minutes left on the order's seat/inventory hold, rounded up so we never quote the
135
+ # bank less time than is actually left. nil when the order has no hold, the hold has
136
+ # already lapsed, or hold_expires_at isn't defined (spree_cm_commissioner not loaded).
137
+ def remaining_hold_minutes
138
+ return nil unless @payment.order.respond_to?(:hold_expires_at)
139
+
140
+ hold_expires_at = @payment.order.hold_expires_at
141
+ return nil if hold_expires_at.blank?
142
+
143
+ minutes = ((hold_expires_at - Time.current) / 60.0).ceil
144
+ minutes if minutes.positive?
145
+ end
146
+
147
+ def strip_whitespace(value)
148
+ value.to_s.gsub(/\s+/, '')
149
+ end
150
+ end
151
+ end
152
+ end
@@ -0,0 +1,120 @@
1
+ require 'faraday'
2
+
3
+ module Vpago
4
+ module AcledaV2
5
+ class Checkout < Base
6
+ attr_reader :error_message
7
+
8
+ def call
9
+ @error_message = nil
10
+ @response = open_session
11
+
12
+ if @response.status != 500 && @response.status != 200
13
+ @error_message = 'Server Error'
14
+ elsif @response.status == 500 # mostly when passing a wrong parameter name
15
+ @error_message = @response.body
16
+ elsif json_response.dig('result', 'code') != 0 # invalid payload, wrong loginId, etc.
17
+ @error_message = json_response.dig('result', 'errorDetails') || 'Unknown Error'
18
+ end
19
+
20
+ update_payment_source
21
+
22
+ self
23
+ end
24
+
25
+ def failed?
26
+ @error_message.present?
27
+ end
28
+
29
+ def json_response
30
+ @json_response ||= parse_json(@response.body)
31
+ end
32
+
33
+ # KHQR/Card secure web redirect form fields (auto-POSTed to paymentPage.jsp).
34
+ def gateway_params
35
+ return {} if failed?
36
+
37
+ {
38
+ merchantID: merchant_id,
39
+ sessionid: json_response.dig('result', 'sessionid'),
40
+ paymenttokenid: payment_token_id,
41
+ description: Base::PURCHASE_DESC,
42
+ expirytime: expiry_time,
43
+ amount: amount,
44
+ quantity: '1',
45
+ item: '1',
46
+ invoiceid: order_number,
47
+ currencytype: purchase_currency,
48
+ transactionID: payment_number,
49
+ successUrlToReturn: continue_success_url,
50
+ errorUrl: continue_success_url
51
+ }
52
+ end
53
+
54
+ # Deep Link redirect target.
55
+ def deeplink_url
56
+ return nil if failed?
57
+
58
+ json_response.dig('result', 'deeplinkUrl')
59
+ end
60
+
61
+ private
62
+
63
+ def open_session
64
+ conn = Faraday::Connection.new
65
+
66
+ conn.post(open_session_url) do |request|
67
+ request.headers['Content-Type'] = Base::CONTENT_TYPE_JSON
68
+ request.body = open_session_payload.to_json
69
+ end
70
+ end
71
+
72
+ def open_session_payload
73
+ base = {
74
+ password: password,
75
+ loginId: login_id,
76
+ merchantID: merchant_id,
77
+ hash: open_session_hash,
78
+ xpayTransaction: xpay_transaction_base
79
+ }
80
+
81
+ if deeplink?
82
+ base[:xpayTransaction].merge!(oprDevice: opr_device, callBackUrl: callback_url)
83
+ else
84
+ base[:xpayTransaction][:paymentCard] = payment_method.payment_card_value
85
+ end
86
+
87
+ base
88
+ end
89
+
90
+ def xpay_transaction_base
91
+ {
92
+ txid: payment_number,
93
+ invoiceid: order_number,
94
+ purchaseAmount: amount,
95
+ purchaseCurrency: purchase_currency,
96
+ purchaseDate: purchase_date,
97
+ purchaseDesc: Base::PURCHASE_DESC,
98
+ item: '1',
99
+ quantity: '1',
100
+ expiryTime: expiry_time
101
+ }
102
+ end
103
+
104
+ def payment_token_id
105
+ json_response.dig('result', 'xTran', 'paymentTokenid')
106
+ end
107
+
108
+ # Persist the paymentTokenid so check_transaction / the bank callback can
109
+ # resolve the payment later. Wrap only the write in the writing role, since
110
+ # the checkout form partial runs on a GET request (replica connection).
111
+ def update_payment_source
112
+ return if failed?
113
+
114
+ ActiveRecord::Base.connected_to(role: :writing) do
115
+ @payment.source.update_column(:transaction_id, payment_token_id)
116
+ end
117
+ end
118
+ end
119
+ end
120
+ end
@@ -0,0 +1,83 @@
1
+ require 'faraday'
2
+
3
+ module Vpago
4
+ module AcledaV2
5
+ class TransactionStatus < Base
6
+ # Terminal failure indicators in result.errorDetails. The PDFs only document
7
+ # code 0 / "SUCCESS"; decline/expiry wording is conservative and should be
8
+ # confirmed against real responses during UAT. Anything not success and not
9
+ # terminal is treated as pending so the poller keeps trying.
10
+ FAILED_ERROR_DETAILS = %w[EXPIRED DECLINED CANCELLED FAILED REJECTED].freeze
11
+
12
+ def call
13
+ @response = check_remote_status
14
+ self
15
+ end
16
+
17
+ def json_response
18
+ @json_response ||= parse_json(@response.body)
19
+ end
20
+
21
+ def result
22
+ json_response['result'] || {}
23
+ end
24
+
25
+ def result_code
26
+ result['code']
27
+ end
28
+
29
+ def error_message
30
+ result['errorDetails']
31
+ end
32
+
33
+ def success?
34
+ return false if token.blank?
35
+
36
+ http_success? && result_code.zero? && error_message == 'SUCCESS'
37
+ end
38
+
39
+ def failed?
40
+ return false if token.blank?
41
+ return false unless http_success?
42
+
43
+ FAILED_ERROR_DETAILS.include?(error_message.to_s.upcase)
44
+ end
45
+
46
+ def pending?
47
+ !success? && !failed?
48
+ end
49
+
50
+ private
51
+
52
+ def http_success?
53
+ @response&.status == 200
54
+ end
55
+
56
+ def token
57
+ @payment.source&.transaction_id
58
+ end
59
+
60
+ def check_remote_status
61
+ conn = Faraday::Connection.new
62
+
63
+ conn.post(get_txn_status_url) do |request|
64
+ request.headers['Content-Type'] = Base::CONTENT_TYPE_JSON
65
+ request.body = payload.to_json
66
+ end
67
+ end
68
+
69
+ # NOTE: getTxnStatus uses merchantId (lowercase d) and an extra merchantName
70
+ # field. merchantName is NOT part of the HMAC message.
71
+ def payload
72
+ {
73
+ loginId: login_id,
74
+ password: password,
75
+ merchantId: merchant_id,
76
+ merchantName: merchant_name,
77
+ hash: txn_status_hash(token),
78
+ paymentTokenid: token
79
+ }
80
+ end
81
+ end
82
+ end
83
+ 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.3.4
4
+ version: 2.3.5.pre.pre.pre.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - You
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2026-06-19 00:00:00.000000000 Z
11
+ date: 2026-07-08 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: faraday
@@ -192,6 +192,7 @@ files:
192
192
  - app/models/concerns/vpago/payoutable.rb
193
193
  - app/models/spree/gateway/acleda.rb
194
194
  - app/models/spree/gateway/acleda_mobile.rb
195
+ - app/models/spree/gateway/acleda_v2.rb
195
196
  - app/models/spree/gateway/payway.rb
196
197
  - app/models/spree/gateway/payway_v2.rb
197
198
  - app/models/spree/gateway/true_money.rb
@@ -280,6 +281,7 @@ files:
280
281
  - app/views/spree/admin/payments/source_forms/_payway_v2.html.erb
281
282
  - app/views/spree/admin/payments/source_views/_acleda.html.erb
282
283
  - app/views/spree/admin/payments/source_views/_acleda_mobile.html.erb
284
+ - app/views/spree/admin/payments/source_views/_acleda_v2.html.erb
283
285
  - app/views/spree/admin/payments/source_views/_payment_payway.html.erb
284
286
  - app/views/spree/admin/payments/source_views/_payway_v2.html.erb
285
287
  - app/views/spree/admin/payments/source_views/_true_money.html.erb
@@ -309,6 +311,7 @@ files:
309
311
  - app/views/spree/checkout/payment/_acleda.html.erb
310
312
  - app/views/spree/checkout/payment/_acleda_checkout_form.html.erb
311
313
  - app/views/spree/checkout/payment/_acleda_mobile.html.erb
314
+ - app/views/spree/checkout/payment/_acleda_v2_checkout_form.html.erb
312
315
  - app/views/spree/checkout/payment/_payment_payway.html.erb
313
316
  - app/views/spree/checkout/payment/_payway_loader.html.erb
314
317
  - app/views/spree/checkout/payment/_payway_root.html.erb
@@ -331,6 +334,7 @@ files:
331
334
  - app/views/spree/payway_v2_card_popups/show.html.erb
332
335
  - app/views/spree/vpago_payments/_transaction_checker.html.erb
333
336
  - app/views/spree/vpago_payments/checkout.html.erb
337
+ - app/views/spree/vpago_payments/forms/spree/gateway/_acleda_v2.html.erb
334
338
  - app/views/spree/vpago_payments/forms/spree/gateway/_payway_v2.html.erb
335
339
  - app/views/spree/vpago_payments/forms/spree/gateway/_true_money.html.erb
336
340
  - app/views/spree/vpago_payments/forms/spree/gateway/_vattanac.html.erb
@@ -388,6 +392,9 @@ files:
388
392
  - lib/vpago/acleda_mobile/payment_request_updater.rb
389
393
  - lib/vpago/acleda_mobile/payment_retriever.rb
390
394
  - lib/vpago/acleda_mobile/transaction_status.rb
395
+ - lib/vpago/acleda_v2/base.rb
396
+ - lib/vpago/acleda_v2/checkout.rb
397
+ - lib/vpago/acleda_v2/transaction_status.rb
391
398
  - lib/vpago/payment_amount_calculator.rb
392
399
  - lib/vpago/payment_request_updater.rb
393
400
  - lib/vpago/payment_status_marker.rb
@@ -443,9 +450,9 @@ required_ruby_version: !ruby/object:Gem::Requirement
443
450
  version: 3.2.0
444
451
  required_rubygems_version: !ruby/object:Gem::Requirement
445
452
  requirements:
446
- - - ">="
453
+ - - ">"
447
454
  - !ruby/object:Gem::Version
448
- version: '0'
455
+ version: 1.3.1
449
456
  requirements:
450
457
  - none
451
458
  rubygems_version: 3.4.1