craftcms / commerce-stripe

Stripe payment gateway for Craft Commerce
https://plugins.craftcms.com/commerce-stripe
MIT License
30 stars 51 forks source link

Adding a payment source redirects to wrong URL #289

Open peterurban opened 7 months ago

peterurban commented 7 months ago

When adding a payment source as part of a subscription flow. The page redirects to: /index.php/actions/commerce-stripe/customers/confirm-setup-intent and not index.php?p=actions/commerce-stripe/customers/confirm-setup-intent causing a 404.

Redirect works as expected in local development, but not production.

Form:

{% set returnUrl = 'shop/subscriptions/payment' %}

{% if chosenPlan|length > 0 %}
  {% set returnUrl = returnUrl ~ '?plan=' ~ chosenPlan %}
{% endif %}

<form id="gateway-{{ plan.gateway.id }}"
        method="post"
        action=""
        class="cards-details__form"
  >
    {{ csrfInput() }}
    {{ actionInput('commerce/payment-sources/add') }}
    {{ hiddenInput('gatewayId', plan.gateway.id) }}
    {{ hiddenInput('successMessage', 'Added payment source.'|hash) }}
    {{ hiddenInput('cancelUrl', returnUrl|hash) }}
    {{ redirectInput(returnUrl) }}

    <div class="cards-details__form__fields">
      {% namespace plan.gateway.handle|commercePaymentFormNamespace %}
        {{ plan.gateway.getPaymentFormHtml({
          paymentFormType: 'elements',
          appearance: {
            theme: 'stripe'
          },
          elementOptions: {
            layout: {
              type: 'accordion',
              defaultCollapsed: false,
              radios: false,
              spacedAccordionItems: false
            }
          },
          submitButtonClasses: 'cards-details__button button',
          submitButtonText: 'Add card',
        })|raw }}
      {% endnamespace %}
    </div>

    <label>
      {{ 'Make primary payment source' }} {{ input('checkbox', 'isPrimaryPaymentSource', 1) }}
    </label>
</form>

Steps to reproduce

  1. Add payment card using above form (3DS in my case)
  2. Submit

Additional info

damonadigital commented 6 months ago

Having the same issue here when trying to add a payment source. Any luck in resolving this?

peterurban commented 6 months ago

Having the same issue here when trying to add a payment source. Any luck in resolving this?

Unfortunately, the issue remains. I had to make an ugly workaround with redirects and session variables. None of the related issues are getting any attention from the team, so I wouldn't get my hopes up for a fix anytime soon.

damonadigital commented 6 months ago

That is unfortunate, thank you for the update.

antcooper commented 6 months ago

@peterurban would you mind sharing your workaround please? Suffering from the same issue. Thanks

peterurban commented 6 months ago

@peterurban would you mind sharing your workaround please? Suffering from the same issue. Thanks

It's not pretty, but it works for my use case. Essentially, I added a redirect in my 404.twig, pointing the user to the desired url. In my case, I also need to keep track of the chosen plan, for which I use a session variable ("plan").

If this bug gets fixed at some point, the system would just send users to the correct redirectUrl and skip this step.

{% set path = craft.app.request.url %}
{% set chosenPlan = craft.app.getSession().get('plan') %}

{% if path starts with '/index.php/actions/commerce-stripe/customers/confirm-setup-intent' %}
  {% if chosenPlan %}
    {% set redirectUrl = '/shop/subscriptions/payment/received?plan=' ~ chosenPlan %}
    {% redirect redirectUrl %}
  {% else%}
    {% redirect '/shop/subscriptions/payment/received' %}
  {% endif %}
{% else %}
  {% redirect '/' %}
{% endif %}
antcooper commented 6 months ago

@peterurban thanks for the pointer. Skipping the confirm-setup-intent step and going straight to confirmation didn't set the payment method as primary for me, so it broke the rest of the subscription flow. I found a way to rewrite the malformed URL so it works and doesn't need the redirect in the session (if it's included in the original form post)

{% if craft.app.request.url starts with '/index.php/actions/commerce-stripe/customers/confirm-setup-intent' %}
  {% redirect craft.app.request.url
    |replace({'/actions/': '?p=actions/', '?setup_intent': '&setup_intent'}) %}

{% endif %}
smalomo commented 6 months ago

Thank you @antcooper - that worked for me.

lukeholder commented 6 months ago

Hey @peterurban @antcooper I can’t seem to replicate this in local development in various browsers, I can't see how production would be any different unless they were configured differently.

What URL does it generate for you in local vs production?

I get this: https://craft4.ddev.site/index.php?p=actions/commerce/payments/complete-payment

antcooper commented 6 months ago

@lukeholder this works fine locally in DDEV. On Servd in Staging and Production, the URL is as below. I've shortened all the hashed values for readability. The ? doesn't appear until much further along the string:

  https://example.com/index.php/actions/commerce-stripe/customers/confirm-setup-intent
    &CRAFT_CSRF_TOKEN=nn93h3pKMm-LhlxG_KxrHi
    &action=commerce%2Fpayment-sources%2Fadd
    &successMessage=7c3c3607c4bd12345Payment%20Method%20Added
    &gatewayId=2
    &isPrimaryPaymentSource=1
    ?setup_intent=seti_000000
    &setup_intent_client_secret=seti_0000
    &redirect_status=succeeded