-1

Paypal says to make the following curl request

  curl -v POST https://api-m.sandbox.paypal.com/v1/oauth2/token \
  -H "Accept: application/json" \
  -H "Accept-Language: en_US" \
  -u "CLIENT_ID:SECRET" \
  -d "grant_type=client_credentials"

However, I want to instead do that through an HTTP request. I tried the following:

const HTTP = require('http')
const data = JSON.stringify({
    paypalclientid:paypalsecretid,
    "grant_type": "client_credentials",
})
const options = {
    host: 'api-m.sandbox.paypal.com',
    port: 80,
    path: '/v1/oauth2/token',
    method: 'POST',
    headers: {
        'Accept': 'application/json',
        "Accept-Language": "en_US"
    }
}
const req = http.request(options, res => {
    console.log(`statusCode: ${res.statusCode}`)

    res.on('data', d => {
        process.stdout.write(d)
    })
})

req.on('error', error => {
    console.error(error)
})

req.write(data)
req.end()

and I got the following:

<HTML><HEAD>
<TITLE>Access Denied</TITLE>
</HEAD><BODY>
<H1>Access Denied</H1>
 
You don't have permission to access "http&#58;&#47;&#47;api&#45;m&#46;sandbox&#46;paypal&#46;com&#47;v1&#47;oauth2&#47;token" on this server.<P>
Reference&#32;&#35;18&#46;9ce33e17&#46;1609625956&#46;708d702f
</BODY>
</HTML>

That is what you get when you do a normal GET request.

Eat Ing
  • 312
  • 1
  • 3
  • 7
  • 1
    curl help page: `-u, --user Server user and password`. You are passing it in the post body instead of as the HTTP user/password. – SuperStormer Jan 02 '21 at 22:24
  • As a side note, I would recommend that you use a library for http requests, the default http module isn't exactly user friendly. I would recommend [node-fetch](https://github.com/node-fetch/node-fetch) since it implements the same api as browsers do. – Olian04 Jan 02 '21 at 22:29
  • 2
    Does this answer your question? [How to use http.client in Node.js if there is basic authorization](https://stackoverflow.com/questions/3905126/how-to-use-http-client-in-node-js-if-there-is-basic-authorization) – Preston PHX Jan 02 '21 at 22:37
  • In the curl request, `https` is used but you defined `port: 80` in `options`. The default port for `https` is `443`. – mottek Jan 02 '21 at 22:43

2 Answers2

1
  • You need to base64 encode your credentials and send them along in an Authorization header.
  • You need to make the request over https.
  • You need to form encode the content.

Here's an example that works with a valid user and pass:

const https = require('https')

const data = `grant_type=client_credentials`;
const user = 'your client id';
const pass = 'your secret';
const authorization = `Basic ` + Buffer.from(`${user}:${pass}`).toString(`base64`);

const options = {
  hostname: 'api.paypal.com',
  port: 443,
  path: '/v1/oauth2/token',
  method: 'POST',
  headers: {
    'Authorization': authorization,
    'Content-Type': 'application/x-www-form-urlencoded',
    'Content-Length': data.length
  },
}

const req = https.request(options, res => {
  console.log(`statusCode: ${res.statusCode}`)

  res.on('data', d => {
    process.stdout.write(d)
  })
})

req.on('error', error => {
  console.error(error)
})

req.write(data)
req.end()
Matt Terski
  • 891
  • 8
  • 11
  • Well no need to base64 encode strings yourself and build a basic authorization header when using a request library that will do it for you with one line. Also the new `api-m` endpoints are faster – Preston PHX Jan 02 '21 at 23:31
0

Seems you need basic authentication:

const options = {
    auth: 'CLIENT_ID:SECRET',
    ...

You should also be using port 443 (HTTPS), as well as:

    'Content-Type': 'application/x-www-form-urlencoded'

for this particular token request (almost all other PayPal REST endpoints take application/json)

Preston PHX
  • 27,642
  • 4
  • 24
  • 44