9

I am trying to incorporate payment gateway into angular app, I found following JavaScript snippet provided by the payment partner for incorporation, I tweaked it by adding ngNoForm and got it working with 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>

Next instead of using HTML <Form> POST + Action directly from component template, I wanted to make a REST call to my back end server perform some other steps and map that API response into what my payment partner expects and and then redirect to my payment partner using HttpClient POST which would supposedly do the same thing and redirect to the payment partner website which is supposed to take care of the payment process, so in short I wanted to achieve the same thing programmatically, I tried:

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

Initially I encountered CORS issue, but I was able to bypass that using Angular CLI's proxy config, now what happens is that instead of redirecting to the payment partner's website, HttpClient's POST method actually returns the web page as a string from the service endpoint, which is not what I though it would do,

Kindly refer to this stackBlitz, for further understanding.

So to sum it all up, basically I am seeking to transform above working template driven POST request into programmatic version. so I could perform some set of operations first and then redirect to the external URL using POST. I believe what I am trying programmatically is probably different from what happens against Html <form> POST + Action. There must be some programmatic equivalent of the same thing.

P.S: I did found this similar question but sadly it has no working answer.

P.S.S: I can not use window.location.href or RouterLink as its supposed to be POST and there is supposed to be info like amount, currency and other things to be passed to the payment partner along side.

9
  • Use your initial form, but hide it using css, and use JavaScript to programmatically submit it. Commented Nov 25, 2018 at 22:20
  • you are asking essentially the same question again - and ignoring the most standard answer: have your back end server that would take your Angular request, submit its own request to payment processor, and return JSON back to Angular client. proxy config may help you in development; but you will have the same problem once you move your code to production Commented Nov 25, 2018 at 22:22
  • @Felix have you opened provided stackBlitz? I bet you haven't. The thing is pesoPay provides two options for payment handling, API and redirecting to pesoPay for payment handling. I am not trying to integrate any API here, what I am trying to do is simply a POST redirection. Which is the reason my back end is not required to do the talking with my payment partner. I didn't highlighted that point well enough in my previous question which is the reason I deleted that. Is it possible to do a POST redirect via Angular? similar to what form post + action does? Commented Nov 26, 2018 at 6:38
  • @JBNizet I know that would be possible, but I don't think that would be the recommended way, for simplicity purpose I have only added three properties i.e. amount, currCode and payMethod, but in actual there can be 15+ properties which has to be handled. I personally don't like the idea of performing tasks via creating unnecessary DOM nodes, I bet this would be do able via code that's why no need to complicate things, Commented Nov 26, 2018 at 6:48
  • 1
    I did... but you don't listen to what people told you on that thread. Browsers POST forms and receive HTML back; Javascript POST xhr and receive JSON. You are hitting the wall that is there by design (maybe bad design; but 20 years ago nobody predicted the patterns that are in use today, like SPA). If you insist that your back end is not required - then you will continue to hit the same wall. Good luck - if you don't get results, you will get experience :) Commented Nov 26, 2018 at 6:55

3 Answers 3

2

Given the scenario we can achieve the desired output by submitting a dynamically created form by using plain JavaScript instead of HttpClient. When we use HttpClient, redirection occurs in the network and not in the client browser. Here is my solution

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();
Sign up to request clarification or add additional context in comments.

2 Comments

hie david / priyanka, the same solution working fine in all browsers, expect in iphones (safari.) ... I'm getting network connection lost error while performing form posting.. could you please advise or provide your inputs on this.
Hi David / Privanka, This works fine in Chrome but headers are not working. Any idea?
1

Initially I didn't think this would work, but after spending the whole week researching and trial and error. It is working nicely for me using Angular 6. You probably can use javascript or any other language you want. Basically, 2 steps you must follow:

1) When calling the login form redirect, you must set respontType=text so HttpClient won't throw an error expecting JSON data.

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

2) Setup an interceptor to intercept your subsequence API request (assuming the endpoint will return json now). In the intercepter, pass withCredentials=true . In Javascript or Curl, you would expect to retrieve that from the login successful and send back JSESSIONID with the API request. In Angular, you only need withCredentials=true in the Interceptor. *NOTE: you cannot pass this in the HttpHeaders before making a request. See bug report here.

Here is my code snippet for Interceptor:

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

Hope this will help.

2 Comments

Can you make your code examples more complete? For example, what is params1? What is headers? What are your imports?
@Jak, It is not about API calling, it is redirect to external URL (not API). So this will not work.
1
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();

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.