title: WooCommerce third-party gateway isn't working on order-pay page
body: <p>I have a third-party payment gateway which works fine on the Checkout page.  When the user clicks the Pay button, it actually returns a Javascript command as the redirect, which then opens up a modal iframe to my payment gateway, like so:</p>
  <pre><code>public function process_payment( $order_id ): array {
      include_once dirname( __FILE__ ) . '/includes/flywire-payment-gateway-request.php';
      $FW_request = new WC_Gateway_Flywire_Request( $this, $order_id );
  
      try {
          $config= $FW_request-&gt;get_config();
      } catch ( Exception $e ) {
          wc_add_notice( $e-&gt;getMessage(), 'error' );
  
          return array(
              'result'   =&gt; 'failure',
              'redirect' =&gt; ''
          );
      }
  
      // TODO: add optional call to Google Tag action
      $return_array = array(
          'result'   =&gt; 'success',
          'redirect' =&gt; 'javascript:window.flywire.WooCommerce.show(' . json_encode($config) . ')'
      );
      $logger = wc_get_logger();
      $context = array( 'source' =&gt; 'flywire' );
      $log = &quot;Initializing Checkout with JSON:\n&quot; . json_encode($return_array) . &quot;\n&quot;;
  
      $logger-&gt;info( $log, $context );
      return $return_array;
  }
  </code></pre>
  <blockquote>
  <p>2022-02-17T11:16:19+00:00 INFO Initializing Checkout with JSON:
  {&quot;result&quot;:&quot;success&quot;,&quot;redirect&quot;:&quot;javascript:window.flywire.WooCommerce.show(&quot;{\&quot;provider\&quot;:\&quot;woocommerce\&quot;,\&quot;env\&quot;:\&quot;demo\&quot;,\&quot;locale\&quot;:\&quot;en\&quot;,\&quot;recipient\&quot;:\&quot;\&quot;,\&quot;amount\&quot;:1800,\&quot;return_url\&quot;:\&quot;http:\\\/\\\/localhost:8888\\\/checkout\\\/order-received\\\/58\\\/?key=wc_order_2jw2UT4xADHU3\&quot;,\&quot;callback_id\&quot;:58,\&quot;callback_url\&quot;:\&quot;http:\\\/\\\/localhost:8888\\\/wc-api\\\/WC_Gateway_Flywire\\\/\&quot;,\&quot;sender_country\&quot;:\&quot;US\&quot;,\&quot;sender_first_name\&quot;:\&quot;Test\&quot;,\&quot;sender_last_name\&quot;:\&quot;Testing\&quot;,\&quot;sender_address1\&quot;:\&quot;1 Test\&quot;,\&quot;sender_phone\&quot;:\&quot;000000000\&quot;,\&quot;sender_city\&quot;:\&quot;Town\&quot;,\&quot;sender_zip\&quot;:\&quot;94043\&quot;,\&quot;sender_email\&quot;:\&quot;admin@example.com\&quot;,\&quot;student_first_name\&quot;:\&quot;Test\&quot;,\&quot;student_last_name\&quot;:\&quot;Testing\&quot;,\&quot;student_email\&quot;:\&quot;admin@example.com\&quot;}&quot;)&quot;}</p>
  </blockquote>
  <p>On the order-pay endpoint, clicking the Pay button generates the exact same button, but the JS does not fire or trigger the breakpoint I put in it.  If I manually try to call the JS from the Dev Tools Console, like below, it triggers the breakpoint:</p>
  <pre><code>window.flywire.WooCommerce.show('foo')
  </code></pre>
  <p>So, I know that the JS script has been enqueued properly and is included in the page.  I also know that the <code>process_payment</code> function is returning the correct redirect value.  And yet, nothing happens.</p>
  <p>As far as I can tell, function <code>process_order_payment</code> in class-wc-checkout.php is what actually takes the return value from my gateway's <code>process_payment</code> function and does its magic.  I added logging there too and can see it fire when I click Pay from the Checkout page.  But, nothing happens from the Order Pay page.</p>
  <p><strong>UPDATE:</strong> No solution yet but found some more information.  <code>process_payment</code> is called in two places.  For checkout, it is called by <code>class-wc-checkout.php</code>.  For the order payment page, it is called by <code>class-wc-form-handler.php</code>.  The code is in both places is <em>almost</em> the same.</p>
  <p>Code on <code>class-wc-checkout.php</code>:</p>
  <pre><code>// Process Payment.
  $result = $available_gateways[ $payment_method ]-&gt;process_payment( $order_id );
  
  // Redirect to success/confirmation/payment page.
  if ( isset( $result['result'] ) &amp;&amp; 'success' === $result['result'] ) {
      $result['order_id'] = $order_id;
  
      $result = apply_filters( 'woocommerce_payment_successful_result', $result, $order_id );
  
      if ( ! wp_doing_ajax() ) {
          // phpcs:ignore WordPress.Security.SafeRedirect.wp_redirect_wp_redirect
          wp_redirect( $result['redirect'] );
          exit;
      }
  
      wp_send_json( $result );
  }
  </code></pre>
  <p>Code on <code>class-wc-form-handler.php</code>:</p>
  <pre><code>$result = $payment_method-&gt;process_payment( $order_id );
  
  // Redirect to success/confirmation/payment page.
  if ( isset( $result['result'] ) &amp;&amp; 'success' === $result['result'] ) {
      $result['order_id'] = $order_id;
  
      $result = apply_filters( 'woocommerce_payment_successful_result', $result, $order_id );
  
      wp_redirect( $result['redirect'] ); //phpcs:ignore WordPress.Security.SafeRedirect.wp_redirect_wp_redirect
      exit;
  }
  </code></pre>
  <p>In the checkout version (which works), it does not call <code>wp_redirect()</code> if WP is doing AJAX and instead sends the JSON to the AJAX.  In the order payment page version, it always just redirects with <code>wp_redirect()</code>.  It's the <code>wp_send_json()</code> that allows the &quot;Javascript:&quot; protocol to work, but I don't understand why paying from the checkout page works differently from the order payment page.</p>