spree_vpago 2.3.5.pre.pre.pre.1 → 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: c0262a0bad21d6ed9d53d73ba6805f307e6b9f82db837ac96fe4f3c4725ae49b
4
- data.tar.gz: 71f83ae18d1c306419bbef87f291185e1835a653fde1d1f0a09e1c783cf6f54c
3
+ metadata.gz: ab21d4fcbe691887d5e573acc9d10f1a320f7a9afa3605a1a4e6b2b678a9e844
4
+ data.tar.gz: 181e9fa1b7726e24a1bea16e87996e5146722ad94c7b237bd9bf8e180c4e955c
5
5
  SHA512:
6
- metadata.gz: ffc03cf77c82129ee5cf13ca1d3abb1646a9d39878ea647e1fd2451c30c027a885d8e8cb99fe45fabef2d7308c73f70c11b654ef9043b59814ef4737a983392c
7
- data.tar.gz: cde29375e88d3428cd5854b47bb597fac4697eaf60550dfb74573dd0d5edff55624ea0df78659328ba40343548c39b60d4284fe7c6bfcd495a24ba405b82fcea
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.5.pre.pre.pre.1)
4
+ spree_vpago (2.3.5.pre.pre.pre.2)
5
5
  faraday
6
6
  google-cloud-firestore
7
7
  spree_api (>= 4.5)
@@ -2,11 +2,8 @@ module Spree
2
2
  class Gateway::AcledaV2 < PaymentMethod
3
3
  MODES = %w[khqr card deeplink].freeze
4
4
 
5
- # BOOKMEPLUS — sent as the "merchantName" field in getTxnStatus requests
6
5
  preference :merchant_name, :string
7
- # e.g. https://epaymentuat.acledabank.com.kh/BOOKMEPLUS/XPAYConnectorServiceInterfaceImplV2/XPAYConnectorServiceInterfaceImplV2RS
8
6
  preference :xpay_service_base_url, :string
9
- # e.g. https://epaymentuat.acledabank.com.kh/BOOKMEPLUS/paymentPage.jsp
10
7
  preference :payment_page_url, :string
11
8
  preference :merchant_id, :string
12
9
  preference :login_id, :string
@@ -60,7 +57,6 @@ module Spree
60
57
  end
61
58
 
62
59
  # override
63
- # mirror PayWay V2: gateway_options[:order_id] == "<order_number>-<payment_number>"
64
60
  def purchase(_amount, _source, gateway_options = {})
65
61
  _, payment_number = gateway_options[:order_id].split('-')
66
62
  payment = Spree::Payment.find_by(number: payment_number)
@@ -1,5 +1,5 @@
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
@@ -20,9 +20,9 @@ module Vpago
20
20
  payment.update(transaction_response: payload)
21
21
  payment
22
22
  elsif acleda_v2_callback?
23
- # ACLEDA V2's static portal callback carries only _paymenttokenid, which we
24
- # stored on the payment source at openSessionV2. Resolve the payment by it.
25
- Spree::VpagoPaymentSource.find_by!(transaction_id: params_hash[:_paymenttokenid]).payment
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])
26
26
  else
27
27
  order = Spree::Order.find_by!(number: params_hash[:order_number])
28
28
  verify_jwt!(order)
@@ -1 +1,5 @@
1
- <%= render 'spree/admin/payments/source_views/vpago_payment_tmpl', payment: payment %>
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: '' %>
@@ -19,7 +19,7 @@
19
19
  }
20
20
  });
21
21
  </script>
22
- <% elsif @payment.payment_method.deeplink? %>
22
+ <% elsif checkout.deeplink? %>
23
23
  <script>
