【问题标题】:Angular 6 Redirect to external url using POSTAngular 6使用POST重定向到外部网址
【发布时间】:2018-11-25 21:20:35
【问题描述】:

我正在尝试将支付网关合并到 Angular 应用程序中,我发现遵循支付合作伙伴提供的 JavaScript sn-p 进行合并,我通过添加 ngNoForm 对其进行了调整,并使其与 angular 一起使用; stackBlitz

<form ngNoForm method="post" action="https://test.pesopay.com/b2cDemo/eng/payment/payForm.jsp">
<input type="hidden" name="amount" value="1" >
<input type="hidden" name="currCode" value="608" >
<input type="hidden" name="payMethod" value="CC">
<input type="submit" name="submit">
</form>

接下来,我不想直接从组件模板使用 HTML &lt;Form&gt; POST + Action,而是想对我的后端服务器进行 REST 调用,执行一些其他步骤,并将 API 响应映射到我的支付合作伙伴的期望,然后重定向到我的支付合作伙伴使用 HttpClient POST 应该会做同样的事情并重定向到应该负责支付过程的支付合作伙伴网站,所以简而言之,我想以编程方式实现同​​样的事情,我试过了:

redirectToPaymentHandler(): Observable<any> {
  const urlEncodeData = 'amount=1&currCode=608&payMethod=CC';
  let headers = new HttpHeaders();
  headers = headers.append('Content-Type', 'application/x-www-form-urlencoded');
  headers = headers.append('Accept', 'text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8');

  return this.httpClient.post('https://test.pesopay.com/b2cDemo/eng/payment/payForm.jsp',
    urlEncodeData, {
      headers,
      responseType: 'text'
    }).pipe(catchError((error) => {
      console.log(error)
      return EMPTY;
    }));
}

最初我遇到了 CORS 问题,但我能够使用 Angular CLI 的代理配置绕过它,现在发生的情况是,HttpClient 的 POST 方法实际上将网页作为字符串返回,而不是重定向到支付合作伙伴的网站 来自服务端点,虽然我不会这样做,

请参考此stackBlitz,以进一步了解。

总而言之,基本上我正在寻求将上述工作模板驱动的 POST 请求转换为程序版本。所以我可以先执行一些操作,然后使用 POST 重定向到外部 URL。我相信我以编程方式尝试的可能与针对 Html &lt;form&gt; POST + Action 发生的不同。必须有一些相同的程序等价物。

P.S:我确实找到了 this 类似的问题,但遗憾的是它没有有效的答案。

P.S.S:我不能使用 window.location.hrefRouterLink 作为它应该是 POST 并且应该有诸如金额、货币和其他信息之类的信息要传递给支付合作伙伴旁边。

【问题讨论】:

  • 使用您的初始表单,但使用 css 隐藏它,并使用 JavaScript 以编程方式提交。
  • 再次问了基本相同的问题 - 并忽略了最标准的答案:有 your 后端服务器来接受您的 Angular 请求,向支付处理器提交自己的请求,并将 JSON 返回给 Angular 客户端。代理配置可能帮助您进行开发;但是一旦将代码移至生产环境,您将遇到同样的问题
  • @Felix 你有没有打开提供的stackBlitz?我打赌你没有。问题是 pesoPay 提供了两种支付处理选项,API 和重定向到 pesoPay 进行支付处理。 我不想在这里集成任何 API,我想做的只是一个 POST 重定向。这就是我的后端不需要与我的支付伙伴进行交谈的原因。我在上一个问题中没有充分强调这一点,这就是我删除它的原因。是否可以通过 Angular 进行 POST 重定向?类似于 post + action 的什么形式?
  • @JBNizet 我知道这是可能的,但我认为这不是推荐的方式,为简单起见,我只添加了三个属性,即金额、currCode 和 payMethod,但实际上存在可以是 15+ 必须处理的属性。我个人不喜欢通过创建不必要的 DOM 节点来执行任务的想法,我敢打赌这可以通过代码来实现,这就是为什么不需要让事情复杂化的原因,
  • 我做了...但你不听人们在那个线程上告诉你的内容。浏览器 POST 表单并接收 HTML 返回; Javascript POST xhr 并接收 JSON。你正在碰壁设计(可能是糟糕的设计;但 20 年前没有人预测到今天使用的模式,比如 SPA)。如果您坚持不需要您的后端 - 那么您将继续碰壁。祝你好运 - 如果你没有得到结果,你会得到经验 :)

