Search code examples
symfonysyliusomnipaypayum

Symfony Routing and Mixed Content Errors


Hi so I am receiving mixed content errors when trying to display a card details form on my checkout page of my Symfony/Sylius app. I am using payum w/ omnipay bridge to do a sage pay checkout.

The reason I get the mixed content error is because I submit a form on my parent page which sends a token to the following route:

payum_capture_do:
    path: /payment/capture/{payum_token}
    defaults: { _controller: sylius.controller.payum.capture:doAction }
    # schemes:  [https]

route which in turn executes some code to get the iFrame src. The response is then fed into the iFrame src. This is actually all done via JS by submitting the form directly to the iFrame:

 let form = jQuery("form[name='sylius_checkout_complete']");

 if (form.length) {
     form.attr('target', 'card-details');
     form.submit();
 }

The problem then arises because the payum route is not an https route and therefore the iFrame is blocked from showing content due a mixed content error. The reason this bug is so strange is because if I force the route to https (as you can see I've tried from the comment), it returns with "Too Many Redirects" and crashes the page (although it does display in the iFrame). I think this is because it tries http first then https and since the payment can only be captured once becomes invalid in doing so.

Any help would be greatly appreciated.


Solution

  • UPDATE

    The correct solution should be to override the route definitions with forcing https, I did:

    payum_all:
        resource: "@PayumBundle/Resources/config/routing/all.xml"
    
    payum_capture_do:
        path: /payment/capture/{payum_token}
        controller: PayumBundle:Capture:do
        schemes: [https]
    

    The problem that Symfony did endless redirects was that I had an Ingress-Nginx in front of the application which handled and terminated https. So the Symfony application actually never thought it was reached via https, hence the redirects.

    For this I had to update the nginx which calls the php_fpm using the following parameter:

    fastcgi_param HTTPS on;

    If you use Kubernetes Ingress and you would like to actually pass https towards your service you can check out:

    nginx.ingress.kubernetes.io/ssl-passthrough: "true"

    Now payum and gateway works by generating correct https routes.

    OLD ANSWER:

    This is my old answer, which didn't work completely in the end, I leave it in for investigation.

    The issue is probably caused by the payum gateway you use, I had the same issue with nfq-eta/payum-braintree.

    The problem was that the file https://github.com/nfq-eta/payum-braintree/blob/037fb302d63e1bfd733ecc86afc3ec869adb8f2b/src/Resources/views/Action/obtain_payment_method_nonce.html.twig included a payment form with a http action url.

    I solved this by overriding the template using config payum.yaml

    gateways:
        offline:
            factory: offline
        braintree:
            factory: braintree
            payum.template.obtain_payment_method_nonce: 'Payment/payum_obtain_payment_method_nonce.html.twig'
    

    Then I created my template at templates/payum_obtain_payment_method_nonce.html.twig:

    {% extends "@PayumBraintree/Action/obtain_payment_method_nonce.html.twig" %}
    
    {% block braintree_payment_form %}
        <form method="POST" id="form">
            <div id="dropin-container"></div>
            <input type="hidden" name="payment_method_nonce" id="payment_method_nonce" value="" />
            <input type="submit" value="Submit payment" id="submit_btn" />
        </form>
    {% endblock %}
    

    I removed the action argument from the form entirely, so that it just used the current one. Which in my case is https://...

    It works, but does someone know a better solution?