24
24
  function showRedirectContainer(buttonLabel, onClick) {
25
25
  const loadingContainer = document.getElementById('vpago_loading_container');
@@ -37,8 +37,14 @@
37
37
  const redirectTo = (url) => { if (url) window.location.href = url; };
38
38
 
39
39
 
40
+ <<<<<<< Updated upstream
40
41
  redirectTo(deeplinkUrl);
41
42
  showRedirectContainer("Open ACLEDA", () => redirectTo(deeplinkUrl));
43
+ =======
44
+ redirectTo(deeplinkUrl);
45
+ showRedirectContainer("Open ACLEDA", () => redirectTo(deeplinkUrl));
46
+
47
+ >>>>>>> Stashed changes
42
48
  </script>
43
49
  <% else %>
44
50
  <%= render 'spree/checkout/payment/acleda_v2_checkout_form',
@@ -1,7 +1,7 @@
1
1
  module SpreeVpago
2
2
  module_function
3
3
 
4
- VERSION = '2.3.5-pre-1'.freeze
4
+ VERSION = '2.3.5-pre-2'.freeze
5
5
 
6
6
  def version
7
7
  Gem::Version.new VERSION
@@ -18,7 +18,6 @@ module Vpago
18
18
  @payment.number
19
19
  end
20
20
 
21
- # PDF samples quote every xpayTransaction field as a JSON string.
22
21
  def amount
23
22
  format('%.2f', @payment.amount)
24
23
  end
@@ -50,15 +49,13 @@ module Vpago
50
49
  payment_method.preferences[:secret]
51
50
  end
52
51
 
53
- # PDF samples quote every xpayTransaction field as a JSON string, even ones
54
- # labeled "Numeric" in the field tables (paymentCard, quantity, expiryTime).
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
55
  def expiry_time
56
- payment_method.preferences[:payment_expiry_time_in_mn].to_s
56
+ @expiry_time ||= (remaining_hold_minutes || payment_method.preferences[:payment_expiry_time_in_mn]).to_s
57
57
  end
58
58
 
59
- # PDF: "Date of Transaction in UTC Time", sent as a YYYY-MM-DD string in the
60
- # samples. Explicit .utc so this stays correct even if config.time_zone is
61
- # ever changed away from UTC.
62
59
  def purchase_date
63
60
  @payment.created_at.utc.strftime('%Y-%m-%d')
64
61
  end
@@ -67,11 +64,6 @@ module Vpago
67
64
  @payment.order.currency
68
65
  end
69
66
 
70
- # --- Endpoints (each stored as a full URL preference) ---
71
- # Strip embedded whitespace: these URLs are long and wrap across lines in
72
- # the bank's PDFs, so a copy-paste into the admin preference easily carries
73
- # over a stray space/line-break where the PDF wrapped.
74
-
75
67
  def xpay_service_base_url
76
68
  strip_whitespace(payment_method.preferences[:xpay_service_base_url])
77
69
  end
@@ -96,13 +88,7 @@ module Vpago
96
88
  end
97
89
 
98
90
  def callback_url
99
- if platform == 'app' && app_scheme.present?
100
- uri = URI.parse(@payment.processing_url)
101
- uri.scheme = app_scheme
102
- uri.to_s
103
- else
104
- @payment.processing_url
105
- end
91
+ @payment.processing_url
106
92
  end
107
93
 
108
94
  def app_scheme
@@ -118,6 +104,10 @@ module Vpago
118
104
  @options[:platform]
119
105
  end
120
106
 
107
+ def deeplink?
108
+ payment_method.deeplink? && platform == 'app'
109
+ end
110
+
121
111
  # --- HMAC-SHA512 (uppercase hex) signing ---
122
112
  # openSessionV2 message: merchantID + loginId + password + txid
123
113
  def open_session_hash
@@ -141,6 +131,19 @@ module Vpago
141
131
 
142
132
  private
143
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
+
144
147
  def strip_whitespace(value)
145
148
  value.to_s.gsub(/\s+/, '')
146
149
  end
@@ -2,10 +2,6 @@ require 'faraday'
2
2
 
3
3
  module Vpago
4
4
  module AcledaV2
5
- # Single class handling all three modes (khqr, card, deeplink).
6
- # Two-step ACLEDA flow: openSessionV2 (JSON, here) yields paymentTokenid +
7
- # sessionid, then either an auto-POST form to paymentPage.jsp (KHQR/Card) or
8
- # a JS deeplink redirect (Deep Link).
9
5
  class Checkout < Base
10
6
  attr_reader :error_message
11
7
 
@@ -82,7 +78,7 @@ module Vpago
82
78
  xpayTransaction: xpay_transaction_base
83
79
  }
84
80
 
85
- if payment_method.deeplink?
81
+ if deeplink?
86
82
  base[:xpayTransaction].merge!(oprDevice: opr_device, callBackUrl: callback_url)
87
83
  else
88
84
  base[:xpayTransaction][:paymentCard] = payment_method.payment_card_value
@@ -31,10 +31,13 @@ module Vpago
31
31
  end
32
32
 
33
33
  def success?
34
- http_success? && result_code == 0 && error_message == 'SUCCESS'
34
+ return false if token.blank?
35
+
36
+ http_success? && result_code.zero? && error_message == 'SUCCESS'
35
37
  end
36
38
 
37
39
  def failed?
40
+ return false if token.blank?
38
41
  return false unless http_success?
39
42
 
40
43
  FAILED_ERROR_DETAILS.include?(error_message.to_s.upcase)
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.5.pre.pre.pre.1
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-07-03 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