Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 7 additions & 3 deletions app/controllers/spree/api/v1/ipay_controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -180,21 +180,21 @@ def return

# Here you might want to implement a status check with iPay
# For now, we'll just redirect to payment info page
redirect_to spree.checkout_state_path(:payment),
redirect_to checkout_state_path_for(order, 'payment'),
notice: 'We are still processing your payment. Please check back soon.'
return
end

# If payment failed
if @payment.failed? || @payment.void?

redirect_to spree.checkout_state_path(:payment),
redirect_to checkout_state_path_for(order, 'payment'),
alert: 'Payment was not completed. Please try again or use a different payment method.'
return
end

# Default fallback
redirect_to spree.checkout_state_path(order.state),
redirect_to checkout_state_path_for(order),
notice: 'Please complete your order.'
rescue StandardError
redirect_to spree.root_path,
Expand All @@ -220,6 +220,10 @@ def status

private

def checkout_state_path_for(order, state = order.state)
spree.checkout_state_path(order.token, state)
end

# Dummy method to satisfy Spree API controller expectations
def try_spree_current_user
nil
Expand Down
20 changes: 12 additions & 8 deletions app/controllers/spree/checkout_controller_decorator.rb
Original file line number Diff line number Diff line change
Expand Up @@ -59,14 +59,14 @@ def handle_ipay_redirect
error_message = Rails.env.development? ? e.message : 'Unable to process payment. Please try again.'

respond_to do |format|
format.html { redirect_to checkout_state_path(@order.state), error: error_message }
format.html { redirect_to checkout_state_path_for(@order), error: error_message }
format.json { render json: { status: 'error', message: error_message }, status: :unprocessable_entity }
end
end
rescue StandardError => e
respond_to do |format|
format.html do
redirect_to checkout_state_path(:payment), error: "Payment processing failed: #{e.message}"
redirect_to checkout_state_path_for(@order, 'payment'), error: "Payment processing failed: #{e.message}"
end
format.json do
render json: {
Expand All @@ -89,9 +89,9 @@ def update
respond_to do |format|
format.html do
if @order.next
redirect_to checkout_state_path(@order.state)
redirect_to checkout_state_path_for(@order)
else
redirect_to checkout_state_path(@order.state)
redirect_to checkout_state_path_for(@order)
end
end

Expand Down Expand Up @@ -156,19 +156,23 @@ def update
end

private

def checkout_state_path_for(order, state = order.state)
checkout_state_path(order.token, state)
end
Comment on lines +160 to +162

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Action required

1. Bad checkout url construction 🐞 Bug ≡ Correctness

checkout_state_path_for calls checkout_state_path(order.token, state), passing the token as a
positional path segment with no evidence in this repo that checkout_state_path is defined to take
a token. This conflicts with existing iPay flows that use order.guest_token as order_token, so
redirects can land on the wrong checkout state (token treated as state) or produce unusable guest
links.
Agent Prompt
### Issue description
`checkout_state_path_for` currently builds checkout URLs as `checkout_state_path(order.token, state)` (and one place uses `spree.checkout_state_path(order.token, order.state)`). In this codebase, the iPay integration uses `order.guest_token` as `order_token` for guest access, and there is no repo-defined checkout route that takes a token as a positional segment.

### Issue Context
Fix should generate checkout URLs by passing the checkout state as the path segment and the guest token as an option (e.g., `order_token:`) consistent with other redirects/return URLs in this repo.

### Fix Focus Areas
- app/controllers/spree/checkout_controller_decorator.rb[160-178]
- app/controllers/spree/ipay_controller.rb[34-36]
- app/controllers/spree/ipay_controller_decorator.rb[76-78]
- app/controllers/spree/api/v1/ipay_controller.rb[223-225]
- app/controllers/spree/gateway_callbacks_controller.rb[120-124]

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


def next_step_url_for(order, next_step)
return unless next_step

case next_step
when 'address'
checkout_state_path('address')
checkout_state_path_for(order, 'address')
when 'delivery'
checkout_state_path('delivery')
checkout_state_path_for(order, 'delivery')
when 'payment'
checkout_state_path('payment')
checkout_state_path_for(order, 'payment')
when 'confirm'
checkout_state_path('confirm')
checkout_state_path_for(order, 'confirm')
when 'complete'
order_path(order, order_token: order.guest_token)
end
Expand Down
2 changes: 1 addition & 1 deletion app/controllers/spree/gateway_callbacks_controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -120,7 +120,7 @@ def confirm
esc_heading = ERB::Util.html_escape(meta[:heading])
esc_color = ERB::Util.html_escape(meta[:color]) # assumed safe, as it's generated SVG markup
esc_root_path = ERB::Util.html_escape(spree.root_path)
esc_payment_path = ERB::Util.html_escape(spree.checkout_state_path(order.state))
esc_payment_path = ERB::Util.html_escape(spree.checkout_state_path(order.token, order.state))

# Build details table safely using helpers
@details = helpers.content_tag(:table,
Expand Down
10 changes: 7 additions & 3 deletions app/controllers/spree/ipay_controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -20,16 +20,20 @@ def interactive_checkout

redirect_to redirect_url, allow_other_host: true
else
redirect_to checkout_state_path(@order.state), alert: "Unable to process payment. Please try again."
redirect_to checkout_state_path_for(@order), alert: "Unable to process payment. Please try again."
end
rescue ActiveRecord::RecordNotFound => e
redirect_to cart_path, alert: "Order not found."
rescue => e
redirect_to checkout_state_path(@order&.state || :cart),
alert: "An error occurred while processing your payment. Please try again."
redirect_to(@order.present? ? checkout_state_path_for(@order) : cart_path,
alert: "An error occurred while processing your payment. Please try again.")
end

private

def checkout_state_path_for(order, state = order.state)
checkout_state_path(order.token, state)
end

# Extract callback parameters based on iPay documentation
def extract_callback_params
Expand Down
13 changes: 9 additions & 4 deletions app/controllers/spree/ipay_controller_decorator.rb
Original file line number Diff line number Diff line change
Expand Up @@ -24,8 +24,7 @@ def interactive_checkout

redirect_to redirect_url, allow_other_host: true
else
redirect_to checkout_state_path(@order.state),
alert: "Unable to process payment. Please try again."
redirect_to checkout_state_path_for(@order), alert: "Unable to process payment. Please try again."
end
end

Expand Down Expand Up @@ -57,8 +56,10 @@ def interactive_checkout
rescue => e
respond_to do |format|
format.html do
redirect_to checkout_state_path(@order&.state || :cart),
alert: "An error occurred while processing your payment. Please try again."
redirect_to(
@order.present? ? checkout_state_path_for(@order) : cart_path,
alert: "An error occurred while processing your payment. Please try again."
)
end
format.json do
render json: {
Expand All @@ -72,6 +73,10 @@ def interactive_checkout

private

def checkout_state_path_for(order, state = order.state)
checkout_state_path(order.token, state)
end

def set_headers
response.headers['Cache-Control'] = 'no-cache, no-store, max-age=0, must-revalidate'
response.headers['Pragma'] = 'no-cache'
Expand Down
Loading