Skip to content

Example PSP integration: iframe

Often the SDKs provided by Payment Service Providers render an iframe to show the form.
On the Magento integration side, this commonly requires calling a method on the SDK, passing along a selector for the target element, into which the SDK will render the iframe with the form elements.

What follows is an imaginary example payment method template.

The demo code loads the PSP SDK library when the payment method is selected, and then initializes the payment method code.
It also provides a callback to the SDK, that will be triggered when the visitor completes the form in the iframe.
The callback receives a token, which it then passes to the Magewire component.

<div>
    <!-- This Magewire payment component template -->
    <!-- It is rendered when the visitor selects the method -->

    <div id="#examplePspFormContainer" wire:ignore>
        <!-- The PSP iframe will be rendered here -->
    </div>

    <script>
        // This script will only be evaluated once, the first time it is rendered.  
        (() => {
          // This function initializes the SDK
          async function initPspForm(SDK) {
            // Initialize the SDK API with merchant config
            const paymentMethod = await SDK.configure({
              merchantKey: '<?= $escaper->escapeJs($magewire->getMerchantKey()) ?>',
              callback: ({token}) => {
                // When the PSP form is complete, pass the payment token to our component
                const component = '<?= $escaper->escapeJs($block->getNameInLayout()) ?>';
                Magewire.find(component).setPaymentToken(token);
              }
            });
            // Tell the SDK to render the iframe
            const target = '#examplePspFormContainer';
            document.querySelector(target) && paymentMethod.mount(target);
          }

          // Load the SDK library file when it is needed
          if (! window.ExamplePaymentSdk) {
            // Add the SDK script tag to the page & initialize onload
            const script = document.createElement('script');
            script.src = '<?= $block->getViewFileUrl('Example_Psp::js/sdk.js') ?>';
            script.onload(() => initPspForm(ExamplePaymentSdk));
            document.head.append(script);
          } else {
            // In case the SDK is already loaded, initialize it immediately
            initPaymentForm(ExamplePaymentSdk);
          }
        })()
    </script>
</div>

The above code is intended as an example only, it has to be adjusted to the API for any given PSP.

Using wire:ignore to protect DOM content rendered by third party scripts

Did you notice the wire:ignore attribute on the DIV in the example code above?

<div id="#examplePspFormContainer" wire:ignore>
    <!-- The PSP iframe will be rendered here -->
</div>

The wire:ignore attribute ensures Magewire will ignore the contents of the element.
Without it, the iframe and any other content rendered by the SDK will disappear after the first Magewire round-trip!

The template of the payment method component will be re-rendered during a subsequent request. The result will be the empty <div id="#examplePspFormContainer" wire:ignore>, without the content created by the SDK!

However, because of the wire:ignore attribute, Magewire will leave it alone and not replace the iframe with the empty placeholder DIV.

<script> tags are only evaluated during the preceding request!

When <script> tags are rendered by component templates, they are only evaluated by the browser during the initial request. If the script is rendered again during subsequent requests, it is ignored by the browser.
Changes to the JavaScript code are ignored.
However, any state that was created during the initial preceding request will persist.