【问题标题】:Angular HttpClient post simulate form submit with the redirect afterwardsAngular HttpClient post 模拟表单提交,然后重定向
【发布时间】:2019-08-15 10:25:13
【问题描述】:

我需要使用 angular typescript 向 3rd 方支付提供商执行表单 POST,然后还要进行重定向。如果我通过标准 html 页面提交标准表单,则表单提交会自动重定向到第三方支付提供商托管的支付页面,但当我在 Angular 中执行 HttpClient.post 时不会。

我查看了 observables 和注入器,看看是否有帮助,但我搜索和发现的任何东西似乎都无法解决这个特定问题。虽然我在不同的角度版本之间阅读了很多不同的问题和解决方案,但我可能已经失去了一些明显的答案。

我不使用隐藏字段的隐藏表单的原因是因为我以后需要能够通过移动(Ionic)应用程序来做同样的事情,并且我需要使用他们内置的 HttpClient 以及普通的 HttpClient标准网页。

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); 
      });
  }
}

我希望能够进行第 3 方托管页面重定向,但我得到的只是来自第 3 方的 html 文本响应。我在进行纯 html 表单提交时也得到了这一点,但不知何故,纯 html 表单提交也处理了重定向。

-- 编辑 我得到的响应是来自我发布到的 URL 的实际 HTML 有效负载,并且期望从该 URL 提供。所以问题是标准的 html 表单提交如何导航到 POST url 并从那里提供返回的内容?

【问题讨论】:

  • 当您说您需要提交响应正文“与”重定向时,您是什么意思?
  • 首先,如果您拨打window.location.href = res.url;,那么您已经在那里丢失了表格。您是重定向到应用程序中的某个页面还是外部的某个页面?
  • 我需要重定向到我的应用程序之外的页面。我从调用中返回了一个 html 响应正文,但我不确定这是否有任何相关性。我知道window.location.href = res.url; 不是我需要做的,只是显示我认为我需要重定向的位置

标签: angular typescript


【解决方案1】:

重定向到外部 URL

导入 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); 
   });
  }
}

将 HTML 动态加载到模板中

根据您的评论,您希望将 HTML 注入您的模板,而不是重定向到外部网站。要注入 HTML,请将其保存在变量中并使用DomSanitizer 对其进行清理或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); 
   });
  }
}

然后,在您的模板中:

<div>
  <div [innerHtml]="data"></div>
</div>

【讨论】:

  • 试过了,没用。问题是我从 post 方法获取 html 有效负载,但期望从该实际 URL 而非我的网页提供。
  • @Bitter 听起来您想将 HTML 有效负载注入到您的 Angular 模板中,而不是重定向到外部 URL。查看更新。
  • 我注入的 html 必须从我得到它的 URL 执行。我不知道表单提交是如何自动完成的:(
  • @Bitter 查看如何在您的应用和 iframe 之间进行通信的答案:stackoverflow.com/q/41674712/1164465
【解决方案2】:

这就是我让它最终工作的方式。基本上我生成了一个带有隐藏表单的html页面并重新编写了文档。它适用于标准角度页面和离子页面。下面是我在 typescript 中编写的让它工作的方法。

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,我面临着完全相同的问题,请您帮助我们解决这个问题。当我进行自动表单提交时,在 Safari 浏览器中同样不起作用..
  • 我在下面的链接中找到了答案,基本上你需要给表单一个 Safari 的目标。见第一个答案。 stackoverflow.com/questions/23218156/…
猜你喜欢
  • 1970-01-01
  • 2012-08-25
  • 1970-01-01
  • 1970-01-01
  • 2013-04-13
  • 1970-01-01
相关资源
最近更新 更多