0

I am trying to contact the barclays payment api, I can send a post request which return the page that I want to redirect the user to using postman.

However, the same request send from an angular 2 app, returns:

XMLHttpRequest cannot load https://test.barclaycardsmartpay.com/hpp/pay.shtml. No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'http://localhost:4200' is therefore not allowed access.

I feel that the error message is a decoy, because if cors was the issue, then I am not sure why it would be working in postman. Perhaps it is because the API I am trying to reach is accepting SOAP requests and I am trying to do this from localhost, which can not be reached from that API (to give a two way connection?).

In my angular app, my post looks like this:

  let paymentPost : iSmartPayment = {
    merchantSig: "23XJ9auO4brdZMzPXoe+Lml4H5PfQERgrImns6s4FdQ=",
    merchantReference: "abc",
    paymentAmount: "1",
    currencyCode: "GBP",
    shipBeforeDate: "2018-01-01",
    skinCode: "neXEF4Y2",
    merchantAccount: "GroupEdTest",       
    sessionValidity: "2018-01-01T00:00:00Z",
    merchantReturnData: "http://www.mywebsiteUrl.com.s3-website.eu-west-2.amazonaws.com/#/transactionhistory",
    shopperEmail: "sam@gmail.com",
    shopperReference: "Sam"

  }

return this.http.post('https://test.barclaycardsmartpay.com/hpp/pay.shtml', JSON.stringify(paymentPost)).map((response: Response) => {
      console.log('TODO: process response', response);
      return response.json();
    }).catch(this.handleError);

Note that I have changed some of the values in the post to keep the data confidential.

Any ideas what might be my issue here?

trees_are_great
  • 3,881
  • 3
  • 31
  • 62
  • 3
    postman doesn't have the same browser to server restrictions that are in place when making ajax calls via CORs in browser. This IS a CORs issue. As an aside, do you actually need to stringify your payload? You should be able to post the object directly. – David L Apr 18 '17 at 16:10
  • Thanks for the side note. Thanks, I will investigate how to change the cors options – trees_are_great Apr 18 '17 at 16:21
  • The issue does not seem to be cors. I am now doing this instead with a stand html form post and it is working. I am happy to use the html approach, but I am curious to find the solution to this nonetheless. – trees_are_great Apr 24 '17 at 15:15
  • I believe that angular 2 can give a cors error when the response type is not json in the expected format. The response this returns is a html page. Therefore, this could be the issue. – trees_are_great Apr 24 '17 at 15:16
  • That isn't how CORs works. It isn't as interested in the response as it is the request itself. It the ***request*** is being made cross-origin, the browser will throw a flag and prevent it, whereas postman will not. – David L Apr 24 '17 at 15:17
  • IA Web Api can be enabled to have requests from any URL. It is up to the web api to specify which URLs can call it, not the client. In this case, Cors has been enabled just fine. The error message above was given by mistake by angular 2, I have seen this happen before. I am not sure what you are debating here.. – trees_are_great Apr 24 '17 at 15:27
  • And I'm trying to explain to you that CORs is not enforced by the server, it's enforced by the browser. In the case of Postman, it doesn't enforce the CORs restriction. See http://stackoverflow.com/questions/36554013/cors-issue-doesnt-occur-when-using-postman – David L Apr 24 '17 at 15:30
  • I think that you are getting confused here. The answer is stating why an extension can work by getting permission first, whereas a browser gets it on each call (stateless). I have implemented many APIs and clients and I know that CORS is enforced by the server. google it :) – trees_are_great Apr 24 '17 at 15:35
  • 1
    Sounds good, good luck on your search :) – David L Apr 24 '17 at 15:35
  • Thanks, best to you :) – trees_are_great Apr 24 '17 at 15:47

2 Answers2

0

You do not need to JSON.stringify the body before posting.

let url: string = 'https://test.barclaycardsmartpay.com/hpp/pay.shtml';

let paymentPost : iSmartPayment = {
    merchantSig: "23XJ9auO4brdZMzPXoe+Lml4H5PfQERgrImns6s4FdQ=",
    merchantReference: "abc",
    paymentAmount: "1",
    currencyCode: "GBP",
    shipBeforeDate: "2018-01-01",
    skinCode: "neXEF4Y2",
    merchantAccount: "GroupEdTest",       
    sessionValidity: "2018-01-01T00:00:00Z",
    merchantReturnData: "http://www.mywebsiteUrl.com.s3-website.eu-west-2.amazonaws.com/#/transactionhistory",
    shopperEmail: "sam@gmail.com",
    shopperReference: "Sam"

  }

return this.http.post(url, paymentPost).map((response: Response) => response.json()).catch(this.handleError);

If this does work, it could be the OPTIONS request that Angular sends before the post that is failing.

Wesley Coetzee
  • 4,768
  • 3
  • 27
  • 45
0

I had the same problem did a lot of research, here's what you all may need.

From your questions reference.

XMLHttpRequest cannot load https://test.barclaycardsmartpay.com/hpp/pay.shtml. No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'http://localhost:4200' is therefore not allowed access.

The exceptions only says that the cross URL request can not share the data. But you can call the GET method as it does not need to send the data from client to Server. But in case of POST, we need to send the data from Client to server and Browser restrict the Data sent across the different Domain because of the CORS.

To fix this, here is what needs to be done, from the API side, we have to add the configuration in web.config file and the setting in the Global.aspx file.

<httpProtocol>
  <customHeaders>
    <add name="Access-Control-Allow-Origin" value="*" />
    <add name="Access-Control-Allow-Headers" value="Origin, X-Requested-With, Content-Type, Accept,Authorization" />
    <add name="Access-Control-Allow-Methods" value="GET, POST, PUT, DELETE, OPTIONS" />
  </customHeaders>
</httpProtocol>

GLOBAL file

    protected void Application_BeginRequest()
    {
        if (Request.Headers.AllKeys.Contains("Origin") && Request.HttpMethod == "OPTIONS")
        {
            Response.Flush();
        }
    }