标签: angular angular-http angular-httpclient


【解决方案1】:

在这种情况下,我们可以通过使用纯 JavaScript 而不是 HttpClient 提交动态创建的表单来实现所需的输出。 当我们使用 HttpClient 时,重定向发生在网络中,而不是在客户端浏览器中。这是我的解决方案

const myform = document.createElement('form');
myform.method = 'POST';
myform.action = "https://test.pesopay.com/b2cDemo/eng/payment/payForm.jsp";
myform.style.display = 'none';
myform.append('Content-Type', 'application/x-www-form-urlencoded');
myform.append('Accept', 'text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8');
document.body.appendChild(myform);
myform.submit();

【讨论】:

  • hie david / priyanka,相同的解决方案在所有浏览器中都可以正常工作,预计在 iphone(safari)中......我在执行表单发布时遇到网络连接丢失错误......你能告诉我吗或提供您对此的意见。
  • 嗨,David / Privanka,这在 Chrome 中运行良好,但标题不起作用。有什么想法吗?
【解决方案2】:

最初我认为这不会奏效,但在花了整整一周的时间研究和反复试验之后。使用 Angular 6 对我来说效果很好。您可能可以使用 javascript 或您想要的任何其他语言。基本上,您必须遵循两个步骤:

1) 在调用登录表单重定向时,您必须设置 respontType=text 以便 HttpClient 不会抛出期望 JSON 数据的错误。

return  this.http.post(this.HOST_URL+'login' ,params1.toString(), 
{
    headers:  headers,
    withCredentials: true,
    observe: 'response',
    params: params1,
    responseType: 'text',
    reportProgress: true
})

2) 设置拦截器来拦截您的子序列 API 请求(假设端点现在将返回 json)。在拦截器中,传递 withCredentials=true 。在 Javascript 或 Curl 中,您希望从登录成功中检索该信息,然后将 JSESSIONID 与 API 请求一起发送回。在 Angular 中,您只需要在拦截器中使用 withCredentials=true。 *注意:在发出请求之前,您不能在 HttpHeaders 中传递它。见bug report here

这是我的拦截器代码 sn-p:

@Injectable()
export class WithCredentialsInterceptor implements HttpInterceptor {

    intercept(request: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
        console.log("Intercepting Request withCredentials=true ");
        request = request.clone({
            withCredentials: true
        });

        return next.handle(request);
    }
}

希望这会有所帮助。

【讨论】:

  • 能否让你的代码示例更完整?例如,什么是 params1?什么是标头?你的进口是什么?
  • @Jak,这与 API 调用无关,它是重定向到外部 URL(不是 API)。所以这行不通。
【解决方案3】:
const mapForm = document.createElement('form');
mapForm.method = 'POST';
mapForm.action = `${b2pApiUrl}/Purchase`;
mapForm.style.display = 'none';

const mapInput = document.createElement('input');
mapInput.type = 'hidden';
mapInput.name = 'param1';
mapInput.value = param1;
mapForm.appendChild(mapInput);

const mapInput1 = document.createElement('input');
mapInput1.type = 'hidden';
mapInput1.name = 'param2';
mapInput1.value = param2;
mapForm.appendChild(mapInput1);
....
document.body.appendChild(mapForm);

mapForm.submit();

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2022-08-20
    • 2023-03-03
    • 1970-01-01
    • 2017-10-07
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-05-02
    相关资源
    最近更新 更多