2

I need to perform a form POST to a 3rd party payment provider with angular typescript and also do the redirect afterwards. If I do standard form submit through a standard html page the form submit automatically redirects to the 3rd party payment providers hosted payment page, but not when I do a HttpClient.post in angular.

I looked at observables and and injectors to see if that would help, but nothing I searched and found seemed to solve this specific problem. Though I read so many different problems and solutions between different angular versions I may have lost some obvious answer along the line.

The reason I am not doing a hidden form with hidden fields is because I need to be able to this same thing through a mobile (Ionic) app later, and I will need to use their inbuilt HttpClient along with the normal HttpClient for standard web pages.

import { Component, OnInit } from '@angular/core';
import { HttpClient, HttpHeaders } from '@angular/common/http';

@Component({
  selector    :  'app-paymenttest-page',
  templateUrl :  'paymenttest.page.html',
  styleUrls   : ['paymenttest.page.scss']
})
export class PaymentTestPage implements OnInit {

  constructor(private  http : HttpClient) {
  }

  private void makePayment(url: str, formData: FormData): void {
    let headers = new HttpHeaders({'Accept' : 'text/html' });

    this.http.post(url, formData, {
      headers         : headers,
      responseType    : 'text',
      })
       .subscribe(
         (res) =>  {
           console.log('post res');
           console.log(res);

           window.location.href = res.url;
    // How do I simulate a form submit redirect with res.body here?
         },
         (err) => {
          console.log('post err');
          console.log(err); 
      });
  }
}

I expect to be able to do a 3rd party hosted page redirect, but all I am getting back is the html text response from the 3rd party. Which I also get when doing a plain html form submit, but somehow the plain html form submit also handles the redirect.

-- Edit The response I am getting is the actual HTML payload from the URL that I am posting to and is expecting to be served from that URL. So the question is how does a standard html form submit navigate to the POST url and serve the returned content from there?

Bitter
  • 21
  • 1
  • 4
  • What do you mean when you say you need to submit the response body "with" the redirect? – Will Alexander Aug 15 '19 at 10:58
  • 1
    Well first, if you are calling `window.location.href = res.url;` then you have already lost the form there. Are you redirecting to some page in your application or some page outside of it? – callback Aug 15 '19 at 11:01
  • I need to redirect to a page outside of my application. I get back an html response body from the call, though I am not sure if that is of any relevance. I know the ```window.location.href = res.url; ``` is not what I need to do, was just showing where I think I need to then the redirect – Bitter Aug 15 '19 at 11:08

2 Answers2

1

Redirect to external URL

Import Angular DOCUMENT.

import { DOCUMENT } from '@angular/common';
import { Inject, Injectable } from '@angular/core';

...
constructor(@Inject(DOCUMENT) private document: any) { }

...
this.http.post(url, formData, { headers: headers, responseType: 'text'}).subscribe(
  (res) =>  {
    console.log('post res');
    console.log(res);

    this.document.location.href  = res.url;
  },
  (err) => {
    console.log('post err');
    console.log(err); 
   });
  }
}

Load HTML dynamically into Template

Based on your comment, you want to inject HTML into your template, rather than redirect to an external website. To inject HTML, save it in a variable and use the DomSanitizer to either sanitize it or bypass the security check:

data: SafeHtml;

constructor(private sanitizer: DomSanitizer) {}      

ngOnInit(){ 
    this.http.post(url, formData, { headers: headers, responseType: 'text'}).subscribe(
    (res) =>  {
      console.log('post res');
      console.log(res);
      
      this.data = this.sanitizer.sanitize(res.html);
            /* OR */
      this.data = this.sanitizer.bypassSecurityTrustHtml(res.html);
  },
  (err) => {
    console.log('post err');
    console.log(err); 
   });
  }
}

Then, in your template:

<div>
  <div [innerHtml]="data"></div>
</div>
Community
  • 1
  • 1
Christopher Peisert
  • 21,862
  • 3
  • 86
  • 117
  • Tried that, did not help. The problem is that I am getting the html payload from from the post method, but it is expecting to be served from that actual URL and not from my web page. – Bitter Aug 15 '19 at 12:12
  • @Bitter It sounds like you want to inject the HTML payload into your Angular template rather than redirect to an external URL. See update. – Christopher Peisert Aug 15 '19 at 12:44
  • The html that I am injecting though has to be executed from the URL that I got it from. I don't know how form submit does this automatically :( – Bitter Aug 15 '19 at 12:45
  • @Bitter See answer for how to communicate between your app and an iframe: https://stackoverflow.com/q/41674712/1164465 – Christopher Peisert Aug 15 '19 at 12:59
0

This is how I got it to finally work. Basically I generated an html page, with a hidden form and re-wrote the document. It's working perfectly for both standard angular pages and ionic. Below is the method I wrote in typescript to get it to work.

private _providerPayment(vpp: bVoucherPaymentPayload): void {
    let pageContent = '<html><head></head><body><form id="payForm" action="' + vpp.endpoint + '" method="POST">';

    for (let item of vpp.formFields) {
      let ff : bLookupItem = (<bLookupItem> item);
      pageContent += '\n  <input type="hidden" name="' + ff.key + '" value="' + ff.value + '">';
    }

    pageContent += '\n</form><script type="text/javascript">document.getElementById("payForm").submit();</script></body></html>';

    // console.log('DYNAMIC FORM!!');
    // console.log(pageContent);



    if (this._runningOnNativeDevice()) {
      const pageContentUrl = 'data:text/html;base64,' + btoa(pageContent);      

      this._inAppBrowser.create(pageContentUrl, "_self", {
       'location'          : 'no',
       'presentationstyle' : 'fullscreen',
      });
    } else {
      document.open();
      document.write(pageContent);
      document.close();
    }
  }
Bitter
  • 21
  • 1
  • 4
  • dear @Bitter, am facing exactly the same issue, could you please help us in this. the same is not working in safari browser when i'm doing auto form submit.. – Kishore Konangi Jun 02 '21 at 11:14
  • I found the answer in the below link, basically you need to give the form a target for Safari. See the first answer. https://stackoverflow.com/questions/23218156/safari-does-not-trigger-form-submit – Bitter Jun 03 '21 at 15:31